temml 0.10.22 → 0.10.24

Sign up to get free protection for your applications and to get access to all the features.
package/dist/temml.mjs CHANGED
@@ -144,11 +144,29 @@ const assert = function(value) {
144
144
 
145
145
  /**
146
146
  * Return the protocol of a URL, or "_relative" if the URL does not specify a
147
- * protocol (and thus is relative).
147
+ * protocol (and thus is relative), or `null` if URL has invalid protocol
148
+ * (so should be outright rejected).
148
149
  */
149
150
  const protocolFromUrl = function(url) {
150
- const protocol = /^\s*([^\\/#]*?)(?::|&#0*58|&#x0*3a)/i.exec(url);
151
- return protocol != null ? protocol[1] : "_relative";
151
+ // Check for possible leading protocol.
152
+ // https://url.spec.whatwg.org/#url-parsing strips leading whitespace
153
+ // (\x00) or C0 control (\x00-\x1F) characters.
154
+ // eslint-disable-next-line no-control-regex
155
+ const protocol = /^[\x00-\x20]*([^\\/#?]*?)(:|&#0*58|&#x0*3a|&colon)/i.exec(url);
156
+ if (!protocol) {
157
+ return "_relative";
158
+ }
159
+ // Reject weird colons
160
+ if (protocol[2] !== ":") {
161
+ return null;
162
+ }
163
+ // Reject invalid characters in scheme according to
164
+ // https://datatracker.ietf.org/doc/html/rfc3986#section-3.1
165
+ if (!/^[a-zA-Z][a-zA-Z0-9+\-.]*$/.test(protocol[1])) {
166
+ return null;
167
+ }
168
+ // Lowercase the protocol
169
+ return protocol[1].toLowerCase();
152
170
  };
153
171
 
154
172
  /**
@@ -213,7 +231,11 @@ class Settings {
213
231
  */
214
232
  isTrusted(context) {
215
233
  if (context.url && !context.protocol) {
216
- context.protocol = utils.protocolFromUrl(context.url);
234
+ const protocol = utils.protocolFromUrl(context.url);
235
+ if (protocol == null) {
236
+ return false
237
+ }
238
+ context.protocol = protocol;
217
239
  }
218
240
  const trust = typeof this.trust === "function" ? this.trust(context) : this.trust;
219
241
  return Boolean(trust);
@@ -1024,6 +1046,7 @@ defineSymbol(math, mathord, "\u2609", "\\astrosun", true);
1024
1046
  defineSymbol(math, mathord, "\u263c", "\\sun", true);
1025
1047
  defineSymbol(math, mathord, "\u263e", "\\leftmoon", true);
1026
1048
  defineSymbol(math, mathord, "\u263d", "\\rightmoon", true);
1049
+ defineSymbol(math, mathord, "\u2295", "\\Earth");
1027
1050
 
1028
1051
  // AMS Negated Binary Relations
1029
1052
  defineSymbol(math, rel, "\u226e", "\\nless", true);
@@ -1251,6 +1274,73 @@ defineSymbol(math, bin, "\u27d5", "\\leftouterjoin", true);
1251
1274
  defineSymbol(math, bin, "\u27d6", "\\rightouterjoin", true);
1252
1275
  defineSymbol(math, bin, "\u27d7", "\\fullouterjoin", true);
1253
1276
 
1277
+ // stix Binary Operators
1278
+ defineSymbol(math, bin, "\u2238", "\\dotminus", true);
1279
+ defineSymbol(math, bin, "\u27D1", "\\wedgedot", true);
1280
+ defineSymbol(math, bin, "\u27C7", "\\veedot", true);
1281
+ defineSymbol(math, bin, "\u2A62", "\\doublebarvee", true);
1282
+ defineSymbol(math, bin, "\u2A63", "\\veedoublebar", true);
1283
+ defineSymbol(math, bin, "\u2A5F", "\\wedgebar", true);
1284
+ defineSymbol(math, bin, "\u2A60", "\\wedgedoublebar", true);
1285
+ defineSymbol(math, bin, "\u2A54", "\\Vee", true);
1286
+ defineSymbol(math, bin, "\u2A53", "\\Wedge", true);
1287
+ defineSymbol(math, bin, "\u2A43", "\\barcap", true);
1288
+ defineSymbol(math, bin, "\u2A42", "\\barcup", true);
1289
+ defineSymbol(math, bin, "\u2A48", "\\capbarcup", true);
1290
+ defineSymbol(math, bin, "\u2A40", "\\capdot", true);
1291
+ defineSymbol(math, bin, "\u2A47", "\\capovercup", true);
1292
+ defineSymbol(math, bin, "\u2A46", "\\cupovercap", true);
1293
+ defineSymbol(math, bin, "\u2A4D", "\\closedvarcap", true);
1294
+ defineSymbol(math, bin, "\u2A4C", "\\closedvarcup", true);
1295
+ defineSymbol(math, bin, "\u2A2A", "\\minusdot", true);
1296
+ defineSymbol(math, bin, "\u2A2B", "\\minusfdots", true);
1297
+ defineSymbol(math, bin, "\u2A2C", "\\minusrdots", true);
1298
+ defineSymbol(math, bin, "\u22BB", "\\Xor", true);
1299
+ defineSymbol(math, bin, "\u22BC", "\\Nand", true);
1300
+ defineSymbol(math, bin, "\u22BD", "\\Nor", true);
1301
+ defineSymbol(math, bin, "\u22BD", "\\barvee");
1302
+ defineSymbol(math, bin, "\u2AF4", "\\interleave", true);
1303
+ defineSymbol(math, bin, "\u29E2", "\\shuffle", true);
1304
+ defineSymbol(math, bin, "\u2AF6", "\\threedotcolon", true);
1305
+ defineSymbol(math, bin, "\u2982", "\\typecolon", true);
1306
+ defineSymbol(math, bin, "\u223E", "\\invlazys", true);
1307
+ defineSymbol(math, bin, "\u2A4B", "\\twocaps", true);
1308
+ defineSymbol(math, bin, "\u2A4A", "\\twocups", true);
1309
+ defineSymbol(math, bin, "\u2A4E", "\\Sqcap", true);
1310
+ defineSymbol(math, bin, "\u2A4F", "\\Sqcup", true);
1311
+ defineSymbol(math, bin, "\u2A56", "\\veeonvee", true);
1312
+ defineSymbol(math, bin, "\u2A55", "\\wedgeonwedge", true);
1313
+ defineSymbol(math, bin, "\u29D7", "\\blackhourglass", true);
1314
+ defineSymbol(math, bin, "\u29C6", "\\boxast", true);
1315
+ defineSymbol(math, bin, "\u29C8", "\\boxbox", true);
1316
+ defineSymbol(math, bin, "\u29C7", "\\boxcircle", true);
1317
+ defineSymbol(math, bin, "\u229C", "\\circledequal", true);
1318
+ defineSymbol(math, bin, "\u29B7", "\\circledparallel", true);
1319
+ defineSymbol(math, bin, "\u29B6", "\\circledvert", true);
1320
+ defineSymbol(math, bin, "\u29B5", "\\circlehbar", true);
1321
+ defineSymbol(math, bin, "\u27E1", "\\concavediamond", true);
1322
+ defineSymbol(math, bin, "\u27E2", "\\concavediamondtickleft", true);
1323
+ defineSymbol(math, bin, "\u27E3", "\\concavediamondtickright", true);
1324
+ defineSymbol(math, bin, "\u22C4", "\\diamond", true);
1325
+ defineSymbol(math, bin, "\u29D6", "\\hourglass", true);
1326
+ defineSymbol(math, bin, "\u27E0", "\\lozengeminus", true);
1327
+ defineSymbol(math, bin, "\u233D", "\\obar", true);
1328
+ defineSymbol(math, bin, "\u29B8", "\\obslash", true);
1329
+ defineSymbol(math, bin, "\u2A38", "\\odiv", true);
1330
+ defineSymbol(math, bin, "\u29C1", "\\ogreaterthan", true);
1331
+ defineSymbol(math, bin, "\u29C0", "\\olessthan", true);
1332
+ defineSymbol(math, bin, "\u29B9", "\\operp", true);
1333
+ defineSymbol(math, bin, "\u2A37", "\\Otimes", true);
1334
+ defineSymbol(math, bin, "\u2A36", "\\otimeshat", true);
1335
+ defineSymbol(math, bin, "\u22C6", "\\star", true);
1336
+ defineSymbol(math, bin, "\u25B3", "\\triangle", true);
1337
+ defineSymbol(math, bin, "\u2A3A", "\\triangleminus", true);
1338
+ defineSymbol(math, bin, "\u2A39", "\\triangleplus", true);
1339
+ defineSymbol(math, bin, "\u2A3B", "\\triangletimes", true);
1340
+ defineSymbol(math, bin, "\u27E4", "\\whitesquaretickleft", true);
1341
+ defineSymbol(math, bin, "\u27E5", "\\whitesquaretickright", true);
1342
+ defineSymbol(math, bin, "\u2A33", "\\smashtimes", true);
1343
+
1254
1344
  // AMS Arrows
1255
1345
  // Note: unicode-math maps \u21e2 to their own function \rightdasharrow.
1256
1346
  // We'll map it to AMS function \dashrightarrow. It produces the same atom.
@@ -1491,8 +1581,8 @@ defineSymbol(math, spacing, null, "\\allowbreak");
1491
1581
  defineSymbol(math, punct, ",", ",");
1492
1582
  defineSymbol(text, punct, ":", ":");
1493
1583
  defineSymbol(math, punct, ";", ";");
1494
- defineSymbol(math, bin, "\u22bc", "\\barwedge", true);
1495
- defineSymbol(math, bin, "\u22bb", "\\veebar", true);
1584
+ defineSymbol(math, bin, "\u22bc", "\\barwedge");
1585
+ defineSymbol(math, bin, "\u22bb", "\\veebar");
1496
1586
  defineSymbol(math, bin, "\u2299", "\\odot", true);
1497
1587
  // Firefox turns ⊕ into an emoji. So append \uFE0E. Define Unicode character in macros, not here.
1498
1588
  defineSymbol(math, bin, "\u2295\uFE0E", "\\oplus");
@@ -1505,7 +1595,6 @@ defineSymbol(math, bin, "\u25b3", "\\bigtriangleup");
1505
1595
  defineSymbol(math, bin, "\u25bd", "\\bigtriangledown");
1506
1596
  defineSymbol(math, bin, "\u2020", "\\dagger");
1507
1597
  defineSymbol(math, bin, "\u22c4", "\\diamond");
1508
- defineSymbol(math, bin, "\u22c6", "\\star");
1509
1598
  defineSymbol(math, bin, "\u25c3", "\\triangleleft");
1510
1599
  defineSymbol(math, bin, "\u25b9", "\\triangleright");
1511
1600
  defineSymbol(math, open, "{", "\\{");
@@ -2019,9 +2108,11 @@ const consolidateText = mrow => {
2019
2108
  };
2020
2109
 
2021
2110
  const numberRegEx$1 = /^[0-9]$/;
2022
- const isCommaOrDot = node => {
2023
- return (node.type === "atom" && node.text === ",") ||
2024
- (node.type === "textord" && node.text === ".")
2111
+ const isDotOrComma = (node, followingNode) => {
2112
+ return ((node.type === "textord" && node.text === ".") ||
2113
+ (node.type === "atom" && node.text === ",")) &&
2114
+ // Don't consolidate if there is a space after the comma.
2115
+ node.loc && followingNode.loc && node.loc.end === followingNode.loc.start
2025
2116
  };
2026
2117
  const consolidateNumbers = expression => {
2027
2118
  // Consolidate adjacent numbers. We want to return <mn>1,506.3</mn>,
@@ -2044,7 +2135,8 @@ const consolidateNumbers = expression => {
2044
2135
 
2045
2136
  // Determine if numeral groups are separated by a comma or dot.
2046
2137
  for (let i = nums.length - 1; i > 0; i--) {
2047
- if (nums[i - 1].end === nums[i].start - 2 && isCommaOrDot(expression[nums[i].start - 1])) {
2138
+ if (nums[i - 1].end === nums[i].start - 2 &&
2139
+ isDotOrComma(expression[nums[i].start - 1], expression[nums[i].start])) {
2048
2140
  // Merge the two groups.
2049
2141
  nums[i - 1].end = nums[i].end;
2050
2142
  nums.splice(i, 1);
@@ -3477,6 +3569,9 @@ defineFunction({
3477
3569
 
3478
3570
  if (funcName === "\\edef" || funcName === "\\xdef") {
3479
3571
  tokens = parser.gullet.expandTokens(tokens);
3572
+ if (tokens.length > parser.gullet.settings.maxExpand) {
3573
+ throw new ParseError("Too many expansions in an " + funcName);
3574
+ }
3480
3575
  tokens.reverse(); // to fit in with stack order
3481
3576
  }
3482
3577
  // Final arg is the expansion of the macro
@@ -5110,6 +5205,21 @@ defineFunction({
5110
5205
  }
5111
5206
  });
5112
5207
 
5208
+ const isLongVariableName = (group, font) => {
5209
+ if (font !== "mathrm" || group.body.type !== "ordgroup" || group.body.body.length === 1) {
5210
+ return false
5211
+ }
5212
+ if (group.body.body[0].type !== "mathord") { return false }
5213
+ for (let i = 1; i < group.body.body.length; i++) {
5214
+ const parseNodeType = group.body.body[i].type;
5215
+ if (!(parseNodeType === "mathord" ||
5216
+ (parseNodeType === "textord" && !isNaN(group.body.body[i].text)))) {
5217
+ return false
5218
+ }
5219
+ }
5220
+ return true
5221
+ };
5222
+
5113
5223
  const mathmlBuilder$6 = (group, style) => {
5114
5224
  const font = group.font;
5115
5225
  const newStyle = style.withFont(font);
@@ -5121,6 +5231,20 @@ const mathmlBuilder$6 = (group, style) => {
5121
5231
  return mathGroup
5122
5232
  }
5123
5233
  // Check if it is possible to consolidate elements into a single <mi> element.
5234
+ if (isLongVariableName(group, font)) {
5235
+ // This is a \mathrm{…} group. It gets special treatment because symbolsOrd.js
5236
+ // wraps <mi> elements with <mrow>s to work around a Firefox bug.
5237
+ const mi = mathGroup.children[0].children[0];
5238
+ delete mi.attributes.mathvariant;
5239
+ for (let i = 1; i < mathGroup.children.length; i++) {
5240
+ mi.children[0].text += mathGroup.children[i].type === "mn"
5241
+ ? mathGroup.children[i].children[0].text
5242
+ : mathGroup.children[i].children[0].children[0].text;
5243
+ }
5244
+ // Wrap in a <mrow> to prevent the same Firefox bug.
5245
+ const bogus = new mathMLTree.MathNode("mtext", new mathMLTree.TextNode("\u200b"));
5246
+ return new mathMLTree.MathNode("mrow", [bogus, mi])
5247
+ }
5124
5248
  let canConsolidate = mathGroup.children[0].type === "mo";
5125
5249
  for (let i = 1; i < mathGroup.children.length; i++) {
5126
5250
  if (mathGroup.children[i].type === "mo" && font === "boldsymbol") {
@@ -13186,7 +13310,7 @@ class Style {
13186
13310
  * https://mit-license.org/
13187
13311
  */
13188
13312
 
13189
- const version = "0.10.22";
13313
+ const version = "0.10.24";
13190
13314
 
13191
13315
  function postProcess(block) {
13192
13316
  const labelMap = {};
@@ -14,7 +14,7 @@
14
14
  * https://mit-license.org/
15
15
  */
16
16
 
17
- const version = "0.10.22";
17
+ const version = "0.10.24";
18
18
 
19
19
  function postProcess(block) {
20
20
  const labelMap = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "temml",
3
- "version": "0.10.22",
3
+ "version": "0.10.24",
4
4
  "description": "TeX to MathML conversion in JavaScript.",
5
5
  "main": "dist/temml.js",
6
6
  "engines": {
package/src/Settings.js CHANGED
@@ -42,7 +42,11 @@ export default class Settings {
42
42
  */
43
43
  isTrusted(context) {
44
44
  if (context.url && !context.protocol) {
45
- context.protocol = utils.protocolFromUrl(context.url);
45
+ const protocol = utils.protocolFromUrl(context.url);
46
+ if (protocol == null) {
47
+ return false
48
+ }
49
+ context.protocol = protocol
46
50
  }
47
51
  const trust = typeof this.trust === "function" ? this.trust(context) : this.trust;
48
52
  return Boolean(trust);
@@ -80,9 +80,11 @@ export const consolidateText = mrow => {
80
80
  }
81
81
 
82
82
  const numberRegEx = /^[0-9]$/
83
- const isCommaOrDot = node => {
84
- return (node.type === "atom" && node.text === ",") ||
85
- (node.type === "textord" && node.text === ".")
83
+ const isDotOrComma = (node, followingNode) => {
84
+ return ((node.type === "textord" && node.text === ".") ||
85
+ (node.type === "atom" && node.text === ",")) &&
86
+ // Don't consolidate if there is a space after the comma.
87
+ node.loc && followingNode.loc && node.loc.end === followingNode.loc.start
86
88
  }
87
89
  const consolidateNumbers = expression => {
88
90
  // Consolidate adjacent numbers. We want to return <mn>1,506.3</mn>,
@@ -105,7 +107,8 @@ const consolidateNumbers = expression => {
105
107
 
106
108
  // Determine if numeral groups are separated by a comma or dot.
107
109
  for (let i = nums.length - 1; i > 0; i--) {
108
- if (nums[i - 1].end === nums[i].start - 2 && isCommaOrDot(expression[nums[i].start - 1])) {
110
+ if (nums[i - 1].end === nums[i].start - 2 &&
111
+ isDotOrComma(expression[nums[i].start - 1], expression[nums[i].start])) {
109
112
  // Merge the two groups.
110
113
  nums[i - 1].end = nums[i].end
111
114
  nums.splice(i, 1)
@@ -141,6 +141,9 @@ defineFunction({
141
141
 
142
142
  if (funcName === "\\edef" || funcName === "\\xdef") {
143
143
  tokens = parser.gullet.expandTokens(tokens);
144
+ if (tokens.length > parser.gullet.settings.maxExpand) {
145
+ throw new ParseError("Too many expansions in an " + funcName);
146
+ }
144
147
  tokens.reverse(); // to fit in with stack order
145
148
  }
146
149
  // Final arg is the expansion of the macro
@@ -2,6 +2,21 @@ import defineFunction, { normalizeArgument } from "../defineFunction"
2
2
  import * as mml from "../buildMathML"
3
3
  import mathMLTree from "../mathMLTree"
4
4
 
5
+ const isLongVariableName = (group, font) => {
6
+ if (font !== "mathrm" || group.body.type !== "ordgroup" || group.body.body.length === 1) {
7
+ return false
8
+ }
9
+ if (group.body.body[0].type !== "mathord") { return false }
10
+ for (let i = 1; i < group.body.body.length; i++) {
11
+ const parseNodeType = group.body.body[i].type
12
+ if (!(parseNodeType === "mathord" ||
13
+ (parseNodeType === "textord" && !isNaN(group.body.body[i].text)))) {
14
+ return false
15
+ }
16
+ }
17
+ return true
18
+ }
19
+
5
20
  const mathmlBuilder = (group, style) => {
6
21
  const font = group.font
7
22
  const newStyle = style.withFont(font)
@@ -13,6 +28,20 @@ const mathmlBuilder = (group, style) => {
13
28
  return mathGroup
14
29
  }
15
30
  // Check if it is possible to consolidate elements into a single <mi> element.
31
+ if (isLongVariableName(group, font)) {
32
+ // This is a \mathrm{…} group. It gets special treatment because symbolsOrd.js
33
+ // wraps <mi> elements with <mrow>s to work around a Firefox bug.
34
+ const mi = mathGroup.children[0].children[0];
35
+ delete mi.attributes.mathvariant
36
+ for (let i = 1; i < mathGroup.children.length; i++) {
37
+ mi.children[0].text += mathGroup.children[i].type === "mn"
38
+ ? mathGroup.children[i].children[0].text
39
+ : mathGroup.children[i].children[0].children[0].text
40
+ }
41
+ // Wrap in a <mrow> to prevent the same Firefox bug.
42
+ const bogus = new mathMLTree.MathNode("mtext", new mathMLTree.TextNode("\u200b"))
43
+ return new mathMLTree.MathNode("mrow", [bogus, mi])
44
+ }
16
45
  let canConsolidate = mathGroup.children[0].type === "mo"
17
46
  for (let i = 1; i < mathGroup.children.length; i++) {
18
47
  if (mathGroup.children[i].type === "mo" && font === "boldsymbol") {
@@ -25,7 +54,7 @@ const mathmlBuilder = (group, style) => {
25
54
  }
26
55
  if (!canConsolidate) { return mathGroup }
27
56
  // Consolidate the <mi> elements.
28
- const mi = mathGroup.children[0]
57
+ const mi = mathGroup.children[0];
29
58
  for (let i = 1; i < mathGroup.children.length; i++) {
30
59
  mi.children.push(mathGroup.children[i].children[0])
31
60
  }
@@ -8,7 +8,7 @@
8
8
  * https://mit-license.org/
9
9
  */
10
10
 
11
- export const version = "0.10.22";
11
+ export const version = "0.10.24";
12
12
 
13
13
  export function postProcess(block) {
14
14
  const labelMap = {}
package/src/symbols.js CHANGED
@@ -218,6 +218,7 @@ defineSymbol(math, mathord, "\u2609", "\\astrosun", true);
218
218
  defineSymbol(math, mathord, "\u263c", "\\sun", true);
219
219
  defineSymbol(math, mathord, "\u263e", "\\leftmoon", true);
220
220
  defineSymbol(math, mathord, "\u263d", "\\rightmoon", true);
221
+ defineSymbol(math, mathord, "\u2295", "\\Earth");
221
222
 
222
223
  // AMS Negated Binary Relations
223
224
  defineSymbol(math, rel, "\u226e", "\\nless", true);
@@ -445,6 +446,73 @@ defineSymbol(math, bin, "\u27d5", "\\leftouterjoin", true);
445
446
  defineSymbol(math, bin, "\u27d6", "\\rightouterjoin", true);
446
447
  defineSymbol(math, bin, "\u27d7", "\\fullouterjoin", true);
447
448
 
449
+ // stix Binary Operators
450
+ defineSymbol(math, bin, "\u2238", "\\dotminus", true);
451
+ defineSymbol(math, bin, "\u27D1", "\\wedgedot", true);
452
+ defineSymbol(math, bin, "\u27C7", "\\veedot", true);
453
+ defineSymbol(math, bin, "\u2A62", "\\doublebarvee", true);
454
+ defineSymbol(math, bin, "\u2A63", "\\veedoublebar", true)
455
+ defineSymbol(math, bin, "\u2A5F", "\\wedgebar", true)
456
+ defineSymbol(math, bin, "\u2A60", "\\wedgedoublebar", true)
457
+ defineSymbol(math, bin, "\u2A54", "\\Vee", true)
458
+ defineSymbol(math, bin, "\u2A53", "\\Wedge", true)
459
+ defineSymbol(math, bin, "\u2A43", "\\barcap", true)
460
+ defineSymbol(math, bin, "\u2A42", "\\barcup", true)
461
+ defineSymbol(math, bin, "\u2A48", "\\capbarcup", true)
462
+ defineSymbol(math, bin, "\u2A40", "\\capdot", true)
463
+ defineSymbol(math, bin, "\u2A47", "\\capovercup", true)
464
+ defineSymbol(math, bin, "\u2A46", "\\cupovercap", true)
465
+ defineSymbol(math, bin, "\u2A4D", "\\closedvarcap", true)
466
+ defineSymbol(math, bin, "\u2A4C", "\\closedvarcup", true)
467
+ defineSymbol(math, bin, "\u2A2A", "\\minusdot", true)
468
+ defineSymbol(math, bin, "\u2A2B", "\\minusfdots", true)
469
+ defineSymbol(math, bin, "\u2A2C", "\\minusrdots", true)
470
+ defineSymbol(math, bin, "\u22BB", "\\Xor", true)
471
+ defineSymbol(math, bin, "\u22BC", "\\Nand", true)
472
+ defineSymbol(math, bin, "\u22BD", "\\Nor", true)
473
+ defineSymbol(math, bin, "\u22BD", "\\barvee")
474
+ defineSymbol(math, bin, "\u2AF4", "\\interleave", true)
475
+ defineSymbol(math, bin, "\u29E2", "\\shuffle", true)
476
+ defineSymbol(math, bin, "\u2AF6", "\\threedotcolon", true)
477
+ defineSymbol(math, bin, "\u2982", "\\typecolon", true)
478
+ defineSymbol(math, bin, "\u223E", "\\invlazys", true)
479
+ defineSymbol(math, bin, "\u2A4B", "\\twocaps", true)
480
+ defineSymbol(math, bin, "\u2A4A", "\\twocups", true)
481
+ defineSymbol(math, bin, "\u2A4E", "\\Sqcap", true)
482
+ defineSymbol(math, bin, "\u2A4F", "\\Sqcup", true)
483
+ defineSymbol(math, bin, "\u2A56", "\\veeonvee", true)
484
+ defineSymbol(math, bin, "\u2A55", "\\wedgeonwedge", true)
485
+ defineSymbol(math, bin, "\u29D7", "\\blackhourglass", true)
486
+ defineSymbol(math, bin, "\u29C6", "\\boxast", true)
487
+ defineSymbol(math, bin, "\u29C8", "\\boxbox", true)
488
+ defineSymbol(math, bin, "\u29C7", "\\boxcircle", true)
489
+ defineSymbol(math, bin, "\u229C", "\\circledequal", true)
490
+ defineSymbol(math, bin, "\u29B7", "\\circledparallel", true)
491
+ defineSymbol(math, bin, "\u29B6", "\\circledvert", true)
492
+ defineSymbol(math, bin, "\u29B5", "\\circlehbar", true)
493
+ defineSymbol(math, bin, "\u27E1", "\\concavediamond", true)
494
+ defineSymbol(math, bin, "\u27E2", "\\concavediamondtickleft", true)
495
+ defineSymbol(math, bin, "\u27E3", "\\concavediamondtickright", true)
496
+ defineSymbol(math, bin, "\u22C4", "\\diamond", true)
497
+ defineSymbol(math, bin, "\u29D6", "\\hourglass", true)
498
+ defineSymbol(math, bin, "\u27E0", "\\lozengeminus", true)
499
+ defineSymbol(math, bin, "\u233D", "\\obar", true)
500
+ defineSymbol(math, bin, "\u29B8", "\\obslash", true)
501
+ defineSymbol(math, bin, "\u2A38", "\\odiv", true)
502
+ defineSymbol(math, bin, "\u29C1", "\\ogreaterthan", true)
503
+ defineSymbol(math, bin, "\u29C0", "\\olessthan", true)
504
+ defineSymbol(math, bin, "\u29B9", "\\operp", true)
505
+ defineSymbol(math, bin, "\u2A37", "\\Otimes", true)
506
+ defineSymbol(math, bin, "\u2A36", "\\otimeshat", true)
507
+ defineSymbol(math, bin, "\u22C6", "\\star", true)
508
+ defineSymbol(math, bin, "\u25B3", "\\triangle", true)
509
+ defineSymbol(math, bin, "\u2A3A", "\\triangleminus", true)
510
+ defineSymbol(math, bin, "\u2A39", "\\triangleplus", true)
511
+ defineSymbol(math, bin, "\u2A3B", "\\triangletimes", true)
512
+ defineSymbol(math, bin, "\u27E4", "\\whitesquaretickleft", true)
513
+ defineSymbol(math, bin, "\u27E5", "\\whitesquaretickright", true)
514
+ defineSymbol(math, bin, "\u2A33", "\\smashtimes", true)
515
+
448
516
  // AMS Arrows
449
517
  // Note: unicode-math maps \u21e2 to their own function \rightdasharrow.
450
518
  // We'll map it to AMS function \dashrightarrow. It produces the same atom.
@@ -685,8 +753,8 @@ defineSymbol(math, spacing, null, "\\allowbreak");
685
753
  defineSymbol(math, punct, ",", ",");
686
754
  defineSymbol(text, punct, ":", ":");
687
755
  defineSymbol(math, punct, ";", ";");
688
- defineSymbol(math, bin, "\u22bc", "\\barwedge", true);
689
- defineSymbol(math, bin, "\u22bb", "\\veebar", true);
756
+ defineSymbol(math, bin, "\u22bc", "\\barwedge");
757
+ defineSymbol(math, bin, "\u22bb", "\\veebar");
690
758
  defineSymbol(math, bin, "\u2299", "\\odot", true);
691
759
  // Firefox turns ⊕ into an emoji. So append \uFE0E. Define Unicode character in macros, not here.
692
760
  defineSymbol(math, bin, "\u2295\uFE0E", "\\oplus");
@@ -699,7 +767,6 @@ defineSymbol(math, bin, "\u25b3", "\\bigtriangleup");
699
767
  defineSymbol(math, bin, "\u25bd", "\\bigtriangledown");
700
768
  defineSymbol(math, bin, "\u2020", "\\dagger");
701
769
  defineSymbol(math, bin, "\u22c4", "\\diamond");
702
- defineSymbol(math, bin, "\u22c6", "\\star");
703
770
  defineSymbol(math, bin, "\u25c3", "\\triangleleft");
704
771
  defineSymbol(math, bin, "\u25b9", "\\triangleright");
705
772
  defineSymbol(math, open, "{", "\\{");
package/src/utils.js CHANGED
@@ -81,11 +81,29 @@ export const assert = function(value) {
81
81
 
82
82
  /**
83
83
  * Return the protocol of a URL, or "_relative" if the URL does not specify a
84
- * protocol (and thus is relative).
84
+ * protocol (and thus is relative), or `null` if URL has invalid protocol
85
+ * (so should be outright rejected).
85
86
  */
86
87
  export const protocolFromUrl = function(url) {
87
- const protocol = /^\s*([^\\/#]*?)(?::|&#0*58|&#x0*3a)/i.exec(url);
88
- return protocol != null ? protocol[1] : "_relative";
88
+ // Check for possible leading protocol.
89
+ // https://url.spec.whatwg.org/#url-parsing strips leading whitespace
90
+ // (\x00) or C0 control (\x00-\x1F) characters.
91
+ // eslint-disable-next-line no-control-regex
92
+ const protocol = /^[\x00-\x20]*([^\\/#?]*?)(:|&#0*58|&#x0*3a|&colon)/i.exec(url);
93
+ if (!protocol) {
94
+ return "_relative";
95
+ }
96
+ // Reject weird colons
97
+ if (protocol[2] !== ":") {
98
+ return null;
99
+ }
100
+ // Reject invalid characters in scheme according to
101
+ // https://datatracker.ietf.org/doc/html/rfc3986#section-3.1
102
+ if (!/^[a-zA-Z][a-zA-Z0-9+\-.]*$/.test(protocol[1])) {
103
+ return null;
104
+ }
105
+ // Lowercase the protocol
106
+ return protocol[1].toLowerCase();
89
107
  };
90
108
 
91
109
  /**