If you manage to come up and implement a sound design for an extension mechanism that does that while still keeping the weird corner cases of the existing constructs undisturbed, be my guest… Reading the spec discussion forum and a few CommonMark implementations it seems no one has a good design for that. Most implementations seem to have a fixed built-in set of (potentially individually) activable (and incompatible) extensions.
I have a few ideas where hooks could be added but once you start thinking about the delicate interplay with the other constructs, it gets a bit unwiedly and as far as I’m concerned I already spent way too much days of my life on this; I wish you had done it rather than flee to F# last year ;–)
Also personally I think some of the extensions veer away too much from markdown’s philosophy which aims at making the source publishable as is without looking like it’s been marked up. I’m mostly interested in using CommonMark with non-technical users and as a templating language (I’m suprised it’s not more used for that since it has raw HTML built in). So I’m not that much interested in those extensions that turn it more into a formal language.
That being said depending on what you want to do I really suggest you look into the label resolvers. Basically by parsing with nested_links:true
you can treat the link text syntax as a generalized span construct and the link label as your own DSL: the syntax is extremely lax and remember that in shortcut reference links both the text and the label coincide.
One example of this is in ocamlmark
: I simply reserve all the link labels that start with !
to stand for the {!…}
constructs of ocamldoc
, the resolver is here in which we recognize these construct and store them in the metadata. After that during the link node translation we translate to the right ocamldoc
construct when we hit these specially marked labels.
Another non public example I have is, without having to fiddle with Text.t
node parsing, support for abbreviation/superscript/subscript via a simple resolver, a mapper and a rendering extension. This syntax:
This is an unexpanded [PDF][!abbr] and square[2][^] or [CO][!abbr][2][_]
This is an inline expanded abbreviation: [PDF](!abbr "Portable Document Format")
This is an expanded abbreviation: [PDF]
[PDF]: !abbr "Portable Document Format"
Renders to
<p>This is an unexpanded <abbr>PDF</abbr> and square<sup>2</sup> or <abbr>CO</abbr><sub>2</sub></p>
<p>This is an inline expanded abbreviation: <abbr title="Portable Document Format">PDF</abbr></p>
<p>This is an expanded abbreviation: <abbr title="Portable Document Format">PDF</abbr></p>
Also note that it does compose you can have an abbr in a link a link in an abbr (thanks to the non-standard parse nested_links:true
). Adding support for [text][.class]
or [text][#id]
to classify an identify spans
would be equally simple.
Other ideas are syntax for data binding and formatting in the style of PHP templating frameworks via shortcut links like [page.date|yyyy-mm-dd]
, [page.author]
I think there’s a lot to tap into here, I hope the sample resolver can get you started on how to come up with this.