Fix registration of InlineMacro with name
MODIFY
asciidoctorj-core/src/main/java/org/asciidoctor/extension/JavaExtensionRegistry.java
asciidoctorj-core/src/main/java/org/asciidoctor/extension/JavaExtensionRegistry.java
@@ -65,7 +65,10 @@ public interface JavaExtensionRegistry {
JavaExtensionRegistry inlineMacro(InlineMacroProcessor inlineMacroProcessor);
- JavaExtensionRegistry inlineMacro(String blockName,
+ JavaExtensionRegistry inlineMacro(String macroName,
+ InlineMacroProcessor inlineMacroProcessor);
+
+ JavaExtensionRegistry inlineMacro(String macroName,
Class<? extends InlineMacroProcessor> inlineMacroProcessor);
JavaExtensionRegistry inlineMacro(Class<? extends InlineMacroProcessor> inlineMacroProcessor);

MODIFY
asciidoctorj-core/src/main/java/org/asciidoctor/extension/processorproxies/BlockMacroProcessorProxy.java
asciidoctorj-core/src/main/java/org/asciidoctor/extension/processorproxies/BlockMacroProcessorProxy.java
@@ -61,9 +61,12 @@ public class BlockMacroProcessorProxy extends AbstractMacroProcessorProxy<BlockM
@JRubyMethod(name = "initialize", required = 1, optional = 1)
public IRubyObject initialize(ThreadContext context, IRubyObject[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
- String macroName = RubyUtils.rubyToJava(getRuntime(), args[0], String.class);
+ String explicitMacroName = RubyUtils.rubyToJava(getRuntime(), args[0], String.class);
if (getProcessor() != null) {
+
+ String macroName = explicitMacroName != null ? explicitMacroName : getProcessor().getName();
+
// Instance was created in Java and has options set, so we pass these
// instead of those passed by asciidoctor
Helpers.invokeSuper(
@@ -72,12 +75,12 @@ public class BlockMacroProcessorProxy extends AbstractMacroProcessorProxy<BlockM
getMetaClass(),
METHOD_NAME_INITIALIZE,
new IRubyObject[]{
- JavaEmbedUtils.javaToRuby(getRuntime(), getProcessor().getName()),
+ JavaEmbedUtils.javaToRuby(getRuntime(), macroName),
RubyHashUtil.convertMapToRubyHashWithSymbols(getRuntime(), getProcessor().getConfig())},
Block.NULL_BLOCK);
- if (macroName != null) {
- getProcessor().setName(macroName);
+ if (explicitMacroName != null) {
+ getProcessor().setName(explicitMacroName);
} else if (getProcessor().getName() == null) {
RubyHash config = (RubyHash) this.callMethod(context, "config");
Object rubyName = config.get(context.getRuntime().newSymbol("name"));
@@ -90,9 +93,9 @@ public class BlockMacroProcessorProxy extends AbstractMacroProcessorProxy<BlockM
getProcessor().updateConfig(new RubyHashMapDecorator((RubyHash)getInstanceVariable(MEMBER_NAME_CONFIG)));
} else {
// First create only the instance passing in the name
- setProcessor(instantiateProcessor(macroName, new HashMap<String, Object>()));
+ setProcessor(instantiateProcessor(explicitMacroName, new HashMap<String, Object>()));
- getProcessor().setName(macroName);
+ getProcessor().setName(explicitMacroName);
// Then create the config hash that may contain config options defined in the Java constructor
RubyHash config = RubyHashUtil.convertMapToRubyHashWithSymbols(context.getRuntime(), getProcessor().getConfig());

MODIFY
asciidoctorj-core/src/main/java/org/asciidoctor/extension/processorproxies/BlockProcessorProxy.java
asciidoctorj-core/src/main/java/org/asciidoctor/extension/processorproxies/BlockProcessorProxy.java
@@ -62,9 +62,12 @@ public class BlockProcessorProxy extends AbstractProcessorProxy<BlockProcessor>
@JRubyMethod(name = "initialize", required = 1, optional = 1)
public IRubyObject initialize(ThreadContext context, IRubyObject[] args) throws IllegalAccessException, InvocationTargetException, InstantiationException {
- String macroName = RubyUtils.rubyToJava(getRuntime(), args[0], String.class);
+ String explicitMacroName = RubyUtils.rubyToJava(getRuntime(), args[0], String.class);
if (getProcessor() != null) {
+
+ String macroName = explicitMacroName != null ? explicitMacroName : getProcessor().getName();
+
// Instance was created in Java and has options set, so we pass these
// instead of those passed by asciidoctor
Helpers.invokeSuper(
@@ -73,12 +76,12 @@ public class BlockProcessorProxy extends AbstractProcessorProxy<BlockProcessor>
getMetaClass(),
METHOD_NAME_INITIALIZE,
new IRubyObject[]{
- JavaEmbedUtils.javaToRuby(getRuntime(), getProcessor().getName()),
+ JavaEmbedUtils.javaToRuby(getRuntime(), macroName),
RubyHashUtil.convertMapToRubyHashWithSymbols(getRuntime(), getProcessor().getConfig())},
Block.NULL_BLOCK);
- if (macroName != null) {
- getProcessor().setName(macroName);
+ if (explicitMacroName != null) {
+ getProcessor().setName(explicitMacroName);
} else if (getProcessor().getName() == null) {
RubyHash config = (RubyHash) this.callMethod(context, "config");
Object rubyName = config.get(context.getRuntime().newSymbol("name"));
@@ -91,9 +94,9 @@ public class BlockProcessorProxy extends AbstractProcessorProxy<BlockProcessor>
getProcessor().updateConfig(new RubyHashMapDecorator((RubyHash) getInstanceVariable(MEMBER_NAME_CONFIG)));
} else {
// First create only the instance passing in the block name
- setProcessor(instantiateProcessor(macroName, new HashMap<String, Object>()));
+ setProcessor(instantiateProcessor(explicitMacroName, new HashMap<String, Object>()));
- getProcessor().setName(macroName);
+ getProcessor().setName(explicitMacroName);
// Then create the config hash that may contain config options defined in the Java constructor
RubyHash config = RubyHashUtil.convertMapToRubyHashWithSymbols(context.getRuntime(), getProcessor().getConfig());

MODIFY
asciidoctorj-core/src/main/java/org/asciidoctor/extension/processorproxies/InlineMacroProcessorProxy.java
asciidoctorj-core/src/main/java/org/asciidoctor/extension/processorproxies/InlineMacroProcessorProxy.java
@@ -63,6 +63,8 @@ public class InlineMacroProcessorProxy extends AbstractMacroProcessorProxy<Inlin
@JRubyMethod(name = "initialize", required = 1, optional = 1)
public IRubyObject initialize(ThreadContext context, IRubyObject[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
+ String explicitMacroName = RubyUtils.rubyToJava(getRuntime(), args[0], String.class);
+
if (getProcessor() != null) {
// Instance was created in Java and has options set, so we pass these
// instead of those passed by asciidoctor
@@ -75,26 +77,36 @@ public class InlineMacroProcessorProxy extends AbstractMacroProcessorProxy<Inlin
rubyConfig.put(regexpSymbol, convertRegexp(getRuntime(), (CharSequence) regexp));
}
+ String macroName = explicitMacroName != null ? explicitMacroName : getProcessor().getName();
+
Helpers.invokeSuper(
context,
this,
getMetaClass(),
METHOD_NAME_INITIALIZE,
new IRubyObject[]{
- JavaEmbedUtils.javaToRuby(getRuntime(), getProcessor().getName()),
+ JavaEmbedUtils.javaToRuby(getRuntime(), macroName),
rubyConfig},
Block.NULL_BLOCK);
+
+ if (explicitMacroName != null) {
+ getProcessor().setName(explicitMacroName);
+ } else if (getProcessor().getName() == null) {
+ RubyHash config = (RubyHash) this.callMethod(context, "config");
+ Object rubyName = config.get(context.getRuntime().newSymbol("name"));
+ if (rubyName != null) {
+ getProcessor().setName(rubyName.toString());
+ }
+ }
+
// The Ruby initialize method may have changed the config, therefore copy it back
// because the accessor is routed to the Java Processor.config
getProcessor().updateConfig(new RubyHashMapDecorator((RubyHash) getInstanceVariable(MEMBER_NAME_CONFIG)));
} else {
- String macroName = RubyUtils.rubyToJava(getRuntime(), args[0], String.class);
// First create only the instance passing in the block name
- setProcessor(instantiateProcessor(macroName));
+ setProcessor(instantiateProcessor(explicitMacroName));
- if (getProcessor().getName() == null) {
- getProcessor().setName(macroName);
- }
+ getProcessor().setName(explicitMacroName);
// Then create the config hash that may contain config options defined in the Java constructor
RubyHash config = RubyHashUtil.convertMapToRubyHashWithSymbols(context.getRuntime(), getProcessor().getConfig());

MODIFY
asciidoctorj-core/src/main/java/org/asciidoctor/internal/JavaExtensionRegistryImpl.java
asciidoctorj-core/src/main/java/org/asciidoctor/internal/JavaExtensionRegistryImpl.java
@@ -246,18 +246,26 @@ public class JavaExtensionRegistryImpl implements JavaExtensionRegistry {
return this;
}
+ @Override
+ public JavaExtensionRegistry inlineMacro(String macroName,
+ InlineMacroProcessor inlineMacroProcessor) {
+ RubyClass rubyClass = InlineMacroProcessorProxy.register(rubyRuntime, inlineMacroProcessor);
+ getAsciidoctorModule().callMethod("inline_macro", rubyClass, rubyRuntime.newString(macroName));
+ return this;
+ }
+
@Override
public JavaExtensionRegistry inlineMacro(InlineMacroProcessor inlineMacroProcessor) {
RubyClass rubyClass = InlineMacroProcessorProxy.register(rubyRuntime, inlineMacroProcessor);
- getAsciidoctorModule().callMethod("inline_macro", rubyClass, rubyRuntime.newString(inlineMacroProcessor.getName()));
+ getAsciidoctorModule().callMethod("inline_macro", rubyClass);
return this;
}
@Override
- public JavaExtensionRegistry inlineMacro(String blockName,
+ public JavaExtensionRegistry inlineMacro(String macroName,
Class<? extends InlineMacroProcessor> inlineMacroProcessor) {
RubyClass rubyClass = InlineMacroProcessorProxy.register(rubyRuntime, inlineMacroProcessor);
- getAsciidoctorModule().callMethod("inline_macro", rubyClass, rubyRuntime.newString(blockName));
+ getAsciidoctorModule().callMethod("inline_macro", rubyClass, rubyRuntime.newString(macroName));
return this;
}
@@ -270,10 +278,10 @@ public class JavaExtensionRegistryImpl implements JavaExtensionRegistry {
}
@Override
- public JavaExtensionRegistry inlineMacro(String blockName, String inlineMacroProcessor) {
+ public JavaExtensionRegistry inlineMacro(String macroName, String inlineMacroProcessor) {
try {
Class<? extends InlineMacroProcessor> inlineMacroProcessorClass = (Class<? extends InlineMacroProcessor>) Class.forName(inlineMacroProcessor);
- inlineMacro(blockName, inlineMacroProcessorClass);
+ inlineMacro(macroName, inlineMacroProcessorClass);
return this;
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);

ADD
asciidoctorj-core/src/test/java/org/asciidoctor/extension/InlineMacroRegistrationTest.java
+package org.asciidoctor.extension;
+
+import org.asciidoctor.Asciidoctor;
+import org.asciidoctor.OptionsBuilder;
+import org.asciidoctor.ast.ContentNode;
+import org.asciidoctor.internal.AsciidoctorCoreException;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jsoup.Jsoup;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Map;
+
+import static java.util.stream.Collectors.joining;
+import static org.junit.Assert.assertEquals;
+
+@RunWith(Arquillian.class)
+public class InlineMacroRegistrationTest {
+
+ @ArquillianResource
+ private Asciidoctor asciidoctor;
+
+ private String document(String blockName, String text) {
+ return "= Test\n" +
+ "\n" +
+ "== A section\n" +
+ "\n" +
+ "\nHello " + blockName + ":" + text + "[]";
+ }
+
+ public static class AbstractTestProcessor extends InlineMacroProcessor {
+ @Override
+ public Object process(ContentNode parent, String target, Map<String, Object> attributes) {
+ String transformed = target.chars()
+ .mapToObj(c -> Character.isUpperCase(c) ? " " + (char) c : Character.toString((char) c))
+ .collect(joining())
+ .toUpperCase().trim();
+ return createPhraseNode(parent, "quoted", transformed);
+ }
+ }
+
+ public static class TestProcessorWithName extends InlineMacroProcessor {
+
+ public static final String NAME = "somename";
+
+ public TestProcessorWithName() {
+ super(NAME);
+ }
+
+ @Override
+ public Object process(ContentNode parent, String target, Map<String, Object> attributes) {
+ String transformed = target.chars()
+ .mapToObj(c -> Character.isUpperCase(c) ? " " + (char) c : Character.toString((char) c))
+ .collect(joining())
+ .toUpperCase().trim();
+ return createPhraseNode(parent, "quoted", transformed);
+ }
+ }
+
+ @Name(AnnotatedTestProcessor.NAME)
+ public static class AnnotatedTestProcessor extends AbstractTestProcessor {
+ public static final String NAME = "annotated";
+ }
+
+ @Test
+ public void testRegisterNamedClassAsClass() {
+ asciidoctor.javaExtensionRegistry().inlineMacro(AnnotatedTestProcessor.class);
+ final String result = asciidoctor.convert(document(AnnotatedTestProcessor.NAME, "World"), OptionsBuilder.options());
+ check("Hello WORLD", result);
+ }
+
+ @Test
+ public void testRegisterNamedClassAsClassWithExplicitName() {
+ final String explicitblockname = "explicitblockname";
+ asciidoctor.javaExtensionRegistry().inlineMacro(explicitblockname, AnnotatedTestProcessor.class);
+ final String result = asciidoctor.convert(document(explicitblockname, "Explicit"), OptionsBuilder.options());
+ check("Hello EXPLICIT", result);
+ }
+
+ @Test
+ public void testRegisterNamedClassAsInstance() {
+ asciidoctor.javaExtensionRegistry().inlineMacro(new AnnotatedTestProcessor());
+ final String result = asciidoctor.convert(document(AnnotatedTestProcessor.NAME, "AnotherTest"), OptionsBuilder.options());
+ check("Hello ANOTHER TEST", result);
+ }
+
+ @Test
+ public void testRegisterNamedClassAsInstanceWithExplicitName() {
+ final String blockName = "somename";
+ asciidoctor.javaExtensionRegistry().inlineMacro(blockName, new AnnotatedTestProcessor());
+ final String result = asciidoctor.convert(document(blockName, "YetAnotherTest"), OptionsBuilder.options());
+ check("Hello YET ANOTHER TEST", result);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testRegisterClassWithoutExplicitName() {
+ asciidoctor.javaExtensionRegistry().inlineMacro(AbstractTestProcessor.class);
+ }
+
+
+ @Test
+ public void testRegisterClassAsClassWithExplicitName() {
+ final String explicitblockname = "anotherexplicitname";
+ asciidoctor.javaExtensionRegistry().inlineMacro(explicitblockname, AbstractTestProcessor.class);
+ final String result = asciidoctor.convert(document(explicitblockname, "ExplicitClass"), OptionsBuilder.options());
+ check("Hello EXPLICIT CLASS", result);
+ }
+
+ @Test(expected = AsciidoctorCoreException.class)
+ public void testRegisterClassAsInstance() {
+ asciidoctor.javaExtensionRegistry().inlineMacro(new AbstractTestProcessor());
+ asciidoctor.convert(document("foo", "HelloExplicitInstance"), OptionsBuilder.options());
+ }
+
+ @Test
+ public void testRegisterClassAsInstanceWithExplicitName() {
+ final String explicitblockname = "someexplicitname";
+ asciidoctor.javaExtensionRegistry().inlineMacro(explicitblockname, new AbstractTestProcessor());
+ final String result = asciidoctor.convert(document(explicitblockname, "ExplicitInstance"), OptionsBuilder.options());
+ check("Hello EXPLICIT INSTANCE", result);
+ }
+
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testRegisterClassWithNameAsClass() {
+ asciidoctor.javaExtensionRegistry().inlineMacro(TestProcessorWithName.class);
+ }
+
+ @Test
+ public void testRegisterClassWithNameAsClassWithExplicitName() {
+ final String explicitblockname = "explicitblockname";
+ asciidoctor.javaExtensionRegistry().inlineMacro(explicitblockname, TestProcessorWithName.class);
+ final String result = asciidoctor.convert(document(explicitblockname, "Explicit"), OptionsBuilder.options());
+ check("Hello EXPLICIT", result);
+ }
+
+ @Test
+ public void testRegisterClassWithNameAsInstance() {
+ asciidoctor.javaExtensionRegistry().inlineMacro(new TestProcessorWithName());
+ final String result = asciidoctor.convert(document(TestProcessorWithName.NAME, "AnotherTest"), OptionsBuilder.options());
+ check("Hello ANOTHER TEST", result);
+ }
+
+ @Test
+ public void testRegisterClassWithNameAsInstanceWithExplicitName() {
+ final String blockName = "somename";
+ asciidoctor.javaExtensionRegistry().inlineMacro(blockName, new TestProcessorWithName());
+ final String result = asciidoctor.convert(document(blockName, "YetAnotherTest"), OptionsBuilder.options());
+ check("Hello YET ANOTHER TEST", result);
+ }
+
+ private void check(String expected, String html) {
+ assertEquals(expected, Jsoup.parse(html).select("div.paragraph > p").first().text());
+ }
+}

Fix registration of InlineMacro with name