Skip to content
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

gracefully handle footnoteReference and footnoteDefinition nodes in mdx field #990

Open
stefanprobst opened this issue Mar 7, 2024 · 4 comments

Comments

@stefanprobst
Copy link
Contributor

currently, when an mdx document has a footnote, the keystatic mdx field errors with the following error message:

Field validation failed: content: Unexpected error: Error: Unhandled type footnoteReference Unhandled type footnoteDefinition

Screenshot_20240307_190715

mdx document used:

---
title: test
---

Some text.[^1]

[^1]: Footnote content.
@stefanprobst
Copy link
Contributor Author

in case it's useful to someone, i am currently replacing native markdown footnotes with a custom mark <Footnote> component, and using a remark plugin to split that into footnote reference and definition:

/** @typedef {import("mdast-util-mdx").MdxJsxAttribute} MdxJsxAttribute */
/** @typedef {import("mdast-util-mdx").MdxJsxTextElement} MdxJsxTextElement */
/** @typedef {import("mdast-util-mdx").MdxJsxFlowElement} MdxJsxFlowElement */

import { SKIP, visit } from "unist-util-visit";

export function withMdxFootnotes() {
  return function transformer(/** @type {import("mdast").Root} */ tree) {
    let count = 1;

    /** @type {MdxJsxTextElement[]} */
    const footnotes = [];

    visit(tree, "mdxJsxTextElement", (node, index, parent) => {
      if (node.name === "Footnote") {
        /** @type {MdxJsxAttribute} */
        const countAttribute = {
          type: "mdxJsxAttribute",
          name: "count",
          value: String(count),
        };

        /** @type {MdxJsxTextElement} */
        const reference = {
          type: "mdxJsxTextElement",
          name: "FootnoteReference",
          attributes: [countAttribute],
          children: [],
        };

        /** @type {MdxJsxTextElement} */
        const content = {
          type: "mdxJsxTextElement",
          name: "FootnoteContent",
          attributes: [countAttribute],
          children: node.children,
        };

        // @ts-expect-error Parent node exists.
        parent.children.splice(index, 1, reference);
        footnotes.push(content);

        count++;
      }

      return SKIP;
    });

    if (footnotes.length > 0) {
      /** @type {MdxJsxFlowElement} */
      const section = {
        type: "mdxJsxFlowElement",
        name: "FootnotesSection",
        attributes: [],
        // @ts-expect-error Should be fine to set `MdxJsxTextElement` children.
        children: footnotes,
      };

      tree.children.push(section);
    }
  };
}

@adamlewkowicz
Copy link

adamlewkowicz commented May 9, 2024

@stefanprobst How did you manage to fix this? How to use this code snippet exactly?
I'm struggling with the same issue.

@stefanprobst
Copy link
Contributor Author

@adamlewkowicz i put together an example here: https://github.com/stefanprobst/keystatic-footnotes

in an .mdx file it will look like this:

This text has a footnote.<Footnote>This is the footnote text.</Footnote> This is the rest of the paragraph.

in the keystatic ui, it will look like this:

Screenshot_20240511_080409

@adamlewkowicz
Copy link

@stefanprobst Thanks a lot for the example! I've used this setup with remote-mdx and it's working 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants