asciidoctorj icon indicating copy to clipboard operation
asciidoctorj copied to clipboard

Getting ?0? as target for inline macro when the target is escaped using $$...$$

Open ygra opened this issue 8 years ago • 8 comments

I have a custom inline macro processor that actually processes the target of the macro in a certain way. Furthermore, the target can contain things like braces or square brackets so in some cases some escaping has to be done to not throw the parser off. Until now I actually didn't do anything with the target except pass it along to be processed by a later state (after Asciidoctor) so the problem wasn't caught.

My guess would be that the $$ escape is implemented in a way that it replaces the text in question by a placeholder (?0? in this case) and later reverts that replacement on the output again, preventing me from seeing the actual target in the macro.

Is there a better way to solve this here? Apparently using +++ has the same problem. Or do I just have to escape each problematic character individually?

(Addendum: Escaping square brackets in the target string doesn't seem to work. Instead I get a target that ends in a backslash.)

ygra avatar May 31 '16 10:05 ygra

If you handle text in a special way in an inline macro extension, then that extension is responsible for handling passthroughs in the text. You can do so by invoking the restore_passthroughs(String) method available on the parent node (the first parameter of the process method).

Before any inline substitution occur, the processor extracts passthrough text (that which is escaped with $$, +++ or pass:[]) and leaves behind these placeholders. These placeholders have to be restored before processing is complete. Usually, this happens automatically. However, if you are using the text in a non-conventional way, then they can be left behind.

mojavelinux avatar May 31 '16 23:05 mojavelinux

@mojavelinux Invoking restore_passthroughs(String) could work on AsciidoctorJ 1.5.x but will currently not work on AsciidoctorJ 1.6. Do you think it makes sense to add this method?

robertpanzer avatar Jun 01 '16 06:06 robertpanzer

I'm currently still on 1.5 due to a bunch of other hacks (e.g. changing the context of a block that has been parsed already), so this works nicely. But adding the method would be nice as well, I think. There are cases where an inline macro may need to do something with the target except just passing it on.

ygra avatar Jun 01 '16 07:06 ygra

I think we should add this method to Processor (or perhaps InlineMacroProcessor) as restorePassthroughs, though it should be marked as experimental. This whole passthrough system is going to go away once we parse inline content into the AST. In fact, anyone writing inline macros should understand that they are likely going to have to be rewritten once we fix the inline parsing (now planned for Asciidoctor 2).

mojavelinux avatar Jun 01 '16 07:06 mojavelinux

@ygra great to hear it!

mojavelinux avatar Jun 01 '16 07:06 mojavelinux

Ok, this seems to work fine as long as there is only a single passthrough in the block. As soon as there are two – in different macros – the second one isn't restored anymore and remains in replaced form.

Looking at the Ruby code for restore_passthroughs (as much as I understand it, at least), it seems like this can only be done exactly once per block, which then restores all passthroughs and clears its internal list of replacements. So when you try it a second time for the block it cannot work anymore because the list has been cleared. So this seems to be only possible to do on the complete block content but not on individual parts (like in my case targets of inline macros).

ygra avatar Jun 01 '16 08:06 ygra

I forgot to mention that you need to pass false as the second argument. The method assumes by default that it only has to run once, then it clears the saved passthrough stack.

mojavelinux avatar Jun 01 '16 08:06 mojavelinux

Ah, indeed, that solves it. I'm not used to conditions appearing after statements or I might have noticed it myself :)

ygra avatar Jun 01 '16 08:06 ygra