diff --git a/mathjax3-ts/input/tex/unicode/UnicodeConfiguration.ts b/mathjax3-ts/input/tex/unicode/UnicodeConfiguration.ts new file mode 100644 index 000000000..f4f5e8e0a --- /dev/null +++ b/mathjax3-ts/input/tex/unicode/UnicodeConfiguration.ts @@ -0,0 +1,100 @@ +/************************************************************* + * + * Copyright (c) 2018 The MathJax Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +/** + * @fileoverview Configuration file for the unicode package. + * + * @author v.sorge@mathjax.org (Volker Sorge) + */ + +import {Configuration} from '../Configuration.js'; +import {EnvList} from '../StackItem.js'; +import TexParser from '../TexParser.js'; +import TexError from '../TexError.js'; +import {CommandMap} from '../SymbolMap.js'; +import {ParseMethod} from '../Types.js'; +import ParseUtil from '../ParseUtil.js'; +import NodeUtil from '../NodeUtil.js'; +import {numeric} from '../../../util/Entities.js'; + +// Namespace +export let UnicodeMethods: Record = {}; + +let UnicodeCache: {[key: number]: [number, number, string, number]} = {}; + +/** + * Parse function for unicode macro. + * @param {TexParser} parser The current tex parser. + * @param {string} name The name of the macro. + */ +UnicodeMethods.Unicode = function(parser: TexParser, name: string) { + let HD = parser.GetBrackets(name); + let HDsplit = null; + let font = null; + if (HD) { + if (HD.replace(/ /g, ''). + match(/^(\d+(\.\d*)?|\.\d+),(\d+(\.\d*)?|\.\d+)$/)) { + HDsplit = HD.replace(/ /g, '').split(/,/); + font = parser.GetBrackets(name); + } else { + font = HD; + } + } + let n = ParseUtil.trimSpaces(parser.GetArgument(name)).replace(/^0x/, 'x'); + if (!n.match(/^(x[0-9A-Fa-f]+|[0-9]+)$/)) { + throw new TexError('BadUnicode', 'Argument to \\unicode must be a number'); + } + let N = parseInt(n.match(/^x/) ? '0' + n : n); + if (!UnicodeCache[N]) { + UnicodeCache[N] = [800, 200, font, N]; + } else if (!font) { + font = UnicodeCache[N][2]; + } + if (HDsplit) { + UnicodeCache[N][0] = Math.floor(parseFloat(HDsplit[0]) * 1000); + UnicodeCache[N][1] = Math.floor(parseFloat(HDsplit[1]) * 1000); + } + let variant = parser.stack.env.font as string; + let def: EnvList = {}; + if (font) { + UnicodeCache[N][2] = def.fontfamily = font.replace(/'/g, '\''); + if (variant) { + if (variant.match(/bold/)) { + def.fontweight = 'bold'; + } + if (variant.match(/italic|-mathit/)) { + def.fontstyle = 'italic'; + } + } + } else if (variant) { + def.mathvariant = variant; + } + let node = parser.create('token', 'mtext', def, numeric(n)); + NodeUtil.setProperty(node, 'unicode', true); + parser.Push(node); +}; + + +new CommandMap('unicode', {unicode: 'Unicode'}, UnicodeMethods); + + +export const UnicodeConfiguration = Configuration.create( + 'unicode', {handler: {macro: ['unicode']}} +); + + diff --git a/samples/tex2mml.js b/samples/tex2mml.js index f0300f4c8..7858516ac 100644 --- a/samples/tex2mml.js +++ b/samples/tex2mml.js @@ -14,11 +14,12 @@ import '../mathjax3/input/tex/action/ActionConfiguration.js'; import '../mathjax3/input/tex/bbox/BboxConfiguration.js'; import '../mathjax3/input/tex/braket/BraketConfiguration.js'; import '../mathjax3/input/tex/physics/PhysicsConfiguration.js'; +import '../mathjax3/input/tex/unicode/UnicodeConfiguration.js'; RegisterHTMLHandler(chooseAdaptor()); let html = MathJax.document('', { - InputJax: new TeX({packages: ['base', 'ams', 'boldsymbol', 'newcommand', 'extpfeil', 'braket', 'physics', 'action', 'bbox']}) + InputJax: new TeX({packages: ['base', 'ams', 'boldsymbol', 'newcommand', 'extpfeil', 'braket', 'physics', 'unicode', 'action', 'bbox']}) }); import {SerializedMmlVisitor as MmlVisitor} from '../mathjax3/core/MmlTree/SerializedMmlVisitor.js'; diff --git a/tests.sh b/tests.sh index 77b288ddb..abcd80a67 100755 --- a/tests.sh +++ b/tests.sh @@ -107,6 +107,7 @@ if [ $# -eq 0 ]; then # More Packages node load.js tests/parser-bbox-tests.js node load.js tests/parser-action-tests.js + node load.js tests/parser-unicode-tests.js exit 0 else repeat=$1 diff --git a/tests/parser-unicode-tests.js b/tests/parser-unicode-tests.js new file mode 100644 index 000000000..5e0bac590 --- /dev/null +++ b/tests/parser-unicode-tests.js @@ -0,0 +1,438 @@ +import {ParserTest} from './parser-tests.js'; +import 'mathjax3/input/tex/unicode/UnicodeConfiguration.js'; + +class ParserUnicodeTest extends ParserTest { + + constructor() { + super(); + this.packages = ['base', 'unicode']; + } + +} + +let parserTest = new ParserUnicodeTest(); + + +parserTest.runTest( + 'Unicode Dec', '\\unicode{8922}', + {"kind": "math", + "texClass": 0, + "attributes": {"display": "block"}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mrow", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mtext", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {"unicode": true}, + "childNodes": [ + {"kind": "text", + "text": "⋚"}], + "isSpacelike": true}], + "isInferred": true, + "isSpacelike": true}], + "isSpacelike": true} +); + +parserTest.runTest( + 'Unicode Hex', '\\unicode{0x22DA}', + {"kind": "math", + "texClass": 0, + "attributes": {"display": "block"}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mrow", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mtext", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {"unicode": true}, + "childNodes": [ + {"kind": "text", + "text": "⋚"}], + "isSpacelike": true}], + "isInferred": true, + "isSpacelike": true}], + "isSpacelike": true} +); + +parserTest.runTest( + 'Unicode Dec A', '\\unicode{65}', + {"kind": "math", + "texClass": 0, + "attributes": {"display": "block"}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mrow", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mtext", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {"unicode": true}, + "childNodes": [ + {"kind": "text", + "text": "A"}], + "isSpacelike": true}], + "isInferred": true, + "isSpacelike": true}], + "isSpacelike": true} +); + +parserTest.runTest( + 'Unicode Hex A', '\\unicode{x41}', + {"kind": "math", + "texClass": 0, + "attributes": {"display": "block"}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mrow", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mtext", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {"unicode": true}, + "childNodes": [ + {"kind": "text", + "text": "A"}], + "isSpacelike": true}], + "isInferred": true, + "isSpacelike": true}], + "isSpacelike": true} +); + +parserTest.runTest( + 'Unicode Scale', '\\unicode[.55,0.05]{x22D6}', + {"kind": "math", + "texClass": 0, + "attributes": {"display": "block"}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mrow", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mtext", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {"unicode": true}, + "childNodes": [ + {"kind": "text", + "text": "⋖"}], + "isSpacelike": true}], + "isInferred": true, + "isSpacelike": true}], + "isSpacelike": true} +); + +parserTest.runTest( + 'Unicode Scale Font', '\\unicode[.55,0.05][Geramond]{x22D6}', + {"kind": "math", + "texClass": 0, + "attributes": {"display": "block"}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mrow", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mtext", + "texClass": 0, + "attributes": {"fontfamily": "Geramond"}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {"unicode": true}, + "childNodes": [ + {"kind": "text", + "text": "⋖"}], + "isSpacelike": true}], + "isInferred": true, + "isSpacelike": true}], + "isSpacelike": true} +); + +parserTest.runTest( + 'Unicode Font', '\\unicode[Garamond]{x22D6}', + {"kind": "math", + "texClass": 0, + "attributes": {"display": "block"}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mrow", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mtext", + "texClass": 0, + "attributes": {"fontfamily": "Garamond"}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {"unicode": true}, + "childNodes": [ + {"kind": "text", + "text": "⋖"}], + "isSpacelike": true}], + "isInferred": true, + "isSpacelike": true}], + "isSpacelike": true} +); + +parserTest.runTest( + 'Unicode Combined', '\\mbox{A}\\unicode{65}{B}', + {"kind": "math", + "texClass": 0, + "attributes": {"display": "block"}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mrow", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mstyle", + "texClass": 0, + "attributes": {"displaystyle": false, + "scriptlevel": 0}, + "inherited": {}, + "properties": {}, + "childNodes": [ + {"kind": "mrow", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": false, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mtext", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": false, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "text", + "text": "A"}], + "isSpacelike": true}], + "isInferred": true, + "isSpacelike": true}], + "isSpacelike": true}, + {"kind": "mtext", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {"unicode": true}, + "childNodes": [ + {"kind": "text", + "text": "A"}], + "isSpacelike": true}, + {"kind": "TeXAtom", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mrow", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mi", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0, + "mathvariant": "italic"}, + "properties": {}, + "childNodes": [ + {"kind": "text", + "text": "B"}]}], + "isInferred": true}]}], + "isInferred": true}]} +); + +parserTest.runTest( + 'Unicode Surrogate Hex', '\\unicode{x1D5A0}', + {"kind": "math", + "texClass": 0, + "attributes": {"display": "block"}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mrow", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mtext", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {"unicode": true}, + "childNodes": [ + {"kind": "text", + "text": "𝖠"}], + "isSpacelike": true}], + "isInferred": true, + "isSpacelike": true}], + "isSpacelike": true} +); + +parserTest.runTest( + 'Unicode Surrogate Dec', '\\unicode{120224}', + {"kind": "math", + "texClass": 0, + "attributes": {"display": "block"}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mrow", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mtext", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {"unicode": true}, + "childNodes": [ + {"kind": "text", + "text": "𝖠"}], + "isSpacelike": true}], + "isInferred": true, + "isSpacelike": true}], + "isSpacelike": true} +); + +parserTest.runTest( + 'Unicode Blackboard', '\\unicode{x1D538}', + {"kind": "math", + "texClass": 0, + "attributes": {"display": "block"}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mrow", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mtext", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {"unicode": true}, + "childNodes": [ + {"kind": "text", + "text": "𝔸"}], + "isSpacelike": true}], + "isInferred": true, + "isSpacelike": true}], + "isSpacelike": true} +); + +parserTest.runTest( + 'Unicode Blackboard Geramond', '\\unicode{x1D538}', + {"kind": "math", + "texClass": 0, + "attributes": {"display": "block"}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mrow", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {}, + "childNodes": [ + {"kind": "mtext", + "texClass": 0, + "attributes": {}, + "inherited": {"displaystyle": true, + "scriptlevel": 0}, + "properties": {"unicode": true}, + "childNodes": [ + {"kind": "text", + "text": "𝔸"}], + "isSpacelike": true}], + "isInferred": true, + "isSpacelike": true}], + "isSpacelike": true} +); + +