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>
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
Your answer worked, but doesn't work with two codes:
!!! 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>
.
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>
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):
In the second admonition, your filter didn't remove the title.
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">"Hello World!"</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">"!!!"</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">"Hello World!"</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">"!!!"</span>)</span></code></pre>
</div>
<p>It is not a good code.</p>
</div>
</div>
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 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
notes
: title for notes
some code and text
```C
int main(){
puts("Hello World!");
}
```
denger
: title for denger
some code and text
```python
print('!!!!')
```
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