Skip to content

MDXv2 broken with remark-heading-id #1953

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
4 tasks done
Eyas opened this issue Feb 26, 2022 · 9 comments
Closed
4 tasks done

MDXv2 broken with remark-heading-id #1953

Eyas opened this issue Feb 26, 2022 · 9 comments
Labels
👀 no/external This makes more sense somewhere else 👎 phase/no Post cannot or will not be acted on

Comments

@Eyas
Copy link

Eyas commented Feb 26, 2022

Initial checklist

Affected packages and versions

2.0.0

Link to runnable example

No response

Steps to reproduce

  • Install & import remark-heading-id
  • in MDX remarkPlugins, add remark-heading-id
  • Try to parse MDX: ## foo {#heading}

Expected behavior

The plugin handles the {#...} extended markup syntax, and MDX parses the document normally

Actual behavior

Get error: Could not parse expression with acorn: Unexpected character '#'

It makes sense that MDX thinks that {...} syntax is inline JS, but I would have thought plugins can be used to support heading ID Markdown extended syntax.

Runtime

Node v16

Package manager

npm v8

OS

Windows

Build and bundle tools

No response

@ChristianMurphy ChristianMurphy added the 👀 no/external This makes more sense somewhere else label Feb 26, 2022
@ChristianMurphy
Copy link
Member

ChristianMurphy commented Feb 26, 2022

https://github.com/imcuttle/remark-heading-id hasn't been updated in several years, and doesn't support the latest version of remark/micromark (imcuttle/remark-heading-id#1) which by extension means it doesn't work with the latest version of mdx.
This can be resolved by opening a PR to remark-heading-id upgrading it to support the new and improved micromark parser.

@ChristianMurphy ChristianMurphy added the 👎 phase/no Post cannot or will not be acted on label Feb 26, 2022
@Eyas
Copy link
Author

Eyas commented Feb 27, 2022

Hm. I have a local version of remark-heading-id that uses "unist-util-visit": "^4.1.0" instead (which should use micromark afaict?) and it doesn't seem to work still. Am I missing something?

@ChristianMurphy
Copy link
Member

There's a deeper upgrade needed to make it work with MDX.
The current approach, using unist-util-visit works on the AST, after the document has already parsed, which means JSX parsing will always take precedence and cause an issue before the plugin can do anything.
If you want to add a new syntax feature, it needs to be implemented as a part of the parser.
See https://github.com/micromark/micromark#extending-markdown and https://github.com/micromark/micromark#creating-a-micromark-extension for more information.

@Eyas
Copy link
Author

Eyas commented Feb 27, 2022

Thanks, that helps! One more question: I'm looking at @mdx-js/mdx's CompileOptions -- where would a micromark syntax extension be registered? I assume it's not a regular remark Plugin in this case, right?

@ChristianMurphy
Copy link
Member

It would be registered as a plugin, similar to how MDX itself registers itself and extends remark and micromark

import {mdxjs} from 'micromark-extension-mdxjs'
import {mdxFromMarkdown, mdxToMarkdown} from 'mdast-util-mdx'
/**
* Plugin to support MDX (import/exports: `export {x} from 'y'`; expressions:
* `{1 + 1}`; and JSX: `<Video id={123} />`).
*
* @type {import('unified').Plugin<[Options?]|Array<void>, Root>}
*/
export default function remarkMdx(options = {}) {
const data = this.data()
add('micromarkExtensions', mdxjs(options))
add('fromMarkdownExtensions', mdxFromMarkdown())
add('toMarkdownExtensions', mdxToMarkdown(options))
/**
* @param {string} field
* @param {unknown} value
*/
function add(field, value) {
const list = /** @type {Array<unknown>} */ (
// Other extensions
/* c8 ignore next 2 */
data[field] ? data[field] : (data[field] = [])
)
list.push(value)
}
}

@Eyas
Copy link
Author

Eyas commented Mar 7, 2022

Thanks for all the pointers! ended up making a separate package: remark-custom-heading-id. The micromark code is substantially different than the unist-util-visit-based approach, and the old extension is still good-enough for non-MDX cases.

@rikusen0335
Copy link

rikusen0335 commented Nov 29, 2022

I'd say thank you so much @Eyas that repo helped me a lot.

@Danii2020
Copy link

Hello, hope you can still help me, I want to use the remark-custom-heading-id to parse custom heading IDs, I'm using the mdxToMarkdown to allow MDX expressions but that function doesn't allow me to use the custom heading id syntax {#custom-id}. I'm using the following function to convert to MDX:

function mdxStringify(this: Processor) {
  const compiler = (tree: Node): string => {
    const markdown = toMarkdown(tree, {
      extensions: [gfmToMarkdown(), mdxToMarkdown()],
      bullet: "-",
      emphasis: "_",
      fences: true,
      resourceLink: true,
    });
    return markdown;
  };

  Object.assign(this, { Compiler: compiler });
}

If I remove the mdxToMarkdown function it handles custom heading ids properly, but I need that function, so is there a way to add a the remark-custom-heading-id as a plugin in that function? Thanks in advance.

@ChristianMurphy
Copy link
Member

@Danii2020 welcome! 👋
You don't appear to be using MDX directly?
Also you asked about parsing, but shared your compiler code 🤔
And your question appears to be more related to https://github.com/Eyas/md-heading-id?

Some suggestions on how to proceed:

@mdx-js mdx-js locked as resolved and limited conversation to collaborators Jul 14, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
👀 no/external This makes more sense somewhere else 👎 phase/no Post cannot or will not be acted on
Development

No branches or pull requests

4 participants