-
Notifications
You must be signed in to change notification settings - Fork 274
Description
It's become a bit of a recurring pattern in my custom HTML renderer for pulldown-cmark that I more or less need to implement something like a tag stack... but I think blockquote tags is the first time I've so overtly needed to do so just to ensure proper HTML semantics are preserved when using the markup the way it was intended.
(Up to this point, it's been less overt stuff, like the need to synthesize a <tbody></tbody> pair if Tag::TableHead/TagEnd::TableHead are encountered.)
With the brand new blockquote tags option, I need to emit </blockquote> if the argument was None and something else (in my case, </aside>) if the argument was Some.
(Because these sorts of tagged blockquotes aren't really blockquotes, semantically... they're asides. They're just piggybacking on the blockquote markup as a generic "Markdown-semantic'd subdocument" syntax (i.e. <div> but for Markdown), in the same way that various use-cases will piggy-back on the fenced code block syntax as a generic "Raw/literal subdocument" syntax (i.e. <pre> plus CDATA)... now all we need is a generic "Markdown-semantic'd inline with arbitrary attributes" (i.e. <span>, but for Markdown) and we can finally match reStructuredText's extensibility.)
Specifically, here's the state of my TagEnd matches, with ones imposed by the interaction between pulldown-cmark itself and HTML semantics in bold:
TagEnd::Blockquotehas the aforementioned requirement to store which kind it was from theTagmatchTagEnd::CodeBlockrequires state tracking so I can implement things like```svgbobwhich aren't rendered with</code></pre>endings.TagEnd::Headingonly has a second line because of ToC autogenerationTagEnd::ItemandTagEnd::Paragraphare only complicated because I want to support turning<li></li>into<li><details><summary>para 1</summary> para 2 +</details></li>TagEnd::Tableis complicated because of the need to keep track of whetherTableHeadwas seen and synthesize<tbody></tbody>tags which don't have a representation in the pulldown-cmark token stream. (Heck, I still have a TODO for deferring the emission of<tbody>because the GFM spec says you shouldn't emit empty<tbody></tbody>elements.)
Everything else that I've implemented so far has just been a simple TagEnd::TableRow => output.push_str("</tr>"),-style line, or something like TagEnd::Image => (), // <img /> is self-closing and the only two things I haven't implemented yet are alignments for table columns and the metadata block extension that I'd forgotten about because I'm not sure if I will.
To me, it seems like a bad design and a footgun for things like ENABLE_GFM and TagEnd::Table to require that the user implement even minimal state tracking, just to be able to generate compliant HTML, when nothing else has.