Skip to content

@docusuarus/mdx-loader frontmatter removal prevents rehype vfile having correct line numbers #3935

@vjpr

Description

@vjpr

module.exports = async function docusaurusMdxLoader(fileString) {
const callback = this.async();
const {data, content} = matter(fileString);
const reqOptions = getOptions(this) || {};
const options = {
...reqOptions,
remarkPlugins: [
...(reqOptions.beforeDefaultRemarkPlugins || []),
...DEFAULT_OPTIONS.remarkPlugins,
[
transformImage,
{staticDir: reqOptions.staticDir, filePath: this.resourcePath},
],
[
transformLinks,
{staticDir: reqOptions.staticDir, filePath: this.resourcePath},
],
...(reqOptions.remarkPlugins || []),
],
rehypePlugins: [
...(reqOptions.beforeDefaultRehypePlugins || []),
...DEFAULT_OPTIONS.rehypePlugins,
...(reqOptions.rehypePlugins || []),
],
filepath: this.resourcePath,
};
let result;
try {
result = await mdx(content, options);
} catch (err) {
return callback(err);
}

I am writing an plugin that adds the source file + line number to every heading element.

Below you can see that the frontmatter is being parsed and then only the remaining markdown content is passed onwards.

const {data, content} = matter(fileString);
// ...
result = await mdx(content, options);

This means that in a rehype plugin the vfile.history[].position.start.line will not be correct, it not take into account the frontmatter lines.

I think a better approach would be to parse the frontmatter using a remark plugin so to retain the original line numbers. Like this: https://www.npmjs.com/package/remark-extract-frontmatter

This should also be corrected on https://mdxjs.com/guides/custom-loader#custom-loader page I think.

Workaround

I could use grey matter to parse the gray matter again in my plugin but that means a lot of duplicate file read operations.

Remark

In remark plugins, I am just using the first comment to apply config.

<!-- {tocMaxDepth: 1, tocMaxDepth: 4} -->

# foo
const plugin = (options = {}) => {
  const name = options.name || 'toc';

  const transformer = (node) => {

    const firstComment = node.children.find(node => node.type === 'comment')
    let config = {}
    if (firstComment) {
      config = JSON.parse(firstComment.value)
    }

	// stuff...

  }

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugAn error in the Docusaurus core causing instability or issues with its executiondomain: markdownRelated to Markdown parsing or syntax

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions