123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- <script type="text/javascript">
- /* global katex */
- var findEndOfMath = function(delimiter, text, startIndex) {
- // Adapted from
- // https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
- var index = startIndex;
- var braceLevel = 0;
- var delimLength = delimiter.length;
- while (index < text.length) {
- var character = text[index];
- if (braceLevel <= 0 &&
- text.slice(index, index + delimLength) === delimiter) {
- return index;
- } else if (character === "\\") {
- index++;
- } else if (character === "{") {
- braceLevel++;
- } else if (character === "}") {
- braceLevel--;
- }
- index++;
- }
- return -1;
- };
- var splitAtDelimiters = function(startData, leftDelim, rightDelim, display) {
- var finalData = [];
- for (var i = 0; i < startData.length; i++) {
- if (startData[i].type === "text") {
- var text = startData[i].data;
- var lookingForLeft = true;
- var currIndex = 0;
- var nextIndex;
- nextIndex = text.indexOf(leftDelim);
- if (nextIndex !== -1) {
- currIndex = nextIndex;
- finalData.push({
- type: "text",
- data: text.slice(0, currIndex)
- });
- lookingForLeft = false;
- }
- while (true) {
- if (lookingForLeft) {
- nextIndex = text.indexOf(leftDelim, currIndex);
- if (nextIndex === -1) {
- break;
- }
- finalData.push({
- type: "text",
- data: text.slice(currIndex, nextIndex)
- });
- currIndex = nextIndex;
- } else {
- nextIndex = findEndOfMath(
- rightDelim,
- text,
- currIndex + leftDelim.length);
- if (nextIndex === -1) {
- break;
- }
- finalData.push({
- type: "math",
- data: text.slice(
- currIndex + leftDelim.length,
- nextIndex),
- rawData: text.slice(
- currIndex,
- nextIndex + rightDelim.length),
- display: display
- });
- currIndex = nextIndex + rightDelim.length;
- }
- lookingForLeft = !lookingForLeft;
- }
- finalData.push({
- type: "text",
- data: text.slice(currIndex)
- });
- } else {
- finalData.push(startData[i]);
- }
- }
- return finalData;
- };
- var splitWithDelimiters = function(text, delimiters) {
- var data = [{type: "text", data: text}];
- for (var i = 0; i < delimiters.length; i++) {
- var delimiter = delimiters[i];
- data = splitAtDelimiters(
- data, delimiter.left, delimiter.right,
- delimiter.display || false);
- }
- return data;
- };
- var renderMathInText = function(text, delimiters) {
- var data = splitWithDelimiters(text, delimiters);
- var fragment = document.createDocumentFragment();
- for (var i = 0; i < data.length; i++) {
- if (data[i].type === "text") {
- fragment.appendChild(document.createTextNode(data[i].data));
- } else {
- var span = document.createElement("span");
- var math = data[i].data;
- try {
- katex.render(math, span, {
- displayMode: data[i].display
- });
- } catch (e) {
- if (!(e instanceof katex.ParseError)) {
- throw e;
- }
- console.error(
- "KaTeX auto-render: Failed to parse `" + data[i].data +
- "` with ",
- e
- );
- fragment.appendChild(document.createTextNode(data[i].rawData));
- continue;
- }
- fragment.appendChild(span);
- }
- }
- return fragment;
- };
- var renderElem = function(elem, delimiters, ignoredTags) {
- for (var i = 0; i < elem.childNodes.length; i++) {
- var childNode = elem.childNodes[i];
- if (childNode.nodeType === 3) {
- // Text node
- var frag = renderMathInText(childNode.textContent, delimiters);
- i += frag.childNodes.length - 1;
- elem.replaceChild(frag, childNode);
- } else if (childNode.nodeType === 1) {
- // Element node
- var shouldRender = ignoredTags.indexOf(
- childNode.nodeName.toLowerCase()) === -1;
- if (shouldRender) {
- renderElem(childNode, delimiters, ignoredTags);
- }
- }
- // Otherwise, it's something else, and ignore it.
- }
- };
- var defaultOptions = {
- delimiters: [
- {left: "$$", right: "$$", display: true},
- {left: "\\[", right: "\\]", display: true},
- {left: "\\(", right: "\\)", display: false}
- // LaTeX uses this, but it ruins the display of normal `$` in text:
- // {left: "$", right: "$", display: false}
- ],
- ignoredTags: [
- "script", "noscript", "style", "textarea", "pre", "code"
- ]
- };
- var extend = function(obj) {
- // Adapted from underscore.js' `_.extend`. See LICENSE.txt for license.
- var source, prop;
- for (var i = 1, length = arguments.length; i < length; i++) {
- source = arguments[i];
- for (prop in source) {
- if (Object.prototype.hasOwnProperty.call(source, prop)) {
- obj[prop] = source[prop];
- }
- }
- }
- return obj;
- };
- var renderMathInElement = function(elem, options) {
- if (!elem) {
- throw new Error("No element provided to render");
- }
- options = extend({}, defaultOptions, options);
- renderElem(elem, options.delimiters, options.ignoredTags);
- };
- renderMathInElement(document.body);
- </script>
|