temml 0.10.3 → 0.10.5
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.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 = {};
|