The macro @markdown
lets you write Markdown inside Pluto notebooks. Here is an example:
import MarkdownLiteral: @markdown
@markdown("""
# MarkdownLiteral.jl
The macro `@markdown` lets you write [Markdown](https://www.markdownguide.org/getting-started/) inside Pluto notebooks. *Here is an example:*
""")
The Markdown parsing is powered by CommonMark.jl, a Julia implementation of the CommonMark specification. Compared to Julia's built-in Markdown parsing, this system is more predicatable and powerful.
The macro @markdown
lets you write HTML inside Pluto notebooks. Here is an example:
@markdown("""
<p>
The macro <code>@markdown</code> lets you write <a href="https://developer.mozilla.org/docs/Web/HTML">HTML</a> inside Pluto notebooks.
<em>Here is an example:</em>
</p>
""")
HTML parsing and interpolation is powered by HypertextLiteral.jl, an interpolation system that understands HTML, CSS and even JavaScript!
Did you see that? It is the same macro! But that's not all!
You can unlock superpowers by combining @markdown
with interpolation (using $
). For our example, let's create some data:
films = [
(title="Frances Ha", director="Noah Baumbach", year=2012)
(title="Portrait de la jeune fille en feu", director="Céline Sciamma", year=2019)
(title="De noorderlingen", director="Alex van Warmerdam", year=1992)
]
Now, we can use interpolation to display our data:
@markdown("""
My films:
$([
"- **$(f.title)** ($(f.year)) by _$(f.director)_\n"
for f in films
])
""")
This gives us:
My films:
- Frances Ha (2012) by Noah Baumbach
- Portrait de la jeune fille en feu (2019) by Céline Sciamma
- De noorderlingen (1992) by Alex van Warmerdam
Alternatively, you could write this using HTML instead of Markdown (with the same macro!):
@markdown("""
<p>My films:</p>
<ul>
$([
@markdown("<li>
<b>$(f.title)</b> ($(f.year)) by <em>$(f.director)</em>
</li>")
for f in films
])
</ul>
""")
Because interpolation is powered by HypertextLiteral.jl, you can use advanced features:
- Interpolated attributes are automatically escaped
- You can use a
NamedTuple
orDict
for the CSSstyle
attribute - Interpolating Julia objects into a
<script>
will automatically convert to JavaScript code(!)
For
logs = [
(text="Info", urgent=false),
(text="Alert", urgent=true),
(text="Update", urgent=false),
]
@markdown("$((
@markdown("<div style=$((
font_weight=900,
padding=".5em",
background=log.urgent ? "pink" : "lightblue",
))>$(log.text)</div>")
for log in logs
))")
Result:
The list of features is really simple to explain: it is everything that CommonMark gives, plus everything that HypertextLiteral gives! This includes:
- CommonMark! Markdown but less glitchy!
- Really flexible interpolation support with infinite nesting and syntax highlighting (since it is a
@markdown("""
macro instead ofmd"""
) - Interpolate Julia objects into
<script>
to automatically convert to JS literals - Context-aware HTML escaping
- Automatic quote wrapping for HTML attributes
- Use a
Dict
orNamedTuple
for thestyle
attribute inside an HTML tag
Also cool: the code is extremely short!
macro md(expr)
cm_parser = CommonMark.Parser()
quote
result = @htl($expr)
htl_output = repr(MIME"text/html"(), result)
$(cm_parser)(htl_output)
end
end
It is essentially the @htl
macro for HypertextLiteral.jl, but the result is passed through a CommonMark parser. This works, because:
- CommonMark allows raw HTML
- HypertextLiteral leaves literal content unchanged, so
hello *world*
appears exactly as-is!