temml 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }