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.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, color) {
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
- for (let i = 0; i < expression.length; i++) {
1789
- const node = expression[i];
1790
- if (node.type && node.type === "mstyle" && node.attributes.mathcolor) {
1791
- if (block.length > 0) {
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
- const element = new mathMLTree.MathNode(tagName, block);
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" && wrapMode === "=") {
1817
- if (node.children.length === 1 && node.children[0].text === "=") {
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(tagName, block);
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
- } else if (node.type && node.type === "mo" && wrapMode === "tex") {
1829
- // This may be a place for a soft line break.
1830
- if (canBeBIN && !node.attributes.form) {
1831
- // Check if the following node is a \nobreak text node, e.g. "~""
1832
- const next = i < expression.length - 1 ? expression[i + 1] : null;
1833
- let glueIsFreeOfNobreak = true;
1834
- if (
1835
- !(
1836
- next &&
1837
- next.type === "mtext" &&
1838
- next.attributes.linebreak &&
1839
- next.attributes.linebreak === "nobreak"
1840
- )
1841
- ) {
1842
- // We may need to start a new block.
1843
- // First, put any post-operator glue on same line as operator.
1844
- for (let j = i + 1; j < expression.length; j++) {
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.attributes &&
1855
- nd.attributes.linebreak &&
1856
- nd.attributes.linebreak === "nobreak"
1822
+ nd.type &&
1823
+ nd.type === "mspace" &&
1824
+ !(nd.attributes.linebreak && nd.attributes.linebreak === "newline")
1857
1825
  ) {
1858
- glueIsFreeOfNobreak = false;
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
- if (glueIsFreeOfNobreak) {
1866
- // Start a new block. (Insert a soft linebreak.)
1867
- const element = new mathMLTree.MathNode(tagName, block);
1868
- if (color) { element.setAttribute("mathcolor", color); }
1869
- mrows.push(element);
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(tagName, block);
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
- const inner = buildExpression(group.body, style.withColor(group.color));
3043
- // Wrap with an <mstyle> element.
3044
- const node = wrapWithMstyle(inner);
3045
- node.setAttribute("mathcolor", group.color);
3046
- return node
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$1 = /^\d(?:[\d,.]*\d)?$/; // Keep in sync with numberRegEx in Parser.js
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$1.test(group.text)) {
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
- "(number" + // numbers (in non-strict mode)
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.3";
11082
+ const version = "0.10.5";
11075
11083
 
11076
11084
  function postProcess(block) {
11077
11085
  const labelMap = {};