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.
- package/LICENSE +21 -0
- package/README.md +44 -0
- package/contrib/auto-render/README.md +89 -0
- package/contrib/auto-render/auto-render.js +128 -0
- package/contrib/auto-render/dist/auto-render.js +217 -0
- package/contrib/auto-render/dist/auto-render.min.js +1 -0
- package/contrib/auto-render/splitAtDelimiters.js +84 -0
- package/contrib/auto-render/test/auto-render-spec.js +234 -0
- package/contrib/auto-render/test/auto-render.js +217 -0
- package/contrib/auto-render/test/test_page.html +59 -0
- package/contrib/mhchem/README.md +26 -0
- package/contrib/mhchem/mhchem.js +1705 -0
- package/contrib/mhchem/mhchem.min.js +1 -0
- package/contrib/physics/README.md +20 -0
- package/contrib/physics/physics.js +131 -0
- package/contrib/texvc/README.md +23 -0
- package/contrib/texvc/texvc.js +61 -0
- package/dist/Temml-Asana.css +201 -0
- package/dist/Temml-Latin-Modern.css +216 -0
- package/dist/Temml-Libertinus.css +214 -0
- package/dist/Temml-Local.css +194 -0
- package/dist/Temml-STIX2.css +203 -0
- package/dist/Temml.woff2 +0 -0
- package/dist/temml.cjs +13122 -0
- package/dist/temml.js +11225 -0
- package/dist/temml.min.js +1 -0
- package/dist/temml.mjs +13120 -0
- package/dist/temmlPostProcess.js +70 -0
- package/package.json +34 -0
- package/src/Lexer.js +121 -0
- package/src/MacroExpander.js +437 -0
- package/src/Namespace.js +107 -0
- package/src/ParseError.js +64 -0
- package/src/Parser.js +977 -0
- package/src/Settings.js +49 -0
- package/src/SourceLocation.js +29 -0
- package/src/Style.js +144 -0
- package/src/Token.js +40 -0
- package/src/buildMathML.js +235 -0
- package/src/constants.js +25 -0
- package/src/defineEnvironment.js +25 -0
- package/src/defineFunction.js +69 -0
- package/src/defineMacro.js +11 -0
- package/src/domTree.js +185 -0
- package/src/environments/array.js +791 -0
- package/src/environments/cd.js +252 -0
- package/src/environments.js +8 -0
- package/src/functions/accent.js +127 -0
- package/src/functions/accentunder.js +38 -0
- package/src/functions/arrow.js +204 -0
- package/src/functions/cancelto.js +36 -0
- package/src/functions/char.js +33 -0
- package/src/functions/color.js +253 -0
- package/src/functions/cr.js +46 -0
- package/src/functions/def.js +259 -0
- package/src/functions/delimsizing.js +304 -0
- package/src/functions/enclose.js +193 -0
- package/src/functions/envTag.js +38 -0
- package/src/functions/environment.js +59 -0
- package/src/functions/font.js +123 -0
- package/src/functions/genfrac.js +333 -0
- package/src/functions/hbox.js +29 -0
- package/src/functions/horizBrace.js +32 -0
- package/src/functions/href.js +90 -0
- package/src/functions/html.js +95 -0
- package/src/functions/includegraphics.js +131 -0
- package/src/functions/kern.js +75 -0
- package/src/functions/label.js +29 -0
- package/src/functions/lap.js +75 -0
- package/src/functions/math.js +40 -0
- package/src/functions/mathchoice.js +41 -0
- package/src/functions/mclass.js +201 -0
- package/src/functions/multiscript.js +91 -0
- package/src/functions/not.js +46 -0
- package/src/functions/op.js +338 -0
- package/src/functions/operatorname.js +139 -0
- package/src/functions/ordgroup.js +9 -0
- package/src/functions/phantom.js +73 -0
- package/src/functions/pmb.js +31 -0
- package/src/functions/raise.js +68 -0
- package/src/functions/ref.js +28 -0
- package/src/functions/relax.js +16 -0
- package/src/functions/rule.js +52 -0
- package/src/functions/sizing.js +64 -0
- package/src/functions/smash.js +66 -0
- package/src/functions/sqrt.js +31 -0
- package/src/functions/styling.js +58 -0
- package/src/functions/supsub.js +135 -0
- package/src/functions/symbolsOp.js +53 -0
- package/src/functions/symbolsOrd.js +102 -0
- package/src/functions/symbolsSpacing.js +53 -0
- package/src/functions/tag.js +8 -0
- package/src/functions/text.js +75 -0
- package/src/functions/tip.js +63 -0
- package/src/functions/toggle.js +13 -0
- package/src/functions/verb.js +33 -0
- package/src/functions.js +57 -0
- package/src/linebreaking.js +159 -0
- package/src/macros.js +708 -0
- package/src/mathMLTree.js +175 -0
- package/src/parseNode.js +42 -0
- package/src/parseTree.js +40 -0
- package/src/postProcess.js +57 -0
- package/src/replace.js +225 -0
- package/src/stretchy.js +66 -0
- package/src/svg.js +110 -0
- package/src/symbols.js +972 -0
- package/src/tree.js +50 -0
- package/src/unicodeAccents.js +16 -0
- package/src/unicodeScripts.js +119 -0
- package/src/unicodeSupOrSub.js +108 -0
- package/src/unicodeSymbolBuilder.js +31 -0
- package/src/unicodeSymbols.js +320 -0
- package/src/units.js +109 -0
- package/src/utils.js +109 -0
- package/src/variant.js +103 -0
- package/temml.js +181 -0
@@ -0,0 +1,234 @@
|
|
1
|
+
/* global beforeEach: false */
|
2
|
+
/* global expect: false */
|
3
|
+
/* global it: false */
|
4
|
+
/* global describe: false */
|
5
|
+
|
6
|
+
import splitAtDelimiters from "../splitAtDelimiters";
|
7
|
+
import renderMathInElement from "../auto-render";
|
8
|
+
|
9
|
+
beforeEach(function() {
|
10
|
+
expect.extend({
|
11
|
+
toSplitInto: function(actual, left, right, result) {
|
12
|
+
const message = {
|
13
|
+
pass: true,
|
14
|
+
message: "'" + actual + "' split correctly"
|
15
|
+
};
|
16
|
+
|
17
|
+
const startData = [{ type: "text", data: actual }];
|
18
|
+
|
19
|
+
const split = splitAtDelimiters(startData, left, right, false);
|
20
|
+
|
21
|
+
if (split.length !== result.length) {
|
22
|
+
message.pass = false;
|
23
|
+
message.message =
|
24
|
+
"Different number of splits: " +
|
25
|
+
split.length +
|
26
|
+
" vs. " +
|
27
|
+
result.length +
|
28
|
+
" (" +
|
29
|
+
JSON.stringify(split) +
|
30
|
+
" vs. " +
|
31
|
+
JSON.stringify(result) +
|
32
|
+
")";
|
33
|
+
return message;
|
34
|
+
}
|
35
|
+
|
36
|
+
for (let i = 0; i < split.length; i++) {
|
37
|
+
const real = split[i];
|
38
|
+
const correct = result[i];
|
39
|
+
|
40
|
+
let good = true;
|
41
|
+
let diff;
|
42
|
+
|
43
|
+
if (real.type !== correct.type) {
|
44
|
+
good = false;
|
45
|
+
diff = "type";
|
46
|
+
} else if (real.data !== correct.data) {
|
47
|
+
good = false;
|
48
|
+
diff = "data";
|
49
|
+
} else if (real.display !== correct.display) {
|
50
|
+
good = false;
|
51
|
+
diff = "display";
|
52
|
+
}
|
53
|
+
|
54
|
+
if (!good) {
|
55
|
+
message.pass = false;
|
56
|
+
message.message =
|
57
|
+
"Difference at split " +
|
58
|
+
(i + 1) +
|
59
|
+
": " +
|
60
|
+
JSON.stringify(real) +
|
61
|
+
" vs. " +
|
62
|
+
JSON.stringify(correct) +
|
63
|
+
" (" +
|
64
|
+
diff +
|
65
|
+
" differs)";
|
66
|
+
break;
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
return message;
|
71
|
+
}
|
72
|
+
});
|
73
|
+
});
|
74
|
+
|
75
|
+
describe("A delimiter splitter", function() {
|
76
|
+
it("doesn't split when there are no delimiters", function() {
|
77
|
+
expect("hello").toSplitInto("(", ")", [{ type: "text", data: "hello" }]);
|
78
|
+
});
|
79
|
+
|
80
|
+
it("doesn't create a math node with only one left delimiter", function() {
|
81
|
+
expect("hello ( world").toSplitInto("(", ")", [
|
82
|
+
{ type: "text", data: "hello " },
|
83
|
+
{ type: "text", data: "( world" }
|
84
|
+
]);
|
85
|
+
});
|
86
|
+
|
87
|
+
it("doesn't split when there's only a right delimiter", function() {
|
88
|
+
expect("hello ) world").toSplitInto("(", ")", [{ type: "text", data: "hello ) world" }]);
|
89
|
+
});
|
90
|
+
|
91
|
+
it("splits when there are both delimiters", function() {
|
92
|
+
expect("hello ( world ) boo").toSplitInto("(", ")", [
|
93
|
+
{ type: "text", data: "hello " },
|
94
|
+
{ type: "math", data: " world ", rawData: "( world )", display: false },
|
95
|
+
{ type: "text", data: " boo" }
|
96
|
+
]);
|
97
|
+
});
|
98
|
+
|
99
|
+
it("splits on multi-character delimiters", function() {
|
100
|
+
expect("hello [[ world ]] boo").toSplitInto("[[", "]]", [
|
101
|
+
{ type: "text", data: "hello " },
|
102
|
+
{ type: "math", data: " world ", rawData: "[[ world ]]", display: false },
|
103
|
+
{ type: "text", data: " boo" }
|
104
|
+
]);
|
105
|
+
});
|
106
|
+
|
107
|
+
it("splits mutliple times", function() {
|
108
|
+
expect("hello ( world ) boo ( more ) stuff").toSplitInto("(", ")", [
|
109
|
+
{ type: "text", data: "hello " },
|
110
|
+
{ type: "math", data: " world ", rawData: "( world )", display: false },
|
111
|
+
{ type: "text", data: " boo " },
|
112
|
+
{ type: "math", data: " more ", rawData: "( more )", display: false },
|
113
|
+
{ type: "text", data: " stuff" }
|
114
|
+
]);
|
115
|
+
});
|
116
|
+
|
117
|
+
it("leaves the ending when there's only a left delimiter", function() {
|
118
|
+
expect("hello ( world ) boo ( left").toSplitInto("(", ")", [
|
119
|
+
{ type: "text", data: "hello " },
|
120
|
+
{ type: "math", data: " world ", rawData: "( world )", display: false },
|
121
|
+
{ type: "text", data: " boo " },
|
122
|
+
{ type: "text", data: "( left" }
|
123
|
+
]);
|
124
|
+
});
|
125
|
+
|
126
|
+
it("doesn't split when close delimiters are in {}s", function() {
|
127
|
+
expect("hello ( world { ) } ) boo").toSplitInto("(", ")", [
|
128
|
+
{ type: "text", data: "hello " },
|
129
|
+
{ type: "math", data: " world { ) } ", rawData: "( world { ) } )", display: false },
|
130
|
+
{ type: "text", data: " boo" }
|
131
|
+
]);
|
132
|
+
|
133
|
+
expect("hello ( world { { } ) } ) boo").toSplitInto("(", ")", [
|
134
|
+
{ type: "text", data: "hello " },
|
135
|
+
{ type: "math", data: " world { { } ) } ", rawData: "( world { { } ) } )", display: false },
|
136
|
+
{ type: "text", data: " boo" }
|
137
|
+
]);
|
138
|
+
});
|
139
|
+
|
140
|
+
it("doesn't split at escaped delimiters", function() {
|
141
|
+
expect("hello ( world \\) ) boo").toSplitInto("(", ")", [
|
142
|
+
{ type: "text", data: "hello " },
|
143
|
+
{ type: "math", data: " world \\) ", rawData: "( world \\) )", display: false },
|
144
|
+
{ type: "text", data: " boo" }
|
145
|
+
]);
|
146
|
+
|
147
|
+
/* TODO(emily): make this work maybe?
|
148
|
+
expect("hello \\( ( world ) boo").toSplitInto(
|
149
|
+
"(", ")",
|
150
|
+
[
|
151
|
+
{type: "text", data: "hello \\( "},
|
152
|
+
{type: "math", data: " world ",
|
153
|
+
rawData: "( world )", display: false},
|
154
|
+
{type: "text", data: " boo"},
|
155
|
+
]);
|
156
|
+
*/
|
157
|
+
});
|
158
|
+
|
159
|
+
it("splits when the right and left delimiters are the same", function() {
|
160
|
+
expect("hello $ world $ boo").toSplitInto("$", "$", [
|
161
|
+
{ type: "text", data: "hello " },
|
162
|
+
{ type: "math", data: " world ", rawData: "$ world $", display: false },
|
163
|
+
{ type: "text", data: " boo" }
|
164
|
+
]);
|
165
|
+
});
|
166
|
+
|
167
|
+
it("remembers which delimiters are display-mode", function() {
|
168
|
+
const startData = [{ type: "text", data: "hello ( world ) boo" }];
|
169
|
+
|
170
|
+
expect(splitAtDelimiters(startData, "(", ")", true)).toEqual([
|
171
|
+
{ type: "text", data: "hello " },
|
172
|
+
{ type: "math", data: " world ", rawData: "( world )", display: true },
|
173
|
+
{ type: "text", data: " boo" }
|
174
|
+
]);
|
175
|
+
});
|
176
|
+
|
177
|
+
it("works with more than one start datum", function() {
|
178
|
+
const startData = [
|
179
|
+
{ type: "text", data: "hello ( world ) boo" },
|
180
|
+
{ type: "math", data: "math", rawData: "(math)", display: true },
|
181
|
+
{ type: "text", data: "hello ( world ) boo" }
|
182
|
+
];
|
183
|
+
|
184
|
+
expect(splitAtDelimiters(startData, "(", ")", false)).toEqual([
|
185
|
+
{ type: "text", data: "hello " },
|
186
|
+
{ type: "math", data: " world ", rawData: "( world )", display: false },
|
187
|
+
{ type: "text", data: " boo" },
|
188
|
+
{ type: "math", data: "math", rawData: "(math)", display: true },
|
189
|
+
{ type: "text", data: "hello " },
|
190
|
+
{ type: "math", data: " world ", rawData: "( world )", display: false },
|
191
|
+
{ type: "text", data: " boo" }
|
192
|
+
]);
|
193
|
+
});
|
194
|
+
|
195
|
+
it("doesn't do splitting inside of math nodes", function() {
|
196
|
+
const startData = [
|
197
|
+
{ type: "text", data: "hello ( world ) boo" },
|
198
|
+
{
|
199
|
+
type: "math",
|
200
|
+
data: "hello ( world ) boo",
|
201
|
+
rawData: "(hello ( world ) boo)",
|
202
|
+
display: true
|
203
|
+
}
|
204
|
+
];
|
205
|
+
|
206
|
+
expect(splitAtDelimiters(startData, "(", ")", false)).toEqual([
|
207
|
+
{ type: "text", data: "hello " },
|
208
|
+
{ type: "math", data: " world ", rawData: "( world )", display: false },
|
209
|
+
{ type: "text", data: " boo" },
|
210
|
+
{
|
211
|
+
type: "math",
|
212
|
+
data: "hello ( world ) boo",
|
213
|
+
rawData: "(hello ( world ) boo)",
|
214
|
+
display: true
|
215
|
+
}
|
216
|
+
]);
|
217
|
+
});
|
218
|
+
});
|
219
|
+
|
220
|
+
describe("Pre-process callback", function() {
|
221
|
+
it("replace `-squared` with `^2 `", function() {
|
222
|
+
const el1 = document.createElement("div");
|
223
|
+
el1.textContent = "Circle equation: $x-squared + y-squared = r-squared$.";
|
224
|
+
const el2 = document.createElement("div");
|
225
|
+
el2.textContent = "Circle equation: $x^2 + y^2 = r^2$.";
|
226
|
+
const delimiters = [{ left: "$", right: "$", display: false }];
|
227
|
+
renderMathInElement(el1, {
|
228
|
+
delimiters,
|
229
|
+
preProcess: (math) => math.replace(/-squared/g, "^2")
|
230
|
+
});
|
231
|
+
renderMathInElement(el2, { delimiters });
|
232
|
+
expect(el1.innerHTML).toEqual(el2.innerHTML);
|
233
|
+
});
|
234
|
+
});
|
@@ -0,0 +1,217 @@
|
|
1
|
+
var renderMathInElement = (function (temml) {
|
2
|
+
'use strict';
|
3
|
+
|
4
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
5
|
+
|
6
|
+
var temml__default = /*#__PURE__*/_interopDefaultLegacy(temml);
|
7
|
+
|
8
|
+
/* eslint no-constant-condition:0 */
|
9
|
+
const findEndOfMath = function(delimiter, text, startIndex) {
|
10
|
+
// Adapted from
|
11
|
+
// https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
|
12
|
+
let index = startIndex;
|
13
|
+
let braceLevel = 0;
|
14
|
+
|
15
|
+
const delimLength = delimiter.length;
|
16
|
+
|
17
|
+
while (index < text.length) {
|
18
|
+
const character = text[index];
|
19
|
+
|
20
|
+
if (braceLevel <= 0 && text.slice(index, index + delimLength) === delimiter) {
|
21
|
+
return index;
|
22
|
+
} else if (character === "\\") {
|
23
|
+
index++;
|
24
|
+
} else if (character === "{") {
|
25
|
+
braceLevel++;
|
26
|
+
} else if (character === "}") {
|
27
|
+
braceLevel--;
|
28
|
+
}
|
29
|
+
|
30
|
+
index++;
|
31
|
+
}
|
32
|
+
|
33
|
+
return -1;
|
34
|
+
};
|
35
|
+
|
36
|
+
const escapeRegex = function(string) {
|
37
|
+
return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
38
|
+
};
|
39
|
+
|
40
|
+
const amsRegex = /^\\begin{/;
|
41
|
+
|
42
|
+
const splitAtDelimiters = function(text, delimiters) {
|
43
|
+
let index;
|
44
|
+
const data = [];
|
45
|
+
|
46
|
+
const regexLeft = new RegExp(
|
47
|
+
"(" + delimiters.map((x) => escapeRegex(x.left)).join("|") + ")"
|
48
|
+
);
|
49
|
+
|
50
|
+
while (true) {
|
51
|
+
index = text.search(regexLeft);
|
52
|
+
if (index === -1) {
|
53
|
+
break;
|
54
|
+
}
|
55
|
+
if (index > 0) {
|
56
|
+
data.push({
|
57
|
+
type: "text",
|
58
|
+
data: text.slice(0, index)
|
59
|
+
});
|
60
|
+
text = text.slice(index); // now text starts with delimiter
|
61
|
+
}
|
62
|
+
// ... so this always succeeds:
|
63
|
+
const i = delimiters.findIndex((delim) => text.startsWith(delim.left));
|
64
|
+
index = findEndOfMath(delimiters[i].right, text, delimiters[i].left.length);
|
65
|
+
if (index === -1) {
|
66
|
+
break;
|
67
|
+
}
|
68
|
+
const rawData = text.slice(0, index + delimiters[i].right.length);
|
69
|
+
const math = amsRegex.test(rawData)
|
70
|
+
? rawData
|
71
|
+
: text.slice(delimiters[i].left.length, index);
|
72
|
+
data.push({
|
73
|
+
type: "math",
|
74
|
+
data: math,
|
75
|
+
rawData,
|
76
|
+
display: delimiters[i].display
|
77
|
+
});
|
78
|
+
text = text.slice(index + delimiters[i].right.length);
|
79
|
+
}
|
80
|
+
|
81
|
+
if (text !== "") {
|
82
|
+
data.push({
|
83
|
+
type: "text",
|
84
|
+
data: text
|
85
|
+
});
|
86
|
+
}
|
87
|
+
|
88
|
+
return data;
|
89
|
+
};
|
90
|
+
|
91
|
+
/* eslint no-console:0 */
|
92
|
+
|
93
|
+
/* Note: optionsCopy is mutated by this method. If it is ever exposed in the
|
94
|
+
* API, we should copy it before mutating.
|
95
|
+
*/
|
96
|
+
const renderMathInText = function(text, optionsCopy) {
|
97
|
+
const data = splitAtDelimiters(text, optionsCopy.delimiters);
|
98
|
+
if (data.length === 1 && data[0].type === "text") {
|
99
|
+
// There is no formula in the text.
|
100
|
+
// Let's return null which means there is no need to replace
|
101
|
+
// the current text node with a new one.
|
102
|
+
return null;
|
103
|
+
}
|
104
|
+
|
105
|
+
const fragment = document.createDocumentFragment();
|
106
|
+
|
107
|
+
for (let i = 0; i < data.length; i++) {
|
108
|
+
if (data[i].type === "text") {
|
109
|
+
fragment.appendChild(document.createTextNode(data[i].data));
|
110
|
+
} else {
|
111
|
+
const span = document.createElement("span");
|
112
|
+
let math = data[i].data;
|
113
|
+
// Override any display mode defined in the settings with that
|
114
|
+
// defined by the text itself
|
115
|
+
optionsCopy.displayMode = data[i].display;
|
116
|
+
try {
|
117
|
+
if (optionsCopy.preProcess) {
|
118
|
+
math = optionsCopy.preProcess(math);
|
119
|
+
}
|
120
|
+
temml__default["default"].render(math, span, optionsCopy);
|
121
|
+
} catch (e) {
|
122
|
+
if (!(e instanceof temml__default["default"].ParseError)) {
|
123
|
+
throw e;
|
124
|
+
}
|
125
|
+
optionsCopy.errorCallback(
|
126
|
+
"Temml auto-render: Failed to parse `" + data[i].data + "` with ",
|
127
|
+
e
|
128
|
+
);
|
129
|
+
fragment.appendChild(document.createTextNode(data[i].rawData));
|
130
|
+
continue;
|
131
|
+
}
|
132
|
+
fragment.appendChild(span);
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
return fragment;
|
137
|
+
};
|
138
|
+
|
139
|
+
const renderElem = function(elem, optionsCopy) {
|
140
|
+
for (let i = 0; i < elem.childNodes.length; i++) {
|
141
|
+
const childNode = elem.childNodes[i];
|
142
|
+
if (childNode.nodeType === 3) {
|
143
|
+
// Text node
|
144
|
+
const frag = renderMathInText(childNode.textContent, optionsCopy);
|
145
|
+
if (frag) {
|
146
|
+
i += frag.childNodes.length - 1;
|
147
|
+
elem.replaceChild(frag, childNode);
|
148
|
+
}
|
149
|
+
} else if (childNode.nodeType === 1) {
|
150
|
+
// Element node
|
151
|
+
const className = " " + childNode.className + " ";
|
152
|
+
const shouldRender =
|
153
|
+
optionsCopy.ignoredTags.indexOf(childNode.nodeName.toLowerCase()) === -1 &&
|
154
|
+
optionsCopy.ignoredClasses.every((x) => className.indexOf(" " + x + " ") === -1);
|
155
|
+
|
156
|
+
if (shouldRender) {
|
157
|
+
renderElem(childNode, optionsCopy);
|
158
|
+
}
|
159
|
+
}
|
160
|
+
// Otherwise, it's something else, and ignore it.
|
161
|
+
}
|
162
|
+
};
|
163
|
+
|
164
|
+
const renderMathInElement = function(elem, options) {
|
165
|
+
if (!elem) {
|
166
|
+
throw new Error("No element provided to render");
|
167
|
+
}
|
168
|
+
|
169
|
+
const optionsCopy = {};
|
170
|
+
|
171
|
+
// Object.assign(optionsCopy, option)
|
172
|
+
for (const option in options) {
|
173
|
+
if (Object.prototype.hasOwnProperty.call(options, option)) {
|
174
|
+
optionsCopy[option] = options[option];
|
175
|
+
}
|
176
|
+
}
|
177
|
+
|
178
|
+
// default options
|
179
|
+
optionsCopy.delimiters = optionsCopy.delimiters || [
|
180
|
+
{ left: "$$", right: "$$", display: true },
|
181
|
+
{ left: "\\(", right: "\\)", display: false },
|
182
|
+
// LaTeX uses $…$, but it ruins the display of normal `$` in text:
|
183
|
+
// {left: "$", right: "$", display: false},
|
184
|
+
// $ must come after $$
|
185
|
+
|
186
|
+
// Render AMS environments even if outside $$…$$ delimiters.
|
187
|
+
{ left: "\\begin{equation}", right: "\\end{equation}", display: true },
|
188
|
+
{ left: "\\begin{align}", right: "\\end{align}", display: true },
|
189
|
+
{ left: "\\begin{alignat}", right: "\\end{alignat}", display: true },
|
190
|
+
{ left: "\\begin{gather}", right: "\\end{gather}", display: true },
|
191
|
+
{ left: "\\begin{CD}", right: "\\end{CD}", display: true },
|
192
|
+
|
193
|
+
{ left: "\\[", right: "\\]", display: true }
|
194
|
+
];
|
195
|
+
optionsCopy.ignoredTags = optionsCopy.ignoredTags || [
|
196
|
+
"script",
|
197
|
+
"noscript",
|
198
|
+
"style",
|
199
|
+
"textarea",
|
200
|
+
"pre",
|
201
|
+
"code",
|
202
|
+
"option"
|
203
|
+
];
|
204
|
+
optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || [];
|
205
|
+
optionsCopy.errorCallback = optionsCopy.errorCallback || console.error;
|
206
|
+
|
207
|
+
// Enable sharing of global macros defined via `\gdef` between different
|
208
|
+
// math elements within a single call to `renderMathInElement`.
|
209
|
+
optionsCopy.macros = optionsCopy.macros || {};
|
210
|
+
|
211
|
+
renderElem(elem, optionsCopy);
|
212
|
+
temml__default["default"].postProcess(elem);
|
213
|
+
};
|
214
|
+
|
215
|
+
return renderMathInElement;
|
216
|
+
|
217
|
+
})(temml);
|
@@ -0,0 +1,59 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<!--To run this example from a clone of the repository, run `yarn start`
|
3
|
+
in the root Temml directory and then visit with your web browser:
|
4
|
+
http://localhost:7936/contrib/auto-render/index.html
|
5
|
+
-->
|
6
|
+
<html>
|
7
|
+
<head>
|
8
|
+
<meta charset="UTF-8">
|
9
|
+
<title>Auto-render test</title>
|
10
|
+
<link rel="stylesheet" href="../../../site/temml/temml.css">
|
11
|
+
<script src="../../../site/temml/temml.min.js" type="text/javascript"></script>
|
12
|
+
<script src="./auto-render.js" type="text/javascript"></script>
|
13
|
+
<style type="text/css">
|
14
|
+
body {
|
15
|
+
margin: 0px;
|
16
|
+
padding: 0px;
|
17
|
+
font-size: 36px;
|
18
|
+
}
|
19
|
+
|
20
|
+
#test > .blue {
|
21
|
+
color: blue;
|
22
|
+
}
|
23
|
+
</style>
|
24
|
+
</head>
|
25
|
+
<body>
|
26
|
+
<div id="test">
|
27
|
+
This is some text $math \frac12$ other text
|
28
|
+
<span class="blue">
|
29
|
+
Other node \[ displaymath \frac{1}{2} \] blah $$ \int_2^3 $$
|
30
|
+
</span>
|
31
|
+
and some <!-- comment --> more text \(and math\) blah. And $math with a
|
32
|
+
\$ sign$.
|
33
|
+
<pre>
|
34
|
+
Stuff in a $pre tag$
|
35
|
+
</pre>
|
36
|
+
<p>An AMS environment without <code>$$…$$</code> delimiters.<p>
|
37
|
+
<p>\begin{equation}\begin{split} a &=b+c\\ &=e+f \end{split} \end{equation}</p>
|
38
|
+
<p>$\unsupported$</p>
|
39
|
+
</div>
|
40
|
+
<script>
|
41
|
+
renderMathInElement(
|
42
|
+
document.getElementById("test"),
|
43
|
+
{
|
44
|
+
delimiters: [
|
45
|
+
{ left: "$$", right: "$$", display: true },
|
46
|
+
{ left: "\\(", right: "\\)", display: false },
|
47
|
+
{ left: "\\begin{equation}", right: "\\end{equation}", display: true },
|
48
|
+
{ left: "\\begin{align}", right: "\\end{align}", display: true },
|
49
|
+
{ left: "\\begin{alignat}", right: "\\end{alignat}", display: true },
|
50
|
+
{ left: "\\begin{gather}", right: "\\end{gather}", display: true },
|
51
|
+
{ left: "\\begin{CD}", right: "\\end{CD}", display: true },
|
52
|
+
{ left: "\\begin{multline}", right: "\\end{multline}", display: true },
|
53
|
+
{ left: "\\[", right: "\\]", display: true }
|
54
|
+
]
|
55
|
+
}
|
56
|
+
);
|
57
|
+
</script>
|
58
|
+
</body>
|
59
|
+
</html>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# mhchem extension
|
2
|
+
|
3
|
+
This extension adds to Temml the `\ce` and `\pu` functions from the [mhchem](https://mhchem.github.io/MathJax-mhchem/) package.
|
4
|
+
|
5
|
+
You can download the `mhchem.min.js` file from this repository.
|
6
|
+
|
7
|
+
### Usage
|
8
|
+
|
9
|
+
This extension isn't part of core Temml, so the script should be separately included. Write the following line into the HTML page's `<head>`. Place it _after_ the line that calls `temml.js`.
|
10
|
+
|
11
|
+
```html
|
12
|
+
<script src="./temml.min.js"></script>
|
13
|
+
<script src="./mhchem.min.js"></script>
|
14
|
+
```
|
15
|
+
|
16
|
+
If you are working sever-side, just use `temml.cjs`. It already includes all the functions in `mhchem.js`.
|
17
|
+
|
18
|
+
### Syntax
|
19
|
+
|
20
|
+
See the [mhchem Manual](https://mhchem.github.io/MathJax-mhchem/) for a full explanation of the input syntax, with working examples. The manual also includes a demonstration box.
|
21
|
+
|
22
|
+
Note that old versions of `mhchem.sty` used `\cf` for chemical formula and `\ce` for chemical equations, but `\cf` has been deprecated in place of `\ce`. This extension supports only `\ce`. You can define a macro mapping `\cf` to `\ce` if needed.
|
23
|
+
|
24
|
+
### Browser Support
|
25
|
+
|
26
|
+
This extension has been tested on Chrome, Firefox, Opera, and Edge.
|