asciidoctorj
asciidoctorj copied to clipboard
BlockProcessor causes exception with missing contexts option
I've tried writing a Block processor in AsciidoctorJ, more or less starting from the YellBlock example. However, I constantly got an exception:
Exception in thread "main" org.asciidoctor.internal.AsciidoctorCoreException: org.jruby.exceptions.RaiseException: (NoMethodError) asciidoctor: FAILED: <stdin>: Failed to load AsciiDoc document - undefined method `include?' for nil:NilClass
at org.asciidoctor.internal.JRubyAsciidoctor.render(JRubyAsciidoctor.java:314)
at org.asciidoctor.internal.JRubyAsciidoctor.render(JRubyAsciidoctor.java:422)
at org.asciidoctor.internal.JRubyAsciidoctor.convert(JRubyAsciidoctor.java:524)
at Main.main(Main.java:10)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: org.jruby.exceptions.RaiseException: (NoMethodError) asciidoctor: FAILED: <stdin>: Failed to load AsciiDoc document - undefined method `include?' for nil:NilClass
at RUBY.registered_for_block?(C:/Users/roessel/.m2/repository/org/asciidoctor/asciidoctorj/1.5.4/asciidoctorj-1.5.4.jar!/gems/asciidoctor-1.5.4/lib/asciidoctor/extensions.rb:907)
at RUBY.next_block(C:/Users/roessel/.m2/repository/org/asciidoctor/asciidoctorj/1.5.4/asciidoctorj-1.5.4.jar!/gems/asciidoctor-1.5.4/lib/asciidoctor/parser.rb:689)
at RUBY.next_section(C:/Users/roessel/.m2/repository/org/asciidoctor/asciidoctorj/1.5.4/asciidoctorj-1.5.4.jar!/gems/asciidoctor-1.5.4/lib/asciidoctor/parser.rb:315)
at RUBY.parse(C:/Users/roessel/.m2/repository/org/asciidoctor/asciidoctorj/1.5.4/asciidoctorj-1.5.4.jar!/gems/asciidoctor-1.5.4/lib/asciidoctor/parser.rb:67)
at RUBY.parse(C:/Users/roessel/.m2/repository/org/asciidoctor/asciidoctorj/1.5.4/asciidoctorj-1.5.4.jar!/gems/asciidoctor-1.5.4/lib/asciidoctor/document.rb:471)
at RUBY.load(C:/Users/roessel/.m2/repository/org/asciidoctor/asciidoctorj/1.5.4/asciidoctorj-1.5.4.jar!/gems/asciidoctor-1.5.4/lib/asciidoctor.rb:1344)
at RUBY.convert(C:/Users/roessel/.m2/repository/org/asciidoctor/asciidoctorj/1.5.4/asciidoctorj-1.5.4.jar!/gems/asciidoctor-1.5.4/lib/asciidoctor.rb:1462)
at RUBY.convert(<script>:72)
at org.jruby.gen.InterfaceImpl865194084.convert(org/jruby/gen/InterfaceImpl865194084.gen:13)
(At least 1.5.4 is more helpful by including the Ruby stacktrace). This seems to stem from the fact that there is no entry with key :contexts
in the extension options. The relevant Ruby portion for this is:
# Public: Checks whether any {BlockProcessor} extensions are registered to
# handle the specified block name appearing on the specified context.
#
# Returns the [Extension] proxy object for the BlockProcessor that matches
# the block name and context or false if no match is found.
def registered_for_block? name, context
if (ext = @block_extensions[name.to_sym])
(ext.config[:contexts].include? context) ? ext : false
else
false
end
end
The exception happens in the if
block.
This essentially means that the example as given in the docs does not work (and the exceptions are/were less than helpful in figuring out what to change).
Hi,
agreed, the documentation is not complete yet. What is missing is passing the context via the config: https://github.com/asciidoctor/asciidoctorj/blob/master/asciidoctorj-core/src/test/java/org/asciidoctor/extension/WhenJavaExtensionIsRegistered.java#L653-L657
Map<String, Object> config = new HashMap<String, Object>();
config.put("contexts", Arrays.asList(":paragraph"));
config.put("content_model", ":simple");
YellBlock yellBlock = new YellBlock("yell", config);
javaExtensionRegistry.block(yellBlock);
Please note that the extensions will get a major overhaul with AsciidoctorJ 1.6.0 and this is already documented there: https://github.com/asciidoctor/asciidoctorj/blob/asciidoctorj-1.6.0/docs/integrator-guide.adoc#block-processors While annotation based configuration is not available on the currently published version of AsciidoctorJ and the method signatures are a bit different I think it still shows what configuration parameters are necessary for an extension.
I'll add my recommendation that anyone writing extensions for AsciidoctorJ should be using AsciidoctorJ 1.6.0. The API has been refactored and documented, so it's going to be a much smoother experience. It also allows us to more easily accept feedback since development is happening on the 1.6.0 branch.
@mojavelinux So essentially, if I'm starting out right now to build a toolchain for converting Asciidoc with custom macros, etc. I should use 1.6 and it should be stable enough right now to be used? I was a bit wary to do so initially as I wasn't sure how many changes were still to come.
I should use 1.6 and it should be stable enough right now to be used?
Yes. In many ways, AsciidoctorJ 1.6.0 is more stable than 1.5.4 (in terms of runtime stability).
I was a bit wary to do so initially as I wasn't sure how many changes were still to come.
Now that we got the AST the way we want it, I'd say it's pretty stable. We'll probably defer any further big changes to 1.7.0. Though, I defer to Robert on that.
The one exception to writing macros for 1.5.x is if you are distributing them to the general public. In that case, you'd have to write against 1.5.x or else you'd be forcing everyone to upgrade. When it's for your own uses (or internal), then we are recommending 1.6.0.
My goal is to have 1.6.0 out by sometime this summer. We need to get over this hump.