temml 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|