Socket
Socket
Sign inDemoInstall

katex

Package Overview
Dependencies
Maintainers
6
Versions
77
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

katex - npm Package Compare versions

Comparing version 0.10.2 to 0.11.0

contrib/render-a11y-string/render-a11y-string.js

42

CHANGELOG.md
# Changelog
All notable changes to this project will be documented in this file. This CHANGELOG roughly follows the guidelines from [www.keepachangelog.com](https://keepachangelog.com/en/1.0.0/).
## [v0.11.0]
### Added
- **BREAKING CHANGE:** trust setting to indicate whether input text is trusted (#1794)
- `\href` and `\url` will break without adjusting the trust setting
- Add test for double square brackets to katex-spec (#1956)
- Add option to render only MathML so that its visible (#1966)
- Support {smallmatrix}, {subarray}, and \substack (#1969)
- Enable minRuleThickness in rendering options (#1964)
- Add \plim (#1952)
- Support Unicode \digamma (#2010)
- Support \operatorname* (#1899)
- Support \includegraphics, with appropriate trust setting (#2053)
- Add render-a11y-string add-on (#2062)
### Changed
- DOC: Fix path to built file (#1976)
- Remove unclosed TODO comment (#1979)
- Add "Tutti Quanti Shelf" app to users page (#1997)
- Document mhchem \cf not supported (use \ce instead) (#2008)
- Replace greenkeeper badge with dependabot badge (#2022)
- Add Unicode digamma to documentation (#2045)
- Add katex-expression to libs page (#2049)
- Suggest <!DOCTYPE html> in documentation (#2052)
- Unicode characters in math render in text mode (#2040)
### Fixed
- Improve output of fonts in MathML (#1965)
- Fix \pmb (#1924)
- \color affects following \right, put array cells in their own groups (#1845)
- Improve MathML for classes (#1929)
- Prevent gaps in tall delimiters (#1986)
- Fix \sqrt SVG path (#2009)
- Do not force sizing groups to display inline-block (#2044)
- Fix font choice in operators like \log (e.g. \boldsymbol{\log}) (#2041)
- Fix argument font sizing in \fbox and \raisebox, fix font sizing in \TeX, \LaTeX, \KaTeX (#1787)
## [v0.10.2]

@@ -11,3 +47,3 @@ ### Added

### Changed
### Changed
- Upgrade minimum development Node version to v8 (#1861)

@@ -25,3 +61,3 @@ - Disable @babel/env debug (#1874)

### Fixed
### Fixed
- Fix \Rho (#1870)

@@ -54,3 +90,3 @@ - Fix nested \dfrac (#1825)

### Removed
### Removed
- Re-added code for \includegraphics but disabled the function until trust settings is merged (#1951)

@@ -57,0 +93,0 @@

6

contrib/copy-tex/README.md

@@ -24,4 +24,4 @@ # Copy-tex extension

```html
<link href="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/contrib/copy-tex.css" rel="stylesheet" type="text/css">
<script src="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/contrib/copy-tex.min.js" integrity="sha384-XhWAe6BtVcvEdS3FFKT7Mcft4HJjPqMQvi5V4YhzH9Qxw497jC13TupOEvjoIPy7" crossorigin="anonymous"></script>
<link href="https://cdn.jsdelivr.net/npm/katex@0.11.0/dist/contrib/copy-tex.css" rel="stylesheet" type="text/css">
<script src="https://cdn.jsdelivr.net/npm/katex@0.11.0/dist/contrib/copy-tex.min.js" integrity="sha384-XhWAe6BtVcvEdS3FFKT7Mcft4HJjPqMQvi5V4YhzH9Qxw497jC13TupOEvjoIPy7" crossorigin="anonymous"></script>
```

@@ -42,3 +42,3 @@

```html
<script type="module" src="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/contrib/copy-tex.mjs" integrity="sha384-kS7UtO844uqLwxPmaRwzg1nGbKiHsIteWh+DP2cvT2FtigL0v6w1yPXYKEDzct0C" crossorigin="anonymous"></script>
<script type="module" src="https://cdn.jsdelivr.net/npm/katex@0.11.0/dist/contrib/copy-tex.mjs" integrity="sha384-kS7UtO844uqLwxPmaRwzg1nGbKiHsIteWh+DP2cvT2FtigL0v6w1yPXYKEDzct0C" crossorigin="anonymous"></script>
```` -->

@@ -45,0 +45,0 @@

@@ -15,3 +15,3 @@ # `math/tex` Custom Script Type Extension

```html
<script src="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/contrib/mathtex-script-type.min.js" integrity="sha384-LJ2FmexL77rmGm6SIpxq7y+XA6bkLzGZEgCywzKOZG/ws4va9fUVu2neMjvc3zdv"></script>
<script src="https://cdn.jsdelivr.net/npm/katex@0.11.0/dist/contrib/mathtex-script-type.min.js" integrity="sha384-LJ2FmexL77rmGm6SIpxq7y+XA6bkLzGZEgCywzKOZG/ws4va9fUVu2neMjvc3zdv"></script>
```

@@ -27,8 +27,8 @@ You can download the script and use it locally, or from a local KaTeX installation instead.

<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/katex.min.css" integrity="sha384-yFRtMMDnQtDRO8rLpMIKrtPCD5jdktao2TV19YiZYWMDkUR5GQZR/NOVTdquEx1j" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/katex.min.js" integrity="sha384-9Nhn55MVVN0/4OFx7EE5kpFBPsEMZxKTCnA+4fqDmg12eCTqGi6+BB2LjY8brQxJ" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.11.0/dist/katex.min.css" integrity="sha384-BdGj8xC2eZkQaxoQ8nSLefg4AV4/AwB3Fj+8SUSo7pnKP6Eoy18liIKTPn9oBYNG" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/katex@0.11.0/dist/katex.min.js" integrity="sha384-JiKN5O8x9Hhs/UE5cT5AAJqieYlOZbGT3CHws/y97o3ty4R7/O5poG9F3JoiOYw1" crossorigin="anonymous"></script>
</head>
<body>
<script type="math/tex">x+\sqrt{1-x^2}</script>
<script src="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/contrib/mathtex-script-type.min.js" integrity="sha384-LJ2FmexL77rmGm6SIpxq7y+XA6bkLzGZEgCywzKOZG/ws4va9fUVu2neMjvc3zdv"></script>
<script src="https://cdn.jsdelivr.net/npm/katex@0.11.0/dist/contrib/mathtex-script-type.min.js" integrity="sha384-LJ2FmexL77rmGm6SIpxq7y+XA6bkLzGZEgCywzKOZG/ws4va9fUVu2neMjvc3zdv"></script>
</body>

@@ -41,3 +41,3 @@ </html>

```html
<script type="module" src="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/contrib/mathtex-script-type.mjs" integrity="sha384-qc7HqE4GHbr2H9R+C8mTSdJmkkZ9E1bkIRyRrxMsoj3dcbGjILzoXJGcBGGns1bk" crossorigin="anonymous"></script>
<script type="module" src="https://cdn.jsdelivr.net/npm/katex@0.11.0/dist/contrib/mathtex-script-type.mjs" integrity="sha384-qc7HqE4GHbr2H9R+C8mTSdJmkkZ9E1bkIRyRrxMsoj3dcbGjILzoXJGcBGGns1bk" crossorigin="anonymous"></script>
```` -->

@@ -10,3 +10,3 @@ # mhchem extension

```html
<script src="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/contrib/mhchem.min.js" integrity="sha384-oa0lfxCGjaU1LdYckhq8LZcP+JTf8cyJXe69O6VE6UrShzWveT6KiCElJrck/stm"></script>
<script src="https://cdn.jsdelivr.net/npm/katex@0.11.0/dist/contrib/mhchem.min.js" integrity="sha384-oa0lfxCGjaU1LdYckhq8LZcP+JTf8cyJXe69O6VE6UrShzWveT6KiCElJrck/stm"></script>
```

@@ -18,4 +18,6 @@

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.

@@ -6,5 +6,5 @@ # [<img src="https://katex.org/img/katex-logo-black.svg" width="130" alt="KaTeX">](https://katex.org/)

[![Join the chat at https://gitter.im/KaTeX/KaTeX](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/KaTeX/KaTeX?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Greenkeeper badge](https://badges.greenkeeper.io/KaTeX/KaTeX.svg)](https://greenkeeper.io/)
[![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=KaTeX/KaTeX)](https://dependabot.com)
[![jsDelivr](https://data.jsdelivr.com/v1/package/npm/katex/badge?style=rounded)](https://www.jsdelivr.com/package/npm/katex)
![](https://img.badgesize.io/KaTeX/KaTeX/v0.10.2/dist/katex.min.js?compression=gzip)
![](https://img.badgesize.io/KaTeX/KaTeX/v0.11.0/dist/katex.min.js?compression=gzip)

@@ -33,9 +33,9 @@ KaTeX is a fast, easy-to-use JavaScript library for TeX math rendering on the web.

<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/katex.min.css" integrity="sha384-yFRtMMDnQtDRO8rLpMIKrtPCD5jdktao2TV19YiZYWMDkUR5GQZR/NOVTdquEx1j" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.11.0/dist/katex.min.css" integrity="sha384-BdGj8xC2eZkQaxoQ8nSLefg4AV4/AwB3Fj+8SUSo7pnKP6Eoy18liIKTPn9oBYNG" crossorigin="anonymous">
<!-- The loading of KaTeX is deferred to speed up page rendering -->
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/katex.min.js" integrity="sha384-9Nhn55MVVN0/4OFx7EE5kpFBPsEMZxKTCnA+4fqDmg12eCTqGi6+BB2LjY8brQxJ" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.11.0/dist/katex.min.js" integrity="sha384-JiKN5O8x9Hhs/UE5cT5AAJqieYlOZbGT3CHws/y97o3ty4R7/O5poG9F3JoiOYw1" 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.10.2/dist/contrib/auto-render.min.js" integrity="sha384-kWPLUVMOks5AQFrykwIup5lo0m3iMkkHrD0uJ4H5cjeGihAutqP0yW0J6dpFiVkI" crossorigin="anonymous"
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.11.0/dist/contrib/auto-render.min.js" integrity="sha384-kWPLUVMOks5AQFrykwIup5lo0m3iMkkHrD0uJ4H5cjeGihAutqP0yW0J6dpFiVkI" crossorigin="anonymous"
onload="renderMathInElement(document.body);"></script>

@@ -42,0 +42,0 @@ </head>

{
"name": "katex",
"version": "0.10.2",
"version": "0.11.0",
"description": "Fast math typesetting for the web.",

@@ -36,3 +36,3 @@ "main": "dist/katex.js",

"codecov": "^3.2.0",
"css-loader": "^2.1.0",
"css-loader": "^3.0.0",
"cssnano": "^4.1.10",

@@ -44,3 +44,3 @@ "eslint": "^5.14.1",

"file-loader": "^3.0.1",
"flow-bin": "^0.93.0",
"flow-bin": "^0.102.0",
"fs-extra": "^7.0.1",

@@ -61,2 +61,3 @@ "husky": "^1.3.1",

"postcss-loader": "^3.0.0",
"prettier": "^1.18.2",
"query-string": "^6.2.0",

@@ -63,0 +64,0 @@ "rimraf": "^2.6.3",

@@ -6,5 +6,5 @@ # [<img src="https://katex.org/img/katex-logo-black.svg" width="130" alt="KaTeX">](https://katex.org/)

[![Join the chat at https://gitter.im/KaTeX/KaTeX](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/KaTeX/KaTeX?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Greenkeeper badge](https://badges.greenkeeper.io/KaTeX/KaTeX.svg)](https://greenkeeper.io/)
[![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=KaTeX/KaTeX)](https://dependabot.com)
[![jsDelivr](https://data.jsdelivr.com/v1/package/npm/katex/badge?style=rounded)](https://www.jsdelivr.com/package/npm/katex)
![](https://img.badgesize.io/KaTeX/KaTeX/v0.10.2/dist/katex.min.js?compression=gzip)
![](https://img.badgesize.io/KaTeX/KaTeX/v0.11.0/dist/katex.min.js?compression=gzip)

@@ -33,9 +33,9 @@ KaTeX is a fast, easy-to-use JavaScript library for TeX math rendering on the web.

<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/katex.min.css" integrity="sha384-yFRtMMDnQtDRO8rLpMIKrtPCD5jdktao2TV19YiZYWMDkUR5GQZR/NOVTdquEx1j" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.11.0/dist/katex.min.css" integrity="sha384-BdGj8xC2eZkQaxoQ8nSLefg4AV4/AwB3Fj+8SUSo7pnKP6Eoy18liIKTPn9oBYNG" crossorigin="anonymous">
<!-- The loading of KaTeX is deferred to speed up page rendering -->
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/katex.min.js" integrity="sha384-9Nhn55MVVN0/4OFx7EE5kpFBPsEMZxKTCnA+4fqDmg12eCTqGi6+BB2LjY8brQxJ" crossorigin="anonymous"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.11.0/dist/katex.min.js" integrity="sha384-JiKN5O8x9Hhs/UE5cT5AAJqieYlOZbGT3CHws/y97o3ty4R7/O5poG9F3JoiOYw1" 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.10.2/dist/contrib/auto-render.min.js" integrity="sha384-kWPLUVMOks5AQFrykwIup5lo0m3iMkkHrD0uJ4H5cjeGihAutqP0yW0J6dpFiVkI" crossorigin="anonymous"
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.11.0/dist/contrib/auto-render.min.js" integrity="sha384-kWPLUVMOks5AQFrykwIup5lo0m3iMkkHrD0uJ4H5cjeGihAutqP0yW0J6dpFiVkI" crossorigin="anonymous"
onload="renderMathInElement(document.body);"></script>

@@ -42,0 +42,0 @@ </head>

@@ -83,5 +83,4 @@ // @flow

// TODO(emily): Figure out a good way to only print this in development
typeof console !== "undefined" && console.warn(
"No character metrics for '" + value + "' in style '" +
fontName + "'");
typeof console !== "undefined" && console.warn("No character metrics " +
`for '${value}' in style '${fontName}' and mode '${mode}'`);
symbolNode = new SymbolNode(value, 0, 0, 0, 0, 0, classes);

@@ -107,4 +106,2 @@ }

* Used for rel, bin, open, close, inner, and punct.
*
* TODO(#953): Make `options` mandatory and always pass it in.
*/

@@ -114,3 +111,3 @@ const mathsym = function(

mode: Mode,
options?: Options,
options: Options,
classes?: string[] = [],

@@ -125,3 +122,3 @@ ): SymbolNode {

// can be used for bold + and -
if ((options && options.font && options.font === "boldsymbol") &&
if (options.font === "boldsymbol" &&
lookupSymbol(value, "Main-Bold", mode).metrics) {

@@ -430,3 +427,6 @@ return makeSymbol(value, "Main-Bold", mode, options,

const line = makeSpan([className], [], options);
line.height = thickness || options.fontMetrics().defaultRuleThickness;
line.height = Math.max(
thickness || options.fontMetrics().defaultRuleThickness,
options.minRuleThickness,
);
line.style.borderBottomWidth = line.height + "em";

@@ -433,0 +433,0 @@ line.maxFontSize = 1.0;

@@ -71,3 +71,3 @@ // @flow

if (output instanceof DocumentFragment) {
const children: HtmlDomNode[] = output.children;
const children: $ReadOnlyArray<HtmlDomNode> = output.children;
groups.push(...children);

@@ -158,2 +158,3 @@ } else {

if (partialGroup) { // Recursive DFS
// $FlowFixMe: make nodes a $ReadOnlyArray by returning a new array
traverseNonSpaceNodes(partialGroup.children, callback, prev);

@@ -160,0 +161,0 @@ continue;

@@ -47,3 +47,3 @@ // @flow

*/
export const makeRow = function(body: MathDomNode[]): MathDomNode {
export const makeRow = function(body: $ReadOnlyArray<MathDomNode>): MathDomNode {
if (body.length === 1) {

@@ -98,2 +98,15 @@ return body[0];

return "bold-italic";
} else if (font === "mathbf") {
return "bold";
} else if (font === "mathbb") {
return "double-struck";
} else if (font === "mathfrak") {
return "fraktur";
} else if (font === "mathscr" || font === "mathcal") {
// MathML makes no distinction between script and caligrahpic
return "script";
} else if (font === "mathsf") {
return "sans-serif";
} else if (font === "mathtt") {
return "monospace";
}

@@ -126,3 +139,15 @@

options: Options,
): MathDomNode[] {
isOrdgroup?: boolean,
): MathNode[] {
if (expression.length === 1) {
const group = buildGroup(expression[0], options);
if (isOrdgroup && group instanceof MathNode && group.type === "mo") {
// When TeX writers want to suppress spacing on an operator,
// they often put the operator by itself inside braces.
group.setAttribute("lspace", "0em");
group.setAttribute("rspace", "0em");
}
return [group];
}
const groups = [];

@@ -179,4 +204,5 @@ let lastGroup;

options: Options,
isOrdgroup?: boolean,
): MathDomNode {
return makeRow(buildExpression(expression, options));
return makeRow(buildExpression(expression, options, isOrdgroup));
};

@@ -191,3 +217,3 @@

options: Options,
): MathDomNode {
): MathNode {
if (!group) {

@@ -220,2 +246,3 @@ return new mathMLTree.MathNode("mrow");

options: Options,
forMathmlOnly: boolean,
): DomSpan {

@@ -244,2 +271,3 @@ const expression = buildExpression(tree, options);

const math = new mathMLTree.MathNode("math", [semantics]);
math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML");

@@ -250,4 +278,5 @@ // You can't style <math> nodes, so we wrap the node in a span.

// of span are expected to have more fields in `buildHtml` contexts.
const wrapperClass = forMathmlOnly ? "katex" : "katex-mathml";
// $FlowFixMe
return buildCommon.makeSpan(["katex-mathml"], [math]);
return buildCommon.makeSpan([wrapperClass], [math]);
}

@@ -16,2 +16,3 @@ // @flow

maxSize: settings.maxSize,
minRuleThickness: settings.minRuleThickness,
});

@@ -40,9 +41,14 @@ };

const options = optionsFromSettings(settings);
const mathMLNode = buildMathML(tree, expression, options);
const htmlNode = buildHTML(tree, options);
let katexNode;
if (settings.output === "mathml") {
return buildMathML(tree, expression, options, true);
} else if (settings.output === "html") {
const htmlNode = buildHTML(tree, options);
katexNode = buildCommon.makeSpan(["katex"], [htmlNode]);
} else {
const mathMLNode = buildMathML(tree, expression, options, false);
const htmlNode = buildHTML(tree, options);
katexNode = buildCommon.makeSpan(["katex"], [mathMLNode, htmlNode]);
}
const katexNode = buildCommon.makeSpan(["katex"], [
mathMLNode, htmlNode,
]);
return displayWrap(katexNode, settings);

@@ -49,0 +55,0 @@ };

@@ -5,3 +5,4 @@ // @flow

import type Parser from "./Parser";
import type {ParseNode, AnyParseNode, NodeType} from "./parseNode";
import type {ParseNode, AnyParseNode, NodeType, UnsupportedCmdParseNode}
from "./parseNode";
import type Options from "./Options";

@@ -25,3 +26,5 @@ import type {ArgType, BreakToken, Mode} from "./types";

optArgs: (?AnyParseNode)[],
) => ParseNode<NODETYPE>;
) => UnsupportedCmdParseNode | ParseNode<NODETYPE>;
// Note: reverse the order of the return type union will cause a flow error.
// See https://github.com/facebook/flow/issues/3663.

@@ -181,3 +184,2 @@ export type HtmlBuilder<NODETYPE> = (ParseNode<NODETYPE>, Options) => HtmlDomNode;

type,
nodeType,
names,

@@ -205,6 +207,2 @@ props,

for (let i = 0; i < names.length; ++i) {
// TODO: The value type of _functions should be a type union of all
// possible `FunctionSpec<>` possibilities instead of `FunctionSpec<*>`,
// which is an existential type.
// $FlowFixMe
_functions[names[i]] = data;

@@ -211,0 +209,0 @@ }

@@ -28,2 +28,3 @@ // @flow

import {PathNode, SvgNode, SymbolNode} from "./domTree";
import {sqrtPath} from "./svgGeometry";
import buildCommon from "./buildCommon";

@@ -181,2 +182,5 @@ import {getCharacterMetrics} from "./fontMetrics";

// Helper for makeStackedDelim
const lap = {type: "kern", size: -0.005};
/**

@@ -314,4 +318,4 @@ * Make a stacked delimiter out of a given delimiter, with the total height at

// Compute the number of copies of the repeat symbol we will need
const repeatCount = Math.ceil(
(heightTotal - minHeight) / (middleFactor * repeatHeightTotal));
const repeatCount = Math.max(0, Math.ceil(
(heightTotal - minHeight) / (middleFactor * repeatHeightTotal)));

@@ -333,2 +337,11 @@ // Compute the total height of the delimiter including all the symbols

// This function differs from the TeX procedure in one way.
// We shift each repeat element downwards by 0.005em, to prevent a gap
// due to browser floating point rounding error.
// Then, at the last element-to element joint, we add one extra repeat
// element to cover the gap created by the shifts.
// Find the shift needed to align the upper end of the extra element at a point
// 0.005em above the lower end of the top element.
const shiftOfExtraElement = (repeatCount + 1) * 0.005 - repeatHeightTotal;
// Now, we start building the pieces that will go into the vlist

@@ -345,2 +358,3 @@

for (let i = 0; i < repeatCount; i++) {
inners.push(lap); // overlap
inners.push(makeInner(repeat, font, mode));

@@ -352,6 +366,13 @@ }

for (let i = 0; i < repeatCount; i++) {
inners.push(lap);
inners.push(makeInner(repeat, font, mode));
}
// Insert one extra repeat element.
inners.push({type: "kern", size: shiftOfExtraElement});
inners.push(makeInner(repeat, font, mode));
inners.push(lap);
// Now insert the middle of the brace.
inners.push(makeInner(middle, font, mode));
for (let i = 0; i < repeatCount; i++) {
inners.push(lap);
inners.push(makeInner(repeat, font, mode));

@@ -361,2 +382,8 @@ }

// To cover the gap create by the overlaps, insert one more repeat element,
// at a position that juts 0.005 above the bottom of the top element.
inners.push({type: "kern", size: shiftOfExtraElement});
inners.push(makeInner(repeat, font, mode));
inners.push(lap);
// Add the top symbol

@@ -387,17 +414,7 @@ inners.push(makeInner(top, font, mode));

viewBoxHeight: number,
extraViniculum: number,
options: Options,
): SvgSpan {
let alternate;
if (sqrtName === "sqrtTall") {
// sqrtTall is from glyph U23B7 in the font KaTeX_Size4-Regular
// One path edge has a variable length. It runs from the viniculumn
// to a point near (14 units) the bottom of the surd. The viniculum
// is 40 units thick. So the length of the line in question is:
const vertSegment = viewBoxHeight - 54 - vbPad;
alternate = `M702 ${vbPad}H400000v40H742v${vertSegment}l-4 4-4 4c-.667.7
-2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1h-12l-28-84c-16.667-52-96.667
-294.333-240-727l-212 -643 -85 170c-4-3.333-8.333-7.667-13 -13l-13-13l77-155
77-156c66 199.333 139 419.667 219 661 l218 661zM702 ${vbPad}H400000v40H742z`;
}
const pathNode = new PathNode(sqrtName, alternate);
const path = sqrtPath(sqrtName, extraViniculum, viewBoxHeight);
const pathNode = new PathNode(sqrtName, path);

@@ -436,2 +453,7 @@ const svg = new SvgNode([pathNode], {

// The standard sqrt SVGs each have a 0.04em thick viniculum.
// If Settings.minRuleThickness is larger than that, we add extraViniculum.
const extraViniculum = Math.max(0,
options.minRuleThickness - options.fontMetrics().sqrtRuleThickness);
// Create a span containing an SVG image of a sqrt symbol.

@@ -452,3 +474,4 @@ let span;

// Get an SVG that is derived from glyph U+221A in font KaTeX-Main.
viewBoxHeight = 1000 + vbPad; // 1000 unit glyph height.
// 1000 unit normal glyph height.
viewBoxHeight = 1000 + 1000 * extraViniculum + vbPad;
if (height < 1.0) {

@@ -459,5 +482,6 @@ sizeMultiplier = 1.0; // mimic a \textfont radical

}
spanHeight = (1.0 + emPad) / sizeMultiplier;
texHeight = 1.00 / sizeMultiplier;
span = sqrtSvg("sqrtMain", spanHeight, viewBoxHeight, options);
spanHeight = (1.0 + extraViniculum + emPad) / sizeMultiplier;
texHeight = (1.00 + extraViniculum) / sizeMultiplier;
span = sqrtSvg("sqrtMain", spanHeight, viewBoxHeight, extraViniculum,
options);
span.style.minWidth = "0.853em";

@@ -469,5 +493,7 @@ advanceWidth = 0.833 / sizeMultiplier; // from the font.

viewBoxHeight = (1000 + vbPad) * sizeToMaxHeight[delim.size];
texHeight = sizeToMaxHeight[delim.size] / sizeMultiplier;
spanHeight = (sizeToMaxHeight[delim.size] + emPad) / sizeMultiplier;
span = sqrtSvg("sqrtSize" + delim.size, spanHeight, viewBoxHeight, options);
texHeight = (sizeToMaxHeight[delim.size] + extraViniculum) / sizeMultiplier;
spanHeight = (sizeToMaxHeight[delim.size] + extraViniculum + emPad)
/ sizeMultiplier;
span = sqrtSvg("sqrtSize" + delim.size, spanHeight, viewBoxHeight,
extraViniculum, options);
span.style.minWidth = "1.02em";

@@ -479,6 +505,7 @@ advanceWidth = 1.0 / sizeMultiplier; // 1.0 from the font.

// We'll use a single SVG to accomplish the same thing.
spanHeight = height + emPad;
texHeight = height;
viewBoxHeight = Math.floor(1000 * height) + vbPad;
span = sqrtSvg("sqrtTall", spanHeight, viewBoxHeight, options);
spanHeight = height + extraViniculum + emPad;
texHeight = height + extraViniculum;
viewBoxHeight = Math.floor(1000 * height + extraViniculum) + vbPad;
span = sqrtSvg("sqrtTall", spanHeight, viewBoxHeight, extraViniculum,
options);
span.style.minWidth = "0.742em";

@@ -498,3 +525,4 @@ advanceWidth = 1.056;

// have thicker rules.
ruleWidth: options.fontMetrics().sqrtRuleThickness * sizeMultiplier,
ruleWidth: (options.fontMetrics().sqrtRuleThickness + extraViniculum)
* sizeMultiplier,
};

@@ -501,0 +529,0 @@ };

@@ -16,3 +16,3 @@ // @flow

import utils from "./utils";
import svgGeometry from "./svgGeometry";
import {path} from "./svgGeometry";
import type Options from "./Options";

@@ -140,4 +140,7 @@ import {DocumentFragment} from "./tree";

borderColor: string,
borderRightStyle: string,
borderRightWidth: string,
borderTopWidth: string,
borderStyle: string;
borderWidth: string,
bottom: string,

@@ -147,2 +150,3 @@ color: string,

left: string,
margin: string,
marginLeft: string,

@@ -535,3 +539,3 @@ marginRight: string,

this.pathName = pathName;
this.alternate = alternate; // Used only for tall \sqrt
this.alternate = alternate; // Used only for \sqrt
}

@@ -546,3 +550,3 @@

} else {
node.setAttribute("d", svgGeometry.path[this.pathName]);
node.setAttribute("d", path[this.pathName]);
}

@@ -557,3 +561,3 @@

} else {
return `<path d='${svgGeometry.path[this.pathName]}'/>`;
return `<path d='${path[this.pathName]}'/>`;
}

@@ -560,0 +564,0 @@ }

// @flow
import buildCommon from "../buildCommon";
import Style from "../Style";
import defineEnvironment from "../defineEnvironment";

@@ -29,3 +30,3 @@ import defineFunction from "../defineFunction";

// Type to indicate column separation in MathML
export type ColSeparationType = "align" | "alignat";
export type ColSeparationType = "align" | "alignat" | "small";

@@ -82,2 +83,5 @@ function getHLines(parser: Parser): boolean[] {

// Start group for first cell
parser.gullet.beginGroup();
let row = [];

@@ -92,3 +96,7 @@ const body = [row];

while (true) { // eslint-disable-line no-constant-condition
// Parse each cell in its own group (namespace)
let cell = parser.parseExpression(false, "\\cr");
parser.gullet.endGroup();
parser.gullet.beginGroup();
cell = {

@@ -137,3 +145,8 @@ type: "ordgroup",

}
// End cell group
parser.gullet.endGroup();
// End array group defining \\
parser.gullet.endGroup();
return {

@@ -180,5 +193,20 @@ type: "array",

const ruleThickness = Math.max(
// From LaTeX \showthe\arrayrulewidth. Equals 0.04 em.
(options.fontMetrics().arrayRuleWidth),
options.minRuleThickness, // User override.
);
// Horizontal spacing
const pt = 1 / options.fontMetrics().ptPerEm;
const arraycolsep = 5 * pt; // \arraycolsep in article.cls
let arraycolsep = 5 * pt; // default value, i.e. \arraycolsep in article.cls
if (group.colSeparationType && group.colSeparationType === "small") {
// We're in a {smallmatrix}. Default column space is \thickspace,
// i.e. 5/18em = 0.2778em, per amsmath.dtx for {smallmatrix}.
// But that needs adjustment because LaTeX applies \scriptstyle to the
// entire array, including the colspace, but this function applies
// \scriptstyle only inside each element.
const localMultiplier = options.havingStyle(Style.SCRIPT).sizeMultiplier;
arraycolsep = 0.2778 * (localMultiplier / options.sizeMultiplier);
}

@@ -282,3 +310,4 @@ // Vertical spacing

if (colDescr.separator === "|") {
if (colDescr.separator === "|" || colDescr.separator === ":") {
const lineType = (colDescr.separator === "|") ? "solid" : "dashed";
const separator = buildCommon.makeSpan(

@@ -288,2 +317,5 @@ ["vertical-separator"], [], options

separator.style.height = totalHeight + "em";
separator.style.borderRightWidth = `${ruleThickness}em`;
separator.style.borderRightStyle = lineType;
separator.style.margin = `0 -${ruleThickness / 2}em`;
separator.style.verticalAlign =

@@ -293,11 +325,2 @@ -(totalHeight - offset) + "em";

cols.push(separator);
} else if (colDescr.separator === ":") {
const separator = buildCommon.makeSpan(
["vertical-separator", "vs-dashed"], [], options
);
separator.style.height = totalHeight + "em";
separator.style.verticalAlign =
-(totalHeight - offset) + "em";
cols.push(separator);
} else {

@@ -362,4 +385,5 @@ throw new ParseError(

if (hlines.length > 0) {
const line = buildCommon.makeLineSpan("hline", options, 0.05);
const dashes = buildCommon.makeLineSpan("hdashline", options, 0.05);
const line = buildCommon.makeLineSpan("hline", options, ruleThickness);
const dashes = buildCommon.makeLineSpan("hdashline", options,
ruleThickness);
const vListElems = [{type: "elem", elem: body, shift: 0}];

@@ -391,3 +415,3 @@ while (hlines.length > 0) {

const mathmlBuilder: MathMLBuilder<"array"> = function(group, options) {
const table = new mathMLTree.MathNode(
let table = new mathMLTree.MathNode(
"mtable", group.body.map(function(row) {

@@ -414,3 +438,5 @@ return new mathMLTree.MathNode(

// similar to LaTeX and in which content does not interfere with \hines.
const gap = 0.16 + group.arraystretch - 1 + (group.addJot ? 0.09 : 0);
const gap = (group.arraystretch === 0.5)
? 0.1 // {smallmatrix}, {subarray}
: 0.16 + group.arraystretch - 1 + (group.addJot ? 0.09 : 0);
table.setAttribute("rowspacing", gap + "em");

@@ -477,2 +503,4 @@

table.setAttribute("columnspacing", "0em");
} else if (group.colSeparationType === "small") {
table.setAttribute("columnspacing", "0.2778em");
} else {

@@ -499,9 +527,14 @@ table.setAttribute("columnspacing", "1em");

if (menclose === "") {
return table;
} else {
const wrapper = new mathMLTree.MathNode("menclose", [table]);
wrapper.setAttribute("notation", menclose.trim());
return wrapper;
if (menclose !== "") {
table = new mathMLTree.MathNode("menclose", [table]);
table.setAttribute("notation", menclose.trim());
}
if (group.arraystretch && group.arraystretch < 1) {
// A small array. Wrap in scriptstyle so row gap is not too large.
table = new mathMLTree.MathNode("mstyle", [table]);
table.setAttribute("scriptlevel", "1");
}
return table;
};

@@ -666,2 +699,3 @@

right: delimiters[1],
rightColor: undefined, // \right uninfluenced by \color in array
} : res;

@@ -673,2 +707,59 @@ },

defineEnvironment({
type: "array",
names: ["smallmatrix"],
props: {
numArgs: 0,
},
handler(context) {
const payload = {arraystretch: 0.5};
const res = parseArray(context.parser, payload, "script");
res.colSeparationType = "small";
return res;
},
htmlBuilder,
mathmlBuilder,
});
defineEnvironment({
type: "array",
names: ["subarray"],
props: {
numArgs: 1,
},
handler(context, args) {
// Parsing of {subarray} is similar to {array}
const symNode = checkSymbolNodeType(args[0]);
const colalign: AnyParseNode[] =
symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body;
const cols = colalign.map(function(nde) {
const node = assertSymbolNodeType(nde);
const ca = node.text;
// {subarray} only recognizes "l" & "c"
if ("lc".indexOf(ca) !== -1) {
return {
type: "align",
align: ca,
};
}
throw new ParseError("Unknown column alignment: " + ca, nde);
});
if (cols.length > 1) {
throw new ParseError("{subarray} can contain only one column");
}
let res = {
cols,
hskipBeforeAndAfter: false,
arraystretch: 0.5,
};
res = parseArray(context.parser, res, "script");
if (res.body[0].length > 1) {
throw new ParseError("{subarray} can contain only one column");
}
return res;
},
htmlBuilder,
mathmlBuilder,
});
// A cases environment (in amsmath.sty) is almost equivalent to

@@ -715,2 +806,3 @@ // \def\arraystretch{1.2}%

right: ".",
rightColor: undefined,
};

@@ -717,0 +809,0 @@ },

@@ -85,2 +85,10 @@ // @flow

doubleRuleSep: [0.2, 0.2, 0.2],
// The width of separator lines in {array} environments. From
// `\showthe\arrayrulewidth` in LaTeX. Equals 0.4 / ptPerEm.
arrayRuleWidth: [0.04, 0.04, 0.04],
// Two values from LaTeX source2e:
fboxsep: [0.3, 0.3, 0.3], // 3 pt / ptPerEm
fboxrule: [0.04, 0.04, 0.04], // 0.4 pt / ptPerEm
};

@@ -87,0 +95,0 @@

@@ -24,4 +24,3 @@ // @flow

import "./functions/htmlmathml";
// Disabled until https://github.com/KaTeX/KaTeX/pull/1794 is merged.
// import "./functions/includegraphics";
import "./functions/includegraphics";
import "./functions/kern";

@@ -28,0 +27,0 @@ import "./functions/lap";

@@ -70,3 +70,9 @@ // @flow

// If we see a styling function, parse out the implicit body
// Set macro \current@color in current namespace to store the current
// color, mimicking the behavior of color.sty.
// This is currently used just to correctly color a \right
// that follows a \color command.
parser.gullet.macros.set("\\current@color", color);
// Parse out the implicit body that should be colored.
const body = parser.parseExpression(true, breakOnTokenText);

@@ -73,0 +79,0 @@

@@ -148,2 +148,7 @@ // @flow

// uses this return value.
const color = context.parser.gullet.macros.get("\\current@color");
if (color && typeof color !== "string") {
throw new ParseError(
"\\current@color set to non-string in \\right");
}
return {

@@ -153,2 +158,3 @@ type: "leftright-right",

delim: checkDelimiter(args[0], context).text,
color, // undefined if not set via \color
};

@@ -183,2 +189,3 @@ },

right: right.delim,
rightColor: right.color,
};

@@ -247,8 +254,10 @@ },

let rightDelim;
// Same for the right delimiter
// Same for the right delimiter, but using color specified by \color
if (group.right === ".") {
rightDelim = html.makeNullDelimiter(options, ["mclose"]);
} else {
const colorOptions = group.rightColor ?
options.withColor(group.rightColor) : options;
rightDelim = delimiter.leftRightDelim(
group.right, innerHeight, innerDepth, options,
group.right, innerHeight, innerDepth, colorOptions,
group.mode, ["mclose"]);

@@ -280,2 +289,6 @@ }

if (group.rightColor) {
rightNode.setAttribute("mathcolor", group.rightColor);
}
inner.push(rightNode);

@@ -282,0 +295,0 @@ }

@@ -49,6 +49,11 @@ // @flow

let vertPad = 0;
// ref: LaTeX source2e: \fboxsep = 3pt; \fboxrule = .4pt
let ruleThickness = 0;
// ref: cancel package: \advance\totalheight2\p@ % "+2"
if (/box/.test(label)) {
vertPad = label === "colorbox" ? 0.3 : 0.34;
ruleThickness = Math.max(
options.fontMetrics().fboxrule, // default
options.minRuleThickness, // User override.
);
vertPad = options.fontMetrics().fboxsep +
(label === "colorbox" ? 0 : ruleThickness);
} else {

@@ -59,2 +64,6 @@ vertPad = isSingleChar ? 0.2 : 0;

img = stretchy.encloseSpan(inner, label, vertPad, options);
if (/fbox|boxed|fcolorbox/.test(label)) {
img.style.borderStyle = "solid";
img.style.borderWidth = `${ruleThickness}em`;
}
imgShift = inner.depth + vertPad;

@@ -116,2 +125,3 @@

const mathmlBuilder = (group, options) => {
let fboxsep = 0;
const node = new mathMLTree.MathNode(

@@ -138,8 +148,13 @@ (group.label.indexOf("colorbox") > -1) ? "mpadded" : "menclose",

// instead. Set some attributes that come included with <menclose>.
node.setAttribute("width", "+6pt");
node.setAttribute("height", "+6pt");
node.setAttribute("lspace", "3pt"); // LaTeX source2e: \fboxsep = 3pt
node.setAttribute("voffset", "3pt");
fboxsep = options.fontMetrics().fboxsep *
options.fontMetrics().ptPerEm;
node.setAttribute("width", `+${2 * fboxsep}pt`);
node.setAttribute("height", `+${2 * fboxsep}pt`);
node.setAttribute("lspace", `${fboxsep}pt`); //
node.setAttribute("voffset", `${fboxsep}pt`);
if (group.label === "\\fcolorbox") {
const thk = options.fontMetrics().defaultRuleThickness;
const thk = Math.max(
options.fontMetrics().fboxrule, // default
options.minRuleThickness, // user override
);
node.setAttribute("style", "border: " + thk + "em solid " +

@@ -214,3 +229,3 @@ String(group.borderColor));

numArgs: 1,
argTypes: ["text"],
argTypes: ["hbox"],
allowedInText: true,

@@ -217,0 +232,0 @@ },

@@ -6,2 +6,3 @@ // @flow

import defineFunction from "../defineFunction";
import utils from "../utils";

@@ -75,2 +76,3 @@ import * as html from "../buildHTML";

const body = args[0];
const isCharacterBox = utils.isCharacterBox(body);
// amsbsy.sty's \boldsymbol uses \binrel spacing to inherit the

@@ -90,2 +92,3 @@ // argument's bin|rel|ord status

],
isCharacterBox: isCharacterBox,
};

@@ -92,0 +95,0 @@ },

@@ -21,2 +21,10 @@ // @flow

const href = assertNodeType(args[0], "url").url;
if (!parser.settings.isTrusted({
command: "\\href",
url: href,
})) {
return parser.formatUnsupportedCmd("\\href");
}
return {

@@ -53,2 +61,10 @@ type: "href",

const href = assertNodeType(args[0], "url").url;
if (!parser.settings.isTrusted({
command: "\\url",
url: href,
})) {
return parser.formatUnsupportedCmd("\\url");
}
const chars = [];

@@ -55,0 +71,0 @@ for (let i = 0; i < href.length; i++) {

@@ -88,2 +88,9 @@ // @flow

if (!parser.settings.isTrusted({
command: "\\includegraphics",
url: src,
})) {
return parser.formatUnsupportedCmd("\\includegraphics");
}
return {

@@ -90,0 +97,0 @@ type: "includegraphics",

@@ -5,2 +5,3 @@ // @flow

import mathMLTree from "../mathMLTree";
import utils from "../utils";
import type {AnyParseNode} from "../parseNode";

@@ -21,4 +22,38 @@

function mathmlBuilder(group: ParseNode<"mclass">, options) {
let node: mathMLTree.MathNode;
const inner = mml.buildExpression(group.body, options);
return mathMLTree.newDocumentFragment(inner);
if (group.mclass === "minner") {
return mathMLTree.newDocumentFragment(inner);
} else if (group.mclass === "mord") {
if (group.isCharacterBox) {
node = inner[0];
node.type = "mi";
} else {
node = new mathMLTree.MathNode("mi", inner);
}
} else {
if (group.isCharacterBox) {
node = inner[0];
node.type = "mo";
} else {
node = new mathMLTree.MathNode("mo", inner);
}
// Set spacing based on what is the most likely adjacent atom type.
// See TeXbook p170.
if (group.mclass === "mbin") {
node.attributes.lspace = "0.22em"; // medium space
node.attributes.rspace = "0.22em";
} else if (group.mclass === "mpunct") {
node.attributes.lspace = "0em";
node.attributes.rspace = "0.17em"; // thinspace
} else if (group.mclass === "mopen" || group.mclass === "mclose") {
node.attributes.lspace = "0em";
node.attributes.rspace = "0em";
}
// MathML <mo> default space is 5/18 em, so <mrel> needs no action.
// Ref: https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mo
}
return node;
}

@@ -41,4 +76,5 @@

mode: parser.mode,
mclass: "m" + funcName.substr(5),
mclass: "m" + funcName.substr(5), // TODO(kevinb): don't prefix with 'm'
body: ordargument(body),
isCharacterBox: utils.isCharacterBox(body),
};

@@ -77,2 +113,3 @@ },

body: [args[1]],
isCharacterBox: utils.isCharacterBox(args[1]),
};

@@ -125,2 +162,3 @@ },

body: [supsub],
isCharacterBox: utils.isCharacterBox(supsub),
};

@@ -127,0 +165,0 @@ },

@@ -9,2 +9,3 @@ // @flow

import Style from "../Style";
import {assembleSupSub} from "./utils/assembleSupSub";
import {assertNodeType, checkNodeType} from "../parseNode";

@@ -109,3 +110,3 @@

for (let i = 1; i < group.name.length; i++) {
output.push(buildCommon.mathsym(group.name[i], group.mode));
output.push(buildCommon.mathsym(group.name[i], group.mode, options));
}

@@ -136,95 +137,5 @@ base = buildCommon.makeSpan(["mop"], output, options);

if (hasLimits) {
// IE 8 clips \int if it is in a display: inline-block. We wrap it
// in a new span so it is an inline, and works.
base = buildCommon.makeSpan([], [base]);
return assembleSupSub(base, supGroup, subGroup, options,
style, slant, baseShift);
let sub;
let sup;
// We manually have to handle the superscripts and subscripts. This,
// aside from the kern calculations, is copied from supsub.
if (supGroup) {
const elem = html.buildGroup(
supGroup, options.havingStyle(style.sup()), options);
sup = {
elem,
kern: Math.max(
options.fontMetrics().bigOpSpacing1,
options.fontMetrics().bigOpSpacing3 - elem.depth),
};
}
if (subGroup) {
const elem = html.buildGroup(
subGroup, options.havingStyle(style.sub()), options);
sub = {
elem,
kern: Math.max(
options.fontMetrics().bigOpSpacing2,
options.fontMetrics().bigOpSpacing4 - elem.height),
};
}
// Build the final group as a vlist of the possible subscript, base,
// and possible superscript.
let finalGroup;
if (sup && sub) {
const bottom = options.fontMetrics().bigOpSpacing5 +
sub.elem.height + sub.elem.depth +
sub.kern +
base.depth + baseShift;
finalGroup = buildCommon.makeVList({
positionType: "bottom",
positionData: bottom,
children: [
{type: "kern", size: options.fontMetrics().bigOpSpacing5},
{type: "elem", elem: sub.elem, marginLeft: -slant + "em"},
{type: "kern", size: sub.kern},
{type: "elem", elem: base},
{type: "kern", size: sup.kern},
{type: "elem", elem: sup.elem, marginLeft: slant + "em"},
{type: "kern", size: options.fontMetrics().bigOpSpacing5},
],
}, options);
} else if (sub) {
const top = base.height - baseShift;
// Shift the limits by the slant of the symbol. Note
// that we are supposed to shift the limits by 1/2 of the slant,
// but since we are centering the limits adding a full slant of
// margin will shift by 1/2 that.
finalGroup = buildCommon.makeVList({
positionType: "top",
positionData: top,
children: [
{type: "kern", size: options.fontMetrics().bigOpSpacing5},
{type: "elem", elem: sub.elem, marginLeft: -slant + "em"},
{type: "kern", size: sub.kern},
{type: "elem", elem: base},
],
}, options);
} else if (sup) {
const bottom = base.depth + baseShift;
finalGroup = buildCommon.makeVList({
positionType: "bottom",
positionData: bottom,
children: [
{type: "elem", elem: base},
{type: "kern", size: sup.kern},
{type: "elem", elem: sup.elem, marginLeft: slant + "em"},
{type: "kern", size: options.fontMetrics().bigOpSpacing5},
],
}, options);
} else {
// This case probably shouldn't occur (this would mean the
// supsub was sending us a group with no superscript or
// subscript) but be safe.
return base;
}
return buildCommon.makeSpan(
["mop", "op-limits"], [finalGroup], options);
} else {

@@ -257,4 +168,2 @@ if (baseShift) {

// operator's name.
// TODO(emily): Add a space in the middle of some of these
// operators, like \limsup.
node = new mathMLTree.MathNode(

@@ -261,0 +170,0 @@ "mi", [new mathMLTree.TextNode(group.name.slice(1))]);

@@ -6,2 +6,4 @@ // @flow

import {SymbolNode} from "../domTree";
import {assembleSupSub} from "./utils/assembleSupSub";
import {assertNodeType, checkNodeType} from "../parseNode";

@@ -11,109 +13,152 @@ import * as html from "../buildHTML";

// \operatorname
// amsopn.dtx: \mathop{#1\kern\z@\operator@font#3}\newmcodes@
defineFunction({
type: "operatorname",
names: ["\\operatorname"],
props: {
numArgs: 1,
},
handler: ({parser}, args) => {
const body = args[0];
return {
type: "operatorname",
mode: parser.mode,
body: ordargument(body),
};
},
import type {HtmlBuilderSupSub, MathMLBuilder} from "../defineFunction";
import type {ParseNode} from "../parseNode";
htmlBuilder: (group, options) => {
if (group.body.length > 0) {
const body = group.body.map(child => {
// $FlowFixMe: Check if the node has a string `text` property.
const childText = child.text;
if (typeof childText === "string") {
return {
type: "textord",
mode: child.mode,
text: childText,
};
} else {
return child;
}
});
// NOTE: Unlike most `htmlBuilder`s, this one handles not only
// "operatorname", but also "supsub" since \operatorname* can
// affect super/subscripting.
export const htmlBuilder: HtmlBuilderSupSub<"operatorname"> = (grp, options) => {
// Operators are handled in the TeXbook pg. 443-444, rule 13(a).
let supGroup;
let subGroup;
let hasLimits = false;
let group: ParseNode<"operatorname">;
const supSub = checkNodeType(grp, "supsub");
if (supSub) {
// If we have limits, supsub will pass us its group to handle. Pull
// out the superscript and subscript and set the group to the op in
// its base.
supGroup = supSub.sup;
subGroup = supSub.sub;
group = assertNodeType(supSub.base, "operatorname");
hasLimits = true;
} else {
group = assertNodeType(grp, "operatorname");
}
// Consolidate function names into symbol characters.
const expression = html.buildExpression(
body, options.withFont("mathrm"), true);
let base;
if (group.body.length > 0) {
const body = group.body.map(child => {
// $FlowFixMe: Check if the node has a string `text` property.
const childText = child.text;
if (typeof childText === "string") {
return {
type: "textord",
mode: child.mode,
text: childText,
};
} else {
return child;
}
});
for (let i = 0; i < expression.length; i++) {
const child = expression[i];
if (child instanceof SymbolNode) {
// Per amsopn package,
// change minus to hyphen and \ast to asterisk
child.text = child.text.replace(/\u2212/, "-")
.replace(/\u2217/, "*");
}
// Consolidate function names into symbol characters.
const expression = html.buildExpression(
body, options.withFont("mathrm"), true);
for (let i = 0; i < expression.length; i++) {
const child = expression[i];
if (child instanceof SymbolNode) {
// Per amsopn package,
// change minus to hyphen and \ast to asterisk
child.text = child.text.replace(/\u2212/, "-")
.replace(/\u2217/, "*");
}
return buildCommon.makeSpan(["mop"], expression, options);
} else {
return buildCommon.makeSpan(["mop"], [], options);
}
},
base = buildCommon.makeSpan(["mop"], expression, options);
} else {
base = buildCommon.makeSpan(["mop"], [], options);
}
mathmlBuilder: (group, options) => {
// The steps taken here are similar to the html version.
let expression = mml.buildExpression(
group.body, options.withFont("mathrm"));
if (hasLimits) {
return assembleSupSub(base, supGroup, subGroup, options,
options.style, 0, 0);
// Is expression a string or has it something like a fraction?
let isAllString = true; // default
for (let i = 0; i < expression.length; i++) {
const node = expression[i];
if (node instanceof mathMLTree.SpaceNode) {
// Do nothing
} else if (node instanceof mathMLTree.MathNode) {
switch (node.type) {
case "mi":
case "mn":
case "ms":
case "mspace":
case "mtext":
break; // Do nothing yet.
case "mo": {
const child = node.children[0];
if (node.children.length === 1 &&
child instanceof mathMLTree.TextNode) {
child.text =
child.text.replace(/\u2212/, "-")
.replace(/\u2217/, "*");
} else {
isAllString = false;
}
break;
} else {
return base;
}
};
const mathmlBuilder: MathMLBuilder<"operatorname"> = (group, options) => {
// The steps taken here are similar to the html version.
let expression = mml.buildExpression(
group.body, options.withFont("mathrm"));
// Is expression a string or has it something like a fraction?
let isAllString = true; // default
for (let i = 0; i < expression.length; i++) {
const node = expression[i];
if (node instanceof mathMLTree.SpaceNode) {
// Do nothing
} else if (node instanceof mathMLTree.MathNode) {
switch (node.type) {
case "mi":
case "mn":
case "ms":
case "mspace":
case "mtext":
break; // Do nothing yet.
case "mo": {
const child = node.children[0];
if (node.children.length === 1 &&
child instanceof mathMLTree.TextNode) {
child.text =
child.text.replace(/\u2212/, "-")
.replace(/\u2217/, "*");
} else {
isAllString = false;
}
default:
isAllString = false;
break;
}
} else {
isAllString = false;
default:
isAllString = false;
}
} else {
isAllString = false;
}
}
if (isAllString) {
// Write a single TextNode instead of multiple nested tags.
const word = expression.map(node => node.toText()).join("");
expression = [new mathMLTree.TextNode(word)];
}
if (isAllString) {
// Write a single TextNode instead of multiple nested tags.
const word = expression.map(node => node.toText()).join("");
expression = [new mathMLTree.TextNode(word)];
}
const identifier = new mathMLTree.MathNode("mi", expression);
identifier.setAttribute("mathvariant", "normal");
const identifier = new mathMLTree.MathNode("mi", expression);
identifier.setAttribute("mathvariant", "normal");
// \u2061 is the same as &ApplyFunction;
// ref: https://www.w3schools.com/charsets/ref_html_entities_a.asp
const operator = new mathMLTree.MathNode("mo",
[mml.makeText("\u2061", "text")]);
// \u2061 is the same as &ApplyFunction;
// ref: https://www.w3schools.com/charsets/ref_html_entities_a.asp
const operator = new mathMLTree.MathNode("mo",
[mml.makeText("\u2061", "text")]);
if (group.parentIsSupSub) {
return new mathMLTree.MathNode("mo", [identifier, operator]);
} else {
return mathMLTree.newDocumentFragment([identifier, operator]);
}
};
// \operatorname
// amsopn.dtx: \mathop{#1\kern\z@\operator@font#3}\newmcodes@
defineFunction({
type: "operatorname",
names: ["\\operatorname", "\\operatorname*"],
props: {
numArgs: 1,
},
handler: ({parser, funcName}, args) => {
const body = args[0];
return {
type: "operatorname",
mode: parser.mode,
body: ordargument(body),
alwaysHandleSupSub: (funcName === "\\operatorname*"),
limits: false,
parentIsSupSub: false,
};
},
htmlBuilder,
mathmlBuilder,
});

@@ -19,5 +19,5 @@ // @flow

mathmlBuilder(group, options) {
return mml.buildExpressionRow(group.body, options);
return mml.buildExpressionRow(group.body, options, true);
},
});

@@ -34,2 +34,3 @@ // @flow

// Generate the vlist, with the appropriate kerns
const defaultRuleThickness = options.fontMetrics().defaultRuleThickness;
const vlist = buildCommon.makeVList({

@@ -39,5 +40,5 @@ positionType: "firstBaseline",

{type: "elem", elem: innerGroup},
{type: "kern", size: 3 * line.height},
{type: "kern", size: 3 * defaultRuleThickness},
{type: "elem", elem: line},
{type: "kern", size: line.height},
{type: "kern", size: defaultRuleThickness},
],

@@ -44,0 +45,0 @@ }, options);

// @flow
import defineFunction, {ordargument} from "../defineFunction";
import defineFunction from "../defineFunction";
import buildCommon from "../buildCommon";

@@ -8,4 +8,4 @@ import mathMLTree from "../mathMLTree";

import * as html from "../buildHTML";
import * as mml from "../buildMathML";
import * as sizing from "./sizing";

@@ -18,3 +18,3 @@ // Box manipulation

numArgs: 2,
argTypes: ["size", "text"],
argTypes: ["size", "hbox"],
allowedInText: true,

@@ -33,15 +33,3 @@ },

htmlBuilder(group, options) {
const text = {
type: "text",
mode: group.mode,
body: ordargument(group.body),
font: "mathrm", // simulate \textrm
};
const sizedText = {
type: "sizing",
mode: group.mode,
body: [text],
size: 6, // simulate \normalsize
};
const body = sizing.htmlBuilder(sizedText, options);
const body = html.buildGroup(group.body, options);
const dy = calculateSize(group.dy, options);

@@ -48,0 +36,0 @@ return buildCommon.makeVList({

@@ -51,11 +51,2 @@ // @flow

// Figure out what style we're changing to.
// TODO(kevinb): dedupe this with buildHTML.js
// This will be easier of handling of styling nodes is in the same file.
const styleMap = {
"display": Style.DISPLAY,
"text": Style.TEXT,
"script": Style.SCRIPT,
"scriptscript": Style.SCRIPTSCRIPT,
};
const newStyle = styleMap[group.style];

@@ -62,0 +53,0 @@ const newOptions = options.havingStyle(newStyle);

@@ -15,2 +15,3 @@ // @flow

import * as op from "./op";
import * as operatorname from "./operatorname";

@@ -43,2 +44,6 @@ import type Options from "../Options";

return delegate ? op.htmlBuilder : null;
} else if (base.type === "operatorname") {
const delegate = base.alwaysHandleSupSub &&
(options.style.size === Style.DISPLAY.size || base.limits);
return delegate ? operatorname.htmlBuilder : null;
} else if (base.type === "accent") {

@@ -206,3 +211,4 @@ return utils.isCharacterBox(base.base) ? accent.htmlBuilder : null;

if (group.base && group.base.type === "op") {
if (group.base &&
(group.base.type === "op" || group.base.type === "operatorname")) {
group.base.parentIsSupSub = true;

@@ -229,2 +235,6 @@ }

nodeType = "mover";
} else if (base && base.type === "operatorname" &&
base.alwaysHandleSupSub &&
(base.limits || options.style === Style.DISPLAY)) {
nodeType = "mover";
} else {

@@ -238,2 +248,6 @@ nodeType = "msup";

nodeType = "munder";
} else if (base && base.type === "operatorname" &&
base.alwaysHandleSupSub &&
(base.limits || options.style === Style.DISPLAY)) {
nodeType = "munder";
} else {

@@ -247,2 +261,6 @@ nodeType = "msub";

nodeType = "munderover";
} else if (base && base.type === "operatorname" &&
base.alwaysHandleSupSub &&
(options.style === Style.DISPLAY || base.limits)) {
nodeType = "munderover";
} else {

@@ -249,0 +267,0 @@ nodeType = "msubsup";

@@ -32,2 +32,3 @@ // @flow

// Generate the vlist, with the appropriate kerns
const defaultRuleThickness = options.fontMetrics().defaultRuleThickness;
const vlist = buildCommon.makeVList({

@@ -37,5 +38,5 @@ positionType: "top",

children: [
{type: "kern", size: line.height},
{type: "kern", size: defaultRuleThickness},
{type: "elem", elem: line},
{type: "kern", size: 3 * line.height},
{type: "kern", size: 3 * defaultRuleThickness},
{type: "elem", elem: innerGroup},

@@ -42,0 +43,0 @@ ],

@@ -54,2 +54,3 @@ // @flow

"|\\\\verb([^*a-zA-Z]).*?\\4" + // \verb unstarred
"|\\\\operatorname\\*" + // \operatorname*
`|${controlWordWhitespaceRegexString}` + // \macroName + spaces

@@ -56,0 +57,0 @@ `|${controlSymbolRegexString})`; // \\, \', etc.

@@ -429,2 +429,5 @@ // @flow

//\newcommand{\substack}[1]{\subarray{c}#1\endsubarray}
defineMacro("\\substack", "\\begin{subarray}{c}#1\\end{subarray}");
// \renewcommand{\colon}{\nobreak\mskip2mu\mathpunct{}\nonscript

@@ -663,9 +666,8 @@ // \mkern-\thinmuskip{:}\mskip6muplus1mu\relax}

// \pmb -- A simulation of bold.
// It works by typesetting three copies of the argument with small offsets.
// Ref: a rather lengthy macro in ambsy.sty
defineMacro("\\pmb", "\\html@mathml{\\@binrel{#1}{" +
"\\mathrlap{#1}" +
"\\mathrlap{\\mkern0.4mu\\raisebox{0.4mu}{$#1$}}" +
"{\\mkern0.8mu#1}" +
"}}{\\mathbf{#1}}");
// The version in ambsy.sty works by typesetting three copies of the argument
// with small offsets. We use two copies. We omit the vertical offset because
// of rendering problems that makeVList encounters in Safari.
defineMacro("\\pmb", "\\html@mathml{" +
"\\@binrel{#1}{\\mathrlap{#1}\\kern0.5px#1}}" +
"{\\mathbf{#1}}");

@@ -698,8 +700,8 @@ //////////////////////////////////////////////////////////////////////

// boxes, though visually the A appears to extend above slightly).
// We compute the corresponding \raisebox when A is rendered at \scriptsize,
// which is size3, which has a scale factor of 0.7 (see Options.js).
// We compute the corresponding \raisebox when A is rendered in \normalsize
// \scriptstyle, which has a scale factor of 0.7 (see Options.js).
const latexRaiseA = fontMetricsData['Main-Regular']["T".charCodeAt(0)][1] -
0.7 * fontMetricsData['Main-Regular']["A".charCodeAt(0)][1] + "em";
defineMacro("\\LaTeX", "\\textrm{\\html@mathml{" +
`L\\kern-.36em\\raisebox{${latexRaiseA}}{\\scriptsize A}` +
`L\\kern-.36em\\raisebox{${latexRaiseA}}{\\scriptstyle A}` +
"\\kern-.15em\\TeX}{LaTeX}}");

@@ -709,3 +711,3 @@

defineMacro("\\KaTeX", "\\textrm{\\html@mathml{" +
`K\\kern-.17em\\raisebox{${latexRaiseA}}{\\scriptsize A}` +
`K\\kern-.17em\\raisebox{${latexRaiseA}}{\\scriptstyle A}` +
"\\kern-.15em\\TeX}{KaTeX}}");

@@ -820,4 +822,4 @@

defineMacro("\\notni", "\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220C}}");
defineMacro("\\limsup", "\\DOTSB\\mathop{\\operatorname{lim\\,sup}}\\limits");
defineMacro("\\liminf", "\\DOTSB\\mathop{\\operatorname{lim\\,inf}}\\limits");
defineMacro("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}");
defineMacro("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}");

@@ -948,4 +950,5 @@ //////////////////////////////////////////////////////////////////////

defineMacro("\\argmin", "\\DOTSB\\mathop{\\operatorname{arg\\,min}}\\limits");
defineMacro("\\argmax", "\\DOTSB\\mathop{\\operatorname{arg\\,max}}\\limits");
defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}");
defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}");
defineMacro("\\plim", "\\DOTSB\\mathop{\\operatorname{plim}}\\limits");

@@ -952,0 +955,0 @@ // Custom Khan Academy colors, should be moved to an optional package

@@ -35,3 +35,5 @@ // @flow

export type documentFragment = DocumentFragment<MathDomNode>;
export function newDocumentFragment(children: MathDomNode[]): documentFragment {
export function newDocumentFragment(
children: $ReadOnlyArray<MathDomNode>
): documentFragment {
return new DocumentFragment(children);

@@ -48,5 +50,5 @@ }

attributes: {[string]: string};
children: MathDomNode[];
children: $ReadOnlyArray<MathDomNode>;
constructor(type: MathNodeType, children?: MathDomNode[]) {
constructor(type: MathNodeType, children?: $ReadOnlyArray<MathDomNode>) {
this.type = type;

@@ -53,0 +55,0 @@ this.attributes = {};

@@ -55,2 +55,3 @@ // @flow

maxSize: number;
minRuleThickness: number;
};

@@ -80,2 +81,3 @@

maxSize: number;
minRuleThickness: number;
_fontMetrics: FontMetrics | void;

@@ -100,2 +102,3 @@

this.maxSize = data.maxSize;
this.minRuleThickness = data.minRuleThickness;
this._fontMetrics = undefined;

@@ -120,2 +123,3 @@ }

maxSize: this.maxSize,
minRuleThickness: this.minRuleThickness,
};

@@ -122,0 +126,0 @@

@@ -22,2 +22,5 @@ // @flow

// ParseNode from `Parser.formatUnsupportedCmd`
export type UnsupportedCmdParseNode = ParseNode<"color">;
// Union of all possible `ParseNode<>` types.

@@ -54,8 +57,2 @@ export type AnyParseNode = $Values<ParseNodeTypes>;

|},
"keyVals": {|
type: "keyVals",
mode: Mode,
loc?: ?SourceLocation,
keyVals: string,
|},
// To avoid requiring run-time type assertions, this more carefully captures

@@ -323,2 +320,3 @@ // the requirements on the fields per the op.js htmlBuilder logic:

right: string,
rightColor: ?string, // undefined means "inherit"
|},

@@ -330,2 +328,3 @@ "leftright-right": {|

delim: string,
color: ?string, // undefined means "inherit"
|},

@@ -353,2 +352,3 @@ "mathchoice": {|

body: AnyParseNode[],
isCharacterBox: boolean,
|},

@@ -360,2 +360,5 @@ "operatorname": {|

body: AnyParseNode[],
alwaysHandleSupSub: boolean,
limits: boolean,
parentIsSupSub: boolean,
|},

@@ -362,0 +365,0 @@ "overline": {|

@@ -10,3 +10,2 @@ // @flow

import unicodeSymbols from "./unicodeSymbols";
import utils from "./utils";
import {checkNodeType} from "./parseNode";

@@ -18,3 +17,4 @@ import ParseError from "./ParseError";

import {Token} from "./Token";
import type {ParseNode, AnyParseNode, SymbolParseNode} from "./parseNode";
import type {ParseNode, AnyParseNode, SymbolParseNode, UnsupportedCmdParseNode}
from "./parseNode";
import type {Atom, Group} from "./symbols";

@@ -271,4 +271,3 @@ import type {Mode, ArgType, BreakToken} from "./types";

*/
handleUnsupportedCmd(): AnyParseNode {
const text = this.nextToken.text;
formatUnsupportedCmd(text: string): UnsupportedCmdParseNode {
const textordArray = [];

@@ -293,3 +292,2 @@

this.consume();
return colorNode;

@@ -324,3 +322,3 @@ }

// We got a limit control
const opNode = checkNodeType(base, "op");
let opNode = checkNodeType(base, "op");
if (opNode) {

@@ -331,5 +329,11 @@ const limits = lex.text === "\\limits";

} else {
throw new ParseError(
"Limit controls must follow a math operator",
lex);
opNode = checkNodeType(base, "operatorname");
if (opNode && opNode.alwaysHandleSupSub) {
const limits = lex.text === "\\limits";
opNode.limits = limits;
} else {
throw new ParseError(
"Limit controls must follow a math operator",
lex);
}
}

@@ -539,2 +543,18 @@ this.consume();

return this.parseGroup(name, optional, greediness, undefined, type);
case "hbox": {
// hbox argument type wraps the argument in the equivalent of
// \hbox, which is like \text but switching to \textstyle size.
const group = this.parseGroup(
name, optional, greediness, undefined, "text");
if (!group) {
return group;
}
const styledGroup = {
type: "styling",
mode: group.mode,
body: [group],
style: "text", // simulate \textstyle
};
return styledGroup;
}
case "raw": {

@@ -733,10 +753,2 @@ if (optional && this.nextToken.text === "{") {

const url = res.text.replace(/\\([#$%&~_^{}])/g, '$1');
let protocol = /^\s*([^\\/#]*?)(?::|&#0*58|&#x0*3a)/i.exec(url);
protocol = (protocol != null ? protocol[1] : "_relative");
const allowed = this.settings.allowedProtocols;
if (!utils.contains(allowed, "*") &&
!utils.contains(allowed, protocol)) {
throw new ParseError(
`Forbidden protocol '${protocol}'`, res);
}
return {

@@ -814,3 +826,4 @@ type: "url",

}
result = this.handleUnsupportedCmd();
result = this.formatUnsupportedCmd(text);
this.consume();
}

@@ -970,5 +983,12 @@ }

}
// All nonmathematical Unicode characters are rendered as if they
// are in text mode (wrapped in \text) because that's what it
// takes to render them in LaTeX. Setting `mode: this.mode` is
// another natural choice (the user requested math mode), but
// this makes it more difficult for getCharacterMetrics() to
// distinguish Unicode characters without metrics and those for
// which we want to simulate the letter M.
symbol = {
type: "textord",
mode: this.mode,
mode: "text",
loc: SourceLocation.range(nucleus),

@@ -975,0 +995,0 @@ text,

@@ -19,4 +19,25 @@ // @flow

export type TrustContextTypes = {
"\\href": {|
command: "\\href",
url: string,
protocol?: string,
|},
"\\includegraphics": {|
command: "\\includegraphics",
url: string,
protocol?: string,
|},
"\\url": {|
command: "\\url",
url: string,
protocol?: string,
|},
};
export type AnyTrustContext = $Values<TrustContextTypes>;
export type TrustFunction = (context: AnyTrustContext) => ?boolean;
export type SettingsOptions = {
displayMode?: boolean;
output?: "html" | "mathml" | "htmlAndMathml";
leqno?: boolean;

@@ -27,7 +48,8 @@ fleqn?: boolean;

macros?: MacroMap;
minRuleThickness?: number;
colorIsTextColor?: boolean;
strict?: boolean | "ignore" | "warn" | "error" | StrictFunction;
trust?: boolean | TrustFunction;
maxSize?: number;
maxExpand?: number;
allowedProtocols?: string[];
};

@@ -45,4 +67,5 @@

*/
class Settings {
export default class Settings {
displayMode: boolean;
output: "html" | "mathml" | "htmlAndMathml";
leqno: boolean;

@@ -53,7 +76,8 @@ fleqn: boolean;

macros: MacroMap;
minRuleThickness: number;
colorIsTextColor: boolean;
strict: boolean | "ignore" | "warn" | "error" | StrictFunction;
trust: boolean | TrustFunction;
maxSize: number;
maxExpand: number;
allowedProtocols: string[];

@@ -64,2 +88,3 @@ constructor(options: SettingsOptions) {

this.displayMode = utils.deflt(options.displayMode, false);
this.output = utils.deflt(options.output, "htmlAndMathml");
this.leqno = utils.deflt(options.leqno, false);

@@ -70,8 +95,11 @@ this.fleqn = utils.deflt(options.fleqn, false);

this.macros = options.macros || {};
this.minRuleThickness = Math.max(
0,
utils.deflt(options.minRuleThickness, 0)
);
this.colorIsTextColor = utils.deflt(options.colorIsTextColor, false);
this.strict = utils.deflt(options.strict, "warn");
this.trust = utils.deflt(options.trust, false);
this.maxSize = Math.max(0, utils.deflt(options.maxSize, Infinity));
this.maxExpand = Math.max(0, utils.deflt(options.maxExpand, 1000));
this.allowedProtocols = utils.deflt(options.allowedProtocols,
["http", "https", "mailto", "_relative"]);
}

@@ -146,4 +174,20 @@

}
/**
* Check whether to test potentially dangerous input, and return
* `true` (trusted) or `false` (untrusted). The sole argument `context`
* should be an object with `command` field specifying the relevant LaTeX
* command (as a string starting with `\`), and any other arguments, etc.
* If `context` has a `url` field, a `protocol` field will automatically
* get added by this function (changing the specified object).
*/
isTrusted(context: AnyTrustContext) {
if (context.url && !context.protocol) {
context.protocol = utils.protocolFromUrl(context.url);
}
const trust = typeof this.trust === "function"
? this.trust(context)
: this.trust;
return Boolean(trust);
}
}
export default Settings;
// @flow
/**
* This file provides support to domTree.js
* This file provides support to domTree.js and delimiter.js.
* It's a storehouse of path geometry for SVG images.

@@ -9,52 +9,143 @@ */

const hLinePad = 80; // padding above a sqrt viniculum.
const hLinePad = 80; // padding above a sqrt viniculum. Prevents image cropping.
const path: {[string]: string} = {
// The viniculum of a \sqrt can be made thicker by a KaTeX rendering option.
// Think of variable extraViniculum as two detours in the SVG path.
// The detour begins at the lower left of the area labeled extraViniculum below.
// The detour proceeds one extraViniculum distance up and slightly to the right,
// displacing the radiused corner between surd and viniculum. The radius is
// traversed as usual, then the detour resumes. It goes right, to the end of
// the very long viniculumn, then down one extraViniculum distance,
// after which it resumes regular path geometry for the radical.
/* viniculum
/
/▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒←extraViniculum
/ █████████████████████←0.04em (40 unit) std viniculum thickness
/ /
/ /
/ /\
/ / surd
*/
const sqrtMain = function(extraViniculum: number, hLinePad: number): string {
// sqrtMain path geometry is from glyph U221A in the font KaTeX Main
// All surds have 80 units padding above the viniculumn.
sqrtMain: `M95,${622 + hLinePad}c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,
-10,-9.5,-14c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54c44.2,-33.3,65.8,
-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10s173,378,173,378c0.7,0,
35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429c69,-144,104.5,-217.7,106.5,
-221c5.3,-9.3,12,-14,20,-14H400000v40H845.2724s-225.272,467,-225.272,467
s-235,486,-235,486c-2.7,4.7,-9,7,-19,7c-6,0,-10,-1,-12,-3s-194,-422,-194,-422
s-65,47,-65,47z M834 ${hLinePad}H400000v40H845z`,
return `M95,${622 + extraViniculum + hLinePad}
c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14
c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54
c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10
s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429
c69,-144,104.5,-217.7,106.5,-221
l${extraViniculum / 2.075} -${extraViniculum}
c5.3,-9.3,12,-14,20,-14
H400000v${40 + extraViniculum}H845.2724
s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7
c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z
M${834 + extraViniculum} ${hLinePad}h400000v${40 + extraViniculum}h-400000z`;
};
const sqrtSize1 = function(extraViniculum: number, hLinePad: number): string {
// size1 is from glyph U221A in the font KaTeX_Size1-Regular
sqrtSize1: `M263,${601 + hLinePad}c0.7,0,18,39.7,52,119c34,79.3,68.167,
158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120c340,-704.7,510.7,-1060.3,512,-1067
c4.7,-7.3,11,-11,19,-11H40000v40H1012.3s-271.3,567,-271.3,567c-38.7,80.7,-84,
175,-136,283c-52,108,-89.167,185.3,-111.5,232c-22.3,46.7,-33.8,70.3,-34.5,71
c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1s-109,-253,-109,-253c-72.7,-168,-109.3,
-252,-110,-252c-10.7,8,-22,16.7,-34,26c-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26
s76,-59,76,-59s76,-60,76,-60z M1001 ${hLinePad}H40000v40H1012z`,
return `M263,${601 + extraViniculum + hLinePad}c0.7,0,18,39.7,52,119
c34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120
c340,-704.7,510.7,-1060.3,512,-1067
l${extraViniculum / 2.084} -${extraViniculum}
c4.7,-7.3,11,-11,19,-11
H40000v${40 + extraViniculum}H1012.3
s-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232
c-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1
s-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26
c-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z
M${1001 + extraViniculum} ${hLinePad}h400000v${40 + extraViniculum}h-400000z`;
};
const sqrtSize2 = function(extraViniculum: number, hLinePad: number): string {
// size2 is from glyph U221A in the font KaTeX_Size2-Regular
// The 80 units padding is most obvious here. Note start node at M1001 80.
sqrtSize2: `M1001,${hLinePad}H400000v40H1013.1s-83.4,268,-264.1,840c-180.7,
572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7s-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,
-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744c-10,12,-21,25,-33,39s-32,39,-32,39
c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30c26.7,-32.7,52,-63,76,-91s52,-60,52,-60
s208,722,208,722c56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,
-658.5c53.7,-170.3,84.5,-266.8,92.5,-289.5c4,-6.7,10,-10,18,-10z
M1001 ${hLinePad}H400000v40H1013z`,
return `M983 ${10 + extraViniculum + hLinePad}
l${extraViniculum / 3.13} -${extraViniculum}
c4,-6.7,10,-10,18,-10 H400000v${40 + extraViniculum}
H1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7
s-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744
c-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30
c26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722
c56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5
c53.7,-170.3,84.5,-266.8,92.5,-289.5z
M${1001 + extraViniculum} ${hLinePad}h400000v${40 + extraViniculum}h-400000z`;
};
const sqrtSize3 = function(extraViniculum: number, hLinePad: number): string {
// size3 is from glyph U221A in the font KaTeX_Size3-Regular
sqrtSize3: `M424,${2398 + hLinePad}c-1.3,-0.7,-38.5,-172,-111.5,-514c-73,
-342,-109.8,-513.3,-110.5,-514c0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,
25c-5.7,9.3,-9.8,16,-12.5,20s-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,
-13s76,-122,76,-122s77,-121,77,-121s209,968,209,968c0,-2,84.7,-361.7,254,-1079
c169.3,-717.3,254.7,-1077.7,256,-1081c4,-6.7,10,-10,18,-10H400000v40H1014.6
s-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185c-2,6,-10,9,-24,9
c-8,0,-12,-0.7,-12,-2z M1001 ${hLinePad}H400000v40H1014z`,
return `M424,${2398 + extraViniculum + hLinePad}
c-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514
c0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20
s-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121
s209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081
l${extraViniculum / 4.223} -${extraViniculum}c4,-6.7,10,-10,18,-10 H400000
v${40 + extraViniculum}H1014.6
s-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185
c-2,6,-10,9,-24,9
c-8,0,-12,-0.7,-12,-2z M${1001 + extraViniculum} ${hLinePad}
h400000v${40 + extraViniculum}h-400000z`;
};
const sqrtSize4 = function(extraViniculum: number, hLinePad: number): string {
// size4 is from glyph U221A in the font KaTeX_Size4-Regular
sqrtSize4: `M473,${2713 + hLinePad}c339.3,-1799.3,509.3,-2700,510,-2702
c3.3,-7.3,9.3,-11,18,-11H400000v40H1017.7s-90.5,478,-276.2,1466c-185.7,988,
-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9c-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,
-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200c0,-1.3,-5.3,8.7,-16,30c-10.7,
21.3,-21.3,42.7,-32,64s-16,33,-16,33s-26,-26,-26,-26s76,-153,76,-153s77,-151,
77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104,606z
M1001 ${hLinePad}H400000v40H1017z`,
return `M473,${2713 + extraViniculum + hLinePad}
c339.3,-1799.3,509.3,-2700,510,-2702 l${extraViniculum / 5.298} -${extraViniculum}
c3.3,-7.3,9.3,-11,18,-11 H400000v${40 + extraViniculum}H1017.7
s-90.5,478,-276.2,1466c-185.7,988,-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9
c-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200
c0,-1.3,-5.3,8.7,-16,30c-10.7,21.3,-21.3,42.7,-32,64s-16,33,-16,33s-26,-26,-26,-26
s76,-153,76,-153s77,-151,77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104,
606zM${1001 + extraViniculum} ${hLinePad}h400000v${40 + extraViniculum}H1017.7z`;
};
const sqrtTall = function(
extraViniculum: number,
hLinePad: number,
viewBoxHeight: number
): string {
// sqrtTall is from glyph U23B7 in the font KaTeX_Size4-Regular
// One path edge has a variable length. It runs vertically from the viniculumn
// to a point near (14 units) the bottom of the surd. The viniculum
// is normally 40 units thick. So the length of the line in question is:
const vertSegment = viewBoxHeight - 54 - hLinePad - extraViniculum;
return `M702 ${extraViniculum + hLinePad}H400000${40 + extraViniculum}
H742v${vertSegment}l-4 4-4 4c-.667.7 -2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1
h-12l-28-84c-16.667-52-96.667 -294.333-240-727l-212 -643 -85 170
c-4-3.333-8.333-7.667-13 -13l-13-13l77-155 77-156c66 199.333 139 419.667
219 661 l218 661zM702 ${hLinePad}H400000v${40 + extraViniculum}H742z`;
};
export const sqrtPath = function(
size: string,
extraViniculum: number,
viewBoxHeight: number
): string {
extraViniculum = 1000 * extraViniculum; // Convert from document ems to viewBox.
let path = "";
switch (size) {
case "sqrtMain":
path = sqrtMain(extraViniculum, hLinePad);
break;
case "sqrtSize1":
path = sqrtSize1(extraViniculum, hLinePad);
break;
case "sqrtSize2":
path = sqrtSize2(extraViniculum, hLinePad);
break;
case "sqrtSize3":
path = sqrtSize3(extraViniculum, hLinePad);
break;
case "sqrtSize4":
path = sqrtSize4(extraViniculum, hLinePad);
break;
case "sqrtTall":
path = sqrtTall(extraViniculum, hLinePad, viewBoxHeight);
}
return path;
};
export const path: {[string]: string} = {
// The doubleleftarrow geometry is from glyph U+21D0 in the font KaTeX Main

@@ -367,4 +458,1 @@ doubleleftarrow: `M262 157

};
export default {path};

@@ -309,3 +309,3 @@ // @flow

// AMS Greek
defineSymbol(math, ams, textord, "\u03dd", "\\digamma");
defineSymbol(math, ams, textord, "\u03dd", "\\digamma", true);
defineSymbol(math, ams, textord, "\u03f0", "\\varkappa");

@@ -312,0 +312,0 @@

@@ -23,3 +23,3 @@ // @flow

implements HtmlDomNode, MathDomNode {
children: ChildType[];
children: $ReadOnlyArray<ChildType>;
// HtmlDomNode

@@ -32,3 +32,3 @@ classes: string[];

constructor(children: ChildType[]) {
constructor(children: $ReadOnlyArray<ChildType>) {
this.children = children;

@@ -35,0 +35,0 @@ this.classes = [];

@@ -23,3 +23,4 @@ // @flow

// - Mode: Node group parsed in given mode.
export type ArgType = "color" | "size" | "url" | "raw" | "original" | Mode;
export type ArgType = "color" | "size" | "url" | "raw" | "original" | "hbox" |
Mode;

@@ -26,0 +27,0 @@ // LaTeX display style.

@@ -14,3 +14,3 @@ /* eslint no-console:0 */

path.join(__dirname, 'unicodeAccents.js')).mtime <= targetMtime) {
return;
process.exit(0);
}

@@ -17,0 +17,0 @@

@@ -94,2 +94,11 @@ // @flow

/**
* Return the protocol of a URL, or "_relative" if the URL does not specify a
* protocol (and thus is relative).
*/
export const protocolFromUrl = function(url: string): string {
const protocol = /^\s*([^\\/#]*?)(?::|&#0*58|&#x0*3a)/i.exec(url);
return (protocol != null ? protocol[1] : "_relative");
};
export default {

@@ -102,2 +111,3 @@ contains,

isCharacterBox,
protocolFromUrl,
};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc