How to create inline macro producing HTML? (In AsciidoctorJ)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
17 messages Options
Reply | Threaded
Open this post in threaded view
|

How to create inline macro producing HTML? (In AsciidoctorJ)

holyjak
Hello!

Inspired by https://github.com/asciidoctor/asciidoctor/issues/252#issuecomment-503605857, instead of writing manually

```
We are pass:["<abbr title='Best Friends Forever'\>BFF</abbr>"]!
```

I want to create a macro that enables me to write


```
We are abbr:BFF["Best Friends Forever"]!
```

However I am not able to find out how to create content that is passed as-is to the HTML generator. I could not find any in-depth documentation about macros and I know only very little Ruby so understanding how it is working is a challenge.

I guess I need to create a "phrase node", but of what type and with what attributes and options? If I read https://github.com/asciidoctor/asciidoctor/blob/v2.0.10/lib/asciidoctor/converter/html5.rb#L50 correctly then the supported "context" of nodes are quoted, anchor, break, button, callout, footnote, image, indexterm, kbd, menu. None of them seems to fit here and I have no idea how to pass raw html to them.

I have tried

```java
createPhraseNode(parent, "pass", "<abbr title=\"" + attributes.get("1") + "\">" + target + "</abbr>"))
```

but it fails because there is no `convert_inline_pass`.

Help and documentation pointers most appreciated!

Cheers, Jakub
Reply | Threaded
Open this post in threaded view
|

Re: How to create inline macro producing HTML? (In AsciidoctorJ)

abelsromero
Since the title mentions AsciidoctorJ, know you can write the extension in Java if that's easier for you.
Have you seen this example? https://github.com/asciidoctor/asciidoctorj/blob/master/docs/integrator-guide.adoc#block-macro-processors.

Also, what building method you use? Plain Java, Maven, Gradle, other?
Reply | Threaded
Open this post in threaded view
|

Re: How to create inline macro producing HTML? (In AsciidoctorJ)

holyjak
Hi, thank you!

Sorry for not being clear. I already have one inline macro that works (the github issue link example from the AsciidoctorJ page). So creating a macro and getting it into the processing is not an issue. What is the issue is how to pass verbatim html so that I achieve the desired effect described above.

(I guess it isn't relevant but I use the Java API from Clojure, using its build tool.)
Reply | Threaded
Open this post in threaded view
|

Re: How to create inline macro producing HTML? (In AsciidoctorJ)

David Jencks
I couldn’t find a way to do that.  What I did was to replace the text in a tree processor.  I’m not sure if it would work in an inline macro.  Have you tried returning either

 "pass:[\"<abbr title='Best Friends Forever'\>BFF</abbr>\”]”

or

"<abbr title='Best Friends Forever'\>BFF</abbr>”

? You aren’t supposed to return text rather than a node but I believe it still works.

David Jencks

On Oct 29, 2020, at 1:49 PM, holyjak [via Asciidoctor :: Discussion] <[hidden email]> wrote:

Hi, thank you!

Sorry for not being clear. I already have one inline macro that works (the github issue link example from the AsciidoctorJ page). So creating a macro and getting it into the processing is not an issue. What is the issue is how to pass verbatim html so that I achieve the desired effect described above.

(I guess it isn't relevant but I use the Java API from Clojure, using its build tool.)


If you reply to this email, your message will be added to the discussion below:
https://discuss.asciidoctor.org/How-to-create-inline-macro-producing-HTML-In-AsciidoctorJ-tp8313p8315.html
To start a new topic under Asciidoctor :: Discussion, [hidden email]
To unsubscribe from Asciidoctor :: Discussion, click here.
NAML

Reply | Threaded
Open this post in threaded view
|

Re: How to create inline macro producing HTML? (In AsciidoctorJ)

abelsromero
There's definetly something I am missing, to my understanding the example in AsciidoctorJ should do what you are asking.
The example injects HTML and it states "As we want to pass through the content directly into the result the context must be pass and the content is the computed HTML string". Also, I know the examples are run as tests during builds, so this works.

I'll build a test later (count 10h from now) but again, I suspect I don't understand the real problem. Can you share a reproducer or exact HTML examples of what expect and waht you get?
Reply | Threaded
Open this post in threaded view
|

Re: How to create inline macro producing HTML? (In AsciidoctorJ)

holyjak
Hello!

The example you refer to is a *block macro* but I want an *inline* macro because I want to use it in the middle of text, like this:

```
Now I am talking about abbr:AOP:["Aspect-Orinted Programming"], an important topic.
```

Are you suggesting that I can actually use block macro for this purpose (and change change from `abbr:` to `abbr:::` in my text)? I am sorry, I understand very little of the Asciidoctor terms such as "block" and "inline" so my intuitive understanding might have been wrong.
Reply | Threaded
Open this post in threaded view
|

Re: How to create inline macro producing HTML? (In AsciidoctorJ)

holyjak
I have tested it and no, block macros cannot be used inside a sentence. Yes, I can create a *block* macro that renders the desired HTML but I need an *inline* macro.
Reply | Threaded
Open this post in threaded view
|

Re: How to create inline macro producing HTML? (In AsciidoctorJ)

abelsromero
In reply to this post by holyjak
See! It was me all allong, that's what I was missing, thanks!
You need an inline macro for sure, now I have everything I need to delve into it later.

In the meantime, if you feel brave, you can have a look at https://github.com/asciidoctor/asciidoctor-extensions-lab, there are some inline macro examples, but in Ruby. For example this one seems to inject HTML directly https://github.com/asciidoctor/asciidoctor-extensions-lab/blob/master/lib/emoji-inline-macro/extension.rb, but could be AsciidoctorJ has some incompatibility/bug.
Reply | Threaded
Open this post in threaded view
|

Re: How to create inline macro producing HTML? (In AsciidoctorJ)

abelsromero
Hi,

Good news is that returning plain string works fine in Java and should in Clojure.

    @Override
    public Object process(ContentNode parent, String target, Map<String, Object> attributes) {
        return "<abbr title=\"" + attributes.get("1") + "\">" + target + "</abbr>";
    }
Seeing there are a couple examples doing so in the extensions-lib should be fine, so long you only convert to 1 format.

Said that, I am digging into the "convert_inline_pass" you reported. It seems to me your first approach was correct and this could be an issue in either Asciidoctorj or Asciidoctor.

Thanks
Reply | Threaded
Open this post in threaded view
|

Re: How to create inline macro producing HTML? (In AsciidoctorJ)

holyjak
You are right, it works! Thanks a lot for your help, it is much appreciated!

Let me know if I can assist in any way in creating an issue on Asciidoctor(J)!

Cheers, Jakub
Reply | Threaded
Open this post in threaded view
|

Re: How to create inline macro producing HTML? (In AsciidoctorJ)

David Jencks
That’s one of the possibilities I proposed.

Returning a string from an inline macro is deprecated, so I hope you can find a way to create the `convert_inline_pass`.

David Jencks

On Oct 30, 2020, at 12:10 PM, holyjak [via Asciidoctor :: Discussion] <[hidden email]> wrote:

You are right, it works! Thanks a lot for your help, it is much appreciated!

Let me know if I can assist in any way in creating an issue on Asciidoctor(J)!

Cheers, Jakub


If you reply to this email, your message will be added to the discussion below:
https://discuss.asciidoctor.org/How-to-create-inline-macro-producing-HTML-In-AsciidoctorJ-tp8313p8323.html
To start a new topic under Asciidoctor :: Discussion, [hidden email]
To unsubscribe from Asciidoctor :: Discussion, click here.
NAML

Reply | Threaded
Open this post in threaded view
|

Re: How to create inline macro producing HTML? (In AsciidoctorJ)

abelsromero
It is deprecated? Documentation does not mention that and the example in the user manual returns string.
In that case, please @Jakub  file an issue in Asciidoctorj repo, I will add my findings.
So far I've seen that AsciidoctorJ and Asciidoctor return different errors, so there's definetly something to improve.
Reply | Threaded
Open this post in threaded view
|

Re: How to create inline macro producing HTML? (In AsciidoctorJ)

mojavelinux
Administrator
> It is deprecated? Documentation does not mention that and the example in the user manual returns string.

The right designation to use is discouraged. You should return a Node if possible.

If you want to return raw HTML, you can return an inline node with the context "quoted" and empty subs (that just results in the content being passed through). The create_inline_pass helper, which does exactly that, was added in Asciidoctor 2.

Best Regards,

-Dan

On Fri, Oct 30, 2020 at 2:34 PM abelsromero [via Asciidoctor :: Discussion] <[hidden email]> wrote:
It is deprecated? Documentation does not mention that and the example in the user manual returns string.
In that case, please @Jakub  file an issue in Asciidoctorj repo, I will add my findings.
So far I've seen that AsciidoctorJ and Asciidoctor return different errors, so there's definetly something to improve.


If you reply to this email, your message will be added to the discussion below:
https://discuss.asciidoctor.org/How-to-create-inline-macro-producing-HTML-In-AsciidoctorJ-tp8313p8325.html
To start a new topic under Asciidoctor :: Discussion, email [hidden email]
To unsubscribe from Asciidoctor :: Discussion, click here.
NAML


--
Dan Allen (he, him, his) | @mojavelinux | https://twitter.com/mojavelinux
Reply | Threaded
Open this post in threaded view
|

Re: How to create inline macro producing HTML? (In AsciidoctorJ)

abelsromero
Thanks Dan!

That helps a lot, that confirms is not an issue then. I admit I don't fully understood the "context" semantics, instead by trial and error I usually get something working but I'd like to address that. So I have a question, why the term "quoted", I understand the meaning is the same as a "pass" block or macro, why not call it "pass" ?

Reply | Threaded
Open this post in threaded view
|

Re: How to create inline macro producing HTML? (In AsciidoctorJ)

mojavelinux
Administrator
> I admit I don't fully understood the "context" semantics

Context is an open-ended way to define a type. Basically, a subclass of Inline.

> why the term "quoted", I understand the meaning is the same as a "pass" block or macro, why not call it "pass"

Technically, an inline pass is not a concrete type. It's only a parsing mode. The closest thing we have is "quoted" with no subs attached. For historical reasons, "quoted" became the type that represents a span of text. (We'll likely rename this in the AsciiDoc spec to formatted text or phrase).

Btw, an extension does not have to use the create* methods. It could just instantiate a new PhraseNode. The create* methods are just helpers.

Best Regards,

-Dan

On Sat, Oct 31, 2020 at 6:31 AM abelsromero [via Asciidoctor :: Discussion] <[hidden email]> wrote:
Thanks Dan!

That helps a lot, that confirms is not an issue then. I admit I don't fully understood the "context" semantics, instead by trial and error I usually get something working but I'd like to address that. So I have a question, why the term "quoted", I understand the meaning is the same as a "pass" block or macro, why not call it "pass" ?




If you reply to this email, your message will be added to the discussion below:
https://discuss.asciidoctor.org/How-to-create-inline-macro-producing-HTML-In-AsciidoctorJ-tp8313p8329.html
To start a new topic under Asciidoctor :: Discussion, email [hidden email]
To unsubscribe from Asciidoctor :: Discussion, click here.
NAML


--
Dan Allen (he, him, his) | @mojavelinux | https://twitter.com/mojavelinux
Reply | Threaded
Open this post in threaded view
|

Re: How to create inline macro producing HTML? (In AsciidoctorJ)

holyjak
In reply to this post by mojavelinux
Hi Dan, thanks a lot! This indeed works:

```clojure
(let [attrs (java.util.HashMap. {})
        opts (java.util.HashMap. {"subs" []})]
    (.createPhraseNode
      this parent, "quoted",
      (str "<abbr title=\"title\">abbreviation</abbr>")
      attrs opts))
```

Is there some introduction to / brief overview of the API where I could learn about the available block x inline contexts and what they mean, and about the possible options and attributes? I feel like a blinded person walking in a maze :-)

> The create_inline_pass helper, which does exactly that, was added in Asciidoctor 2.

How do I use it from Java? If I change the context above to "pass" then it fails with

    java.util.concurrent.ExecutionException: org.asciidoctor.jruby.internal.AsciidoctorCoreException: org.jruby.exceptions.NoMethodError: (NoMethodError) undefined method `convert_inline_pass' for #<Asciidoctor::Converter::Html5Converter:0x3227d4d1>

i.e. it is looking for `convert_inline_pass`, not `create_inline_pass`.

> Btw, an extension does not have to use the create* methods. It could just instantiate a new PhraseNode. The create* methods are just helpers.

I have looked into creating my own PhraseNode but the code that does it - https://github.com/asciidoctor/asciidoctorj/blob/6a3a38925dc2683a2ba6d3dcffd6f71c21b7c8d7/asciidoctorj-core/src/main/java/org/asciidoctor/jruby/extension/internal/JRubyProcessor.java#L175 - is currently beyond my understanding, as it calls into the Ruby code that I do not know. And I don't know what I would gain by doing this manually so I will keep to the helpers :)

Thanks a lot!
Reply | Threaded
Open this post in threaded view
|

Re: How to create inline macro producing HTML? (In AsciidoctorJ)

mojavelinux
Administrator
Glad you got it working! That's exactly the right way to do it.

> > The create_inline_pass helper, which does exactly that, was added in Asciidoctor 2.

> How do I use it from Java? If I change the context above to "pass" then it fails with

What I was pointing out is that it is not available in AsciidoctorJ. If you set the context to pass, it is going to try to convert an inline node of type pass, which is a non-existing thing. inline pass is a parsing concept, not a document node.

> Is there some introduction to / brief overview of the API where I could learn about the available block x inline contexts and what they mean, and about the possible options and attributes?

The best resource at the moment is the integrator guide. See https://github.com/asciidoctor/asciidoctorj/blob/master/docs/integrator-guide.adoc We are working on a new documentation site for Asciidoctor where this document will be available (and likely expanded on / improved).

Best Regards,

-Dan


On Tue, Nov 3, 2020 at 1:20 AM holyjak [via Asciidoctor :: Discussion] <[hidden email]> wrote:
Hi Dan, thanks a lot! This indeed works:

```clojure
(let [attrs (java.util.HashMap. {})
        opts (java.util.HashMap. {"subs" []})]
    (.createPhraseNode
      this parent, "quoted",
      (str "<abbr title=\"title\">abbreviation</abbr>")
      attrs opts))
```

Is there some introduction to / brief overview of the API where I could learn about the available block x inline contexts and what they mean, and about the possible options and attributes? I feel like a blinded person walking in a maze :-)

> The create_inline_pass helper, which does exactly that, was added in Asciidoctor 2.

How do I use it from Java? If I change the context above to "pass" then it fails with

    java.util.concurrent.ExecutionException: org.asciidoctor.jruby.internal.AsciidoctorCoreException: org.jruby.exceptions.NoMethodError: (NoMethodError) undefined method `convert_inline_pass' for #<Asciidoctor::Converter::Html5Converter:0x3227d4d1>

i.e. it is looking for `convert_inline_pass`, not `create_inline_pass`.

> Btw, an extension does not have to use the create* methods. It could just instantiate a new PhraseNode. The create* methods are just helpers.

I have looked into creating my own PhraseNode but the code that does it - https://github.com/asciidoctor/asciidoctorj/blob/6a3a38925dc2683a2ba6d3dcffd6f71c21b7c8d7/asciidoctorj-core/src/main/java/org/asciidoctor/jruby/extension/internal/JRubyProcessor.java#L175 - is currently beyond my understanding, as it calls into the Ruby code that I do not know. And I don't know what I would gain by doing this manually so I will keep to the helpers :)

Thanks a lot!


If you reply to this email, your message will be added to the discussion below:
https://discuss.asciidoctor.org/How-to-create-inline-macro-producing-HTML-In-AsciidoctorJ-tp8313p8336.html
To start a new topic under Asciidoctor :: Discussion, email [hidden email]
To unsubscribe from Asciidoctor :: Discussion, click here.
NAML


--
Dan Allen (he, him, his) | @mojavelinux | https://twitter.com/mojavelinux