diff --git a/package.json b/package.json index eb84956..6b1e2f1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mathml2latex", - "version": "1.1.3", + "version": "1.1.4", "description": "Convert mathml to latex.", "author": "Mika", "license": "MIT", diff --git a/src/mathml2latex.js b/src/mathml2latex.js index 0068c39..69d5a46 100644 --- a/src/mathml2latex.js +++ b/src/mathml2latex.js @@ -63,38 +63,60 @@ function parseLeaf(node) { return r; } +// References: +// - https://w3c.github.io/mathml-core/#the-mathvariant-attribute +// - https://ftp.tu-chemnitz.de/pub/tex/info/symbols/comprehensive/symbols-a4.pdf#page=123 +function formatMathVariant (node, it) { + const mathVariant = NodeTool.getAttr(node, "mathvariant", "").toLowerCase() + const substitutions = { + "normal": "\\mathrm", + "bold": "\\mathbf", + "italic": "\\mathrm", + "bold-italic": "\\boldsymbol", + "double-struck": "\\mathbb", + "script": "\\mathscr", + "fraktur": "\\mathfrak", + "sans-serif": "\\mathsf" + } + const substituted = substitutions[mathVariant] + const hasSubstitution = !!substituted + + return hasSubstitution ? `${substituted}{${it}}` : it +} + // operator token, mathematical operators function parseOperator(node) { let it = NodeTool.getNodeText(node).trim(); it = MathSymbol.parseOperator(it); - return escapeSpecialChars(it); + return formatMathVariant(node, escapeSpecialChars(it)); } // Math identifier function parseElementMi(node){ let it = NodeTool.getNodeText(node).trim(); it = MathSymbol.parseIdentifier(it); - return escapeSpecialChars(it); + return formatMathVariant(node, escapeSpecialChars(it)); } // Math Number function parseElementMn(node){ let it = NodeTool.getNodeText(node).trim(); - return escapeSpecialChars(it); + return formatMathVariant(node, escapeSpecialChars(it)); } // Math String function parseElementMs(node){ const content = NodeTool.getNodeText(node).trimRight(); const it = escapeSpecialChars(content); - return ['"', it, '"'].join(''); + return ['"', formatMathVariant(node, it), '"'].join(''); } // Math Text + function parseElementMtext(node){ const content = NodeTool.getNodeText(node) const it = escapeSpecialChars(content); - return `\\text{${it}}`; + return `\\text{${formatMathVariant(node, it)}}` } // Math glyph (image) diff --git a/test/test-base.js b/test/test-base.js index 8788574..c5bde2f 100644 --- a/test/test-base.js +++ b/test/test-base.js @@ -79,8 +79,27 @@ const names = [ names.forEach(testOverlapFunName) - test("mo-math-func-name(overlap), multiply names", convert({ from: 'sinsinh', to: '\\sin \\sinh ', })); + +const mathVariantPairs = [ + ["normal", "\\mathrm"], + ["bold", "\\mathbf"], + ["italic", "\\mathnormal"], + ["bold-italic", "\\bm"], + ["double-struck", "\\mathbb"], + ["script", "\\mathscr"], + ["fraktur", "\\mathfrak"], + ["sans-serif", "\\mathsf"], +] + +function testMathVariant([variant, translated]) { + test(`mi-mathvariant: ${variant}`, convert({ + from: `R`, + to: `${translated}{R}` + })); +} + +mathVariantPairs.forEach(testMathVariant)