Generic directives/plugins syntax

Yeah, I wouldn’t be really opposed to @name[]() instead of @name[](){} if that should emerge as the consensus for a more limited syntax.

That being said, I guess the appeal of {} to me is that I would like it to become a no-brainer for a user to know what to put in there because it’s the same everywhere. The distinction between values () and key-value pairs {} is also somewhat inspired by ConTeXt (see 1.3 Commands). (btw: ConTeXt, as opposed to LaTeX, also has a notion of a class, so .myClass isn’t entirely HTML-centric.)

Finally, {} is probably also easier to implement in parsers. But yes, as you proposed, I guess we could also have all the attributes in the (), as in

@video[title](filename.mp4 "autoplay=1")

![altText](myImage.png "title" .myClass width=40 height=50)

### myHeader ### #myId

It works okay for everything but headers (although it still works I guess). But some implementations like Pandoc already make use of {} for attributes in some places. And my proposed span syntax [text]{.class} can’t be converted to []() since that is already taken for links.

1 Like

The issue with that is that some existing parsers will process everything in () as a url.

Could something like this be suitable? Where we have a semi json { and } field (but made easier by not needing " for setting names. And just use that for directives

link style directives:

For standard links:

[ Textual Information ]( hypertext url ){ semi-json style settings}

Which can be omitted most of the time if needed:
    [ Textual Information ]( hypertext url )

For picture or video links, where it is recognized by `.png` or `.mp4` etc... :
    ![ Textual Information ]( hypertext url ){ semi-json style settings}

To which we can either go classic semi-json or html inspired:

![altText](myImage.png){ title="title", class=.myClass, width=40, height=50 }
![altText](myImage.png){ "title" .myClass width=40 height=50}

For shorthand picture or video links

![ Textual Information ]( Image url ){ semi-json style settings}
!video[ Textual Information ]( video url ){ semi-json style settings}
!audio[ Textual Information ]( audio url ){ semi-json style settings}
!base64[ Textual Information ]( embedded binary file ){ semi-json style settings}

The benefit to this approach is that we keep the settings or the ‘markup’ separate from the actual content of ![]()

block style directives

So for directives + semi-json semi-html. Sticking to the style of code fencing. We could use this.

@@@latex [title]{fontsize=14}
\frac{1,2} = 0.5

Btw, why @@@@, and not $$$$$ or even ~~~~ ( Maybe !!!! since ![](){} but looks rather ugly)

~~~~~latex [title] {fontsize=14}
\frac{1,2} = 0.5

$$$$$latex [title] {fontsize=14}
\frac{1,2} = 0.5

{} [] and () are all optional.

e.g. using url for up to date csv input?

@@@graphGen [My Graph Generator] ( {graphsize=10}


When choosing directives, please try to keep to the tradition of

  • [] is only for text title/descriptor
  • () is only for url.
  • {} is only for options & markups

As per ![](){} tradition.

EDIT: Modified example to better match how fenced code block is treated according to mb21 . Instead of @@.latex, its @@latex

1 Like

@mofosyne While I like your idea of having only a URL/identifier in the (), actually Common Mark defines images already as ![foo](/url "title")and that’s kind of why I worte that the part between () “is a string to be interpreted by the custom directive that generally is not going to be directly visible”. But we could of course do it “better” for directives than what happened to the image syntax, but then again that’s kind of restricting directives more than really necessary.

I think ![altText](myImage.png){.myClass width=40 height=50} is great and is in fact already proposed in the consistent attribute syntax thread. About the comma-separated variant: personally, I don’t like there being too many ways to write the same thing and think this is already “semi-json” enough.

About container block directives: for fenced code blocks, the standard currently says to use:


and not:


So I think that’s consistent with my proposal. I agree that the spacing probably should be allowed there as you suggested and that also the [] might be optional there.

Finally, the @ and @@@ is a rather arbitrary choice. But it should be some special character that is easily distinguishable from ! (to make it easy to see that it’s not an image) and $ is often already used to mark up mathematics.

As @mb21 mentioned, images as well as links allow a title to be declared in parenthesis.

That’s why I suspect users may get confused and try to write expressions like the following:

  • ![image](/url){title="My image"} instead of ![image](/url "My image")

Options can be in either () or {}, there is no rule or easy way to guess which option goes where (when you’re new to CommonMark) and you have to try by trial-and-error.

I’m all for a generic attribute syntax that is applicable everywhere so it’s easier to learn the language, however sadly we’re already stuck with the options-in-parenthesis due to backwards compatibility. The question that must be answered now is what’s easier for users to learn and continually use.

I don’t see how we can’t support both methods?
You could call options-in-parenthesis inside (/url "My image") as “shorthand” for {title="My image"}.

We need to encourage {} but recongize that in most use cases, people will only need to declare title, and thus contextually ![image](/url "My image") is enough.

Just make it so that internally the parser, automagically converts:

![image](/url "My image") --> ![image](/url){title="My image"}

tl:dr: Treat options-in-parenthesis as syntactic sugar of {} .


Since {} is already in use for attributes, I tend to favour it over () for options. Personally I find the title in ![altText](image.png "title") kind of unfortunate, but it’s way too late to change that. But when writing custom directives, the discussion here convinced me that we should discourage the use of multiple things in (). The question is whether we should actually disallow it. I just edited my first post above and changed (options) to (arg) to reflect this.

Depends on how much you hate programmers lol. Hmmm… should we actively disallow the use of multiple things in ()?

For ![]() media:

The answer is no, since people use it as shorthand ![image](/url "My image") (and that is a good thing). Heck in normal english language, we use shorthand all the time. Since we expect others to be able to derive the full meaning with a bit of context. Speed is of essence in life.

 !mediaType[description](url){#myId .myClass key=val key2="val 2"}
  • mediaType :~ (e.g. !youtube) Assumed to be image if left blank

For @[]() directives:

I think it depends. In some cases it may make sense to have syntactic sugar in []. But since it’s an extension directive, just pass anything in arg into a string to the extension, and let it deal with that issue. For consistency sake however {} should only hold key values pairs to be passed to the extension and CSS IDs and Class as you have illustrated already.

@name[content](arg){#myId .myClass key=val key2="val 2"}
  • name :~ name of extension to call
  • arg :~ Everything in arg is just passed directly to the extension as a single string. It is up to the extension if it wants to implement any shorthand notations.
  • {} :~ The parser will read #myId and .myClass for HTML attributes before passing everything in {} to the extension

The {#myId .myClass key=val key2="val 2"} comes from this discussion about keeping attributes syntax consistant. Since we are passing attributes and parameters, I’m using this as reference.

As someone who has written a few syntax extensions, I like this proposal.

In one of the comments, someone commented that parsers that don’t support this syntax will render these as ordinary links. In most of the cases above, that is actually the big advantage of this proposal, since they are effectively links, and rendering a link to them is a very appropriate fallback. We’re currently using a very similar syntax to this for code snippets, have a look at what the GitHub markdown renderer does with them:

It renders them as links to the actual file, which is a perfect fallback, and is a big reason why we chose that syntax.

1 Like

Sweet, so with your example, if the extension was called “setContent-Type” would be:


Example mockups for inspiration. How would a python extension to markdown look like? Obviously the actual python extension might treat arg and parameters bit differently.

Scientific document with inline runnable snippets of python.

@@@python[ Test Prog ]( SciPy, NumPy ){ codePreview=yes }
    print("Hello World")
    # More python code for scientist here

So is there a consensus forming here? Any Objections?

Not quiet, in my example, the extension would be called “snip”, and would look like this:


snip is the extension (code snipped from external file), the bit in the [] is the fragment of code snipped from the file, so in the file, you’ll see stuff like this:

    "A scala result" should {
      "default result Content-Type" in {
        val textResult = Ok("Hello World!")
        testContentType(textResult, "text/plain")

And then what gets rendered is the val textResult = ....

Though, we might also consider something like this:

@snip[Some label](code/ScalaResults.scala){#content-type_text}

Now the bit in the [] might be an optional title rendered above the code snippet. This syntax I think would be more in line with the spirit of the description of each element in this proposal.

Of course, we’re talking about extensions to the markdown syntax here that are never intended to be part of markdown proper, all of this is just a guide, it’s not prescriptive, there’s no right or wrong way in how to use it.

1 Like

Ah okay. Well aside from the specificity of how your “snip” extension works jroper. Is there a consensus for general extension syntax ?

@name[content](arg){#myId .myClass key=val key2="val 2"}

@@@name[content](arg){#myId .myClass key=val key2="val 2"}
      \*Content to pass to extension*\

If there are going to be extensions using a JSON-style settings hash, I suggest making the list of attributes look more like JSON/YAML rather than HTML attributes. For example:

!audio[ title ]( url ){ size: 10, duration: 10, cycle: forever }

is more readable than:

!audio[ title ]( url ){ size=10 duration=10 cycle=forever }

The lack of whitespace between the key/value pairs in the latter example makes the syntax feel squashed.

1 Like

Note also that MarkdownExtra uses curly braces for attributes as well. It has been around a long time (the curly braces since at least the 1.0 of PHP MarkdownExtra, dated 5 September 2005! FWIW…).

1 Like

Yup and is our prime inspiration in this thread. Pandoc as always is ahead of the pack. One may say we are pulling up markdown. I say we are catching up to Pandoc.

Any further objection or discussion on syntax? If not, then this can be done as a feature request in.

Most people writing markdown are more familiar with HTML I would think. Plus CommonMark accepts HTML tags, so best to minimise mental switching cost by keeping the syntax somewhat same.

Also {} is not encouraged to be used liberally, it should only really be used when there is no other alternatives. So keeping it short, quick and dirty, and compact will minimize it’s visual presence in the page.

As someone who works a lot with JSON, I can confirm the first version feels more readable to me – I however doubt that this is a generic rule applicable to everyone. I don’t believe that a key-value pair using colons : is generally more readable than one using equality signs =.

I also don’t believe we should use colons just because JSON also happens to use curly braces.

On the other side, I wouldn’t see any harm in allowing either colons : or equality signs = when specifying attributes, or allowing optional commas ,. The values on the right-hand side of a key-value pair shouldn’t contain either symbol and the additional overhead for parsers is minimal.

It makes the syntax more complicated to learn if there are 2 alternate ways to specify attributes, but also more flexible. Either solution has its merits.

Should similarity to HTML be the goal here? Markdown was designed to be easy to read, in direct contrast to HTML which isn’t particular easy for a non-developer to understand. The use of HTML seems like a fallback in the original spec. For other parts of the Markdown syntax, the syntax choice appears to be in opposition to HTML.

It’s worth asking why colons were chosen for some languages instead of equals signs. In particular YAML. As with Markdown, YAML was designed to be human readable first and foremost. Have a look at part of this example YAML document from Wikipedia:

receipt:     Oz-Ware Purchase Invoice
date:        2012-08-06
    given:   Dorothy
    family:  Gale

The syntax is quite readable to a human, spaced out with key/value pairs seperated as you might expect a list to be written down. Also, the colon is used in English to express “this is what I mean” whereas an equals sign is typically used to express something mathematical. E.g. John Gruber created a language: Markdown.

That sounds reasonable. Good point about YAML and the usual meaning of : vs =. Still think we can do without commas (fine if commas is optional).

What do you think about this:

!audio[ title ]( url ){ size:10 duration:10 cycle:forever }

In YAML’s (JSON like) stream context, the advantage of using comma as item separators is that it allows omission of quotation marks in many cases, even when a value contains spaces. But YAML would require a space after the colons, unless the values were quoted.

So a more YAML like attribute notation might be:

{ title: some audio ambiance, cycle: forever }

It’s not the computer parser that concerns me, but the human parser. Whenever you add a second way to say something, readers are going to wonder what the distinction means. Remember, this is already a slightly esoteric region for non-programmers and not all Markdown flavors support it. So there will be some situations where folks will see a bit of line noise{id: “line-noise”, title = ‘$#@^(’ .extreme_example_to_prove_a_point} in their documents. If sometimes authors use = and other times : with optional commas and quotations and so on, it will make the problem exponentially worse.

Note: I’m a Perl programmer, so I’m used to reading cartoon character swearing. As a programmer, I like the flexibility. As someone who needs to explain Markdown to non-technical people sometimes, I dread it. So let’s pick one syntax and stick to it.

Since Markdown has close ties to HTML, we should prefer HTML attribute syntax.