wooorm / markdown-rs

CommonMark compliant markdown parser in Rust with ASTs and extensions
https://docs.rs/markdown/1.0.0-alpha.20/markdown/
MIT License
905 stars 50 forks source link

Add support for directives #57

Open tonyalaribe opened 1 year ago

tonyalaribe commented 1 year ago

I have a usecase where we need to support the commonmark directives (https://github.com/remarkjs/remark-directive) and wondering if there are plans to support this, or if it's something I could contribute to.

For my usecase, markdown-rs is used as a library and it's fine to write rust code to define the directives directly, or as a fallback, even just render the directives as a web component format <directive-name attr=attrVal> and then the user can supply the webcomponent implementations themselves.

wooorm commented 1 year ago

Hi Anthony!

It’s definitely a welcome addition. It’s in the JS version of this. And I think they’re very important to have for markdown!

The reason I haven’t added support for them yet, is that I wasn’t really sure how the output should look like in HTML, or how the API would look for users to handle them and turn them to HTML.

There are some ways around this:

a) not emit them to HTML at all yet, then folks will have to use the AST (this doesn’t solve your use case but lets us at least work on the parsing side first) b) Emit custom elements like your <directive-name attr=attrVal> proposal c) Figure out some way to add support for users to handle them, like this: https://github.com/micromark/micromark-extension-directive#handle

I don’t have the time to work on this the in the foreseeable future, but I’d be very excited for this feature and can help review!

slorber commented 1 year ago

Also super interested to have this for Docusaurus 😄 Since we are using directives for admonitions now, this would give us the opportunity to use faster Rust MDX compilation in some optimistic cases where users do not provide fancy remark plugins.

Or at least faster Markdown parsing to AST. I guess there are not a lot of remark plugins that use custom extensions.

tonyalaribe commented 1 year ago

I'm slowly getting a hang of how the state machine works and compiling the events into the AST. So we're slowly getting close to a rough PR.

But I have a question about supporting attributes: https://mb21.github.io/stmd/spec.html#horizontal-rules-1

directives heavily rely on attributes, but attributes as feature extends beyond directives and there's also spec proposals for attributes on most other elements.

Would it make sense to also support attributes at some point in a general way that works for any other markdown elements? If yes, then I would leave attributes support out of this initial directives PR, and then in a later PR figure out how we can support directives for any elements (including directives).

wooorm commented 1 year ago

Cool!

I particularly recommend keeping the JS version next to the Rust version. Such as: https://github.com/micromark/micromark-extension-mdx-jsx/blob/a7c51df47d975069e000f7429dde992f57da3eb7/dev/lib/factory-tag.js#L102 compared to https://github.com/wooorm/markdown-rs/blob/7340a46b5c7fdb05796377d8c73c4843b6ae2876/src/construct/partial_mdx_jsx.rs#L177. They work a bit differently, but JS is easier to understand for me, and then you can directly port micromark-extension-directive to Rust: https://github.com/micromark/micromark-extension-directive/blob/5facf31692d581650ddf349852421c351af243d8/dev/lib/directive-leaf.js#L32

As far as I know “attributes” as an extension does not have the exact same style of attributes as the ones in directives? But, both are not really standardized.

I like directives more than attributes: I think they solve a bigger issue than attributes do. And with directives, most of the need for attributes also disappears.

I think I’d need more convincing to allow arbitrary attributes on everything, so I’d prefer sticking with directives for now, and leave that for a later discussion.

As for getting code in earlier: sure, I’m open to a PR that doesn’t yet support attributes on directives!

tommy-gilligan commented 1 year ago

This sounds like a great feature! Curious how it is going? Jonesing to have a crack myself.

slorber commented 11 months ago

Apparently ByteDance devs have implemented it in a fork: https://github.com/web-infra-dev/mdx-rs/blob/main/crates/plugin_container/src/lib.rs https://twitter.com/sanyuan0704/status/1714618540924489949