File size: 1,862 Bytes
5a29263
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import katex from 'katex';

// Adapted from https://github.com/SchneeHertz/markdown-it-katex-gpt
// MIT license

const defaultOptions = {
  delimiters: [
    { left: '\\[', right: '\\]', display: true },
    { left: '\\(', right: '\\)', display: false },
  ],
};

export function renderLatexHTML(content, display = false) {
  return katex.renderToString(content, {
    throwOnError: false,
    output: 'mathml',
    displayMode: display,
  });
}

function escapedBracketRule(options) {
  return (state, silent) => {
    const max = state.posMax;
    const start = state.pos;

    for (const { left, right, display } of options.delimiters) {

      // Check if it starts with the left delimiter
      if (!state.src.slice(start).startsWith(left)) continue;

      // Skip the length of the left delimiter
      let pos = start + left.length;

      // Find the matching right delimiter
      while (pos < max) {
        if (state.src.slice(pos).startsWith(right)) {
          break;
        }
        pos++;
      }

      // No matching right delimiter found, skip to the next match
      if (pos >= max) continue;

      // If not in silent mode, convert LaTeX formula to MathML
      if (!silent) {
        const content = state.src.slice(start + left.length, pos);
        try {
          const renderedContent = renderLatexHTML(content, display);
          const token = state.push('html_inline', '', 0);
          token.content = renderedContent;
        } catch (e) {
          console.error(e);
        }
      }

      // Update position, skip the length of the right delimiter
      state.pos = pos + right.length;
      return true;
    }
  }
}

export default function (md, options = defaultOptions) {
  md.inline.ruler.after('text', 'escaped_bracket', escapedBracketRule(options));
}