markdown: Proposal: a new general purpose Block extension
I haven’t solidified the proposal yet, but I am envisioning something like a fenced code block (except its not for code and would use different delimitators) which might support two different block types:
- Element Block: The user would define the HTML element (tag) and any attributes. This would be simpler to deal with (read, write and parse) that md_in_html as it avoids lots of HTML tags in your Markdown.
- Templated Block: The user would define the block ‘type’ and any attributes. So long as a template exists for the ‘type’, then the content is inserted into the template after being parsed as Markdown.
Therefore, if the user provided div
(for an element block), the content is parsed as Markdown and then wrapped in a div
element with any additional attributes being set on the div
. However, if the user provides a ‘type’ of admonition
, then the admonition
template is used. Presumably the template would expect a set of attributes (including the admonition type), a title and a body and insert those values into the HTML template. Other templates might accept other options.
This would also allow users to use the CSS provided by whichever CSS framework they are using. For example, the MkDocs default theme is using Bootstrap, which provides it own set of alerts. However, MkDocs doesn’t use them, but instead also provides CSS for Rst style admonitions because that is what the admonition extension expects. With a new block extension, a Bootstrap alert template could allow Bootstrap’s CSS to be used along with all of Bootstrap’s alert features (icons, dismissal, etc) removing the need for the MkDocs theme to also include the Rst based CSS.
A few additional things to note:
I would prefer to not add any new extensions to the core library. So I would expect this to be developed in a separate repo. However, I mention it here because it could effect how we proceed with #1174. Also, I would appreciate any feedback on the idea and/or input on a possible syntax proposal.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 84 (22 by maintainers)
@matchavez I think that syntax has zero ideological overlap with this particular thread. The GitHub syntax lets you achieve only these 5 exact blocks with absolutely zero leeway for extensibility (any deviation makes the syntax unrecognized by GitHub).
That said, I will advertise a thread where there is interest in making this work despite these limitations, not as a general syntax
Well, it may be time to update all of this.
GitHub has implemented their Admonition style, and it’s a Blockquote fallback.
Maybe implement the new style for specific admonitions (presumed), and then leave the
!!!
for an unstructured block as suggested, that continues to render as it does.>[!NOTE]
!!!
- follow the Material for MkDocs style for custom blocks???
- use as a “Spoiler” indicator, with the same unstructured block hidden by default.Here’s the current supported array:
@squidfunk I am purposely not focusing on the API right now as I want to nail down syntax first. If you really want to jump into the API, I think the Admonition block is a good template to get started. I would just ignore the
on_register
andon_parse
events as those are used to handle dynamic type generation for the block and are more advanced.At the very least you need an
on_create
event.NAME
must be a unique name to avoid conflicts with other registered blocks.ARGUMENTS
is used to specify what some may think of as the “title” input:/// block | argument
.OPTIONS
specifies block-specific inputs that can be given via a YAML block in the header. Regardless of the block, theattributes
option is always special and allows adding extra classes, ID, or whatever else is desired, so that option name is kind of reserved.CONFIG
is used to specify any global config settings for the block. These are done when registering your block and only then.If you have general feedback, please provide it at the alpha’s discussion topic here: https://github.com/facelessuser/pymdown-extensions/discussions/1868
If you have additional questions related to the API, please create a separate discussion thread on the repo. I’m happy to answer any additional questions, but since API is not the primary focus of the first alpha, and the API could change some before I document the API for a future alpha, that is not my focus, and I’d like to keep the main focus, at least in the alpha release topic, on nailing down the syntax.
I’ll go a little further to say, the intent is not to invalidate work others have done, and if an existing generic block satisfies your needs, I’d say that maybe what we are doing here won’t make a difference to you.
With that said, I’ve tried to put a lot of thought into the generic blocks we are currently implementing.
on_end
event for that. Does your generic block need to parse the content but then run a treeproessor on it later, maybe after some other extension? You should be able to use theon_register
event to add a tree processor in conjunction.While there are other solutions that may be sufficient for others, I am hoping that some will find what we are trying to do here a welcome addition. I’m trying to involve users of Python Markdown to give their input to try and make this a useful solution moving forward. I am hoping to have a pre-release soon to start allowing people to try it out. It has definitely been more involved to write this extension than what I initial thought, so work near the end has slowed as other obligations in life have crept in, but I think we are very soon reaching an alpha release. Hopefully, with feedback, we can polish any rough edges and get something useful out.
Just in case you don’t know it, there is an extension, Custom Blocks, quite similar to what you are proposing here but in my opinion (skewed as i am the author) it uses a more simpler syntax (no need for a closing tag, no need for a separator between the block name and the parameters… It also has a more flexible mapping of parameters to python function parameters which makes defining custom blocks quite easy.
By default it generates:
That is:
But you can customize it with a simple python function like this one:
To generate:
I am still moving forward with this, but I’m finding that I like the requirement less and less which requires the content block to have a new line before it.
I really just want to make compact blocks at times:
I think compact blocks are a bit more readable when compact (when possible) especially when you have a number of blocks or nested blocks.
If people feel very strongly with hate for YAML fences (
---
), maybe I can add a general option to make them optional (or not optional depending on what the default is).I didn’t think it would bother me as much as it does, but as time has gone on, I think it really does bother me 😅.
I think we might move towards this syntax:
I wanted to use
:::
as it aligned (at least in spirit) to what Myst and Pandoc use for generic blocks. With that said, there are some MkDocs and Python Markdown extensions in the wild using:::
for other purposes.The reality is there is limited, reasonable syntax available for Markdown, which is why a general purpose block extension is a good idea moving forward – inventing non-conflicting new syntax becomes more of a chore as time goes on. I’m okay with conflicting with existing plugins in order to expose a, hopefully, more sane approach to generic-blocks.
///
may also conflict with something out in the wild, but it will probably conflict with less, at least that is my thinking.Ideally, moving forward, extensions will try to adopt this more generic approach for generic blocks and help consolidate some of this syntax (this might not actually happen, but we can dream), but it may be nicer to reduce the impact by choosing a syntax at least less conflicting.
That is my current leaning.
Okay,
blocks
actually aligns with what I was already thinking. I’ll probably just do that.Yeah, nesting under
attributes
would be a requirement if exposing any attribute on any block.Some blocks could potentially have options to target specific elements with specific attributes (assuming some complex HTML structure), but
attributes
would assume the outer HTML element under evaluation.Interesting. Over
:
and|
, I think I prefer|
as well. I had not considered doubling them though, so::
is interesting as well. I’m not sure why I don’t like||
as much, but I may need to play with it. This really does help, and I think at this point I’m going to forgo quotes.At this point, I think I’m ready to code up the final bits as whatever tokens we chose, they will not affect the parsing logic. I can easily swap out
///
,:::
, and separators without upending any of the core logic, so I can figure out the final tokens we use after finalizing core logic.As far as
---
is concerned, if we do end up requiring content having 1 blank line before it, we could make---
optional. For YAML purists who like to use it, or for people who just want to remind people they are working in YAML, they could use it. For others, they could omit it.Yeah, the idea of templates wasn’t really laid out, and I do realize what I have isn’t a template. The naming is quite wrong in that regard. I haven’t even thought about true templates yet. I’m still working through getting the blocks to not get messed up when passing through lists. There are always list corner cases…always 😢 .
I feel there is an advantage to more advanced, non-template type variants, but I can also see the attraction for actual tempaltes.
As a user, I think this is a wonderful idea! I’m currently migrating a mediawiki site to git/markdown. For admonitions, the pandoc mediawiki→markdown converter produced
::: warning
, which is the same that markdown-it, docusaurus and some others use. It’ll take time to update hundreds of wiki pages to!!! warning
and indented content that mkdocs uses. Also, if I ever need to switch away from mkdocs in the future, I’ll have to convert the content once more. The::: class
(and the::: tag
) ideas are so powerful, that will probably make!!! admonitions
obsolete if they’re implemented! I hope we can see this in production soon! 😃