diff --git a/src/buildCommon.js b/src/buildCommon.js index e8f39453..28d88df5 100644 --- a/src/buildCommon.js +++ b/src/buildCommon.js @@ -649,45 +649,10 @@ const retrieveTextFontName = function( return `${baseFontName}-${fontStylesName}`; }; -// A map of spacing functions to their attributes, like size and corresponding -// CSS class -const spacingFunctions: {[string]: {| size: string, className: string |}} = { - "\\qquad": { - size: "2em", - className: "qquad", - }, - "\\quad": { - size: "1em", - className: "quad", - }, - "\\enspace": { - size: "0.5em", - className: "enspace", - }, - "\\;": { - size: "0.277778em", - className: "thickspace", - }, - "\\:": { - size: "0.22222em", - className: "mediumspace", - }, - "\\,": { - size: "0.16667em", - className: "thinspace", - }, - "\\!": { - size: "-0.16667em", - className: "negativethinspace", - }, - "\\nobreak": { - size: "0em", - className: "nobreak", - }, - "\\allowbreak": { - size: "0em", - className: "allowbreak", - }, +// A map of CSS-based spacing functions to their CSS class. +const cssSpace: {[string]: string} = { + "\\nobreak": "nobreak", + "\\allowbreak": "allowbreak", }; // A lookup table to determine whether a spacing function/symbol should be @@ -802,6 +767,6 @@ export default { staticSvg, svgData, tryCombineChars, - spacingFunctions, + cssSpace, regularSpace, }; diff --git a/src/defineFunction.js b/src/defineFunction.js index faab9811..4d1cfb8c 100644 --- a/src/defineFunction.js +++ b/src/defineFunction.js @@ -8,7 +8,7 @@ import type Options from "./Options"; import type {ArgType, BreakToken, Mode} from "./types"; import type {HtmlDomNode} from "./domTree"; import type {Token} from "./Token"; -import type {MathNode, TextNode} from "./mathMLTree"; +import type {MathNodeClass} from "./mathMLTree"; /** Context provided to function handlers for error messages. */ export type FunctionContext = {| @@ -28,7 +28,7 @@ export type HtmlBuilder = (ParseNode, Options) => HtmlDomNod export type MathMLBuilder = ( group: ParseNode, options: Options, -) => MathNode | TextNode | domTree.documentFragment; +) => MathNodeClass | domTree.documentFragment; // More general version of `HtmlBuilder` for nodes (e.g. \sum, accent types) // whose presence impacts super/subscripting. In this case, ParseNode<"supsub"> diff --git a/src/functions.js b/src/functions.js index c5227318..0583238e 100644 --- a/src/functions.js +++ b/src/functions.js @@ -24,7 +24,6 @@ import "./functions/lap"; import "./functions/math"; import "./functions/mathchoice"; import "./functions/mclass"; -import "./functions/mod"; import "./functions/op"; import "./functions/operatorname"; import "./functions/ordgroup"; diff --git a/src/functions/kern.js b/src/functions/kern.js index 2d8f5659..8fd353fc 100644 --- a/src/functions/kern.js +++ b/src/functions/kern.js @@ -48,11 +48,7 @@ defineFunction({ return buildCommon.makeGlue(group.value.dimension, options); }, mathmlBuilder: (group, options) => { - const node = new mathMLTree.MathNode("mspace"); - const dimension = calculateSize(group.value.dimension, options); - node.setAttribute("width", dimension + "em"); - - return node; + return new mathMLTree.SpaceNode(dimension); }, }); diff --git a/src/functions/mod.js b/src/functions/mod.js deleted file mode 100644 index 902664d4..00000000 --- a/src/functions/mod.js +++ /dev/null @@ -1,133 +0,0 @@ -// @flow -// \mod-type functions -import defineFunction, {ordargument} from "../defineFunction"; -import buildCommon from "../buildCommon"; -import mathMLTree from "../mathMLTree"; -import Style from "../Style"; - -import * as html from "../buildHTML"; -import * as mml from "../buildMathML"; - -const htmlModBuilder = (group, options) => { - const inner = []; - - if (group.value.modType === "bmod") { - // “\nonscript\mskip-\medmuskip\mkern5mu”, where \medmuskip is - // 4mu plus 2mu minus 1mu, translates to 1mu space in - // display/textstyle and 5mu space in script/scriptscriptstyle. - if (!options.style.isTight()) { - inner.push(buildCommon.makeSpan( - ["mspace", "muspace"], [], options)); - } else { - inner.push(buildCommon.makeSpan( - ["mspace", "thickspace"], [], options)); - } - } else if (options.style.size === Style.DISPLAY.size) { - inner.push(buildCommon.makeSpan(["mspace", "quad"], [], options)); - } else if (group.value.modType === "mod") { - inner.push( - buildCommon.makeSpan(["mspace", "twelvemuspace"], [], options)); - } else { - inner.push( - buildCommon.makeSpan(["mspace", "eightmuspace"], [], options)); - } - - if (group.value.modType === "pod" || group.value.modType === "pmod") { - inner.push(buildCommon.mathsym("(", group.mode)); - } - - if (group.value.modType !== "pod") { - const modInner = [ - buildCommon.mathsym("m", group.mode), - buildCommon.mathsym("o", group.mode), - buildCommon.mathsym("d", group.mode)]; - if (group.value.modType === "bmod") { - inner.push(buildCommon.makeSpan(["mbin"], modInner, options)); - // “\mkern5mu\nonscript\mskip-\medmuskip” as above - if (!options.style.isTight()) { - inner.push(buildCommon.makeSpan( - ["mspace", "muspace"], [], options)); - } else { - inner.push(buildCommon.makeSpan( - ["mspace", "thickspace"], [], options)); - } - } else { - Array.prototype.push.apply(inner, modInner); - inner.push( - buildCommon.makeSpan(["mspace", "sixmuspace"], [], options)); - } - } - - if (group.value.value) { - Array.prototype.push.apply(inner, - html.buildExpression(group.value.value, options, false)); - } - - if (group.value.modType === "pod" || group.value.modType === "pmod") { - inner.push(buildCommon.mathsym(")", group.mode)); - } - - return buildCommon.makeFragment(inner); -}; - -const mmlModBuilder = (group, options) => { - let inner = []; - - if (group.value.modType === "pod" || group.value.modType === "pmod") { - inner.push(new mathMLTree.MathNode( - "mo", [mml.makeText("(", group.mode)])); - } - if (group.value.modType !== "pod") { - inner.push(new mathMLTree.MathNode( - "mo", [mml.makeText("mod", group.mode)])); - } - if (group.value.value) { - const space = new mathMLTree.MathNode("mspace"); - space.setAttribute("width", "0.333333em"); - inner.push(space); - inner = inner.concat(mml.buildExpression(group.value.value, options)); - } - if (group.value.modType === "pod" || group.value.modType === "pmod") { - inner.push(new mathMLTree.MathNode( - "mo", [mml.makeText(")", group.mode)])); - } - - return new mathMLTree.MathNode("mo", inner); -}; - -defineFunction({ - type: "mod", - names: ["\\bmod"], - props: { - numArgs: 0, - }, - handler: (context, args) => { - return { - type: "mod", - modType: "bmod", - value: null, - }; - }, - htmlBuilder: htmlModBuilder, - mathmlBuilder: mmlModBuilder, -}); - -// Note: calling defineFunction with a type that's already been defined only -// works because the same htmlBuilder and mathmlBuilder are being used. -defineFunction({ - type: "mod", - names: ["\\pod", "\\pmod", "\\mod"], - props: { - numArgs: 1, - }, - handler: (context, args) => { - const body = args[0]; - return { - type: "mod", - modType: context.funcName.substr(1), - value: ordargument(body), - }; - }, - htmlBuilder: htmlModBuilder, - mathmlBuilder: mmlModBuilder, -}); diff --git a/src/functions/operatorname.js b/src/functions/operatorname.js index 82c470ef..b67052af 100644 --- a/src/functions/operatorname.js +++ b/src/functions/operatorname.js @@ -77,10 +77,10 @@ defineFunction({ group.value.value, options.withFont("mathrm")); let word = temp.map(node => node.toText()).join(""); - word = word.replace(/\u2212/g, "-"); word = word.replace(/\u2217/g, "*"); - output = [new mathMLTree.TextNode(word)]; + // word has already been escaped by `node.toText()` + output = [new mathMLTree.TextNode(word, false)]; } const identifier = new mathMLTree.MathNode("mi", output); identifier.setAttribute("mathvariant", "normal"); diff --git a/src/functions/symbolsSpacing.js b/src/functions/symbolsSpacing.js index 533e874a..78ace473 100644 --- a/src/functions/symbolsSpacing.js +++ b/src/functions/symbolsSpacing.js @@ -2,6 +2,7 @@ import {defineFunctionBuilders} from "../defineFunction"; import buildCommon from "../buildCommon"; import mathMLTree from "../mathMLTree"; +import ParseError from "../ParseError"; // ParseNode<"spacing"> created in Parser.js from the "spacing" symbol Groups in // src/symbols.js. @@ -22,12 +23,13 @@ defineFunctionBuilders({ [buildCommon.mathsym(group.value, group.mode, options)], options); } - } else { - // Other kinds of spaces are of arbitrary width. We use CSS to - // generate these. + } else if (buildCommon.cssSpace.hasOwnProperty(group.value)) { + // Spaces based on just a CSS class. return buildCommon.makeSpan( - ["mspace", buildCommon.spacingFunctions[group.value].className], + ["mspace", buildCommon.cssSpace[group.value]], [], options); + } else { + throw new ParseError(`Unknown type of space "${group.value}"`); } }, mathmlBuilder(group, options) { @@ -36,11 +38,11 @@ defineFunctionBuilders({ if (buildCommon.regularSpace.hasOwnProperty(group.value)) { node = new mathMLTree.MathNode( "mtext", [new mathMLTree.TextNode("\u00a0")]); + } else if (buildCommon.cssSpace.hasOwnProperty(group.value)) { + // CSS-based MathML spaces (\nobreak, \allowbreak) are ignored + return new mathMLTree.MathNode("mspace"); } else { - node = new mathMLTree.MathNode("mspace"); - - node.setAttribute( - "width", buildCommon.spacingFunctions[group.value].size); + throw new ParseError(`Unknown type of space "${group.value}"`); } return node; diff --git a/src/katex.less b/src/katex.less index 09834d95..498fbba8 100644 --- a/src/katex.less +++ b/src/katex.less @@ -244,54 +244,6 @@ .mspace { display: inline-block; - - &.negativethinspace { - margin-left: -@thinspace; - } - - &.muspace { - width: @muspace; - } - - &.thinspace { - width: @thinspace; - } - - &.negativemediumspace { - margin-left: -@mediumspace; - } - - &.mediumspace { - width: @mediumspace; - } - - &.thickspace { - width: @thickspace; - } - - &.sixmuspace { - width: 0.333333em; - } - - &.eightmuspace { - width: 0.444444em; - } - - &.enspace { - width: 0.5em; - } - - &.twelvemuspace { - width: 0.666667em; - } - - &.quad { - width: 1em; - } - - &.qquad { - width: 2em; - } } .llap, diff --git a/src/macros.js b/src/macros.js index b80b718f..e89b3f85 100644 --- a/src/macros.js +++ b/src/macros.js @@ -292,8 +292,6 @@ const dotsByToken = { '\\bigoplus': '\\dotsb', '\\bigodot': '\\dotsb', '\\bigsqcup': '\\dotsb', - '\\implies': '\\dotsb', - '\\impliedby': '\\dotsb', '\\And': '\\dotsb', '\\longrightarrow': '\\dotsb', '\\Longrightarrow': '\\dotsb', @@ -304,11 +302,9 @@ const dotsByToken = { '\\mapsto': '\\dotsb', '\\longmapsto': '\\dotsb', '\\hookrightarrow': '\\dotsb', - '\\iff': '\\dotsb', '\\doteq': '\\dotsb', // Symbols whose definition starts with \mathbin: '\\mathbin': '\\dotsb', - '\\bmod': '\\dotsb', // Symbols whose definition starts with \mathrel: '\\mathrel': '\\dotsb', '\\relbar': '\\dotsb', @@ -416,10 +412,44 @@ defineMacro("\\DOTSI", "\\relax"); defineMacro("\\DOTSB", "\\relax"); defineMacro("\\DOTSX", "\\relax"); -// http://texdoc.net/texmf-dist/doc/latex/amsmath/amsmath.pdf -defineMacro("\\thinspace", "\\,"); // \let\thinspace\, -defineMacro("\\medspace", "\\:"); // \let\medspace\: -defineMacro("\\thickspace", "\\;"); // \let\thickspace\; +// Spacing, based on amsmath.sty's override of LaTeX defaults +// \DeclareRobustCommand{\tmspace}[3]{% +// \ifmmode\mskip#1#2\else\kern#1#3\fi\relax} +defineMacro("\\tmspace", "\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"); +// \renewcommand{\,}{\tmspace+\thinmuskip{.1667em}} +// TODO: math mode should use \thinmuskip +defineMacro("\\,", "\\tmspace+{3mu}{.1667em}"); +// \let\thinspace\, +defineMacro("\\thinspace", "\\,"); +// \renewcommand{\:}{\tmspace+\medmuskip{.2222em}} +// TODO: math mode should use \medmuskip = 4mu plus 2mu minus 4mu +defineMacro("\\:", "\\tmspace+{4mu}{.2222em}"); +// \let\medspace\: +defineMacro("\\medspace", "\\:"); +// \renewcommand{\;}{\tmspace+\thickmuskip{.2777em}} +// TODO: math mode should use \thickmuskip = 5mu plus 5mu +defineMacro("\\;", "\\tmspace+{5mu}{.2777em}"); +// \let\thickspace\; +defineMacro("\\thickspace", "\\;"); +// \renewcommand{\!}{\tmspace-\thinmuskip{.1667em}} +// TODO: math mode should use \thinmuskip +defineMacro("\\!", "\\tmspace-{3mu}{.1667em}"); +// \let\negthinspace\! +defineMacro("\\negthinspace", "\\!"); +// \newcommand{\negmedspace}{\tmspace-\medmuskip{.2222em}} +// TODO: math mode should use \medmuskip +defineMacro("\\negmedspace", "\\tmspace-{4mu}{.2222em}"); +// \newcommand{\negthickspace}{\tmspace-\thickmuskip{.2777em}} +// TODO: math mode should use \thickmuskip +defineMacro("\\negthickspace", "\\tmspace-{5mu}{.277em}"); +// \def\enspace{\kern.5em } +defineMacro("\\enspace", "\\kern.5em "); +// \def\enskip{\hskip.5em\relax} +defineMacro("\\enskip", "\\hskip.5em\\relax"); +// \def\quad{\hskip1em\relax} +defineMacro("\\quad", "\\hskip1em\\relax"); +// \def\qquad{\hskip2em\relax} +defineMacro("\\qquad", "\\hskip2em\\relax"); // \tag@in@display form of \tag defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren"); @@ -431,6 +461,26 @@ defineMacro("\\tag@literal", (context) => { return "\\gdef\\df@tag{\\text{#1}}"; }); +// \renewcommand{\bmod}{\nonscript\mskip-\medmuskip\mkern5mu\mathbin +// {\operator@font mod}\penalty900 +// \mkern5mu\nonscript\mskip-\medmuskip} +// \newcommand{\pod}[1]{\allowbreak +// \if@display\mkern18mu\else\mkern8mu\fi(#1)} +// \renewcommand{\pmod}[1]{\pod{{\operator@font mod}\mkern6mu#1}} +// \newcommand{\mod}[1]{\allowbreak\if@display\mkern18mu +// \else\mkern12mu\fi{\operator@font mod}\,\,#1} +// TODO: math mode should use \medmuskip = 4mu plus 2mu minus 4mu +defineMacro("\\bmod", + "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}" + + "\\mathbin{\\rm mod}" + + "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}"); +defineMacro("\\pod", "\\allowbreak" + + "\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)"); +defineMacro("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}"); +defineMacro("\\mod", "\\allowbreak" + + "\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}" + + "{\\rm mod}\\,\\,#1"); + ////////////////////////////////////////////////////////////////////// // LaTeX source2e diff --git a/src/mathMLTree.js b/src/mathMLTree.js index 4adc9e07..ce301a8e 100644 --- a/src/mathMLTree.js +++ b/src/mathMLTree.js @@ -24,6 +24,8 @@ export type MathNodeType = "mrow" | "menclose" | "mstyle" | "mpadded" | "mphantom"; +export type MathNodeClass = MathNode | TextNode | SpaceNode; + /** * This node represents a general purpose MathML node of any type. The * constructor requires the type of node to create (for example, `"mo"` or @@ -95,18 +97,9 @@ export class MathNode { } /** - * Converts the math node into a string, similar to innerText. + * Converts the math node into a string, similar to innerText, but escaped. */ toText(): string { - if (this.type === "mspace") { - if (this.attributes.width === "0.16667em") { - return "\u2006"; - } else { - // TODO: Use other space characters for different widths. - // https://github.com/Khan/KaTeX/issues/1036 - return " "; - } - } return this.children.map(child => child.toText()).join(""); } } @@ -116,34 +109,114 @@ export class MathNode { */ export class TextNode { text: string; + needsEscape: boolean; - constructor(text: string) { + constructor(text: string, needsEscape: boolean = true) { this.text = text; + this.needsEscape = needsEscape; } /** * Converts the text node into a DOM text node. */ toNode(): Node { - return document.createTextNode(this.text); + return document.createTextNode(this.toText()); } /** - * Converts the text node into HTML markup (which is just the text itself). + * Converts the text node into escaped HTML markup + * (representing the text itself). */ toMarkup(): string { - return utils.escape(this.text); + return this.toText(); } /** - * Converts the text node into a string (which is just the text iteself). + * Converts the text node into an escaped string + * (representing the text iteself). */ toText(): string { - return this.text; + return this.needsEscape ? utils.escape(this.text) : this.text; + } +} + +/** + * This node represents a space, but may render as or as text, + * depending on the width. + */ +class SpaceNode { + width: number; + character: ?string; + + /** + * Create a Space node with width given in CSS ems. + */ + constructor(width: number) { + this.width = width; + // See https://www.w3.org/TR/2000/WD-MathML2-20000328/chapter6.html + // for a table of space-like characters. We consistently use the + // &LongNames; because Unicode does not have single characters for + //    (\u2005\u200a) and all negative spaces. + if (width >= 0.05555 && width <= 0.05556) { + this.character = " "; // \u200a + } else if (width >= 0.1666 && width <= 0.1667) { + this.character = " "; // \u2009 + } else if (width >= 0.2222 && width <= 0.2223) { + this.character = " "; // \u2005 + } else if (width >= 0.2777 && width <= 0.2778) { + this.character = "  "; // \u2005\u200a + } else if (width >= -0.05556 && width <= -0.05555) { + this.character = "​"; + } else if (width >= -0.1667 && width <= -0.1666) { + this.character = "​"; + } else if (width >= -0.2223 && width <= -0.2222) { + this.character = "​"; + } else if (width >= -0.2778 && width <= -0.2777) { + this.character = "​"; + } else { + this.character = null; + } + } + + /** + * Converts the math node into a MathML-namespaced DOM element. + */ + toNode(): Node { + if (this.character) { + return document.createTextNode(this.character); + } else { + const node = document.createElementNS( + "http://www.w3.org/1998/Math/MathML", "mspace"); + node.setAttribute("width", this.width + "em"); + return node; + } + } + + /** + * Converts the math node into an HTML markup string. + */ + toMarkup(): string { + if (this.character) { + return `${this.character}`; + } else { + return ``; + } + } + + /** + * Converts the math node into a string, similar to innerText. + */ + toText(): string { + if (this.character) { + return this.character; + } else { + return " "; + } } } export default { MathNode, TextNode, + SpaceNode, }; diff --git a/src/symbols.js b/src/symbols.js index 36c750d8..50ffeed2 100644 --- a/src/symbols.js +++ b/src/symbols.js @@ -571,27 +571,13 @@ defineSymbol(math, main, rel, "\u2192", "\\rightarrow", true); defineSymbol(math, main, rel, "\u2192", "\\to"); defineSymbol(math, ams, rel, "\u2271", "\\ngeq", true); defineSymbol(math, ams, rel, "\u2270", "\\nleq", true); -defineSymbol(math, main, spacing, null, "\\!"); defineSymbol(math, main, spacing, "\u00a0", "\\ "); defineSymbol(math, main, spacing, "\u00a0", "~"); -defineSymbol(math, main, spacing, null, "\\,"); -defineSymbol(math, main, spacing, null, "\\:"); -defineSymbol(math, main, spacing, null, "\\;"); -defineSymbol(math, main, spacing, null, "\\enspace"); -defineSymbol(math, main, spacing, null, "\\qquad"); -defineSymbol(math, main, spacing, null, "\\quad"); defineSymbol(math, main, spacing, "\u00a0", "\\space"); // Ref: LaTeX Source 2e: \DeclareRobustCommand{\nobreakspace}{% defineSymbol(math, main, spacing, "\u00a0", "\\nobreakspace"); -defineSymbol(text, main, spacing, null, "\\!"); defineSymbol(text, main, spacing, "\u00a0", "\\ "); defineSymbol(text, main, spacing, "\u00a0", "~"); -defineSymbol(text, main, spacing, null, "\\,"); -defineSymbol(text, main, spacing, null, "\\:"); -defineSymbol(text, main, spacing, null, "\\;"); -defineSymbol(text, main, spacing, null, "\\enspace"); -defineSymbol(text, main, spacing, null, "\\qquad"); -defineSymbol(text, main, spacing, null, "\\quad"); defineSymbol(text, main, spacing, "\u00a0", "\\space"); defineSymbol(text, main, spacing, "\u00a0", "\\nobreakspace"); defineSymbol(math, main, spacing, null, "\\nobreak"); diff --git a/test/__snapshots__/mathml-spec.js.snap b/test/__snapshots__/mathml-spec.js.snap index 138404b0..4cbaaca0 100644 --- a/test/__snapshots__/mathml-spec.js.snap +++ b/test/__snapshots__/mathml-spec.js.snap @@ -57,6 +57,24 @@ exports[`A MathML builder accents turn into in MathML 1`] `; +exports[`A MathML builder normal spaces render normally 1`] = ` + + + + + + + + + + + \\kern1em\\kern1ex + + + + +`; + exports[`A MathML builder should concatenate digits into single 1`] = ` @@ -125,8 +143,9 @@ exports[`A MathML builder should generate the right types of nodes 1`] = ` 1 - - + +    + a @@ -169,7 +188,7 @@ exports[`A MathML builder should output \\limsup_{x \\rightarrow \\infty} correc - lim sup + lim sup ⁡ @@ -204,7 +223,7 @@ exports[`A MathML builder should output \\limsup_{x \\rightarrow \\infty} in dis - lim sup + lim sup ⁡ @@ -519,6 +538,74 @@ exports[`A MathML builder should use for large operators 1`] = ` `; +exports[`A MathML builder special spaces render specially 1`] = ` + + + + + +   + + +   + + +   + + +   + + +    + + +    + + + ​ + + + ​ + + + ​ + + + ​ + + +   + + +   + + +   + + +    + + + ​ + + + ​ + + + ​ + + + ​ + + + + \\,\\thinspace\\:\\medspace\\;\\thickspace\\!\\negthinspace\\negmedspace\\negthickspace\\mkern1mu\\mkern3mu\\mkern4mu\\mkern5mu\\mkern-1mu\\mkern-3mu\\mkern-4mu\\mkern-5mu + + + + +`; + exports[`A MathML builder tags use 1`] = ` diff --git a/test/mathml-spec.js b/test/mathml-spec.js index 57f5c436..3af5faa1 100644 --- a/test/mathml-spec.js +++ b/test/mathml-spec.js @@ -107,4 +107,15 @@ describe("A MathML builder", function() { expect(getMathML("\\tag{hi} x+y^2", {displayMode: true})) .toMatchSnapshot(); }); + + it('normal spaces render normally', function() { + expect(getMathML("\\kern1em\\kern1ex")).toMatchSnapshot(); + }); + it('special spaces render specially', function() { + expect(getMathML( + "\\,\\thinspace\\:\\medspace\\;\\thickspace" + + "\\!\\negthinspace\\negmedspace\\negthickspace" + + "\\mkern1mu\\mkern3mu\\mkern4mu\\mkern5mu" + + "\\mkern-1mu\\mkern-3mu\\mkern-4mu\\mkern-5mu")).toMatchSnapshot(); + }); }); diff --git a/test/screenshotter/images/ArrayMode-chrome.png b/test/screenshotter/images/ArrayMode-chrome.png index 1859b946..0f96c706 100644 Binary files a/test/screenshotter/images/ArrayMode-chrome.png and b/test/screenshotter/images/ArrayMode-chrome.png differ diff --git a/test/screenshotter/images/ArrayMode-firefox.png b/test/screenshotter/images/ArrayMode-firefox.png index a676fa2b..afcad4a7 100644 Binary files a/test/screenshotter/images/ArrayMode-firefox.png and b/test/screenshotter/images/ArrayMode-firefox.png differ diff --git a/test/screenshotter/images/FractionTest-chrome.png b/test/screenshotter/images/FractionTest-chrome.png index a8d88e5c..39765322 100644 Binary files a/test/screenshotter/images/FractionTest-chrome.png and b/test/screenshotter/images/FractionTest-chrome.png differ diff --git a/test/screenshotter/images/LimitControls-chrome.png b/test/screenshotter/images/LimitControls-chrome.png index 1b75bec5..b3b9904c 100644 Binary files a/test/screenshotter/images/LimitControls-chrome.png and b/test/screenshotter/images/LimitControls-chrome.png differ diff --git a/test/screenshotter/images/ModScript-chrome.png b/test/screenshotter/images/ModScript-chrome.png index 2ce8ac15..675ffa4a 100644 Binary files a/test/screenshotter/images/ModScript-chrome.png and b/test/screenshotter/images/ModScript-chrome.png differ diff --git a/test/screenshotter/images/ModScript-firefox.png b/test/screenshotter/images/ModScript-firefox.png index 27ecd68c..b141a23c 100644 Binary files a/test/screenshotter/images/ModScript-firefox.png and b/test/screenshotter/images/ModScript-firefox.png differ diff --git a/test/screenshotter/images/StyleSpacing-chrome.png b/test/screenshotter/images/StyleSpacing-chrome.png index dad5e8cd..e0b8ab29 100644 Binary files a/test/screenshotter/images/StyleSpacing-chrome.png and b/test/screenshotter/images/StyleSpacing-chrome.png differ diff --git a/test/screenshotter/images/StyleSpacing-firefox.png b/test/screenshotter/images/StyleSpacing-firefox.png index 6599401a..a7c22944 100644 Binary files a/test/screenshotter/images/StyleSpacing-firefox.png and b/test/screenshotter/images/StyleSpacing-firefox.png differ