This is a proposal for a generic syntax to accommodate custom directives/plugins, which is as simple and markdown-like as possible while still accommodating a lot of use cases. While not enabling all markdown extensions (e.g. tables, custom linebreak behaviour etc. doesn’t really fit the template), it works for a lot of them.
There are three different kinds of directives:
-
Inline, start with one colon (analogous to
span
s) -
Leaf block, start with two colons (analogous to empty
div
s) -
Container block, start with at least three colons (analogous to
div
s containing further blocks)
This enables parsers to easily distinguish between inline and leaf blocks (even if an inline directive is the only content of a paragraph), and between leaf and container blocks (without a lot of lookahead).
1. Inline Directive Syntax
The syntax for inline directives:
:name[content]{key=val}
Exactly one colon, followed by the name
which is the identifier for the extension and must be a string without spaces, content
may be further inline markdown elements to be interpreted and then printed in one way or another and the {#myId .myClass key=val key2="val 2"}
contain generic attributes (i.e. key-value pairs) and are optional.
(Originally, the :
was an @
, but !
and ::
are also under discussion. Also, the original post proposed :name[](){}
with the ()
containing a string that’s supposed to contain one or more identifiers, e.g. ids, URLs or filepaths.)
A few example applications:
- Pandoc’s citation syntax could then consequently be changed to
:cit[smith04]
and:cit[@doe99, pp. 33-35, 38-39 and *passim*]
. -
spoilers that are hidden by default
:spoiler[it's a _happy_ ending]
- Wikipedia links:
:wikipedia[Foobar]
-
Small caps:
:smallcaps[content]
-
References to figures:
as seen in the :ref[scatter plot]{target=myFigure}
could expand to:as seen in the <a href="#myFigure">scatter plot (Figure 15)</a>
(when the image with idmyFigure
is the 15th) - Create
tel:
-links for phone numbers::tel[+375255318270]
- more on this GitHub wiki page…
2. Leaf Block Directives
The syntax for leaf block directives:
:: name [content] {key=val}
To be recognized as a directive, this has to form an otherwise empty paragraph. But as opposed to inline directives, there are two colons now, the brackets []
are optional as well, and spaces may be interspersed for readability.
Example applications:
- Proposal from this thread for code snippets:
::snip[label]{file=path/to/code.scala}
- and from this thread:
::youtube[title]{vid=09jf3ow9jfw}
-
this thread:
::video[title]{file=filename.mp4}
-
transclusions:
::include{file=other-file.md}
- placing a table of contents:
::toc[Table des matières]
3. Container Block Directives
Container blocks contain further blocks. The proposed syntax for container block directives is:
::: name [inline-content] {key=val}
contents, which are sometimes further block elements
:::
Analogous to fenced code blocks, an arbitrary number of colons greater or equal three could be used as long as the closing line is longer than the opening line. That way, you can even nest blocks (think div
s) by using successively fewer colons for each containing block. Finally, the first line might also have non-significant trailing colons, so you can do things like:
:::::::::::: SPOILER :::::::::::::
We're going to spoil it in three
easy steps:
1. ready
2. steady
3. go
::::::::::::::::::::::::::::::::::
Further examples include this proposal:
:::eval [label] {.python}
x = 1+1
print x
:::
amending this proposal:
:::form
Choose an email
_____
Choose a password
*****
[submit]
:::
and replacing the .md.html.
-example syntax from the CommonMark spec.txt:
:::md-example
- one
- two
:
<ul>
<li>one</li>
<li>two</li>
</ul>
:::
If no name is provided, it falls back naturally to a div
with optional attributes:
::: {.myClass}
some markdown
:::
Span element
And because it’s quite similar, a proposal for a native span element with attributes:
hello [world]{.myClass}
which would translate to:
<p>hello <span class="myClass">world</span>
Identifier Registry
Finally, we could set up a maintained registry for the extension-identifiers (cit
, snip
, etc.) and if a processor doesn’t know an extension it could always fall back to a span with class="extension-name"
for HTML. Even more useful should be a generic directive representation in the AST which modules or filters could hook into to use a different set of directives for different use cases. That representation then should contain both the parsed and raw strings of the directives’ contents, because some plugins might want to use the parsed markdown while others want to do the parsing of the contents themselves.