temml 0.10.3 → 0.10.5
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/temml.cjs +116 -108
- package/dist/temml.js +116 -108
- package/dist/temml.min.js +1 -1
- package/dist/temml.mjs +116 -108
- package/dist/temmlPostProcess.js +1 -1
- package/package.json +8 -2
- package/src/Lexer.js +2 -8
- package/src/Parser.js +0 -11
- package/src/buildMathML.js +44 -0
- package/src/functions/color.js +10 -6
- package/src/functions/symbolsOrd.js +1 -1
- package/src/linebreaking.js +60 -82
- package/src/postProcess.js +1 -1
package/dist/temml.js
CHANGED
@@ -1762,125 +1762,102 @@ var temml = (function () {
|
|
1762
1762
|
* much of this module.
|
1763
1763
|
*/
|
1764
1764
|
|
1765
|
-
function setLineBreaks(expression, wrapMode, isDisplayMode
|
1766
|
-
if (color === undefined && wrapMode !== "none") {
|
1767
|
-
// First, make one pass through the expression and split any color nodes.
|
1768
|
-
const upperLimit = expression.length - 1;
|
1769
|
-
for (let i = upperLimit; i >= 0; i--) {
|
1770
|
-
const node = expression[i];
|
1771
|
-
if (node.type === "mstyle" && node.attributes.mathcolor) {
|
1772
|
-
const color = node.attributes.mathcolor;
|
1773
|
-
const fragment = setLineBreaks(node.children, wrapMode, isDisplayMode, color);
|
1774
|
-
if (!(fragment.type && fragment.type !== "mtable")) {
|
1775
|
-
expression.splice(i, 1, ...fragment.children);
|
1776
|
-
}
|
1777
|
-
}
|
1778
|
-
}
|
1779
|
-
}
|
1780
|
-
|
1781
|
-
const tagName = color ? "mstyle" : "mrow";
|
1782
|
-
|
1765
|
+
function setLineBreaks(expression, wrapMode, isDisplayMode) {
|
1783
1766
|
const mtrs = [];
|
1784
1767
|
let mrows = [];
|
1785
1768
|
let block = [];
|
1786
1769
|
let numTopLevelEquals = 0;
|
1787
1770
|
let canBeBIN = false; // The first node cannot be an infix binary operator.
|
1788
|
-
|
1789
|
-
|
1790
|
-
|
1791
|
-
|
1792
|
-
// Start a new block. (Insert a soft linebreak.)
|
1793
|
-
mrows.push(new mathMLTree.MathNode(tagName, block));
|
1794
|
-
}
|
1795
|
-
// Insert the mstyle
|
1796
|
-
mrows.push(node);
|
1797
|
-
block = [];
|
1798
|
-
continue
|
1771
|
+
let i = 0;
|
1772
|
+
while (i < expression.length) {
|
1773
|
+
while (expression[i] instanceof DocumentFragment) {
|
1774
|
+
expression.splice(i, 1, ...expression[i].children); // Expand the fragment.
|
1799
1775
|
}
|
1776
|
+
const node = expression[i];
|
1800
1777
|
if (node.attributes && node.attributes.linebreak &&
|
1801
1778
|
node.attributes.linebreak === "newline") {
|
1802
1779
|
// A hard line break. Create a <mtr> for the current block.
|
1803
1780
|
if (block.length > 0) {
|
1804
|
-
|
1805
|
-
if (color) { element.setAttribute("mathcolor", color); }
|
1806
|
-
mrows.push(new mathMLTree.MathNode(tagName, block));
|
1781
|
+
mrows.push(new mathMLTree.MathNode("mrow", block));
|
1807
1782
|
}
|
1808
1783
|
mrows.push(node);
|
1809
1784
|
block = [];
|
1810
1785
|
const mtd = new mathMLTree.MathNode("mtd", mrows);
|
1786
|
+
mtd.style.textAlign = "left";
|
1811
1787
|
mtrs.push(new mathMLTree.MathNode("mtr", [mtd]));
|
1812
1788
|
mrows = [];
|
1789
|
+
i += 1;
|
1813
1790
|
continue
|
1814
1791
|
}
|
1815
1792
|
block.push(node);
|
1816
|
-
if (node.type && node.type === "mo" &&
|
1817
|
-
if (
|
1793
|
+
if (node.type && node.type === "mo" && node.children.length === 1) {
|
1794
|
+
if (wrapMode === "=" && node.children[0].text === "=") {
|
1818
1795
|
numTopLevelEquals += 1;
|
1819
1796
|
if (numTopLevelEquals > 1) {
|
1820
1797
|
block.pop();
|
1821
1798
|
// Start a new block. (Insert a soft linebreak.)
|
1822
|
-
const element = new mathMLTree.MathNode(
|
1823
|
-
if (color) { element.setAttribute("mathcolor", color); }
|
1799
|
+
const element = new mathMLTree.MathNode("mrow", block);
|
1824
1800
|
mrows.push(element);
|
1825
1801
|
block = [node];
|
1826
1802
|
}
|
1827
|
-
}
|
1828
|
-
|
1829
|
-
|
1830
|
-
|
1831
|
-
|
1832
|
-
|
1833
|
-
|
1834
|
-
|
1835
|
-
|
1836
|
-
|
1837
|
-
|
1838
|
-
|
1839
|
-
|
1840
|
-
)
|
1841
|
-
|
1842
|
-
|
1843
|
-
|
1844
|
-
|
1845
|
-
const nd = expression[j];
|
1846
|
-
if (
|
1847
|
-
nd.type &&
|
1848
|
-
nd.type === "mspace" &&
|
1849
|
-
!(nd.attributes.linebreak && nd.attributes.linebreak === "newline")
|
1850
|
-
) {
|
1851
|
-
block.push(nd);
|
1852
|
-
i += 1;
|
1803
|
+
} else if (wrapMode === "tex") {
|
1804
|
+
// This may be a place for a soft line break.
|
1805
|
+
if (canBeBIN && !node.attributes.form) {
|
1806
|
+
// Check if the following node is a \nobreak text node, e.g. "~""
|
1807
|
+
const next = i < expression.length - 1 ? expression[i + 1] : null;
|
1808
|
+
let glueIsFreeOfNobreak = true;
|
1809
|
+
if (
|
1810
|
+
!(
|
1811
|
+
next &&
|
1812
|
+
next.type === "mtext" &&
|
1813
|
+
next.attributes.linebreak &&
|
1814
|
+
next.attributes.linebreak === "nobreak"
|
1815
|
+
)
|
1816
|
+
) {
|
1817
|
+
// We may need to start a new block.
|
1818
|
+
// First, put any post-operator glue on same line as operator.
|
1819
|
+
for (let j = i + 1; j < expression.length; j++) {
|
1820
|
+
const nd = expression[j];
|
1853
1821
|
if (
|
1854
|
-
nd.
|
1855
|
-
nd.
|
1856
|
-
nd.attributes.linebreak === "
|
1822
|
+
nd.type &&
|
1823
|
+
nd.type === "mspace" &&
|
1824
|
+
!(nd.attributes.linebreak && nd.attributes.linebreak === "newline")
|
1857
1825
|
) {
|
1858
|
-
|
1826
|
+
block.push(nd);
|
1827
|
+
i += 1;
|
1828
|
+
if (
|
1829
|
+
nd.attributes &&
|
1830
|
+
nd.attributes.linebreak &&
|
1831
|
+
nd.attributes.linebreak === "nobreak"
|
1832
|
+
) {
|
1833
|
+
glueIsFreeOfNobreak = false;
|
1834
|
+
}
|
1835
|
+
} else {
|
1836
|
+
break;
|
1859
1837
|
}
|
1860
|
-
} else {
|
1861
|
-
break;
|
1862
1838
|
}
|
1863
1839
|
}
|
1840
|
+
if (glueIsFreeOfNobreak) {
|
1841
|
+
// Start a new block. (Insert a soft linebreak.)
|
1842
|
+
const element = new mathMLTree.MathNode("mrow", block);
|
1843
|
+
mrows.push(element);
|
1844
|
+
block = [];
|
1845
|
+
}
|
1846
|
+
canBeBIN = false;
|
1864
1847
|
}
|
1865
|
-
|
1866
|
-
|
1867
|
-
|
1868
|
-
|
1869
|
-
|
1870
|
-
block = [];
|
1871
|
-
}
|
1872
|
-
canBeBIN = false;
|
1848
|
+
const isOpenDelimiter = node.attributes.form && node.attributes.form === "prefix";
|
1849
|
+
// Any operator that follows an open delimiter is unary.
|
1850
|
+
canBeBIN = !(node.attributes.separator || isOpenDelimiter);
|
1851
|
+
} else {
|
1852
|
+
canBeBIN = true;
|
1873
1853
|
}
|
1874
|
-
const isOpenDelimiter = node.attributes.form && node.attributes.form === "prefix";
|
1875
|
-
// Any operator that follows an open delimiter is unary.
|
1876
|
-
canBeBIN = !(node.attributes.separator || isOpenDelimiter);
|
1877
1854
|
} else {
|
1878
1855
|
canBeBIN = true;
|
1879
1856
|
}
|
1857
|
+
i += 1;
|
1880
1858
|
}
|
1881
1859
|
if (block.length > 0) {
|
1882
|
-
const element = new mathMLTree.MathNode(
|
1883
|
-
if (color) { element.setAttribute("mathcolor", color); }
|
1860
|
+
const element = new mathMLTree.MathNode("mrow", block);
|
1884
1861
|
mrows.push(element);
|
1885
1862
|
}
|
1886
1863
|
if (mtrs.length > 0) {
|
@@ -1967,6 +1944,48 @@ var temml = (function () {
|
|
1967
1944
|
return mtext
|
1968
1945
|
};
|
1969
1946
|
|
1947
|
+
const numberRegEx$1 = /^[0-9]$/;
|
1948
|
+
const isCommaOrDot = node => {
|
1949
|
+
return (node.type === "atom" && node.text === ",") ||
|
1950
|
+
(node.type === "textord" && node.text === ".")
|
1951
|
+
};
|
1952
|
+
const consolidateNumbers = expression => {
|
1953
|
+
// Consolidate adjacent numbers. We want to return <mn>1,506.3</mn>,
|
1954
|
+
// not <mn>1</mn><mo>,</mo><mn>5</mn><mn>0</mn><mn>6</mn><mi>.</mi><mn>3</mn>
|
1955
|
+
if (expression.length < 2) { return }
|
1956
|
+
const nums = [];
|
1957
|
+
let inNum = false;
|
1958
|
+
// Find adjacent numerals
|
1959
|
+
for (let i = 0; i < expression.length; i++) {
|
1960
|
+
const node = expression[i];
|
1961
|
+
if (node.type === "textord" && numberRegEx$1.test(node.text)) {
|
1962
|
+
if (!inNum) { nums.push({ start: i }); }
|
1963
|
+
inNum = true;
|
1964
|
+
} else {
|
1965
|
+
if (inNum) { nums[nums.length - 1].end = i - 1; }
|
1966
|
+
inNum = false;
|
1967
|
+
}
|
1968
|
+
}
|
1969
|
+
if (inNum) { nums[nums.length - 1].end = expression.length - 1; }
|
1970
|
+
|
1971
|
+
// Determine if numeral groups are separated by a comma or dot.
|
1972
|
+
for (let i = nums.length - 1; i > 0; i--) {
|
1973
|
+
if (nums[i - 1].end === nums[i].start - 2 && isCommaOrDot(expression[nums[i].start - 1])) {
|
1974
|
+
// Merge the two groups.
|
1975
|
+
nums[i - 1].end = nums[i].end;
|
1976
|
+
nums.splice(i, 1);
|
1977
|
+
}
|
1978
|
+
}
|
1979
|
+
|
1980
|
+
// Consolidate the number nodes
|
1981
|
+
for (let i = nums.length - 1; i >= 0; i--) {
|
1982
|
+
for (let j = nums[i].start + 1; j <= nums[i].end; j++) {
|
1983
|
+
expression[nums[i].start].text += expression[j].text;
|
1984
|
+
}
|
1985
|
+
expression.splice(nums[i].start + 1, nums[i].end - nums[i].start);
|
1986
|
+
}
|
1987
|
+
};
|
1988
|
+
|
1970
1989
|
/**
|
1971
1990
|
* Wrap the given array of nodes in an <mrow> node if needed, i.e.,
|
1972
1991
|
* unless the array has length 1. Always returns a single node.
|
@@ -2002,6 +2021,8 @@ var temml = (function () {
|
|
2002
2021
|
return [group];
|
2003
2022
|
}
|
2004
2023
|
|
2024
|
+
consolidateNumbers(expression);
|
2025
|
+
|
2005
2026
|
const groups = [];
|
2006
2027
|
for (let i = 0; i < expression.length; i++) {
|
2007
2028
|
const group = buildGroup$1(expression[i], style);
|
@@ -3039,11 +3060,15 @@ var temml = (function () {
|
|
3039
3060
|
};
|
3040
3061
|
|
3041
3062
|
const mathmlBuilder$9 = (group, style) => {
|
3042
|
-
|
3043
|
-
//
|
3044
|
-
|
3045
|
-
|
3046
|
-
|
3063
|
+
// In LaTeX, color is not supposed to change the spacing of any node.
|
3064
|
+
// So instead of wrapping the group in an <mstyle>, we apply
|
3065
|
+
// the color individually to each node and return a document fragment.
|
3066
|
+
let expr = buildExpression(group.body, style.withColor(group.color));
|
3067
|
+
expr = expr.map(e => {
|
3068
|
+
e.style.color = group.color;
|
3069
|
+
return e
|
3070
|
+
});
|
3071
|
+
return mathMLTree.newDocumentFragment(expr)
|
3047
3072
|
};
|
3048
3073
|
|
3049
3074
|
defineFunction({
|
@@ -7644,7 +7669,7 @@ var temml = (function () {
|
|
7644
7669
|
// "mathord" and "textord" ParseNodes created in Parser.js from symbol Groups in
|
7645
7670
|
// src/symbols.js.
|
7646
7671
|
|
7647
|
-
const numberRegEx
|
7672
|
+
const numberRegEx = /^\d(?:[\d,.]*\d)?$/;
|
7648
7673
|
const latinRegEx = /[A-Ba-z]/;
|
7649
7674
|
|
7650
7675
|
const italicNumber = (text, variant, tag) => {
|
@@ -7698,7 +7723,7 @@ var temml = (function () {
|
|
7698
7723
|
const variant = getVariant(group, style) || "normal";
|
7699
7724
|
|
7700
7725
|
let node;
|
7701
|
-
if (numberRegEx
|
7726
|
+
if (numberRegEx.test(group.text)) {
|
7702
7727
|
const tag = group.mode === "text" ? "mtext" : "mn";
|
7703
7728
|
if (variant === "italic" || variant === "bold-italic") {
|
7704
7729
|
return italicNumber(text, variant, tag)
|
@@ -8011,8 +8036,7 @@ var temml = (function () {
|
|
8011
8036
|
const tokenRegexString =
|
8012
8037
|
`(${spaceRegexString}+)|` + // whitespace
|
8013
8038
|
`${controlSpaceRegexString}|` + // whitespace
|
8014
|
-
"(
|
8015
|
-
"|[!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + // single codepoint
|
8039
|
+
"([!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + // single codepoint
|
8016
8040
|
`${combiningDiacriticalMarkString}*` + // ...plus accents
|
8017
8041
|
"|[\uD800-\uDBFF][\uDC00-\uDFFF]" + // surrogate pair
|
8018
8042
|
`${combiningDiacriticalMarkString}*` + // ...plus accents
|
@@ -8027,12 +8051,7 @@ var temml = (function () {
|
|
8027
8051
|
// Separate accents from characters
|
8028
8052
|
this.input = input;
|
8029
8053
|
this.settings = settings;
|
8030
|
-
this.tokenRegex = new RegExp(
|
8031
|
-
// Strict Temml, like TeX, lexes one numeral at a time.
|
8032
|
-
// Default Temml lexes contiguous numerals into a single <mn> element.
|
8033
|
-
tokenRegexString.replace("number|", settings.strict ? "" : "\\d(?:[\\d,.]*\\d)?|"),
|
8034
|
-
"g"
|
8035
|
-
);
|
8054
|
+
this.tokenRegex = new RegExp(tokenRegexString, 'g');
|
8036
8055
|
// Category codes. The lexer only supports comment characters (14) for now.
|
8037
8056
|
// MacroExpander additionally distinguishes active (13).
|
8038
8057
|
this.catcodes = {
|
@@ -9900,8 +9919,6 @@ var temml = (function () {
|
|
9900
9919
|
|
9901
9920
|
/* eslint no-constant-condition:0 */
|
9902
9921
|
|
9903
|
-
const numberRegEx = /^\d(?:[\d,.]*\d)?$/; // Keep in sync with numberRegEx in symbolsOrd.js
|
9904
|
-
|
9905
9922
|
/**
|
9906
9923
|
* This file contains the parser used to parse out a TeX expression from the
|
9907
9924
|
* input. Since TeX isn't context-free, standard parsers don't work particularly
|
@@ -10823,15 +10840,6 @@ var temml = (function () {
|
|
10823
10840
|
};
|
10824
10841
|
}
|
10825
10842
|
symbol = s;
|
10826
|
-
} else if (!this.strict && numberRegEx.test(text)) {
|
10827
|
-
// A number. Wrap in a <mn> if in math mode; <mtext> otherwise.
|
10828
|
-
this.consume();
|
10829
|
-
return {
|
10830
|
-
type: "textord",
|
10831
|
-
mode: this.mode,
|
10832
|
-
loc: SourceLocation.range(nucleus),
|
10833
|
-
text
|
10834
|
-
}
|
10835
10843
|
} else if (text.charCodeAt(0) >= 0x80) {
|
10836
10844
|
// no symbol for e.g. ^
|
10837
10845
|
if (this.settings.strict) {
|
@@ -11071,7 +11079,7 @@ var temml = (function () {
|
|
11071
11079
|
* https://mit-license.org/
|
11072
11080
|
*/
|
11073
11081
|
|
11074
|
-
const version = "0.10.
|
11082
|
+
const version = "0.10.5";
|
11075
11083
|
|
11076
11084
|
function postProcess(block) {
|
11077
11085
|
const labelMap = {};
|