1e5c31af7Sopenharmony_ciimport katex from '../katex.mjs';
2e5c31af7Sopenharmony_ci
3e5c31af7Sopenharmony_ci/* eslint no-constant-condition:0 */
4e5c31af7Sopenharmony_ciconst findEndOfMath = function findEndOfMath(delimiter, text, startIndex) {
5e5c31af7Sopenharmony_ci  // Adapted from
6e5c31af7Sopenharmony_ci  // https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
7e5c31af7Sopenharmony_ci  let index = startIndex;
8e5c31af7Sopenharmony_ci  let braceLevel = 0;
9e5c31af7Sopenharmony_ci  const delimLength = delimiter.length;
10e5c31af7Sopenharmony_ci
11e5c31af7Sopenharmony_ci  while (index < text.length) {
12e5c31af7Sopenharmony_ci    const character = text[index];
13e5c31af7Sopenharmony_ci
14e5c31af7Sopenharmony_ci    if (braceLevel <= 0 && text.slice(index, index + delimLength) === delimiter) {
15e5c31af7Sopenharmony_ci      return index;
16e5c31af7Sopenharmony_ci    } else if (character === "\\") {
17e5c31af7Sopenharmony_ci      index++;
18e5c31af7Sopenharmony_ci    } else if (character === "{") {
19e5c31af7Sopenharmony_ci      braceLevel++;
20e5c31af7Sopenharmony_ci    } else if (character === "}") {
21e5c31af7Sopenharmony_ci      braceLevel--;
22e5c31af7Sopenharmony_ci    }
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci    index++;
25e5c31af7Sopenharmony_ci  }
26e5c31af7Sopenharmony_ci
27e5c31af7Sopenharmony_ci  return -1;
28e5c31af7Sopenharmony_ci};
29e5c31af7Sopenharmony_ci
30e5c31af7Sopenharmony_ciconst splitAtDelimiters = function splitAtDelimiters(startData, leftDelim, rightDelim, display) {
31e5c31af7Sopenharmony_ci  const finalData = [];
32e5c31af7Sopenharmony_ci
33e5c31af7Sopenharmony_ci  for (let i = 0; i < startData.length; i++) {
34e5c31af7Sopenharmony_ci    if (startData[i].type === "text") {
35e5c31af7Sopenharmony_ci      const text = startData[i].data;
36e5c31af7Sopenharmony_ci      let lookingForLeft = true;
37e5c31af7Sopenharmony_ci      let currIndex = 0;
38e5c31af7Sopenharmony_ci      let nextIndex;
39e5c31af7Sopenharmony_ci      nextIndex = text.indexOf(leftDelim);
40e5c31af7Sopenharmony_ci
41e5c31af7Sopenharmony_ci      if (nextIndex !== -1) {
42e5c31af7Sopenharmony_ci        currIndex = nextIndex;
43e5c31af7Sopenharmony_ci        finalData.push({
44e5c31af7Sopenharmony_ci          type: "text",
45e5c31af7Sopenharmony_ci          data: text.slice(0, currIndex)
46e5c31af7Sopenharmony_ci        });
47e5c31af7Sopenharmony_ci        lookingForLeft = false;
48e5c31af7Sopenharmony_ci      }
49e5c31af7Sopenharmony_ci
50e5c31af7Sopenharmony_ci      while (true) {
51e5c31af7Sopenharmony_ci        if (lookingForLeft) {
52e5c31af7Sopenharmony_ci          nextIndex = text.indexOf(leftDelim, currIndex);
53e5c31af7Sopenharmony_ci
54e5c31af7Sopenharmony_ci          if (nextIndex === -1) {
55e5c31af7Sopenharmony_ci            break;
56e5c31af7Sopenharmony_ci          }
57e5c31af7Sopenharmony_ci
58e5c31af7Sopenharmony_ci          finalData.push({
59e5c31af7Sopenharmony_ci            type: "text",
60e5c31af7Sopenharmony_ci            data: text.slice(currIndex, nextIndex)
61e5c31af7Sopenharmony_ci          });
62e5c31af7Sopenharmony_ci          currIndex = nextIndex;
63e5c31af7Sopenharmony_ci        } else {
64e5c31af7Sopenharmony_ci          nextIndex = findEndOfMath(rightDelim, text, currIndex + leftDelim.length);
65e5c31af7Sopenharmony_ci
66e5c31af7Sopenharmony_ci          if (nextIndex === -1) {
67e5c31af7Sopenharmony_ci            break;
68e5c31af7Sopenharmony_ci          }
69e5c31af7Sopenharmony_ci
70e5c31af7Sopenharmony_ci          finalData.push({
71e5c31af7Sopenharmony_ci            type: "math",
72e5c31af7Sopenharmony_ci            data: text.slice(currIndex + leftDelim.length, nextIndex),
73e5c31af7Sopenharmony_ci            rawData: text.slice(currIndex, nextIndex + rightDelim.length),
74e5c31af7Sopenharmony_ci            display: display
75e5c31af7Sopenharmony_ci          });
76e5c31af7Sopenharmony_ci          currIndex = nextIndex + rightDelim.length;
77e5c31af7Sopenharmony_ci        }
78e5c31af7Sopenharmony_ci
79e5c31af7Sopenharmony_ci        lookingForLeft = !lookingForLeft;
80e5c31af7Sopenharmony_ci      }
81e5c31af7Sopenharmony_ci
82e5c31af7Sopenharmony_ci      finalData.push({
83e5c31af7Sopenharmony_ci        type: "text",
84e5c31af7Sopenharmony_ci        data: text.slice(currIndex)
85e5c31af7Sopenharmony_ci      });
86e5c31af7Sopenharmony_ci    } else {
87e5c31af7Sopenharmony_ci      finalData.push(startData[i]);
88e5c31af7Sopenharmony_ci    }
89e5c31af7Sopenharmony_ci  }
90e5c31af7Sopenharmony_ci
91e5c31af7Sopenharmony_ci  return finalData;
92e5c31af7Sopenharmony_ci};
93e5c31af7Sopenharmony_ci
94e5c31af7Sopenharmony_ci/* eslint no-console:0 */
95e5c31af7Sopenharmony_ci
96e5c31af7Sopenharmony_ciconst splitWithDelimiters = function splitWithDelimiters(text, delimiters) {
97e5c31af7Sopenharmony_ci  let data = [{
98e5c31af7Sopenharmony_ci    type: "text",
99e5c31af7Sopenharmony_ci    data: text
100e5c31af7Sopenharmony_ci  }];
101e5c31af7Sopenharmony_ci
102e5c31af7Sopenharmony_ci  for (let i = 0; i < delimiters.length; i++) {
103e5c31af7Sopenharmony_ci    const delimiter = delimiters[i];
104e5c31af7Sopenharmony_ci    data = splitAtDelimiters(data, delimiter.left, delimiter.right, delimiter.display || false);
105e5c31af7Sopenharmony_ci  }
106e5c31af7Sopenharmony_ci
107e5c31af7Sopenharmony_ci  return data;
108e5c31af7Sopenharmony_ci};
109e5c31af7Sopenharmony_ci/* Note: optionsCopy is mutated by this method. If it is ever exposed in the
110e5c31af7Sopenharmony_ci * API, we should copy it before mutating.
111e5c31af7Sopenharmony_ci */
112e5c31af7Sopenharmony_ci
113e5c31af7Sopenharmony_ci
114e5c31af7Sopenharmony_ciconst renderMathInText = function renderMathInText(text, optionsCopy) {
115e5c31af7Sopenharmony_ci  const data = splitWithDelimiters(text, optionsCopy.delimiters);
116e5c31af7Sopenharmony_ci  const fragment = document.createDocumentFragment();
117e5c31af7Sopenharmony_ci
118e5c31af7Sopenharmony_ci  for (let i = 0; i < data.length; i++) {
119e5c31af7Sopenharmony_ci    if (data[i].type === "text") {
120e5c31af7Sopenharmony_ci      fragment.appendChild(document.createTextNode(data[i].data));
121e5c31af7Sopenharmony_ci    } else {
122e5c31af7Sopenharmony_ci      const span = document.createElement("span");
123e5c31af7Sopenharmony_ci      let math = data[i].data; // Override any display mode defined in the settings with that
124e5c31af7Sopenharmony_ci      // defined by the text itself
125e5c31af7Sopenharmony_ci
126e5c31af7Sopenharmony_ci      optionsCopy.displayMode = data[i].display;
127e5c31af7Sopenharmony_ci
128e5c31af7Sopenharmony_ci      try {
129e5c31af7Sopenharmony_ci        if (optionsCopy.preProcess) {
130e5c31af7Sopenharmony_ci          math = optionsCopy.preProcess(math);
131e5c31af7Sopenharmony_ci        }
132e5c31af7Sopenharmony_ci
133e5c31af7Sopenharmony_ci        katex.render(math, span, optionsCopy);
134e5c31af7Sopenharmony_ci      } catch (e) {
135e5c31af7Sopenharmony_ci        if (!(e instanceof katex.ParseError)) {
136e5c31af7Sopenharmony_ci          throw e;
137e5c31af7Sopenharmony_ci        }
138e5c31af7Sopenharmony_ci
139e5c31af7Sopenharmony_ci        optionsCopy.errorCallback("KaTeX auto-render: Failed to parse `" + data[i].data + "` with ", e);
140e5c31af7Sopenharmony_ci        fragment.appendChild(document.createTextNode(data[i].rawData));
141e5c31af7Sopenharmony_ci        continue;
142e5c31af7Sopenharmony_ci      }
143e5c31af7Sopenharmony_ci
144e5c31af7Sopenharmony_ci      fragment.appendChild(span);
145e5c31af7Sopenharmony_ci    }
146e5c31af7Sopenharmony_ci  }
147e5c31af7Sopenharmony_ci
148e5c31af7Sopenharmony_ci  return fragment;
149e5c31af7Sopenharmony_ci};
150e5c31af7Sopenharmony_ci
151e5c31af7Sopenharmony_ciconst renderElem = function renderElem(elem, optionsCopy) {
152e5c31af7Sopenharmony_ci  for (let i = 0; i < elem.childNodes.length; i++) {
153e5c31af7Sopenharmony_ci    const childNode = elem.childNodes[i];
154e5c31af7Sopenharmony_ci
155e5c31af7Sopenharmony_ci    if (childNode.nodeType === 3) {
156e5c31af7Sopenharmony_ci      // Text node
157e5c31af7Sopenharmony_ci      const frag = renderMathInText(childNode.textContent, optionsCopy);
158e5c31af7Sopenharmony_ci      i += frag.childNodes.length - 1;
159e5c31af7Sopenharmony_ci      elem.replaceChild(frag, childNode);
160e5c31af7Sopenharmony_ci    } else if (childNode.nodeType === 1) {
161e5c31af7Sopenharmony_ci      // Element node
162e5c31af7Sopenharmony_ci      const className = ' ' + childNode.className + ' ';
163e5c31af7Sopenharmony_ci      const shouldRender = optionsCopy.ignoredTags.indexOf(childNode.nodeName.toLowerCase()) === -1 && optionsCopy.ignoredClasses.every(x => className.indexOf(' ' + x + ' ') === -1);
164e5c31af7Sopenharmony_ci
165e5c31af7Sopenharmony_ci      if (shouldRender) {
166e5c31af7Sopenharmony_ci        renderElem(childNode, optionsCopy);
167e5c31af7Sopenharmony_ci      }
168e5c31af7Sopenharmony_ci    } // Otherwise, it's something else, and ignore it.
169e5c31af7Sopenharmony_ci
170e5c31af7Sopenharmony_ci  }
171e5c31af7Sopenharmony_ci};
172e5c31af7Sopenharmony_ci
173e5c31af7Sopenharmony_ciconst renderMathInElement = function renderMathInElement(elem, options) {
174e5c31af7Sopenharmony_ci  if (!elem) {
175e5c31af7Sopenharmony_ci    throw new Error("No element provided to render");
176e5c31af7Sopenharmony_ci  }
177e5c31af7Sopenharmony_ci
178e5c31af7Sopenharmony_ci  const optionsCopy = {}; // Object.assign(optionsCopy, option)
179e5c31af7Sopenharmony_ci
180e5c31af7Sopenharmony_ci  for (const option in options) {
181e5c31af7Sopenharmony_ci    if (options.hasOwnProperty(option)) {
182e5c31af7Sopenharmony_ci      optionsCopy[option] = options[option];
183e5c31af7Sopenharmony_ci    }
184e5c31af7Sopenharmony_ci  } // default options
185e5c31af7Sopenharmony_ci
186e5c31af7Sopenharmony_ci
187e5c31af7Sopenharmony_ci  optionsCopy.delimiters = optionsCopy.delimiters || [{
188e5c31af7Sopenharmony_ci    left: "$$",
189e5c31af7Sopenharmony_ci    right: "$$",
190e5c31af7Sopenharmony_ci    display: true
191e5c31af7Sopenharmony_ci  }, {
192e5c31af7Sopenharmony_ci    left: "\\(",
193e5c31af7Sopenharmony_ci    right: "\\)",
194e5c31af7Sopenharmony_ci    display: false
195e5c31af7Sopenharmony_ci  }, // LaTeX uses $…$, but it ruins the display of normal `$` in text:
196e5c31af7Sopenharmony_ci  // {left: "$", right: "$", display: false},
197e5c31af7Sopenharmony_ci  //  \[…\] must come last in this array. Otherwise, renderMathInElement
198e5c31af7Sopenharmony_ci  //  will search for \[ before it searches for $$ or  \(
199e5c31af7Sopenharmony_ci  // That makes it susceptible to finding a \\[0.3em] row delimiter and
200e5c31af7Sopenharmony_ci  // treating it as if it were the start of a KaTeX math zone.
201e5c31af7Sopenharmony_ci  {
202e5c31af7Sopenharmony_ci    left: "\\[",
203e5c31af7Sopenharmony_ci    right: "\\]",
204e5c31af7Sopenharmony_ci    display: true
205e5c31af7Sopenharmony_ci  }];
206e5c31af7Sopenharmony_ci  optionsCopy.ignoredTags = optionsCopy.ignoredTags || ["script", "noscript", "style", "textarea", "pre", "code"];
207e5c31af7Sopenharmony_ci  optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || [];
208e5c31af7Sopenharmony_ci  optionsCopy.errorCallback = optionsCopy.errorCallback || console.error; // Enable sharing of global macros defined via `\gdef` between different
209e5c31af7Sopenharmony_ci  // math elements within a single call to `renderMathInElement`.
210e5c31af7Sopenharmony_ci
211e5c31af7Sopenharmony_ci  optionsCopy.macros = optionsCopy.macros || {};
212e5c31af7Sopenharmony_ci  renderElem(elem, optionsCopy);
213e5c31af7Sopenharmony_ci};
214e5c31af7Sopenharmony_ci
215e5c31af7Sopenharmony_ciexport default renderMathInElement;
216