From 9822414733b315fa78e7b3f81da0e4dc011d293a Mon Sep 17 00:00:00 2001 From: Ron Kok Date: Mon, 13 May 2019 16:31:04 -0700 Subject: [PATCH] Render MathML directly (#1966) * Render MathML * Fix lint error * Change from main api to rendering options --- docs/options.md | 4 +++ src/Settings.js | 3 ++ src/buildMathML.js | 5 ++- src/buildTree.js | 17 ++++++---- test/__snapshots__/katex-spec.js.snap | 4 +-- test/__snapshots__/mathml-spec.js.snap | 46 +++++++++++++------------- 6 files changed, 47 insertions(+), 32 deletions(-) diff --git a/docs/options.md b/docs/options.md index 86e87915..d10458d6 100644 --- a/docs/options.md +++ b/docs/options.md @@ -5,6 +5,10 @@ title: Options You can provide an object of options as the last argument to [`katex.render` and `katex.renderToString`](api.md). Available options are: - `displayMode`: `boolean`. If `true` the math will be rendered in display mode, which will put the math in display style (so `\int` and `\sum` are large, for example), and will center the math on the page on its own line. If `false` the math will be rendered in inline mode. (default: `false`) +- `output`: `string`. Determines the markup language of the output. The valid choices are: + - `html`: Outputs KaTeX in HTML only. + - `mathml`: Outputs KaTeX in MathML only. + - `htmlAndMathml`: Outputs HTML for visual rendering and includes MathML for accessibility. This is the default. - `leqno`: `boolean`. If `true`, display math has `\tag`s rendered on the left instead of the right, like `\usepackage[leqno]{amsmath}` in LaTeX. - `fleqn`: `boolean`. If `true`, display math renders flush left, like `\documentclass[fleqn]` in LaTeX. - `throwOnError`: `boolean`. If `true` (the default), KaTeX will throw a `ParseError` when it encounters an unsupported command or invalid LaTeX. If `false`, KaTeX will render unsupported commands as text, and render invalid LaTeX as its source code with hover text giving the error, in the color given by `errorColor`. diff --git a/src/Settings.js b/src/Settings.js index 5ecc1d8b..14d5520d 100644 --- a/src/Settings.js +++ b/src/Settings.js @@ -18,6 +18,7 @@ export type StrictFunction = export type SettingsOptions = { displayMode?: boolean; + output?: "html" | "mathml" | "htmlAndMathml"; leqno?: boolean; fleqn?: boolean; throwOnError?: boolean; @@ -42,6 +43,7 @@ export type SettingsOptions = { */ class Settings { displayMode: boolean; + output: "html" | "mathml" | "htmlAndMathml"; leqno: boolean; fleqn: boolean; throwOnError: boolean; @@ -57,6 +59,7 @@ class Settings { // allow null options options = options || {}; this.displayMode = utils.deflt(options.displayMode, false); + this.output = utils.deflt(options.output, "htmlAndMathml"); this.leqno = utils.deflt(options.leqno, false); this.fleqn = utils.deflt(options.fleqn, false); this.throwOnError = utils.deflt(options.throwOnError, true); diff --git a/src/buildMathML.js b/src/buildMathML.js index 89aa6e58..65572f4e 100644 --- a/src/buildMathML.js +++ b/src/buildMathML.js @@ -212,6 +212,7 @@ export default function buildMathML( tree: AnyParseNode[], texExpression: string, options: Options, + forMathmlOnly: boolean, ): DomSpan { const expression = buildExpression(tree, options); @@ -235,11 +236,13 @@ export default function buildMathML( "semantics", [wrapper, annotation]); const math = new mathMLTree.MathNode("math", [semantics]); + math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML"); // You can't style nodes, so we wrap the node in a span. // NOTE: The span class is not typed to have nodes as children, and // we don't want to make the children type more generic since the children // 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]); } diff --git a/src/buildTree.js b/src/buildTree.js index d012513e..32ff073f 100644 --- a/src/buildTree.js +++ b/src/buildTree.js @@ -36,12 +36,17 @@ export const buildTree = function( settings: Settings, ): DomSpan { const options = optionsFromSettings(settings); - const mathMLNode = buildMathML(tree, expression, options); - const htmlNode = buildHTML(tree, options); - - const katexNode = buildCommon.makeSpan(["katex"], [ - mathMLNode, htmlNode, - ]); + 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]); + } return displayWrap(katexNode, settings); }; diff --git a/test/__snapshots__/katex-spec.js.snap b/test/__snapshots__/katex-spec.js.snap index 7c224f25..ffd69040 100755 --- a/test/__snapshots__/katex-spec.js.snap +++ b/test/__snapshots__/katex-spec.js.snap @@ -784,7 +784,7 @@ exports[`Extending katex by new fonts and symbols Add new font class to new exte - + @@ -862,7 +862,7 @@ exports[`Newlines via \\\\ and \\newline \\\\ causes newline, even after mrel an - + diff --git a/test/__snapshots__/mathml-spec.js.snap b/test/__snapshots__/mathml-spec.js.snap index 59b63ca6..7ed2d0b0 100644 --- a/test/__snapshots__/mathml-spec.js.snap +++ b/test/__snapshots__/mathml-spec.js.snap @@ -2,7 +2,7 @@ exports[`A MathML builder \\html@mathml makes clean symbols 1`] = ` - + @@ -31,7 +31,7 @@ exports[`A MathML builder \\html@mathml makes clean symbols 1`] = ` exports[`A MathML builder \\text fonts become mathvariant 1`] = ` - + @@ -115,7 +115,7 @@ exports[`A MathML builder \\text fonts become mathvariant 1`] = ` exports[`A MathML builder accents turn into in MathML 1`] = ` - + @@ -172,7 +172,7 @@ exports[`A MathML builder accents turn into in MathML 1`] exports[`A MathML builder ligatures render properly 1`] = ` - + @@ -218,7 +218,7 @@ exports[`A MathML builder ligatures render properly 1`] = ` exports[`A MathML builder normal spaces render normally 1`] = ` - + @@ -236,7 +236,7 @@ exports[`A MathML builder normal spaces render normally 1`] = ` exports[`A MathML builder should concatenate digits into single 1`] = ` - + @@ -265,7 +265,7 @@ exports[`A MathML builder should concatenate digits into single 1`] = ` exports[`A MathML builder should generate nodes for \\phantom 1`] = ` - + @@ -284,7 +284,7 @@ exports[`A MathML builder should generate nodes for \\phantom 1`] = ` exports[`A MathML builder should generate the right types of nodes 1`] = ` - + @@ -319,7 +319,7 @@ exports[`A MathML builder should generate the right types of nodes 1`] = ` exports[`A MathML builder should make prime operators into nodes 1`] = ` - + @@ -341,7 +341,7 @@ exports[`A MathML builder should make prime operators into nodes 1`] = ` exports[`A MathML builder should output \\limsup_{x \\rightarrow \\infty} correctly in \\textstyle 1`] = ` - + @@ -376,7 +376,7 @@ exports[`A MathML builder should output \\limsup_{x \\rightarrow \\infty} correc exports[`A MathML builder should output \\limsup_{x \\rightarrow \\infty} in displaymode correctly 1`] = ` - + @@ -411,7 +411,7 @@ exports[`A MathML builder should output \\limsup_{x \\rightarrow \\infty} in dis exports[`A MathML builder should render boldsymbol with the correct mathvariants 1`] = ` - + @@ -451,7 +451,7 @@ exports[`A MathML builder should render boldsymbol with the correct mathvariants exports[`A MathML builder should render mathchoice as if there was nothing 1`] = ` - + + @@ -539,7 +539,7 @@ exports[`A MathML builder should render mathchoice as if there was nothing 2`] = exports[`A MathML builder should render mathchoice as if there was nothing 3`] = ` - + @@ -561,7 +561,7 @@ exports[`A MathML builder should render mathchoice as if there was nothing 3`] = exports[`A MathML builder should render mathchoice as if there was nothing 4`] = ` - + @@ -588,7 +588,7 @@ exports[`A MathML builder should render mathchoice as if there was nothing 4`] = exports[`A MathML builder should set href attribute for href appropriately 1`] = ` - + @@ -605,7 +605,7 @@ exports[`A MathML builder should set href attribute for href appropriately 1`] = exports[`A MathML builder should use for colorbox 1`] = ` - + for colorbox 1`] = ` exports[`A MathML builder should use for raisebox 1`] = ` - + @@ -648,7 +648,7 @@ exports[`A MathML builder should use for raisebox 1`] = ` exports[`A MathML builder should use for regular operators 1`] = ` - + for regular operators 1`] = ` exports[`A MathML builder should use for large operators 1`] = ` - + for large operators 1`] = ` exports[`A MathML builder special spaces render specially 1`] = ` - + @@ -777,7 +777,7 @@ exports[`A MathML builder special spaces render specially 1`] = ` exports[`A MathML builder tags use 1`] = ` - +