temml 0.10.22 → 0.10.24

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/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
  /**