@pixerate/editor 0.23.0 → 0.24.0

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.
Files changed (155) hide show
  1. package/README.md +96 -1
  2. package/THIRD_PARTY_NOTICES.md +51 -0
  3. package/dist/agent/index.cjs +9 -8
  4. package/dist/agent/index.cjs.map +1 -1
  5. package/dist/agent/index.d.cts +4 -3
  6. package/dist/agent/index.d.ts +4 -3
  7. package/dist/agent/index.js +3 -2
  8. package/dist/agent/index.js.map +1 -1
  9. package/dist/canvas/index.cjs +1210 -17
  10. package/dist/canvas/index.cjs.map +1 -1
  11. package/dist/canvas/index.d.cts +318 -1
  12. package/dist/canvas/index.d.ts +318 -1
  13. package/dist/canvas/index.js +1199 -6
  14. package/dist/canvas/index.js.map +1 -1
  15. package/dist/{chunk-QBJ22YZR.js → chunk-3CN2WD3X.js} +1354 -206
  16. package/dist/chunk-3CN2WD3X.js.map +1 -0
  17. package/dist/{chunk-JJDLPEWL.js → chunk-3LV6RRPH.js} +2 -2
  18. package/dist/{chunk-MJZBNWG7.js → chunk-5S3Z4PPF.js} +78 -557
  19. package/dist/chunk-5S3Z4PPF.js.map +1 -0
  20. package/dist/chunk-664LQYFJ.js +115 -0
  21. package/dist/chunk-664LQYFJ.js.map +1 -0
  22. package/dist/{chunk-AA4ZEVCC.cjs → chunk-D27YFC46.cjs} +101 -580
  23. package/dist/chunk-D27YFC46.cjs.map +1 -0
  24. package/dist/chunk-D6FH2YAX.cjs +131 -0
  25. package/dist/chunk-D6FH2YAX.cjs.map +1 -0
  26. package/dist/{chunk-4SUNJZWB.cjs → chunk-FD4LPFAE.cjs} +48 -200
  27. package/dist/chunk-FD4LPFAE.cjs.map +1 -0
  28. package/dist/chunk-FODNLX5N.js +749 -0
  29. package/dist/chunk-FODNLX5N.js.map +1 -0
  30. package/dist/{chunk-OYXSKQFR.js → chunk-FPENXAEJ.js} +35 -187
  31. package/dist/chunk-FPENXAEJ.js.map +1 -0
  32. package/dist/chunk-HLIMTC6N.js +1 -0
  33. package/dist/chunk-HLIMTC6N.js.map +1 -0
  34. package/dist/{chunk-QGHGJ56O.js → chunk-ITBSKI26.js} +1483 -19
  35. package/dist/chunk-ITBSKI26.js.map +1 -0
  36. package/dist/{chunk-XDMXXC4Z.cjs → chunk-MA2F5KHF.cjs} +350 -227
  37. package/dist/chunk-MA2F5KHF.cjs.map +1 -0
  38. package/dist/{chunk-RIKBJLS2.cjs → chunk-MCSJFWAO.cjs} +1356 -208
  39. package/dist/chunk-MCSJFWAO.cjs.map +1 -0
  40. package/dist/chunk-MKA3AHLV.cjs +256 -0
  41. package/dist/chunk-MKA3AHLV.cjs.map +1 -0
  42. package/dist/chunk-OLZJXL4R.cjs +749 -0
  43. package/dist/chunk-OLZJXL4R.cjs.map +1 -0
  44. package/dist/chunk-OXSV64JX.js +689 -0
  45. package/dist/chunk-OXSV64JX.js.map +1 -0
  46. package/dist/chunk-P3RQ5UJE.cjs +689 -0
  47. package/dist/chunk-P3RQ5UJE.cjs.map +1 -0
  48. package/dist/chunk-P6ODPZ4W.js +256 -0
  49. package/dist/chunk-P6ODPZ4W.js.map +1 -0
  50. package/dist/chunk-PGNZKFQS.js +685 -0
  51. package/dist/chunk-PGNZKFQS.js.map +1 -0
  52. package/dist/chunk-PL4JB3BF.cjs +1 -0
  53. package/dist/chunk-PL4JB3BF.cjs.map +1 -0
  54. package/dist/{chunk-GVSMRPHB.cjs → chunk-SBCZ6RN5.cjs} +1568 -104
  55. package/dist/chunk-SBCZ6RN5.cjs.map +1 -0
  56. package/dist/{chunk-CL37JGFW.cjs → chunk-SML64VJG.cjs} +4 -4
  57. package/dist/{chunk-CL37JGFW.cjs.map → chunk-SML64VJG.cjs.map} +1 -1
  58. package/dist/chunk-TNNJXF46.cjs +115 -0
  59. package/dist/chunk-TNNJXF46.cjs.map +1 -0
  60. package/dist/chunk-U5HZSFCS.js +131 -0
  61. package/dist/chunk-U5HZSFCS.js.map +1 -0
  62. package/dist/{chunk-K3R5NG2D.js → chunk-U5KWZU4X.js} +251 -128
  63. package/dist/chunk-U5KWZU4X.js.map +1 -0
  64. package/dist/chunk-XNORY7M6.cjs +685 -0
  65. package/dist/chunk-XNORY7M6.cjs.map +1 -0
  66. package/dist/commands/index.d.cts +5 -353
  67. package/dist/commands/index.d.ts +5 -353
  68. package/dist/comment-store-BEMgVlAA.d.cts +135 -0
  69. package/dist/comment-store-BEMgVlAA.d.ts +135 -0
  70. package/dist/compare/index.cjs +15 -0
  71. package/dist/compare/index.cjs.map +1 -0
  72. package/dist/compare/index.d.cts +58 -0
  73. package/dist/compare/index.d.ts +58 -0
  74. package/dist/compare/index.js +15 -0
  75. package/dist/compare/index.js.map +1 -0
  76. package/dist/{controller-pePCJLT1.d.cts → controller-BhLLAoi8.d.cts} +45 -4
  77. package/dist/{controller-pePCJLT1.d.ts → controller-BhLLAoi8.d.ts} +45 -4
  78. package/dist/documents-BQjzJNe2.d.ts +76 -0
  79. package/dist/documents-KRTPhvst.d.cts +76 -0
  80. package/dist/extensions/index.cjs +53 -5
  81. package/dist/extensions/index.cjs.map +1 -1
  82. package/dist/extensions/index.d.cts +7 -3
  83. package/dist/extensions/index.d.ts +7 -3
  84. package/dist/extensions/index.js +52 -4
  85. package/dist/generation/index.cjs +1373 -0
  86. package/dist/generation/index.cjs.map +1 -0
  87. package/dist/generation/index.d.cts +554 -0
  88. package/dist/generation/index.d.ts +554 -0
  89. package/dist/generation/index.js +1373 -0
  90. package/dist/generation/index.js.map +1 -0
  91. package/dist/grammar/index.cjs +48 -3
  92. package/dist/grammar/index.cjs.map +1 -1
  93. package/dist/grammar/index.d.cts +322 -100
  94. package/dist/grammar/index.d.ts +322 -100
  95. package/dist/grammar/index.js +54 -9
  96. package/dist/image-editor/index.cjs +1831 -30
  97. package/dist/image-editor/index.cjs.map +1 -1
  98. package/dist/image-editor/index.d.cts +590 -3
  99. package/dist/image-editor/index.d.ts +590 -3
  100. package/dist/image-editor/index.js +1807 -6
  101. package/dist/image-editor/index.js.map +1 -1
  102. package/dist/{index-CCr_z9kF.d.cts → index-BhJBSm2d.d.cts} +370 -4
  103. package/dist/{index-Ck6ajwXh.d.ts → index-fJrlkJCd.d.ts} +370 -4
  104. package/dist/index.cjs +162 -25
  105. package/dist/index.cjs.map +1 -1
  106. package/dist/index.d.cts +14 -8
  107. package/dist/index.d.ts +14 -8
  108. package/dist/index.js +174 -37
  109. package/dist/index.js.map +1 -1
  110. package/dist/migrate-iTlm3a8h.d.cts +112 -0
  111. package/dist/migrate-iTlm3a8h.d.ts +112 -0
  112. package/dist/persistence/index.cjs +676 -0
  113. package/dist/persistence/index.cjs.map +1 -0
  114. package/dist/persistence/index.d.cts +347 -0
  115. package/dist/persistence/index.d.ts +347 -0
  116. package/dist/persistence/index.js +676 -0
  117. package/dist/persistence/index.js.map +1 -0
  118. package/dist/{registry-D5-R90p0.d.cts → registry-BDe-vlv3.d.ts} +2 -40
  119. package/dist/registry-D32LpIc4.d.cts +354 -0
  120. package/dist/{registry-D5-R90p0.d.ts → registry-DnzpgY27.d.cts} +2 -40
  121. package/dist/registry-evKTP4ls.d.ts +354 -0
  122. package/dist/schema-DYDGdYL9.d.cts +41 -0
  123. package/dist/schema-DYDGdYL9.d.ts +41 -0
  124. package/dist/serializers/index.cjs +4 -3
  125. package/dist/serializers/index.cjs.map +1 -1
  126. package/dist/serializers/index.d.cts +2 -1
  127. package/dist/serializers/index.d.ts +2 -1
  128. package/dist/serializers/index.js +3 -2
  129. package/dist/sourcemap-C8AH3MBQ.d.cts +91 -0
  130. package/dist/sourcemap-DA1Evhrv.d.ts +91 -0
  131. package/dist/spreadsheet/index.cjs +37 -3
  132. package/dist/spreadsheet/index.cjs.map +1 -1
  133. package/dist/spreadsheet/index.d.cts +188 -17
  134. package/dist/spreadsheet/index.d.ts +188 -17
  135. package/dist/spreadsheet/index.js +43 -9
  136. package/dist/{tokens-CyLZmIei.d.cts → tokens-D7yXvUU6.d.cts} +15 -2
  137. package/dist/{tokens-CyLZmIei.d.ts → tokens-D7yXvUU6.d.ts} +15 -2
  138. package/dist/{track-changes-BSF58RK0.d.ts → track-changes-BK5sVf4_.d.cts} +18 -136
  139. package/dist/{track-changes-BSF58RK0.d.cts → track-changes-CDjCrwKe.d.ts} +18 -136
  140. package/package.json +16 -1
  141. package/dist/chunk-4SUNJZWB.cjs.map +0 -1
  142. package/dist/chunk-AA4ZEVCC.cjs.map +0 -1
  143. package/dist/chunk-AXV2ZW34.cjs +0 -118
  144. package/dist/chunk-AXV2ZW34.cjs.map +0 -1
  145. package/dist/chunk-B2ZRLN4S.js +0 -118
  146. package/dist/chunk-B2ZRLN4S.js.map +0 -1
  147. package/dist/chunk-GVSMRPHB.cjs.map +0 -1
  148. package/dist/chunk-K3R5NG2D.js.map +0 -1
  149. package/dist/chunk-MJZBNWG7.js.map +0 -1
  150. package/dist/chunk-OYXSKQFR.js.map +0 -1
  151. package/dist/chunk-QBJ22YZR.js.map +0 -1
  152. package/dist/chunk-QGHGJ56O.js.map +0 -1
  153. package/dist/chunk-RIKBJLS2.cjs.map +0 -1
  154. package/dist/chunk-XDMXXC4Z.cjs.map +0 -1
  155. /package/dist/{chunk-JJDLPEWL.js.map → chunk-3LV6RRPH.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2;// src/spreadsheet/formula/lexer.ts
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3;// src/spreadsheet/formula/lexer.ts
2
2
  function tokenizeFormula(formula) {
3
3
  const tokens = [];
4
4
  let input = formula.trim();
@@ -982,209 +982,1343 @@ function parseCriteria(criterion) {
982
982
  };
983
983
  }
984
984
 
985
- // src/spreadsheet/formula/format.ts
986
- function formatCellDisplay(cell) {
987
- if (!cell) return "";
988
- if (cell.error) return cell.error;
989
- const { value, numberFormat } = cell;
990
- if (numberFormat && value !== "" && value !== null && value !== void 0 && typeof value !== "boolean") {
991
- if (/^\[h\]/i.test(numberFormat) && typeof value === "number") return formatElapsedHours(value);
992
- if (numberFormat === "# ?/?" && typeof value === "number") return formatFraction(value);
993
- const formatted = formatValueWithCode(value, numberFormat);
994
- if (formatted !== null) return formatted;
995
- }
996
- return toText(value);
997
- }
998
- function formatFraction(value) {
999
- const sign = value < 0 ? "-" : "";
1000
- const abs = Math.abs(value);
1001
- let whole = Math.floor(abs);
1002
- const frac = abs - whole;
1003
- let best = { num: 0, den: 1, err: frac };
1004
- for (let den = 2; den <= 9; den++) {
1005
- const num = Math.round(frac * den);
1006
- const err = Math.abs(frac - num / den);
1007
- if (err < best.err - 1e-12) best = { num, den, err };
1008
- }
1009
- if (best.num === best.den) {
1010
- whole += 1;
1011
- best = { num: 0, den: 1, err: 0 };
1012
- }
1013
- if (best.num === 0) return `${sign}${whole}`;
1014
- return `${sign}${whole === 0 ? "" : `${whole} `}${best.num}/${best.den}`;
1015
- }
1016
- function formatElapsedHours(days) {
1017
- const total = Math.round(Math.abs(days) * 86400);
1018
- const p = (n) => String(n).padStart(2, "0");
1019
- const text = `${Math.floor(total / 3600)}:${p(Math.floor(total / 60) % 60)}:${p(total % 60)}`;
1020
- return days < 0 ? `-${text}` : text;
1021
- }
1022
- function formatValueWithCode(value, format) {
1023
- if (isDateFormat(format)) {
1024
- const date = toDate(value);
1025
- return date ? formatDate(date, format) : null;
1026
- }
1027
- const num = typeof value === "boolean" ? null : numericValue(value);
1028
- return num === null ? toText(value) : formatNumber(num, format);
1029
- }
1030
- function tokenize(format) {
1031
- const out = [];
1032
- const push = (literal, text) => {
1033
- const last = out[out.length - 1];
1034
- if (last && last.literal === literal) last.text += text;
1035
- else out.push({ literal, text });
1036
- };
1037
- for (let i = 0; i < format.length; i++) {
1038
- const char = format[i];
1039
- if (char === '"') {
1040
- const end = format.indexOf('"', i + 1);
1041
- const stop = end === -1 ? format.length : end;
1042
- push(true, format.slice(i + 1, stop));
1043
- i = stop;
1044
- } else if (char === "\\" && i + 1 < format.length) {
1045
- push(true, format[++i]);
985
+ // src/spreadsheet/numfmt/decimal.ts
986
+ var MAX_DECIMALS = 400;
987
+ function significantDigits(a, n) {
988
+ const s = a.toExponential(Math.max(0, Math.min(100, n - 1)));
989
+ const e = s.indexOf("e");
990
+ const digits = [];
991
+ for (let i = 0; i < e; i++) {
992
+ const c = s.charCodeAt(i);
993
+ if (c >= 48 && c <= 57) digits.push(c - 48);
994
+ }
995
+ return { digits, exp: Number(s.slice(e + 1)) };
996
+ }
997
+ function exactDigits(a) {
998
+ const view = new DataView(new ArrayBuffer(8));
999
+ view.setFloat64(0, a);
1000
+ const hi = view.getUint32(0);
1001
+ const lo = view.getUint32(4);
1002
+ const biased = hi >>> 20 & 2047;
1003
+ let mantissa = BigInt(hi & 1048575) << 32n | BigInt(lo);
1004
+ let exp2;
1005
+ if (biased === 0) {
1006
+ exp2 = -1074;
1007
+ } else {
1008
+ mantissa |= 1n << 52n;
1009
+ exp2 = biased - 1075;
1010
+ }
1011
+ const digits = exp2 >= 0 ? (mantissa << BigInt(exp2)).toString() : (mantissa * 5n ** BigInt(-exp2)).toString();
1012
+ return digits.replace(/0+$/, "");
1013
+ }
1014
+ function isExactTie(a) {
1015
+ const isTie = (ds) => ds.length >= 16 && ds[15] === "5" && /^0*$/.test(ds.slice(16));
1016
+ return isTie(significantDigits(a, 30).digits.join("")) && isTie(exactDigits(a).padEnd(16, "0"));
1017
+ }
1018
+ function decimalDigits(a) {
1019
+ if (!Number.isFinite(a) || a <= 0) return { digits: new Array(15).fill(0), exp: 0 };
1020
+ const { digits: d16, exp } = significantDigits(a, 16);
1021
+ const digits = d16.slice(0, 15);
1022
+ while (digits.length < 15) digits.push(0);
1023
+ const sixteenth = _nullishCoalesce(d16[15], () => ( 0));
1024
+ if (sixteenth <= 4) return { digits, exp };
1025
+ if (sixteenth === 5) {
1026
+ if (isExactTie(a)) return { digits, exp };
1027
+ const r = significantDigits(a, 15);
1028
+ while (r.digits.length < 15) r.digits.push(0);
1029
+ return r;
1030
+ }
1031
+ let e = exp;
1032
+ let carry = true;
1033
+ for (let i = 14; i >= 0; i--) {
1034
+ if (digits[i] === 9) {
1035
+ digits[i] = 0;
1046
1036
  } else {
1047
- push(false, char);
1037
+ digits[i] += 1;
1038
+ carry = false;
1039
+ break;
1040
+ }
1041
+ }
1042
+ if (carry) {
1043
+ digits.fill(0);
1044
+ digits[0] = 1;
1045
+ e += 1;
1046
+ }
1047
+ return { digits, exp: e };
1048
+ }
1049
+ function fixedFromDigits(digits, exp, decimals) {
1050
+ const decimalsCalc = Math.min(decimals, MAX_DECIMALS);
1051
+ const keep = exp + decimalsCalc + 1;
1052
+ let m;
1053
+ if (keep <= 0) {
1054
+ m = keep === 0 && (_nullishCoalesce(digits[0], () => ( 0))) >= 5 ? [1] : [];
1055
+ } else if (keep >= digits.length) {
1056
+ m = digits.slice();
1057
+ while (m.length < keep) m.push(0);
1058
+ } else {
1059
+ m = digits.slice(0, keep);
1060
+ if ((_nullishCoalesce(digits[keep], () => ( 0))) >= 5) {
1061
+ let carry = true;
1062
+ for (let i = m.length - 1; i >= 0; i--) {
1063
+ if (m[i] === 9) {
1064
+ m[i] = 0;
1065
+ } else {
1066
+ m[i] += 1;
1067
+ carry = false;
1068
+ break;
1069
+ }
1070
+ }
1071
+ if (carry) m.unshift(1);
1072
+ }
1073
+ }
1074
+ let lead = 0;
1075
+ while (lead < m.length && m[lead] === 0) lead++;
1076
+ m = m.slice(lead);
1077
+ const toS = (ds) => ds.join("");
1078
+ let int;
1079
+ let frac;
1080
+ if (m.length <= decimalsCalc) {
1081
+ int = "";
1082
+ frac = "0".repeat(decimalsCalc - m.length) + toS(m);
1083
+ } else {
1084
+ const split = m.length - decimalsCalc;
1085
+ int = toS(m.slice(0, split));
1086
+ frac = toS(m.slice(split));
1087
+ }
1088
+ if (decimals > decimalsCalc) frac += "0".repeat(decimals - decimalsCalc);
1089
+ return [int, frac];
1090
+ }
1091
+ function fixed(a, decimals) {
1092
+ if (!Number.isFinite(a) || a <= 0) return ["", "0".repeat(Math.min(decimals, MAX_DECIMALS * 4))];
1093
+ const { digits, exp } = decimalDigits(a);
1094
+ return fixedFromDigits(digits, exp, decimals);
1095
+ }
1096
+ var charCount = (s) => Array.from(s).length;
1097
+ function formatGeneralFit(n, maxChars) {
1098
+ if (!Number.isFinite(n)) return null;
1099
+ if (n === 0) return maxChars >= 1 ? "0" : null;
1100
+ const sign = n < 0 ? "-" : "";
1101
+ const { digits, exp: x } = decimalDigits(Math.abs(n));
1102
+ const intLen = sign.length + Math.max(x, 0) + 1;
1103
+ if (x >= -4 && intLen <= maxChars) {
1104
+ const avail = maxChars - intLen;
1105
+ let decimals = avail >= 2 ? avail - 1 : 0;
1106
+ for (; ; ) {
1107
+ const [i, f0] = fixedFromDigits(digits, x, decimals);
1108
+ const f = f0.replace(/0+$/, "");
1109
+ if (i === "" && f === "") break;
1110
+ let s = sign + (i === "" ? "0" : i);
1111
+ if (f !== "") s += `.${f}`;
1112
+ if (charCount(s) <= maxChars) return s;
1113
+ if (decimals === 0) break;
1114
+ decimals -= 1;
1115
+ }
1116
+ }
1117
+ for (let md = Math.min(maxChars, 14); md >= 0; md--) {
1118
+ let e = x;
1119
+ let [mi, mf] = fixedFromDigits(digits, 0, md);
1120
+ if (mi.length > 1) {
1121
+ e += 1;
1122
+ [mi, mf] = fixedFromDigits(digits, -1, md);
1123
+ }
1124
+ mf = mf.replace(/0+$/, "");
1125
+ let s = sign + (mi === "" ? "0" : mi);
1126
+ if (mf !== "") s += `.${mf}`;
1127
+ s += `E${e < 0 ? "-" : "+"}${String(Math.abs(e)).padStart(2, "0")}`;
1128
+ if (charCount(s) <= maxChars) return s;
1129
+ }
1130
+ return null;
1131
+ }
1132
+
1133
+ // src/spreadsheet/numfmt/builtin.ts
1134
+ var BUILTINS = [
1135
+ [0, "General"],
1136
+ [1, "0"],
1137
+ [2, "0.00"],
1138
+ [3, "#,##0"],
1139
+ [4, "#,##0.00"],
1140
+ [5, '"$"#,##0_);\\("$"#,##0\\)'],
1141
+ [6, '"$"#,##0_);[Red]\\("$"#,##0\\)'],
1142
+ [7, '"$"#,##0.00_);\\("$"#,##0.00\\)'],
1143
+ [8, '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)'],
1144
+ [9, "0%"],
1145
+ [10, "0.00%"],
1146
+ [11, "0.00E+00"],
1147
+ [12, "# ?/?"],
1148
+ [13, "# ??/??"],
1149
+ [14, "m/d/yyyy"],
1150
+ [15, "d-mmm-yy"],
1151
+ [16, "d-mmm"],
1152
+ [17, "mmm-yy"],
1153
+ [18, "h:mm AM/PM"],
1154
+ [19, "h:mm:ss AM/PM"],
1155
+ [20, "h:mm"],
1156
+ [21, "h:mm:ss"],
1157
+ [22, "m/d/yyyy h:mm"],
1158
+ [37, "#,##0 ;(#,##0)"],
1159
+ [38, "#,##0 ;[Red](#,##0)"],
1160
+ [39, "#,##0.00;(#,##0.00)"],
1161
+ [40, "#,##0.00;[Red](#,##0.00)"],
1162
+ [41, '_(* #,##0_);_(* \\(#,##0\\);_(* "-"_);_(@_)'],
1163
+ [42, '_("$"* #,##0_);_("$"* \\(#,##0\\);_("$"* "-"_);_(@_)'],
1164
+ [43, '_(* #,##0.00_);_(* \\(#,##0.00\\);_(* "-"??_);_(@_)'],
1165
+ [44, '_("$"* #,##0.00_);_("$"* \\(#,##0.00\\);_("$"* "-"??_);_(@_)'],
1166
+ [45, "mm:ss"],
1167
+ [46, "[h]:mm:ss"],
1168
+ [47, "mmss.0"],
1169
+ [48, "##0.0E+0"],
1170
+ [49, "@"]
1171
+ ];
1172
+ function builtinNumberFormat(id) {
1173
+ return _optionalChain([BUILTINS, 'access', _5 => _5.find, 'call', _6 => _6(([i]) => i === id), 'optionalAccess', _7 => _7[1]]);
1174
+ }
1175
+ function builtinNumberFormatId(code) {
1176
+ const exact = BUILTINS.find(([, c]) => c === code);
1177
+ if (exact) return exact[0];
1178
+ const norm = (s) => s.replace(/\\/g, "").toLowerCase();
1179
+ const n = norm(code);
1180
+ return _optionalChain([BUILTINS, 'access', _8 => _8.find, 'call', _9 => _9(([, c]) => norm(c) === n), 'optionalAccess', _10 => _10[0]]);
1181
+ }
1182
+
1183
+ // src/spreadsheet/numfmt/parse.ts
1184
+ var MAX_SECTIONS = 4;
1185
+ var isCalendarPart = (d) => d.k === "year" || d.k === "month" || d.k === "day";
1186
+ function literalText(tok) {
1187
+ switch (tok.t) {
1188
+ case "lit":
1189
+ case "denom":
1190
+ return tok.s;
1191
+ case "digit":
1192
+ return tok.c;
1193
+ case "point":
1194
+ return ".";
1195
+ case "comma":
1196
+ return ",";
1197
+ case "percent":
1198
+ return "%";
1199
+ case "exp":
1200
+ return `${tok.upper ? "E" : "e"}${tok.plus ? "+" : "-"}`;
1201
+ case "slash":
1202
+ return "/";
1203
+ default:
1204
+ return "";
1205
+ }
1206
+ }
1207
+ function testCond(c, v) {
1208
+ switch (c.op) {
1209
+ case "=":
1210
+ return v === c.value;
1211
+ case "<>":
1212
+ return v !== c.value;
1213
+ case "<":
1214
+ return v < c.value;
1215
+ case "<=":
1216
+ return v <= c.value;
1217
+ case ">":
1218
+ return v > c.value;
1219
+ case ">=":
1220
+ return v >= c.value;
1221
+ }
1222
+ }
1223
+ var isDigitTok = (t, c) => _optionalChain([t, 'optionalAccess', _11 => _11.t]) === "digit" && (c === void 0 || t.c === c);
1224
+ function splitSections(code) {
1225
+ const cs = Array.from(code);
1226
+ const lastClose = cs.lastIndexOf("]");
1227
+ const out = [""];
1228
+ let quoted = false;
1229
+ let escape = false;
1230
+ let i = 0;
1231
+ while (i < cs.length) {
1232
+ const c = cs[i];
1233
+ i += 1;
1234
+ const cur = out.length - 1;
1235
+ if (escape) {
1236
+ out[cur] += c;
1237
+ escape = false;
1238
+ continue;
1239
+ }
1240
+ if (c === '"') {
1241
+ quoted = !quoted;
1242
+ out[cur] += c;
1243
+ } else if ((c === "\\" || c === "_" || c === "*") && !quoted) {
1244
+ escape = true;
1245
+ out[cur] += c;
1246
+ } else if (c === "[" && !quoted && lastClose >= i) {
1247
+ let s = c;
1248
+ while (i < cs.length) {
1249
+ const d = cs[i];
1250
+ i += 1;
1251
+ s += d;
1252
+ if (d === "]") break;
1253
+ }
1254
+ out[cur] += s;
1255
+ } else if (c === ";" && !quoted) {
1256
+ if (out.length >= MAX_SECTIONS) break;
1257
+ out.push("");
1258
+ } else {
1259
+ out[cur] += c;
1048
1260
  }
1049
1261
  }
1050
1262
  return out;
1051
1263
  }
1052
- var codeText = (format) => tokenize(format).filter((t) => !t.literal).map((t) => t.text).join("");
1053
- function isDateFormat(format) {
1054
- const code = codeText(format);
1055
- if (/[0#?]/.test(code)) return false;
1056
- return /[ydhs]|m/i.test(code);
1057
- }
1058
- function formatNumber(num, format) {
1059
- const sections = splitSections(format);
1060
- let section = sections[0];
1061
- let value = num;
1062
- let sign = num < 0 ? "-" : "";
1063
- if (num < 0 && sections.length > 1) {
1064
- section = sections[1];
1065
- value = Math.abs(num);
1066
- sign = "";
1067
- } else if (num === 0 && sections.length > 2) {
1068
- section = sections[2];
1069
- }
1070
- let prefix = "";
1071
- let suffix = "";
1072
- let pattern = "";
1073
- for (const token of tokenize(section)) {
1074
- if (token.literal) {
1075
- if (pattern) suffix += token.text;
1076
- else prefix += token.text;
1264
+ var lowerAscii = (c) => c >= "A" && c <= "Z" ? c.toLowerCase() : c;
1265
+ function startsWithCi(cs, i, pat) {
1266
+ for (let k = 0; k < pat.length; k++) {
1267
+ const c = cs[i + k];
1268
+ if (c === void 0 || lowerAscii(c) !== pat[k]) return false;
1269
+ }
1270
+ return true;
1271
+ }
1272
+ function pushLit(toks, s) {
1273
+ if (s === "") return;
1274
+ const last = toks[toks.length - 1];
1275
+ if (_optionalChain([last, 'optionalAccess', _12 => _12.t]) === "lit") last.s += s;
1276
+ else toks.push({ t: "lit", s });
1277
+ }
1278
+ var CURRENCY_CHARS = /* @__PURE__ */ new Set(["$", "\u20AC", "\xA3", "\xA5", "\u20B9", "\u20A9", "\u20BD", "\xA2", "\u20AA", "\u20AB", "\u0E3F"]);
1279
+ var isCurrencyChar = (c) => CURRENCY_CHARS.has(c);
1280
+ var NAMED_COLORS = /* @__PURE__ */ new Set(["black", "blue", "cyan", "green", "magenta", "red", "white", "yellow"]);
1281
+ function parseColor(lc) {
1282
+ if (NAMED_COLORS.has(lc)) return lc;
1283
+ if (!lc.startsWith("color")) return void 0;
1284
+ const rest = lc.slice(5).trim();
1285
+ if (!/^\+?\d{1,3}$/.test(rest)) return void 0;
1286
+ const n = Number(rest);
1287
+ return n >= 1 && n <= 56 ? `color${n}` : void 0;
1288
+ }
1289
+ function parseCond(s) {
1290
+ const t = s.trim();
1291
+ let op;
1292
+ let rest;
1293
+ if (t.startsWith("<=")) [op, rest] = ["<=", t.slice(2)];
1294
+ else if (t.startsWith(">=")) [op, rest] = [">=", t.slice(2)];
1295
+ else if (t.startsWith("<>")) [op, rest] = ["<>", t.slice(2)];
1296
+ else if (t.startsWith("<")) [op, rest] = ["<", t.slice(1)];
1297
+ else if (t.startsWith(">")) [op, rest] = [">", t.slice(1)];
1298
+ else if (t.startsWith("=")) [op, rest] = ["=", t.slice(1)];
1299
+ else return void 0;
1300
+ const r = rest.trim();
1301
+ if (!/^[+-]?(\d+\.?\d*|\.\d+)(e[+-]?\d+)?$/i.test(r)) return void 0;
1302
+ const value = Number(r);
1303
+ return Number.isFinite(value) ? { op, value } : void 0;
1304
+ }
1305
+ function bracket(raw, content) {
1306
+ const lc = content.trim().toLowerCase();
1307
+ const color = parseColor(lc);
1308
+ if (color) {
1309
+ raw.color = color;
1310
+ return;
1311
+ }
1312
+ if (lc.startsWith("<") || lc.startsWith(">") || lc.startsWith("=")) {
1313
+ const c = parseCond(lc);
1314
+ if (c) raw.cond = c;
1315
+ return;
1316
+ }
1317
+ if (content.startsWith("$")) {
1318
+ const sym = content.slice(1).split("-")[0];
1319
+ if (sym !== "") {
1320
+ raw.currency = true;
1321
+ pushLit(raw.toks, sym);
1322
+ }
1323
+ return;
1324
+ }
1325
+ const first = lc[0];
1326
+ if ((first === "h" || first === "m" || first === "s") && Array.from(lc).every((c) => c === first)) {
1327
+ const n = Math.min(Array.from(lc).length, 255);
1328
+ raw.toks.push({ t: "date", d: { k: first === "h" ? "eh" : first === "m" ? "em" : "es", n } });
1329
+ }
1330
+ }
1331
+ function tokenize(src) {
1332
+ const cs = Array.from(src);
1333
+ const raw = { toks: [], currency: false };
1334
+ const toks = raw.toks;
1335
+ const lastClose = cs.lastIndexOf("]");
1336
+ let i = 0;
1337
+ while (i < cs.length) {
1338
+ const c = cs[i];
1339
+ if (c === '"') {
1340
+ let s = "";
1341
+ i += 1;
1342
+ while (i < cs.length) {
1343
+ const d = cs[i];
1344
+ i += 1;
1345
+ if (d === '"') break;
1346
+ s += d;
1347
+ }
1348
+ if (Array.from(s).some(isCurrencyChar)) raw.currency = true;
1349
+ pushLit(toks, s);
1350
+ continue;
1351
+ }
1352
+ if (c === "\\") {
1353
+ const d = cs[i + 1];
1354
+ if (d !== void 0) {
1355
+ if (isCurrencyChar(d)) raw.currency = true;
1356
+ pushLit(toks, d);
1357
+ }
1358
+ i += 2;
1077
1359
  continue;
1078
1360
  }
1079
- for (let i = 0; i < token.text.length; i++) {
1080
- const char = token.text[i];
1081
- const isExponent = /e/i.test(char) && /[+-]/.test(_nullishCoalesce(token.text[i + 1], () => ( "")));
1082
- const isExponentSign = /[+-]/.test(char) && /e$/i.test(pattern);
1083
- if (/[0#?.,]/.test(char) || pattern && (isExponent || isExponentSign)) {
1084
- pattern += char;
1085
- } else if (pattern) {
1086
- suffix += char;
1361
+ if (c === "_") {
1362
+ if (cs[i + 1] !== void 0) pushLit(toks, " ");
1363
+ i += 2;
1364
+ continue;
1365
+ }
1366
+ if (c === "*") {
1367
+ const d = cs[i + 1];
1368
+ if (d !== void 0) toks.push({ t: "fill", c: d });
1369
+ i += 2;
1370
+ continue;
1371
+ }
1372
+ if (c === "[") {
1373
+ const close = lastClose > i ? cs.indexOf("]", i + 1) : -1;
1374
+ if (close !== -1) {
1375
+ bracket(raw, cs.slice(i + 1, close).join(""));
1376
+ i = close + 1;
1087
1377
  } else {
1088
- prefix += char;
1089
- }
1090
- }
1091
- }
1092
- const percents = (prefix + suffix).split("%").length - 1;
1093
- value = Math.abs(value) * Math.pow(100, percents);
1094
- if (!pattern) return `${sign}${prefix}${suffix}`;
1095
- const expMatch = /^([^Ee]*)[Ee]([+-])(0+)$/.exec(pattern);
1096
- if (expMatch) {
1097
- const [, mantissa, expSign, expDigits] = expMatch;
1098
- const decimals = (_nullishCoalesce(mantissa.split(".")[1], () => ( ""))).length;
1099
- const [m, e] = value.toExponential(decimals).split("e");
1100
- const exponent = Number(e);
1101
- const expText = String(Math.abs(exponent)).padStart(expDigits.length, "0");
1102
- const shownSign = exponent < 0 ? "-" : expSign === "+" ? "+" : "";
1103
- return `${sign}${prefix}${m}E${shownSign}${expText}${suffix}`;
1104
- }
1105
- const [intPattern, decPattern = ""] = pattern.split(".");
1106
- const maxDecimals = (_nullishCoalesce(decPattern.match(/[0#?]/g), () => ( []))).length;
1107
- const minDecimals = (_nullishCoalesce(decPattern.match(/0/g), () => ( []))).length;
1108
- const minInt = (_nullishCoalesce(intPattern.match(/0/g), () => ( []))).length;
1109
- const grouping = intPattern.includes(",");
1110
- const rounded = roundHalfAwayFromZero(value, maxDecimals);
1111
- let [intPart, decPart = ""] = rounded.toFixed(maxDecimals).split(".");
1112
- while (decPart.length > minDecimals && decPart.endsWith("0")) decPart = decPart.slice(0, -1);
1113
- if (intPart === "0" && minInt === 0) intPart = "";
1114
- intPart = intPart.padStart(minInt, "0");
1115
- if (grouping) intPart = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
1116
- const showSign = sign && /[1-9]/.test(intPart + decPart) ? sign : "";
1117
- return `${showSign}${prefix}${intPart}${decPart ? `.${decPart}` : ""}${suffix}`;
1118
- }
1119
- function splitSections(format) {
1120
- const sections = [""];
1121
- let quoted = false;
1122
- for (let i = 0; i < format.length; i++) {
1123
- const char = format[i];
1124
- if (char === '"') quoted = !quoted;
1125
- if (char === "\\" && i + 1 < format.length) {
1126
- sections[sections.length - 1] += char + format[++i];
1378
+ pushLit(toks, "[");
1379
+ i += 1;
1380
+ }
1127
1381
  continue;
1128
1382
  }
1129
- if (char === ";" && !quoted) sections.push("");
1130
- else sections[sections.length - 1] += char;
1383
+ if (c === "0" || c === "#" || c === "?") toks.push({ t: "digit", c });
1384
+ else if (c === ".") toks.push({ t: "point" });
1385
+ else if (c === ",") toks.push({ t: "comma" });
1386
+ else if (c === "%") toks.push({ t: "percent" });
1387
+ else if (c === "@") toks.push({ t: "at" });
1388
+ else if (c === "/") {
1389
+ toks.push({ t: "slash" });
1390
+ i += 1;
1391
+ if (cs[i] !== void 0 && cs[i] >= "1" && cs[i] <= "9") {
1392
+ let s = "";
1393
+ while (i < cs.length && cs[i] >= "0" && cs[i] <= "9") {
1394
+ s += cs[i];
1395
+ i += 1;
1396
+ }
1397
+ toks.push({ t: "denom", s });
1398
+ }
1399
+ continue;
1400
+ } else if ((c === "e" || c === "E") && (cs[i + 1] === "+" || cs[i + 1] === "-")) {
1401
+ toks.push({ t: "exp", upper: c === "E", plus: cs[i + 1] === "+" });
1402
+ i += 2;
1403
+ continue;
1404
+ } else if ((c === "G" || c === "g") && startsWithCi(cs, i, "general")) {
1405
+ toks.push({ t: "general" });
1406
+ i += 7;
1407
+ continue;
1408
+ } else if ((c === "A" || c === "a") && startsWithCi(cs, i, "am/pm")) {
1409
+ toks.push({ t: "date", d: { k: "ampm" } });
1410
+ i += 5;
1411
+ continue;
1412
+ } else if ((c === "A" || c === "a") && startsWithCi(cs, i, "a/p")) {
1413
+ toks.push({ t: "date", d: { k: "ap", a: c, p: _nullishCoalesce(cs[i + 2], () => ( "P")) } });
1414
+ i += 3;
1415
+ continue;
1416
+ } else if ("yYmMdDhHsSeE".includes(c)) {
1417
+ const lc = lowerAscii(c);
1418
+ let n = 0;
1419
+ while (cs[i + n] !== void 0 && lowerAscii(cs[i + n]) === lc) n += 1;
1420
+ const n8 = Math.min(n, 255);
1421
+ const d = lc === "y" ? { k: "year", n: n8 } : lc === "e" ? { k: "year", n: 4 } : lc === "m" ? { k: "month", n: n8 } : lc === "d" ? { k: "day", n: n8 } : lc === "h" ? { k: "hour", n: n8 } : { k: "second", n: n8 };
1422
+ toks.push({ t: "date", d });
1423
+ i += Math.max(n, 1);
1424
+ continue;
1425
+ } else {
1426
+ if (isCurrencyChar(c)) raw.currency = true;
1427
+ pushLit(toks, c);
1428
+ }
1429
+ i += 1;
1131
1430
  }
1132
- return sections;
1431
+ return raw;
1133
1432
  }
1433
+ var datePartOf = (t) => _optionalChain([t, 'optionalAccess', _13 => _13.t]) === "date" ? t.d : void 0;
1434
+ function analyze(raw) {
1435
+ const toks = raw.toks;
1436
+ const isDate = toks.some((t) => t.t === "date");
1437
+ const hasGeneral = toks.some((t) => t.t === "general");
1438
+ const sec = {
1439
+ toks: [],
1440
+ color: raw.color,
1441
+ cond: raw.cond,
1442
+ kind: "number",
1443
+ thousands: false,
1444
+ scale: 0,
1445
+ percent: 0,
1446
+ hasAt: toks.some((t) => t.t === "at"),
1447
+ hasDigits: false,
1448
+ exp: false,
1449
+ fraction: false,
1450
+ currency: raw.currency,
1451
+ fill: toks.some((t) => t.t === "fill")
1452
+ };
1453
+ if (isDate) {
1454
+ sec.kind = "date";
1455
+ const prevPart = [];
1456
+ let last;
1457
+ for (let i2 = 0; i2 < toks.length; i2++) {
1458
+ prevPart.push(last);
1459
+ const d = datePartOf(toks[i2]);
1460
+ if (d) last = d;
1461
+ }
1462
+ const nextPart = new Array(toks.length);
1463
+ let next;
1464
+ for (let i2 = toks.length - 1; i2 >= 0; i2--) {
1465
+ nextPart[i2] = next;
1466
+ const d = datePartOf(toks[i2]);
1467
+ if (d) next = d;
1468
+ }
1469
+ for (let i2 = 0; i2 < toks.length; i2++) {
1470
+ const t = toks[i2];
1471
+ if (t.t !== "date" || t.d.k !== "month" || t.d.n > 2) continue;
1472
+ const prev = prevPart[i2];
1473
+ const nxt = nextPart[i2];
1474
+ const afterH = _optionalChain([prev, 'optionalAccess', _14 => _14.k]) === "hour" || _optionalChain([prev, 'optionalAccess', _15 => _15.k]) === "eh";
1475
+ const beforeS = _optionalChain([nxt, 'optionalAccess', _16 => _16.k]) === "second" || _optionalChain([nxt, 'optionalAccess', _17 => _17.k]) === "es";
1476
+ if (afterH || beforeS) toks[i2] = { t: "date", d: { k: "minute", n: t.d.n } };
1477
+ }
1478
+ const out2 = [];
1479
+ let i = 0;
1480
+ while (i < toks.length) {
1481
+ const t = toks[i];
1482
+ if (t.t === "point" && isDigitTok(toks[i + 1], "0")) {
1483
+ let n = 0;
1484
+ while (isDigitTok(toks[i + 1 + n], "0")) n += 1;
1485
+ out2.push({ t: "date", d: { k: "subsec", n: Math.min(n, 255) } });
1486
+ i += 1 + n;
1487
+ continue;
1488
+ }
1489
+ if (t.t === "date" || t.t === "fill") out2.push(t);
1490
+ else pushLit(out2, literalText(t));
1491
+ i += 1;
1492
+ }
1493
+ sec.toks = out2;
1494
+ return sec;
1495
+ }
1496
+ if (hasGeneral) {
1497
+ sec.kind = "general";
1498
+ const out2 = [];
1499
+ for (const t of toks) {
1500
+ if (t.t === "general" || t.t === "fill") out2.push(t);
1501
+ else pushLit(out2, literalText(t));
1502
+ }
1503
+ sec.toks = out2;
1504
+ return sec;
1505
+ }
1506
+ sec.hasDigits = toks.some((t) => t.t === "digit");
1507
+ if (sec.hasAt && !sec.hasDigits) {
1508
+ sec.kind = "text";
1509
+ const out2 = [];
1510
+ for (const t of toks) {
1511
+ if (t.t === "at" || t.t === "fill") out2.push(t);
1512
+ else pushLit(out2, literalText(t));
1513
+ }
1514
+ sec.toks = out2;
1515
+ return sec;
1516
+ }
1517
+ let seenPoint = false;
1518
+ let seenExp = false;
1519
+ let seenDigit = false;
1520
+ let fractionSlash = false;
1521
+ const digitAfterCommas = new Array(toks.length).fill(false);
1522
+ const firstNonLitAfter = new Array(toks.length);
1523
+ let after = false;
1524
+ let nonLit;
1525
+ for (let j = toks.length - 1; j >= 0; j--) {
1526
+ digitAfterCommas[j] = after;
1527
+ firstNonLitAfter[j] = nonLit;
1528
+ const t = toks[j];
1529
+ if (t.t !== "comma") after = t.t === "digit";
1530
+ if (t.t !== "lit") nonLit = t;
1531
+ }
1532
+ let lastExp = -1;
1533
+ for (let j = toks.length - 1; j >= 0; j--) {
1534
+ if (toks[j].t === "exp") {
1535
+ lastExp = j;
1536
+ break;
1537
+ }
1538
+ }
1539
+ const firstDigit = toks.findIndex((t) => t.t === "digit");
1540
+ const scientific = firstDigit !== -1 && toks.slice(firstDigit).some((t) => t.t === "exp");
1541
+ for (let i = 0; i < toks.length; i++) {
1542
+ const t = toks[i];
1543
+ let replace;
1544
+ switch (t.t) {
1545
+ case "digit":
1546
+ seenDigit = true;
1547
+ break;
1548
+ case "point":
1549
+ if (seenPoint || seenExp) replace = { t: "lit", s: "." };
1550
+ else seenPoint = true;
1551
+ break;
1552
+ case "percent":
1553
+ sec.percent += 1;
1554
+ break;
1555
+ case "exp":
1556
+ if (seenExp || !seenDigit) replace = { t: "lit", s: literalText(t) };
1557
+ else {
1558
+ seenExp = true;
1559
+ sec.exp = true;
1560
+ }
1561
+ break;
1562
+ case "comma": {
1563
+ const nextDigit = digitAfterCommas[i];
1564
+ if (seenDigit && nextDigit && !seenPoint && !seenExp) {
1565
+ sec.thousands = true;
1566
+ replace = { t: "lit", s: "" };
1567
+ } else if (seenDigit && scientific) {
1568
+ replace = { t: "lit", s: "" };
1569
+ } else if (seenDigit && !nextDigit) {
1570
+ sec.scale += 1;
1571
+ replace = { t: "lit", s: "" };
1572
+ } else {
1573
+ replace = { t: "lit", s: "," };
1574
+ }
1575
+ break;
1576
+ }
1577
+ case "slash": {
1578
+ const nextOk = _optionalChain([toks, 'access', _18 => _18[i + 1], 'optionalAccess', _19 => _19.t]) === "denom" || _optionalChain([firstNonLitAfter, 'access', _20 => _20[i], 'optionalAccess', _21 => _21.t]) === "digit";
1579
+ const hasExp = seenExp || lastExp > i;
1580
+ if (!fractionSlash && seenDigit && nextOk && !seenPoint && !hasExp) {
1581
+ fractionSlash = true;
1582
+ sec.fraction = true;
1583
+ } else {
1584
+ replace = { t: "lit", s: "/" };
1585
+ }
1586
+ break;
1587
+ }
1588
+ case "denom":
1589
+ if (!(_optionalChain([toks, 'access', _22 => _22[i - 1], 'optionalAccess', _23 => _23.t]) === "slash" && sec.fraction)) replace = { t: "lit", s: t.s };
1590
+ break;
1591
+ default:
1592
+ break;
1593
+ }
1594
+ if (replace) toks[i] = replace;
1595
+ }
1596
+ if (sec.fraction) {
1597
+ for (let i = 0; i < toks.length; i++) if (toks[i].t === "point") toks[i] = { t: "lit", s: "." };
1598
+ }
1599
+ const out = [];
1600
+ for (const t of toks) {
1601
+ if (t.t === "lit") pushLit(out, t.s);
1602
+ else out.push(t);
1603
+ }
1604
+ sec.toks = out;
1605
+ return sec;
1606
+ }
1607
+ function parseSections(code) {
1608
+ return splitSections(code).map((s) => analyze(tokenize(s)));
1609
+ }
1610
+
1611
+ // src/spreadsheet/numfmt/render.ts
1612
+ var MAX_DATE_SERIAL = 2958465;
1134
1613
  var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
1135
- var DAYS = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
1136
- var pad3 = (n) => String(n).padStart(2, "0");
1137
- function formatDate(date, format) {
1138
- const parts = [];
1139
- for (const token of tokenize(format)) {
1140
- if (token.literal) {
1141
- parts.push(token);
1614
+ var WEEKDAYS = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
1615
+ var UNIX_1899_12_302 = -25569;
1616
+ function civilFromDays(z0) {
1617
+ const z = z0 + 719468;
1618
+ const era = Math.floor(z / 146097);
1619
+ const doe = z - era * 146097;
1620
+ const yoe = Math.floor((doe - Math.floor(doe / 1460) + Math.floor(doe / 36524) - Math.floor(doe / 146096)) / 365);
1621
+ const doy = doe - (365 * yoe + Math.floor(yoe / 4) - Math.floor(yoe / 100));
1622
+ const mp = Math.floor((5 * doy + 2) / 153);
1623
+ const d = doy - Math.floor((153 * mp + 2) / 5) + 1;
1624
+ const m = mp < 10 ? mp + 3 : mp - 9;
1625
+ return { y: yoe + era * 400 + (m <= 2 ? 1 : 0), m, d };
1626
+ }
1627
+ function dateFromSerial(day) {
1628
+ const weekday = ((day + 6) % 7 + 7) % 7;
1629
+ if (day === 60) return { year: 1900, month: 2, day: 29, weekday };
1630
+ if (day === 0) return { year: 1900, month: 1, day: 0, weekday };
1631
+ const real = day < 60 ? day + 1 : day;
1632
+ const { y, m, d } = civilFromDays(real + UNIX_1899_12_302);
1633
+ return { year: y, month: m, day: d, weekday };
1634
+ }
1635
+ var Out = (_class2 = class {constructor() { _class2.prototype.__init3.call(this);_class2.prototype.__init4.call(this); }
1636
+ __init3() {this.text = ""}
1637
+
1638
+ /** True when every digit shown is zero (a number section that rounded to zero). */
1639
+ __init4() {this.zero = false}
1640
+ push(s) {
1641
+ this.text += s;
1642
+ }
1643
+ setFill(c) {
1644
+ if (!this.fill) this.fill = { char: c, index: this.text.length };
1645
+ }
1646
+ prepend(s) {
1647
+ this.text = s + this.text;
1648
+ if (this.fill) this.fill.index += s.length;
1649
+ }
1650
+ }, _class2);
1651
+ function renderText(sec, text) {
1652
+ const out = new Out();
1653
+ for (const t of sec.toks) {
1654
+ if (t.t === "at") out.push(text);
1655
+ else if (t.t === "fill") out.setFill(t.c);
1656
+ else out.push(literalText(t));
1657
+ }
1658
+ return out;
1659
+ }
1660
+ function renderGeneral(sec, v, width) {
1661
+ const out = new Out();
1662
+ for (const t of sec.toks) {
1663
+ if (t.t === "general") out.push(_nullishCoalesce(formatGeneralFit(v, width), () => ( "#".repeat(Math.min(Math.max(width, 1), 11)))));
1664
+ else if (t.t === "fill") out.setFill(t.c);
1665
+ else out.push(literalText(t));
1666
+ }
1667
+ return out;
1668
+ }
1669
+ var padNum = (n, w) => w >= 2 ? String(n).padStart(Math.min(w, 20), "0") : String(n);
1670
+ function renderDate(sec, v) {
1671
+ if (!Number.isFinite(v) || v < 0 || v >= MAX_DATE_SERIAL + 1) return null;
1672
+ let subDigits = 0;
1673
+ for (const t of sec.toks) if (t.t === "date" && t.d.k === "subsec") subDigits = Math.max(subDigits, t.d.n);
1674
+ subDigits = Math.min(subDigits, 3);
1675
+ const unit = 10 ** (3 - subDigits);
1676
+ let day = Math.floor(v);
1677
+ let ms = Math.round((v - Math.floor(v)) * 864e5 / unit) * unit;
1678
+ if (ms >= 864e5) {
1679
+ ms -= 864e5;
1680
+ day += 1;
1681
+ }
1682
+ const totalMs = day * 864e5 + ms;
1683
+ const needsDate = sec.toks.some((t) => t.t === "date" && isCalendarPart(t.d));
1684
+ if (needsDate && day > MAX_DATE_SERIAL) return null;
1685
+ const dt = needsDate ? dateFromSerial(day) : dateFromSerial(0);
1686
+ const ampm = sec.toks.some((t) => t.t === "date" && (t.d.k === "ampm" || t.d.k === "ap"));
1687
+ const hour = Math.floor(ms / 36e5);
1688
+ const minute = Math.floor(ms / 6e4) % 60;
1689
+ const second = Math.floor(ms / 1e3) % 60;
1690
+ const milli = ms % 1e3;
1691
+ const monthName = _nullishCoalesce(MONTHS[dt.month - 1], () => ( ""));
1692
+ const dayName = _nullishCoalesce(WEEKDAYS[dt.weekday], () => ( ""));
1693
+ const out = new Out();
1694
+ for (const t of sec.toks) {
1695
+ if (t.t === "fill") {
1696
+ out.setFill(t.c);
1142
1697
  continue;
1143
1698
  }
1144
- const re = /AM\/PM|am\/pm|A\/P|a\/p|y+|m+|d+|h+|s+|[^ymdhsaA]+|./gi;
1145
- for (const match of _nullishCoalesce(token.text.match(re), () => ( []))) {
1146
- const isCode = /^(AM\/PM|A\/P|y+|m+|d+|h+|s+)$/i.test(match);
1147
- parts.push({ literal: !isCode, text: match });
1699
+ if (t.t !== "date") {
1700
+ out.push(literalText(t));
1701
+ continue;
1148
1702
  }
1703
+ const d = t.d;
1704
+ let s;
1705
+ switch (d.k) {
1706
+ case "year":
1707
+ s = d.n <= 2 ? String((dt.year % 100 + 100) % 100).padStart(2, "0") : String(dt.year).padStart(4, "0");
1708
+ break;
1709
+ case "month":
1710
+ s = d.n <= 2 ? padNum(dt.month, d.n) : d.n === 3 ? monthName.slice(0, 3) : d.n === 5 ? monthName.slice(0, 1) : monthName;
1711
+ break;
1712
+ case "day":
1713
+ s = d.n <= 2 ? padNum(dt.day, d.n) : d.n === 3 ? dayName.slice(0, 3) : dayName;
1714
+ break;
1715
+ case "hour":
1716
+ s = padNum(ampm ? hour % 12 || 12 : hour, d.n);
1717
+ break;
1718
+ case "minute":
1719
+ s = padNum(minute, d.n);
1720
+ break;
1721
+ case "second":
1722
+ s = padNum(second, d.n);
1723
+ break;
1724
+ case "subsec": {
1725
+ s = `.${String(milli).padStart(3, "0")}`.slice(0, 1 + Math.min(d.n, 3));
1726
+ if (d.n > 3) s += "0".repeat(d.n - 3);
1727
+ break;
1728
+ }
1729
+ case "eh":
1730
+ s = padNum(Math.floor(totalMs / 36e5), d.n);
1731
+ break;
1732
+ case "em":
1733
+ s = padNum(Math.floor(totalMs / 6e4), d.n);
1734
+ break;
1735
+ case "es":
1736
+ s = padNum(Math.floor(totalMs / 1e3), d.n);
1737
+ break;
1738
+ case "ampm":
1739
+ s = hour >= 12 ? "PM" : "AM";
1740
+ break;
1741
+ case "ap":
1742
+ s = hour >= 12 ? d.p : d.a;
1743
+ break;
1744
+ }
1745
+ out.push(s);
1149
1746
  }
1150
- const codes = parts.map((p, i) => ({ ...p, i })).filter((p) => !p.literal);
1151
- const twelveHour = codes.some((p) => /^(AM\/PM|A\/P)$/i.test(p.text));
1152
- return parts.map((part, index) => {
1153
- if (part.literal) return part.text;
1154
- const code = part.text;
1155
- const lower = code.toLowerCase();
1156
- if (/^(am\/pm|a\/p)$/.test(lower)) {
1157
- const pm = date.getHours() >= 12;
1158
- const full = pm ? "PM" : "AM";
1159
- const text = lower === "a/p" ? full[0] : full;
1160
- return code[0] === code[0].toLowerCase() ? text.toLowerCase() : text;
1161
- }
1162
- if (lower.startsWith("y")) {
1163
- return lower.length <= 2 ? pad3(date.getFullYear() % 100) : String(date.getFullYear());
1747
+ return out;
1748
+ }
1749
+ var digitChar = (toks, i) => {
1750
+ const t = toks[i];
1751
+ return _optionalChain([t, 'optionalAccess', _24 => _24.t]) === "digit" ? t.c : "0";
1752
+ };
1753
+ function fillInt(toks, idxs, digits, thousands, forceZero, pieces) {
1754
+ let rem = digits.length;
1755
+ let pos = 0;
1756
+ const count = idxs.length;
1757
+ for (let k = 0; k < count; k++) {
1758
+ const ti = idxs[count - 1 - k];
1759
+ const leftmost = k + 1 === count;
1760
+ const ph = digitChar(toks, ti);
1761
+ const rev = [];
1762
+ const pushDigit = (c) => {
1763
+ if (thousands && pos > 0 && pos % 3 === 0) rev.push(",");
1764
+ rev.push(c);
1765
+ pos += 1;
1766
+ };
1767
+ const take = leftmost ? rem : Math.min(rem, 1);
1768
+ if (take === 0) {
1769
+ if (ph === "0") pushDigit("0");
1770
+ else if (forceZero && k === 0) pushDigit("0");
1771
+ else if (ph === "?") {
1772
+ if (thousands && pos > 0 && pos % 3 === 0) rev.push(" ");
1773
+ rev.push(" ");
1774
+ pos += 1;
1775
+ }
1776
+ } else {
1777
+ for (let n = 0; n < take; n++) {
1778
+ rem -= 1;
1779
+ pushDigit(_nullishCoalesce(digits[rem], () => ( "0")));
1780
+ }
1164
1781
  }
1165
- if (lower.startsWith("d")) {
1166
- if (lower.length >= 4) return DAYS[date.getDay()];
1167
- if (lower.length === 3) return DAYS[date.getDay()].slice(0, 3);
1168
- return lower.length === 2 ? pad3(date.getDate()) : String(date.getDate());
1782
+ pieces[ti] = rev.reverse().join("");
1783
+ }
1784
+ }
1785
+ function withCommas(digits, thousands) {
1786
+ if (!thousands) return digits;
1787
+ const n = digits.length;
1788
+ let s = "";
1789
+ for (let i = 0; i < n; i++) {
1790
+ if (i > 0 && (n - i) % 3 === 0) s += ",";
1791
+ s += digits[i];
1792
+ }
1793
+ return s;
1794
+ }
1795
+ function fillFrac(toks, idxs, frac, pieces) {
1796
+ let lastSig = -1;
1797
+ for (let i = frac.length - 1; i >= 0; i--) {
1798
+ if (frac[i] !== "0") {
1799
+ lastSig = i;
1800
+ break;
1169
1801
  }
1170
- if (lower.startsWith("h")) {
1171
- let hours = date.getHours();
1172
- if (twelveHour) hours = hours % 12 || 12;
1173
- return lower.length >= 2 ? pad3(hours) : String(hours);
1802
+ }
1803
+ idxs.forEach((ti, i) => {
1804
+ const ph = digitChar(toks, ti);
1805
+ pieces[ti] = i <= lastSig ? _nullishCoalesce(frac[i], () => ( "0")) : ph === "0" ? "0" : ph === "?" ? " " : "";
1806
+ });
1807
+ }
1808
+ function digitIndices(toks, start, end) {
1809
+ const out = [];
1810
+ for (let i = start; i < end; i++) if (_optionalChain([toks, 'access', _25 => _25[i], 'optionalAccess', _26 => _26.t]) === "digit") out.push(i);
1811
+ return out;
1812
+ }
1813
+ function renderNumber(sec, v) {
1814
+ let x = Math.abs(v);
1815
+ if (sec.percent > 0 && !sec.exp) x *= 100 ** Math.min(sec.percent, 20);
1816
+ if (sec.scale > 0) x /= 1e3 ** Math.min(sec.scale, 110);
1817
+ if (!Number.isFinite(x)) x = Number.MAX_VALUE;
1818
+ const toks = sec.toks;
1819
+ const n = toks.length;
1820
+ const pieces = new Array(n).fill("");
1821
+ const before = new Array(n + 1).fill("");
1822
+ const lits = new Array(n);
1823
+ let zero = false;
1824
+ if (sec.fraction) {
1825
+ renderFraction(sec, x, pieces, lits);
1826
+ } else {
1827
+ const pointIdx = toks.findIndex((t) => t.t === "point");
1828
+ const expIdx = toks.findIndex((t) => t.t === "exp");
1829
+ const point = pointIdx === -1 ? void 0 : pointIdx;
1830
+ const exp = expIdx === -1 ? void 0 : expIdx;
1831
+ const intEnd = _nullishCoalesce(_nullishCoalesce(point, () => ( exp)), () => ( n));
1832
+ const fracEnd = _nullishCoalesce(exp, () => ( n));
1833
+ const intIdx = digitIndices(toks, 0, intEnd);
1834
+ const fracIdx = point === void 0 ? [] : digitIndices(toks, point + 1, fracEnd);
1835
+ let intS;
1836
+ let fracS;
1837
+ if (exp !== void 0) {
1838
+ const expDigitIdx = digitIndices(toks, exp + 1, n);
1839
+ const step = Math.max(intIdx.length, 1);
1840
+ let e;
1841
+ if (x === 0) {
1842
+ e = 0;
1843
+ intS = "0".repeat(intIdx.length);
1844
+ fracS = "0".repeat(fracIdx.length);
1845
+ } else {
1846
+ const { digits, exp: xe } = decimalDigits(x);
1847
+ e = xe - (xe % step + step) % step;
1848
+ [intS, fracS] = fixedFromDigits(digits, xe - e, fracIdx.length);
1849
+ if (intS.length > step) {
1850
+ e += step;
1851
+ [intS, fracS] = fixedFromDigits(digits, xe - e, fracIdx.length);
1852
+ }
1853
+ }
1854
+ const et = toks[exp];
1855
+ const upper = et.t === "exp" ? et.upper : true;
1856
+ const plus = et.t === "exp" ? et.plus : true;
1857
+ if (intS === "" && /^0*$/.test(fracS)) e = 0;
1858
+ const head = upper ? "E" : "e";
1859
+ const sign = e < 0 ? "-" : plus ? "+" : "";
1860
+ const expDigits = String(Math.abs(e));
1861
+ if (expDigitIdx.length > 0) {
1862
+ pieces[exp] = head;
1863
+ before[expDigitIdx[0]] = sign;
1864
+ fillInt(toks, expDigitIdx, expDigits, false, false, pieces);
1865
+ } else {
1866
+ pieces[exp] = `${head}${sign}${expDigits}`;
1867
+ }
1868
+ } else {
1869
+ [intS, fracS] = fixed(x, fracIdx.length);
1870
+ }
1871
+ zero = /^0*$/.test(intS + fracS);
1872
+ fillInt(toks, intIdx, intS, sec.thousands, false, pieces);
1873
+ const anchor = _nullishCoalesce(point, () => ( exp));
1874
+ if (intIdx.length === 0 && intS !== "" && anchor !== void 0) before[anchor] = withCommas(intS, sec.thousands);
1875
+ fillFrac(toks, fracIdx, fracS, pieces);
1876
+ if (point !== void 0) pieces[point] = ".";
1877
+ }
1878
+ const out = new Out();
1879
+ for (let i = 0; i < n; i++) {
1880
+ out.push(before[i]);
1881
+ const t = toks[i];
1882
+ if (t.t === "lit") out.push(_nullishCoalesce(lits[i], () => ( t.s)));
1883
+ else if (t.t === "percent") out.push("%");
1884
+ else if (t.t === "fill") out.setFill(t.c);
1885
+ else if (t.t === "at" || t.t === "general" || t.t === "date" || t.t === "comma") continue;
1886
+ else out.push(pieces[i]);
1887
+ }
1888
+ out.zero = zero;
1889
+ return out;
1890
+ }
1891
+ function approximate(x, maxDen) {
1892
+ if (Number.isNaN(x) || x <= 0 || !Number.isFinite(x)) return [0, 1];
1893
+ if (x >= 1e15) return [Math.round(x), 1];
1894
+ let [p0, q0, p1, q1] = [0, 1, 1, 0];
1895
+ let r = x;
1896
+ for (let iter = 0; iter < 64; iter++) {
1897
+ const aF = Math.floor(r);
1898
+ if (aF > 1e15) break;
1899
+ const q2 = aF * q1 + q0;
1900
+ if (q2 > maxDen) break;
1901
+ const p2 = aF * p1 + p0;
1902
+ [p0, q0, p1, q1] = [p1, q1, p2, q2];
1903
+ const frac = r - aF;
1904
+ if (frac < 1e-12) break;
1905
+ r = 1 / frac;
1906
+ }
1907
+ if (q1 === 0) return [Math.round(x), 1];
1908
+ const k = Math.floor((maxDen - q0) / q1);
1909
+ const pb = p0 + k * p1;
1910
+ const qb = q0 + k * q1;
1911
+ const errA = Math.abs(p1 / q1 - x);
1912
+ const errB = qb > 0 ? Math.abs(pb / qb - x) : Infinity;
1913
+ return errB < errA ? [pb, qb] : [p1, q1];
1914
+ }
1915
+ function shownWidth(t) {
1916
+ if (t.t === "lit" || t.t === "denom") return Array.from(t.s).length;
1917
+ return t.t === "digit" || t.t === "slash" ? 1 : 0;
1918
+ }
1919
+ function blankRange(toks, start, end, spaces, pieces, lits) {
1920
+ for (let i = start; i < end && i < toks.length; i++) {
1921
+ const t = toks[i];
1922
+ const s = spaces ? " ".repeat(shownWidth(t)) : "";
1923
+ if (t.t === "lit") lits[i] = s;
1924
+ else if (t.t === "digit" || t.t === "slash" || t.t === "denom") pieces[i] = s;
1925
+ }
1926
+ }
1927
+ function renderFraction(sec, x, pieces, lits) {
1928
+ const toks = sec.toks;
1929
+ const isDigit = (i) => _optionalChain([toks, 'access', _27 => _27[i], 'optionalAccess', _28 => _28.t]) === "digit";
1930
+ const slash = toks.findIndex((t) => t.t === "slash");
1931
+ if (slash === -1) return;
1932
+ let numLast = -1;
1933
+ for (let i = slash - 1; i >= 0; i--) {
1934
+ if (isDigit(i)) {
1935
+ numLast = i;
1936
+ break;
1174
1937
  }
1175
- if (lower.startsWith("s")) {
1176
- return lower.length >= 2 ? pad3(date.getSeconds()) : String(date.getSeconds());
1938
+ }
1939
+ if (numLast === -1) return;
1940
+ let numStart = numLast;
1941
+ while (numStart > 0 && isDigit(numStart - 1)) numStart -= 1;
1942
+ const wholeIdx = digitIndices(toks, 0, numStart);
1943
+ const numIdx = digitIndices(toks, numStart, numLast + 1);
1944
+ const sepStart = wholeIdx.length > 0 ? wholeIdx[wholeIdx.length - 1] + 1 : numStart;
1945
+ let fixedDen;
1946
+ let denStart;
1947
+ const afterSlash = toks[slash + 1];
1948
+ if (_optionalChain([afterSlash, 'optionalAccess', _29 => _29.t]) === "denom") {
1949
+ const parsed = Number(afterSlash.s);
1950
+ fixedDen = Math.min(Math.max(Number.isFinite(parsed) ? parsed : 1e9, 1), 1e9);
1951
+ denStart = slash + 1;
1952
+ } else {
1953
+ denStart = slash + 1;
1954
+ while (_optionalChain([toks, 'access', _30 => _30[denStart], 'optionalAccess', _31 => _31.t]) === "lit") denStart += 1;
1955
+ }
1956
+ let denEnd = denStart;
1957
+ if (fixedDen !== void 0) denEnd += 1;
1958
+ else while (isDigit(denEnd)) denEnd += 1;
1959
+ const denIdx = digitIndices(toks, denStart, denEnd);
1960
+ const hasQ = (idx) => idx.some((i) => isDigitTok2(toks[i], "?"));
1961
+ const hasWhole = wholeIdx.length > 0;
1962
+ let whole = hasWhole ? Math.floor(x) : 0;
1963
+ const f = hasWhole ? x - Math.floor(x) : x;
1964
+ let num;
1965
+ let den;
1966
+ if (fixedDen !== void 0) {
1967
+ num = Math.round(f * fixedDen);
1968
+ den = fixedDen;
1969
+ } else {
1970
+ const digits = Math.min(Math.max(denIdx.length, 1), 7);
1971
+ [num, den] = approximate(f, 10 ** digits - 1);
1972
+ }
1973
+ if (hasWhole && num >= den && den > 0) {
1974
+ whole += Math.floor(num / den);
1975
+ num %= den;
1976
+ }
1977
+ const wholeS = whole >= 1 ? fixed(whole, 0)[0] : "";
1978
+ const numZeroPh = numIdx.some((i) => isDigitTok2(toks[i], "0"));
1979
+ if (hasWhole && num === 0 && !numZeroPh) {
1980
+ fillInt(toks, wholeIdx, wholeS, sec.thousands, true, pieces);
1981
+ const spaces = hasQ(wholeIdx) || hasQ(numIdx) || hasQ(denIdx);
1982
+ blankRange(toks, sepStart, denEnd, spaces, pieces, lits);
1983
+ return;
1984
+ }
1985
+ if (hasWhole) {
1986
+ const unitsHash = isDigitTok2(toks[wholeIdx[wholeIdx.length - 1]], "#");
1987
+ const force = wholeS === "" && num === 0 && !unitsHash;
1988
+ fillInt(toks, wholeIdx, wholeS, sec.thousands, force, pieces);
1989
+ const wholeShown = wholeIdx.some((i) => /[0-9]/.test(_nullishCoalesce(pieces[i], () => ( ""))));
1990
+ if (!wholeShown) {
1991
+ const spaces = hasQ(wholeIdx) || hasQ(numIdx);
1992
+ blankRange(toks, sepStart, numStart, spaces, pieces, lits);
1177
1993
  }
1178
- const position = codes.findIndex((c) => c.i === index);
1179
- const prev = _nullishCoalesce(_optionalChain([codes, 'access', _5 => _5[position - 1], 'optionalAccess', _6 => _6.text, 'access', _7 => _7.toLowerCase, 'call', _8 => _8()]), () => ( ""));
1180
- const next = _nullishCoalesce(_optionalChain([codes, 'access', _9 => _9[position + 1], 'optionalAccess', _10 => _10.text, 'access', _11 => _11.toLowerCase, 'call', _12 => _12()]), () => ( ""));
1181
- if (lower.length <= 2 && (prev.startsWith("h") || next.startsWith("s"))) {
1182
- return lower.length === 2 ? pad3(date.getMinutes()) : String(date.getMinutes());
1994
+ }
1995
+ fillInt(toks, numIdx, fixed(num, 0)[0] || "0", false, true, pieces);
1996
+ pieces[slash] = "/";
1997
+ const denS = fixed(den, 0)[0] || "0";
1998
+ if (fixedDen !== void 0) {
1999
+ pieces[denStart] = denS;
2000
+ } else {
2001
+ const zeros = denIdx.filter((i) => isDigitTok2(toks[i], "0")).length;
2002
+ const padded = "0".repeat(Math.max(zeros - denS.length, 0)) + denS;
2003
+ const count = denIdx.length;
2004
+ denIdx.forEach((ti, k) => {
2005
+ let s = k + 1 === count ? padded.slice(k) : _nullishCoalesce(padded[k], () => ( ""));
2006
+ if (s === "") s = isDigitTok2(toks[ti], "?") ? " " : isDigitTok2(toks[ti], "0") ? "0" : "";
2007
+ pieces[ti] = s;
2008
+ });
2009
+ }
2010
+ }
2011
+ function isDigitTok2(t, c) {
2012
+ return _optionalChain([t, 'optionalAccess', _32 => _32.t]) === "digit" && t.c === c;
2013
+ }
2014
+
2015
+ // src/spreadsheet/numfmt/index.ts
2016
+ var GENERAL_WIDTH = 11;
2017
+ var OVERFLOW = "########";
2018
+ var MAX_NUMBER_FORMAT_CODE_CHARS = 255;
2019
+ function tooLong(code) {
2020
+ return code.length > MAX_NUMBER_FORMAT_CODE_CHARS && Array.from(code).length > MAX_NUMBER_FORMAT_CODE_CHARS;
2021
+ }
2022
+ var SPECIAL_CODES = ["00000", "00000-0000", "[<=9999999]###-####;(###) ###-####", "000-00-0000"];
2023
+ var NumberFormat = class _NumberFormat {
2024
+
2025
+
2026
+
2027
+ /** Sections that apply to numbers (a trailing text section is excluded). */
2028
+
2029
+ /** Index of the section that applies to text, if any. */
2030
+
2031
+ constructor(code, uncapped) {
2032
+ this.code = code;
2033
+ const trimmed = code.trim();
2034
+ if (trimmed === "" || trimmed.toLowerCase() === "general" || trimmed === "checkbox" || !uncapped && tooLong(code)) {
2035
+ this.general = true;
2036
+ this.sections = [];
2037
+ this.numSections = 0;
2038
+ this.textSection = void 0;
2039
+ return;
2040
+ }
2041
+ this.general = false;
2042
+ this.sections = parseSections(code);
2043
+ const len = this.sections.length;
2044
+ const lastIsText = _optionalChain([this, 'access', _33 => _33.sections, 'access', _34 => _34[len - 1], 'optionalAccess', _35 => _35.kind]) === "text";
2045
+ this.textSection = len >= 4 ? 3 : lastIsText ? len - 1 : void 0;
2046
+ this.numSections = len >= 4 ? 3 : lastIsText ? len - 1 : len;
2047
+ }
2048
+ /**
2049
+ * Parses a format code. Never throws: unknown or malformed parts degrade to
2050
+ * literal text, and a code longer than 255 characters degrades to General.
2051
+ */
2052
+ static parse(code) {
2053
+ return new _NumberFormat(code, false);
2054
+ }
2055
+ /** `parse` without the 255-character cap (for tests that reach renderer edge cases). */
2056
+ static parseUncapped(code) {
2057
+ return new _NumberFormat(code, true);
2058
+ }
2059
+ /** Like `parse`, but remembers recently parsed codes (bounded), so formatting many values parses a code once. */
2060
+ static parseCached(code) {
2061
+ if (code.length > CACHE_MAX_CODE_LENGTH) return _NumberFormat.parse(code);
2062
+ let fmt = parseCache.get(code);
2063
+ if (!fmt) {
2064
+ fmt = _NumberFormat.parse(code);
2065
+ if (parseCache.size >= CACHE_CAPACITY) parseCache.clear();
2066
+ parseCache.set(code, fmt);
2067
+ }
2068
+ return fmt;
2069
+ }
2070
+ static general() {
2071
+ return _NumberFormat.parse("General");
2072
+ }
2073
+ isGeneral() {
2074
+ return this.general;
2075
+ }
2076
+ numberSections() {
2077
+ return this.sections.slice(0, this.numSections);
2078
+ }
2079
+ /** True when the code contains date or time tokens. */
2080
+ isDate() {
2081
+ return this.numberSections().some((s) => s.kind === "date");
2082
+ }
2083
+ isPercent() {
2084
+ return this.numberSections().some((s) => s.kind === "number" && s.percent > 0);
2085
+ }
2086
+ /** True for a pure text format such as `@`. */
2087
+ isText() {
2088
+ return this.numSections === 0 && this.textSection !== void 0;
2089
+ }
2090
+ /** Best guess at the format category. */
2091
+ kind() {
2092
+ if (this.general) return "general";
2093
+ if (this.isText()) return "text";
2094
+ if (SPECIAL_CODES.includes(this.code)) return "special";
2095
+ const s = this.sections[0];
2096
+ if (!s) return "custom";
2097
+ if (s.kind === "general") return "general";
2098
+ if (s.kind === "text") return "text";
2099
+ if (s.kind === "date") {
2100
+ const calendar = s.toks.some((t) => t.t === "date" && (t.d.k === "year" || t.d.k === "month" || t.d.k === "day"));
2101
+ return calendar ? "date" : "time";
2102
+ }
2103
+ if (s.fraction) return "fraction";
2104
+ if (s.exp) return "scientific";
2105
+ if (s.percent > 0) return "percentage";
2106
+ if (s.fill && s.hasDigits) return "accounting";
2107
+ if (s.currency && s.hasDigits) return "currency";
2108
+ if (s.hasDigits) return "number";
2109
+ return "custom";
2110
+ }
2111
+ /**
2112
+ * Picks the number section for `v`, and whether the minus sign is dropped
2113
+ * (a negative section shows the absolute value). Null means General.
2114
+ */
2115
+ select(v) {
2116
+ const secs = this.numberSections();
2117
+ const k = secs.length;
2118
+ const s0 = secs[0];
2119
+ if (!s0) return null;
2120
+ const c0 = s0.cond;
2121
+ const c1 = _optionalChain([secs, 'access', _36 => _36[1], 'optionalAccess', _37 => _37.cond]);
2122
+ if (c0 || c1) {
2123
+ let idx;
2124
+ if (c0 && testCond(c0, v)) idx = 0;
2125
+ else if (c1 && testCond(c1, v)) idx = 1;
2126
+ else if (c0 && c1) idx = 2;
2127
+ else if (!c0) idx = 0;
2128
+ else idx = 1;
2129
+ const sec = secs[idx];
2130
+ return sec ? { sec, dropSign: k >= 2 } : null;
2131
+ }
2132
+ if (v < 0 && k >= 2) return { sec: secs[1], dropSign: true };
2133
+ if (v === 0 && k >= 3) return { sec: secs[2], dropSign: false };
2134
+ return { sec: s0, dropSign: false };
2135
+ }
2136
+ /**
2137
+ * Formats a number. `overflow` is true when the value can't be shown (a
2138
+ * date out of range, painted as `########`).
2139
+ */
2140
+ formatNumber(n) {
2141
+ const general = () => ({
2142
+ text: _nullishCoalesce(formatGeneralFit(n, GENERAL_WIDTH), () => ( OVERFLOW)),
2143
+ numeric: true,
2144
+ overflow: false
2145
+ });
2146
+ if (!Number.isFinite(n)) return { text: "#NUM!", numeric: false, overflow: true };
2147
+ if (this.general) return general();
2148
+ const picked = this.select(n);
2149
+ if (!picked) return general();
2150
+ const { sec, dropSign } = picked;
2151
+ const minus = n < 0 && !dropSign;
2152
+ let out;
2153
+ switch (sec.kind) {
2154
+ case "text":
2155
+ out = renderText(sec, _nullishCoalesce(formatGeneralFit(n, GENERAL_WIDTH), () => ( "")));
2156
+ break;
2157
+ case "general":
2158
+ out = renderGeneral(sec, Math.abs(n), minus ? GENERAL_WIDTH - 1 : GENERAL_WIDTH);
2159
+ break;
2160
+ case "date":
2161
+ out = minus ? null : renderDate(sec, Math.abs(n));
2162
+ break;
2163
+ default:
2164
+ out = renderNumber(sec, Math.abs(n));
1183
2165
  }
1184
- if (lower.length >= 4) return MONTHS[date.getMonth()];
1185
- if (lower.length === 3) return MONTHS[date.getMonth()].slice(0, 3);
1186
- return lower.length === 2 ? pad3(date.getMonth() + 1) : String(date.getMonth() + 1);
1187
- }).join("");
2166
+ if (!out) return withColor({ text: OVERFLOW, numeric: true, overflow: true }, sec.color);
2167
+ if (minus && sec.kind !== "text" && !out.zero) out.prepend("-");
2168
+ return withColor({ text: out.text, numeric: true, overflow: false, ...out.fill ? { fill: out.fill } : {} }, sec.color);
2169
+ }
2170
+ /** Formats text through the text section (`@`), or returns it unchanged. */
2171
+ formatText(text) {
2172
+ const sec = this.textSection === void 0 ? void 0 : this.sections[this.textSection];
2173
+ if (!sec) return { text, numeric: false };
2174
+ const out = renderText(sec, text);
2175
+ return withColor({ text: out.text, numeric: false, ...out.fill ? { fill: out.fill } : {} }, sec.color);
2176
+ }
2177
+ /**
2178
+ * Formats a cell value: numbers through the number sections, ISO date text
2179
+ * (`2026-03-04`, `2026-03-04 18:00:00`) and `Date`s as serial numbers, other
2180
+ * text through the text section; booleans show TRUE/FALSE and error values
2181
+ * themselves.
2182
+ */
2183
+ format(value) {
2184
+ if (value === "" || value === null || value === void 0) return { text: "", numeric: false };
2185
+ if (typeof value === "boolean") return { text: value ? "TRUE" : "FALSE", numeric: false };
2186
+ if (typeof value === "number") {
2187
+ const { overflow: _overflow, ...rest } = this.formatNumber(value);
2188
+ return rest;
2189
+ }
2190
+ if (typeof value === "string" && FORMULA_ERRORS.has(value)) return { text: value, numeric: false };
2191
+ const serial = dateValueToSerial(value);
2192
+ if (serial !== null) {
2193
+ const { overflow: _overflow, ...rest } = this.formatNumber(serial);
2194
+ return rest;
2195
+ }
2196
+ return this.formatText(String(value));
2197
+ }
2198
+ };
2199
+ function withColor(value, color) {
2200
+ if (color) value.color = color;
2201
+ return value;
2202
+ }
2203
+ var CACHE_CAPACITY = 64;
2204
+ var CACHE_MAX_CODE_LENGTH = 256;
2205
+ var parseCache = /* @__PURE__ */ new Map();
2206
+ function clearNumberFormatCache() {
2207
+ parseCache.clear();
2208
+ }
2209
+ var ISO_DATE_TIME = /^(\d{4})-(\d{1,2})-(\d{1,2})(?:[ T](\d{1,2}):(\d{2})(?::(\d{2}(?:\.\d+)?))?)?$/;
2210
+ function dateValueToSerial(value) {
2211
+ if (value instanceof Date) {
2212
+ if (isNaN(value.getTime())) return null;
2213
+ const serial2 = serialFromYmd(value.getFullYear(), value.getMonth() + 1, value.getDate());
2214
+ return serial2 === null ? null : serial2 + timeFraction(value.getHours(), value.getMinutes(), value.getSeconds() + value.getMilliseconds() / 1e3);
2215
+ }
2216
+ if (typeof value !== "string" || value.length < 8 || value.length > 30) return null;
2217
+ const m = ISO_DATE_TIME.exec(value.trim());
2218
+ if (!m) return null;
2219
+ const [y, mo, d] = [Number(m[1]), Number(m[2]), Number(m[3])];
2220
+ if (mo < 1 || mo > 12 || d < 1 || d > daysInMonth(y, mo)) return null;
2221
+ const serial = serialFromYmd(y, mo, d);
2222
+ if (serial === null) return null;
2223
+ if (m[4] === void 0) return serial;
2224
+ const [hh, mm, ss] = [Number(m[4]), Number(m[5]), Number(_nullishCoalesce(m[6], () => ( 0)))];
2225
+ if (hh > 23 || mm > 59 || ss >= 60) return null;
2226
+ return serial + timeFraction(hh, mm, ss);
2227
+ }
2228
+ function formatNumberFormatValue(value, code) {
2229
+ return NumberFormat.parseCached(code).format(value);
2230
+ }
2231
+ function formatTextFunction(value, code) {
2232
+ if (typeof value === "string" && FORMULA_ERRORS.has(value)) return { error: value };
2233
+ if (code === "") return { text: "" };
2234
+ if (tooLong(code)) return { error: "#VALUE!" };
2235
+ const fmt = NumberFormat.parseCached(code);
2236
+ let n;
2237
+ if (value === "" || value === null || value === void 0) n = 0;
2238
+ else if (typeof value === "number") n = value;
2239
+ else if (typeof value === "boolean") return { text: fmt.formatText(value ? "TRUE" : "FALSE").text };
2240
+ else {
2241
+ const serial = dateValueToSerial(value);
2242
+ const parsed = _nullishCoalesce(serial, () => ( (typeof value === "string" ? parseNumberText(value) : null)));
2243
+ if (parsed === null) return { text: fmt.formatText(String(value)).text };
2244
+ n = parsed;
2245
+ }
2246
+ if (!Number.isFinite(n)) return { error: "#NUM!" };
2247
+ const f = fmt.formatNumber(n);
2248
+ return f.overflow ? { error: "#VALUE!" } : { text: f.text };
2249
+ }
2250
+ var INDEXED_COLORS = [
2251
+ "#000000",
2252
+ "#FFFFFF",
2253
+ "#FF0000",
2254
+ "#00FF00",
2255
+ "#0000FF",
2256
+ "#FFFF00",
2257
+ "#FF00FF",
2258
+ "#00FFFF",
2259
+ "#800000",
2260
+ "#008000",
2261
+ "#000080",
2262
+ "#808000",
2263
+ "#800080",
2264
+ "#008080",
2265
+ "#C0C0C0",
2266
+ "#808080",
2267
+ "#9999FF",
2268
+ "#993366",
2269
+ "#FFFFCC",
2270
+ "#CCFFFF",
2271
+ "#660066",
2272
+ "#FF8080",
2273
+ "#0066CC",
2274
+ "#CCCCFF",
2275
+ "#000080",
2276
+ "#FF00FF",
2277
+ "#FFFF00",
2278
+ "#00FFFF",
2279
+ "#800080",
2280
+ "#800000",
2281
+ "#008080",
2282
+ "#0000FF",
2283
+ "#00CCFF",
2284
+ "#CCFFFF",
2285
+ "#CCFFCC",
2286
+ "#FFFF99",
2287
+ "#99CCFF",
2288
+ "#FF99CC",
2289
+ "#CC99FF",
2290
+ "#FFCC99",
2291
+ "#3366FF",
2292
+ "#33CCCC",
2293
+ "#99CC00",
2294
+ "#FFCC00",
2295
+ "#FF9900",
2296
+ "#FF6600",
2297
+ "#666699",
2298
+ "#969696",
2299
+ "#003366",
2300
+ "#339966",
2301
+ "#003300",
2302
+ "#333300",
2303
+ "#993300",
2304
+ "#993366",
2305
+ "#333399",
2306
+ "#333333"
2307
+ ];
2308
+ var NAMED_CSS = {
2309
+ black: "#000000",
2310
+ blue: "#0000FF",
2311
+ cyan: "#00FFFF",
2312
+ green: "#00FF00",
2313
+ magenta: "#FF00FF",
2314
+ red: "#FF0000",
2315
+ white: "#FFFFFF",
2316
+ yellow: "#FFFF00"
2317
+ };
2318
+ function numberFormatColorToCss(color) {
2319
+ const named = NAMED_CSS[color];
2320
+ if (named) return named;
2321
+ return _nullishCoalesce(INDEXED_COLORS[Number(color.slice(5)) - 1], () => ( "#000000"));
1188
2322
  }
1189
2323
 
1190
2324
  // src/spreadsheet/formula/functions/helpers.ts
@@ -2197,15 +3331,19 @@ var TEXT_FUNCTIONS = [
2197
3331
  {
2198
3332
  name: "TEXT",
2199
3333
  category: "text",
2200
- description: 'Formats a number or date as text using a format code such as "0.00", "#,##0", "0%" or "yyyy-mm-dd".',
3334
+ description: 'Formats a number or date as text using an Excel format code such as "0.00", "#,##0", "0%", "# ?/?" or "yyyy-mm-dd".',
2201
3335
  args: [arg("value", "The number or date to format."), arg("format_text", "The format code.", "text")],
2202
3336
  evaluate: (ctx) => {
2203
3337
  const value = ctx.scalar(0);
2204
3338
  if (isFormulaError(value)) return value;
2205
3339
  const format = ctx.text(1);
2206
3340
  if (failed(format)) return format;
2207
- const result = formatValueWithCode(value, format);
2208
- return _nullishCoalesce(result, () => ( ctx.argError(0, "#VALUE!", `isn't a date, so it can't use the format "${format}".`)));
3341
+ const result = formatTextFunction(value, format);
3342
+ if ("text" in result) return result.text;
3343
+ if (result.error === "#VALUE!") {
3344
+ return Array.from(format).length > 255 ? ctx.argError(1, "#VALUE!", "is longer than 255 characters.") : ctx.argError(0, "#VALUE!", `is outside the date range, so it can't use the format "${format}".`);
3345
+ }
3346
+ return result.error;
2209
3347
  }
2210
3348
  }
2211
3349
  ];
@@ -2270,15 +3408,15 @@ function tableLookup(ctx, vertical) {
2270
3408
  if (failed(table)) return table;
2271
3409
  const index = ctx.integer(2);
2272
3410
  if (failed(index)) return index;
2273
- const approximate = ctx.boolean(3, true);
2274
- if (failed(approximate)) return approximate;
3411
+ const approximate2 = ctx.boolean(3, true);
3412
+ if (failed(approximate2)) return approximate2;
2275
3413
  const span = vertical ? table.cols : table.rows;
2276
3414
  if (index < 1) return ctx.argError(2, "#VALUE!", "must be 1 or more.");
2277
3415
  if (index > span) {
2278
3416
  return ctx.argError(2, "#REF!", `is larger than the number of ${vertical ? "columns" : "rows"} in the table (${span}).`);
2279
3417
  }
2280
3418
  const keys = vertical ? sliceRange(table, 0, table.rows, 0, 1) : sliceRange(table, 0, 1, 0, table.cols);
2281
- const position = lookupIndex(keys, target, approximate ? "sorted-asc" : "wildcard");
3419
+ const position = lookupIndex(keys, target, approximate2 ? "sorted-asc" : "wildcard");
2282
3420
  if (position === -1) return notFound(ctx, target);
2283
3421
  return vertical ? rangeGet(table, position, index - 1) : rangeGet(table, index - 1, position);
2284
3422
  }
@@ -3044,17 +4182,17 @@ function layoutOf(def) {
3044
4182
  return { fixed: def.args.slice(0, groupStart), group: def.args.slice(groupStart), groupStart };
3045
4183
  }
3046
4184
  function getFormulaArgumentSpecIndex(def, argIndex) {
3047
- const { fixed, group, groupStart } = layoutOf(def);
3048
- if (argIndex < fixed.length) return argIndex;
4185
+ const { fixed: fixed2, group, groupStart } = layoutOf(def);
4186
+ if (argIndex < fixed2.length) return argIndex;
3049
4187
  if (group.length === 0) return -1;
3050
4188
  return groupStart + (argIndex - groupStart) % group.length;
3051
4189
  }
3052
4190
  function checkFormulaArgumentCount(def, count) {
3053
- const { fixed, group } = layoutOf(def);
3054
- const requiredFixed = fixed.filter((arg2) => !arg2.optional).length;
4191
+ const { fixed: fixed2, group } = layoutOf(def);
4192
+ const requiredFixed = fixed2.filter((arg2) => !arg2.optional).length;
3055
4193
  const groupRequired = group.length > 0 && !group[0].optional;
3056
4194
  const min2 = requiredFixed + (groupRequired ? group.length : 0);
3057
- const max2 = group.length > 0 ? Infinity : fixed.length;
4195
+ const max2 = group.length > 0 ? Infinity : fixed2.length;
3058
4196
  const given = `${count} ${count === 1 ? "was" : "were"} given`;
3059
4197
  const plural = (n) => `${n} argument${n === 1 ? "" : "s"}`;
3060
4198
  if (count < min2) {
@@ -3065,8 +4203,8 @@ function checkFormulaArgumentCount(def, count) {
3065
4203
  const expected = min2 === max2 ? plural(max2) : `at most ${plural(max2)}`;
3066
4204
  return max2 === 0 ? `${def.name} takes no arguments, but ${given}.` : `${def.name} takes ${expected}, but ${given}.`;
3067
4205
  }
3068
- if (group.length > 1 && count > fixed.length) {
3069
- const extra = (count - fixed.length) % group.length;
4206
+ if (group.length > 1 && count > fixed2.length) {
4207
+ const extra = (count - fixed2.length) % group.length;
3070
4208
  if (extra !== 0 && !(def.allowTrailingArgument && extra === 1)) {
3071
4209
  const names = group.map((arg2) => arg2.name).join(", ");
3072
4210
  return `${def.name} expects its repeating arguments (${names}) in complete groups.`;
@@ -3077,7 +4215,7 @@ function checkFormulaArgumentCount(def, count) {
3077
4215
  function getFormulaSignatureParts(nameOrDef, activeArgIndex) {
3078
4216
  const def = typeof nameOrDef === "string" ? getFormulaFunction(nameOrDef) : nameOrDef;
3079
4217
  if (!def) return [];
3080
- const { fixed, group, groupStart } = layoutOf(def);
4218
+ const { fixed: fixed2, group, groupStart } = layoutOf(def);
3081
4219
  let activeSpec = -1;
3082
4220
  let activeRepeat = 0;
3083
4221
  if (activeArgIndex !== void 0 && activeArgIndex !== null && activeArgIndex >= 0) {
@@ -3091,7 +4229,7 @@ function getFormulaSignatureParts(nameOrDef, activeArgIndex) {
3091
4229
  if (parts.length > 1) parts.push({ text: ", ", specIndex: null, active: false });
3092
4230
  parts.push({ text, specIndex, active: specIndex === activeSpec && repeat === activeRepeat });
3093
4231
  };
3094
- fixed.forEach((arg2, i) => pushArg(arg2.optional ? `[${arg2.name}]` : arg2.name, i));
4232
+ fixed2.forEach((arg2, i) => pushArg(arg2.optional ? `[${arg2.name}]` : arg2.name, i));
3095
4233
  if (group.length > 0) {
3096
4234
  const groupOptional = !!group[0].optional;
3097
4235
  group.forEach((arg2, i) => {
@@ -3151,12 +4289,12 @@ function buildArray(rows, cols, fn) {
3151
4289
  }
3152
4290
  var isMultiArray = (value) => Array.isArray(value) && value.length > 1;
3153
4291
  var firstValue = (value) => Array.isArray(value) ? value.length ? value[0] : "" : value;
3154
- var FormulaEvaluator = (_class2 = class {
4292
+ var FormulaEvaluator = (_class3 = class {
3155
4293
 
3156
- __init3() {this.diagnostics = []}
4294
+ __init5() {this.diagnostics = []}
3157
4295
  // LET variables, innermost scope last.
3158
- __init4() {this.scopes = []}
3159
- constructor(context = {}) {;_class2.prototype.__init3.call(this);_class2.prototype.__init4.call(this);
4296
+ __init6() {this.scopes = []}
4297
+ constructor(context = {}) {;_class3.prototype.__init5.call(this);_class3.prototype.__init6.call(this);
3160
4298
  this.context = context;
3161
4299
  }
3162
4300
  /**
@@ -3191,14 +4329,14 @@ var FormulaEvaluator = (_class2 = class {
3191
4329
  const result = {
3192
4330
  value,
3193
4331
  error: code,
3194
- message: _nullishCoalesce(_optionalChain([diagnostic, 'optionalAccess', _13 => _13.message]), () => ( describeFormulaError(code)))
4332
+ message: _nullishCoalesce(_optionalChain([diagnostic, 'optionalAccess', _38 => _38.message]), () => ( describeFormulaError(code)))
3195
4333
  };
3196
4334
  if (array) result.array = array;
3197
4335
  return result;
3198
4336
  }
3199
4337
  return array ? { value, array } : { value };
3200
4338
  } catch (err) {
3201
- return { value: "#ERROR!", error: "#ERROR!", message: _optionalChain([err, 'optionalAccess', _14 => _14.message]) || "Formula error" };
4339
+ return { value: "#ERROR!", error: "#ERROR!", message: _optionalChain([err, 'optionalAccess', _39 => _39.message]) || "Formula error" };
3202
4340
  } finally {
3203
4341
  this.diagnostics = saved;
3204
4342
  this.scopes = savedScopes;
@@ -3379,7 +4517,7 @@ var FormulaEvaluator = (_class2 = class {
3379
4517
  const value = this.evaluateNode(argument);
3380
4518
  if (!Array.isArray(value)) return value;
3381
4519
  if (value.length <= 1) return firstValue(value);
3382
- const cell = _optionalChain([this, 'access', _15 => _15.context, 'access', _16 => _16.getFormulaCell, 'optionalCall', _17 => _17()]);
4520
+ const cell = _optionalChain([this, 'access', _40 => _40.context, 'access', _41 => _41.getFormulaCell, 'optionalCall', _42 => _42()]);
3383
4521
  if (argument.type === "Range" && cell) {
3384
4522
  const range = toFormulaRange(value);
3385
4523
  const top = Math.min(argument.startRow, argument.endRow);
@@ -3461,7 +4599,7 @@ var FormulaEvaluator = (_class2 = class {
3461
4599
  * multi-value array.
3462
4600
  */
3463
4601
  liftOverArrays(def, args) {
3464
- const liftable = (index) => _optionalChain([def, 'access', _18 => _18.args, 'access', _19 => _19[getFormulaArgumentSpecIndex(def, index)], 'optionalAccess', _20 => _20.type]) !== "range";
4602
+ const liftable = (index) => _optionalChain([def, 'access', _43 => _43.args, 'access', _44 => _44[getFormulaArgumentSpecIndex(def, index)], 'optionalAccess', _45 => _45.type]) !== "range";
3465
4603
  const triggers = def.elementwise === true ? args.map((a) => a.index) : def.elementwise;
3466
4604
  if (!triggers.some((i) => i < args.length && liftable(i) && isMultiArray(args[i].value()))) return void 0;
3467
4605
  let rows = 1;
@@ -3581,7 +4719,17 @@ var FormulaEvaluator = (_class2 = class {
3581
4719
  }
3582
4720
  };
3583
4721
  }
3584
- }, _class2);
4722
+ }, _class3);
4723
+
4724
+
4725
+
4726
+
4727
+
4728
+
4729
+
4730
+
4731
+
4732
+
3585
4733
 
3586
4734
 
3587
4735
 
@@ -3619,5 +4767,5 @@ var FormulaEvaluator = (_class2 = class {
3619
4767
 
3620
4768
 
3621
4769
 
3622
- exports.tokenizeFormula = tokenizeFormula; exports.WHOLE_COLUMN_END_ROW = WHOLE_COLUMN_END_ROW; exports.parseCellReference = parseCellReference; exports.parseRange = parseRange; exports.FormulaParser = FormulaParser; exports.parseFormula = parseFormula; exports.serialFromYmd = serialFromYmd; exports.parseCellInput = parseCellInput; exports.parseNumberText = parseNumberText; exports.FORMULA_ERRORS = FORMULA_ERRORS; exports.isFormulaError = isFormulaError; exports.numberToText = numberToText; exports.numericValue = numericValue; exports.compareNumbers = compareNumbers; exports.compareValues = compareValues; exports.sortCompareValues = sortCompareValues; exports.colNameToIndex = colNameToIndex; exports.indexToColName = indexToColName; exports.parseIsoDate = parseIsoDate; exports.wildcardToRegExp = wildcardToRegExp; exports.parseCriteria = parseCriteria; exports.formatCellDisplay = formatCellDisplay; exports.formatValueWithCode = formatValueWithCode; exports.registerFormulaFunction = registerFormulaFunction; exports.unregisterFormulaFunction = unregisterFormulaFunction; exports.getFormulaFunction = getFormulaFunction; exports.listFormulaFunctions = listFormulaFunctions; exports.searchFormulaFunctions = searchFormulaFunctions; exports.getFormulaArgumentSpecIndex = getFormulaArgumentSpecIndex; exports.checkFormulaArgumentCount = checkFormulaArgumentCount; exports.getFormulaSignatureParts = getFormulaSignatureParts; exports.getFormulaSignature = getFormulaSignature; exports.describeFormulaError = describeFormulaError; exports.MAX_FORMULA_ARRAY_SIZE = MAX_FORMULA_ARRAY_SIZE; exports.FormulaEvaluator = FormulaEvaluator;
3623
- //# sourceMappingURL=chunk-RIKBJLS2.cjs.map
4770
+ exports.tokenizeFormula = tokenizeFormula; exports.WHOLE_COLUMN_END_ROW = WHOLE_COLUMN_END_ROW; exports.parseCellReference = parseCellReference; exports.parseRange = parseRange; exports.FormulaParser = FormulaParser; exports.parseFormula = parseFormula; exports.serialFromYmd = serialFromYmd; exports.parseCellInput = parseCellInput; exports.parseNumberText = parseNumberText; exports.FORMULA_ERRORS = FORMULA_ERRORS; exports.isFormulaError = isFormulaError; exports.isBlank = isBlank; exports.toText = toText; exports.numberToText = numberToText; exports.numericValue = numericValue; exports.compareNumbers = compareNumbers; exports.compareValues = compareValues; exports.sortCompareValues = sortCompareValues; exports.colNameToIndex = colNameToIndex; exports.indexToColName = indexToColName; exports.parseIsoDate = parseIsoDate; exports.wildcardToRegExp = wildcardToRegExp; exports.parseCriteria = parseCriteria; exports.formatGeneralFit = formatGeneralFit; exports.builtinNumberFormat = builtinNumberFormat; exports.builtinNumberFormatId = builtinNumberFormatId; exports.MAX_NUMBER_FORMAT_CODE_CHARS = MAX_NUMBER_FORMAT_CODE_CHARS; exports.NumberFormat = NumberFormat; exports.clearNumberFormatCache = clearNumberFormatCache; exports.dateValueToSerial = dateValueToSerial; exports.formatNumberFormatValue = formatNumberFormatValue; exports.formatTextFunction = formatTextFunction; exports.numberFormatColorToCss = numberFormatColorToCss; exports.registerFormulaFunction = registerFormulaFunction; exports.unregisterFormulaFunction = unregisterFormulaFunction; exports.getFormulaFunction = getFormulaFunction; exports.listFormulaFunctions = listFormulaFunctions; exports.searchFormulaFunctions = searchFormulaFunctions; exports.getFormulaArgumentSpecIndex = getFormulaArgumentSpecIndex; exports.checkFormulaArgumentCount = checkFormulaArgumentCount; exports.getFormulaSignatureParts = getFormulaSignatureParts; exports.getFormulaSignature = getFormulaSignature; exports.describeFormulaError = describeFormulaError; exports.MAX_FORMULA_ARRAY_SIZE = MAX_FORMULA_ARRAY_SIZE; exports.FormulaEvaluator = FormulaEvaluator;
4771
+ //# sourceMappingURL=chunk-MCSJFWAO.cjs.map