Asciidoctor: eval macros from asciidoc

Created on 6 Feb 2019  路  2Comments  路  Source: asciidoctor/asciidoctor

@mojavelinux states that asciidoctor does not support the eval* macros from asciidoc. Any chance eval* macros will be implemented in asciidoctor? Although security issues exist inline Ruby enables database access, calculations, and regular expressions among many other powerful capabilities.

documentation

Most helpful comment

There are several reasons why the eval macro was not brought over from AsciiDoc Python. First, as you mentioned, is the security issue. Such a macro would not only introduce an attack vector, it would disqualify Asciidoctor from being used on GitHub (their terms). Second, it's not a portable macro between Asciidoctor and AsciiDoc Python (and Asciidoctor.js and AsciidoctorJ) on account of the languages being different. And thirdly, there are so many different ways it could work that it ends up being a mess of an implementation. That's why AsciiDoc Python ended up with 3 different eval macros (and as many sys macros). And there could easily be twice that many.

Finally, the eval macro transformed into something much more powerful in Asciidoctor, the extension API. If you want to create an eval macro, you can do so using the extension API. That gives you the freedom to add all the bells and whistles you want.

For these reasons, we won't be bringing the eval macro into Asciidoctor core.

Here's a very simple implementation of an eval macro for Asciidoctor that uses the eval functionality of Ruby:

Asciidoctor::Extensions.register do
  block_macro do
    named :eval
    content_model :text
    process do |parent, target, attrs|
      source = attrs['text'] 
      evaluated_result = eval source
      create_paragraph parent, evaluated_result, {}
    end
  end
end

This extension can be used to process the following AsciiDoc source:

eval::['hello'.upcase]

Using the following call:

asciidoctor -r ./eval-block-macro.rb -o - -s document.adoc

To produce:

<div class="paragraph">
<p>HELLO</p>
</div>

All 2 comments

There are several reasons why the eval macro was not brought over from AsciiDoc Python. First, as you mentioned, is the security issue. Such a macro would not only introduce an attack vector, it would disqualify Asciidoctor from being used on GitHub (their terms). Second, it's not a portable macro between Asciidoctor and AsciiDoc Python (and Asciidoctor.js and AsciidoctorJ) on account of the languages being different. And thirdly, there are so many different ways it could work that it ends up being a mess of an implementation. That's why AsciiDoc Python ended up with 3 different eval macros (and as many sys macros). And there could easily be twice that many.

Finally, the eval macro transformed into something much more powerful in Asciidoctor, the extension API. If you want to create an eval macro, you can do so using the extension API. That gives you the freedom to add all the bells and whistles you want.

For these reasons, we won't be bringing the eval macro into Asciidoctor core.

Here's a very simple implementation of an eval macro for Asciidoctor that uses the eval functionality of Ruby:

Asciidoctor::Extensions.register do
  block_macro do
    named :eval
    content_model :text
    process do |parent, target, attrs|
      source = attrs['text'] 
      evaluated_result = eval source
      create_paragraph parent, evaluated_result, {}
    end
  end
end

This extension can be used to process the following AsciiDoc source:

eval::['hello'.upcase]

Using the following call:

asciidoctor -r ./eval-block-macro.rb -o - -s document.adoc

To produce:

<div class="paragraph">
<p>HELLO</p>
</div>

I'd consider adding this sample to either the docs or the extensions lab. I think it fits better in the docs, to be honest.

Was this page helpful?
0 / 5 - 0 ratings