Hi, everyone!
I made a plugin for markdown-it which fully implement this spec.
If you use javascript as your development language, just have a look!
If you think this work can help you, please give me a star!
Hi, everyone!
I made a plugin for markdown-it which fully implement this spec.
If you use javascript as your development language, just have a look!
If you think this work can help you, please give me a star!
I donât think itâs yet in the current official standard, but thanks @lookas for making an implementation. It will be interesting to see how well it will work in the real world. Is there a way to track if people are having issues with how your plugin is implemented that the community should account for?
It doesnât look like anyone has explicitly discussed significant whitespace in directives. Currently the only Markdown syntax that supports significant whitespace is code blocks, and otherwise the spec says that leading whitespace should be trimmed. However, even in the OPâs examples, there is code inside the directives. Iâm currently using an implementation of generic directives via the remark-directive plugin, and virtually all of the container directives Iâve implemented could benefit greatly from respecting significant whitespace.
Interestingly, I can maintain significant whitespace in my directives by also wrapping them in code fences, e.g.
:::ditaa
```
+---+
| A |
+-+-+
| +---+
+->+ B +
+---+
```
:::
While this works, itâs not particularly intuitive, and honestly itâs probably more of a bug than a feature.
The biggest concern that I have with making all directives respect significant whitespace is that there may be some directives that specifically shouldnât respect it. Considering that all generic directives will need an implementation to be built into their renderer, though, I think itâs reasonable to assume that significant whitespace could be trimmed in the renderer in those cases.
considering that already the parser has to decide how to handle the contents of a directive, this is not something that can be handled in the renderer. IMHO, the contents of directives should always be parsed as markdown. For your use-case, using code blocks (with attributes) seems to be the right solution:
``` {.ditaa}
+---+
| A |
+-+-+
| +---+
+->+ B +
+---+
```
Reading your original post, it really feels to me like that wasnât the intention, specially given directives such as :::eval
, :::form
and :::md-example
given as examples in the post, which definitely contain things that cannot be interpreted as plain Markdown.
Also, I wanted to be able to share a suggestion regarding this. Talking specifically about block directives: Is it really necessary to interpret attributes in any way in the CommonMark specification itself?
The specification currently makes no effort to actually parse the info string in code blocks, leaving it up to implementations to handle it whichever way they prefer. Would it not make sense to do the same with blocks of nested Markdown?
For example, consider the following:
~~~ class="lang-c" id="block"
int main() { return 0; }
~~~
CommonMark doesnât specify that the info string should be interpreted as a sole language name, so if some implementation wants to parse the above as attributes to apply to the pre
or code
elements (if converting to HTML), it is free to do so. (And it can choose whatever syntax it wants.)
I think that could be extended for blocks of Markdown too, where the âinfo stringâ is also left to be parsed by the implementation itself:
::: aside class="ad"
Buy **our product**!
:::
The whole aside class="ad"
would be parsed as an opaque string in the CommonMark spec, and the implementation could be free to interpret whichever way it wants.
For inline text spans, I think a good approach would be to simply have a []{}
syntax, where the text inside []
is always parsed as inline Markdown, and the text inside {}
is also an opaque string (that implementations can choose what to do with).
Considering that already the parser has to decide how to handle the contents of a directive, this is not something that can be handled in the renderer.
Directives seem like a really great opportunity to enable any type of custom rendering, but being prescriptive about how the contents should be handled limits the opportunities to any type of custom rendering, so long as youâre good with the contents being converted to Markdown first.
To remedy this, I think that the parser should decide to leave the content of the directive alone. If the user wants the directive to be rendered to Markdown, they can rerun the parser separately.
As a more concrete example, consider a directive that renders Markdown into a specific element, like a figure
with a figcaption
:
:::figure
![Image](image_url)
::figcaption[A description of the *diagram* rendered ~below~ above.]
:::
Outputs:
<figure>
<img title="Image" src="image_url">
<figcaption>A description of the <em>diagram</em> rendered <s>below<s> above.</figcaption>
</figure>
The parser would not parse the contents of the directive, which kind of sucks. However, if the contents of the directive need to be rendered as Markdown, the renderer could run the parser again over contents of the directive. Thatâs maybe not ideal, but it enables so many more opportunities.
For your use-case, using code blocks (with attributes) seems to be the right solutionâŚ
In my case, Iâm not trying to render a code block. The contents of the directive are actually being captured, encoded, passed to an API, then the API returns an SVG to be rendered in place of the original ASCII diagram. You can see a live example of this on my website. All of the diagrams are rendered with a generic directive, similar to the one I posted above with the code fences. The figures are also using generic directives. The implementation looks like this:
::::figure
:::ditaa
```
(diagram)
```
:::
::figcaption[A description of the diagram rendered above.]
::::
You can also check out this Github issue that I created on the remark-directive
repository about enabling this option where I go into some more technical details of how Iâd like to see it work.
Now, I realize that Iâm talking very specifically about my personal desires for what generic directives could be, but I feel like itâs a really good example of the types of opportunities that generic directives can enable.
That doesnât work well because of reference links and embedded HTML. It can also behave awkwardly in light of code blocks.
Example 1:
[a]: https://example
See [b].
::: foo
[b]: https://example
See [a].
:::
Example 2:
::: foo
<script>
/*
:::
*/
</script>
:::
Example 3:
::: foo
~~~ colons
:::
~~~
:::
Edit: Removed âcode spansâ from the list of potential problems, because it doesnât make much sense.
Using indented code blocks instead of fenced makes this syntax a bit less noisy. It might still be unintuitive to require a code block, but custom directives already presume some author knowledge.
::: ditaa
+---+
| A |
+-+-+
| +---+
+->+ B +
+---+
:::
The most likely issue with this is uninitiated authors editing an existing document and not understanding why the new diagram they added isnât displaying properly.
Another option is to copy what Pandoc does: Itâs quite established and I like its syntax. It uses class names for commands (and omits the prefixed dot outside curly braces):
[markdown]{.cmd key=val}
::: cmd {key=val}
markdown
:::
``` cmd {key=val}
text
```
<!--New syntax: attributes after a thematic break -->
--- cmd {key=val}
However, it may also make sense to keep the namespaces of commands and classes separate. That could be achieved as follows:
[markdown]{!cmd key=val}
::: !cmd {key=val}
markdown
:::
``` !cmd {key=val}
text
```
--- !cmd {key=val}
Example â figure captions:
::: !figure
![](some/image.jpg)
::: !figcaption
This is an image.
:::
:::
Example â index entries:
[]{!index key="true" md="`true`"}
`true` is a boolean value.
The exclamation mark syntax [content]{!cmd key=val}
looks good, and doing something thatâs already in use is a great idea.
How are key-value pairs separated? And is it possible to have keyless (i.e. numerical, ) values (e.g. I was working the other day on a Wikidata linking synax that in this scenario would look something like [D. Adams]{!wd Q42}
).
Oh, looking at the Pandoc docs, it looks like the attributes are space-separated and optionally quoted, I guess following the same rules as XML attributes. So it wouldnât make sense to have a keyless value; such a thing would be a valueless key (and permitted).