asciidoctor / asciidoctor-ant

:ant: Ant task to render Asciidoc documentation
Apache License 2.0
9 stars 5 forks source link

Adding Ruby extensions inline #61

Open twogee opened 7 years ago

twogee commented 7 years ago

I would like to add a custom extension to the Ant task using inline Ruby like this

<asciidoctor ...>
<inlineMacroProcessor>
<![CDATA[
   use_dsl
 
   named :man
   name_positional_attributes 'volnum'

   def process parent, target, attrs
     text = manname = target
     suffix = ''
     target = %(#{manname}.html)
    suffix = if (volnum = attrs['volnum'])
    "(#{volnum})"
  else
    nil
  end
  if parent.document.basebackend? 'html'
    parent.document.register :links, target
    %(#{(create_anchor parent, text, type: :link, target: target).render}#{suffix})
  elsif parent.document.backend == 'manpage'
    %(\\fB#{manname}\\fP#{suffix})
  else
    %(#{manname}#{suffix})
  end
end
]]>
</inlineMacroProcessor>
</asciidoctor>

(the code would be wrapped as a class extending Extensions::InlineMacroProcessor and registered as an extension).

The idea is to avoid compiling an extension Java class and adding it to the classpath. Would it be possible?

binout commented 7 years ago

Nice idea ! But i don't know if it's possible ;-)

A solution : copy the ruby code in a temporary file and load it with 'require' in order to be registered. Cf https://blog.jdriven.com/2016/11/awesome-asciidoctor-using-ruby-extensions-asciidoctor-gradle-plugin/ for gradle

Another solution for inline extension : use another script language more compatible with jvm such as Groovy ?

twogee commented 7 years ago

How would a Groovy extension work with Ant?

binout commented 7 years ago

Using GroovyCompiler and GroovyClassloader https://stackoverflow.com/questions/16902906/compiling-and-using-groovy-classes-from-java-at-runtime

Maybe a bit experimental ......

twogee commented 7 years ago

Aren't we looking too far? org.asciidoctor.internal.RubyUtils.loadRubyClass() might be a good starting point...

twogee commented 7 years ago

So, WDYT about adding RubyExtensionRegistry.loadClassScript() and corresponding RubyUtils.loadRubyClassScript() or something like that?

binout commented 7 years ago

i think, just map the inlineMacroProcessor with RubyExtensionRegistry. inlineMacro(blockName, <ruby code>)

about xml definifition, i propose

<inlineMacroProcessor blockName="twitter" source="ruby">
<![CDATA[ .... ]]>
</inlineMacroProcessor>

and to keep backward compatibility, source has default value java

<inlineMacroProcessor blockName="twitter" source="java" classname="...."/>
binout commented 7 years ago

@mojavelinux If you have a few minutes, can you give your opinion? :wink:

twogee commented 6 years ago

Thanks for the pointer, XML definition is fine. Should I consider this a go-ahead?

mojavelinux commented 6 years ago

Seems reasonable to me.

Another option is to leverage the Groovy-based extension DSL, which is what is used in the Gradle plugin. See https://github.com/asciidoctor/asciidoctorj-groovy-dsl. That's where the language setting would probably come in.

mojavelinux commented 6 years ago

Though I would propose dropping the "Processor" part as that is meant to be an internal construct. So it would be:

<inlineMacro>
</inlineMacro>

Another option would just be extensions and allow anything that goes inside the Asciidoctor::Extensions.register block.

twogee commented 6 years ago

Hmm, extensions is an attribute, so it could be confusing. Dropping "Processor" would eventually lead to <post/>, <pre/>, etc should the idea be applied to other extensions...

mojavelinux commented 6 years ago

Sorry, I meant drop "Processor" when it's a syntax extension. In other words, use the same names that are used in the DSL.

mojavelinux commented 6 years ago

To be consistent with the Ant ecosystem, I think you should use all lowercase.

twogee commented 6 years ago

Thanks, I get it now. I believe Ant is case insensitive; camelcase is used for clarity and reflects the naming of underlying Java methods.

mojavelinux commented 6 years ago

Sure, I get your point. But when you document it, I think it's important to fit with the ecosystem for which your developing. The Ant manual uses lowercase for all tags, so using lowercase would make it look consistent. But that's just a suggestion. It's up to you to decide what to do.

binout commented 6 years ago

Ok thanks for the proposals ! Regarding this issue, i propose to keep a consistent syntax with the current implementation

<inlineMacroProcessor blockName="twitter" source="ruby">
<![CDATA[ .... ]]>
</inlineMacroProcessor>

and i will open an issue to rename macro attributes (without processor) and to support lowerCase, maybe for 1.6.X version because of compatibility backward