temml 0.10.0 → 0.10.2
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/contrib/auto-render/test/auto-render-spec.js +1 -1
- package/contrib/mhchem/mhchem.js +2 -2
- package/dist/temml.cjs +60 -44
- package/dist/temml.js +58 -42
- package/dist/temml.min.js +1 -1
- package/dist/temml.mjs +60 -44
- package/dist/temmlPostProcess.js +1 -1
- package/package.json +2 -1
- package/src/MacroExpander.js +20 -21
- package/src/Parser.js +8 -3
- package/src/buildMathML.js +1 -1
- package/src/functions/delimsizing.js +5 -0
- package/src/functions/op.js +1 -5
- package/src/functions/operatorname.js +10 -8
- package/src/functions/supsub.js +7 -0
- package/src/mathMLTree.js +1 -1
- package/src/postProcess.js +1 -1
- package/src/symbols.js +5 -2
package/dist/temml.mjs
CHANGED
@@ -666,7 +666,7 @@ class TextNode {
|
|
666
666
|
|
667
667
|
/**
|
668
668
|
* Converts the text node into a string
|
669
|
-
* (representing the text
|
669
|
+
* (representing the text itself).
|
670
670
|
*/
|
671
671
|
toText() {
|
672
672
|
return this.text;
|
@@ -843,7 +843,6 @@ defineSymbol(math, rel, "\u226a", "\\ll", true);
|
|
843
843
|
defineSymbol(math, rel, "\u226b", "\\gg", true);
|
844
844
|
defineSymbol(math, rel, "\u224d", "\\asymp", true);
|
845
845
|
defineSymbol(math, rel, "\u2225", "\\parallel");
|
846
|
-
defineSymbol(math, rel, "\u22c8", "\\bowtie", true);
|
847
846
|
defineSymbol(math, rel, "\u2323", "\\smile", true);
|
848
847
|
defineSymbol(math, rel, "\u2291", "\\sqsubseteq", true);
|
849
848
|
defineSymbol(math, rel, "\u2292", "\\sqsupseteq", true);
|
@@ -1160,7 +1159,6 @@ defineSymbol(math, rel, "\u22d9", "\\gggtr");
|
|
1160
1159
|
defineSymbol(math, bin, "\u22b2", "\\lhd");
|
1161
1160
|
defineSymbol(math, bin, "\u22b3", "\\rhd");
|
1162
1161
|
defineSymbol(math, rel, "\u2242", "\\eqsim", true);
|
1163
|
-
defineSymbol(math, rel, "\u22c8", "\\Join");
|
1164
1162
|
defineSymbol(math, rel, "\u2251", "\\Doteq", true);
|
1165
1163
|
defineSymbol(math, rel, "\u297d", "\\strictif", true);
|
1166
1164
|
defineSymbol(math, rel, "\u297c", "\\strictfi", true);
|
@@ -1186,6 +1184,11 @@ defineSymbol(math, bin, "\u22ba", "\\intercal", true);
|
|
1186
1184
|
defineSymbol(math, bin, "\u22d2", "\\doublecap");
|
1187
1185
|
defineSymbol(math, bin, "\u22d3", "\\doublecup");
|
1188
1186
|
defineSymbol(math, bin, "\u22a0", "\\boxtimes", true);
|
1187
|
+
defineSymbol(math, bin, "\u22c8", "\\bowtie", true);
|
1188
|
+
defineSymbol(math, bin, "\u22c8", "\\Join");
|
1189
|
+
defineSymbol(math, bin, "\u27d5", "\\leftouterjoin", true);
|
1190
|
+
defineSymbol(math, bin, "\u27d6", "\\rightouterjoin", true);
|
1191
|
+
defineSymbol(math, bin, "\u27d7", "\\fullouterjoin", true);
|
1189
1192
|
|
1190
1193
|
// AMS Arrows
|
1191
1194
|
// Note: unicode-math maps \u21e2 to their own function \rightdasharrow.
|
@@ -1890,7 +1893,7 @@ function setLineBreaks(expression, wrapMode, isDisplayMode, color) {
|
|
1890
1893
|
}
|
1891
1894
|
|
1892
1895
|
/**
|
1893
|
-
* This file converts a parse tree into a
|
1896
|
+
* This file converts a parse tree into a corresponding MathML tree. The main
|
1894
1897
|
* entry point is the `buildMathML` function, which takes a parse tree from the
|
1895
1898
|
* parser.
|
1896
1899
|
*/
|
@@ -3521,6 +3524,11 @@ const delimiters = [
|
|
3521
3524
|
"."
|
3522
3525
|
];
|
3523
3526
|
|
3527
|
+
// Export isDelimiter for benefit of parser.
|
3528
|
+
const dels = ["}", "\\left", "\\middle", "\\right"];
|
3529
|
+
const isDelimiter = str => str.length > 0 &&
|
3530
|
+
(delimiters.includes(str) || delimiterSizes[str] || dels.includes(str));
|
3531
|
+
|
3524
3532
|
// Metrics of the different sizes. Found by looking at TeX's output of
|
3525
3533
|
// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$
|
3526
3534
|
// Used to create stacked delimiters of appropriate sizes in makeSizedDelim.
|
@@ -6203,10 +6211,6 @@ const noSuccessor = ["\\smallint"];
|
|
6203
6211
|
// Math operators (e.g. \sin) need a space between these types and themselves:
|
6204
6212
|
const ordTypes = ["textord", "mathord", "ordgroup", "close", "leftright"];
|
6205
6213
|
|
6206
|
-
const dels$1 = ["}", "\\left", "\\middle", "\\right"];
|
6207
|
-
const isDelimiter$1 = str => str.length > 0 &&
|
6208
|
-
(delimiters.includes(str) || delimiterSizes[str] || dels$1.includes(str));
|
6209
|
-
|
6210
6214
|
// NOTE: Unlike most `builders`s, this one handles not only "op", but also
|
6211
6215
|
// "supsub" since some of them (like \int) can affect super/subscripting.
|
6212
6216
|
|
@@ -6427,7 +6431,7 @@ defineFunction({
|
|
6427
6431
|
parentIsSupSub: false,
|
6428
6432
|
symbol: false,
|
6429
6433
|
stack: false,
|
6430
|
-
isFollowedByDelimiter: isDelimiter
|
6434
|
+
isFollowedByDelimiter: isDelimiter(next),
|
6431
6435
|
needsLeadingSpace: prevAtomType.length > 0 && ordTypes.includes(prevAtomType),
|
6432
6436
|
name: funcName
|
6433
6437
|
};
|
@@ -6452,7 +6456,7 @@ defineFunction({
|
|
6452
6456
|
parentIsSupSub: false,
|
6453
6457
|
symbol: false,
|
6454
6458
|
stack: false,
|
6455
|
-
isFollowedByDelimiter: isDelimiter
|
6459
|
+
isFollowedByDelimiter: isDelimiter(next),
|
6456
6460
|
needsLeadingSpace: prevAtomType.length > 0 && ordTypes.includes(prevAtomType),
|
6457
6461
|
name: funcName
|
6458
6462
|
};
|
@@ -6538,11 +6542,7 @@ function defineMacro(name, body) {
|
|
6538
6542
|
_macros[name] = body;
|
6539
6543
|
}
|
6540
6544
|
|
6541
|
-
|
6542
|
-
const isDelimiter = str => str.length > 0 &&
|
6543
|
-
(delimiters.includes(str) || delimiterSizes[str] || dels.includes(str));
|
6544
|
-
|
6545
|
-
// NOTE: Unlike most builders, this one handles not only
|
6545
|
+
// NOTE: Unlike most builders, this one handles not only
|
6546
6546
|
// "operatorname", but also "supsub" since \operatorname* can
|
6547
6547
|
// affect super/subscripting.
|
6548
6548
|
|
@@ -6552,8 +6552,12 @@ const mathmlBuilder$1 = (group, style) => {
|
|
6552
6552
|
// Is expression a string or has it something like a fraction?
|
6553
6553
|
let isAllString = true; // default
|
6554
6554
|
for (let i = 0; i < expression.length; i++) {
|
6555
|
-
|
6555
|
+
let node = expression[i];
|
6556
6556
|
if (node instanceof mathMLTree.MathNode) {
|
6557
|
+
if (node.type === "mrow" && node.children.length === 1 &&
|
6558
|
+
node.children[0] instanceof mathMLTree.MathNode) {
|
6559
|
+
node = node.children[0];
|
6560
|
+
}
|
6557
6561
|
switch (node.type) {
|
6558
6562
|
case "mi":
|
6559
6563
|
case "mn":
|
@@ -6611,7 +6615,9 @@ const mathmlBuilder$1 = (group, style) => {
|
|
6611
6615
|
let wrapper;
|
6612
6616
|
if (isAllString) {
|
6613
6617
|
wrapper = new mathMLTree.MathNode("mi", expression);
|
6614
|
-
|
6618
|
+
if (expression[0].text.length === 1) {
|
6619
|
+
wrapper.setAttribute("mathvariant", "normal");
|
6620
|
+
}
|
6615
6621
|
} else {
|
6616
6622
|
wrapper = new mathMLTree.MathNode("mrow", expression);
|
6617
6623
|
}
|
@@ -7149,6 +7155,7 @@ defineFunctionBuilders({
|
|
7149
7155
|
let isOver;
|
7150
7156
|
let isSup;
|
7151
7157
|
let appendApplyFunction = false;
|
7158
|
+
let appendSpace = false;
|
7152
7159
|
let needsLeadingSpace = false;
|
7153
7160
|
|
7154
7161
|
if (group.base && group.base.type === "horizBrace") {
|
@@ -7163,6 +7170,7 @@ defineFunctionBuilders({
|
|
7163
7170
|
(group.base.type === "op" || group.base.type === "operatorname")) {
|
7164
7171
|
group.base.parentIsSupSub = true;
|
7165
7172
|
appendApplyFunction = !group.base.symbol;
|
7173
|
+
appendSpace = appendApplyFunction && !group.isFollowedByDelimiter;
|
7166
7174
|
needsLeadingSpace = group.base.needsLeadingSpace;
|
7167
7175
|
}
|
7168
7176
|
|
@@ -7250,6 +7258,11 @@ defineFunctionBuilders({
|
|
7250
7258
|
} else {
|
7251
7259
|
node = mathMLTree.newDocumentFragment([node, operator]);
|
7252
7260
|
}
|
7261
|
+
if (appendSpace) {
|
7262
|
+
const space = new mathMLTree.MathNode("mspace");
|
7263
|
+
space.setAttribute("width", "0.1667em"); // thin space.
|
7264
|
+
node.children.push(space);
|
7265
|
+
}
|
7253
7266
|
} else if (symbolRegEx.test(nodeType)) {
|
7254
7267
|
// Wrap in a <mrow>. Otherwise Firefox stretchy parens will not stretch to include limits.
|
7255
7268
|
node = new mathMLTree.MathNode("mrow", [node]);
|
@@ -8882,7 +8895,7 @@ defineMacro("\\incoh", `{\\mkern5mu\\rule{}{0.7em}\\mathrlap{\\smash{\\raise2mu{
|
|
8882
8895
|
defineMacro("\\standardstate", "\\text{\\tiny\\char`⦵}");
|
8883
8896
|
|
8884
8897
|
/* eslint-disable */
|
8885
|
-
/* -*- Mode:
|
8898
|
+
/* -*- Mode: JavaScript; indent-tabs-mode:nil; js-indent-level: 2 -*- */
|
8886
8899
|
/* vim: set ts=2 et sw=2 tw=80: */
|
8887
8900
|
|
8888
8901
|
/*************************************************************
|
@@ -10579,7 +10592,7 @@ defineMacro("\\tripleDashBetweenDoubleLine", `\\kern0.075em\\mathrlap{\\mathrlap
|
|
10579
10592
|
};
|
10580
10593
|
|
10581
10594
|
//
|
10582
|
-
// Helpers for code
|
10595
|
+
// Helpers for code analysis
|
10583
10596
|
// Will show type error at calling position
|
10584
10597
|
//
|
10585
10598
|
/** @param {number} a */
|
@@ -11004,15 +11017,15 @@ class MacroExpander {
|
|
11004
11017
|
* Expand the next token only once if possible.
|
11005
11018
|
*
|
11006
11019
|
* If the token is expanded, the resulting tokens will be pushed onto
|
11007
|
-
* the stack in reverse order and
|
11008
|
-
*
|
11020
|
+
* the stack in reverse order, and the number of such tokens will be
|
11021
|
+
* returned. This number might be zero or positive.
|
11009
11022
|
*
|
11010
|
-
* If not, the
|
11011
|
-
*
|
11012
|
-
* instead of an `Array` return value.
|
11023
|
+
* If not, the return value is `false`, and the next token remains at the
|
11024
|
+
* top of the stack.
|
11013
11025
|
*
|
11014
11026
|
* In either case, the next token will be on the top of the stack,
|
11015
|
-
* or the stack will be empty
|
11027
|
+
* or the stack will be empty (in case of empty expansion
|
11028
|
+
* and no other tokens).
|
11016
11029
|
*
|
11017
11030
|
* Used to implement `expandAfterFuture` and `expandNextToken`.
|
11018
11031
|
*
|
@@ -11028,7 +11041,7 @@ class MacroExpander {
|
|
11028
11041
|
throw new ParseError("Undefined control sequence: " + name);
|
11029
11042
|
}
|
11030
11043
|
this.pushToken(topToken);
|
11031
|
-
return
|
11044
|
+
return false;
|
11032
11045
|
}
|
11033
11046
|
this.expansionCount++;
|
11034
11047
|
if (this.expansionCount > this.settings.maxExpand) {
|
@@ -11062,7 +11075,7 @@ class MacroExpander {
|
|
11062
11075
|
}
|
11063
11076
|
// Concatenate expansion onto top of stack.
|
11064
11077
|
this.pushTokens(tokens);
|
11065
|
-
return tokens;
|
11078
|
+
return tokens.length;
|
11066
11079
|
}
|
11067
11080
|
|
11068
11081
|
/**
|
@@ -11081,14 +11094,13 @@ class MacroExpander {
|
|
11081
11094
|
*/
|
11082
11095
|
expandNextToken() {
|
11083
11096
|
for (;;) {
|
11084
|
-
|
11085
|
-
|
11086
|
-
if (expanded instanceof Token) {
|
11097
|
+
if (this.expandOnce() === false) { // fully expanded
|
11098
|
+
const token = this.stack.pop();
|
11087
11099
|
// The token after \noexpand is interpreted as if its meaning were ‘\relax’
|
11088
|
-
if (
|
11089
|
-
|
11100
|
+
if (token.treatAsRelax) {
|
11101
|
+
token.text = "\\relax";
|
11090
11102
|
}
|
11091
|
-
return
|
11103
|
+
return token
|
11092
11104
|
}
|
11093
11105
|
}
|
11094
11106
|
|
@@ -11114,15 +11126,15 @@ class MacroExpander {
|
|
11114
11126
|
const oldStackLength = this.stack.length;
|
11115
11127
|
this.pushTokens(tokens);
|
11116
11128
|
while (this.stack.length > oldStackLength) {
|
11117
|
-
|
11118
|
-
|
11119
|
-
|
11120
|
-
if (
|
11129
|
+
// Expand only expandable tokens
|
11130
|
+
if (this.expandOnce(true) === false) { // fully expanded
|
11131
|
+
const token = this.stack.pop();
|
11132
|
+
if (token.treatAsRelax) {
|
11121
11133
|
// the expansion of \noexpand is the token itself
|
11122
|
-
|
11123
|
-
|
11134
|
+
token.noexpand = false;
|
11135
|
+
token.treatAsRelax = false;
|
11124
11136
|
}
|
11125
|
-
output.push(
|
11137
|
+
output.push(token);
|
11126
11138
|
}
|
11127
11139
|
}
|
11128
11140
|
return output;
|
@@ -11950,7 +11962,7 @@ class Parser {
|
|
11950
11962
|
* Parses an "expression", which is a list of atoms.
|
11951
11963
|
*
|
11952
11964
|
* `breakOnInfix`: Should the parsing stop when we hit infix nodes? This
|
11953
|
-
* happens when functions have higher
|
11965
|
+
* happens when functions have higher precedence han infix
|
11954
11966
|
* nodes in implicit parses.
|
11955
11967
|
*
|
11956
11968
|
* `breakOnTokenText`: The text of the token that the expression should end
|
@@ -12201,12 +12213,16 @@ class Parser {
|
|
12201
12213
|
return base
|
12202
12214
|
} else {
|
12203
12215
|
// We got either a superscript or subscript, create a supsub
|
12216
|
+
const isFollowedByDelimiter = (!base || base.type !== "op" && base.type !== "operatorname")
|
12217
|
+
? undefined
|
12218
|
+
: isDelimiter(this.nextToken.text);
|
12204
12219
|
return {
|
12205
12220
|
type: "supsub",
|
12206
12221
|
mode: this.mode,
|
12207
12222
|
base: base,
|
12208
12223
|
sup: superscript,
|
12209
|
-
sub: subscript
|
12224
|
+
sub: subscript,
|
12225
|
+
isFollowedByDelimiter
|
12210
12226
|
}
|
12211
12227
|
}
|
12212
12228
|
} else {
|
@@ -12367,7 +12383,7 @@ class Parser {
|
|
12367
12383
|
while (true) {
|
12368
12384
|
const ch = this.fetch().text;
|
12369
12385
|
// \ufe0e is the Unicode variation selector to supress emoji. Ignore it.
|
12370
|
-
if (ch === " " || ch === "\ufe0e") {
|
12386
|
+
if (ch === " " || ch === "\u00a0" || ch === "\ufe0e") {
|
12371
12387
|
this.consume();
|
12372
12388
|
} else {
|
12373
12389
|
break
|
@@ -12959,7 +12975,7 @@ class Style {
|
|
12959
12975
|
* https://mit-license.org/
|
12960
12976
|
*/
|
12961
12977
|
|
12962
|
-
const version = "0.10.
|
12978
|
+
const version = "0.10.2";
|
12963
12979
|
|
12964
12980
|
function postProcess(block) {
|
12965
12981
|
const labelMap = {};
|
package/dist/temmlPostProcess.js
CHANGED
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "temml",
|
3
|
-
"version": "0.10.
|
3
|
+
"version": "0.10.2",
|
4
4
|
"description": "TeX to MathML conversion in JavaScript.",
|
5
5
|
"main": "dist/temml.js",
|
6
6
|
"homepage": "https://temml.org",
|
@@ -8,6 +8,7 @@
|
|
8
8
|
"type": "git",
|
9
9
|
"url": "git://github.com/ronkok/Temml"
|
10
10
|
},
|
11
|
+
"packageManager": "yarn@3.3.1",
|
11
12
|
"files": [
|
12
13
|
"temml.js",
|
13
14
|
"src/",
|
package/src/MacroExpander.js
CHANGED
@@ -230,15 +230,15 @@ export default class MacroExpander {
|
|
230
230
|
* Expand the next token only once if possible.
|
231
231
|
*
|
232
232
|
* If the token is expanded, the resulting tokens will be pushed onto
|
233
|
-
* the stack in reverse order and
|
234
|
-
*
|
233
|
+
* the stack in reverse order, and the number of such tokens will be
|
234
|
+
* returned. This number might be zero or positive.
|
235
235
|
*
|
236
|
-
* If not, the
|
237
|
-
*
|
238
|
-
* instead of an `Array` return value.
|
236
|
+
* If not, the return value is `false`, and the next token remains at the
|
237
|
+
* top of the stack.
|
239
238
|
*
|
240
239
|
* In either case, the next token will be on the top of the stack,
|
241
|
-
* or the stack will be empty
|
240
|
+
* or the stack will be empty (in case of empty expansion
|
241
|
+
* and no other tokens).
|
242
242
|
*
|
243
243
|
* Used to implement `expandAfterFuture` and `expandNextToken`.
|
244
244
|
*
|
@@ -254,7 +254,7 @@ export default class MacroExpander {
|
|
254
254
|
throw new ParseError("Undefined control sequence: " + name);
|
255
255
|
}
|
256
256
|
this.pushToken(topToken);
|
257
|
-
return
|
257
|
+
return false;
|
258
258
|
}
|
259
259
|
this.expansionCount++;
|
260
260
|
if (this.expansionCount > this.settings.maxExpand) {
|
@@ -288,7 +288,7 @@ export default class MacroExpander {
|
|
288
288
|
}
|
289
289
|
// Concatenate expansion onto top of stack.
|
290
290
|
this.pushTokens(tokens);
|
291
|
-
return tokens;
|
291
|
+
return tokens.length;
|
292
292
|
}
|
293
293
|
|
294
294
|
/**
|
@@ -307,14 +307,13 @@ export default class MacroExpander {
|
|
307
307
|
*/
|
308
308
|
expandNextToken() {
|
309
309
|
for (;;) {
|
310
|
-
|
311
|
-
|
312
|
-
if (expanded instanceof Token) {
|
310
|
+
if (this.expandOnce() === false) { // fully expanded
|
311
|
+
const token = this.stack.pop();
|
313
312
|
// The token after \noexpand is interpreted as if its meaning were ‘\relax’
|
314
|
-
if (
|
315
|
-
|
313
|
+
if (token.treatAsRelax) {
|
314
|
+
token.text = "\\relax"
|
316
315
|
}
|
317
|
-
return
|
316
|
+
return token
|
318
317
|
}
|
319
318
|
}
|
320
319
|
|
@@ -340,15 +339,15 @@ export default class MacroExpander {
|
|
340
339
|
const oldStackLength = this.stack.length;
|
341
340
|
this.pushTokens(tokens);
|
342
341
|
while (this.stack.length > oldStackLength) {
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
if (
|
342
|
+
// Expand only expandable tokens
|
343
|
+
if (this.expandOnce(true) === false) { // fully expanded
|
344
|
+
const token = this.stack.pop();
|
345
|
+
if (token.treatAsRelax) {
|
347
346
|
// the expansion of \noexpand is the token itself
|
348
|
-
|
349
|
-
|
347
|
+
token.noexpand = false;
|
348
|
+
token.treatAsRelax = false;
|
350
349
|
}
|
351
|
-
output.push(
|
350
|
+
output.push(token);
|
352
351
|
}
|
353
352
|
}
|
354
353
|
return output;
|
package/src/Parser.js
CHANGED
@@ -10,6 +10,7 @@ import { uSubsAndSups, unicodeSubRegEx } from "./unicodeSupOrSub"
|
|
10
10
|
import { asciiFromScript } from "./asciiFromScript"
|
11
11
|
import SourceLocation from "./SourceLocation";
|
12
12
|
import { Token } from "./Token";
|
13
|
+
import { isDelimiter } from "./functions/delimsizing"
|
13
14
|
|
14
15
|
// Pre-evaluate both modules as unicodeSymbols require String.normalize()
|
15
16
|
import unicodeAccents from /*preval*/ "./unicodeAccents";
|
@@ -173,7 +174,7 @@ export default class Parser {
|
|
173
174
|
* Parses an "expression", which is a list of atoms.
|
174
175
|
*
|
175
176
|
* `breakOnInfix`: Should the parsing stop when we hit infix nodes? This
|
176
|
-
* happens when functions have higher
|
177
|
+
* happens when functions have higher precedence han infix
|
177
178
|
* nodes in implicit parses.
|
178
179
|
*
|
179
180
|
* `breakOnTokenText`: The text of the token that the expression should end
|
@@ -424,12 +425,16 @@ export default class Parser {
|
|
424
425
|
return base
|
425
426
|
} else {
|
426
427
|
// We got either a superscript or subscript, create a supsub
|
428
|
+
const isFollowedByDelimiter = (!base || base.type !== "op" && base.type !== "operatorname")
|
429
|
+
? undefined
|
430
|
+
: isDelimiter(this.nextToken.text);
|
427
431
|
return {
|
428
432
|
type: "supsub",
|
429
433
|
mode: this.mode,
|
430
434
|
base: base,
|
431
435
|
sup: superscript,
|
432
|
-
sub: subscript
|
436
|
+
sub: subscript,
|
437
|
+
isFollowedByDelimiter
|
433
438
|
}
|
434
439
|
}
|
435
440
|
} else {
|
@@ -590,7 +595,7 @@ export default class Parser {
|
|
590
595
|
while (true) {
|
591
596
|
const ch = this.fetch().text
|
592
597
|
// \ufe0e is the Unicode variation selector to supress emoji. Ignore it.
|
593
|
-
if (ch === " " || ch === "\ufe0e") {
|
598
|
+
if (ch === " " || ch === "\u00a0" || ch === "\ufe0e") {
|
594
599
|
this.consume()
|
595
600
|
} else {
|
596
601
|
break
|
package/src/buildMathML.js
CHANGED
@@ -89,6 +89,11 @@ export const delimiters = [
|
|
89
89
|
"."
|
90
90
|
];
|
91
91
|
|
92
|
+
// Export isDelimiter for benefit of parser.
|
93
|
+
const dels = ["}", "\\left", "\\middle", "\\right"]
|
94
|
+
export const isDelimiter = str => str.length > 0 &&
|
95
|
+
(delimiters.includes(str) || delimiterSizes[str] || dels.includes(str))
|
96
|
+
|
92
97
|
// Metrics of the different sizes. Found by looking at TeX's output of
|
93
98
|
// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$
|
94
99
|
// Used to create stacked delimiters of appropriate sizes in makeSizedDelim.
|
package/src/functions/op.js
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
import defineFunction, { ordargument } from "../defineFunction";
|
3
3
|
import * as mathMLTree from "../mathMLTree";
|
4
4
|
import * as mml from "../buildMathML";
|
5
|
-
import {
|
5
|
+
import { isDelimiter } from "./delimsizing"
|
6
6
|
|
7
7
|
// Some helpers
|
8
8
|
|
@@ -14,10 +14,6 @@ const noSuccessor = ["\\smallint"];
|
|
14
14
|
// Math operators (e.g. \sin) need a space between these types and themselves:
|
15
15
|
export const ordTypes = ["textord", "mathord", "ordgroup", "close", "leftright"];
|
16
16
|
|
17
|
-
const dels = ["}", "\\left", "\\middle", "\\right"]
|
18
|
-
const isDelimiter = str => str.length > 0 &&
|
19
|
-
(delimiters.includes(str) || delimiterSizes[str] || dels.includes(str))
|
20
|
-
|
21
17
|
// NOTE: Unlike most `builders`s, this one handles not only "op", but also
|
22
18
|
// "supsub" since some of them (like \int) can affect super/subscripting.
|
23
19
|
|
@@ -3,15 +3,11 @@ import defineMacro from "../defineMacro";
|
|
3
3
|
import mathMLTree from "../mathMLTree"
|
4
4
|
import { spaceCharacter } from "./kern"
|
5
5
|
import { ordTypes } from "./op"
|
6
|
-
import {
|
6
|
+
import { isDelimiter } from "./delimsizing"
|
7
7
|
|
8
8
|
import * as mml from "../buildMathML"
|
9
9
|
|
10
|
-
|
11
|
-
const isDelimiter = str => str.length > 0 &&
|
12
|
-
(delimiters.includes(str) || delimiterSizes[str] || dels.includes(str))
|
13
|
-
|
14
|
-
// NOTE: Unlike most builders, this one handles not only
|
10
|
+
// NOTE: Unlike most builders, this one handles not only
|
15
11
|
// "operatorname", but also "supsub" since \operatorname* can
|
16
12
|
// affect super/subscripting.
|
17
13
|
|
@@ -21,8 +17,12 @@ const mathmlBuilder = (group, style) => {
|
|
21
17
|
// Is expression a string or has it something like a fraction?
|
22
18
|
let isAllString = true; // default
|
23
19
|
for (let i = 0; i < expression.length; i++) {
|
24
|
-
|
20
|
+
let node = expression[i]
|
25
21
|
if (node instanceof mathMLTree.MathNode) {
|
22
|
+
if (node.type === "mrow" && node.children.length === 1 &&
|
23
|
+
node.children[0] instanceof mathMLTree.MathNode) {
|
24
|
+
node = node.children[0]
|
25
|
+
}
|
26
26
|
switch (node.type) {
|
27
27
|
case "mi":
|
28
28
|
case "mn":
|
@@ -80,7 +80,9 @@ const mathmlBuilder = (group, style) => {
|
|
80
80
|
let wrapper;
|
81
81
|
if (isAllString) {
|
82
82
|
wrapper = new mathMLTree.MathNode("mi", expression)
|
83
|
-
|
83
|
+
if (expression[0].text.length === 1) {
|
84
|
+
wrapper.setAttribute("mathvariant", "normal")
|
85
|
+
}
|
84
86
|
} else {
|
85
87
|
wrapper = new mathMLTree.MathNode("mrow", expression)
|
86
88
|
}
|
package/src/functions/supsub.js
CHANGED
@@ -24,6 +24,7 @@ defineFunctionBuilders({
|
|
24
24
|
let isOver
|
25
25
|
let isSup
|
26
26
|
let appendApplyFunction = false
|
27
|
+
let appendSpace = false
|
27
28
|
let needsLeadingSpace = false
|
28
29
|
|
29
30
|
if (group.base && group.base.type === "horizBrace") {
|
@@ -38,6 +39,7 @@ defineFunctionBuilders({
|
|
38
39
|
(group.base.type === "op" || group.base.type === "operatorname")) {
|
39
40
|
group.base.parentIsSupSub = true
|
40
41
|
appendApplyFunction = !group.base.symbol
|
42
|
+
appendSpace = appendApplyFunction && !group.isFollowedByDelimiter
|
41
43
|
needsLeadingSpace = group.base.needsLeadingSpace
|
42
44
|
}
|
43
45
|
|
@@ -125,6 +127,11 @@ defineFunctionBuilders({
|
|
125
127
|
} else {
|
126
128
|
node = mathMLTree.newDocumentFragment([node, operator])
|
127
129
|
}
|
130
|
+
if (appendSpace) {
|
131
|
+
const space = new mathMLTree.MathNode("mspace")
|
132
|
+
space.setAttribute("width", "0.1667em") // thin space.
|
133
|
+
node.children.push(space)
|
134
|
+
}
|
128
135
|
} else if (symbolRegEx.test(nodeType)) {
|
129
136
|
// Wrap in a <mrow>. Otherwise Firefox stretchy parens will not stretch to include limits.
|
130
137
|
node = new mathMLTree.MathNode("mrow", [node])
|
package/src/mathMLTree.js
CHANGED
package/src/postProcess.js
CHANGED
package/src/symbols.js
CHANGED
@@ -85,7 +85,6 @@ defineSymbol(math, rel, "\u226a", "\\ll", true);
|
|
85
85
|
defineSymbol(math, rel, "\u226b", "\\gg", true);
|
86
86
|
defineSymbol(math, rel, "\u224d", "\\asymp", true);
|
87
87
|
defineSymbol(math, rel, "\u2225", "\\parallel");
|
88
|
-
defineSymbol(math, rel, "\u22c8", "\\bowtie", true);
|
89
88
|
defineSymbol(math, rel, "\u2323", "\\smile", true);
|
90
89
|
defineSymbol(math, rel, "\u2291", "\\sqsubseteq", true);
|
91
90
|
defineSymbol(math, rel, "\u2292", "\\sqsupseteq", true);
|
@@ -402,7 +401,6 @@ defineSymbol(math, rel, "\u22d9", "\\gggtr");
|
|
402
401
|
defineSymbol(math, bin, "\u22b2", "\\lhd");
|
403
402
|
defineSymbol(math, bin, "\u22b3", "\\rhd");
|
404
403
|
defineSymbol(math, rel, "\u2242", "\\eqsim", true);
|
405
|
-
defineSymbol(math, rel, "\u22c8", "\\Join");
|
406
404
|
defineSymbol(math, rel, "\u2251", "\\Doteq", true);
|
407
405
|
defineSymbol(math, rel, "\u297d", "\\strictif", true);
|
408
406
|
defineSymbol(math, rel, "\u297c", "\\strictfi", true);
|
@@ -428,6 +426,11 @@ defineSymbol(math, bin, "\u22ba", "\\intercal", true);
|
|
428
426
|
defineSymbol(math, bin, "\u22d2", "\\doublecap");
|
429
427
|
defineSymbol(math, bin, "\u22d3", "\\doublecup");
|
430
428
|
defineSymbol(math, bin, "\u22a0", "\\boxtimes", true);
|
429
|
+
defineSymbol(math, bin, "\u22c8", "\\bowtie", true);
|
430
|
+
defineSymbol(math, bin, "\u22c8", "\\Join");
|
431
|
+
defineSymbol(math, bin, "\u27d5", "\\leftouterjoin", true);
|
432
|
+
defineSymbol(math, bin, "\u27d6", "\\rightouterjoin", true);
|
433
|
+
defineSymbol(math, bin, "\u27d7", "\\fullouterjoin", true);
|
431
434
|
|
432
435
|
// AMS Arrows
|
433
436
|
// Note: unicode-math maps \u21e2 to their own function \rightdasharrow.
|