Convertng Markdown admonition syntax to HTML, using Lua for Pandoc
Asked Answered
P

1

3

The Markdown admonition syntax is based on https://python-markdown.github.io/extensions/admonition/:

!!! note Important note
    You should note that the title will be automatically capitalized.

The Pandoc documentation is very poorly explained and badly written. I've trained myself with the following questions:

I attempted to build in Lua:

function Para (para)
  if para.content[1].text == "!!!" and para.content[1].text == "note" then
    return pandoc.Plain(
      {pandoc.RawInline('html', '<div class="admonition note">')} ..
      {pandoc.RawInline('html', '<p class="admonition-title">')} ..
      para.content[2].text ..
      {pandoc.RawInline('html', '</p>')} ..
      para.content[3].text ..
      {pandoc.RawInline('html', '</div>')}
    )
  elseif para.content[1].text == "!!!" and para.content[1].text == "danger" then
    return pandoc.Plain(
      {pandoc.RawInline('html', '<div class="admonition danger">')} ..
      {pandoc.RawInline('html', '<p class="admonition-title">')} ..
      para.content[2].text ..
      {pandoc.RawInline('html', '</p>')} ..
      para.content[3].text ..
      {pandoc.RawInline('html', '</div>')}
    )
  end
end

I would expect:

<div class="admonition note">
<p class="admonition-title">Important note</p>
<p>You should note that the title will be automatically capitalized.</p>
</div>

Update 1

It almost worked, I just didn't like para.content[number].text because I need to surround "Important note" for admonition title and to catch the whole sentence after that admonition title for a paragraph.

function Para(para)
  if para.content[1].text == '!!!' and para.content[2].tag == 'Space' and para.content[3].text == 'note' then
    return pandoc.RawInline('html',
      '<div class="admonition note">'
        .. '\n\t' ..
        '<p class="admonition-title">' 
          .. para.content[5].text .. 
        '</p>'
        .. '\n\t' ..
        para.content[5].text ..
        '\n' .. 
      '</div>')
  elseif para.content[1].text == '!!!' and para.content[2].tag == 'Space' and para.content[3].text == 'danger' then
    return pandoc.Emph {pandoc.Str "Danger"}
  end
end

Update 2

Your answer worked, but doesn't work with two codes:

  1. When no title, it looks like:
!!! important ""

But it gave an output:

<div class="admonition important ““"><p class="admonition-title">IMPORTANT</p>
admonition with no title
</div>

You can notice important ““". If I want to use "" to hide the title, it would give an output: <div class="admonition important"><p class="admonition-title no-title">IMPORTANT</p></div>.

  1. When I want to include one than paragraphs, containing italic, bold, blockquote, code, etc., your filter takes only the first paragraph, therefore, ignores the rest of the text. You can see the the reference: https://github.com/qjebbs/vscode-markdown-extended#admonition. It should look like in HTML:
<div class="admonition important"><p class="admonition-title">IMPORTANT</p>
<p> Here is the first paragraph with a <code>code</code>...</p>
<p> Here is the second paragraph with <i>italic</i> and <b>boild</b>...
<pre><code class="language-css">.css { color: black; }</code></pre>
<blockquote>
Accidit in puncto, quod non contingit in anno
</blockquote>
Julius Caesarus
</div>

Update 3

Please forgive me for failing to deliver the full CSS code for you before. Get the full code below:

@font-face {
    font-family: "Material Icons";
    font-style: normal;
    font-weight: 400;
    src: local("Material Icons"), local("MaterialIcons-Regular"), url("data:application/x-font-woff;charset=utf-8;base64,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") format("woff");
}

.admonition {
    box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 1px 5px 0 rgba(0, 0, 0, .12), 0 3px 1px -2px rgba(0, 0, 0, .2);
    position: relative;
    margin: 1.5625em 0;
    padding: 0 1.2rem;
    border-left: .4rem solid rgba(68, 138, 255, .8);
    border-radius: .2rem;
    background-color: rgba(255, 255, 255, 0.05);
    overflow: auto;
}

.admonition>p {
    margin-top: .8rem;
}

.admonition>.admonition-title {
    margin: 0 -1.2rem;
    padding: .8rem 1.2rem .8rem 3.6rem;
    border-bottom: 1px solid rgba(68, 138, 255, .2);
    background-color: rgba(68, 138, 255, .1);
    font-weight: 700;
}

.admonition>.admonition-title:before {
    position: absolute;
    left: 1.2rem;
    font-size: 1.5rem;
    color: rgba(68, 138, 255, .8);
    content: "\E3C9";
}

.admonition>.admonition-title:before {
    font-family: Material Icons;
    font-style: normal;
    font-variant: normal;
    font-weight: 400;
    line-height: 2rem;
    text-transform: none;
    white-space: nowrap;
    speak: none;
    word-wrap: normal;
    direction: ltr;
}

.admonition.summary,
.admonition.abstract,
.admonition.tldr {
    border-left-color: rgba(0, 176, 255, .8);
}

.admonition.summary>.admonition-title,
.admonition.abstract>.admonition-title,
.admonition.tldr>.admonition-title {
    background-color: rgba(0, 176, 255, .1);
    border-bottom-color: rgba(0, 176, 255, .2);
}

.admonition.summary>.admonition-title:before,
.admonition.abstract>.admonition-title:before,
.admonition.tldr>.admonition-title:before {
    color: rgba(0, 176, 255, 1);
    ;
    content: "\E8D2";
}

.admonition.hint,
.admonition.tip {
    border-left-color: rgba(0, 191, 165, .8);
}

.admonition.hint>.admonition-title,
.admonition.tip>.admonition-title {
    background-color: rgba(0, 191, 165, .1);
    border-bottom-color: rgba(0, 191, 165, .2);
}

.admonition.hint>.admonition-title:before,
.admonition.tip>.admonition-title:before {
    color: rgba(0, 191, 165, 1);
    content: "\E80E";
}

.admonition.info,
.admonition.todo {
    border-left-color: rgba(0, 184, 212, .8);
}

.admonition.info>.admonition-title,
.admonition.todo>.admonition-title {
    background-color: rgba(0, 184, 212, .1);
    border-bottom-color: rgba(0, 184, 212, .2);
}

.admonition.info>.admonition-title:before,
.admonition.todo>.admonition-title:before {
    color: rgba(0, 184, 212, 1);
    ;
    content: "\E88E";
}

.admonition.success,
.admonition.check,
.admonition.done {
    border-left-color: rgba(0, 200, 83, .8);
}

.admonition.success>.admonition-title,
.admonition.check>.admonition-title,
.admonition.done>.admonition-title {
    background-color: rgba(0, 200, 83, .1);
    border-bottom-color: rgba(0, 200, 83, .2);
}

.admonition.success>.admonition-title:before,
.admonition.check>.admonition-title:before,
.admonition.done>.admonition-title:before {
    color: rgba(0, 200, 83, 1);
    ;
    content: "\E876";
}

.admonition.question,
.admonition.help,
.admonition.faq {
    border-left-color: rgba(100, 221, 23, .8);
}

.admonition.question>.admonition-title,
.admonition.help>.admonition-title,
.admonition.faq>.admonition-title {
    background-color: rgba(100, 221, 23, .1);
    border-bottom-color: rgba(100, 221, 23, .2);
}

.admonition.question>.admonition-title:before,
.admonition.help>.admonition-title:before,
.admonition.faq>.admonition-title:before {
    color: rgba(100, 221, 23, 1);
    ;
    content: "\E887";
}

.admonition.warning,
.admonition.attention,
.admonition.caution {
    border-left-color: rgba(255, 145, 0, .8);
}

.admonition.warning>.admonition-title,
.admonition.attention>.admonition-title,
.admonition.caution>.admonition-title {
    background-color: rgba(255, 145, 0, .1);
    border-bottom-color: rgba(255, 145, 0, .2);
}

.admonition.attention>.admonition-title:before {
    color: rgba(255, 145, 0, 1);
    content: "\E417";
}

.admonition.warning>.admonition-title:before,
.admonition.caution>.admonition-title:before {
    color: rgba(255, 145, 0, 1);
    content: "\E002";
}

.admonition.failure,
.admonition.fail,
.admonition.missing {
    border-left-color: rgba(255, 82, 82, .8);
}

.admonition.failure>.admonition-title,
.admonition.fail>.admonition-title,
.admonition.missing>.admonition-title {
    background-color: rgba(255, 82, 82, .1);
    border-bottom-color: rgba(255, 82, 82, .2);
}

.admonition.failure>.admonition-title:before,
.admonition.fail>.admonition-title:before,
.admonition.missing>.admonition-title:before {
    color: rgba(255, 82, 82, 1);
    ;
    content: "\E14C";
}

.admonition.danger,
.admonition.error,
.admonition.bug {
    border-left-color: rgba(255, 23, 68, .8);
}

.admonition.danger>.admonition-title,
.admonition.error>.admonition-title,
.admonition.bug>.admonition-title {
    background-color: rgba(255, 23, 68, .1);
    border-bottom-color: rgba(255, 23, 68, .2);
}

.admonition.danger>.admonition-title:before {
    color: rgba(255, 23, 68, 1);
    content: "\E3E7";
}

.admonition.error>.admonition-title:before {
    color: rgba(255, 23, 68, 1);
    content: "\E14C";
}

.admonition.bug>.admonition-title:before {
    color: rgba(255, 23, 68, 1);
    content: "\E868";
}

.admonition.example,
.admonition.snippet {
    border-left-color: rgba(0, 184, 212, .8);
}

.admonition.example>.admonition-title,
.admonition.snippet>.admonition-title {
    background-color: rgba(0, 184, 212, .1);
    border-bottom-color: rgba(0, 184, 212, .2);
}

.admonition.example>.admonition-title:before,
.admonition.snippet>.admonition-title:before {
    color: rgba(0, 184, 212, 1);
    ;
    content: "\E242";
}

.admonition.quote,
.admonition.cite {
    border-left-color: rgba(158, 158, 158, .8);
}

.admonition.quote>.admonition-title,
.admonition.cite>.admonition-title {
    background-color: rgba(158, 158, 158, .1);
    border-bottom-color: rgba(158, 158, 158, .2);
}

.admonition.quote>.admonition-title:before,
.admonition.cite>.admonition-title:before {
    color: rgba(158, 158, 158, 1);
    ;
    content: "\E244";
}

.no-title
{
    display: none;
}

I had acknowledged of Pandoc's new Markdown syntax definition, but it is a bad idea to use dl, dt and dd for admonitions because they are designed for definitions, dictionaries, and glossaries. But anyway, I also tested with and without a Markdown syntax : and it wasn't what I expected.

With your updated Lua code, here is the result (click the image to enlarge):

result

In the second admonition, your filter didn't remove the title.

Expected:

expected

You can compare the images and understand it easily.

I prepared Markdown and HTML codes for you.

Here is the Markdown code:

<!-- With title -->
!!! note "Pay attention!"
    Title for notes

    some code and text
    
    ```C
    int main(){
        puts("Hello World!");
    }
    ```

    It is a good code.

    !!! danger "Be careful!"
    Title for denger
    
    some code and text

    ```python
    print
    ```

    It is not a good

<!-- Without title -->
!!! note ""
    Title for notes

    some code and text

    ```C
    int main(){
        puts("Hello World!");
    }
    ```

    It is a good code.

    !!! danger "Be careful!"
    Title for denger
    
    some code and text

    ```python
    print
    ```

    It is not a good

And the HTML code:

  <!-- With title -->

  <div class="admonition note">
    <p class="admonition-title">Pay attention!</p>

    <p>Title for notes</p>
    <p>some code and text</p>
    <div class="sourceCode" id="cb1">
      <pre class="sourceCode C"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(){</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    puts<span class="op">(</span><span class="st">&quot;Hello World!&quot;</span><span class="op">);</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre>
    </div>
    <p>It is a good code.</p>
    <div class="admonition danger">
      <p class="admonition-title">Be careful!</p>

      <p>Title for denger</p>
      <p>some code and text</p>
      <div class="sourceCode" id="cb2">
        <pre
          class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(<span class="st">&quot;!!!&quot;</span>)</span></code></pre>
      </div>
      <p>It is not a good code.</p>
    </div>

  </div>

  <!-- Without title -->

  <div class="admonition note">
    <p class="admonition-title no-title">Pay attention!</p>

    <p>Title for notes</p>
    <p>some code and text</p>
    <div class="sourceCode" id="cb3">
      <pre class="sourceCode C"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(){</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    puts<span class="op">(</span><span class="st">&quot;Hello World!&quot;</span><span class="op">);</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre>
    </div>
    <p>It is a good code.</p>
    <div class="admonition danger">
      <p class="admonition-title">Be careful!</p>

      <p>Title for denger</p>
      <p>some code and text</p>
      <div class="sourceCode" id="cb4">
        <pre
          class="sourceCode python"><code class="sourceCode python"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(<span class="st">&quot;!!!&quot;</span>)</span></code></pre>
      </div>
      <p>It is not a good code.</p>
    </div>

  </div>
Plicate answered 20/7, 2022 at 9:42 Comment(4)
para.content[1].text == "!!!" and para.content[1].text == "note" is always false, as is para.content[1].text == "!!!" and para.content[1].text == "danger"; your ifs can't possibly execute. You'll want to match para.content[1].text against something such as para.content[1].text:match"^!!!%s+note.Unequivocal
Well, your tip does not work.Patman
@GustavoReis I use pandoc's definition list syntax and replace lua filter to javascript code.The render will happen when browser load the document.I add : at next line of title and tags, and pandoc read it as a whole definition list include its child admonitions.see Update 3 of my answer.Guimond
pandoc readers can parse admonition syntax, but that requires to parse full markdown syntax in lua, which is more harder then my javascript code.Guimond
G
4

Here is a lua filter like Python-Markdown's Admonition extension syntax.

You can use many tags(CSS class names), and Quoted title ""

the different in this filter is you can't use indent, for pandoc do not think !!! should have a indent, so pandoc will render badly if you use indent.

!!! danger notes "title"
You should note that the title will be automatically capitalized.
```haskell
--code will be rendered
main::IO ()
main = main
```

*Emph string* and **strong string**

!!! important ""
admonition with no title

the lua filter

function Para(para)
  if para.content[1] and para.content[1].text == '!!!' and 
    para.content[2] and para.content[2].tag == 'Space' and 
    para.content[3] and para.content[3].tag == 'Str' then
    local text = para.content[3].text -- default title is tag
    tags = text
    title = string.upper(text)
    i = 4
    -- parse tags
    while para.content[i] and para.content[i].tag ~= 'SoftBreak'
    do
      -- tags can only be string or spaces
      if para.content[i].tag == 'Str' then
        tags = tags .. para.content[i].text
      elseif para.content[i].tag == 'Space' then
        tags = tags .. ' '
      -- Quoted is title
      elseif para.content[i].tag == 'Quoted' then
        title = pandoc.utils.stringify(para.content[i].content)
      end
      i = i + 1
    end
    if para.content[i] and para.content[i].tag == 'SoftBreak' then
      body = pandoc.List({table.unpack(para.content, i+1)})
    else
      body = '' -- no body
    end
    return pandoc.Blocks( -- merge into blocks
      {
        pandoc.RawInline(
          'html','<div class="admonition ' .. tags .. '">' ..
          '<p class="admonition-title">' .. title .. '</p>'
        ),
        pandoc.Plain(body),
        pandoc.RawInline('html', '</div>')
      }
    )
  end
end

preview output(the first paragraph)

$ pandoc test.md --lua-filter f.lua
<div class="admonition danger notes "><p class="admonition-title">title</p>
You should note that the title will be automatically capitalized.
</div>

you can add a stylesheet, for example H.html

<style>
div.note {
    background-color: #24502426;
}
div.danger {
    background-color: #8c24047a;
}
p.admonition-title {
    font-family: cursive;
}
</style>

then run

$ pandoc test.md --lua-filter f.lua -s -o main.html -H H.html

Update 2

update for empty title

@Gustavo Reis pandoc read wrong indentation before filter processing the text, so my filter can't be nesting.If you want to change this, you can try definition lists which can be nesting

function Para(para)
  if para.content[1] and para.content[1].text == '!!!' and 
    para.content[2] and para.content[2].tag == 'Space' and 
    para.content[3] and para.content[3].tag == 'Str' then
    local text = para.content[3].text -- default title is tag
    tags = text
    title = string.upper(text)
    i = 4
    -- parse tags
    while para.content[i] and para.content[i].tag ~= 'SoftBreak'
    do
      -- tags can only be string or spaces
      if para.content[i].tag == 'Str' then
        if para.content[i].text == '“”' then
          title = nil
        else
          tags = tags .. para.content[i].text
        end
      elseif para.content[i].tag == 'Space' then
        tags = tags .. ' '
      -- Quoted is title
      elseif para.content[i].tag == 'Quoted' then
        title = pandoc.utils.stringify(para.content[i].content)
      end
      i = i + 1
    end
    if para.content[i] and para.content[i].tag == 'SoftBreak' then
      body = pandoc.List({table.unpack(para.content, i+1)})
    else
      body = '' -- no body
    end
    if title==nil then
      title_html = '<p class="admonition-title no-title"/>'
    else
      title_html = '<p class="admonition-title">' .. title .. '</p>'
    end
    return pandoc.Blocks( -- merge into blocks
      {
        pandoc.RawInline(
          'html','<div class="admonition ' .. tags .. '">' .. title_html
        ),
        pandoc.Plain(body),
        pandoc.RawInline('html', '</div>')
      }
    )
  end
end

definition list example

definition list example

notes

:   title for notes

    some code and text
    ```C
    int main(){
        puts("Hello World!");
    }
    ```

    denger
    :   title for denger
    
        some code and text
        ```python
        print('!!!!')
        ```

Update 3

in this update, I use definition list in markdown(with !!! syntax) and replace lua filter to javascript code.

window.onload = function(){
    document.querySelectorAll('dl').forEach(n => n.classList.add('admonition'))
    let dts = document.querySelectorAll('dt');
    for(let dt of dts){
        let text = dt.innerText;
        let default_title = false;
        if (text.slice(0, 4)=='!!! '){
            let i = text.lastIndexOf('“');
            dt.classList.add('admonition-title');
            if (i == -1) {
                i = text.length;
                default_title = true;
            }
            let tags = text.slice(4, i).split(' ').filter((x)=>x.length);
            for (var j = tags.length - 1; j >= 0; j--) {
                dt.parentNode.classList.add(tags[j]);
            }
            if (default_title) {
                dt.innerText = tags[0] || "";
            }else{
                let end = text.lastIndexOf('”');
                if (end == -1) {
                    end = text.length;
                }
                dt.innerText = text.slice(i+1, end);
                if (dt.innerText == '') {
                    dt.classList.add('no-title');
                }
            }
        }         
    }
}

the markdown code

<!-- With title -->
!!! note "Pay attention!"
:   Title for notes

    some code and text
    
    ```C
    int main(){
        puts("Hello World!");
    }
    ```

    It is a good code.

    !!! danger "Be careful!"
    :   Title for denger
    
        some code and text
    
        ```python
        print
        ```
    
        It is not a good

<!-- Without title -->
!!! note ""
:   Title for notes

    some code and text

    ```C
    int main(){
        puts("Hello World!");
    }
    ```

    It is a good code.

    !!! danger "Be careful!"
    :   Title for denger
        
        some code and text
    
        ```python
        print
        ```
    
       It is not a good

this CSS code is unchanged

below is screenshot

It seems that the effect of using dt, dl, dd is similar to using div

Guimond answered 25/7, 2022 at 6:23 Comment(2)
Please check Update 2 in my question detail.Patman
Please forgive me for having failed to deliver the full CSS code for you to ease your understanding. Please check Update 3. I added two images, one resulted and another expected for easing your understanding. I also prepared the full Markdown and HTML codes for easing your analysis.Patman

© 2022 - 2024 — McMap. All rights reserved.