Thinkmill / keystatic

First class CMS experience, TypeScript API, Markdown & YAML/JSON based, no DB
https://keystatic.com
MIT License
1.25k stars 80 forks source link

MDX Field serialises latex expression #1319

Open shmmh opened 1 month ago

shmmh commented 1 month ago

So the Mdx content editor serialises latex expressions. I guess it serialises all the JS expressions. image

image

Acorn parse error is thrown when I modify the file locally. image

The issue might be with Prosemirror and/or with Mdx. Without remark-math plugin, even my vscode editor throws an acron parse error.

I found Prosemirror Math extension.

ethan-ou commented 1 month ago

I had the same problem and I found it was due to acorn escaping curly braces {} to avoid text being converted into MDX expressions. In MDX you can add variables to your markdown as soon as you add the braces:

export const year = 2023
In {year}, the snowfall was above average.

Acorn escapes these but the unintended consequence is that curly braces in math equations no longer work.

The way I found around this is to create a remark plugin to remove the escapes before they're rendered. Here's the plugin:

// You'll need to install unist-util-visit, mdast and mdast-util-math as dependencies to use this plugin.
import { visit } from "unist-util-visit";
import type { Root } from "mdast";
import type { InlineMath } from "mdast-util-math";

const replaceEscapes = (text: string) => text.replaceAll("\\_", "_").replaceAll("\\{", "{");

export default function remarkMathRemoveEscapes() {
  return (tree: Root) => {
    visit(tree, "inlineMath", (node: InlineMath) => {
      node.value = replaceEscapes(node.value);
      if (node.data && node.data.hChildren) {
        const children = [];
        for (const child of node.data.hChildren) {
          child.value = replaceEscapes(child.value);
          children.push(child);
        }

        node.data.hChildren = children;
      }
    });
  };
}

And here's how I'm using it in an Astro project:

import { defineConfig } from "astro/config";
import remarkMathRemoveEscapes from "./extensions/remark-math-remove-escapes/src";
import remarkMath from "remark-math";
import rehypeKatex from "rehype-katex";
import "katex/dist/contrib/mhchem.mjs";

// https://astro.build/config
export default defineConfig({
// more config here...
  markdown: {
    remarkPlugins: [[remarkMath, { singleDollarTextMath: false }], remarkMathRemoveEscapes],
    rehypePlugins: [rehypeKatex],
  },
});

The result is you can use Keystatic to write Latex and it'll render correctly on your site. But you'll need to escape any curly braces to write Latex in markdown.