temml 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +44 -0
  3. package/contrib/auto-render/README.md +89 -0
  4. package/contrib/auto-render/auto-render.js +128 -0
  5. package/contrib/auto-render/dist/auto-render.js +217 -0
  6. package/contrib/auto-render/dist/auto-render.min.js +1 -0
  7. package/contrib/auto-render/splitAtDelimiters.js +84 -0
  8. package/contrib/auto-render/test/auto-render-spec.js +234 -0
  9. package/contrib/auto-render/test/auto-render.js +217 -0
  10. package/contrib/auto-render/test/test_page.html +59 -0
  11. package/contrib/mhchem/README.md +26 -0
  12. package/contrib/mhchem/mhchem.js +1705 -0
  13. package/contrib/mhchem/mhchem.min.js +1 -0
  14. package/contrib/physics/README.md +20 -0
  15. package/contrib/physics/physics.js +131 -0
  16. package/contrib/texvc/README.md +23 -0
  17. package/contrib/texvc/texvc.js +61 -0
  18. package/dist/Temml-Asana.css +201 -0
  19. package/dist/Temml-Latin-Modern.css +216 -0
  20. package/dist/Temml-Libertinus.css +214 -0
  21. package/dist/Temml-Local.css +194 -0
  22. package/dist/Temml-STIX2.css +203 -0
  23. package/dist/Temml.woff2 +0 -0
  24. package/dist/temml.cjs +13122 -0
  25. package/dist/temml.js +11225 -0
  26. package/dist/temml.min.js +1 -0
  27. package/dist/temml.mjs +13120 -0
  28. package/dist/temmlPostProcess.js +70 -0
  29. package/package.json +34 -0
  30. package/src/Lexer.js +121 -0
  31. package/src/MacroExpander.js +437 -0
  32. package/src/Namespace.js +107 -0
  33. package/src/ParseError.js +64 -0
  34. package/src/Parser.js +977 -0
  35. package/src/Settings.js +49 -0
  36. package/src/SourceLocation.js +29 -0
  37. package/src/Style.js +144 -0
  38. package/src/Token.js +40 -0
  39. package/src/buildMathML.js +235 -0
  40. package/src/constants.js +25 -0
  41. package/src/defineEnvironment.js +25 -0
  42. package/src/defineFunction.js +69 -0
  43. package/src/defineMacro.js +11 -0
  44. package/src/domTree.js +185 -0
  45. package/src/environments/array.js +791 -0
  46. package/src/environments/cd.js +252 -0
  47. package/src/environments.js +8 -0
  48. package/src/functions/accent.js +127 -0
  49. package/src/functions/accentunder.js +38 -0
  50. package/src/functions/arrow.js +204 -0
  51. package/src/functions/cancelto.js +36 -0
  52. package/src/functions/char.js +33 -0
  53. package/src/functions/color.js +253 -0
  54. package/src/functions/cr.js +46 -0
  55. package/src/functions/def.js +259 -0
  56. package/src/functions/delimsizing.js +304 -0
  57. package/src/functions/enclose.js +193 -0
  58. package/src/functions/envTag.js +38 -0
  59. package/src/functions/environment.js +59 -0
  60. package/src/functions/font.js +123 -0
  61. package/src/functions/genfrac.js +333 -0
  62. package/src/functions/hbox.js +29 -0
  63. package/src/functions/horizBrace.js +32 -0
  64. package/src/functions/href.js +90 -0
  65. package/src/functions/html.js +95 -0
  66. package/src/functions/includegraphics.js +131 -0
  67. package/src/functions/kern.js +75 -0
  68. package/src/functions/label.js +29 -0
  69. package/src/functions/lap.js +75 -0
  70. package/src/functions/math.js +40 -0
  71. package/src/functions/mathchoice.js +41 -0
  72. package/src/functions/mclass.js +201 -0
  73. package/src/functions/multiscript.js +91 -0
  74. package/src/functions/not.js +46 -0
  75. package/src/functions/op.js +338 -0
  76. package/src/functions/operatorname.js +139 -0
  77. package/src/functions/ordgroup.js +9 -0
  78. package/src/functions/phantom.js +73 -0
  79. package/src/functions/pmb.js +31 -0
  80. package/src/functions/raise.js +68 -0
  81. package/src/functions/ref.js +28 -0
  82. package/src/functions/relax.js +16 -0
  83. package/src/functions/rule.js +52 -0
  84. package/src/functions/sizing.js +64 -0
  85. package/src/functions/smash.js +66 -0
  86. package/src/functions/sqrt.js +31 -0
  87. package/src/functions/styling.js +58 -0
  88. package/src/functions/supsub.js +135 -0
  89. package/src/functions/symbolsOp.js +53 -0
  90. package/src/functions/symbolsOrd.js +102 -0
  91. package/src/functions/symbolsSpacing.js +53 -0
  92. package/src/functions/tag.js +8 -0
  93. package/src/functions/text.js +75 -0
  94. package/src/functions/tip.js +63 -0
  95. package/src/functions/toggle.js +13 -0
  96. package/src/functions/verb.js +33 -0
  97. package/src/functions.js +57 -0
  98. package/src/linebreaking.js +159 -0
  99. package/src/macros.js +708 -0
  100. package/src/mathMLTree.js +175 -0
  101. package/src/parseNode.js +42 -0
  102. package/src/parseTree.js +40 -0
  103. package/src/postProcess.js +57 -0
  104. package/src/replace.js +225 -0
  105. package/src/stretchy.js +66 -0
  106. package/src/svg.js +110 -0
  107. package/src/symbols.js +972 -0
  108. package/src/tree.js +50 -0
  109. package/src/unicodeAccents.js +16 -0
  110. package/src/unicodeScripts.js +119 -0
  111. package/src/unicodeSupOrSub.js +108 -0
  112. package/src/unicodeSymbolBuilder.js +31 -0
  113. package/src/unicodeSymbols.js +320 -0
  114. package/src/units.js +109 -0
  115. package/src/utils.js +109 -0
  116. package/src/variant.js +103 -0
  117. package/temml.js +181 -0
@@ -0,0 +1,75 @@
1
+ import defineFunction, { ordargument } from "../defineFunction";
2
+ import * as mml from "../buildMathML";
3
+
4
+ // Non-mathy text, possibly in a font
5
+ const textFontFamilies = {
6
+ "\\text": undefined,
7
+ "\\textrm": "textrm",
8
+ "\\textsf": "textsf",
9
+ "\\texttt": "texttt",
10
+ "\\textnormal": "textrm",
11
+ "\\textsc": "textsc" // small caps
12
+ };
13
+
14
+ const textFontWeights = {
15
+ "\\textbf": "textbf",
16
+ "\\textmd": "textmd"
17
+ };
18
+
19
+ const textFontShapes = {
20
+ "\\textit": "textit",
21
+ "\\textup": "textup"
22
+ };
23
+
24
+ const styleWithFont = (group, style) => {
25
+ const font = group.font;
26
+ // Checks if the argument is a font family or a font style.
27
+ if (!font) {
28
+ return style;
29
+ } else if (textFontFamilies[font]) {
30
+ return style.withTextFontFamily(textFontFamilies[font]);
31
+ } else if (textFontWeights[font]) {
32
+ return style.withTextFontWeight(textFontWeights[font]);
33
+ } else {
34
+ return style.withTextFontShape(textFontShapes[font]);
35
+ }
36
+ };
37
+
38
+ defineFunction({
39
+ type: "text",
40
+ names: [
41
+ // Font families
42
+ "\\text",
43
+ "\\textrm",
44
+ "\\textsf",
45
+ "\\texttt",
46
+ "\\textnormal",
47
+ "\\textsc",
48
+ // Font weights
49
+ "\\textbf",
50
+ "\\textmd",
51
+ // Font Shapes
52
+ "\\textit",
53
+ "\\textup"
54
+ ],
55
+ props: {
56
+ numArgs: 1,
57
+ argTypes: ["text"],
58
+ allowedInArgument: true,
59
+ allowedInText: true
60
+ },
61
+ handler({ parser, funcName }, args) {
62
+ const body = args[0];
63
+ return {
64
+ type: "text",
65
+ mode: parser.mode,
66
+ body: ordargument(body),
67
+ font: funcName
68
+ };
69
+ },
70
+ mathmlBuilder(group, style) {
71
+ const newStyle = styleWithFont(group, style)
72
+ const mrow = mml.buildExpressionRow(group.body, newStyle)
73
+ return mml.consolidateText(mrow)
74
+ }
75
+ });
@@ -0,0 +1,63 @@
1
+ import defineFunction from "../defineFunction";
2
+ import mathMLTree from "../mathMLTree";
3
+ import * as mml from "../buildMathML";
4
+
5
+ // Two functions included to enable migration from Mathjax.
6
+
7
+ defineFunction({
8
+ type: "tip",
9
+ names: ["\\mathtip"],
10
+ props: {
11
+ numArgs: 2
12
+ },
13
+ handler({ parser }, args) {
14
+ return {
15
+ type: "tip",
16
+ mode: parser.mode,
17
+ body: args[0],
18
+ tip: args[1]
19
+ };
20
+ },
21
+ mathmlBuilder: (group, style) => {
22
+ const math = mml.buildGroup(group.body, style)
23
+ const tip = mml.buildGroup(group.tip, style)
24
+ // Browsers don't support the tooltip actiontype.
25
+ // TODO: Come back and fix \mathtip when it can be done via CSS w/o a JS event.
26
+ const node = new mathMLTree.MathNode("maction", [math, tip], ["tml-tip"])
27
+ node.setAttribute("actiontype", "tooltip")
28
+ return node
29
+ }
30
+ })
31
+
32
+ defineFunction({
33
+ type: "tip",
34
+ names: ["\\texttip"],
35
+ props: {
36
+ numArgs: 2,
37
+ argTypes: ["math", "text"]
38
+ },
39
+ handler({ parser }, args) {
40
+ return {
41
+ type: "tip",
42
+ mode: parser.mode,
43
+ body: args[0],
44
+ tip: args[1]
45
+ };
46
+ },
47
+ mathmlBuilder: (group, style) => {
48
+ const math = mml.buildGroup(group.body, style)
49
+ const tip = mml.buildGroup(group.tip, style)
50
+ // args[1] only accepted text, so tip is a <mtext> element or a <mrow> of them.
51
+ let str = ""
52
+ if (tip.type === "mtext") {
53
+ str = tip.children[0].text
54
+ } else {
55
+ for (const child of tip.children) {
56
+ str += child.children[0].text
57
+ }
58
+ }
59
+ // Implement \texttip via a title attribute.
60
+ math.setAttribute("title", str)
61
+ return math
62
+ }
63
+ })
@@ -0,0 +1,13 @@
1
+ import { defineFunctionBuilders } from "../defineFunction";
2
+ import mathMLTree from "../mathMLTree";
3
+ import * as mml from "../buildMathML";
4
+
5
+ defineFunctionBuilders({
6
+ type: "toggle",
7
+ mathmlBuilder(group, style) {
8
+ const expression = mml.buildExpression(group.body, style)
9
+ const node = new mathMLTree.MathNode("maction", expression, [], { cursor: "default" })
10
+ node.setAttribute("actiontype", "toggle")
11
+ return node
12
+ }
13
+ })
@@ -0,0 +1,33 @@
1
+ import defineFunction from "../defineFunction";
2
+ import mathMLTree from "../mathMLTree";
3
+ import ParseError from "../ParseError";
4
+
5
+ defineFunction({
6
+ type: "verb",
7
+ names: ["\\verb"],
8
+ props: {
9
+ numArgs: 0,
10
+ allowedInText: true
11
+ },
12
+ handler(context, args, optArgs) {
13
+ // \verb and \verb* are dealt with directly in Parser.js.
14
+ // If we end up here, it's because of a failure to match the two delimiters
15
+ // in the regex in Lexer.js. LaTeX raises the following error when \verb is
16
+ // terminated by end of line (or file).
17
+ throw new ParseError("\\verb ended by end of line instead of matching delimiter");
18
+ },
19
+ mathmlBuilder(group, style) {
20
+ const text = new mathMLTree.TextNode(makeVerb(group));
21
+ const node = new mathMLTree.MathNode("mtext", [text]);
22
+ node.setAttribute("mathvariant", "monospace");
23
+ return node;
24
+ }
25
+ });
26
+
27
+ /**
28
+ * Converts verb group into body string.
29
+ *
30
+ * \verb* replaces each space with an open box \u2423
31
+ * \verb replaces each space with a no-break space \xA0
32
+ */
33
+ const makeVerb = (group) => group.body.replace(/ /g, group.star ? "\u2423" : "\xA0");
@@ -0,0 +1,57 @@
1
+ /** Include this to ensure that all functions are defined. */
2
+ import { _functions } from "./defineFunction";
3
+
4
+ const functions = _functions;
5
+ export default functions;
6
+
7
+ // TODO(kevinb): have functions return an object and call defineFunction with
8
+ // that object in this file instead of relying on side-effects.
9
+ import "./functions/accent";
10
+ import "./functions/accentunder";
11
+ import "./functions/arrow";
12
+ //import "./functions/cancelto";
13
+ import "./environments/cd";
14
+ import "./functions/char";
15
+ import "./functions/color";
16
+ import "./functions/cr";
17
+ import "./functions/def";
18
+ import "./functions/delimsizing";
19
+ import "./functions/enclose";
20
+ import "./functions/environment";
21
+ import "./functions/envTag";
22
+ import "./functions/font";
23
+ import "./functions/genfrac";
24
+ import "./functions/horizBrace";
25
+ import "./functions/href";
26
+ import "./functions/html";
27
+ import "./functions/includegraphics";
28
+ import "./functions/kern";
29
+ import "./functions/label";
30
+ import "./functions/lap";
31
+ import "./functions/math";
32
+ import "./functions/mathchoice";
33
+ import "./functions/mclass";
34
+ import "./functions/multiscript";
35
+ import "./functions/not";
36
+ import "./functions/op";
37
+ import "./functions/operatorname";
38
+ import "./functions/ordgroup";
39
+ import "./functions/phantom";
40
+ import "./functions/pmb";
41
+ import "./functions/raise";
42
+ import "./functions/ref";
43
+ import "./functions/relax";
44
+ import "./functions/rule";
45
+ import "./functions/sizing";
46
+ import "./functions/smash";
47
+ import "./functions/sqrt";
48
+ import "./functions/styling";
49
+ import "./functions/supsub";
50
+ import "./functions/symbolsOp";
51
+ import "./functions/symbolsOrd";
52
+ import "./functions/symbolsSpacing";
53
+ import "./functions/tag";
54
+ import "./functions/text";
55
+ // import "./functions/tip";
56
+ // import "./functions/toggle";
57
+ import "./functions/verb";
@@ -0,0 +1,159 @@
1
+ import mathMLTree from "./mathMLTree"
2
+
3
+ /*
4
+ * Neither Firefox nor Chrome support hard line breaks or soft line breaks.
5
+ * (Despite https://www.w3.org/Math/draft-spec/mathml.html#chapter3_presm.lbattrs)
6
+ * So Temml has work-arounds for both hard and soft breaks.
7
+ * The work-arounds sadly do not work simultaneously. Any top-level hard
8
+ * break makes soft line breaks impossible.
9
+ *
10
+ * Hard breaks are simulated by creating a <mtable> and putting each line in its own <mtr>.
11
+ *
12
+ * To create soft line breaks, Temml avoids using the <semantics> and <annotation> tags.
13
+ * Then the top level of a <math> element can be occupied by <mrow> elements, and the browser
14
+ * will break after a <mrow> if the expression extends beyond the container limit.
15
+ *
16
+ * We want the expression to render with soft line breaks after each top-level binary or
17
+ * relational operator, per TeXbook p. 173. So we gather the expression into <mrow>s so that
18
+ * each <mrow> ends in a binary or relational operator.
19
+ *
20
+ * Soft line breaks will not work in Chromium and Safari, only Firefox.
21
+ *
22
+ * Hopefully browsers will someday do their own linebreaking and we will be able to delete
23
+ * much of this module.
24
+ */
25
+
26
+ export default function setLineBreaks(expression, wrapMode, isDisplayMode, color) {
27
+ if (color === undefined && wrapMode !== "none") {
28
+ // First, make one pass through the expression and split any color nodes.
29
+ const upperLimit = expression.length - 1
30
+ for (let i = upperLimit; i >= 0; i--) {
31
+ const node = expression[i];
32
+ if (node.type === "mstyle" && node.attributes.mathcolor) {
33
+ const color = node.attributes.mathcolor
34
+ const fragment = setLineBreaks(node.children, wrapMode, isDisplayMode, color)
35
+ if (!(fragment.type && fragment.type !== "mtable")) {
36
+ expression.splice(i, 1, ...fragment.children)
37
+ }
38
+ }
39
+ }
40
+ }
41
+
42
+ const tagName = color ? "mstyle" : "mrow"
43
+
44
+ const mtrs = [];
45
+ let mrows = [];
46
+ let block = [];
47
+ let numTopLevelEquals = 0
48
+ let canBeBIN = false // The first node cannot be an infix binary operator.
49
+ for (let i = 0; i < expression.length; i++) {
50
+ const node = expression[i];
51
+ if (node.type && node.type === "mstyle" && node.attributes.mathcolor) {
52
+ if (block.length > 0) {
53
+ // Start a new block. (Insert a soft linebreak.)
54
+ mrows.push(new mathMLTree.MathNode(tagName, block))
55
+ }
56
+ // Insert the mstyle
57
+ mrows.push(node)
58
+ block = [];
59
+ continue
60
+ }
61
+ if (node.attributes && node.attributes.linebreak &&
62
+ node.attributes.linebreak === "newline") {
63
+ // A hard line break. Create a <mtr> for the current block.
64
+ if (block.length > 0) {
65
+ const element = new mathMLTree.MathNode(tagName, block)
66
+ if (color) { element.setAttribute("mathcolor", color) }
67
+ mrows.push(new mathMLTree.MathNode(tagName, block))
68
+ }
69
+ mrows.push(node)
70
+ block = [];
71
+ const mtd = new mathMLTree.MathNode("mtd", mrows)
72
+ mtrs.push(new mathMLTree.MathNode("mtr", [mtd]))
73
+ mrows = [];
74
+ continue
75
+ }
76
+ block.push(node);
77
+ if (node.type && node.type === "mo" && wrapMode === "=") {
78
+ if (node.children.length === 1 && node.children[0].text === "=") {
79
+ numTopLevelEquals += 1
80
+ if (numTopLevelEquals > 1) {
81
+ block.pop()
82
+ // Start a new block. (Insert a soft linebreak.)
83
+ const element = new mathMLTree.MathNode(tagName, block)
84
+ if (color) { element.setAttribute("mathcolor", color) }
85
+ mrows.push(element)
86
+ block = [node];
87
+ }
88
+ }
89
+ } else if (node.type && node.type === "mo" && wrapMode === "tex") {
90
+ // This may be a place for a soft line break.
91
+ if (canBeBIN && !node.attributes.form) {
92
+ // Check if the following node is a \nobreak text node, e.g. "~""
93
+ const next = i < expression.length - 1 ? expression[i + 1] : null;
94
+ let glueIsFreeOfNobreak = true;
95
+ if (
96
+ !(
97
+ next &&
98
+ next.type === "mtext" &&
99
+ next.attributes.linebreak &&
100
+ next.attributes.linebreak === "nobreak"
101
+ )
102
+ ) {
103
+ // We may need to start a new block.
104
+ // First, put any post-operator glue on same line as operator.
105
+ for (let j = i + 1; j < expression.length; j++) {
106
+ const nd = expression[j];
107
+ if (
108
+ nd.type &&
109
+ nd.type === "mspace" &&
110
+ !(nd.attributes.linebreak && nd.attributes.linebreak === "newline")
111
+ ) {
112
+ block.push(nd);
113
+ i += 1;
114
+ if (
115
+ nd.attributes &&
116
+ nd.attributes.linebreak &&
117
+ nd.attributes.linebreak === "nobreak"
118
+ ) {
119
+ glueIsFreeOfNobreak = false;
120
+ }
121
+ } else {
122
+ break;
123
+ }
124
+ }
125
+ }
126
+ if (glueIsFreeOfNobreak) {
127
+ // Start a new block. (Insert a soft linebreak.)
128
+ const element = new mathMLTree.MathNode(tagName, block)
129
+ if (color) { element.setAttribute("mathcolor", color) }
130
+ mrows.push(element)
131
+ block = [];
132
+ }
133
+ canBeBIN = false;
134
+ }
135
+ const isOpenDelimiter = node.attributes.form && node.attributes.form === "prefix";
136
+ // Any operator that follows an open delimiter is unary.
137
+ canBeBIN = !(node.attributes.separator || isOpenDelimiter);
138
+ } else {
139
+ canBeBIN = true;
140
+ }
141
+ }
142
+ if (block.length > 0) {
143
+ const element = new mathMLTree.MathNode(tagName, block)
144
+ if (color) { element.setAttribute("mathcolor", color) }
145
+ mrows.push(element)
146
+ }
147
+ if (mtrs.length > 0) {
148
+ const mtd = new mathMLTree.MathNode("mtd", mrows)
149
+ const mtr = new mathMLTree.MathNode("mtr", [mtd])
150
+ mtrs.push(mtr)
151
+ const mtable = new mathMLTree.MathNode("mtable", mtrs)
152
+ if (!isDisplayMode) {
153
+ mtable.setAttribute("columnalign", "left")
154
+ mtable.setAttribute("rowspacing", "0em")
155
+ }
156
+ return mtable
157
+ }
158
+ return mathMLTree.newDocumentFragment(mrows);
159
+ }