add initial marp implementation with sample content and build configuration
This commit is contained in:
21
node_modules/katex/LICENSE
generated
vendored
Normal file
21
node_modules/katex/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2020 Khan Academy and other contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
125
node_modules/katex/README.md
generated
vendored
Normal file
125
node_modules/katex/README.md
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
<h1><a href="https://katex.org/">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://katex.org/img/katex-logo.svg">
|
||||
<img alt="KaTeX" width=130 src="https://katex.org/img/katex-logo-black.svg">
|
||||
</picture>
|
||||
</a></h1>
|
||||
|
||||
[](https://www.npmjs.com/package/katex)
|
||||
[](https://github.com/semantic-release/semantic-release)
|
||||
[](https://github.com/KaTeX/KaTeX/actions?query=workflow%3ACI)
|
||||
[](https://codecov.io/gh/KaTeX/KaTeX)
|
||||
[](https://github.com/KaTeX/KaTeX/discussions)
|
||||
[](https://www.jsdelivr.com/package/npm/katex)
|
||||

|
||||
[](https://gitpod.io/#https://github.com/KaTeX/KaTeX)
|
||||
[](https://opencollective.com/katex)
|
||||
|
||||
KaTeX is a fast, easy-to-use JavaScript library for TeX math rendering on the web.
|
||||
|
||||
* **Fast:** KaTeX renders its math synchronously and doesn't need to reflow the page. See how it compares to a competitor in [this speed test](https://www.intmath.com/cg5/katex-mathjax-comparison.php).
|
||||
* **Print quality:** KaTeX's layout is based on Donald Knuth's TeX, the gold standard for math typesetting.
|
||||
* **Self contained:** KaTeX has no dependencies and can easily be bundled with your website resources.
|
||||
* **Server side rendering:** KaTeX produces the same output regardless of browser or environment, so you can pre-render expressions using Node.js and send them as plain HTML.
|
||||
|
||||
KaTeX is compatible with all major browsers, including Chrome, Safari, Firefox, Opera, Edge, and IE 11.
|
||||
|
||||
KaTeX supports much (but not all) of LaTeX and many LaTeX packages. See the [list of supported functions](https://katex.org/docs/supported.html).
|
||||
|
||||
Try out KaTeX [on the demo page](https://katex.org/#demo)!
|
||||
|
||||
## Getting started
|
||||
|
||||
### Starter template
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<!-- KaTeX requires the use of the HTML5 doctype. Without it, KaTeX may not render properly -->
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.css" integrity="sha384-5TcZemv2l/9On385z///+d7MSYlvIEw9FuZTIdZ14vJLqWphw7e7ZPuOiCHJcFCP" crossorigin="anonymous">
|
||||
|
||||
<!-- The loading of KaTeX is deferred to speed up page rendering -->
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.js" integrity="sha384-cMkvdD8LoxVzGF/RPUKAcvmm49FQ0oxwDF3BGKtDXcEc+T1b2N+teh/OJfpU0jr6" crossorigin="anonymous"></script>
|
||||
|
||||
<!-- To automatically render math in text elements, include the auto-render extension: -->
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/contrib/auto-render.min.js" integrity="sha384-hCXGrW6PitJEwbkoStFjeJxv+fSOOQKOPbJxSfM6G5sWZjAyWhXiTIIAmQqnlLlh" crossorigin="anonymous"
|
||||
onload="renderMathInElement(document.body);"></script>
|
||||
</head>
|
||||
...
|
||||
</html>
|
||||
```
|
||||
|
||||
You can also [download KaTeX](https://github.com/KaTeX/KaTeX/releases) and host it yourself.
|
||||
|
||||
For details on how to configure auto-render extension, refer to [the documentation](https://katex.org/docs/autorender.html).
|
||||
|
||||
### API
|
||||
|
||||
Call `katex.render` to render a TeX expression directly into a DOM element.
|
||||
For example:
|
||||
|
||||
```js
|
||||
katex.render("c = \\pm\\sqrt{a^2 + b^2}", element, {
|
||||
throwOnError: false
|
||||
});
|
||||
```
|
||||
|
||||
Call `katex.renderToString` to generate an HTML string of the rendered math,
|
||||
e.g., for server-side rendering. For example:
|
||||
|
||||
```js
|
||||
var html = katex.renderToString("c = \\pm\\sqrt{a^2 + b^2}", {
|
||||
throwOnError: false
|
||||
});
|
||||
// '<span class="katex">...</span>'
|
||||
```
|
||||
|
||||
Make sure to include the CSS and font files in both cases.
|
||||
If you are doing all rendering on the server, there is no need to include the
|
||||
JavaScript on the client.
|
||||
|
||||
The examples above use the `throwOnError: false` option, which renders invalid
|
||||
inputs as the TeX source code in red (by default), with the error message as
|
||||
hover text. For other available options, see the
|
||||
[API documentation](https://katex.org/docs/api.html),
|
||||
[options documentation](https://katex.org/docs/options.html), and
|
||||
[handling errors documentation](https://katex.org/docs/error.html).
|
||||
|
||||
## Demo and Documentation
|
||||
|
||||
Learn more about using KaTeX [on the website](https://katex.org)!
|
||||
|
||||
## Contributors
|
||||
|
||||
### Code Contributors
|
||||
|
||||
This project exists thanks to all the people who contribute code. If you'd like to help, see [our guide to contributing code](CONTRIBUTING.md).
|
||||
<a href="https://github.com/KaTeX/KaTeX/graphs/contributors"><img src="https://contributors-svg.opencollective.com/katex/contributors.svg?width=890&button=false" alt="Code contributors" /></a>
|
||||
|
||||
### Financial Contributors
|
||||
|
||||
Become a financial contributor and help us sustain our community.
|
||||
|
||||
#### Individuals
|
||||
|
||||
<a href="https://opencollective.com/katex"><img src="https://opencollective.com/katex/individuals.svg?width=890" alt="Contribute on Open Collective"></a>
|
||||
|
||||
#### Organizations
|
||||
|
||||
Support this project with your organization. Your logo will show up here with a link to your website.
|
||||
|
||||
<a href="https://opencollective.com/katex/organization/0/website"><img src="https://opencollective.com/katex/organization/0/avatar.svg" alt="Organization 1"></a>
|
||||
<a href="https://opencollective.com/katex/organization/1/website"><img src="https://opencollective.com/katex/organization/1/avatar.svg" alt="Organization 2"></a>
|
||||
<a href="https://opencollective.com/katex/organization/2/website"><img src="https://opencollective.com/katex/organization/2/avatar.svg" alt="Organization 3"></a>
|
||||
<a href="https://opencollective.com/katex/organization/3/website"><img src="https://opencollective.com/katex/organization/3/avatar.svg" alt="Organization 4"></a>
|
||||
<a href="https://opencollective.com/katex/organization/4/website"><img src="https://opencollective.com/katex/organization/4/avatar.svg" alt="Organization 5"></a>
|
||||
<a href="https://opencollective.com/katex/organization/5/website"><img src="https://opencollective.com/katex/organization/5/avatar.svg" alt="Organization 6"></a>
|
||||
<a href="https://opencollective.com/katex/organization/6/website"><img src="https://opencollective.com/katex/organization/6/avatar.svg" alt="Organization 7"></a>
|
||||
<a href="https://opencollective.com/katex/organization/7/website"><img src="https://opencollective.com/katex/organization/7/avatar.svg" alt="Organization 8"></a>
|
||||
<a href="https://opencollective.com/katex/organization/8/website"><img src="https://opencollective.com/katex/organization/8/avatar.svg" alt="Organization 9"></a>
|
||||
<a href="https://opencollective.com/katex/organization/9/website"><img src="https://opencollective.com/katex/organization/9/avatar.svg" alt="Organization 10"></a>
|
||||
|
||||
## License
|
||||
|
||||
KaTeX is licensed under the [MIT License](https://opensource.org/licenses/MIT).
|
||||
112
node_modules/katex/cli.js
generated
vendored
Executable file
112
node_modules/katex/cli.js
generated
vendored
Executable file
@@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env node
|
||||
// Simple CLI for KaTeX.
|
||||
// Reads TeX from stdin, outputs HTML to stdout.
|
||||
// To run this from the repository, you must first build KaTeX by running
|
||||
// `yarn` and `yarn build`.
|
||||
|
||||
/* eslint no-console:0 */
|
||||
|
||||
let katex;
|
||||
try {
|
||||
katex = require("./");
|
||||
} catch (e) {
|
||||
console.error(
|
||||
"KaTeX could not import, likely because dist/katex.js is missing.");
|
||||
console.error("Please run 'yarn' and 'yarn build' before running");
|
||||
console.error("cli.js from the KaTeX repository.");
|
||||
console.error();
|
||||
throw e;
|
||||
}
|
||||
const {version} = require("./package.json");
|
||||
const fs = require("fs");
|
||||
|
||||
const program = require("commander").version(version);
|
||||
for (const prop in katex.SETTINGS_SCHEMA) {
|
||||
if (katex.SETTINGS_SCHEMA.hasOwnProperty(prop)) {
|
||||
const opt = katex.SETTINGS_SCHEMA[prop];
|
||||
if (opt.cli !== false) {
|
||||
program.option(opt.cli || "--" + prop, opt.cliDescription ||
|
||||
opt.description, opt.cliProcessor, opt.cliDefault);
|
||||
}
|
||||
}
|
||||
}
|
||||
program.option("-f, --macro-file <path>",
|
||||
"Read macro definitions, one per line, from the given file.")
|
||||
.option("-i, --input <path>", "Read LaTeX input from the given file.")
|
||||
.option("-o, --output <path>", "Write html output to the given file.");
|
||||
|
||||
let options;
|
||||
|
||||
function readMacros() {
|
||||
if (options.macroFile) {
|
||||
fs.readFile(options.macroFile, "utf-8", function(err, data) {
|
||||
if (err) {throw err;}
|
||||
splitMacros(data.toString().split('\n'));
|
||||
});
|
||||
} else {
|
||||
splitMacros([]);
|
||||
}
|
||||
}
|
||||
|
||||
function splitMacros(macroStrings) {
|
||||
// Override macros from macro file (if any)
|
||||
// with macros from command line (if any)
|
||||
macroStrings = macroStrings.concat(options.macro);
|
||||
|
||||
const macros = {};
|
||||
|
||||
for (const m of macroStrings) {
|
||||
const i = m.search(":");
|
||||
if (i !== -1) {
|
||||
macros[m.substring(0, i).trim()] = m.substring(i + 1).trim();
|
||||
}
|
||||
}
|
||||
|
||||
options.macros = macros;
|
||||
readInput();
|
||||
}
|
||||
|
||||
function readInput() {
|
||||
let input = "";
|
||||
|
||||
if (options.input) {
|
||||
fs.readFile(options.input, "utf-8", function(err, data) {
|
||||
if (err) {throw err;}
|
||||
input = data.toString();
|
||||
writeOutput(input);
|
||||
});
|
||||
} else {
|
||||
process.stdin.on("data", function(chunk) {
|
||||
input += chunk.toString();
|
||||
});
|
||||
|
||||
process.stdin.on("end", function() {
|
||||
writeOutput(input);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function writeOutput(input) {
|
||||
// --format specifies the KaTeX output
|
||||
const outputFile = options.output;
|
||||
options.output = options.format;
|
||||
|
||||
const output = katex.renderToString(input, options) + "\n";
|
||||
|
||||
if (outputFile) {
|
||||
fs.writeFile(outputFile, output, function(err) {
|
||||
if (err) {
|
||||
return console.log(err);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log(output);
|
||||
}
|
||||
}
|
||||
|
||||
if (require.main !== module) {
|
||||
module.exports = program;
|
||||
} else {
|
||||
options = program.parse(process.argv).opts();
|
||||
readMacros();
|
||||
}
|
||||
8
node_modules/katex/contrib/auto-render/README.md
generated
vendored
Normal file
8
node_modules/katex/contrib/auto-render/README.md
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Auto-render extension
|
||||
|
||||
This is an extension to automatically render all of the math inside of text. It
|
||||
searches all of the text nodes in a given element for the given delimiters, and
|
||||
renders the math in place.
|
||||
|
||||
See [Auto-render extension documentation](https://katex.org/docs/autorender.html)
|
||||
for more information.
|
||||
142
node_modules/katex/contrib/auto-render/auto-render.js
generated
vendored
Normal file
142
node_modules/katex/contrib/auto-render/auto-render.js
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
/* eslint no-console:0 */
|
||||
|
||||
import katex from "katex";
|
||||
import splitAtDelimiters from "./splitAtDelimiters";
|
||||
|
||||
/* Note: optionsCopy is mutated by this method. If it is ever exposed in the
|
||||
* API, we should copy it before mutating.
|
||||
*/
|
||||
const renderMathInText = function(text, optionsCopy) {
|
||||
const data = splitAtDelimiters(text, optionsCopy.delimiters);
|
||||
if (data.length === 1 && data[0].type === 'text') {
|
||||
// There is no formula in the text.
|
||||
// Let's return null which means there is no need to replace
|
||||
// the current text node with a new one.
|
||||
return null;
|
||||
}
|
||||
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
if (data[i].type === "text") {
|
||||
fragment.appendChild(document.createTextNode(data[i].data));
|
||||
} else {
|
||||
const span = document.createElement("span");
|
||||
let math = data[i].data;
|
||||
// Override any display mode defined in the settings with that
|
||||
// defined by the text itself
|
||||
optionsCopy.displayMode = data[i].display;
|
||||
try {
|
||||
if (optionsCopy.preProcess) {
|
||||
math = optionsCopy.preProcess(math);
|
||||
}
|
||||
katex.render(math, span, optionsCopy);
|
||||
} catch (e) {
|
||||
if (!(e instanceof katex.ParseError)) {
|
||||
throw e;
|
||||
}
|
||||
optionsCopy.errorCallback(
|
||||
"KaTeX auto-render: Failed to parse `" + data[i].data +
|
||||
"` with ",
|
||||
e
|
||||
);
|
||||
fragment.appendChild(document.createTextNode(data[i].rawData));
|
||||
continue;
|
||||
}
|
||||
fragment.appendChild(span);
|
||||
}
|
||||
}
|
||||
|
||||
return fragment;
|
||||
};
|
||||
|
||||
const renderElem = function(elem, optionsCopy) {
|
||||
for (let i = 0; i < elem.childNodes.length; i++) {
|
||||
const childNode = elem.childNodes[i];
|
||||
if (childNode.nodeType === 3) {
|
||||
// Text node
|
||||
// Concatenate all sibling text nodes.
|
||||
// Webkit browsers split very large text nodes into smaller ones,
|
||||
// so the delimiters may be split across different nodes.
|
||||
let textContentConcat = childNode.textContent;
|
||||
let sibling = childNode.nextSibling;
|
||||
let nSiblings = 0;
|
||||
while (sibling && (sibling.nodeType === Node.TEXT_NODE)) {
|
||||
textContentConcat += sibling.textContent;
|
||||
sibling = sibling.nextSibling;
|
||||
nSiblings++;
|
||||
}
|
||||
const frag = renderMathInText(textContentConcat, optionsCopy);
|
||||
if (frag) {
|
||||
// Remove extra text nodes
|
||||
for (let j = 0; j < nSiblings; j++) {
|
||||
childNode.nextSibling.remove();
|
||||
}
|
||||
i += frag.childNodes.length - 1;
|
||||
elem.replaceChild(frag, childNode);
|
||||
} else {
|
||||
// If the concatenated text does not contain math
|
||||
// the siblings will not either
|
||||
i += nSiblings;
|
||||
}
|
||||
} else if (childNode.nodeType === 1) {
|
||||
// Element node
|
||||
const className = ' ' + childNode.className + ' ';
|
||||
const shouldRender = optionsCopy.ignoredTags.indexOf(
|
||||
childNode.nodeName.toLowerCase()) === -1 &&
|
||||
optionsCopy.ignoredClasses.every(
|
||||
x => className.indexOf(' ' + x + ' ') === -1);
|
||||
|
||||
if (shouldRender) {
|
||||
renderElem(childNode, optionsCopy);
|
||||
}
|
||||
}
|
||||
// Otherwise, it's something else, and ignore it.
|
||||
}
|
||||
};
|
||||
|
||||
const renderMathInElement = function(elem, options) {
|
||||
if (!elem) {
|
||||
throw new Error("No element provided to render");
|
||||
}
|
||||
|
||||
const optionsCopy = {};
|
||||
|
||||
// Object.assign(optionsCopy, option)
|
||||
for (const option in options) {
|
||||
if (options.hasOwnProperty(option)) {
|
||||
optionsCopy[option] = options[option];
|
||||
}
|
||||
}
|
||||
|
||||
// default options
|
||||
optionsCopy.delimiters = optionsCopy.delimiters || [
|
||||
{left: "$$", right: "$$", display: true},
|
||||
{left: "\\(", right: "\\)", display: false},
|
||||
// LaTeX uses $…$, but it ruins the display of normal `$` in text:
|
||||
// {left: "$", right: "$", display: false},
|
||||
// $ must come after $$
|
||||
|
||||
// Render AMS environments even if outside $$…$$ delimiters.
|
||||
{left: "\\begin{equation}", right: "\\end{equation}", display: true},
|
||||
{left: "\\begin{align}", right: "\\end{align}", display: true},
|
||||
{left: "\\begin{alignat}", right: "\\end{alignat}", display: true},
|
||||
{left: "\\begin{gather}", right: "\\end{gather}", display: true},
|
||||
{left: "\\begin{CD}", right: "\\end{CD}", display: true},
|
||||
|
||||
{left: "\\[", right: "\\]", display: true},
|
||||
];
|
||||
optionsCopy.ignoredTags = optionsCopy.ignoredTags || [
|
||||
"script", "noscript", "style", "textarea", "pre", "code", "option",
|
||||
];
|
||||
optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || [];
|
||||
optionsCopy.errorCallback = optionsCopy.errorCallback || console.error;
|
||||
|
||||
// Enable sharing of global macros defined via `\gdef` between different
|
||||
// math elements within a single call to `renderMathInElement`.
|
||||
optionsCopy.macros = optionsCopy.macros || {};
|
||||
|
||||
renderElem(elem, optionsCopy);
|
||||
};
|
||||
|
||||
export default renderMathInElement;
|
||||
56
node_modules/katex/contrib/auto-render/index.html
generated
vendored
Normal file
56
node_modules/katex/contrib/auto-render/index.html
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<!DOCTYPE html>
|
||||
<!--To run this example from a clone of the repository, run `yarn start`
|
||||
in the root KaTeX directory and then visit with your web browser:
|
||||
http://localhost:7936/contrib/auto-render/index.html
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Auto-render test</title>
|
||||
<script src="/katex.js" type="text/javascript"></script>
|
||||
<script src="/contrib/auto-render.js" type="text/javascript"></script>
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
#test > .blue {
|
||||
color: blue;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="test">
|
||||
This is some text $math \frac12$ other text $\unsupported$
|
||||
<span class="blue">
|
||||
Other node \[ \text{displaymath} \frac{1}{2} \] blah $$ \int_2^3 $$
|
||||
</span>
|
||||
and some <!-- comment --> more text \(and math\) blah. And $math with a
|
||||
\$ sign$.
|
||||
<pre>
|
||||
Stuff in a $pre tag$
|
||||
</pre>
|
||||
<p>An AMS environment without <code>$$…$$</code> delimiters.</p>
|
||||
<p>\begin{equation} \begin{split} a &=b+c\\ &=e+f \end{split} \end{equation}</p>
|
||||
</div>
|
||||
<script>
|
||||
renderMathInElement(
|
||||
document.getElementById("test"),
|
||||
{
|
||||
delimiters: [
|
||||
{left: "$$", right: "$$", display: true},
|
||||
{left: "$", right: "$", display: false},
|
||||
{left: "\\begin{equation}", right: "\\end{equation}", display: true},
|
||||
{left: "\\begin{align}", right: "\\end{align}", display: true},
|
||||
{left: "\\begin{alignat}", right: "\\end{alignat}", display: true},
|
||||
{left: "\\begin{gather}", right: "\\end{gather}", display: true},
|
||||
{left: "\\(", right: "\\)", display: false},
|
||||
{left: "\\[", right: "\\]", display: true}
|
||||
]
|
||||
}
|
||||
);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
85
node_modules/katex/contrib/auto-render/splitAtDelimiters.js
generated
vendored
Normal file
85
node_modules/katex/contrib/auto-render/splitAtDelimiters.js
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
/* eslint no-constant-condition:0 */
|
||||
const findEndOfMath = function(delimiter, text, startIndex) {
|
||||
// Adapted from
|
||||
// https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
|
||||
let index = startIndex;
|
||||
let braceLevel = 0;
|
||||
|
||||
const delimLength = delimiter.length;
|
||||
|
||||
while (index < text.length) {
|
||||
const 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;
|
||||
};
|
||||
|
||||
const escapeRegex = function(string) {
|
||||
return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
||||
};
|
||||
|
||||
const amsRegex = /^\\begin{/;
|
||||
|
||||
const splitAtDelimiters = function(text, delimiters) {
|
||||
let index;
|
||||
const data = [];
|
||||
|
||||
const regexLeft = new RegExp(
|
||||
"(" + delimiters.map((x) => escapeRegex(x.left)).join("|") + ")"
|
||||
);
|
||||
|
||||
while (true) {
|
||||
index = text.search(regexLeft);
|
||||
if (index === -1) {
|
||||
break;
|
||||
}
|
||||
if (index > 0) {
|
||||
data.push({
|
||||
type: "text",
|
||||
data: text.slice(0, index),
|
||||
});
|
||||
text = text.slice(index); // now text starts with delimiter
|
||||
}
|
||||
// ... so this always succeeds:
|
||||
const i = delimiters.findIndex((delim) => text.startsWith(delim.left));
|
||||
index = findEndOfMath(delimiters[i].right, text, delimiters[i].left.length);
|
||||
if (index === -1) {
|
||||
break;
|
||||
}
|
||||
const rawData = text.slice(0, index + delimiters[i].right.length);
|
||||
const math = amsRegex.test(rawData)
|
||||
? rawData
|
||||
: text.slice(delimiters[i].left.length, index);
|
||||
data.push({
|
||||
type: "math",
|
||||
data: math,
|
||||
rawData,
|
||||
display: delimiters[i].display,
|
||||
});
|
||||
text = text.slice(index + delimiters[i].right.length);
|
||||
}
|
||||
|
||||
if (text !== "") {
|
||||
data.push({
|
||||
type: "text",
|
||||
data: text,
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export default splitAtDelimiters;
|
||||
363
node_modules/katex/contrib/auto-render/test/auto-render-spec.js
generated
vendored
Normal file
363
node_modules/katex/contrib/auto-render/test/auto-render-spec.js
generated
vendored
Normal file
@@ -0,0 +1,363 @@
|
||||
/**
|
||||
* @jest-environment jsdom
|
||||
*/
|
||||
import splitAtDelimiters from "../splitAtDelimiters";
|
||||
import renderMathInElement from "../auto-render";
|
||||
|
||||
beforeEach(function() {
|
||||
expect.extend({
|
||||
toSplitInto: function(actual, result, delimiters) {
|
||||
const message = {
|
||||
pass: true,
|
||||
message: () => "'" + actual + "' split correctly",
|
||||
};
|
||||
|
||||
const split =
|
||||
splitAtDelimiters(actual, delimiters);
|
||||
|
||||
if (split.length !== result.length) {
|
||||
message.pass = false;
|
||||
message.message = () => "Different number of splits: " +
|
||||
split.length + " vs. " + result.length + " (" +
|
||||
JSON.stringify(split) + " vs. " +
|
||||
JSON.stringify(result) + ")";
|
||||
return message;
|
||||
}
|
||||
|
||||
for (let i = 0; i < split.length; i++) {
|
||||
const real = split[i];
|
||||
const correct = result[i];
|
||||
|
||||
let good = true;
|
||||
let diff;
|
||||
|
||||
if (real.type !== correct.type) {
|
||||
good = false;
|
||||
diff = "type";
|
||||
} else if (real.data !== correct.data) {
|
||||
good = false;
|
||||
diff = "data";
|
||||
} else if (real.display !== correct.display) {
|
||||
good = false;
|
||||
diff = "display";
|
||||
}
|
||||
|
||||
if (!good) {
|
||||
message.pass = false;
|
||||
message.message = () => "Difference at split " +
|
||||
(i + 1) + ": " + JSON.stringify(real) +
|
||||
" vs. " + JSON.stringify(correct) +
|
||||
" (" + diff + " differs)";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return message;
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
describe("A delimiter splitter", function() {
|
||||
it("doesn't split when there are no delimiters", function() {
|
||||
expect("hello").toSplitInto(
|
||||
[
|
||||
{type: "text", data: "hello"},
|
||||
],
|
||||
[
|
||||
{left: "(", right: ")", display: false},
|
||||
]);
|
||||
});
|
||||
|
||||
it("doesn't create a math node with only one left delimiter", function() {
|
||||
expect("hello ( world").toSplitInto(
|
||||
[
|
||||
{type: "text", data: "hello "},
|
||||
{type: "text", data: "( world"},
|
||||
],
|
||||
[
|
||||
{left: "(", right: ")", display: false},
|
||||
]);
|
||||
});
|
||||
|
||||
it("doesn't split when there's only a right delimiter", function() {
|
||||
expect("hello ) world").toSplitInto(
|
||||
[
|
||||
{type: "text", data: "hello ) world"},
|
||||
],
|
||||
[
|
||||
{left: "(", right: ")", display: false},
|
||||
]);
|
||||
});
|
||||
|
||||
it("splits when there are both delimiters", function() {
|
||||
expect("hello ( world ) boo").toSplitInto(
|
||||
[
|
||||
{type: "text", data: "hello "},
|
||||
{type: "math", data: " world ",
|
||||
rawData: "( world )", display: false},
|
||||
{type: "text", data: " boo"},
|
||||
],
|
||||
[
|
||||
{left: "(", right: ")", display: false},
|
||||
]);
|
||||
});
|
||||
|
||||
it("splits on multi-character delimiters", function() {
|
||||
expect("hello [[ world ]] boo").toSplitInto(
|
||||
[
|
||||
{type: "text", data: "hello "},
|
||||
{type: "math", data: " world ",
|
||||
rawData: "[[ world ]]", display: false},
|
||||
{type: "text", data: " boo"},
|
||||
],
|
||||
[
|
||||
{left: "[[", right: "]]", display: false},
|
||||
]);
|
||||
expect("hello \\begin{equation} world \\end{equation} boo").toSplitInto(
|
||||
[
|
||||
{type: "text", data: "hello "},
|
||||
{type: "math", data: "\\begin{equation} world \\end{equation}",
|
||||
rawData: "\\begin{equation} world \\end{equation}",
|
||||
display: false},
|
||||
{type: "text", data: " boo"},
|
||||
],
|
||||
[
|
||||
{left: "\\begin{equation}", right: "\\end{equation}",
|
||||
display: false},
|
||||
]);
|
||||
});
|
||||
|
||||
it("splits multiple times", function() {
|
||||
expect("hello ( world ) boo ( more ) stuff").toSplitInto(
|
||||
[
|
||||
{type: "text", data: "hello "},
|
||||
{type: "math", data: " world ",
|
||||
rawData: "( world )", display: false},
|
||||
{type: "text", data: " boo "},
|
||||
{type: "math", data: " more ",
|
||||
rawData: "( more )", display: false},
|
||||
{type: "text", data: " stuff"},
|
||||
],
|
||||
[
|
||||
{left: "(", right: ")", display: false},
|
||||
]);
|
||||
});
|
||||
|
||||
it("leaves the ending when there's only a left delimiter", function() {
|
||||
expect("hello ( world ) boo ( left").toSplitInto(
|
||||
[
|
||||
{type: "text", data: "hello "},
|
||||
{type: "math", data: " world ",
|
||||
rawData: "( world )", display: false},
|
||||
{type: "text", data: " boo "},
|
||||
{type: "text", data: "( left"},
|
||||
],
|
||||
[
|
||||
{left: "(", right: ")", display: false},
|
||||
]);
|
||||
});
|
||||
|
||||
it("doesn't split when close delimiters are in {}s", function() {
|
||||
expect("hello ( world { ) } ) boo").toSplitInto(
|
||||
[
|
||||
{type: "text", data: "hello "},
|
||||
{type: "math", data: " world { ) } ",
|
||||
rawData: "( world { ) } )", display: false},
|
||||
{type: "text", data: " boo"},
|
||||
],
|
||||
[
|
||||
{left: "(", right: ")", display: false},
|
||||
]);
|
||||
|
||||
expect("hello ( world { { } ) } ) boo").toSplitInto(
|
||||
[
|
||||
{type: "text", data: "hello "},
|
||||
{type: "math", data: " world { { } ) } ",
|
||||
rawData: "( world { { } ) } )", display: false},
|
||||
{type: "text", data: " boo"},
|
||||
],
|
||||
[
|
||||
{left: "(", right: ")", display: false},
|
||||
]);
|
||||
});
|
||||
|
||||
it("correctly processes sequences of $..$", function() {
|
||||
expect("$hello$$world$$boo$").toSplitInto(
|
||||
[
|
||||
{type: "math", data: "hello",
|
||||
rawData: "$hello$", display: false},
|
||||
{type: "math", data: "world",
|
||||
rawData: "$world$", display: false},
|
||||
{type: "math", data: "boo",
|
||||
rawData: "$boo$", display: false},
|
||||
],
|
||||
[
|
||||
{left: "$", right: "$", display: false},
|
||||
]);
|
||||
});
|
||||
|
||||
it("doesn't split at escaped delimiters", function() {
|
||||
expect("hello ( world \\) ) boo").toSplitInto(
|
||||
[
|
||||
{type: "text", data: "hello "},
|
||||
{type: "math", data: " world \\) ",
|
||||
rawData: "( world \\) )", display: false},
|
||||
{type: "text", data: " boo"},
|
||||
],
|
||||
[
|
||||
{left: "(", right: ")", display: false},
|
||||
]);
|
||||
|
||||
/* TODO(emily): make this work maybe?
|
||||
expect("hello \\( ( world ) boo").toSplitInto(
|
||||
"(", ")",
|
||||
[
|
||||
{type: "text", data: "hello \\( "},
|
||||
{type: "math", data: " world ",
|
||||
rawData: "( world )", display: false},
|
||||
{type: "text", data: " boo"},
|
||||
]);
|
||||
*/
|
||||
});
|
||||
|
||||
it("splits when the right and left delimiters are the same", function() {
|
||||
expect("hello $ world $ boo").toSplitInto(
|
||||
[
|
||||
{type: "text", data: "hello "},
|
||||
{type: "math", data: " world ",
|
||||
rawData: "$ world $", display: false},
|
||||
{type: "text", data: " boo"},
|
||||
],
|
||||
[
|
||||
{left: "$", right: "$", display: false},
|
||||
]);
|
||||
});
|
||||
|
||||
it("ignores \\$", function() {
|
||||
expect("$x = \\$5$").toSplitInto(
|
||||
[
|
||||
{type: "math", data: "x = \\$5",
|
||||
rawData: "$x = \\$5$", display: false},
|
||||
],
|
||||
[
|
||||
{left: "$", right: "$", display: false},
|
||||
]);
|
||||
});
|
||||
|
||||
it("remembers which delimiters are display-mode", function() {
|
||||
const startData = "hello ( world ) boo";
|
||||
|
||||
expect(splitAtDelimiters(startData,
|
||||
[{left:"(", right:")", display:true}])).toEqual(
|
||||
[
|
||||
{type: "text", data: "hello "},
|
||||
{type: "math", data: " world ",
|
||||
rawData: "( world )", display: true},
|
||||
{type: "text", data: " boo"},
|
||||
]);
|
||||
});
|
||||
|
||||
it("handles nested delimiters irrespective of order", function() {
|
||||
expect(splitAtDelimiters("$\\fbox{\\(hi\\)}$",
|
||||
[
|
||||
{left:"\\(", right:"\\)", display:false},
|
||||
{left:"$", right:"$", display:false},
|
||||
])).toEqual(
|
||||
[
|
||||
{type: "math", data: "\\fbox{\\(hi\\)}",
|
||||
rawData: "$\\fbox{\\(hi\\)}$", display: false},
|
||||
]);
|
||||
expect(splitAtDelimiters("\\(\\fbox{$hi$}\\)",
|
||||
[
|
||||
{left:"\\(", right:"\\)", display:false},
|
||||
{left:"$", right:"$", display:false},
|
||||
])).toEqual(
|
||||
[
|
||||
{type: "math", data: "\\fbox{$hi$}",
|
||||
rawData: "\\(\\fbox{$hi$}\\)", display: false},
|
||||
]);
|
||||
});
|
||||
|
||||
it("handles a mix of $ and $$", function() {
|
||||
expect(splitAtDelimiters("$hello$world$$boo$$",
|
||||
[
|
||||
{left:"$$", right:"$$", display:true},
|
||||
{left:"$", right:"$", display:false},
|
||||
])).toEqual(
|
||||
[
|
||||
{type: "math", data: "hello",
|
||||
rawData: "$hello$", display: false},
|
||||
{type: "text", data: "world"},
|
||||
{type: "math", data: "boo",
|
||||
rawData: "$$boo$$", display: true},
|
||||
]);
|
||||
expect(splitAtDelimiters("$hello$$world$$$boo$$",
|
||||
[
|
||||
{left:"$$", right:"$$", display:true},
|
||||
{left:"$", right:"$", display:false},
|
||||
])).toEqual(
|
||||
[
|
||||
{type: "math", data: "hello",
|
||||
rawData: "$hello$", display: false},
|
||||
{type: "math", data: "world",
|
||||
rawData: "$world$", display: false},
|
||||
{type: "math", data: "boo",
|
||||
rawData: "$$boo$$", display: true},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Pre-process callback", function() {
|
||||
it("replace `-squared` with `^2 `", function() {
|
||||
const el1 = document.createElement('div');
|
||||
el1.textContent = 'Circle equation: $x-squared + y-squared = r-squared$.';
|
||||
const el2 = document.createElement('div');
|
||||
el2.textContent = 'Circle equation: $x^2 + y^2 = r^2$.';
|
||||
const delimiters = [{left: "$", right: "$", display: false}];
|
||||
renderMathInElement(el1, {
|
||||
delimiters,
|
||||
preProcess: math => math.replace(/-squared/g, '^2'),
|
||||
});
|
||||
renderMathInElement(el2, {delimiters});
|
||||
expect(el1.innerHTML).toEqual(el2.innerHTML);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Parse adjacent text nodes", function() {
|
||||
it("parse adjacent text nodes with math", function() {
|
||||
const textNodes = ['\\[',
|
||||
'x^2 + y^2 = r^2',
|
||||
'\\]'];
|
||||
const el = document.createElement('div');
|
||||
for (let i = 0; i < textNodes.length; i++) {
|
||||
const txt = document.createTextNode(textNodes[i]);
|
||||
el.appendChild(txt);
|
||||
}
|
||||
const el2 = document.createElement('div');
|
||||
const txt = document.createTextNode(textNodes.join(''));
|
||||
el2.appendChild(txt);
|
||||
const delimiters = [{left: "\\[", right: "\\]", display: true}];
|
||||
renderMathInElement(el, {delimiters});
|
||||
renderMathInElement(el2, {delimiters});
|
||||
expect(el).toStrictEqual(el2);
|
||||
});
|
||||
|
||||
it("parse adjacent text nodes without math", function() {
|
||||
const textNodes = ['Lorem ipsum dolor',
|
||||
'sit amet',
|
||||
'consectetur adipiscing elit'];
|
||||
const el = document.createElement('div');
|
||||
for (let i = 0; i < textNodes.length; i++) {
|
||||
const txt = document.createTextNode(textNodes[i]);
|
||||
el.appendChild(txt);
|
||||
}
|
||||
const el2 = document.createElement('div');
|
||||
for (let i = 0; i < textNodes.length; i++) {
|
||||
const txt = document.createTextNode(textNodes[i]);
|
||||
el2.appendChild(txt);
|
||||
}
|
||||
const delimiters = [{left: "\\[", right: "\\]", display: true}];
|
||||
renderMathInElement(el, {delimiters});
|
||||
expect(el).toStrictEqual(el2);
|
||||
});
|
||||
});
|
||||
39
node_modules/katex/contrib/copy-tex/README.md
generated
vendored
Normal file
39
node_modules/katex/contrib/copy-tex/README.md
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
# Copy-tex extension
|
||||
|
||||
This extension modifies the copy/paste behavior in any browser supporting the
|
||||
[Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent)
|
||||
so that, when selecting and copying KaTeX-rendered elements, the text
|
||||
content of the resulting clipboard renders KaTeX elements as their LaTeX source
|
||||
surrounded by specified delimiters. (The HTML content of the resulting
|
||||
clipboard remains the selected HTML content, as it normally would.)
|
||||
The default delimiters are `$...$` for inline math and `$$...$$` for display
|
||||
math, but you can easy switch them to e.g. `\(...\)` and `\[...\]` by
|
||||
modifying `copyDelimiters` in [the source code](copy-tex.js).
|
||||
Note that a selection containing part of a KaTeX formula gets extended to
|
||||
include the entire KaTeX formula.
|
||||
|
||||
## Usage
|
||||
|
||||
This extension isn't part of KaTeX proper, so the script should be separately
|
||||
included in the page.
|
||||
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/contrib/copy-tex.min.js" integrity="sha384-HORx6nWi8j5/mYA+y57/9/CZc5z8HnEw4WUZWy5yOn9ToKBv1l58vJaufFAn9Zzi" crossorigin="anonymous"></script>
|
||||
```
|
||||
|
||||
(Note that, as of KaTeX 0.16.0, there is no longer a corresponding CSS file.)
|
||||
|
||||
See [index.html](index.html) for an example.
|
||||
(To run this example from a clone of the repository, run `yarn start`
|
||||
in the root KaTeX directory, and then visit
|
||||
http://localhost:7936/contrib/copy-tex/index.html
|
||||
with your web browser.)
|
||||
|
||||
If you want to build your own custom copy handler based on this one,
|
||||
copy the `copy-tex.js` into your codebase and replace the `require`
|
||||
statement with `require('katex/contrib/copy-tex/katex2tex.js')`.
|
||||
|
||||
ECMAScript module is also available:
|
||||
```html
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/contrib/copy-tex.mjs" integrity="sha384-bVEnwt0PtX+1EuJoOEcm4rgTUWvb2ILTdjHfI1gUe/r5fdqrTcQaUuRdHG2DciuQ" crossorigin="anonymous"></script>
|
||||
```
|
||||
51
node_modules/katex/contrib/copy-tex/copy-tex.js
generated
vendored
Normal file
51
node_modules/katex/contrib/copy-tex/copy-tex.js
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
// @flow
|
||||
|
||||
import katexReplaceWithTex from './katex2tex';
|
||||
|
||||
// Return <div class="katex"> element containing node, or null if not found.
|
||||
function closestKatex(node: Node): ?Element {
|
||||
// If node is a Text Node, for example, go up to containing Element,
|
||||
// where we can apply the `closest` method.
|
||||
const element: ?Element =
|
||||
(node instanceof Element ? node : node.parentElement);
|
||||
return element && element.closest('.katex');
|
||||
}
|
||||
|
||||
// Global copy handler to modify behavior on/within .katex elements.
|
||||
document.addEventListener('copy', function(event: ClipboardEvent) {
|
||||
const selection = window.getSelection();
|
||||
if (selection.isCollapsed || !event.clipboardData) {
|
||||
return; // default action OK if selection is empty or unchangeable
|
||||
}
|
||||
const clipboardData = event.clipboardData;
|
||||
const range = selection.getRangeAt(0);
|
||||
|
||||
// When start point is within a formula, expand to entire formula.
|
||||
const startKatex = closestKatex(range.startContainer);
|
||||
if (startKatex) {
|
||||
range.setStartBefore(startKatex);
|
||||
}
|
||||
|
||||
// Similarly, when end point is within a formula, expand to entire formula.
|
||||
const endKatex = closestKatex(range.endContainer);
|
||||
if (endKatex) {
|
||||
range.setEndAfter(endKatex);
|
||||
}
|
||||
|
||||
const fragment = range.cloneContents();
|
||||
if (!fragment.querySelector('.katex-mathml')) {
|
||||
return; // default action OK if no .katex-mathml elements
|
||||
}
|
||||
|
||||
const htmlContents = Array.prototype.map.call(fragment.childNodes,
|
||||
(el) => (el instanceof Text ? el.textContent : el.outerHTML)
|
||||
).join('');
|
||||
|
||||
// Preserve usual HTML copy/paste behavior.
|
||||
clipboardData.setData('text/html', htmlContents);
|
||||
// Rewrite plain-text version.
|
||||
clipboardData.setData('text/plain',
|
||||
katexReplaceWithTex(fragment).textContent);
|
||||
// Prevent normal copy handling.
|
||||
event.preventDefault();
|
||||
});
|
||||
38
node_modules/katex/contrib/copy-tex/index.html
generated
vendored
Normal file
38
node_modules/katex/contrib/copy-tex/index.html
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<!DOCTYPE html>
|
||||
<!--To run this example from a clone of the repository, run `yarn start`
|
||||
in the root KaTeX directory and then visit with your web browser:
|
||||
http://localhost:7936/contrib/copy-tex/index.html
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Copy-tex test</title>
|
||||
<script src="/katex.js" type="text/javascript"></script>
|
||||
<script src="/contrib/auto-render.js" type="text/javascript"></script>
|
||||
<script src="/contrib/copy-tex.js" type="text/javascript"></script>
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
#test > .blue {
|
||||
color: blue;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Copy-tex test</h1>
|
||||
<h2>Try copy/pasting some of the text below!</h2>
|
||||
<p>
|
||||
Here is some \(\KaTeX\) math: $$ x^2+y^2=z^2 $$
|
||||
The variables are \(x\), \(y\), and \(z\),
|
||||
which are all in \(\mathbb{R}^+\).
|
||||
Q.E.D.
|
||||
</p>
|
||||
<script>
|
||||
renderMathInElement(document.body);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
61
node_modules/katex/contrib/copy-tex/katex2tex.js
generated
vendored
Normal file
61
node_modules/katex/contrib/copy-tex/katex2tex.js
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
// @flow
|
||||
|
||||
export interface CopyDelimiters {
|
||||
inline: [string, string],
|
||||
display: [string, string],
|
||||
}
|
||||
|
||||
// Set these to how you want inline and display math to be delimited.
|
||||
export const defaultCopyDelimiters: CopyDelimiters = {
|
||||
inline: ['$', '$'], // alternative: ['\(', '\)']
|
||||
display: ['$$', '$$'], // alternative: ['\[', '\]']
|
||||
};
|
||||
|
||||
// Replace .katex elements with their TeX source (<annotation> element).
|
||||
// Modifies fragment in-place. Useful for writing your own 'copy' handler,
|
||||
// as in copy-tex.js.
|
||||
export function katexReplaceWithTex(
|
||||
fragment: DocumentFragment,
|
||||
copyDelimiters: CopyDelimiters = defaultCopyDelimiters
|
||||
): DocumentFragment {
|
||||
// Remove .katex-html blocks that are preceded by .katex-mathml blocks
|
||||
// (which will get replaced below).
|
||||
const katexHtml = fragment.querySelectorAll('.katex-mathml + .katex-html');
|
||||
for (let i = 0; i < katexHtml.length; i++) {
|
||||
const element = katexHtml[i];
|
||||
if (element.remove) {
|
||||
element.remove();
|
||||
} else if (element.parentNode) {
|
||||
element.parentNode.removeChild(element);
|
||||
}
|
||||
}
|
||||
// Replace .katex-mathml elements with their annotation (TeX source)
|
||||
// descendant, with inline delimiters.
|
||||
const katexMathml = fragment.querySelectorAll('.katex-mathml');
|
||||
for (let i = 0; i < katexMathml.length; i++) {
|
||||
const element = katexMathml[i];
|
||||
const texSource = element.querySelector('annotation');
|
||||
if (texSource) {
|
||||
if (element.replaceWith) {
|
||||
element.replaceWith(texSource);
|
||||
} else if (element.parentNode) {
|
||||
element.parentNode.replaceChild(texSource, element);
|
||||
}
|
||||
texSource.innerHTML = copyDelimiters.inline[0] +
|
||||
texSource.innerHTML + copyDelimiters.inline[1];
|
||||
}
|
||||
}
|
||||
// Switch display math to display delimiters.
|
||||
const displays = fragment.querySelectorAll('.katex-display annotation');
|
||||
for (let i = 0; i < displays.length; i++) {
|
||||
const element = displays[i];
|
||||
element.innerHTML = copyDelimiters.display[0] +
|
||||
element.innerHTML.substr(copyDelimiters.inline[0].length,
|
||||
element.innerHTML.length - copyDelimiters.inline[0].length
|
||||
- copyDelimiters.inline[1].length)
|
||||
+ copyDelimiters.display[1];
|
||||
}
|
||||
return fragment;
|
||||
}
|
||||
|
||||
export default katexReplaceWithTex;
|
||||
38
node_modules/katex/contrib/mathtex-script-type/README.md
generated
vendored
Normal file
38
node_modules/katex/contrib/mathtex-script-type/README.md
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
# `math/tex` Custom Script Type Extension
|
||||
|
||||
This is an extension to automatically display code inside `script` tags with `type=math/tex` using KaTeX.
|
||||
This script type is commonly used by MathJax, so this can be used to support compatibility with MathJax.
|
||||
|
||||
### Usage
|
||||
|
||||
This extension isn't part of KaTeX proper, so the script should be separately
|
||||
included in the page, in addition to KaTeX.
|
||||
|
||||
Load the extension by adding the following line to your HTML file.
|
||||
|
||||
```html
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/contrib/mathtex-script-type.min.js" integrity="sha384-sg4gBRJTqTCyzYbB7e72xGs3dA2LK994XRZS6urZW6Uh6Mu3j2JJ3YG2s9HALO8U" crossorigin="anonymous"></script>
|
||||
```
|
||||
You can download the script and use it locally, or from a local KaTeX installation instead.
|
||||
|
||||
For example, in the following simple page, we first load KaTeX as usual.
|
||||
Then, in the body, we use a `math/tex` script to typeset the equation `x+\sqrt{1-x^2}`.
|
||||
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.css" integrity="sha384-5TcZemv2l/9On385z///+d7MSYlvIEw9FuZTIdZ14vJLqWphw7e7ZPuOiCHJcFCP" crossorigin="anonymous">
|
||||
<script src="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.js" integrity="sha384-cMkvdD8LoxVzGF/RPUKAcvmm49FQ0oxwDF3BGKtDXcEc+T1b2N+teh/OJfpU0jr6" crossorigin="anonymous"></script>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/contrib/mathtex-script-type.min.js" integrity="sha384-sg4gBRJTqTCyzYbB7e72xGs3dA2LK994XRZS6urZW6Uh6Mu3j2JJ3YG2s9HALO8U" crossorigin="anonymous"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script type="math/tex">x+\sqrt{1-x^2}</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
ECMAScript module is also available:
|
||||
```html
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/contrib/mathtex-script-type.mjs" integrity="sha384-4EJvC5tvqq9XJxXvdD4JutBokuFw/dCe2AB4gZ9sRpwFFXECpL3qT43tmE0PkpVg" crossorigin="anonymous"></script>
|
||||
22
node_modules/katex/contrib/mathtex-script-type/mathtex-script-type.js
generated
vendored
Normal file
22
node_modules/katex/contrib/mathtex-script-type/mathtex-script-type.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
import katex from "katex";
|
||||
|
||||
let scripts = document.body.getElementsByTagName("script");
|
||||
scripts = Array.prototype.slice.call(scripts);
|
||||
scripts.forEach(function(script) {
|
||||
if (!script.type || !script.type.match(/math\/tex/i)) {
|
||||
return -1;
|
||||
}
|
||||
const display =
|
||||
(script.type.match(/mode\s*=\s*display(;|\s|\n|$)/) != null);
|
||||
|
||||
const katexElement = document.createElement(display ? "div" : "span");
|
||||
katexElement.setAttribute("class",
|
||||
display ? "equation" : "inline-equation");
|
||||
try {
|
||||
katex.render(script.text, katexElement, {displayMode: display});
|
||||
} catch (err) {
|
||||
//console.error(err); linter doesn't like this
|
||||
katexElement.textContent = script.text;
|
||||
}
|
||||
script.parentNode.replaceChild(katexElement, script);
|
||||
});
|
||||
23
node_modules/katex/contrib/mhchem/README.md
generated
vendored
Normal file
23
node_modules/katex/contrib/mhchem/README.md
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
# mhchem extension
|
||||
|
||||
This extension adds to KaTeX the `\ce` and `\pu` functions from the [mhchem](https://mhchem.github.io/MathJax-mhchem/) package.
|
||||
|
||||
### Usage
|
||||
|
||||
This extension isn't part of core KaTeX, so the script should be separately included. Write the following line into the HTML page's `<head>`. Place it *after* the line that calls `katex.js`, and if you make use of the [auto-render](https://katex.org/docs/autorender.html) extension, place it *before* the line that calls `auto-render.js`.
|
||||
|
||||
```html
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/contrib/mhchem.min.js" integrity="sha384-F2ptQFZqNJuqfGGl28mIXyQ5kXH48spn7rcoS0Y9psqIKAcZPLd1NzwFlm/bl1mH" crossorigin="anonymous"></script>
|
||||
```
|
||||
|
||||
If you remove the `defer` attribute from this tag, then you must also remove the `defer` attribute from the `<script src="https://../katex.min.js">` tag.
|
||||
|
||||
### Syntax
|
||||
|
||||
See the [mhchem Manual](https://mhchem.github.io/MathJax-mhchem/) for a full explanation of the input syntax, with working examples. The manual also includes a demonstration box.
|
||||
|
||||
Note that old versions of `mhchem.sty` used `\cf` for chemical formula and `\ce` for chemical equations, but `\cf` has been deprecated in place of `\ce`. This extension supports only `\ce`. You can define a macro mapping `\cf` to `\ce` if needed.
|
||||
|
||||
### Browser Support
|
||||
|
||||
This extension has been tested on Chrome, Firefox, Opera, and Edge.
|
||||
1695
node_modules/katex/contrib/mhchem/mhchem.js
generated
vendored
Normal file
1695
node_modules/katex/contrib/mhchem/mhchem.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
746
node_modules/katex/contrib/render-a11y-string/render-a11y-string.js
generated
vendored
Normal file
746
node_modules/katex/contrib/render-a11y-string/render-a11y-string.js
generated
vendored
Normal file
@@ -0,0 +1,746 @@
|
||||
// @flow
|
||||
/**
|
||||
* renderA11yString returns a readable string.
|
||||
*
|
||||
* In some cases the string will have the proper semantic math
|
||||
* meaning,:
|
||||
* renderA11yString("\\frac{1}{2}"")
|
||||
* -> "start fraction, 1, divided by, 2, end fraction"
|
||||
*
|
||||
* However, other cases do not:
|
||||
* renderA11yString("f(x) = x^2")
|
||||
* -> "f, left parenthesis, x, right parenthesis, equals, x, squared"
|
||||
*
|
||||
* The commas in the string aim to increase ease of understanding
|
||||
* when read by a screenreader.
|
||||
*/
|
||||
|
||||
// NOTE: since we're importing types here these files won't actually be
|
||||
// included in the build.
|
||||
import type {Atom} from "../../src/symbols";
|
||||
import type {AnyParseNode} from "../../src/parseNode";
|
||||
import type {SettingsOptions} from "../../src/Settings";
|
||||
|
||||
// $FlowIgnore: we import the types directly anyways
|
||||
import katex from "katex";
|
||||
|
||||
const stringMap = {
|
||||
"(": "left parenthesis",
|
||||
")": "right parenthesis",
|
||||
"[": "open bracket",
|
||||
"]": "close bracket",
|
||||
"\\{": "left brace",
|
||||
"\\}": "right brace",
|
||||
"\\lvert": "open vertical bar",
|
||||
"\\rvert": "close vertical bar",
|
||||
"|": "vertical bar",
|
||||
"\\uparrow": "up arrow",
|
||||
"\\Uparrow": "up arrow",
|
||||
"\\downarrow": "down arrow",
|
||||
"\\Downarrow": "down arrow",
|
||||
"\\updownarrow": "up down arrow",
|
||||
"\\leftarrow": "left arrow",
|
||||
"\\Leftarrow": "left arrow",
|
||||
"\\rightarrow": "right arrow",
|
||||
"\\Rightarrow": "right arrow",
|
||||
"\\langle": "open angle",
|
||||
"\\rangle": "close angle",
|
||||
"\\lfloor": "open floor",
|
||||
"\\rfloor": "close floor",
|
||||
"\\int": "integral",
|
||||
"\\intop": "integral",
|
||||
"\\lim": "limit",
|
||||
"\\ln": "natural log",
|
||||
"\\log": "log",
|
||||
"\\sin": "sine",
|
||||
"\\cos": "cosine",
|
||||
"\\tan": "tangent",
|
||||
"\\cot": "cotangent",
|
||||
"\\sum": "sum",
|
||||
"/": "slash",
|
||||
",": "comma",
|
||||
".": "point",
|
||||
"-": "negative",
|
||||
"+": "plus",
|
||||
"~": "tilde",
|
||||
":": "colon",
|
||||
"?": "question mark",
|
||||
"'": "apostrophe",
|
||||
"\\%": "percent",
|
||||
" ": "space",
|
||||
"\\ ": "space",
|
||||
"\\$": "dollar sign",
|
||||
"\\angle": "angle",
|
||||
"\\degree": "degree",
|
||||
"\\circ": "circle",
|
||||
"\\vec": "vector",
|
||||
"\\triangle": "triangle",
|
||||
"\\pi": "pi",
|
||||
"\\prime": "prime",
|
||||
"\\infty": "infinity",
|
||||
"\\alpha": "alpha",
|
||||
"\\beta": "beta",
|
||||
"\\gamma": "gamma",
|
||||
"\\omega": "omega",
|
||||
"\\theta": "theta",
|
||||
"\\sigma": "sigma",
|
||||
"\\lambda": "lambda",
|
||||
"\\tau": "tau",
|
||||
"\\Delta": "delta",
|
||||
"\\delta": "delta",
|
||||
"\\mu": "mu",
|
||||
"\\rho": "rho",
|
||||
"\\nabla": "del",
|
||||
"\\ell": "ell",
|
||||
"\\ldots": "dots",
|
||||
// TODO: add entries for all accents
|
||||
"\\hat": "hat",
|
||||
"\\acute": "acute",
|
||||
};
|
||||
|
||||
const powerMap = {
|
||||
"prime": "prime",
|
||||
"degree": "degrees",
|
||||
"circle": "degrees",
|
||||
"2": "squared",
|
||||
"3": "cubed",
|
||||
};
|
||||
|
||||
const openMap = {
|
||||
"|": "open vertical bar",
|
||||
".": "",
|
||||
};
|
||||
|
||||
const closeMap = {
|
||||
"|": "close vertical bar",
|
||||
".": "",
|
||||
};
|
||||
|
||||
const binMap = {
|
||||
"+": "plus",
|
||||
"-": "minus",
|
||||
"\\pm": "plus minus",
|
||||
"\\cdot": "dot",
|
||||
"*": "times",
|
||||
"/": "divided by",
|
||||
"\\times": "times",
|
||||
"\\div": "divided by",
|
||||
"\\circ": "circle",
|
||||
"\\bullet": "bullet",
|
||||
};
|
||||
|
||||
const relMap = {
|
||||
"=": "equals",
|
||||
"\\approx": "approximately equals",
|
||||
"≠": "does not equal",
|
||||
"\\geq": "is greater than or equal to",
|
||||
"\\ge": "is greater than or equal to",
|
||||
"\\leq": "is less than or equal to",
|
||||
"\\le": "is less than or equal to",
|
||||
">": "is greater than",
|
||||
"<": "is less than",
|
||||
"\\leftarrow": "left arrow",
|
||||
"\\Leftarrow": "left arrow",
|
||||
"\\rightarrow": "right arrow",
|
||||
"\\Rightarrow": "right arrow",
|
||||
":": "colon",
|
||||
};
|
||||
|
||||
const accentUnderMap = {
|
||||
"\\underleftarrow": "left arrow",
|
||||
"\\underrightarrow": "right arrow",
|
||||
"\\underleftrightarrow": "left-right arrow",
|
||||
"\\undergroup": "group",
|
||||
"\\underlinesegment": "line segment",
|
||||
"\\utilde": "tilde",
|
||||
};
|
||||
|
||||
type NestedArray<T> = Array<T | NestedArray<T>>;
|
||||
|
||||
const buildString = (
|
||||
str: string,
|
||||
type: Atom | "normal",
|
||||
a11yStrings: NestedArray<string>,
|
||||
) => {
|
||||
if (!str) {
|
||||
return;
|
||||
}
|
||||
|
||||
let ret;
|
||||
|
||||
if (type === "open") {
|
||||
ret = str in openMap ? openMap[str] : stringMap[str] || str;
|
||||
} else if (type === "close") {
|
||||
ret = str in closeMap ? closeMap[str] : stringMap[str] || str;
|
||||
} else if (type === "bin") {
|
||||
ret = binMap[str] || str;
|
||||
} else if (type === "rel") {
|
||||
ret = relMap[str] || str;
|
||||
} else {
|
||||
ret = stringMap[str] || str;
|
||||
}
|
||||
|
||||
// If the text to add is a number and there is already a string
|
||||
// in the list and the last string is a number then we should
|
||||
// combine them into a single number
|
||||
if (
|
||||
/^\d+$/.test(ret) &&
|
||||
a11yStrings.length > 0 &&
|
||||
// TODO(kevinb): check that the last item in a11yStrings is a string
|
||||
// I think we might be able to drop the nested arrays, which would make
|
||||
// this easier to type
|
||||
// $FlowFixMe
|
||||
/^\d+$/.test(a11yStrings[a11yStrings.length - 1])
|
||||
) {
|
||||
a11yStrings[a11yStrings.length - 1] += ret;
|
||||
} else if (ret) {
|
||||
a11yStrings.push(ret);
|
||||
}
|
||||
};
|
||||
|
||||
const buildRegion = (
|
||||
a11yStrings: NestedArray<string>,
|
||||
callback: (regionStrings: NestedArray<string>) => void,
|
||||
) => {
|
||||
const regionStrings: NestedArray<string> = [];
|
||||
a11yStrings.push(regionStrings);
|
||||
callback(regionStrings);
|
||||
};
|
||||
|
||||
const handleObject = (
|
||||
tree: AnyParseNode,
|
||||
a11yStrings: NestedArray<string>,
|
||||
atomType: Atom | "normal",
|
||||
) => {
|
||||
// Everything else is assumed to be an object...
|
||||
switch (tree.type) {
|
||||
case "accent": {
|
||||
buildRegion(a11yStrings, (a11yStrings) => {
|
||||
buildA11yStrings(tree.base, a11yStrings, atomType);
|
||||
a11yStrings.push("with");
|
||||
buildString(tree.label, "normal", a11yStrings);
|
||||
a11yStrings.push("on top");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "accentUnder": {
|
||||
buildRegion(a11yStrings, (a11yStrings) => {
|
||||
buildA11yStrings(tree.base, a11yStrings, atomType);
|
||||
a11yStrings.push("with");
|
||||
buildString(accentUnderMap[tree.label], "normal", a11yStrings);
|
||||
a11yStrings.push("underneath");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "accent-token": {
|
||||
// Used internally by accent symbols.
|
||||
break;
|
||||
}
|
||||
|
||||
case "atom": {
|
||||
const {text} = tree;
|
||||
switch (tree.family) {
|
||||
case "bin": {
|
||||
buildString(text, "bin", a11yStrings);
|
||||
break;
|
||||
}
|
||||
case "close": {
|
||||
buildString(text, "close", a11yStrings);
|
||||
break;
|
||||
}
|
||||
// TODO(kevinb): figure out what should be done for inner
|
||||
case "inner": {
|
||||
buildString(tree.text, "inner", a11yStrings);
|
||||
break;
|
||||
}
|
||||
case "open": {
|
||||
buildString(text, "open", a11yStrings);
|
||||
break;
|
||||
}
|
||||
case "punct": {
|
||||
buildString(text, "punct", a11yStrings);
|
||||
break;
|
||||
}
|
||||
case "rel": {
|
||||
buildString(text, "rel", a11yStrings);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
(tree.family: empty);
|
||||
throw new Error(`"${tree.family}" is not a valid atom type`);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "color": {
|
||||
const color = tree.color.replace(/katex-/, "");
|
||||
|
||||
buildRegion(a11yStrings, (regionStrings) => {
|
||||
regionStrings.push("start color " + color);
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end color " + color);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "color-token": {
|
||||
// Used by \color, \colorbox, and \fcolorbox but not directly rendered.
|
||||
// It's a leaf node and has no children so just break.
|
||||
break;
|
||||
}
|
||||
|
||||
case "delimsizing": {
|
||||
if (tree.delim && tree.delim !== ".") {
|
||||
buildString(tree.delim, "normal", a11yStrings);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "genfrac": {
|
||||
buildRegion(a11yStrings, (regionStrings) => {
|
||||
// genfrac can have unbalanced delimiters
|
||||
const {leftDelim, rightDelim} = tree;
|
||||
|
||||
// NOTE: Not sure if this is a safe assumption
|
||||
// hasBarLine true -> fraction, false -> binomial
|
||||
if (tree.hasBarLine) {
|
||||
regionStrings.push("start fraction");
|
||||
leftDelim && buildString(leftDelim, "open", regionStrings);
|
||||
buildA11yStrings(tree.numer, regionStrings, atomType);
|
||||
regionStrings.push("divided by");
|
||||
buildA11yStrings(tree.denom, regionStrings, atomType);
|
||||
rightDelim && buildString(rightDelim, "close", regionStrings);
|
||||
regionStrings.push("end fraction");
|
||||
} else {
|
||||
regionStrings.push("start binomial");
|
||||
leftDelim && buildString(leftDelim, "open", regionStrings);
|
||||
buildA11yStrings(tree.numer, regionStrings, atomType);
|
||||
regionStrings.push("over");
|
||||
buildA11yStrings(tree.denom, regionStrings, atomType);
|
||||
rightDelim && buildString(rightDelim, "close", regionStrings);
|
||||
regionStrings.push("end binomial");
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "hbox": {
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "kern": {
|
||||
// No op: we don't attempt to present kerning information
|
||||
// to the screen reader.
|
||||
break;
|
||||
}
|
||||
|
||||
case "leftright": {
|
||||
buildRegion(a11yStrings, (regionStrings) => {
|
||||
buildString(tree.left, "open", regionStrings);
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
buildString(tree.right, "close", regionStrings);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "leftright-right": {
|
||||
// TODO: double check that this is a no-op
|
||||
break;
|
||||
}
|
||||
|
||||
case "lap": {
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "mathord": {
|
||||
buildString(tree.text, "normal", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "op": {
|
||||
const {body, name} = tree;
|
||||
if (body) {
|
||||
buildA11yStrings(body, a11yStrings, atomType);
|
||||
} else if (name) {
|
||||
buildString(name, "normal", a11yStrings);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "op-token": {
|
||||
// Used internally by operator symbols.
|
||||
buildString(tree.text, atomType, a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "ordgroup": {
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "overline": {
|
||||
buildRegion(a11yStrings, function(a11yStrings) {
|
||||
a11yStrings.push("start overline");
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
a11yStrings.push("end overline");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "pmb": {
|
||||
a11yStrings.push("bold");
|
||||
break;
|
||||
}
|
||||
|
||||
case "phantom": {
|
||||
a11yStrings.push("empty space");
|
||||
break;
|
||||
}
|
||||
|
||||
case "raisebox": {
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "rule": {
|
||||
a11yStrings.push("rectangle");
|
||||
break;
|
||||
}
|
||||
|
||||
case "sizing": {
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "spacing": {
|
||||
a11yStrings.push("space");
|
||||
break;
|
||||
}
|
||||
|
||||
case "styling": {
|
||||
// We ignore the styling and just pass through the contents
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "sqrt": {
|
||||
buildRegion(a11yStrings, (regionStrings) => {
|
||||
const {body, index} = tree;
|
||||
if (index) {
|
||||
const indexString = flatten(
|
||||
buildA11yStrings(index, [], atomType)).join(",");
|
||||
if (indexString === "3") {
|
||||
regionStrings.push("cube root of");
|
||||
buildA11yStrings(body, regionStrings, atomType);
|
||||
regionStrings.push("end cube root");
|
||||
return;
|
||||
}
|
||||
|
||||
regionStrings.push("root");
|
||||
regionStrings.push("start index");
|
||||
buildA11yStrings(index, regionStrings, atomType);
|
||||
regionStrings.push("end index");
|
||||
return;
|
||||
}
|
||||
|
||||
regionStrings.push("square root of");
|
||||
buildA11yStrings(body, regionStrings, atomType);
|
||||
regionStrings.push("end square root");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "supsub": {
|
||||
const {base, sub, sup} = tree;
|
||||
let isLog = false;
|
||||
|
||||
if (base) {
|
||||
buildA11yStrings(base, a11yStrings, atomType);
|
||||
isLog = base.type === "op" && base.name === "\\log";
|
||||
}
|
||||
|
||||
if (sub) {
|
||||
const regionName = isLog ? "base" : "subscript";
|
||||
buildRegion(a11yStrings, function(regionStrings) {
|
||||
regionStrings.push(`start ${regionName}`);
|
||||
buildA11yStrings(sub, regionStrings, atomType);
|
||||
regionStrings.push(`end ${regionName}`);
|
||||
});
|
||||
}
|
||||
|
||||
if (sup) {
|
||||
buildRegion(a11yStrings, function(regionStrings) {
|
||||
const supString = flatten(
|
||||
buildA11yStrings(sup, [], atomType)).join(",");
|
||||
|
||||
if (supString in powerMap) {
|
||||
regionStrings.push(powerMap[supString]);
|
||||
return;
|
||||
}
|
||||
|
||||
regionStrings.push("start superscript");
|
||||
buildA11yStrings(sup, regionStrings, atomType);
|
||||
regionStrings.push("end superscript");
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "text": {
|
||||
// TODO: handle other fonts
|
||||
if (tree.font === "\\textbf") {
|
||||
buildRegion(a11yStrings, function(regionStrings) {
|
||||
regionStrings.push("start bold text");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end bold text");
|
||||
});
|
||||
break;
|
||||
}
|
||||
buildRegion(a11yStrings, function(regionStrings) {
|
||||
regionStrings.push("start text");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end text");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "textord": {
|
||||
buildString(tree.text, atomType, a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "smash": {
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "enclose": {
|
||||
// TODO: create a map for these.
|
||||
// TODO: differentiate between a body with a single atom, e.g.
|
||||
// "cancel a" instead of "start cancel, a, end cancel"
|
||||
if (/cancel/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function(regionStrings) {
|
||||
regionStrings.push("start cancel");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end cancel");
|
||||
});
|
||||
break;
|
||||
} else if (/box/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function(regionStrings) {
|
||||
regionStrings.push("start box");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end box");
|
||||
});
|
||||
break;
|
||||
} else if (/sout/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function(regionStrings) {
|
||||
regionStrings.push("start strikeout");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end strikeout");
|
||||
});
|
||||
break;
|
||||
} else if (/phase/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function(regionStrings) {
|
||||
regionStrings.push("start phase angle");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end phase angle");
|
||||
});
|
||||
break;
|
||||
}
|
||||
throw new Error(
|
||||
`KaTeX-a11y: enclose node with ${tree.label} not supported yet`);
|
||||
}
|
||||
|
||||
case "vcenter": {
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "vphantom": {
|
||||
throw new Error("KaTeX-a11y: vphantom not implemented yet");
|
||||
}
|
||||
|
||||
case "hphantom": {
|
||||
throw new Error("KaTeX-a11y: hphantom not implemented yet");
|
||||
}
|
||||
|
||||
case "operatorname": {
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "array": {
|
||||
throw new Error("KaTeX-a11y: array not implemented yet");
|
||||
}
|
||||
|
||||
case "raw": {
|
||||
throw new Error("KaTeX-a11y: raw not implemented yet");
|
||||
}
|
||||
|
||||
case "size": {
|
||||
// Although there are nodes of type "size" in the parse tree, they have
|
||||
// no semantic meaning and should be ignored.
|
||||
break;
|
||||
}
|
||||
|
||||
case "url": {
|
||||
throw new Error("KaTeX-a11y: url not implemented yet");
|
||||
}
|
||||
|
||||
case "tag": {
|
||||
throw new Error("KaTeX-a11y: tag not implemented yet");
|
||||
}
|
||||
|
||||
case "verb": {
|
||||
buildString(`start verbatim`, "normal", a11yStrings);
|
||||
buildString(tree.body, "normal", a11yStrings);
|
||||
buildString(`end verbatim`, "normal", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "environment": {
|
||||
throw new Error("KaTeX-a11y: environment not implemented yet");
|
||||
}
|
||||
|
||||
case "horizBrace": {
|
||||
buildString(`start ${tree.label.slice(1)}`, "normal", a11yStrings);
|
||||
buildA11yStrings(tree.base, a11yStrings, atomType);
|
||||
buildString(`end ${tree.label.slice(1)}`, "normal", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "infix": {
|
||||
// All infix nodes are replace with other nodes.
|
||||
break;
|
||||
}
|
||||
|
||||
case "includegraphics": {
|
||||
throw new Error("KaTeX-a11y: includegraphics not implemented yet");
|
||||
}
|
||||
|
||||
case "font": {
|
||||
// TODO: callout the start/end of specific fonts
|
||||
// TODO: map \BBb{N} to "the naturals" or something like that
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "href": {
|
||||
throw new Error("KaTeX-a11y: href not implemented yet");
|
||||
}
|
||||
|
||||
case "cr": {
|
||||
// This is used by environments.
|
||||
throw new Error("KaTeX-a11y: cr not implemented yet");
|
||||
}
|
||||
|
||||
case "underline": {
|
||||
buildRegion(a11yStrings, function(a11yStrings) {
|
||||
a11yStrings.push("start underline");
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
a11yStrings.push("end underline");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "xArrow": {
|
||||
throw new Error("KaTeX-a11y: xArrow not implemented yet");
|
||||
}
|
||||
|
||||
case "cdlabel": {
|
||||
throw new Error("KaTeX-a11y: cdlabel not implemented yet");
|
||||
}
|
||||
|
||||
case "cdlabelparent": {
|
||||
throw new Error("KaTeX-a11y: cdlabelparent not implemented yet");
|
||||
}
|
||||
|
||||
case "mclass": {
|
||||
// \neq and \ne are macros so we let "htmlmathml" render the mathmal
|
||||
// side of things and extract the text from that.
|
||||
const atomType = tree.mclass.slice(1);
|
||||
// $FlowFixMe: drop the leading "m" from the values in mclass
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "mathchoice": {
|
||||
// TODO: track which style we're using, e.g. display, text, etc.
|
||||
// default to text style if even that may not be the correct style
|
||||
buildA11yStrings(tree.text, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "htmlmathml": {
|
||||
buildA11yStrings(tree.mathml, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "middle": {
|
||||
buildString(tree.delim, atomType, a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "internal": {
|
||||
// internal nodes are never included in the parse tree
|
||||
break;
|
||||
}
|
||||
|
||||
case "html": {
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
(tree.type: empty);
|
||||
throw new Error("KaTeX a11y un-recognized type: " + tree.type);
|
||||
}
|
||||
};
|
||||
|
||||
const buildA11yStrings = (
|
||||
tree: AnyParseNode | AnyParseNode[],
|
||||
a11yStrings: NestedArray<string> = [],
|
||||
atomType: Atom | "normal",
|
||||
) => {
|
||||
if (tree instanceof Array) {
|
||||
for (let i = 0; i < tree.length; i++) {
|
||||
buildA11yStrings(tree[i], a11yStrings, atomType);
|
||||
}
|
||||
} else {
|
||||
handleObject(tree, a11yStrings, atomType);
|
||||
}
|
||||
|
||||
return a11yStrings;
|
||||
};
|
||||
|
||||
|
||||
const flatten = function(array) {
|
||||
let result = [];
|
||||
|
||||
array.forEach(function(item) {
|
||||
if (item instanceof Array) {
|
||||
result = result.concat(flatten(item));
|
||||
} else {
|
||||
result.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const renderA11yString = function(
|
||||
text: string,
|
||||
settings?: SettingsOptions,
|
||||
): string {
|
||||
|
||||
const tree = katex.__parse(text, settings);
|
||||
const a11yStrings = buildA11yStrings(tree, [], "normal");
|
||||
return flatten(a11yStrings).join(", ");
|
||||
};
|
||||
|
||||
export default renderA11yString;
|
||||
549
node_modules/katex/contrib/render-a11y-string/test/render-a11y-string-spec.js
generated
vendored
Normal file
549
node_modules/katex/contrib/render-a11y-string/test/render-a11y-string-spec.js
generated
vendored
Normal file
@@ -0,0 +1,549 @@
|
||||
/* eslint-disable max-len */
|
||||
// @flow
|
||||
import renderA11yString from "../render-a11y-string";
|
||||
|
||||
describe("renderA11yString", () => {
|
||||
describe("basic expressions", () => {
|
||||
test("simple addition", () => {
|
||||
const result = renderA11yString("1 + 2");
|
||||
expect(result).toMatchInlineSnapshot(`"1, plus, 2"`);
|
||||
});
|
||||
});
|
||||
|
||||
describe("accent", () => {
|
||||
test("\\vec", () => {
|
||||
const result = renderA11yString("\\vec{a}");
|
||||
expect(result).toMatchInlineSnapshot(`"a, with, vector, on top"`);
|
||||
});
|
||||
|
||||
test("\\acute{a}", () => {
|
||||
const result = renderA11yString("\\acute{a}");
|
||||
expect(result).toMatchInlineSnapshot(`"a, with, acute, on top"`);
|
||||
});
|
||||
|
||||
test("\\hat{a}", () => {
|
||||
const result = renderA11yString("\\hat{a}");
|
||||
expect(result).toMatchInlineSnapshot(`"a, with, hat, on top"`);
|
||||
});
|
||||
});
|
||||
|
||||
describe("accentUnder", () => {
|
||||
test("\\underleftarrow", () => {
|
||||
const result = renderA11yString("\\underleftarrow{1+2}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"1, plus, 2, with, left arrow, underneath"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("\\underlinesegment", () => {
|
||||
const result = renderA11yString("\\underlinesegment{1+2}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"1, plus, 2, with, line segment, underneath"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("atom", () => {
|
||||
test("punct", () => {
|
||||
const result = renderA11yString("1, 2, 3");
|
||||
expect(result).toMatchInlineSnapshot(`"1, comma, 2, comma, 3"`);
|
||||
});
|
||||
});
|
||||
|
||||
describe("color", () => {
|
||||
test("\\color{red}", () => {
|
||||
const result = renderA11yString("\\color{red}1+2");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start color red, 1, plus, 2, end color red"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("\\color{FF0000}", () => {
|
||||
const result = renderA11yString("\\color{FF0000}1+2");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start color #FF0000, 1, plus, 2, end color #FF0000"`,
|
||||
);
|
||||
});
|
||||
|
||||
// colorIsTextColor is an option added in KaTeX 0.9.0 for backward
|
||||
// compatibility. It makes \color parse like \textcolor. We use it
|
||||
// in the KA webapp, and need it here because the tests are written
|
||||
// assuming it is set.
|
||||
test("\\color{red} with {colorIsTextColor: true}", () => {
|
||||
const result = renderA11yString("\\color{red}1+2", {
|
||||
colorIsTextColor: true,
|
||||
});
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start color red, 1, end color red, plus, 2"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("\\textcolor{red}", () => {
|
||||
const result = renderA11yString("\\textcolor{red}1+2");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start color red, 1, end color red, plus, 2"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("delimiters", () => {
|
||||
test("simple parens", () => {
|
||||
const result = renderA11yString("(1 + 3)");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"left parenthesis, 1, plus, 3, right parenthesis"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("simple brackets", () => {
|
||||
const result = renderA11yString("[1 + 3]");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"open bracket, 1, plus, 3, close bracket"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("nested parens", () => {
|
||||
const result = renderA11yString("(a + (b + c))");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"left parenthesis, a, plus, left parenthesis, b, plus, c, right parenthesis, right parenthesis"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("stretchy parens around fractions", () => {
|
||||
const result = renderA11yString("\\left(\\frac{1}{x}\\right)");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"left parenthesis, start fraction, 1, divided by, x, end fraction, right parenthesis"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("delimsizing", () => {
|
||||
test("\\bigl(1+2\\bigr)", () => {
|
||||
const result = renderA11yString("\\bigl(1+2\\bigr)");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"left parenthesis, 1, plus, 2, right parenthesis"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("enclose", () => {
|
||||
test("\\cancel", () => {
|
||||
const result = renderA11yString("\\cancel{a}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start cancel, a, end cancel"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("\\fbox", () => {
|
||||
const result = renderA11yString("\\fbox{a}");
|
||||
expect(result).toMatchInlineSnapshot(`"start box, a, end box"`);
|
||||
});
|
||||
|
||||
test("\\boxed", () => {
|
||||
const result = renderA11yString("\\boxed{a}");
|
||||
expect(result).toMatchInlineSnapshot(`"start box, a, end box"`);
|
||||
});
|
||||
|
||||
test("\\sout", () => {
|
||||
const result = renderA11yString("\\sout{a}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start strikeout, a, end strikeout"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("phase", () => {
|
||||
test("\\phase", () => {
|
||||
const result = renderA11yString("\\phase{a}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start phase angle, a, end phase angle"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("exponents", () => {
|
||||
test("simple exponent", () => {
|
||||
const result = renderA11yString("e^x");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"e, start superscript, x, end superscript"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("^{\\circ} => degrees", () => {
|
||||
const result = renderA11yString("90^{\\circ}");
|
||||
expect(result).toMatchInlineSnapshot(`"90, degrees"`);
|
||||
});
|
||||
|
||||
test("^{\\degree} => degrees", () => {
|
||||
const result = renderA11yString("90^{\\degree}");
|
||||
expect(result).toMatchInlineSnapshot(`"90, degrees"`);
|
||||
});
|
||||
|
||||
test("^{\\prime} => prime", () => {
|
||||
const result = renderA11yString("f^{\\prime}");
|
||||
expect(result).toMatchInlineSnapshot(`"f, prime"`);
|
||||
});
|
||||
|
||||
test("^2 => squared", () => {
|
||||
const result = renderA11yString("x^2");
|
||||
expect(result).toMatchInlineSnapshot(`"x, squared"`);
|
||||
});
|
||||
|
||||
test("^3 => cubed", () => {
|
||||
const result = renderA11yString("x^3");
|
||||
expect(result).toMatchInlineSnapshot(`"x, cubed"`);
|
||||
});
|
||||
|
||||
test("log_2", () => {
|
||||
const result = renderA11yString("\\log_2{x+1}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"log, start base, 2, end base, x, plus, 1"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("a_{n+1}", () => {
|
||||
const result = renderA11yString("a_{n+1}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"a, start subscript, n, plus, 1, end subscript"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("genfrac", () => {
|
||||
test("simple fractions", () => {
|
||||
const result = renderA11yString("\\frac{2}{3}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start fraction, 2, divided by, 3, end fraction"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("nested fractions", () => {
|
||||
const result = renderA11yString("\\frac{1}{1+\\frac{1}{x}}");
|
||||
// TODO: this result is ambiguous, we need to fix this
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start fraction, 1, divided by, 1, plus, start fraction, 1, divided by, x, end fraction, end fraction"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("binomials", () => {
|
||||
const result = renderA11yString("\\binom{n}{k}");
|
||||
// TODO: drop the parenthesis as they're not normally read
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start binomial, left parenthesis, n, over, k, right parenthesis, end binomial"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("horizBrace", () => {
|
||||
test("\\overbrace", () => {
|
||||
const result = renderA11yString("\\overbrace{1+2}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start overbrace, 1, plus, 2, end overbrace"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("\\underbrace", () => {
|
||||
const result = renderA11yString("\\underbrace{1+2}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start underbrace, 1, plus, 2, end underbrace"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("infix", () => {
|
||||
test("\\over", () => {
|
||||
const result = renderA11yString("a \\over b");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start fraction, a, divided by, b, end fraction"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("\\choose", () => {
|
||||
const result = renderA11yString("a \\choose b");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start binomial, left parenthesis, a, over, b, right parenthesis, end binomial"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("\\above", () => {
|
||||
const result = renderA11yString("a \\above{2pt} b");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start fraction, a, divided by, b, end fraction"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("hbox", () => {
|
||||
test("\\hbox", () => {
|
||||
const result = renderA11yString("x+\\hbox{y}");
|
||||
expect(result).toMatchInlineSnapshot(`"x, plus, y"`);
|
||||
});
|
||||
});
|
||||
|
||||
describe("inner", () => {
|
||||
test("\\ldots", () => {
|
||||
const result = renderA11yString("\\ldots");
|
||||
expect(result).toMatchInlineSnapshot(`"dots"`);
|
||||
});
|
||||
});
|
||||
|
||||
describe("lap", () => {
|
||||
test("\\llap", () => {
|
||||
const result = renderA11yString("a\\llap{b}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"a, start text, b, end text"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("\\rlap", () => {
|
||||
const result = renderA11yString("a\\rlap{b}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"a, start text, b, end text"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("middle", () => {
|
||||
test("\\middle", () => {
|
||||
const result = renderA11yString("\\left(a\\middle|b\\right)");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"left parenthesis, a, vertical bar, b, right parenthesis"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("mod", () => {
|
||||
test("\\mod", () => {
|
||||
const result = renderA11yString("\\mod{23}");
|
||||
// TODO: drop the "space"
|
||||
// TODO: collate m, o, d... we should fix this inside of KaTeX since
|
||||
// this affects the HTML and MathML output as well
|
||||
expect(result).toMatchInlineSnapshot(`"space, m, o, d, 23"`);
|
||||
});
|
||||
});
|
||||
|
||||
describe("op", () => {
|
||||
test("\\lim", () => {
|
||||
const result = renderA11yString("\\lim{x+1}");
|
||||
// TODO: add begin/end to track argument of operators
|
||||
expect(result).toMatchInlineSnapshot(`"limit, x, plus, 1"`);
|
||||
});
|
||||
|
||||
test("\\sin 2\\pi", () => {
|
||||
const result = renderA11yString("\\sin{2\\pi}");
|
||||
// TODO: add begin/end to track argument of operators
|
||||
expect(result).toMatchInlineSnapshot(`"sine, 2, pi"`);
|
||||
});
|
||||
|
||||
test("\\sum_{i=0}", () => {
|
||||
const result = renderA11yString("\\sum_{i=0}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"sum, start subscript, i, equals, 0, end subscript"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("\u2211_{i=0}", () => {
|
||||
const result = renderA11yString("\u2211_{i=0}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"sum, start subscript, i, equals, 0, end subscript"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("operatorname", () => {
|
||||
test("\\limsup", () => {
|
||||
const result = renderA11yString("\\limsup");
|
||||
// TODO: collate strings so that this is "lim, sup"
|
||||
// NOTE: this also affect HTML and MathML output
|
||||
expect(result).toMatchInlineSnapshot(`"l, i, m, s, u, p"`);
|
||||
});
|
||||
|
||||
test("\\liminf", () => {
|
||||
const result = renderA11yString("\\liminf");
|
||||
expect(result).toMatchInlineSnapshot(`"l, i, m, i, n, f"`);
|
||||
});
|
||||
|
||||
test("\\argmin", () => {
|
||||
const result = renderA11yString("\\argmin");
|
||||
expect(result).toMatchInlineSnapshot(`"a, r, g, m, i, n"`);
|
||||
});
|
||||
});
|
||||
|
||||
describe("overline", () => {
|
||||
test("\\overline", () => {
|
||||
const result = renderA11yString("\\overline{1+2}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start overline, 1, plus, 2, end overline"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("phantom", () => {
|
||||
test("\\phantom", () => {
|
||||
const result = renderA11yString("1+\\phantom{2}");
|
||||
expect(result).toMatchInlineSnapshot(`"1, plus, empty space"`);
|
||||
});
|
||||
});
|
||||
|
||||
describe("raisebox", () => {
|
||||
test("\\raisebox", () => {
|
||||
const result = renderA11yString("x+\\raisebox{1em}{y}");
|
||||
expect(result).toMatchInlineSnapshot(`"x, plus, y"`);
|
||||
});
|
||||
});
|
||||
|
||||
describe("relations", () => {
|
||||
test("1 \\neq 2", () => {
|
||||
const result = renderA11yString("1 \\neq 2");
|
||||
expect(result).toMatchInlineSnapshot(`"1, does not equal, 2"`);
|
||||
});
|
||||
|
||||
test("1 \\ne 2", () => {
|
||||
const result = renderA11yString("1 \\ne 2");
|
||||
expect(result).toMatchInlineSnapshot(`"1, does not equal, 2"`);
|
||||
});
|
||||
|
||||
test("1 \\geq 2", () => {
|
||||
const result = renderA11yString("1 \\geq 2");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"1, is greater than or equal to, 2"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("1 \\ge 2", () => {
|
||||
const result = renderA11yString("1 \\ge 2");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"1, is greater than or equal to, 2"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("1 \\leq 2", () => {
|
||||
const result = renderA11yString("1 \\leq 3");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"1, is less than or equal to, 3"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("1 \\le 2", () => {
|
||||
const result = renderA11yString("1 \\le 3");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"1, is less than or equal to, 3"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("rule", () => {
|
||||
test("\\rule", () => {
|
||||
const result = renderA11yString("\\rule{1em}{1em}");
|
||||
expect(result).toMatchInlineSnapshot(`"rectangle"`);
|
||||
});
|
||||
});
|
||||
|
||||
describe("smash", () => {
|
||||
test("1 + \\smash{2}", () => {
|
||||
const result = renderA11yString("1 + \\smash{2}");
|
||||
expect(result).toMatchInlineSnapshot(`"1, plus, 2"`);
|
||||
});
|
||||
});
|
||||
|
||||
describe("sqrt", () => {
|
||||
test("square root", () => {
|
||||
const result = renderA11yString("\\sqrt{x + 1}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"square root of, x, plus, 1, end square root"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("nest square root", () => {
|
||||
const result = renderA11yString("\\sqrt{x + \\sqrt{y}}");
|
||||
// TODO: this sounds ambiguous as well... we should probably say "start square root"
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"square root of, x, plus, square root of, y, end square root, end square root"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("cube root", () => {
|
||||
const result = renderA11yString("\\sqrt[3]{x + 1}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"cube root of, x, plus, 1, end cube root"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("nth root", () => {
|
||||
const result = renderA11yString("\\sqrt[n]{x + 1}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"root, start index, n, end index"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("sizing", () => {
|
||||
test("\\Huge is ignored", () => {
|
||||
const result = renderA11yString("\\Huge{a+b}");
|
||||
expect(result).toMatchInlineSnapshot(`"a, plus, b"`);
|
||||
});
|
||||
|
||||
test("\\small is ignored", () => {
|
||||
const result = renderA11yString("\\small{a+b}");
|
||||
expect(result).toMatchInlineSnapshot(`"a, plus, b"`);
|
||||
});
|
||||
|
||||
// We don't need to test all sizing commands since all style
|
||||
// nodes are treated in the same way.
|
||||
});
|
||||
|
||||
describe("styling", () => {
|
||||
test("\\displaystyle is ignored", () => {
|
||||
const result = renderA11yString("\\displaystyle{a+b}");
|
||||
expect(result).toMatchInlineSnapshot(`"a, plus, b"`);
|
||||
});
|
||||
|
||||
test("\\textstyle is ignored", () => {
|
||||
const result = renderA11yString("\\textstyle{a+b}");
|
||||
expect(result).toMatchInlineSnapshot(`"a, plus, b"`);
|
||||
});
|
||||
|
||||
// We don't need to test all styling commands since all style
|
||||
// nodes are treated in the same way.
|
||||
});
|
||||
|
||||
describe("text", () => {
|
||||
test("\\text", () => {
|
||||
const result = renderA11yString("\\text{hello}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start text, h, e, l, l, o, end text"`,
|
||||
);
|
||||
});
|
||||
|
||||
test("\\textbf", () => {
|
||||
const result = renderA11yString("\\textbf{hello}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start bold text, h, e, l, l, o, end bold text"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("underline", () => {
|
||||
test("\\underline", () => {
|
||||
const result = renderA11yString("\\underline{1+2}");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start underline, 1, plus, 2, end underline"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("vcenter", () => {
|
||||
test("\\vcenter", () => {
|
||||
const result = renderA11yString("x+\\vcenter{y}");
|
||||
expect(result).toMatchInlineSnapshot(`"x, plus, y"`);
|
||||
});
|
||||
});
|
||||
|
||||
describe("verb", () => {
|
||||
test("\\verb", () => {
|
||||
const result = renderA11yString("\\verb|hello|");
|
||||
expect(result).toMatchInlineSnapshot(
|
||||
`"start verbatim, hello, end verbatim"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
125
node_modules/katex/dist/README.md
generated
vendored
Normal file
125
node_modules/katex/dist/README.md
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
<h1><a href="https://katex.org/">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://katex.org/img/katex-logo.svg">
|
||||
<img alt="KaTeX" width=130 src="https://katex.org/img/katex-logo-black.svg">
|
||||
</picture>
|
||||
</a></h1>
|
||||
|
||||
[](https://www.npmjs.com/package/katex)
|
||||
[](https://github.com/semantic-release/semantic-release)
|
||||
[](https://github.com/KaTeX/KaTeX/actions?query=workflow%3ACI)
|
||||
[](https://codecov.io/gh/KaTeX/KaTeX)
|
||||
[](https://github.com/KaTeX/KaTeX/discussions)
|
||||
[](https://www.jsdelivr.com/package/npm/katex)
|
||||

|
||||
[](https://gitpod.io/#https://github.com/KaTeX/KaTeX)
|
||||
[](https://opencollective.com/katex)
|
||||
|
||||
KaTeX is a fast, easy-to-use JavaScript library for TeX math rendering on the web.
|
||||
|
||||
* **Fast:** KaTeX renders its math synchronously and doesn't need to reflow the page. See how it compares to a competitor in [this speed test](https://www.intmath.com/cg5/katex-mathjax-comparison.php).
|
||||
* **Print quality:** KaTeX's layout is based on Donald Knuth's TeX, the gold standard for math typesetting.
|
||||
* **Self contained:** KaTeX has no dependencies and can easily be bundled with your website resources.
|
||||
* **Server side rendering:** KaTeX produces the same output regardless of browser or environment, so you can pre-render expressions using Node.js and send them as plain HTML.
|
||||
|
||||
KaTeX is compatible with all major browsers, including Chrome, Safari, Firefox, Opera, Edge, and IE 11.
|
||||
|
||||
KaTeX supports much (but not all) of LaTeX and many LaTeX packages. See the [list of supported functions](https://katex.org/docs/supported.html).
|
||||
|
||||
Try out KaTeX [on the demo page](https://katex.org/#demo)!
|
||||
|
||||
## Getting started
|
||||
|
||||
### Starter template
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<!-- KaTeX requires the use of the HTML5 doctype. Without it, KaTeX may not render properly -->
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.css" integrity="sha384-5TcZemv2l/9On385z///+d7MSYlvIEw9FuZTIdZ14vJLqWphw7e7ZPuOiCHJcFCP" crossorigin="anonymous">
|
||||
|
||||
<!-- The loading of KaTeX is deferred to speed up page rendering -->
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.js" integrity="sha384-cMkvdD8LoxVzGF/RPUKAcvmm49FQ0oxwDF3BGKtDXcEc+T1b2N+teh/OJfpU0jr6" crossorigin="anonymous"></script>
|
||||
|
||||
<!-- To automatically render math in text elements, include the auto-render extension: -->
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/contrib/auto-render.min.js" integrity="sha384-hCXGrW6PitJEwbkoStFjeJxv+fSOOQKOPbJxSfM6G5sWZjAyWhXiTIIAmQqnlLlh" crossorigin="anonymous"
|
||||
onload="renderMathInElement(document.body);"></script>
|
||||
</head>
|
||||
...
|
||||
</html>
|
||||
```
|
||||
|
||||
You can also [download KaTeX](https://github.com/KaTeX/KaTeX/releases) and host it yourself.
|
||||
|
||||
For details on how to configure auto-render extension, refer to [the documentation](https://katex.org/docs/autorender.html).
|
||||
|
||||
### API
|
||||
|
||||
Call `katex.render` to render a TeX expression directly into a DOM element.
|
||||
For example:
|
||||
|
||||
```js
|
||||
katex.render("c = \\pm\\sqrt{a^2 + b^2}", element, {
|
||||
throwOnError: false
|
||||
});
|
||||
```
|
||||
|
||||
Call `katex.renderToString` to generate an HTML string of the rendered math,
|
||||
e.g., for server-side rendering. For example:
|
||||
|
||||
```js
|
||||
var html = katex.renderToString("c = \\pm\\sqrt{a^2 + b^2}", {
|
||||
throwOnError: false
|
||||
});
|
||||
// '<span class="katex">...</span>'
|
||||
```
|
||||
|
||||
Make sure to include the CSS and font files in both cases.
|
||||
If you are doing all rendering on the server, there is no need to include the
|
||||
JavaScript on the client.
|
||||
|
||||
The examples above use the `throwOnError: false` option, which renders invalid
|
||||
inputs as the TeX source code in red (by default), with the error message as
|
||||
hover text. For other available options, see the
|
||||
[API documentation](https://katex.org/docs/api.html),
|
||||
[options documentation](https://katex.org/docs/options.html), and
|
||||
[handling errors documentation](https://katex.org/docs/error.html).
|
||||
|
||||
## Demo and Documentation
|
||||
|
||||
Learn more about using KaTeX [on the website](https://katex.org)!
|
||||
|
||||
## Contributors
|
||||
|
||||
### Code Contributors
|
||||
|
||||
This project exists thanks to all the people who contribute code. If you'd like to help, see [our guide to contributing code](CONTRIBUTING.md).
|
||||
<a href="https://github.com/KaTeX/KaTeX/graphs/contributors"><img src="https://contributors-svg.opencollective.com/katex/contributors.svg?width=890&button=false" alt="Code contributors" /></a>
|
||||
|
||||
### Financial Contributors
|
||||
|
||||
Become a financial contributor and help us sustain our community.
|
||||
|
||||
#### Individuals
|
||||
|
||||
<a href="https://opencollective.com/katex"><img src="https://opencollective.com/katex/individuals.svg?width=890" alt="Contribute on Open Collective"></a>
|
||||
|
||||
#### Organizations
|
||||
|
||||
Support this project with your organization. Your logo will show up here with a link to your website.
|
||||
|
||||
<a href="https://opencollective.com/katex/organization/0/website"><img src="https://opencollective.com/katex/organization/0/avatar.svg" alt="Organization 1"></a>
|
||||
<a href="https://opencollective.com/katex/organization/1/website"><img src="https://opencollective.com/katex/organization/1/avatar.svg" alt="Organization 2"></a>
|
||||
<a href="https://opencollective.com/katex/organization/2/website"><img src="https://opencollective.com/katex/organization/2/avatar.svg" alt="Organization 3"></a>
|
||||
<a href="https://opencollective.com/katex/organization/3/website"><img src="https://opencollective.com/katex/organization/3/avatar.svg" alt="Organization 4"></a>
|
||||
<a href="https://opencollective.com/katex/organization/4/website"><img src="https://opencollective.com/katex/organization/4/avatar.svg" alt="Organization 5"></a>
|
||||
<a href="https://opencollective.com/katex/organization/5/website"><img src="https://opencollective.com/katex/organization/5/avatar.svg" alt="Organization 6"></a>
|
||||
<a href="https://opencollective.com/katex/organization/6/website"><img src="https://opencollective.com/katex/organization/6/avatar.svg" alt="Organization 7"></a>
|
||||
<a href="https://opencollective.com/katex/organization/7/website"><img src="https://opencollective.com/katex/organization/7/avatar.svg" alt="Organization 8"></a>
|
||||
<a href="https://opencollective.com/katex/organization/8/website"><img src="https://opencollective.com/katex/organization/8/avatar.svg" alt="Organization 9"></a>
|
||||
<a href="https://opencollective.com/katex/organization/9/website"><img src="https://opencollective.com/katex/organization/9/avatar.svg" alt="Organization 10"></a>
|
||||
|
||||
## License
|
||||
|
||||
KaTeX is licensed under the [MIT License](https://opensource.org/licenses/MIT).
|
||||
338
node_modules/katex/dist/contrib/auto-render.js
generated
vendored
Normal file
338
node_modules/katex/dist/contrib/auto-render.js
generated
vendored
Normal file
@@ -0,0 +1,338 @@
|
||||
(function webpackUniversalModuleDefinition(root, factory) {
|
||||
if(typeof exports === 'object' && typeof module === 'object')
|
||||
module.exports = factory(require("katex"));
|
||||
else if(typeof define === 'function' && define.amd)
|
||||
define(["katex"], factory);
|
||||
else if(typeof exports === 'object')
|
||||
exports["renderMathInElement"] = factory(require("katex"));
|
||||
else
|
||||
root["renderMathInElement"] = factory(root["katex"]);
|
||||
})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__757__) {
|
||||
return /******/ (function() { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ 757:
|
||||
/***/ (function(module) {
|
||||
|
||||
module.exports = __WEBPACK_EXTERNAL_MODULE__757__;
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ var __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
||||
/******/ if (cachedModule !== undefined) {
|
||||
/******/ return cachedModule.exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/************************************************************************/
|
||||
/******/ /* webpack/runtime/compat get default export */
|
||||
/******/ !function() {
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function() { return module['default']; } :
|
||||
/******/ function() { return module; };
|
||||
/******/ __webpack_require__.d(getter, { a: getter });
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/define property getters */
|
||||
/******/ !function() {
|
||||
/******/ // define getter functions for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, definition) {
|
||||
/******/ for(var key in definition) {
|
||||
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
||||
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
|
||||
/******/ }();
|
||||
/******/
|
||||
/************************************************************************/
|
||||
var __webpack_exports__ = {};
|
||||
|
||||
// EXPORTS
|
||||
__webpack_require__.d(__webpack_exports__, {
|
||||
"default": function() { return /* binding */ auto_render; }
|
||||
});
|
||||
|
||||
// EXTERNAL MODULE: external "katex"
|
||||
var external_katex_ = __webpack_require__(757);
|
||||
var external_katex_default = /*#__PURE__*/__webpack_require__.n(external_katex_);
|
||||
;// CONCATENATED MODULE: ./contrib/auto-render/splitAtDelimiters.js
|
||||
/* eslint no-constant-condition:0 */
|
||||
const findEndOfMath = function (delimiter, text, startIndex) {
|
||||
// Adapted from
|
||||
// https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
|
||||
let index = startIndex;
|
||||
let braceLevel = 0;
|
||||
const delimLength = delimiter.length;
|
||||
|
||||
while (index < text.length) {
|
||||
const 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;
|
||||
};
|
||||
|
||||
const escapeRegex = function (string) {
|
||||
return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
||||
};
|
||||
|
||||
const amsRegex = /^\\begin{/;
|
||||
|
||||
const splitAtDelimiters = function (text, delimiters) {
|
||||
let index;
|
||||
const data = [];
|
||||
const regexLeft = new RegExp("(" + delimiters.map(x => escapeRegex(x.left)).join("|") + ")");
|
||||
|
||||
while (true) {
|
||||
index = text.search(regexLeft);
|
||||
|
||||
if (index === -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (index > 0) {
|
||||
data.push({
|
||||
type: "text",
|
||||
data: text.slice(0, index)
|
||||
});
|
||||
text = text.slice(index); // now text starts with delimiter
|
||||
} // ... so this always succeeds:
|
||||
|
||||
|
||||
const i = delimiters.findIndex(delim => text.startsWith(delim.left));
|
||||
index = findEndOfMath(delimiters[i].right, text, delimiters[i].left.length);
|
||||
|
||||
if (index === -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
const rawData = text.slice(0, index + delimiters[i].right.length);
|
||||
const math = amsRegex.test(rawData) ? rawData : text.slice(delimiters[i].left.length, index);
|
||||
data.push({
|
||||
type: "math",
|
||||
data: math,
|
||||
rawData,
|
||||
display: delimiters[i].display
|
||||
});
|
||||
text = text.slice(index + delimiters[i].right.length);
|
||||
}
|
||||
|
||||
if (text !== "") {
|
||||
data.push({
|
||||
type: "text",
|
||||
data: text
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
/* harmony default export */ var auto_render_splitAtDelimiters = (splitAtDelimiters);
|
||||
;// CONCATENATED MODULE: ./contrib/auto-render/auto-render.js
|
||||
/* eslint no-console:0 */
|
||||
|
||||
|
||||
/* Note: optionsCopy is mutated by this method. If it is ever exposed in the
|
||||
* API, we should copy it before mutating.
|
||||
*/
|
||||
|
||||
const renderMathInText = function (text, optionsCopy) {
|
||||
const data = auto_render_splitAtDelimiters(text, optionsCopy.delimiters);
|
||||
|
||||
if (data.length === 1 && data[0].type === 'text') {
|
||||
// There is no formula in the text.
|
||||
// Let's return null which means there is no need to replace
|
||||
// the current text node with a new one.
|
||||
return null;
|
||||
}
|
||||
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
if (data[i].type === "text") {
|
||||
fragment.appendChild(document.createTextNode(data[i].data));
|
||||
} else {
|
||||
const span = document.createElement("span");
|
||||
let math = data[i].data; // Override any display mode defined in the settings with that
|
||||
// defined by the text itself
|
||||
|
||||
optionsCopy.displayMode = data[i].display;
|
||||
|
||||
try {
|
||||
if (optionsCopy.preProcess) {
|
||||
math = optionsCopy.preProcess(math);
|
||||
}
|
||||
|
||||
external_katex_default().render(math, span, optionsCopy);
|
||||
} catch (e) {
|
||||
if (!(e instanceof (external_katex_default()).ParseError)) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
optionsCopy.errorCallback("KaTeX auto-render: Failed to parse `" + data[i].data + "` with ", e);
|
||||
fragment.appendChild(document.createTextNode(data[i].rawData));
|
||||
continue;
|
||||
}
|
||||
|
||||
fragment.appendChild(span);
|
||||
}
|
||||
}
|
||||
|
||||
return fragment;
|
||||
};
|
||||
|
||||
const renderElem = function (elem, optionsCopy) {
|
||||
for (let i = 0; i < elem.childNodes.length; i++) {
|
||||
const childNode = elem.childNodes[i];
|
||||
|
||||
if (childNode.nodeType === 3) {
|
||||
// Text node
|
||||
// Concatenate all sibling text nodes.
|
||||
// Webkit browsers split very large text nodes into smaller ones,
|
||||
// so the delimiters may be split across different nodes.
|
||||
let textContentConcat = childNode.textContent;
|
||||
let sibling = childNode.nextSibling;
|
||||
let nSiblings = 0;
|
||||
|
||||
while (sibling && sibling.nodeType === Node.TEXT_NODE) {
|
||||
textContentConcat += sibling.textContent;
|
||||
sibling = sibling.nextSibling;
|
||||
nSiblings++;
|
||||
}
|
||||
|
||||
const frag = renderMathInText(textContentConcat, optionsCopy);
|
||||
|
||||
if (frag) {
|
||||
// Remove extra text nodes
|
||||
for (let j = 0; j < nSiblings; j++) {
|
||||
childNode.nextSibling.remove();
|
||||
}
|
||||
|
||||
i += frag.childNodes.length - 1;
|
||||
elem.replaceChild(frag, childNode);
|
||||
} else {
|
||||
// If the concatenated text does not contain math
|
||||
// the siblings will not either
|
||||
i += nSiblings;
|
||||
}
|
||||
} else if (childNode.nodeType === 1) {
|
||||
// Element node
|
||||
const className = ' ' + childNode.className + ' ';
|
||||
const shouldRender = optionsCopy.ignoredTags.indexOf(childNode.nodeName.toLowerCase()) === -1 && optionsCopy.ignoredClasses.every(x => className.indexOf(' ' + x + ' ') === -1);
|
||||
|
||||
if (shouldRender) {
|
||||
renderElem(childNode, optionsCopy);
|
||||
}
|
||||
} // Otherwise, it's something else, and ignore it.
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
const renderMathInElement = function (elem, options) {
|
||||
if (!elem) {
|
||||
throw new Error("No element provided to render");
|
||||
}
|
||||
|
||||
const optionsCopy = {}; // Object.assign(optionsCopy, option)
|
||||
|
||||
for (const option in options) {
|
||||
if (options.hasOwnProperty(option)) {
|
||||
optionsCopy[option] = options[option];
|
||||
}
|
||||
} // default options
|
||||
|
||||
|
||||
optionsCopy.delimiters = optionsCopy.delimiters || [{
|
||||
left: "$$",
|
||||
right: "$$",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\(",
|
||||
right: "\\)",
|
||||
display: false
|
||||
}, // LaTeX uses $…$, but it ruins the display of normal `$` in text:
|
||||
// {left: "$", right: "$", display: false},
|
||||
// $ must come after $$
|
||||
// Render AMS environments even if outside $$…$$ delimiters.
|
||||
{
|
||||
left: "\\begin{equation}",
|
||||
right: "\\end{equation}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\begin{align}",
|
||||
right: "\\end{align}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\begin{alignat}",
|
||||
right: "\\end{alignat}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\begin{gather}",
|
||||
right: "\\end{gather}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\begin{CD}",
|
||||
right: "\\end{CD}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\[",
|
||||
right: "\\]",
|
||||
display: true
|
||||
}];
|
||||
optionsCopy.ignoredTags = optionsCopy.ignoredTags || ["script", "noscript", "style", "textarea", "pre", "code", "option"];
|
||||
optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || [];
|
||||
optionsCopy.errorCallback = optionsCopy.errorCallback || console.error; // Enable sharing of global macros defined via `\gdef` between different
|
||||
// math elements within a single call to `renderMathInElement`.
|
||||
|
||||
optionsCopy.macros = optionsCopy.macros || {};
|
||||
renderElem(elem, optionsCopy);
|
||||
};
|
||||
|
||||
/* harmony default export */ var auto_render = (renderMathInElement);
|
||||
__webpack_exports__ = __webpack_exports__["default"];
|
||||
/******/ return __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
});
|
||||
1
node_modules/katex/dist/contrib/auto-render.min.js
generated
vendored
Normal file
1
node_modules/katex/dist/contrib/auto-render.min.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={757:function(t){t.exports=e}},n={};function r(e){var o=n[e];if(void 0!==o)return o.exports;var i=n[e]={exports:{}};return t[e](i,i.exports,r),i.exports}r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,{a:t}),t},r.d=function(e,t){for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var o={};r.d(o,{default:function(){return p}});var i=r(757),a=r.n(i);const l=function(e,t,n){let r=n,o=0;const i=e.length;for(;r<t.length;){const n=t[r];if(o<=0&&t.slice(r,r+i)===e)return r;"\\"===n?r++:"{"===n?o++:"}"===n&&o--,r++}return-1},s=/^\\begin{/;var d=function(e,t){let n;const r=[],o=new RegExp("("+t.map((e=>e.left.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"))).join("|")+")");for(;n=e.search(o),-1!==n;){n>0&&(r.push({type:"text",data:e.slice(0,n)}),e=e.slice(n));const o=t.findIndex((t=>e.startsWith(t.left)));if(n=l(t[o].right,e,t[o].left.length),-1===n)break;const i=e.slice(0,n+t[o].right.length),a=s.test(i)?i:e.slice(t[o].left.length,n);r.push({type:"math",data:a,rawData:i,display:t[o].display}),e=e.slice(n+t[o].right.length)}return""!==e&&r.push({type:"text",data:e}),r};const c=function(e,t){const n=d(e,t.delimiters);if(1===n.length&&"text"===n[0].type)return null;const r=document.createDocumentFragment();for(let e=0;e<n.length;e++)if("text"===n[e].type)r.appendChild(document.createTextNode(n[e].data));else{const o=document.createElement("span");let i=n[e].data;t.displayMode=n[e].display;try{t.preProcess&&(i=t.preProcess(i)),a().render(i,o,t)}catch(o){if(!(o instanceof a().ParseError))throw o;t.errorCallback("KaTeX auto-render: Failed to parse `"+n[e].data+"` with ",o),r.appendChild(document.createTextNode(n[e].rawData));continue}r.appendChild(o)}return r},f=function(e,t){for(let n=0;n<e.childNodes.length;n++){const r=e.childNodes[n];if(3===r.nodeType){let o=r.textContent,i=r.nextSibling,a=0;for(;i&&i.nodeType===Node.TEXT_NODE;)o+=i.textContent,i=i.nextSibling,a++;const l=c(o,t);if(l){for(let e=0;e<a;e++)r.nextSibling.remove();n+=l.childNodes.length-1,e.replaceChild(l,r)}else n+=a}else if(1===r.nodeType){const e=" "+r.className+" ";-1===t.ignoredTags.indexOf(r.nodeName.toLowerCase())&&t.ignoredClasses.every((t=>-1===e.indexOf(" "+t+" ")))&&f(r,t)}}};var p=function(e,t){if(!e)throw new Error("No element provided to render");const n={};for(const e in t)t.hasOwnProperty(e)&&(n[e]=t[e]);n.delimiters=n.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\begin{equation}",right:"\\end{equation}",display:!0},{left:"\\begin{align}",right:"\\end{align}",display:!0},{left:"\\begin{alignat}",right:"\\end{alignat}",display:!0},{left:"\\begin{gather}",right:"\\end{gather}",display:!0},{left:"\\begin{CD}",right:"\\end{CD}",display:!0},{left:"\\[",right:"\\]",display:!0}],n.ignoredTags=n.ignoredTags||["script","noscript","style","textarea","pre","code","option"],n.ignoredClasses=n.ignoredClasses||[],n.errorCallback=n.errorCallback||console.error,n.macros=n.macros||{},f(e,n)};return o=o.default}()}));
|
||||
244
node_modules/katex/dist/contrib/auto-render.mjs
generated
vendored
Normal file
244
node_modules/katex/dist/contrib/auto-render.mjs
generated
vendored
Normal file
@@ -0,0 +1,244 @@
|
||||
import katex from '../katex.mjs';
|
||||
|
||||
/* eslint no-constant-condition:0 */
|
||||
var findEndOfMath = function findEndOfMath(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 escapeRegex = function escapeRegex(string) {
|
||||
return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
||||
};
|
||||
|
||||
var amsRegex = /^\\begin{/;
|
||||
|
||||
var splitAtDelimiters = function splitAtDelimiters(text, delimiters) {
|
||||
var index;
|
||||
var data = [];
|
||||
var regexLeft = new RegExp("(" + delimiters.map(x => escapeRegex(x.left)).join("|") + ")");
|
||||
|
||||
while (true) {
|
||||
index = text.search(regexLeft);
|
||||
|
||||
if (index === -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (index > 0) {
|
||||
data.push({
|
||||
type: "text",
|
||||
data: text.slice(0, index)
|
||||
});
|
||||
text = text.slice(index); // now text starts with delimiter
|
||||
} // ... so this always succeeds:
|
||||
|
||||
|
||||
var i = delimiters.findIndex(delim => text.startsWith(delim.left));
|
||||
index = findEndOfMath(delimiters[i].right, text, delimiters[i].left.length);
|
||||
|
||||
if (index === -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
var rawData = text.slice(0, index + delimiters[i].right.length);
|
||||
var math = amsRegex.test(rawData) ? rawData : text.slice(delimiters[i].left.length, index);
|
||||
data.push({
|
||||
type: "math",
|
||||
data: math,
|
||||
rawData,
|
||||
display: delimiters[i].display
|
||||
});
|
||||
text = text.slice(index + delimiters[i].right.length);
|
||||
}
|
||||
|
||||
if (text !== "") {
|
||||
data.push({
|
||||
type: "text",
|
||||
data: text
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
/* eslint no-console:0 */
|
||||
/* Note: optionsCopy is mutated by this method. If it is ever exposed in the
|
||||
* API, we should copy it before mutating.
|
||||
*/
|
||||
|
||||
var renderMathInText = function renderMathInText(text, optionsCopy) {
|
||||
var data = splitAtDelimiters(text, optionsCopy.delimiters);
|
||||
|
||||
if (data.length === 1 && data[0].type === 'text') {
|
||||
// There is no formula in the text.
|
||||
// Let's return null which means there is no need to replace
|
||||
// the current text node with a new one.
|
||||
return null;
|
||||
}
|
||||
|
||||
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; // Override any display mode defined in the settings with that
|
||||
// defined by the text itself
|
||||
|
||||
optionsCopy.displayMode = data[i].display;
|
||||
|
||||
try {
|
||||
if (optionsCopy.preProcess) {
|
||||
math = optionsCopy.preProcess(math);
|
||||
}
|
||||
|
||||
katex.render(math, span, optionsCopy);
|
||||
} catch (e) {
|
||||
if (!(e instanceof katex.ParseError)) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
optionsCopy.errorCallback("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 renderElem(elem, optionsCopy) {
|
||||
for (var i = 0; i < elem.childNodes.length; i++) {
|
||||
var childNode = elem.childNodes[i];
|
||||
|
||||
if (childNode.nodeType === 3) {
|
||||
// Text node
|
||||
// Concatenate all sibling text nodes.
|
||||
// Webkit browsers split very large text nodes into smaller ones,
|
||||
// so the delimiters may be split across different nodes.
|
||||
var textContentConcat = childNode.textContent;
|
||||
var sibling = childNode.nextSibling;
|
||||
var nSiblings = 0;
|
||||
|
||||
while (sibling && sibling.nodeType === Node.TEXT_NODE) {
|
||||
textContentConcat += sibling.textContent;
|
||||
sibling = sibling.nextSibling;
|
||||
nSiblings++;
|
||||
}
|
||||
|
||||
var frag = renderMathInText(textContentConcat, optionsCopy);
|
||||
|
||||
if (frag) {
|
||||
// Remove extra text nodes
|
||||
for (var j = 0; j < nSiblings; j++) {
|
||||
childNode.nextSibling.remove();
|
||||
}
|
||||
|
||||
i += frag.childNodes.length - 1;
|
||||
elem.replaceChild(frag, childNode);
|
||||
} else {
|
||||
// If the concatenated text does not contain math
|
||||
// the siblings will not either
|
||||
i += nSiblings;
|
||||
}
|
||||
} else if (childNode.nodeType === 1) {
|
||||
(function () {
|
||||
// Element node
|
||||
var className = ' ' + childNode.className + ' ';
|
||||
var shouldRender = optionsCopy.ignoredTags.indexOf(childNode.nodeName.toLowerCase()) === -1 && optionsCopy.ignoredClasses.every(x => className.indexOf(' ' + x + ' ') === -1);
|
||||
|
||||
if (shouldRender) {
|
||||
renderElem(childNode, optionsCopy);
|
||||
}
|
||||
})();
|
||||
} // Otherwise, it's something else, and ignore it.
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
var renderMathInElement = function renderMathInElement(elem, options) {
|
||||
if (!elem) {
|
||||
throw new Error("No element provided to render");
|
||||
}
|
||||
|
||||
var optionsCopy = {}; // Object.assign(optionsCopy, option)
|
||||
|
||||
for (var option in options) {
|
||||
if (options.hasOwnProperty(option)) {
|
||||
optionsCopy[option] = options[option];
|
||||
}
|
||||
} // default options
|
||||
|
||||
|
||||
optionsCopy.delimiters = optionsCopy.delimiters || [{
|
||||
left: "$$",
|
||||
right: "$$",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\(",
|
||||
right: "\\)",
|
||||
display: false
|
||||
}, // LaTeX uses $…$, but it ruins the display of normal `$` in text:
|
||||
// {left: "$", right: "$", display: false},
|
||||
// $ must come after $$
|
||||
// Render AMS environments even if outside $$…$$ delimiters.
|
||||
{
|
||||
left: "\\begin{equation}",
|
||||
right: "\\end{equation}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\begin{align}",
|
||||
right: "\\end{align}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\begin{alignat}",
|
||||
right: "\\end{alignat}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\begin{gather}",
|
||||
right: "\\end{gather}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\begin{CD}",
|
||||
right: "\\end{CD}",
|
||||
display: true
|
||||
}, {
|
||||
left: "\\[",
|
||||
right: "\\]",
|
||||
display: true
|
||||
}];
|
||||
optionsCopy.ignoredTags = optionsCopy.ignoredTags || ["script", "noscript", "style", "textarea", "pre", "code", "option"];
|
||||
optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || [];
|
||||
optionsCopy.errorCallback = optionsCopy.errorCallback || console.error; // Enable sharing of global macros defined via `\gdef` between different
|
||||
// math elements within a single call to `renderMathInElement`.
|
||||
|
||||
optionsCopy.macros = optionsCopy.macros || {};
|
||||
renderElem(elem, optionsCopy);
|
||||
};
|
||||
|
||||
export { renderMathInElement as default };
|
||||
127
node_modules/katex/dist/contrib/copy-tex.js
generated
vendored
Normal file
127
node_modules/katex/dist/contrib/copy-tex.js
generated
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
(function webpackUniversalModuleDefinition(root, factory) {
|
||||
if(typeof exports === 'object' && typeof module === 'object')
|
||||
module.exports = factory();
|
||||
else if(typeof define === 'function' && define.amd)
|
||||
define([], factory);
|
||||
else {
|
||||
var a = factory();
|
||||
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
|
||||
}
|
||||
})((typeof self !== 'undefined' ? self : this), function() {
|
||||
return /******/ (function() { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
var __webpack_exports__ = {};
|
||||
|
||||
;// CONCATENATED MODULE: ./contrib/copy-tex/katex2tex.js
|
||||
// Set these to how you want inline and display math to be delimited.
|
||||
const defaultCopyDelimiters = {
|
||||
inline: ['$', '$'],
|
||||
// alternative: ['\(', '\)']
|
||||
display: ['$$', '$$'] // alternative: ['\[', '\]']
|
||||
|
||||
}; // Replace .katex elements with their TeX source (<annotation> element).
|
||||
// Modifies fragment in-place. Useful for writing your own 'copy' handler,
|
||||
// as in copy-tex.js.
|
||||
|
||||
function katexReplaceWithTex(fragment, copyDelimiters) {
|
||||
if (copyDelimiters === void 0) {
|
||||
copyDelimiters = defaultCopyDelimiters;
|
||||
}
|
||||
|
||||
// Remove .katex-html blocks that are preceded by .katex-mathml blocks
|
||||
// (which will get replaced below).
|
||||
const katexHtml = fragment.querySelectorAll('.katex-mathml + .katex-html');
|
||||
|
||||
for (let i = 0; i < katexHtml.length; i++) {
|
||||
const element = katexHtml[i];
|
||||
|
||||
if (element.remove) {
|
||||
element.remove();
|
||||
} else if (element.parentNode) {
|
||||
element.parentNode.removeChild(element);
|
||||
}
|
||||
} // Replace .katex-mathml elements with their annotation (TeX source)
|
||||
// descendant, with inline delimiters.
|
||||
|
||||
|
||||
const katexMathml = fragment.querySelectorAll('.katex-mathml');
|
||||
|
||||
for (let i = 0; i < katexMathml.length; i++) {
|
||||
const element = katexMathml[i];
|
||||
const texSource = element.querySelector('annotation');
|
||||
|
||||
if (texSource) {
|
||||
if (element.replaceWith) {
|
||||
element.replaceWith(texSource);
|
||||
} else if (element.parentNode) {
|
||||
element.parentNode.replaceChild(texSource, element);
|
||||
}
|
||||
|
||||
texSource.innerHTML = copyDelimiters.inline[0] + texSource.innerHTML + copyDelimiters.inline[1];
|
||||
}
|
||||
} // Switch display math to display delimiters.
|
||||
|
||||
|
||||
const displays = fragment.querySelectorAll('.katex-display annotation');
|
||||
|
||||
for (let i = 0; i < displays.length; i++) {
|
||||
const element = displays[i];
|
||||
element.innerHTML = copyDelimiters.display[0] + element.innerHTML.substr(copyDelimiters.inline[0].length, element.innerHTML.length - copyDelimiters.inline[0].length - copyDelimiters.inline[1].length) + copyDelimiters.display[1];
|
||||
}
|
||||
|
||||
return fragment;
|
||||
}
|
||||
/* harmony default export */ var katex2tex = (katexReplaceWithTex);
|
||||
;// CONCATENATED MODULE: ./contrib/copy-tex/copy-tex.js
|
||||
// Return <div class="katex"> element containing node, or null if not found.
|
||||
|
||||
function closestKatex(node) {
|
||||
// If node is a Text Node, for example, go up to containing Element,
|
||||
// where we can apply the `closest` method.
|
||||
const element = node instanceof Element ? node : node.parentElement;
|
||||
return element && element.closest('.katex');
|
||||
} // Global copy handler to modify behavior on/within .katex elements.
|
||||
|
||||
|
||||
document.addEventListener('copy', function (event) {
|
||||
const selection = window.getSelection();
|
||||
|
||||
if (selection.isCollapsed || !event.clipboardData) {
|
||||
return; // default action OK if selection is empty or unchangeable
|
||||
}
|
||||
|
||||
const clipboardData = event.clipboardData;
|
||||
const range = selection.getRangeAt(0); // When start point is within a formula, expand to entire formula.
|
||||
|
||||
const startKatex = closestKatex(range.startContainer);
|
||||
|
||||
if (startKatex) {
|
||||
range.setStartBefore(startKatex);
|
||||
} // Similarly, when end point is within a formula, expand to entire formula.
|
||||
|
||||
|
||||
const endKatex = closestKatex(range.endContainer);
|
||||
|
||||
if (endKatex) {
|
||||
range.setEndAfter(endKatex);
|
||||
}
|
||||
|
||||
const fragment = range.cloneContents();
|
||||
|
||||
if (!fragment.querySelector('.katex-mathml')) {
|
||||
return; // default action OK if no .katex-mathml elements
|
||||
}
|
||||
|
||||
const htmlContents = Array.prototype.map.call(fragment.childNodes, el => el instanceof Text ? el.textContent : el.outerHTML).join(''); // Preserve usual HTML copy/paste behavior.
|
||||
|
||||
clipboardData.setData('text/html', htmlContents); // Rewrite plain-text version.
|
||||
|
||||
clipboardData.setData('text/plain', katex2tex(fragment).textContent); // Prevent normal copy handling.
|
||||
|
||||
event.preventDefault();
|
||||
});
|
||||
__webpack_exports__ = __webpack_exports__["default"];
|
||||
/******/ return __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
});
|
||||
1
node_modules/katex/dist/contrib/copy-tex.min.js
generated
vendored
Normal file
1
node_modules/katex/dist/contrib/copy-tex.min.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var n=t();for(var o in n)("object"==typeof exports?exports:e)[o]=n[o]}}("undefined"!=typeof self?self:this,(function(){return function(){"use strict";var e={};const t={inline:["$","$"],display:["$$","$$"]};var n=function(e,n){void 0===n&&(n=t);const o=e.querySelectorAll(".katex-mathml + .katex-html");for(let e=0;e<o.length;e++){const t=o[e];t.remove?t.remove():t.parentNode&&t.parentNode.removeChild(t)}const r=e.querySelectorAll(".katex-mathml");for(let e=0;e<r.length;e++){const t=r[e],o=t.querySelector("annotation");o&&(t.replaceWith?t.replaceWith(o):t.parentNode&&t.parentNode.replaceChild(o,t),o.innerHTML=n.inline[0]+o.innerHTML+n.inline[1])}const l=e.querySelectorAll(".katex-display annotation");for(let e=0;e<l.length;e++){const t=l[e];t.innerHTML=n.display[0]+t.innerHTML.substr(n.inline[0].length,t.innerHTML.length-n.inline[0].length-n.inline[1].length)+n.display[1]}return e};function o(e){const t=e instanceof Element?e:e.parentElement;return t&&t.closest(".katex")}return document.addEventListener("copy",(function(e){const t=window.getSelection();if(t.isCollapsed||!e.clipboardData)return;const r=e.clipboardData,l=t.getRangeAt(0),i=o(l.startContainer);i&&l.setStartBefore(i);const a=o(l.endContainer);a&&l.setEndAfter(a);const s=l.cloneContents();if(!s.querySelector(".katex-mathml"))return;const c=Array.prototype.map.call(s.childNodes,(e=>e instanceof Text?e.textContent:e.outerHTML)).join("");r.setData("text/html",c),r.setData("text/plain",n(s).textContent),e.preventDefault()})),e=e.default}()}));
|
||||
105
node_modules/katex/dist/contrib/copy-tex.mjs
generated
vendored
Normal file
105
node_modules/katex/dist/contrib/copy-tex.mjs
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
// Set these to how you want inline and display math to be delimited.
|
||||
var defaultCopyDelimiters = {
|
||||
inline: ['$', '$'],
|
||||
// alternative: ['\(', '\)']
|
||||
display: ['$$', '$$'] // alternative: ['\[', '\]']
|
||||
|
||||
}; // Replace .katex elements with their TeX source (<annotation> element).
|
||||
// Modifies fragment in-place. Useful for writing your own 'copy' handler,
|
||||
// as in copy-tex.js.
|
||||
|
||||
function katexReplaceWithTex(fragment, copyDelimiters) {
|
||||
if (copyDelimiters === void 0) {
|
||||
copyDelimiters = defaultCopyDelimiters;
|
||||
}
|
||||
|
||||
// Remove .katex-html blocks that are preceded by .katex-mathml blocks
|
||||
// (which will get replaced below).
|
||||
var katexHtml = fragment.querySelectorAll('.katex-mathml + .katex-html');
|
||||
|
||||
for (var i = 0; i < katexHtml.length; i++) {
|
||||
var element = katexHtml[i];
|
||||
|
||||
if (element.remove) {
|
||||
element.remove();
|
||||
} else if (element.parentNode) {
|
||||
element.parentNode.removeChild(element);
|
||||
}
|
||||
} // Replace .katex-mathml elements with their annotation (TeX source)
|
||||
// descendant, with inline delimiters.
|
||||
|
||||
|
||||
var katexMathml = fragment.querySelectorAll('.katex-mathml');
|
||||
|
||||
for (var _i = 0; _i < katexMathml.length; _i++) {
|
||||
var _element = katexMathml[_i];
|
||||
|
||||
var texSource = _element.querySelector('annotation');
|
||||
|
||||
if (texSource) {
|
||||
if (_element.replaceWith) {
|
||||
_element.replaceWith(texSource);
|
||||
} else if (_element.parentNode) {
|
||||
_element.parentNode.replaceChild(texSource, _element);
|
||||
}
|
||||
|
||||
texSource.innerHTML = copyDelimiters.inline[0] + texSource.innerHTML + copyDelimiters.inline[1];
|
||||
}
|
||||
} // Switch display math to display delimiters.
|
||||
|
||||
|
||||
var displays = fragment.querySelectorAll('.katex-display annotation');
|
||||
|
||||
for (var _i2 = 0; _i2 < displays.length; _i2++) {
|
||||
var _element2 = displays[_i2];
|
||||
_element2.innerHTML = copyDelimiters.display[0] + _element2.innerHTML.substr(copyDelimiters.inline[0].length, _element2.innerHTML.length - copyDelimiters.inline[0].length - copyDelimiters.inline[1].length) + copyDelimiters.display[1];
|
||||
}
|
||||
|
||||
return fragment;
|
||||
}
|
||||
|
||||
function closestKatex(node) {
|
||||
// If node is a Text Node, for example, go up to containing Element,
|
||||
// where we can apply the `closest` method.
|
||||
var element = node instanceof Element ? node : node.parentElement;
|
||||
return element && element.closest('.katex');
|
||||
} // Global copy handler to modify behavior on/within .katex elements.
|
||||
|
||||
|
||||
document.addEventListener('copy', function (event) {
|
||||
var selection = window.getSelection();
|
||||
|
||||
if (selection.isCollapsed || !event.clipboardData) {
|
||||
return; // default action OK if selection is empty or unchangeable
|
||||
}
|
||||
|
||||
var clipboardData = event.clipboardData;
|
||||
var range = selection.getRangeAt(0); // When start point is within a formula, expand to entire formula.
|
||||
|
||||
var startKatex = closestKatex(range.startContainer);
|
||||
|
||||
if (startKatex) {
|
||||
range.setStartBefore(startKatex);
|
||||
} // Similarly, when end point is within a formula, expand to entire formula.
|
||||
|
||||
|
||||
var endKatex = closestKatex(range.endContainer);
|
||||
|
||||
if (endKatex) {
|
||||
range.setEndAfter(endKatex);
|
||||
}
|
||||
|
||||
var fragment = range.cloneContents();
|
||||
|
||||
if (!fragment.querySelector('.katex-mathml')) {
|
||||
return; // default action OK if no .katex-mathml elements
|
||||
}
|
||||
|
||||
var htmlContents = Array.prototype.map.call(fragment.childNodes, el => el instanceof Text ? el.textContent : el.outerHTML).join(''); // Preserve usual HTML copy/paste behavior.
|
||||
|
||||
clipboardData.setData('text/html', htmlContents); // Rewrite plain-text version.
|
||||
|
||||
clipboardData.setData('text/plain', katexReplaceWithTex(fragment).textContent); // Prevent normal copy handling.
|
||||
|
||||
event.preventDefault();
|
||||
});
|
||||
109
node_modules/katex/dist/contrib/mathtex-script-type.js
generated
vendored
Normal file
109
node_modules/katex/dist/contrib/mathtex-script-type.js
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
(function webpackUniversalModuleDefinition(root, factory) {
|
||||
if(typeof exports === 'object' && typeof module === 'object')
|
||||
module.exports = factory(require("katex"));
|
||||
else if(typeof define === 'function' && define.amd)
|
||||
define(["katex"], factory);
|
||||
else {
|
||||
var a = typeof exports === 'object' ? factory(require("katex")) : factory(root["katex"]);
|
||||
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
|
||||
}
|
||||
})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__757__) {
|
||||
return /******/ (function() { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ 757:
|
||||
/***/ (function(module) {
|
||||
|
||||
module.exports = __WEBPACK_EXTERNAL_MODULE__757__;
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ var __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
||||
/******/ if (cachedModule !== undefined) {
|
||||
/******/ return cachedModule.exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/************************************************************************/
|
||||
/******/ /* webpack/runtime/compat get default export */
|
||||
/******/ !function() {
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function() { return module['default']; } :
|
||||
/******/ function() { return module; };
|
||||
/******/ __webpack_require__.d(getter, { a: getter });
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/define property getters */
|
||||
/******/ !function() {
|
||||
/******/ // define getter functions for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, definition) {
|
||||
/******/ for(var key in definition) {
|
||||
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
||||
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
|
||||
/******/ }();
|
||||
/******/
|
||||
/************************************************************************/
|
||||
var __webpack_exports__ = {};
|
||||
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(757);
|
||||
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(katex__WEBPACK_IMPORTED_MODULE_0__);
|
||||
|
||||
let scripts = document.body.getElementsByTagName("script");
|
||||
scripts = Array.prototype.slice.call(scripts);
|
||||
scripts.forEach(function (script) {
|
||||
if (!script.type || !script.type.match(/math\/tex/i)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const display = script.type.match(/mode\s*=\s*display(;|\s|\n|$)/) != null;
|
||||
const katexElement = document.createElement(display ? "div" : "span");
|
||||
katexElement.setAttribute("class", display ? "equation" : "inline-equation");
|
||||
|
||||
try {
|
||||
katex__WEBPACK_IMPORTED_MODULE_0___default().render(script.text, katexElement, {
|
||||
displayMode: display
|
||||
});
|
||||
} catch (err) {
|
||||
//console.error(err); linter doesn't like this
|
||||
katexElement.textContent = script.text;
|
||||
}
|
||||
|
||||
script.parentNode.replaceChild(katexElement, script);
|
||||
});
|
||||
__webpack_exports__ = __webpack_exports__["default"];
|
||||
/******/ return __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
});
|
||||
1
node_modules/katex/dist/contrib/mathtex-script-type.min.js
generated
vendored
Normal file
1
node_modules/katex/dist/contrib/mathtex-script-type.min.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("katex"));else if("function"==typeof define&&define.amd)define(["katex"],t);else{var n="object"==typeof exports?t(require("katex")):t(e.katex);for(var r in n)("object"==typeof exports?exports:e)[r]=n[r]}}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={757:function(t){t.exports=e}},n={};function r(e){var o=n[e];if(void 0!==o)return o.exports;var i=n[e]={exports:{}};return t[e](i,i.exports,r),i.exports}r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,{a:t}),t},r.d=function(e,t){for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var o={},i=r(757),a=r.n(i);let u=document.body.getElementsByTagName("script");return u=Array.prototype.slice.call(u),u.forEach((function(e){if(!e.type||!e.type.match(/math\/tex/i))return-1;const t=null!=e.type.match(/mode\s*=\s*display(;|\s|\n|$)/),n=document.createElement(t?"div":"span");n.setAttribute("class",t?"equation":"inline-equation");try{a().render(e.text,n,{displayMode:t})}catch(t){n.textContent=e.text}e.parentNode.replaceChild(n,e)})),o=o.default}()}));
|
||||
24
node_modules/katex/dist/contrib/mathtex-script-type.mjs
generated
vendored
Normal file
24
node_modules/katex/dist/contrib/mathtex-script-type.mjs
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import katex from '../katex.mjs';
|
||||
|
||||
var scripts = document.body.getElementsByTagName("script");
|
||||
scripts = Array.prototype.slice.call(scripts);
|
||||
scripts.forEach(function (script) {
|
||||
if (!script.type || !script.type.match(/math\/tex/i)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
var display = script.type.match(/mode\s*=\s*display(;|\s|\n|$)/) != null;
|
||||
var katexElement = document.createElement(display ? "div" : "span");
|
||||
katexElement.setAttribute("class", display ? "equation" : "inline-equation");
|
||||
|
||||
try {
|
||||
katex.render(script.text, katexElement, {
|
||||
displayMode: display
|
||||
});
|
||||
} catch (err) {
|
||||
//console.error(err); linter doesn't like this
|
||||
katexElement.textContent = script.text;
|
||||
}
|
||||
|
||||
script.parentNode.replaceChild(katexElement, script);
|
||||
});
|
||||
3213
node_modules/katex/dist/contrib/mhchem.js
generated
vendored
Normal file
3213
node_modules/katex/dist/contrib/mhchem.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
node_modules/katex/dist/contrib/mhchem.min.js
generated
vendored
Normal file
1
node_modules/katex/dist/contrib/mhchem.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
3109
node_modules/katex/dist/contrib/mhchem.mjs
generated
vendored
Normal file
3109
node_modules/katex/dist/contrib/mhchem.mjs
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
887
node_modules/katex/dist/contrib/render-a11y-string.js
generated
vendored
Normal file
887
node_modules/katex/dist/contrib/render-a11y-string.js
generated
vendored
Normal file
@@ -0,0 +1,887 @@
|
||||
(function webpackUniversalModuleDefinition(root, factory) {
|
||||
if(typeof exports === 'object' && typeof module === 'object')
|
||||
module.exports = factory(require("katex"));
|
||||
else if(typeof define === 'function' && define.amd)
|
||||
define(["katex"], factory);
|
||||
else {
|
||||
var a = typeof exports === 'object' ? factory(require("katex")) : factory(root["katex"]);
|
||||
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
|
||||
}
|
||||
})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__757__) {
|
||||
return /******/ (function() { // webpackBootstrap
|
||||
/******/ "use strict";
|
||||
/******/ var __webpack_modules__ = ({
|
||||
|
||||
/***/ 757:
|
||||
/***/ (function(module) {
|
||||
|
||||
module.exports = __WEBPACK_EXTERNAL_MODULE__757__;
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
/************************************************************************/
|
||||
/******/ // The module cache
|
||||
/******/ var __webpack_module_cache__ = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/ // Check if module is in cache
|
||||
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
||||
/******/ if (cachedModule !== undefined) {
|
||||
/******/ return cachedModule.exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = __webpack_module_cache__[moduleId] = {
|
||||
/******/ // no module.id needed
|
||||
/******/ // no module.loaded needed
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/************************************************************************/
|
||||
/******/ /* webpack/runtime/compat get default export */
|
||||
/******/ !function() {
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function() { return module['default']; } :
|
||||
/******/ function() { return module; };
|
||||
/******/ __webpack_require__.d(getter, { a: getter });
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/define property getters */
|
||||
/******/ !function() {
|
||||
/******/ // define getter functions for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, definition) {
|
||||
/******/ for(var key in definition) {
|
||||
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
||||
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/ }();
|
||||
/******/
|
||||
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
||||
/******/ !function() {
|
||||
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
|
||||
/******/ }();
|
||||
/******/
|
||||
/************************************************************************/
|
||||
var __webpack_exports__ = {};
|
||||
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(757);
|
||||
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(katex__WEBPACK_IMPORTED_MODULE_0__);
|
||||
/**
|
||||
* renderA11yString returns a readable string.
|
||||
*
|
||||
* In some cases the string will have the proper semantic math
|
||||
* meaning,:
|
||||
* renderA11yString("\\frac{1}{2}"")
|
||||
* -> "start fraction, 1, divided by, 2, end fraction"
|
||||
*
|
||||
* However, other cases do not:
|
||||
* renderA11yString("f(x) = x^2")
|
||||
* -> "f, left parenthesis, x, right parenthesis, equals, x, squared"
|
||||
*
|
||||
* The commas in the string aim to increase ease of understanding
|
||||
* when read by a screenreader.
|
||||
*/
|
||||
// NOTE: since we're importing types here these files won't actually be
|
||||
// included in the build.
|
||||
// $FlowIgnore: we import the types directly anyways
|
||||
|
||||
const stringMap = {
|
||||
"(": "left parenthesis",
|
||||
")": "right parenthesis",
|
||||
"[": "open bracket",
|
||||
"]": "close bracket",
|
||||
"\\{": "left brace",
|
||||
"\\}": "right brace",
|
||||
"\\lvert": "open vertical bar",
|
||||
"\\rvert": "close vertical bar",
|
||||
"|": "vertical bar",
|
||||
"\\uparrow": "up arrow",
|
||||
"\\Uparrow": "up arrow",
|
||||
"\\downarrow": "down arrow",
|
||||
"\\Downarrow": "down arrow",
|
||||
"\\updownarrow": "up down arrow",
|
||||
"\\leftarrow": "left arrow",
|
||||
"\\Leftarrow": "left arrow",
|
||||
"\\rightarrow": "right arrow",
|
||||
"\\Rightarrow": "right arrow",
|
||||
"\\langle": "open angle",
|
||||
"\\rangle": "close angle",
|
||||
"\\lfloor": "open floor",
|
||||
"\\rfloor": "close floor",
|
||||
"\\int": "integral",
|
||||
"\\intop": "integral",
|
||||
"\\lim": "limit",
|
||||
"\\ln": "natural log",
|
||||
"\\log": "log",
|
||||
"\\sin": "sine",
|
||||
"\\cos": "cosine",
|
||||
"\\tan": "tangent",
|
||||
"\\cot": "cotangent",
|
||||
"\\sum": "sum",
|
||||
"/": "slash",
|
||||
",": "comma",
|
||||
".": "point",
|
||||
"-": "negative",
|
||||
"+": "plus",
|
||||
"~": "tilde",
|
||||
":": "colon",
|
||||
"?": "question mark",
|
||||
"'": "apostrophe",
|
||||
"\\%": "percent",
|
||||
" ": "space",
|
||||
"\\ ": "space",
|
||||
"\\$": "dollar sign",
|
||||
"\\angle": "angle",
|
||||
"\\degree": "degree",
|
||||
"\\circ": "circle",
|
||||
"\\vec": "vector",
|
||||
"\\triangle": "triangle",
|
||||
"\\pi": "pi",
|
||||
"\\prime": "prime",
|
||||
"\\infty": "infinity",
|
||||
"\\alpha": "alpha",
|
||||
"\\beta": "beta",
|
||||
"\\gamma": "gamma",
|
||||
"\\omega": "omega",
|
||||
"\\theta": "theta",
|
||||
"\\sigma": "sigma",
|
||||
"\\lambda": "lambda",
|
||||
"\\tau": "tau",
|
||||
"\\Delta": "delta",
|
||||
"\\delta": "delta",
|
||||
"\\mu": "mu",
|
||||
"\\rho": "rho",
|
||||
"\\nabla": "del",
|
||||
"\\ell": "ell",
|
||||
"\\ldots": "dots",
|
||||
// TODO: add entries for all accents
|
||||
"\\hat": "hat",
|
||||
"\\acute": "acute"
|
||||
};
|
||||
const powerMap = {
|
||||
"prime": "prime",
|
||||
"degree": "degrees",
|
||||
"circle": "degrees",
|
||||
"2": "squared",
|
||||
"3": "cubed"
|
||||
};
|
||||
const openMap = {
|
||||
"|": "open vertical bar",
|
||||
".": ""
|
||||
};
|
||||
const closeMap = {
|
||||
"|": "close vertical bar",
|
||||
".": ""
|
||||
};
|
||||
const binMap = {
|
||||
"+": "plus",
|
||||
"-": "minus",
|
||||
"\\pm": "plus minus",
|
||||
"\\cdot": "dot",
|
||||
"*": "times",
|
||||
"/": "divided by",
|
||||
"\\times": "times",
|
||||
"\\div": "divided by",
|
||||
"\\circ": "circle",
|
||||
"\\bullet": "bullet"
|
||||
};
|
||||
const relMap = {
|
||||
"=": "equals",
|
||||
"\\approx": "approximately equals",
|
||||
"≠": "does not equal",
|
||||
"\\geq": "is greater than or equal to",
|
||||
"\\ge": "is greater than or equal to",
|
||||
"\\leq": "is less than or equal to",
|
||||
"\\le": "is less than or equal to",
|
||||
">": "is greater than",
|
||||
"<": "is less than",
|
||||
"\\leftarrow": "left arrow",
|
||||
"\\Leftarrow": "left arrow",
|
||||
"\\rightarrow": "right arrow",
|
||||
"\\Rightarrow": "right arrow",
|
||||
":": "colon"
|
||||
};
|
||||
const accentUnderMap = {
|
||||
"\\underleftarrow": "left arrow",
|
||||
"\\underrightarrow": "right arrow",
|
||||
"\\underleftrightarrow": "left-right arrow",
|
||||
"\\undergroup": "group",
|
||||
"\\underlinesegment": "line segment",
|
||||
"\\utilde": "tilde"
|
||||
};
|
||||
|
||||
const buildString = (str, type, a11yStrings) => {
|
||||
if (!str) {
|
||||
return;
|
||||
}
|
||||
|
||||
let ret;
|
||||
|
||||
if (type === "open") {
|
||||
ret = str in openMap ? openMap[str] : stringMap[str] || str;
|
||||
} else if (type === "close") {
|
||||
ret = str in closeMap ? closeMap[str] : stringMap[str] || str;
|
||||
} else if (type === "bin") {
|
||||
ret = binMap[str] || str;
|
||||
} else if (type === "rel") {
|
||||
ret = relMap[str] || str;
|
||||
} else {
|
||||
ret = stringMap[str] || str;
|
||||
} // If the text to add is a number and there is already a string
|
||||
// in the list and the last string is a number then we should
|
||||
// combine them into a single number
|
||||
|
||||
|
||||
if (/^\d+$/.test(ret) && a11yStrings.length > 0 && // TODO(kevinb): check that the last item in a11yStrings is a string
|
||||
// I think we might be able to drop the nested arrays, which would make
|
||||
// this easier to type
|
||||
// $FlowFixMe
|
||||
/^\d+$/.test(a11yStrings[a11yStrings.length - 1])) {
|
||||
a11yStrings[a11yStrings.length - 1] += ret;
|
||||
} else if (ret) {
|
||||
a11yStrings.push(ret);
|
||||
}
|
||||
};
|
||||
|
||||
const buildRegion = (a11yStrings, callback) => {
|
||||
const regionStrings = [];
|
||||
a11yStrings.push(regionStrings);
|
||||
callback(regionStrings);
|
||||
};
|
||||
|
||||
const handleObject = (tree, a11yStrings, atomType) => {
|
||||
// Everything else is assumed to be an object...
|
||||
switch (tree.type) {
|
||||
case "accent":
|
||||
{
|
||||
buildRegion(a11yStrings, a11yStrings => {
|
||||
buildA11yStrings(tree.base, a11yStrings, atomType);
|
||||
a11yStrings.push("with");
|
||||
buildString(tree.label, "normal", a11yStrings);
|
||||
a11yStrings.push("on top");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "accentUnder":
|
||||
{
|
||||
buildRegion(a11yStrings, a11yStrings => {
|
||||
buildA11yStrings(tree.base, a11yStrings, atomType);
|
||||
a11yStrings.push("with");
|
||||
buildString(accentUnderMap[tree.label], "normal", a11yStrings);
|
||||
a11yStrings.push("underneath");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "accent-token":
|
||||
{
|
||||
// Used internally by accent symbols.
|
||||
break;
|
||||
}
|
||||
|
||||
case "atom":
|
||||
{
|
||||
const {
|
||||
text
|
||||
} = tree;
|
||||
|
||||
switch (tree.family) {
|
||||
case "bin":
|
||||
{
|
||||
buildString(text, "bin", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "close":
|
||||
{
|
||||
buildString(text, "close", a11yStrings);
|
||||
break;
|
||||
}
|
||||
// TODO(kevinb): figure out what should be done for inner
|
||||
|
||||
case "inner":
|
||||
{
|
||||
buildString(tree.text, "inner", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "open":
|
||||
{
|
||||
buildString(text, "open", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "punct":
|
||||
{
|
||||
buildString(text, "punct", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "rel":
|
||||
{
|
||||
buildString(text, "rel", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
tree.family;
|
||||
throw new Error("\"" + tree.family + "\" is not a valid atom type");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "color":
|
||||
{
|
||||
const color = tree.color.replace(/katex-/, "");
|
||||
buildRegion(a11yStrings, regionStrings => {
|
||||
regionStrings.push("start color " + color);
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end color " + color);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "color-token":
|
||||
{
|
||||
// Used by \color, \colorbox, and \fcolorbox but not directly rendered.
|
||||
// It's a leaf node and has no children so just break.
|
||||
break;
|
||||
}
|
||||
|
||||
case "delimsizing":
|
||||
{
|
||||
if (tree.delim && tree.delim !== ".") {
|
||||
buildString(tree.delim, "normal", a11yStrings);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "genfrac":
|
||||
{
|
||||
buildRegion(a11yStrings, regionStrings => {
|
||||
// genfrac can have unbalanced delimiters
|
||||
const {
|
||||
leftDelim,
|
||||
rightDelim
|
||||
} = tree; // NOTE: Not sure if this is a safe assumption
|
||||
// hasBarLine true -> fraction, false -> binomial
|
||||
|
||||
if (tree.hasBarLine) {
|
||||
regionStrings.push("start fraction");
|
||||
leftDelim && buildString(leftDelim, "open", regionStrings);
|
||||
buildA11yStrings(tree.numer, regionStrings, atomType);
|
||||
regionStrings.push("divided by");
|
||||
buildA11yStrings(tree.denom, regionStrings, atomType);
|
||||
rightDelim && buildString(rightDelim, "close", regionStrings);
|
||||
regionStrings.push("end fraction");
|
||||
} else {
|
||||
regionStrings.push("start binomial");
|
||||
leftDelim && buildString(leftDelim, "open", regionStrings);
|
||||
buildA11yStrings(tree.numer, regionStrings, atomType);
|
||||
regionStrings.push("over");
|
||||
buildA11yStrings(tree.denom, regionStrings, atomType);
|
||||
rightDelim && buildString(rightDelim, "close", regionStrings);
|
||||
regionStrings.push("end binomial");
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "hbox":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "kern":
|
||||
{
|
||||
// No op: we don't attempt to present kerning information
|
||||
// to the screen reader.
|
||||
break;
|
||||
}
|
||||
|
||||
case "leftright":
|
||||
{
|
||||
buildRegion(a11yStrings, regionStrings => {
|
||||
buildString(tree.left, "open", regionStrings);
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
buildString(tree.right, "close", regionStrings);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "leftright-right":
|
||||
{
|
||||
// TODO: double check that this is a no-op
|
||||
break;
|
||||
}
|
||||
|
||||
case "lap":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "mathord":
|
||||
{
|
||||
buildString(tree.text, "normal", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "op":
|
||||
{
|
||||
const {
|
||||
body,
|
||||
name
|
||||
} = tree;
|
||||
|
||||
if (body) {
|
||||
buildA11yStrings(body, a11yStrings, atomType);
|
||||
} else if (name) {
|
||||
buildString(name, "normal", a11yStrings);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "op-token":
|
||||
{
|
||||
// Used internally by operator symbols.
|
||||
buildString(tree.text, atomType, a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "ordgroup":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "overline":
|
||||
{
|
||||
buildRegion(a11yStrings, function (a11yStrings) {
|
||||
a11yStrings.push("start overline");
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
a11yStrings.push("end overline");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "pmb":
|
||||
{
|
||||
a11yStrings.push("bold");
|
||||
break;
|
||||
}
|
||||
|
||||
case "phantom":
|
||||
{
|
||||
a11yStrings.push("empty space");
|
||||
break;
|
||||
}
|
||||
|
||||
case "raisebox":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "rule":
|
||||
{
|
||||
a11yStrings.push("rectangle");
|
||||
break;
|
||||
}
|
||||
|
||||
case "sizing":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "spacing":
|
||||
{
|
||||
a11yStrings.push("space");
|
||||
break;
|
||||
}
|
||||
|
||||
case "styling":
|
||||
{
|
||||
// We ignore the styling and just pass through the contents
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "sqrt":
|
||||
{
|
||||
buildRegion(a11yStrings, regionStrings => {
|
||||
const {
|
||||
body,
|
||||
index
|
||||
} = tree;
|
||||
|
||||
if (index) {
|
||||
const indexString = flatten(buildA11yStrings(index, [], atomType)).join(",");
|
||||
|
||||
if (indexString === "3") {
|
||||
regionStrings.push("cube root of");
|
||||
buildA11yStrings(body, regionStrings, atomType);
|
||||
regionStrings.push("end cube root");
|
||||
return;
|
||||
}
|
||||
|
||||
regionStrings.push("root");
|
||||
regionStrings.push("start index");
|
||||
buildA11yStrings(index, regionStrings, atomType);
|
||||
regionStrings.push("end index");
|
||||
return;
|
||||
}
|
||||
|
||||
regionStrings.push("square root of");
|
||||
buildA11yStrings(body, regionStrings, atomType);
|
||||
regionStrings.push("end square root");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "supsub":
|
||||
{
|
||||
const {
|
||||
base,
|
||||
sub,
|
||||
sup
|
||||
} = tree;
|
||||
let isLog = false;
|
||||
|
||||
if (base) {
|
||||
buildA11yStrings(base, a11yStrings, atomType);
|
||||
isLog = base.type === "op" && base.name === "\\log";
|
||||
}
|
||||
|
||||
if (sub) {
|
||||
const regionName = isLog ? "base" : "subscript";
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start " + regionName);
|
||||
buildA11yStrings(sub, regionStrings, atomType);
|
||||
regionStrings.push("end " + regionName);
|
||||
});
|
||||
}
|
||||
|
||||
if (sup) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
const supString = flatten(buildA11yStrings(sup, [], atomType)).join(",");
|
||||
|
||||
if (supString in powerMap) {
|
||||
regionStrings.push(powerMap[supString]);
|
||||
return;
|
||||
}
|
||||
|
||||
regionStrings.push("start superscript");
|
||||
buildA11yStrings(sup, regionStrings, atomType);
|
||||
regionStrings.push("end superscript");
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "text":
|
||||
{
|
||||
// TODO: handle other fonts
|
||||
if (tree.font === "\\textbf") {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start bold text");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end bold text");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start text");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end text");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "textord":
|
||||
{
|
||||
buildString(tree.text, atomType, a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "smash":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "enclose":
|
||||
{
|
||||
// TODO: create a map for these.
|
||||
// TODO: differentiate between a body with a single atom, e.g.
|
||||
// "cancel a" instead of "start cancel, a, end cancel"
|
||||
if (/cancel/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start cancel");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end cancel");
|
||||
});
|
||||
break;
|
||||
} else if (/box/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start box");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end box");
|
||||
});
|
||||
break;
|
||||
} else if (/sout/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start strikeout");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end strikeout");
|
||||
});
|
||||
break;
|
||||
} else if (/phase/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start phase angle");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end phase angle");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
throw new Error("KaTeX-a11y: enclose node with " + tree.label + " not supported yet");
|
||||
}
|
||||
|
||||
case "vcenter":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "vphantom":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: vphantom not implemented yet");
|
||||
}
|
||||
|
||||
case "hphantom":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: hphantom not implemented yet");
|
||||
}
|
||||
|
||||
case "operatorname":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "array":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: array not implemented yet");
|
||||
}
|
||||
|
||||
case "raw":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: raw not implemented yet");
|
||||
}
|
||||
|
||||
case "size":
|
||||
{
|
||||
// Although there are nodes of type "size" in the parse tree, they have
|
||||
// no semantic meaning and should be ignored.
|
||||
break;
|
||||
}
|
||||
|
||||
case "url":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: url not implemented yet");
|
||||
}
|
||||
|
||||
case "tag":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: tag not implemented yet");
|
||||
}
|
||||
|
||||
case "verb":
|
||||
{
|
||||
buildString("start verbatim", "normal", a11yStrings);
|
||||
buildString(tree.body, "normal", a11yStrings);
|
||||
buildString("end verbatim", "normal", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "environment":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: environment not implemented yet");
|
||||
}
|
||||
|
||||
case "horizBrace":
|
||||
{
|
||||
buildString("start " + tree.label.slice(1), "normal", a11yStrings);
|
||||
buildA11yStrings(tree.base, a11yStrings, atomType);
|
||||
buildString("end " + tree.label.slice(1), "normal", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "infix":
|
||||
{
|
||||
// All infix nodes are replace with other nodes.
|
||||
break;
|
||||
}
|
||||
|
||||
case "includegraphics":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: includegraphics not implemented yet");
|
||||
}
|
||||
|
||||
case "font":
|
||||
{
|
||||
// TODO: callout the start/end of specific fonts
|
||||
// TODO: map \BBb{N} to "the naturals" or something like that
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "href":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: href not implemented yet");
|
||||
}
|
||||
|
||||
case "cr":
|
||||
{
|
||||
// This is used by environments.
|
||||
throw new Error("KaTeX-a11y: cr not implemented yet");
|
||||
}
|
||||
|
||||
case "underline":
|
||||
{
|
||||
buildRegion(a11yStrings, function (a11yStrings) {
|
||||
a11yStrings.push("start underline");
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
a11yStrings.push("end underline");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "xArrow":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: xArrow not implemented yet");
|
||||
}
|
||||
|
||||
case "cdlabel":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: cdlabel not implemented yet");
|
||||
}
|
||||
|
||||
case "cdlabelparent":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: cdlabelparent not implemented yet");
|
||||
}
|
||||
|
||||
case "mclass":
|
||||
{
|
||||
// \neq and \ne are macros so we let "htmlmathml" render the mathmal
|
||||
// side of things and extract the text from that.
|
||||
const atomType = tree.mclass.slice(1); // $FlowFixMe: drop the leading "m" from the values in mclass
|
||||
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "mathchoice":
|
||||
{
|
||||
// TODO: track which style we're using, e.g. display, text, etc.
|
||||
// default to text style if even that may not be the correct style
|
||||
buildA11yStrings(tree.text, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "htmlmathml":
|
||||
{
|
||||
buildA11yStrings(tree.mathml, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "middle":
|
||||
{
|
||||
buildString(tree.delim, atomType, a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "internal":
|
||||
{
|
||||
// internal nodes are never included in the parse tree
|
||||
break;
|
||||
}
|
||||
|
||||
case "html":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
tree.type;
|
||||
throw new Error("KaTeX a11y un-recognized type: " + tree.type);
|
||||
}
|
||||
};
|
||||
|
||||
const buildA11yStrings = function (tree, a11yStrings, atomType) {
|
||||
if (a11yStrings === void 0) {
|
||||
a11yStrings = [];
|
||||
}
|
||||
|
||||
if (tree instanceof Array) {
|
||||
for (let i = 0; i < tree.length; i++) {
|
||||
buildA11yStrings(tree[i], a11yStrings, atomType);
|
||||
}
|
||||
} else {
|
||||
handleObject(tree, a11yStrings, atomType);
|
||||
}
|
||||
|
||||
return a11yStrings;
|
||||
};
|
||||
|
||||
const flatten = function (array) {
|
||||
let result = [];
|
||||
array.forEach(function (item) {
|
||||
if (item instanceof Array) {
|
||||
result = result.concat(flatten(item));
|
||||
} else {
|
||||
result.push(item);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
const renderA11yString = function (text, settings) {
|
||||
const tree = katex__WEBPACK_IMPORTED_MODULE_0___default().__parse(text, settings);
|
||||
|
||||
const a11yStrings = buildA11yStrings(tree, [], "normal");
|
||||
return flatten(a11yStrings).join(", ");
|
||||
};
|
||||
|
||||
/* harmony default export */ __webpack_exports__["default"] = (renderA11yString);
|
||||
__webpack_exports__ = __webpack_exports__["default"];
|
||||
/******/ return __webpack_exports__;
|
||||
/******/ })()
|
||||
;
|
||||
});
|
||||
1
node_modules/katex/dist/contrib/render-a11y-string.min.js
generated
vendored
Normal file
1
node_modules/katex/dist/contrib/render-a11y-string.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
800
node_modules/katex/dist/contrib/render-a11y-string.mjs
generated
vendored
Normal file
800
node_modules/katex/dist/contrib/render-a11y-string.mjs
generated
vendored
Normal file
@@ -0,0 +1,800 @@
|
||||
import katex from '../katex.mjs';
|
||||
|
||||
/**
|
||||
* renderA11yString returns a readable string.
|
||||
*
|
||||
* In some cases the string will have the proper semantic math
|
||||
* meaning,:
|
||||
* renderA11yString("\\frac{1}{2}"")
|
||||
* -> "start fraction, 1, divided by, 2, end fraction"
|
||||
*
|
||||
* However, other cases do not:
|
||||
* renderA11yString("f(x) = x^2")
|
||||
* -> "f, left parenthesis, x, right parenthesis, equals, x, squared"
|
||||
*
|
||||
* The commas in the string aim to increase ease of understanding
|
||||
* when read by a screenreader.
|
||||
*/
|
||||
var stringMap = {
|
||||
"(": "left parenthesis",
|
||||
")": "right parenthesis",
|
||||
"[": "open bracket",
|
||||
"]": "close bracket",
|
||||
"\\{": "left brace",
|
||||
"\\}": "right brace",
|
||||
"\\lvert": "open vertical bar",
|
||||
"\\rvert": "close vertical bar",
|
||||
"|": "vertical bar",
|
||||
"\\uparrow": "up arrow",
|
||||
"\\Uparrow": "up arrow",
|
||||
"\\downarrow": "down arrow",
|
||||
"\\Downarrow": "down arrow",
|
||||
"\\updownarrow": "up down arrow",
|
||||
"\\leftarrow": "left arrow",
|
||||
"\\Leftarrow": "left arrow",
|
||||
"\\rightarrow": "right arrow",
|
||||
"\\Rightarrow": "right arrow",
|
||||
"\\langle": "open angle",
|
||||
"\\rangle": "close angle",
|
||||
"\\lfloor": "open floor",
|
||||
"\\rfloor": "close floor",
|
||||
"\\int": "integral",
|
||||
"\\intop": "integral",
|
||||
"\\lim": "limit",
|
||||
"\\ln": "natural log",
|
||||
"\\log": "log",
|
||||
"\\sin": "sine",
|
||||
"\\cos": "cosine",
|
||||
"\\tan": "tangent",
|
||||
"\\cot": "cotangent",
|
||||
"\\sum": "sum",
|
||||
"/": "slash",
|
||||
",": "comma",
|
||||
".": "point",
|
||||
"-": "negative",
|
||||
"+": "plus",
|
||||
"~": "tilde",
|
||||
":": "colon",
|
||||
"?": "question mark",
|
||||
"'": "apostrophe",
|
||||
"\\%": "percent",
|
||||
" ": "space",
|
||||
"\\ ": "space",
|
||||
"\\$": "dollar sign",
|
||||
"\\angle": "angle",
|
||||
"\\degree": "degree",
|
||||
"\\circ": "circle",
|
||||
"\\vec": "vector",
|
||||
"\\triangle": "triangle",
|
||||
"\\pi": "pi",
|
||||
"\\prime": "prime",
|
||||
"\\infty": "infinity",
|
||||
"\\alpha": "alpha",
|
||||
"\\beta": "beta",
|
||||
"\\gamma": "gamma",
|
||||
"\\omega": "omega",
|
||||
"\\theta": "theta",
|
||||
"\\sigma": "sigma",
|
||||
"\\lambda": "lambda",
|
||||
"\\tau": "tau",
|
||||
"\\Delta": "delta",
|
||||
"\\delta": "delta",
|
||||
"\\mu": "mu",
|
||||
"\\rho": "rho",
|
||||
"\\nabla": "del",
|
||||
"\\ell": "ell",
|
||||
"\\ldots": "dots",
|
||||
// TODO: add entries for all accents
|
||||
"\\hat": "hat",
|
||||
"\\acute": "acute"
|
||||
};
|
||||
var powerMap = {
|
||||
"prime": "prime",
|
||||
"degree": "degrees",
|
||||
"circle": "degrees",
|
||||
"2": "squared",
|
||||
"3": "cubed"
|
||||
};
|
||||
var openMap = {
|
||||
"|": "open vertical bar",
|
||||
".": ""
|
||||
};
|
||||
var closeMap = {
|
||||
"|": "close vertical bar",
|
||||
".": ""
|
||||
};
|
||||
var binMap = {
|
||||
"+": "plus",
|
||||
"-": "minus",
|
||||
"\\pm": "plus minus",
|
||||
"\\cdot": "dot",
|
||||
"*": "times",
|
||||
"/": "divided by",
|
||||
"\\times": "times",
|
||||
"\\div": "divided by",
|
||||
"\\circ": "circle",
|
||||
"\\bullet": "bullet"
|
||||
};
|
||||
var relMap = {
|
||||
"=": "equals",
|
||||
"\\approx": "approximately equals",
|
||||
"≠": "does not equal",
|
||||
"\\geq": "is greater than or equal to",
|
||||
"\\ge": "is greater than or equal to",
|
||||
"\\leq": "is less than or equal to",
|
||||
"\\le": "is less than or equal to",
|
||||
">": "is greater than",
|
||||
"<": "is less than",
|
||||
"\\leftarrow": "left arrow",
|
||||
"\\Leftarrow": "left arrow",
|
||||
"\\rightarrow": "right arrow",
|
||||
"\\Rightarrow": "right arrow",
|
||||
":": "colon"
|
||||
};
|
||||
var accentUnderMap = {
|
||||
"\\underleftarrow": "left arrow",
|
||||
"\\underrightarrow": "right arrow",
|
||||
"\\underleftrightarrow": "left-right arrow",
|
||||
"\\undergroup": "group",
|
||||
"\\underlinesegment": "line segment",
|
||||
"\\utilde": "tilde"
|
||||
};
|
||||
|
||||
var buildString = (str, type, a11yStrings) => {
|
||||
if (!str) {
|
||||
return;
|
||||
}
|
||||
|
||||
var ret;
|
||||
|
||||
if (type === "open") {
|
||||
ret = str in openMap ? openMap[str] : stringMap[str] || str;
|
||||
} else if (type === "close") {
|
||||
ret = str in closeMap ? closeMap[str] : stringMap[str] || str;
|
||||
} else if (type === "bin") {
|
||||
ret = binMap[str] || str;
|
||||
} else if (type === "rel") {
|
||||
ret = relMap[str] || str;
|
||||
} else {
|
||||
ret = stringMap[str] || str;
|
||||
} // If the text to add is a number and there is already a string
|
||||
// in the list and the last string is a number then we should
|
||||
// combine them into a single number
|
||||
|
||||
|
||||
if (/^\d+$/.test(ret) && a11yStrings.length > 0 && // TODO(kevinb): check that the last item in a11yStrings is a string
|
||||
// I think we might be able to drop the nested arrays, which would make
|
||||
// this easier to type
|
||||
// $FlowFixMe
|
||||
/^\d+$/.test(a11yStrings[a11yStrings.length - 1])) {
|
||||
a11yStrings[a11yStrings.length - 1] += ret;
|
||||
} else if (ret) {
|
||||
a11yStrings.push(ret);
|
||||
}
|
||||
};
|
||||
|
||||
var buildRegion = (a11yStrings, callback) => {
|
||||
var regionStrings = [];
|
||||
a11yStrings.push(regionStrings);
|
||||
callback(regionStrings);
|
||||
};
|
||||
|
||||
var handleObject = (tree, a11yStrings, atomType) => {
|
||||
// Everything else is assumed to be an object...
|
||||
switch (tree.type) {
|
||||
case "accent":
|
||||
{
|
||||
buildRegion(a11yStrings, a11yStrings => {
|
||||
buildA11yStrings(tree.base, a11yStrings, atomType);
|
||||
a11yStrings.push("with");
|
||||
buildString(tree.label, "normal", a11yStrings);
|
||||
a11yStrings.push("on top");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "accentUnder":
|
||||
{
|
||||
buildRegion(a11yStrings, a11yStrings => {
|
||||
buildA11yStrings(tree.base, a11yStrings, atomType);
|
||||
a11yStrings.push("with");
|
||||
buildString(accentUnderMap[tree.label], "normal", a11yStrings);
|
||||
a11yStrings.push("underneath");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "accent-token":
|
||||
{
|
||||
// Used internally by accent symbols.
|
||||
break;
|
||||
}
|
||||
|
||||
case "atom":
|
||||
{
|
||||
var {
|
||||
text
|
||||
} = tree;
|
||||
|
||||
switch (tree.family) {
|
||||
case "bin":
|
||||
{
|
||||
buildString(text, "bin", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "close":
|
||||
{
|
||||
buildString(text, "close", a11yStrings);
|
||||
break;
|
||||
}
|
||||
// TODO(kevinb): figure out what should be done for inner
|
||||
|
||||
case "inner":
|
||||
{
|
||||
buildString(tree.text, "inner", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "open":
|
||||
{
|
||||
buildString(text, "open", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "punct":
|
||||
{
|
||||
buildString(text, "punct", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "rel":
|
||||
{
|
||||
buildString(text, "rel", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
tree.family;
|
||||
throw new Error("\"" + tree.family + "\" is not a valid atom type");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "color":
|
||||
{
|
||||
var color = tree.color.replace(/katex-/, "");
|
||||
buildRegion(a11yStrings, regionStrings => {
|
||||
regionStrings.push("start color " + color);
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end color " + color);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "color-token":
|
||||
{
|
||||
// Used by \color, \colorbox, and \fcolorbox but not directly rendered.
|
||||
// It's a leaf node and has no children so just break.
|
||||
break;
|
||||
}
|
||||
|
||||
case "delimsizing":
|
||||
{
|
||||
if (tree.delim && tree.delim !== ".") {
|
||||
buildString(tree.delim, "normal", a11yStrings);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "genfrac":
|
||||
{
|
||||
buildRegion(a11yStrings, regionStrings => {
|
||||
// genfrac can have unbalanced delimiters
|
||||
var {
|
||||
leftDelim,
|
||||
rightDelim
|
||||
} = tree; // NOTE: Not sure if this is a safe assumption
|
||||
// hasBarLine true -> fraction, false -> binomial
|
||||
|
||||
if (tree.hasBarLine) {
|
||||
regionStrings.push("start fraction");
|
||||
leftDelim && buildString(leftDelim, "open", regionStrings);
|
||||
buildA11yStrings(tree.numer, regionStrings, atomType);
|
||||
regionStrings.push("divided by");
|
||||
buildA11yStrings(tree.denom, regionStrings, atomType);
|
||||
rightDelim && buildString(rightDelim, "close", regionStrings);
|
||||
regionStrings.push("end fraction");
|
||||
} else {
|
||||
regionStrings.push("start binomial");
|
||||
leftDelim && buildString(leftDelim, "open", regionStrings);
|
||||
buildA11yStrings(tree.numer, regionStrings, atomType);
|
||||
regionStrings.push("over");
|
||||
buildA11yStrings(tree.denom, regionStrings, atomType);
|
||||
rightDelim && buildString(rightDelim, "close", regionStrings);
|
||||
regionStrings.push("end binomial");
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "hbox":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "kern":
|
||||
{
|
||||
// No op: we don't attempt to present kerning information
|
||||
// to the screen reader.
|
||||
break;
|
||||
}
|
||||
|
||||
case "leftright":
|
||||
{
|
||||
buildRegion(a11yStrings, regionStrings => {
|
||||
buildString(tree.left, "open", regionStrings);
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
buildString(tree.right, "close", regionStrings);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "leftright-right":
|
||||
{
|
||||
// TODO: double check that this is a no-op
|
||||
break;
|
||||
}
|
||||
|
||||
case "lap":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "mathord":
|
||||
{
|
||||
buildString(tree.text, "normal", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "op":
|
||||
{
|
||||
var {
|
||||
body,
|
||||
name
|
||||
} = tree;
|
||||
|
||||
if (body) {
|
||||
buildA11yStrings(body, a11yStrings, atomType);
|
||||
} else if (name) {
|
||||
buildString(name, "normal", a11yStrings);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "op-token":
|
||||
{
|
||||
// Used internally by operator symbols.
|
||||
buildString(tree.text, atomType, a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "ordgroup":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "overline":
|
||||
{
|
||||
buildRegion(a11yStrings, function (a11yStrings) {
|
||||
a11yStrings.push("start overline");
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
a11yStrings.push("end overline");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "pmb":
|
||||
{
|
||||
a11yStrings.push("bold");
|
||||
break;
|
||||
}
|
||||
|
||||
case "phantom":
|
||||
{
|
||||
a11yStrings.push("empty space");
|
||||
break;
|
||||
}
|
||||
|
||||
case "raisebox":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "rule":
|
||||
{
|
||||
a11yStrings.push("rectangle");
|
||||
break;
|
||||
}
|
||||
|
||||
case "sizing":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "spacing":
|
||||
{
|
||||
a11yStrings.push("space");
|
||||
break;
|
||||
}
|
||||
|
||||
case "styling":
|
||||
{
|
||||
// We ignore the styling and just pass through the contents
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "sqrt":
|
||||
{
|
||||
buildRegion(a11yStrings, regionStrings => {
|
||||
var {
|
||||
body,
|
||||
index
|
||||
} = tree;
|
||||
|
||||
if (index) {
|
||||
var indexString = flatten(buildA11yStrings(index, [], atomType)).join(",");
|
||||
|
||||
if (indexString === "3") {
|
||||
regionStrings.push("cube root of");
|
||||
buildA11yStrings(body, regionStrings, atomType);
|
||||
regionStrings.push("end cube root");
|
||||
return;
|
||||
}
|
||||
|
||||
regionStrings.push("root");
|
||||
regionStrings.push("start index");
|
||||
buildA11yStrings(index, regionStrings, atomType);
|
||||
regionStrings.push("end index");
|
||||
return;
|
||||
}
|
||||
|
||||
regionStrings.push("square root of");
|
||||
buildA11yStrings(body, regionStrings, atomType);
|
||||
regionStrings.push("end square root");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "supsub":
|
||||
{
|
||||
var {
|
||||
base,
|
||||
sub,
|
||||
sup
|
||||
} = tree;
|
||||
var isLog = false;
|
||||
|
||||
if (base) {
|
||||
buildA11yStrings(base, a11yStrings, atomType);
|
||||
isLog = base.type === "op" && base.name === "\\log";
|
||||
}
|
||||
|
||||
if (sub) {
|
||||
var regionName = isLog ? "base" : "subscript";
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start " + regionName);
|
||||
buildA11yStrings(sub, regionStrings, atomType);
|
||||
regionStrings.push("end " + regionName);
|
||||
});
|
||||
}
|
||||
|
||||
if (sup) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
var supString = flatten(buildA11yStrings(sup, [], atomType)).join(",");
|
||||
|
||||
if (supString in powerMap) {
|
||||
regionStrings.push(powerMap[supString]);
|
||||
return;
|
||||
}
|
||||
|
||||
regionStrings.push("start superscript");
|
||||
buildA11yStrings(sup, regionStrings, atomType);
|
||||
regionStrings.push("end superscript");
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case "text":
|
||||
{
|
||||
// TODO: handle other fonts
|
||||
if (tree.font === "\\textbf") {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start bold text");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end bold text");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start text");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end text");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "textord":
|
||||
{
|
||||
buildString(tree.text, atomType, a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "smash":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "enclose":
|
||||
{
|
||||
// TODO: create a map for these.
|
||||
// TODO: differentiate between a body with a single atom, e.g.
|
||||
// "cancel a" instead of "start cancel, a, end cancel"
|
||||
if (/cancel/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start cancel");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end cancel");
|
||||
});
|
||||
break;
|
||||
} else if (/box/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start box");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end box");
|
||||
});
|
||||
break;
|
||||
} else if (/sout/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start strikeout");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end strikeout");
|
||||
});
|
||||
break;
|
||||
} else if (/phase/.test(tree.label)) {
|
||||
buildRegion(a11yStrings, function (regionStrings) {
|
||||
regionStrings.push("start phase angle");
|
||||
buildA11yStrings(tree.body, regionStrings, atomType);
|
||||
regionStrings.push("end phase angle");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
throw new Error("KaTeX-a11y: enclose node with " + tree.label + " not supported yet");
|
||||
}
|
||||
|
||||
case "vcenter":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "vphantom":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: vphantom not implemented yet");
|
||||
}
|
||||
|
||||
case "hphantom":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: hphantom not implemented yet");
|
||||
}
|
||||
|
||||
case "operatorname":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "array":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: array not implemented yet");
|
||||
}
|
||||
|
||||
case "raw":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: raw not implemented yet");
|
||||
}
|
||||
|
||||
case "size":
|
||||
{
|
||||
// Although there are nodes of type "size" in the parse tree, they have
|
||||
// no semantic meaning and should be ignored.
|
||||
break;
|
||||
}
|
||||
|
||||
case "url":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: url not implemented yet");
|
||||
}
|
||||
|
||||
case "tag":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: tag not implemented yet");
|
||||
}
|
||||
|
||||
case "verb":
|
||||
{
|
||||
buildString("start verbatim", "normal", a11yStrings);
|
||||
buildString(tree.body, "normal", a11yStrings);
|
||||
buildString("end verbatim", "normal", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "environment":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: environment not implemented yet");
|
||||
}
|
||||
|
||||
case "horizBrace":
|
||||
{
|
||||
buildString("start " + tree.label.slice(1), "normal", a11yStrings);
|
||||
buildA11yStrings(tree.base, a11yStrings, atomType);
|
||||
buildString("end " + tree.label.slice(1), "normal", a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "infix":
|
||||
{
|
||||
// All infix nodes are replace with other nodes.
|
||||
break;
|
||||
}
|
||||
|
||||
case "includegraphics":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: includegraphics not implemented yet");
|
||||
}
|
||||
|
||||
case "font":
|
||||
{
|
||||
// TODO: callout the start/end of specific fonts
|
||||
// TODO: map \BBb{N} to "the naturals" or something like that
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "href":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: href not implemented yet");
|
||||
}
|
||||
|
||||
case "cr":
|
||||
{
|
||||
// This is used by environments.
|
||||
throw new Error("KaTeX-a11y: cr not implemented yet");
|
||||
}
|
||||
|
||||
case "underline":
|
||||
{
|
||||
buildRegion(a11yStrings, function (a11yStrings) {
|
||||
a11yStrings.push("start underline");
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
a11yStrings.push("end underline");
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case "xArrow":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: xArrow not implemented yet");
|
||||
}
|
||||
|
||||
case "cdlabel":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: cdlabel not implemented yet");
|
||||
}
|
||||
|
||||
case "cdlabelparent":
|
||||
{
|
||||
throw new Error("KaTeX-a11y: cdlabelparent not implemented yet");
|
||||
}
|
||||
|
||||
case "mclass":
|
||||
{
|
||||
// \neq and \ne are macros so we let "htmlmathml" render the mathmal
|
||||
// side of things and extract the text from that.
|
||||
var _atomType = tree.mclass.slice(1); // $FlowFixMe: drop the leading "m" from the values in mclass
|
||||
|
||||
|
||||
buildA11yStrings(tree.body, a11yStrings, _atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "mathchoice":
|
||||
{
|
||||
// TODO: track which style we're using, e.g. display, text, etc.
|
||||
// default to text style if even that may not be the correct style
|
||||
buildA11yStrings(tree.text, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "htmlmathml":
|
||||
{
|
||||
buildA11yStrings(tree.mathml, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
case "middle":
|
||||
{
|
||||
buildString(tree.delim, atomType, a11yStrings);
|
||||
break;
|
||||
}
|
||||
|
||||
case "internal":
|
||||
{
|
||||
// internal nodes are never included in the parse tree
|
||||
break;
|
||||
}
|
||||
|
||||
case "html":
|
||||
{
|
||||
buildA11yStrings(tree.body, a11yStrings, atomType);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
tree.type;
|
||||
throw new Error("KaTeX a11y un-recognized type: " + tree.type);
|
||||
}
|
||||
};
|
||||
|
||||
var buildA11yStrings = function buildA11yStrings(tree, a11yStrings, atomType) {
|
||||
if (a11yStrings === void 0) {
|
||||
a11yStrings = [];
|
||||
}
|
||||
|
||||
if (tree instanceof Array) {
|
||||
for (var i = 0; i < tree.length; i++) {
|
||||
buildA11yStrings(tree[i], a11yStrings, atomType);
|
||||
}
|
||||
} else {
|
||||
handleObject(tree, a11yStrings, atomType);
|
||||
}
|
||||
|
||||
return a11yStrings;
|
||||
};
|
||||
|
||||
var flatten = function flatten(array) {
|
||||
var result = [];
|
||||
array.forEach(function (item) {
|
||||
if (item instanceof Array) {
|
||||
result = result.concat(flatten(item));
|
||||
} else {
|
||||
result.push(item);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
var renderA11yString = function renderA11yString(text, settings) {
|
||||
var tree = katex.__parse(text, settings);
|
||||
|
||||
var a11yStrings = buildA11yStrings(tree, [], "normal");
|
||||
return flatten(a11yStrings).join(", ");
|
||||
};
|
||||
|
||||
export { renderA11yString as default };
|
||||
BIN
node_modules/katex/dist/fonts/KaTeX_AMS-Regular.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_AMS-Regular.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_AMS-Regular.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_AMS-Regular.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_AMS-Regular.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_AMS-Regular.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Caligraphic-Bold.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Caligraphic-Bold.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Caligraphic-Bold.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Caligraphic-Bold.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Caligraphic-Bold.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Caligraphic-Bold.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Caligraphic-Regular.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Caligraphic-Regular.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Caligraphic-Regular.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Caligraphic-Regular.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Caligraphic-Regular.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Caligraphic-Regular.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Fraktur-Bold.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Fraktur-Bold.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Fraktur-Bold.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Fraktur-Bold.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Fraktur-Bold.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Fraktur-Bold.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Fraktur-Regular.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Fraktur-Regular.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Fraktur-Regular.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Fraktur-Regular.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Fraktur-Regular.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Fraktur-Regular.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Main-Bold.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Main-Bold.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Main-Bold.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Main-Bold.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Main-Bold.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Main-Bold.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Main-BoldItalic.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Main-BoldItalic.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Main-BoldItalic.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Main-BoldItalic.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Main-BoldItalic.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Main-BoldItalic.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Main-Italic.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Main-Italic.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Main-Italic.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Main-Italic.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Main-Italic.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Main-Italic.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Main-Regular.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Main-Regular.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Main-Regular.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Main-Regular.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Main-Regular.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Main-Regular.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Math-BoldItalic.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Math-BoldItalic.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Math-BoldItalic.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Math-BoldItalic.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Math-BoldItalic.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Math-BoldItalic.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Math-Italic.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Math-Italic.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Math-Italic.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Math-Italic.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Math-Italic.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Math-Italic.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_SansSerif-Bold.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_SansSerif-Bold.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_SansSerif-Bold.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_SansSerif-Bold.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_SansSerif-Bold.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_SansSerif-Bold.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_SansSerif-Italic.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_SansSerif-Italic.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_SansSerif-Italic.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_SansSerif-Italic.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_SansSerif-Italic.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_SansSerif-Italic.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_SansSerif-Regular.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_SansSerif-Regular.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_SansSerif-Regular.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_SansSerif-Regular.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_SansSerif-Regular.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_SansSerif-Regular.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Script-Regular.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Script-Regular.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Script-Regular.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Script-Regular.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Script-Regular.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Script-Regular.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Size1-Regular.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Size1-Regular.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Size1-Regular.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Size1-Regular.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Size1-Regular.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Size1-Regular.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Size2-Regular.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Size2-Regular.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Size2-Regular.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Size2-Regular.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Size2-Regular.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Size2-Regular.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Size3-Regular.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Size3-Regular.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Size3-Regular.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Size3-Regular.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Size3-Regular.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Size3-Regular.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Size4-Regular.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Size4-Regular.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Size4-Regular.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Size4-Regular.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Size4-Regular.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Size4-Regular.woff2
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Typewriter-Regular.ttf
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Typewriter-Regular.ttf
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Typewriter-Regular.woff
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Typewriter-Regular.woff
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/katex/dist/fonts/KaTeX_Typewriter-Regular.woff2
generated
vendored
Normal file
BIN
node_modules/katex/dist/fonts/KaTeX_Typewriter-Regular.woff2
generated
vendored
Normal file
Binary file not shown.
1210
node_modules/katex/dist/katex.css
generated
vendored
Normal file
1210
node_modules/katex/dist/katex.css
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
19092
node_modules/katex/dist/katex.js
generated
vendored
Normal file
19092
node_modules/katex/dist/katex.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
node_modules/katex/dist/katex.min.css
generated
vendored
Normal file
1
node_modules/katex/dist/katex.min.css
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
node_modules/katex/dist/katex.min.js
generated
vendored
Normal file
1
node_modules/katex/dist/katex.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
18549
node_modules/katex/dist/katex.mjs
generated
vendored
Normal file
18549
node_modules/katex/dist/katex.mjs
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
247
node_modules/katex/katex.js
generated
vendored
Normal file
247
node_modules/katex/katex.js
generated
vendored
Normal file
@@ -0,0 +1,247 @@
|
||||
// @flow
|
||||
/* eslint no-console:0 */
|
||||
/**
|
||||
* This is the main entry point for KaTeX. Here, we expose functions for
|
||||
* rendering expressions either to DOM nodes or to markup strings.
|
||||
*
|
||||
* We also expose the ParseError class to check if errors thrown from KaTeX are
|
||||
* errors in the expression, or errors in javascript handling.
|
||||
*/
|
||||
|
||||
import ParseError from "./src/ParseError";
|
||||
import Settings, {SETTINGS_SCHEMA} from "./src/Settings";
|
||||
|
||||
import {buildTree, buildHTMLTree} from "./src/buildTree";
|
||||
import parseTree from "./src/parseTree";
|
||||
import buildCommon from "./src/buildCommon";
|
||||
import {
|
||||
Span,
|
||||
Anchor,
|
||||
SymbolNode,
|
||||
SvgNode,
|
||||
PathNode,
|
||||
LineNode,
|
||||
} from "./src/domTree";
|
||||
|
||||
import type {SettingsOptions} from "./src/Settings";
|
||||
import type {AnyParseNode} from "./src/parseNode";
|
||||
import type {DomSpan} from "./src/domTree";
|
||||
|
||||
import {defineSymbol} from './src/symbols';
|
||||
import defineFunction from './src/defineFunction';
|
||||
import defineMacro from './src/defineMacro';
|
||||
import {setFontMetrics} from './src/fontMetrics';
|
||||
|
||||
declare var __VERSION__: string;
|
||||
|
||||
/**
|
||||
* Parse and build an expression, and place that expression in the DOM node
|
||||
* given.
|
||||
*/
|
||||
let render: (string, Node, SettingsOptions) => void = function(
|
||||
expression: string,
|
||||
baseNode: Node,
|
||||
options: SettingsOptions,
|
||||
) {
|
||||
baseNode.textContent = "";
|
||||
const node = renderToDomTree(expression, options).toNode();
|
||||
baseNode.appendChild(node);
|
||||
};
|
||||
|
||||
// KaTeX's styles don't work properly in quirks mode. Print out an error, and
|
||||
// disable rendering.
|
||||
if (typeof document !== "undefined") {
|
||||
if (document.compatMode !== "CSS1Compat") {
|
||||
typeof console !== "undefined" && console.warn(
|
||||
"Warning: KaTeX doesn't work in quirks mode. Make sure your " +
|
||||
"website has a suitable doctype.");
|
||||
|
||||
render = function() {
|
||||
throw new ParseError("KaTeX doesn't work in quirks mode.");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse and build an expression, and return the markup for that.
|
||||
*/
|
||||
const renderToString = function(
|
||||
expression: string,
|
||||
options: SettingsOptions,
|
||||
): string {
|
||||
const markup = renderToDomTree(expression, options).toMarkup();
|
||||
return markup;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse an expression and return the parse tree.
|
||||
*/
|
||||
const generateParseTree = function(
|
||||
expression: string,
|
||||
options: SettingsOptions,
|
||||
): AnyParseNode[] {
|
||||
const settings = new Settings(options);
|
||||
return parseTree(expression, settings);
|
||||
};
|
||||
|
||||
/**
|
||||
* If the given error is a KaTeX ParseError and options.throwOnError is false,
|
||||
* renders the invalid LaTeX as a span with hover title giving the KaTeX
|
||||
* error message. Otherwise, simply throws the error.
|
||||
*/
|
||||
const renderError = function(
|
||||
error,
|
||||
expression: string,
|
||||
options: Settings,
|
||||
) {
|
||||
if (options.throwOnError || !(error instanceof ParseError)) {
|
||||
throw error;
|
||||
}
|
||||
const node = buildCommon.makeSpan(["katex-error"],
|
||||
[new SymbolNode(expression)]);
|
||||
node.setAttribute("title", error.toString());
|
||||
node.setAttribute("style", `color:${options.errorColor}`);
|
||||
return node;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates and returns the katex build tree. This is used for advanced
|
||||
* use cases (like rendering to custom output).
|
||||
*/
|
||||
const renderToDomTree = function(
|
||||
expression: string,
|
||||
options: SettingsOptions,
|
||||
): DomSpan {
|
||||
const settings = new Settings(options);
|
||||
try {
|
||||
const tree = parseTree(expression, settings);
|
||||
return buildTree(tree, expression, settings);
|
||||
} catch (error) {
|
||||
return renderError(error, expression, settings);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates and returns the katex build tree, with just HTML (no MathML).
|
||||
* This is used for advanced use cases (like rendering to custom output).
|
||||
*/
|
||||
const renderToHTMLTree = function(
|
||||
expression: string,
|
||||
options: SettingsOptions,
|
||||
): DomSpan {
|
||||
const settings = new Settings(options);
|
||||
try {
|
||||
const tree = parseTree(expression, settings);
|
||||
return buildHTMLTree(tree, expression, settings);
|
||||
} catch (error) {
|
||||
return renderError(error, expression, settings);
|
||||
}
|
||||
};
|
||||
|
||||
const version = __VERSION__;
|
||||
|
||||
const __domTree = {
|
||||
Span,
|
||||
Anchor,
|
||||
SymbolNode,
|
||||
SvgNode,
|
||||
PathNode,
|
||||
LineNode,
|
||||
};
|
||||
|
||||
// ESM exports
|
||||
export {
|
||||
version,
|
||||
render,
|
||||
renderToString,
|
||||
ParseError,
|
||||
SETTINGS_SCHEMA,
|
||||
generateParseTree as __parse,
|
||||
renderToDomTree as __renderToDomTree,
|
||||
renderToHTMLTree as __renderToHTMLTree,
|
||||
setFontMetrics as __setFontMetrics,
|
||||
defineSymbol as __defineSymbol,
|
||||
defineFunction as __defineFunction,
|
||||
defineMacro as __defineMacro,
|
||||
__domTree,
|
||||
};
|
||||
|
||||
// CJS exports and ESM default export
|
||||
export default {
|
||||
/**
|
||||
* Current KaTeX version
|
||||
*/
|
||||
version,
|
||||
/**
|
||||
* Renders the given LaTeX into an HTML+MathML combination, and adds
|
||||
* it as a child to the specified DOM node.
|
||||
*/
|
||||
render,
|
||||
/**
|
||||
* Renders the given LaTeX into an HTML+MathML combination string,
|
||||
* for sending to the client.
|
||||
*/
|
||||
renderToString,
|
||||
/**
|
||||
* KaTeX error, usually during parsing.
|
||||
*/
|
||||
ParseError,
|
||||
/**
|
||||
* The schema of Settings
|
||||
*/
|
||||
SETTINGS_SCHEMA,
|
||||
/**
|
||||
* Parses the given LaTeX into KaTeX's internal parse tree structure,
|
||||
* without rendering to HTML or MathML.
|
||||
*
|
||||
* NOTE: This method is not currently recommended for public use.
|
||||
* The internal tree representation is unstable and is very likely
|
||||
* to change. Use at your own risk.
|
||||
*/
|
||||
__parse: generateParseTree,
|
||||
/**
|
||||
* Renders the given LaTeX into an HTML+MathML internal DOM tree
|
||||
* representation, without flattening that representation to a string.
|
||||
*
|
||||
* NOTE: This method is not currently recommended for public use.
|
||||
* The internal tree representation is unstable and is very likely
|
||||
* to change. Use at your own risk.
|
||||
*/
|
||||
__renderToDomTree: renderToDomTree,
|
||||
/**
|
||||
* Renders the given LaTeX into an HTML internal DOM tree representation,
|
||||
* without MathML and without flattening that representation to a string.
|
||||
*
|
||||
* NOTE: This method is not currently recommended for public use.
|
||||
* The internal tree representation is unstable and is very likely
|
||||
* to change. Use at your own risk.
|
||||
*/
|
||||
__renderToHTMLTree: renderToHTMLTree,
|
||||
/**
|
||||
* extends internal font metrics object with a new object
|
||||
* each key in the new object represents a font name
|
||||
*/
|
||||
__setFontMetrics: setFontMetrics,
|
||||
/**
|
||||
* adds a new symbol to builtin symbols table
|
||||
*/
|
||||
__defineSymbol: defineSymbol,
|
||||
/**
|
||||
* adds a new function to builtin function list,
|
||||
* which directly produce parse tree elements
|
||||
* and have their own html/mathml builders
|
||||
*/
|
||||
__defineFunction: defineFunction,
|
||||
/**
|
||||
* adds a new macro to builtin macro list
|
||||
*/
|
||||
__defineMacro: defineMacro,
|
||||
/**
|
||||
* Expose the dom tree node types, which can be useful for type checking nodes.
|
||||
*
|
||||
* NOTE: These methods are not currently recommended for public use.
|
||||
* The internal tree representation is unstable and is very likely
|
||||
* to change. Use at your own risk.
|
||||
*/
|
||||
__domTree,
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user