@pixerate/editor 0.22.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 (188) hide show
  1. package/README.md +175 -2
  2. package/THIRD_PARTY_NOTICES.md +139 -0
  3. package/dist/agent/index.cjs +87 -111
  4. package/dist/agent/index.cjs.map +1 -1
  5. package/dist/agent/index.d.cts +70 -211
  6. package/dist/agent/index.d.ts +70 -211
  7. package/dist/agent/index.js +78 -102
  8. package/dist/agent/index.js.map +1 -1
  9. package/dist/arrangeShortcuts-B8O3f8-P.d.cts +184 -0
  10. package/dist/arrangeShortcuts-sLlD2rSX.d.ts +184 -0
  11. package/dist/canvas/index.cjs +2075 -86
  12. package/dist/canvas/index.cjs.map +1 -1
  13. package/dist/canvas/index.d.cts +608 -186
  14. package/dist/canvas/index.d.ts +608 -186
  15. package/dist/canvas/index.js +2060 -71
  16. package/dist/canvas/index.js.map +1 -1
  17. package/dist/chunk-26BVFKHU.cjs +453 -0
  18. package/dist/chunk-26BVFKHU.cjs.map +1 -0
  19. package/dist/chunk-2H7ZHPEJ.js +762 -0
  20. package/dist/chunk-2H7ZHPEJ.js.map +1 -0
  21. package/dist/{chunk-DENSCKFC.js → chunk-3CN2WD3X.js} +1730 -189
  22. package/dist/chunk-3CN2WD3X.js.map +1 -0
  23. package/dist/{chunk-JJDLPEWL.js → chunk-3LV6RRPH.js} +2 -2
  24. package/dist/{chunk-MJZBNWG7.js → chunk-5S3Z4PPF.js} +78 -557
  25. package/dist/chunk-5S3Z4PPF.js.map +1 -0
  26. package/dist/chunk-664LQYFJ.js +115 -0
  27. package/dist/chunk-664LQYFJ.js.map +1 -0
  28. package/dist/chunk-7DWMJCAT.js +453 -0
  29. package/dist/chunk-7DWMJCAT.js.map +1 -0
  30. package/dist/chunk-ARRTP33I.js +101 -0
  31. package/dist/chunk-ARRTP33I.js.map +1 -0
  32. package/dist/chunk-CPOKFNBG.cjs +101 -0
  33. package/dist/chunk-CPOKFNBG.cjs.map +1 -0
  34. package/dist/{chunk-AA4ZEVCC.cjs → chunk-D27YFC46.cjs} +101 -580
  35. package/dist/chunk-D27YFC46.cjs.map +1 -0
  36. package/dist/chunk-D6FH2YAX.cjs +131 -0
  37. package/dist/chunk-D6FH2YAX.cjs.map +1 -0
  38. package/dist/{chunk-4SUNJZWB.cjs → chunk-FD4LPFAE.cjs} +48 -200
  39. package/dist/chunk-FD4LPFAE.cjs.map +1 -0
  40. package/dist/chunk-FODNLX5N.js +749 -0
  41. package/dist/chunk-FODNLX5N.js.map +1 -0
  42. package/dist/{chunk-OYXSKQFR.js → chunk-FPENXAEJ.js} +35 -187
  43. package/dist/chunk-FPENXAEJ.js.map +1 -0
  44. package/dist/chunk-G2I4QJOT.cjs +762 -0
  45. package/dist/chunk-G2I4QJOT.cjs.map +1 -0
  46. package/dist/chunk-HLIMTC6N.js +1 -0
  47. package/dist/chunk-HLIMTC6N.js.map +1 -0
  48. package/dist/{chunk-QGHGJ56O.js → chunk-ITBSKI26.js} +1483 -19
  49. package/dist/chunk-ITBSKI26.js.map +1 -0
  50. package/dist/{chunk-6M3BCTBD.cjs → chunk-MA2F5KHF.cjs} +470 -242
  51. package/dist/chunk-MA2F5KHF.cjs.map +1 -0
  52. package/dist/{chunk-SAZRENEZ.cjs → chunk-MCSJFWAO.cjs} +1733 -192
  53. package/dist/chunk-MCSJFWAO.cjs.map +1 -0
  54. package/dist/chunk-MKA3AHLV.cjs +256 -0
  55. package/dist/chunk-MKA3AHLV.cjs.map +1 -0
  56. package/dist/chunk-OLZJXL4R.cjs +749 -0
  57. package/dist/chunk-OLZJXL4R.cjs.map +1 -0
  58. package/dist/chunk-OXSV64JX.js +689 -0
  59. package/dist/chunk-OXSV64JX.js.map +1 -0
  60. package/dist/chunk-P3RQ5UJE.cjs +689 -0
  61. package/dist/chunk-P3RQ5UJE.cjs.map +1 -0
  62. package/dist/chunk-P6ODPZ4W.js +256 -0
  63. package/dist/chunk-P6ODPZ4W.js.map +1 -0
  64. package/dist/chunk-PGNZKFQS.js +685 -0
  65. package/dist/chunk-PGNZKFQS.js.map +1 -0
  66. package/dist/chunk-PL4JB3BF.cjs +1 -0
  67. package/dist/chunk-PL4JB3BF.cjs.map +1 -0
  68. package/dist/{chunk-GVSMRPHB.cjs → chunk-SBCZ6RN5.cjs} +1568 -104
  69. package/dist/chunk-SBCZ6RN5.cjs.map +1 -0
  70. package/dist/{chunk-CL37JGFW.cjs → chunk-SML64VJG.cjs} +4 -4
  71. package/dist/{chunk-CL37JGFW.cjs.map → chunk-SML64VJG.cjs.map} +1 -1
  72. package/dist/chunk-TNNJXF46.cjs +115 -0
  73. package/dist/chunk-TNNJXF46.cjs.map +1 -0
  74. package/dist/chunk-U5HZSFCS.js +131 -0
  75. package/dist/chunk-U5HZSFCS.js.map +1 -0
  76. package/dist/{chunk-RU52I7QO.js → chunk-U5KWZU4X.js} +388 -160
  77. package/dist/chunk-U5KWZU4X.js.map +1 -0
  78. package/dist/chunk-XNORY7M6.cjs +685 -0
  79. package/dist/chunk-XNORY7M6.cjs.map +1 -0
  80. package/dist/commands/index.cjs +860 -0
  81. package/dist/commands/index.cjs.map +1 -0
  82. package/dist/commands/index.d.cts +244 -0
  83. package/dist/commands/index.d.ts +244 -0
  84. package/dist/commands/index.js +860 -0
  85. package/dist/commands/index.js.map +1 -0
  86. package/dist/comment-store-BEMgVlAA.d.cts +135 -0
  87. package/dist/comment-store-BEMgVlAA.d.ts +135 -0
  88. package/dist/compare/index.cjs +15 -0
  89. package/dist/compare/index.cjs.map +1 -0
  90. package/dist/compare/index.d.cts +58 -0
  91. package/dist/compare/index.d.ts +58 -0
  92. package/dist/compare/index.js +15 -0
  93. package/dist/compare/index.js.map +1 -0
  94. package/dist/{controller-B7GIybc4.d.cts → controller-BhLLAoi8.d.cts} +119 -5
  95. package/dist/{controller-B7GIybc4.d.ts → controller-BhLLAoi8.d.ts} +119 -5
  96. package/dist/documents-BQjzJNe2.d.ts +76 -0
  97. package/dist/documents-KRTPhvst.d.cts +76 -0
  98. package/dist/extensions/index.cjs +53 -5
  99. package/dist/extensions/index.cjs.map +1 -1
  100. package/dist/extensions/index.d.cts +7 -3
  101. package/dist/extensions/index.d.ts +7 -3
  102. package/dist/extensions/index.js +52 -4
  103. package/dist/generation/index.cjs +1373 -0
  104. package/dist/generation/index.cjs.map +1 -0
  105. package/dist/generation/index.d.cts +554 -0
  106. package/dist/generation/index.d.ts +554 -0
  107. package/dist/generation/index.js +1373 -0
  108. package/dist/generation/index.js.map +1 -0
  109. package/dist/grammar/index.cjs +48 -3
  110. package/dist/grammar/index.cjs.map +1 -1
  111. package/dist/grammar/index.d.cts +322 -100
  112. package/dist/grammar/index.d.ts +322 -100
  113. package/dist/grammar/index.js +54 -9
  114. package/dist/history/index.cjs +12 -2
  115. package/dist/history/index.cjs.map +1 -1
  116. package/dist/history/index.d.cts +211 -7
  117. package/dist/history/index.d.ts +211 -7
  118. package/dist/history/index.js +13 -3
  119. package/dist/image-editor/index.cjs +2244 -38
  120. package/dist/image-editor/index.cjs.map +1 -1
  121. package/dist/image-editor/index.d.cts +742 -4
  122. package/dist/image-editor/index.d.ts +742 -4
  123. package/dist/image-editor/index.js +2222 -16
  124. package/dist/image-editor/index.js.map +1 -1
  125. package/dist/{index-CCr_z9kF.d.cts → index-BhJBSm2d.d.cts} +370 -4
  126. package/dist/{index-Ck6ajwXh.d.ts → index-fJrlkJCd.d.ts} +370 -4
  127. package/dist/index.cjs +193 -98
  128. package/dist/index.cjs.map +1 -1
  129. package/dist/index.d.cts +17 -48
  130. package/dist/index.d.ts +17 -48
  131. package/dist/index.js +198 -103
  132. package/dist/index.js.map +1 -1
  133. package/dist/migrate-iTlm3a8h.d.cts +112 -0
  134. package/dist/migrate-iTlm3a8h.d.ts +112 -0
  135. package/dist/persistence/index.cjs +676 -0
  136. package/dist/persistence/index.cjs.map +1 -0
  137. package/dist/persistence/index.d.cts +347 -0
  138. package/dist/persistence/index.d.ts +347 -0
  139. package/dist/persistence/index.js +676 -0
  140. package/dist/persistence/index.js.map +1 -0
  141. package/dist/registry-BDe-vlv3.d.ts +171 -0
  142. package/dist/registry-D32LpIc4.d.cts +354 -0
  143. package/dist/registry-DnzpgY27.d.cts +171 -0
  144. package/dist/registry-evKTP4ls.d.ts +354 -0
  145. package/dist/schema-DYDGdYL9.d.cts +41 -0
  146. package/dist/schema-DYDGdYL9.d.ts +41 -0
  147. package/dist/serializers/index.cjs +4 -3
  148. package/dist/serializers/index.cjs.map +1 -1
  149. package/dist/serializers/index.d.cts +2 -1
  150. package/dist/serializers/index.d.ts +2 -1
  151. package/dist/serializers/index.js +3 -2
  152. package/dist/sourcemap-C8AH3MBQ.d.cts +91 -0
  153. package/dist/sourcemap-DA1Evhrv.d.ts +91 -0
  154. package/dist/spreadsheet/index.cjs +53 -3
  155. package/dist/spreadsheet/index.cjs.map +1 -1
  156. package/dist/spreadsheet/index.d.cts +247 -18
  157. package/dist/spreadsheet/index.d.ts +247 -18
  158. package/dist/spreadsheet/index.js +58 -8
  159. package/dist/{tokens-CyLZmIei.d.cts → tokens-D7yXvUU6.d.cts} +15 -2
  160. package/dist/{tokens-CyLZmIei.d.ts → tokens-D7yXvUU6.d.ts} +15 -2
  161. package/dist/{track-changes-BSF58RK0.d.cts → track-changes-BK5sVf4_.d.cts} +18 -136
  162. package/dist/{track-changes-BSF58RK0.d.ts → track-changes-CDjCrwKe.d.ts} +18 -136
  163. package/dist/{types-CJ4U-HHI.d.ts → types-DX4Mh4SL.d.cts} +1 -1
  164. package/dist/{types-CJ4U-HHI.d.cts → types-DX4Mh4SL.d.ts} +1 -1
  165. package/dist/types-GT5a5YAX.d.cts +86 -0
  166. package/dist/types-GT5a5YAX.d.ts +86 -0
  167. package/package.json +23 -2
  168. package/dist/chunk-2TWGLC5K.cjs +0 -262
  169. package/dist/chunk-2TWGLC5K.cjs.map +0 -1
  170. package/dist/chunk-4SUNJZWB.cjs.map +0 -1
  171. package/dist/chunk-6M3BCTBD.cjs.map +0 -1
  172. package/dist/chunk-AA4ZEVCC.cjs.map +0 -1
  173. package/dist/chunk-AXV2ZW34.cjs +0 -118
  174. package/dist/chunk-AXV2ZW34.cjs.map +0 -1
  175. package/dist/chunk-B2ZRLN4S.js +0 -118
  176. package/dist/chunk-B2ZRLN4S.js.map +0 -1
  177. package/dist/chunk-DENSCKFC.js.map +0 -1
  178. package/dist/chunk-GVSMRPHB.cjs.map +0 -1
  179. package/dist/chunk-KAADNAPF.js +0 -262
  180. package/dist/chunk-KAADNAPF.js.map +0 -1
  181. package/dist/chunk-MJZBNWG7.js.map +0 -1
  182. package/dist/chunk-OYXSKQFR.js.map +0 -1
  183. package/dist/chunk-QGHGJ56O.js.map +0 -1
  184. package/dist/chunk-RU52I7QO.js.map +0 -1
  185. package/dist/chunk-SAZRENEZ.cjs.map +0 -1
  186. package/dist/types-BZgcDsC5.d.cts +0 -42
  187. package/dist/types-BZgcDsC5.d.ts +0 -42
  188. /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();
@@ -414,9 +414,7 @@ function toNumber(value) {
414
414
  if (isBlank(value)) return 0;
415
415
  if (typeof value === "boolean") return value ? 1 : 0;
416
416
  if (typeof value === "number") return value;
417
- const trimmed = String(value).trim();
418
- const num = trimmed === "" ? NaN : Number(trimmed);
419
- return isNaN(num) ? "#VALUE!" : num;
417
+ return _nullishCoalesce(parseNumberText(String(value)), () => ( "#VALUE!"));
420
418
  }
421
419
  function toBoolean(value) {
422
420
  if (isFormulaError(value)) return value;
@@ -428,7 +426,26 @@ function toBoolean(value) {
428
426
  if (upper === "FALSE") return false;
429
427
  return "#VALUE!";
430
428
  }
431
- var toText = (value) => isBlank(value) ? "" : typeof value === "boolean" ? value ? "TRUE" : "FALSE" : String(value);
429
+ var toText = (value) => isBlank(value) ? "" : typeof value === "boolean" ? value ? "TRUE" : "FALSE" : typeof value === "number" ? numberToText(value) : String(value);
430
+ function numberToText(n) {
431
+ if (n === 0 || !Number.isFinite(n)) return "0";
432
+ const a = Math.abs(n);
433
+ if ((a < 1e-9 || a >= 1e15) && Math.round(a) !== a || a >= 1e15) return sciText(n, 15);
434
+ let mag = Math.floor(Math.log10(a));
435
+ if (a >= Math.pow(10, mag + 1)) mag++;
436
+ const decimals = Math.min(Math.max(14 - mag, 0), 30);
437
+ return trimDecimal(n.toFixed(decimals));
438
+ }
439
+ function trimDecimal(s) {
440
+ if (!s.includes(".")) return s;
441
+ const t = s.replace(/0+$/, "").replace(/\.$/, "");
442
+ return t === "-0" ? "0" : t;
443
+ }
444
+ function sciText(n, sig) {
445
+ const [mantissa, exp] = n.toExponential(Math.max(sig - 1, 0)).split("e");
446
+ const e = Number(exp);
447
+ return `${trimDecimal(mantissa)}E${e < 0 ? "-" : "+"}${String(Math.abs(e)).padStart(2, "0")}`;
448
+ }
432
449
  function numericValue(value) {
433
450
  if (typeof value === "number") return Number.isFinite(value) ? value : null;
434
451
  if (typeof value !== "string" || FORMULA_ERRORS.has(value)) return null;
@@ -441,22 +458,68 @@ function normalizeValue(value) {
441
458
  const num = typeof value === "string" ? numericValue(value) : null;
442
459
  return num === null ? value : num;
443
460
  }
461
+ var ERROR_ORDER = ["#NULL!", "#DIV/0!", "#VALUE!", "#REF!", "#NAME?", "#NUM!", "#N/A", "#SPILL!", "#CALC!", "#CYCLE!", "#ERROR!"];
462
+ function valueRank(value) {
463
+ if (isBlank(value)) return 4;
464
+ if (typeof value === "number") return 0;
465
+ if (typeof value === "boolean") return 2;
466
+ if (typeof value === "string" && FORMULA_ERRORS.has(value)) return 3;
467
+ return 1;
468
+ }
469
+ function compareNumbers(a, b) {
470
+ if (a === b) return 0;
471
+ if (Math.abs(a - b) > Math.max(Math.abs(a), Math.abs(b)) * 1e-13) return a < b ? -1 : 1;
472
+ const round15 = (x2) => !Number.isFinite(x2) || x2 === 0 ? x2 : Number(x2.toExponential(14));
473
+ const x = round15(a);
474
+ const y = round15(b);
475
+ return x < y ? -1 : x > y ? 1 : 0;
476
+ }
477
+ function compareText(a, b) {
478
+ const x = a.toLowerCase();
479
+ const y = b.toLowerCase();
480
+ return x < y ? -1 : x > y ? 1 : 0;
481
+ }
444
482
  function compareValues(left, right) {
445
- if (typeof left === "string" && typeof right === "string") {
446
- const a = isoDateTime(left);
447
- const b = a === null ? null : isoDateTime(right);
448
- if (a !== null && b !== null) return a - b;
449
- }
450
- const rank = (v) => typeof v === "boolean" ? 2 : typeof v === "string" ? 1 : 0;
451
- const l = isBlank(left) ? typeof right === "string" ? "" : 0 : left;
452
- const r = isBlank(right) ? typeof l === "string" ? "" : 0 : right;
453
- if (rank(l) !== rank(r)) return rank(l) - rank(r);
454
- if (typeof l === "string") {
455
- const a = l.toLowerCase();
456
- const b = r.toLowerCase();
457
- return a < b ? -1 : a > b ? 1 : 0;
458
- }
459
- return Number(l) - Number(r);
483
+ const lRank = valueRank(left);
484
+ const rRank = valueRank(right);
485
+ if (lRank === 4 || rRank === 4) {
486
+ if (lRank === rRank) return 0;
487
+ const blankFirst = lRank === 4;
488
+ const other = blankFirst ? right : left;
489
+ const otherRank = blankFirst ? rRank : lRank;
490
+ let cmp;
491
+ if (otherRank === 0) cmp = compareNumbers(0, other);
492
+ else if (otherRank === 1) cmp = String(other) === "" ? 0 : -1;
493
+ else if (otherRank === 2) cmp = other ? -1 : 0;
494
+ else return lRank - rRank;
495
+ return blankFirst ? cmp : -cmp;
496
+ }
497
+ if (lRank === 1 && rRank === 1) {
498
+ const a = String(left);
499
+ const b = String(right);
500
+ const ta = isoDateTime(a);
501
+ const tb = ta === null ? null : isoDateTime(b);
502
+ if (ta !== null && tb !== null) return Math.sign(ta - tb);
503
+ return compareText(a, b);
504
+ }
505
+ if (lRank === 0 && rRank === 1 || lRank === 1 && rRank === 0) {
506
+ const date = parseIsoDate(lRank === 1 ? left : right);
507
+ if (date) {
508
+ const serial = dateToSerial(date);
509
+ return lRank === 0 ? compareNumbers(left, serial) : compareNumbers(serial, right);
510
+ }
511
+ }
512
+ if (lRank !== rRank) return lRank - rRank;
513
+ if (lRank === 0) return compareNumbers(left, right);
514
+ if (lRank === 2) return Number(left) - Number(right);
515
+ return Math.sign(ERROR_ORDER.indexOf(left) - ERROR_ORDER.indexOf(right));
516
+ }
517
+ function sortCompareValues(left, right) {
518
+ const lBlank = isBlank(left);
519
+ const rBlank = isBlank(right);
520
+ if (lBlank || rBlank) return lBlank === rBlank ? 0 : lBlank ? 1 : -1;
521
+ if (isFormulaError(left) && isFormulaError(right)) return 0;
522
+ return compareValues(left, right);
460
523
  }
461
524
  function roundHalfAwayFromZero(value, decimals) {
462
525
  const factor = Math.pow(10, decimals);
@@ -565,6 +628,282 @@ var daysBetween = (start, end) => Math.round(
565
628
  (Date.UTC(end.getFullYear(), end.getMonth(), end.getDate()) - Date.UTC(start.getFullYear(), start.getMonth(), start.getDate())) / MS_PER_DAY
566
629
  );
567
630
 
631
+ // src/spreadsheet/formula/parse-input.ts
632
+ var MONTH_NAMES = [
633
+ "January",
634
+ "February",
635
+ "March",
636
+ "April",
637
+ "May",
638
+ "June",
639
+ "July",
640
+ "August",
641
+ "September",
642
+ "October",
643
+ "November",
644
+ "December"
645
+ ];
646
+ function daysFromCivil(year, month, day) {
647
+ const y = month <= 2 ? year - 1 : year;
648
+ const era = Math.floor((y >= 0 ? y : y - 399) / 400);
649
+ const yoe = y - era * 400;
650
+ const doy = Math.floor((153 * (month > 2 ? month - 3 : month + 9) + 2) / 5) + day - 1;
651
+ const doe = yoe * 365 + Math.floor(yoe / 4) - Math.floor(yoe / 100) + doy;
652
+ return era * 146097 + doe - 719468;
653
+ }
654
+ var isLeapYear = (y) => y % 4 === 0 && y % 100 !== 0 || y % 400 === 0;
655
+ function daysInMonth(year, month) {
656
+ if (month === 2) return isLeapYear(year) ? 29 : 28;
657
+ if ([4, 6, 9, 11].includes(month)) return 30;
658
+ return month >= 1 && month <= 12 ? 31 : 0;
659
+ }
660
+ var daysInMonth1900 = (year, month) => year === 1900 && month === 2 ? 29 : daysInMonth(year, month);
661
+ var UNIX_1899_12_30 = -25569;
662
+ var MAX_SERIAL_1900 = 2958465;
663
+ function serialFromYmd(year, month, day) {
664
+ if (![year, month, day].every(Number.isSafeInteger)) return null;
665
+ let y = year >= 0 && year < 1900 ? year + 1900 : year;
666
+ const m0 = month - 1;
667
+ y += Math.floor(m0 / 12);
668
+ const m = (m0 % 12 + 12) % 12 + 1;
669
+ if (y < 1900 || y > 9999) return null;
670
+ const first = daysFromCivil(y, m, 1) - UNIX_1899_12_30 - (y === 1900 && m <= 2 ? 1 : 0);
671
+ const serial = first + day - 1;
672
+ return serial >= 0 && serial <= MAX_SERIAL_1900 ? serial : null;
673
+ }
674
+ var timeFraction = (h, m, s) => (h * 3600 + m * 60 + s) / 86400;
675
+ var currentYear = () => (/* @__PURE__ */ new Date()).getFullYear();
676
+ function parseCellInput(input) {
677
+ if (input === "") return { value: "", type: "empty" };
678
+ if (input.startsWith("'")) return { value: input.slice(1), type: "text" };
679
+ const t = input.trim();
680
+ const upper = t.toUpperCase();
681
+ if (upper === "TRUE") return { value: true, type: "boolean" };
682
+ if (upper === "FALSE") return { value: false, type: "boolean" };
683
+ if (FORMULA_ERRORS.has(upper)) return { value: upper, type: "error" };
684
+ const numeric = parseNumeric(t);
685
+ if (numeric) {
686
+ if (numeric.kind === "date") {
687
+ const iso = isoText(numeric.date);
688
+ if (iso !== null) {
689
+ return { value: iso, type: "date", numberFormat: numeric.format, formatKind: "date", cellFormat: "date" };
690
+ }
691
+ } else {
692
+ const formatKind = numeric.kind === "time" ? "time" : formatKindOf(numeric.format);
693
+ return {
694
+ value: normalizeZero(numeric.value),
695
+ type: "number",
696
+ ...numeric.format ? { numberFormat: numeric.format } : {},
697
+ ...formatKind ? { formatKind } : {},
698
+ ...formatKind && formatKind !== "time" ? { cellFormat: formatKind } : {}
699
+ };
700
+ }
701
+ }
702
+ return { value: input, type: "text" };
703
+ }
704
+ function parseNumberText(text) {
705
+ const numeric = parseNumeric(text.trim());
706
+ if (!numeric) return null;
707
+ if (numeric.kind !== "date") return normalizeZero(numeric.value);
708
+ const { year, month, day, time = 0 } = numeric.date;
709
+ const serial = serialFromYmd(year, month, day);
710
+ return serial === null ? null : serial + time;
711
+ }
712
+ var normalizeZero = (n) => n === 0 ? 0 : n;
713
+ function formatKindOf(format) {
714
+ if (!format) return void 0;
715
+ if (format.includes("$")) return "currency";
716
+ if (format.includes("%")) return "percentage";
717
+ return "number";
718
+ }
719
+ var pad2 = (n, width = 2) => String(n).padStart(width, "0");
720
+ function isoText({ year, month, day, time }) {
721
+ if (day > daysInMonth(year, month)) return null;
722
+ const date = `${pad2(year, 4)}-${pad2(month)}-${pad2(day)}`;
723
+ if (time === void 0) return date;
724
+ let seconds = Math.round(time * 86400);
725
+ if (seconds >= 86400) seconds = 86399;
726
+ return `${date} ${pad2(Math.floor(seconds / 3600))}:${pad2(Math.floor(seconds / 60) % 60)}:${pad2(seconds % 60)}`;
727
+ }
728
+ function parseNumeric(t) {
729
+ if (t === "") return null;
730
+ if (t.startsWith("(") && t.endsWith(")") && t.length >= 2) {
731
+ const inner = parseNumeric(t.slice(1, -1).trim());
732
+ if (!inner || inner.kind === "date") return null;
733
+ return { ...inner, value: -inner.value };
734
+ }
735
+ const plain = parsePlain(t);
736
+ if (plain) return plain;
737
+ const fraction = parseFraction(t);
738
+ if (fraction !== null) return { kind: "number", value: fraction, format: "# ?/?" };
739
+ return parseDateTime(t);
740
+ }
741
+ var startsWithDigitOrDot = (s) => /^[0-9.]/.test(s);
742
+ function parsePlain(t) {
743
+ let s = t;
744
+ let neg = false;
745
+ let currency = false;
746
+ let percent = false;
747
+ if (s.startsWith("-")) {
748
+ neg = true;
749
+ s = s.slice(1).trimStart();
750
+ } else if (s.startsWith("+")) {
751
+ s = s.slice(1).trimStart();
752
+ }
753
+ if (s.startsWith("$")) {
754
+ currency = true;
755
+ s = s.slice(1).trimStart();
756
+ if (!neg && s.startsWith("-")) {
757
+ neg = true;
758
+ s = s.slice(1);
759
+ }
760
+ }
761
+ if (s.endsWith("%")) {
762
+ percent = true;
763
+ s = s.slice(0, -1).trimEnd();
764
+ }
765
+ if (s === "") return null;
766
+ const hasSep = s.includes(",");
767
+ let digits;
768
+ if (hasSep) {
769
+ const dot = s.indexOf(".");
770
+ const int = dot === -1 ? s : s.slice(0, dot);
771
+ const frac = dot === -1 ? null : s.slice(dot + 1);
772
+ const groups = int.split(",");
773
+ const first = groups[0];
774
+ if (first === "" || first.length > 3 || groups.slice(1).some((g) => g.length !== 3)) return null;
775
+ digits = groups.join("") + (frac !== null ? `.${frac}` : "");
776
+ } else {
777
+ digits = s;
778
+ }
779
+ if (!/^[0-9.eE+-]+$/.test(digits) || !startsWithDigitOrDot(digits)) return null;
780
+ if (!/^(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/.test(digits)) return null;
781
+ let n = Number(digits);
782
+ if (!Number.isFinite(n)) return null;
783
+ const sci = /[eE]/.test(digits);
784
+ if (percent) n /= 100;
785
+ if (neg) n = -n;
786
+ const hasDot = digits.includes(".");
787
+ const format = currency ? hasDot ? '"$"#,##0.00' : '"$"#,##0' : percent ? hasDot ? "0.00%" : "0%" : sci ? "0.00E+00" : hasSep ? hasDot ? "#,##0.00" : "#,##0" : void 0;
788
+ return { kind: "number", value: n, ...format ? { format } : {} };
789
+ }
790
+ var parseDecimal = (s) => /^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/.test(s) ? Number(s) : null;
791
+ function parseFraction(t) {
792
+ const space = t.indexOf(" ");
793
+ if (space === -1) return null;
794
+ const whole = t.slice(0, space);
795
+ const frac = t.slice(space + 1).trim();
796
+ const neg = whole.startsWith("-");
797
+ const w = parseDecimal(whole.replace(/^-+/, ""));
798
+ const slash = frac.indexOf("/");
799
+ if (w === null || slash === -1) return null;
800
+ const a = parseDecimal(frac.slice(0, slash));
801
+ const b = parseDecimal(frac.slice(slash + 1));
802
+ if (a === null || b === null || b === 0 || !Number.isFinite(w)) return null;
803
+ const v = w + a / b;
804
+ return neg ? -v : v;
805
+ }
806
+ function monthFromName(s) {
807
+ const l = s.toLowerCase();
808
+ if (l.length < 3) return null;
809
+ const index = MONTH_NAMES.findIndex((m) => m.toLowerCase().startsWith(l));
810
+ return index === -1 ? null : index + 1;
811
+ }
812
+ function parseTime(input) {
813
+ const lower = input.trim().toLowerCase();
814
+ let body = lower;
815
+ let pm = null;
816
+ for (const [suffix, isPm] of [["am", false], ["a", false], ["pm", true], ["p", true]]) {
817
+ if (lower.endsWith(suffix)) {
818
+ body = lower.slice(0, -suffix.length).trim();
819
+ pm = isPm;
820
+ break;
821
+ }
822
+ }
823
+ const parts = body.split(":");
824
+ if (parts.length === 1 && pm === null) return null;
825
+ if (parts.length > 3 || parts.some((p) => p === "")) return null;
826
+ const num = (p) => p === void 0 ? 0 : parseDecimal(p);
827
+ let h = num(parts[0]);
828
+ const m = num(parts[1]);
829
+ const s = num(parts[2]);
830
+ if (h === null || m === null || s === null) return null;
831
+ if (m >= 60 || s >= 60 || h < 0 || m < 0 || s < 0) return null;
832
+ if (pm !== null) {
833
+ if (h > 12) return null;
834
+ if (h === 12) h = 0;
835
+ if (pm) h += 12;
836
+ } else if (h >= 1e4) {
837
+ return null;
838
+ }
839
+ return { fraction: timeFraction(h, m, s), seconds: parts.length === 3, ampm: pm !== null };
840
+ }
841
+ var expandYear = (text, y) => text.length <= 2 ? y < 30 ? 2e3 + y : 1900 + y : y;
842
+ function validYmd(year, month, day) {
843
+ if (month < 1 || month > 12 || day < 1 || year < 1900 || year > 9999) return null;
844
+ if (day > daysInMonth1900(year, month)) return null;
845
+ return { year, month, day };
846
+ }
847
+ function parseDate(input) {
848
+ const t = input.trim().replace(/,+$/, "");
849
+ const num = (s) => /^[+-]?\d+$/.test(s.trim()) ? Number(s.trim()) : null;
850
+ const withFormat = (date, format) => date ? { date, format } : null;
851
+ const parts = t.split(/[/.-]/);
852
+ if (parts.length === 3) {
853
+ const [a, b, c] = parts.map((p) => p.trim());
854
+ if (a.length === 4) {
855
+ const [y2, m2, d2] = [num(a), num(b), num(c)];
856
+ if (y2 !== null && m2 !== null && d2 !== null) return withFormat(validYmd(y2, m2, d2), "yyyy-mm-dd");
857
+ }
858
+ {
859
+ const [m2, d2, y2] = [num(a), num(b), num(c)];
860
+ if (m2 !== null && d2 !== null && y2 !== null) return withFormat(validYmd(expandYear(c, y2), m2, d2), "m/d/yyyy");
861
+ }
862
+ const [d, m, y] = [num(a), monthFromName(b), num(c)];
863
+ if (d !== null && m !== null && y !== null) return withFormat(validYmd(expandYear(c, y), m, d), "d-mmm-yy");
864
+ }
865
+ if (parts.length === 2) {
866
+ const [a, b] = parts.map((p) => p.trim());
867
+ const [x, y] = [num(a), num(b)];
868
+ if (x !== null && y !== null) {
869
+ if (x >= 1 && x <= 12 && y >= 1 && y <= 31) return withFormat(validYmd(currentYear(), x, y), "d-mmm");
870
+ if (x >= 1 && x <= 12 && b.length === 4) return withFormat(validYmd(y, x, 1), "mmm-yy");
871
+ }
872
+ const dayA = num(a);
873
+ const monthB = monthFromName(b);
874
+ if (dayA !== null && monthB !== null) return withFormat(validYmd(currentYear(), monthB, dayA), "d-mmm");
875
+ const monthA = monthFromName(a);
876
+ const yearB = num(b);
877
+ if (monthA !== null && yearB !== null) return withFormat(validYmd(expandYear(b, yearB), monthA, 1), "mmm-yy");
878
+ }
879
+ const words = t.split(/[ ,]/).filter((w) => w !== "");
880
+ if (words.length === 3) {
881
+ const [w0, w1, w2] = words;
882
+ let [m, d, y] = [monthFromName(w0), num(w1), num(w2)];
883
+ if (m !== null && d !== null && y !== null) return withFormat(validYmd(expandYear(w2, y), m, d), "d-mmm-yy");
884
+ [d, m, y] = [num(w0), monthFromName(w1), num(w2)];
885
+ if (d !== null && m !== null && y !== null) return withFormat(validYmd(expandYear(w2, y), m, d), "d-mmm-yy");
886
+ }
887
+ return null;
888
+ }
889
+ function parseDateTime(t) {
890
+ const time = parseTime(t);
891
+ if (time) {
892
+ const format = time.fraction >= 1 ? "[h]:mm:ss" : time.seconds ? time.ampm ? "h:mm:ss AM/PM" : "h:mm:ss" : time.ampm ? "h:mm AM/PM" : "h:mm";
893
+ return { kind: "time", value: time.fraction, format };
894
+ }
895
+ const date = parseDate(t);
896
+ if (date) return { kind: "date", date: date.date, format: date.format };
897
+ for (let i = t.indexOf(" "); i !== -1; i = t.indexOf(" ", i + 1)) {
898
+ const d = parseDate(t.slice(0, i));
899
+ const tm = d ? parseTime(t.slice(i + 1)) : null;
900
+ if (d && tm && tm.fraction < 1) {
901
+ return { kind: "date", date: { ...d.date, time: tm.fraction }, format: "m/d/yyyy h:mm" };
902
+ }
903
+ }
904
+ return null;
905
+ }
906
+
568
907
  // src/spreadsheet/formula/criteria.ts
569
908
  function wildcardToRegExp(pattern) {
570
909
  let source = "";
@@ -601,12 +940,17 @@ function parseCriteria(criterion) {
601
940
  if (op === "<>") return (value) => !isBlank(value);
602
941
  return () => false;
603
942
  }
604
- const operandNumber = numericValue(operand);
943
+ const parsed = parseCellInput(operand.trim());
944
+ const operandNumber = _nullishCoalesce(numericValue(operand), () => ( (parsed.type === "number" ? parsed.value : null)));
945
+ const operandDate = parsed.type === "date" ? parsed.value : null;
946
+ const isDateValue = (value) => typeof value === "number" || parseIsoDate(value) !== null;
605
947
  const operandUpper = operand.trim().toUpperCase();
606
948
  const operandBoolean = operandUpper === "TRUE" ? true : operandUpper === "FALSE" ? false : null;
607
949
  if (op === "=" || op === "<>") {
608
950
  let equals;
609
- if (operandNumber !== null) {
951
+ if (operandDate !== null) {
952
+ equals = (value) => isDateValue(value) && compareValues(value, operandDate) === 0;
953
+ } else if (operandNumber !== null) {
610
954
  equals = (value) => numericValue(value) === operandNumber;
611
955
  } else if (operandBoolean !== null) {
612
956
  equals = (value) => value === operandBoolean || typeof value === "string" && value.trim().toUpperCase() === operandUpper;
@@ -619,6 +963,9 @@ function parseCriteria(criterion) {
619
963
  return op === "=" ? (value) => !isFormulaError(value) && equals(value) : (value) => !isFormulaError(value) && !equals(value);
620
964
  }
621
965
  const test = (cmp) => op === "<" ? cmp < 0 : op === "<=" ? cmp <= 0 : op === ">" ? cmp > 0 : cmp >= 0;
966
+ if (operandDate !== null) {
967
+ return (value) => isDateValue(value) && test(compareValues(value, operandDate));
968
+ }
622
969
  if (operandNumber !== null) {
623
970
  return (value) => {
624
971
  const num = numericValue(value);
@@ -635,173 +982,1343 @@ function parseCriteria(criterion) {
635
982
  };
636
983
  }
637
984
 
638
- // src/spreadsheet/formula/format.ts
639
- function formatValueWithCode(value, format) {
640
- if (isDateFormat(format)) {
641
- const date = toDate(value);
642
- return date ? formatDate(date, format) : null;
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);
643
994
  }
644
- const num = typeof value === "boolean" ? null : numericValue(value);
645
- return num === null ? toText(value) : formatNumber(num, format);
995
+ return { digits, exp: Number(s.slice(e + 1)) };
646
996
  }
647
- function tokenize(format) {
648
- const out = [];
649
- const push = (literal, text) => {
650
- const last = out[out.length - 1];
651
- if (last && last.literal === literal) last.text += text;
652
- else out.push({ literal, text });
653
- };
654
- for (let i = 0; i < format.length; i++) {
655
- const char = format[i];
656
- if (char === '"') {
657
- const end = format.indexOf('"', i + 1);
658
- const stop = end === -1 ? format.length : end;
659
- push(true, format.slice(i + 1, stop));
660
- i = stop;
661
- } else if (char === "\\" && i + 1 < format.length) {
662
- push(true, format[++i]);
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;
1036
+ } else {
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("");
663
1258
  } else {
664
- push(false, char);
1259
+ out[cur] += c;
665
1260
  }
666
1261
  }
667
1262
  return out;
668
1263
  }
669
- var codeText = (format) => tokenize(format).filter((t) => !t.literal).map((t) => t.text).join("");
670
- function isDateFormat(format) {
671
- const code = codeText(format);
672
- if (/[0#?]/.test(code)) return false;
673
- return /[ydhs]|m/i.test(code);
674
- }
675
- function formatNumber(num, format) {
676
- const sections = splitSections(format);
677
- let section = sections[0];
678
- let value = num;
679
- let sign = num < 0 ? "-" : "";
680
- if (num < 0 && sections.length > 1) {
681
- section = sections[1];
682
- value = Math.abs(num);
683
- sign = "";
684
- } else if (num === 0 && sections.length > 2) {
685
- section = sections[2];
686
- }
687
- let prefix = "";
688
- let suffix = "";
689
- let pattern = "";
690
- for (const token of tokenize(section)) {
691
- if (token.literal) {
692
- if (pattern) suffix += token.text;
693
- 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;
1359
+ continue;
1360
+ }
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;
694
1370
  continue;
695
1371
  }
696
- for (let i = 0; i < token.text.length; i++) {
697
- const char = token.text[i];
698
- const isExponent = /e/i.test(char) && /[+-]/.test(_nullishCoalesce(token.text[i + 1], () => ( "")));
699
- const isExponentSign = /[+-]/.test(char) && /e$/i.test(pattern);
700
- if (/[0#?.,]/.test(char) || pattern && (isExponent || isExponentSign)) {
701
- pattern += char;
702
- } else if (pattern) {
703
- suffix += char;
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;
704
1377
  } else {
705
- prefix += char;
706
- }
707
- }
708
- }
709
- const percents = (prefix + suffix).split("%").length - 1;
710
- value = Math.abs(value) * Math.pow(100, percents);
711
- if (!pattern) return `${sign}${prefix}${suffix}`;
712
- const expMatch = /^([^Ee]*)[Ee]([+-])(0+)$/.exec(pattern);
713
- if (expMatch) {
714
- const [, mantissa, expSign, expDigits] = expMatch;
715
- const decimals = (_nullishCoalesce(mantissa.split(".")[1], () => ( ""))).length;
716
- const [m, e] = value.toExponential(decimals).split("e");
717
- const exponent = Number(e);
718
- const expText = String(Math.abs(exponent)).padStart(expDigits.length, "0");
719
- const shownSign = exponent < 0 ? "-" : expSign === "+" ? "+" : "";
720
- return `${sign}${prefix}${m}E${shownSign}${expText}${suffix}`;
721
- }
722
- const [intPattern, decPattern = ""] = pattern.split(".");
723
- const maxDecimals = (_nullishCoalesce(decPattern.match(/[0#?]/g), () => ( []))).length;
724
- const minDecimals = (_nullishCoalesce(decPattern.match(/0/g), () => ( []))).length;
725
- const minInt = (_nullishCoalesce(intPattern.match(/0/g), () => ( []))).length;
726
- const grouping = intPattern.includes(",");
727
- const rounded = roundHalfAwayFromZero(value, maxDecimals);
728
- let [intPart, decPart = ""] = rounded.toFixed(maxDecimals).split(".");
729
- while (decPart.length > minDecimals && decPart.endsWith("0")) decPart = decPart.slice(0, -1);
730
- if (intPart === "0" && minInt === 0) intPart = "";
731
- intPart = intPart.padStart(minInt, "0");
732
- if (grouping) intPart = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
733
- const showSign = sign && /[1-9]/.test(intPart + decPart) ? sign : "";
734
- return `${showSign}${prefix}${intPart}${decPart ? `.${decPart}` : ""}${suffix}`;
735
- }
736
- function splitSections(format) {
737
- const sections = [""];
738
- let quoted = false;
739
- for (let i = 0; i < format.length; i++) {
740
- const char = format[i];
741
- if (char === '"') quoted = !quoted;
742
- if (char === "\\" && i + 1 < format.length) {
743
- sections[sections.length - 1] += char + format[++i];
1378
+ pushLit(toks, "[");
1379
+ i += 1;
1380
+ }
744
1381
  continue;
745
1382
  }
746
- if (char === ";" && !quoted) sections.push("");
747
- 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;
1430
+ }
1431
+ return raw;
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
+ }
748
1538
  }
749
- return sections;
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;
750
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;
751
1613
  var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
752
- var DAYS = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
753
- var pad2 = (n) => String(n).padStart(2, "0");
754
- function formatDate(date, format) {
755
- const parts = [];
756
- for (const token of tokenize(format)) {
757
- if (token.literal) {
758
- 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);
759
1697
  continue;
760
1698
  }
761
- const re = /AM\/PM|am\/pm|A\/P|a\/p|y+|m+|d+|h+|s+|[^ymdhsaA]+|./gi;
762
- for (const match of _nullishCoalesce(token.text.match(re), () => ( []))) {
763
- const isCode = /^(AM\/PM|A\/P|y+|m+|d+|h+|s+)$/i.test(match);
764
- parts.push({ literal: !isCode, text: match });
1699
+ if (t.t !== "date") {
1700
+ out.push(literalText(t));
1701
+ continue;
765
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);
766
1746
  }
767
- const codes = parts.map((p, i) => ({ ...p, i })).filter((p) => !p.literal);
768
- const twelveHour = codes.some((p) => /^(AM\/PM|A\/P)$/i.test(p.text));
769
- return parts.map((part, index) => {
770
- if (part.literal) return part.text;
771
- const code = part.text;
772
- const lower = code.toLowerCase();
773
- if (/^(am\/pm|a\/p)$/.test(lower)) {
774
- const pm = date.getHours() >= 12;
775
- const full = pm ? "PM" : "AM";
776
- const text = lower === "a/p" ? full[0] : full;
777
- return code[0] === code[0].toLowerCase() ? text.toLowerCase() : text;
778
- }
779
- if (lower.startsWith("y")) {
780
- return lower.length <= 2 ? pad2(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
+ }
781
1781
  }
782
- if (lower.startsWith("d")) {
783
- if (lower.length >= 4) return DAYS[date.getDay()];
784
- if (lower.length === 3) return DAYS[date.getDay()].slice(0, 3);
785
- return lower.length === 2 ? pad2(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;
786
1801
  }
787
- if (lower.startsWith("h")) {
788
- let hours = date.getHours();
789
- if (twelveHour) hours = hours % 12 || 12;
790
- return lower.length >= 2 ? pad2(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;
791
1937
  }
792
- if (lower.startsWith("s")) {
793
- return lower.length >= 2 ? pad2(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);
794
1993
  }
795
- const position = codes.findIndex((c) => c.i === index);
796
- const prev = _nullishCoalesce(_optionalChain([codes, 'access', _5 => _5[position - 1], 'optionalAccess', _6 => _6.text, 'access', _7 => _7.toLowerCase, 'call', _8 => _8()]), () => ( ""));
797
- const next = _nullishCoalesce(_optionalChain([codes, 'access', _9 => _9[position + 1], 'optionalAccess', _10 => _10.text, 'access', _11 => _11.toLowerCase, 'call', _12 => _12()]), () => ( ""));
798
- if (lower.length <= 2 && (prev.startsWith("h") || next.startsWith("s"))) {
799
- return lower.length === 2 ? pad2(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));
800
2165
  }
801
- if (lower.length >= 4) return MONTHS[date.getMonth()];
802
- if (lower.length === 3) return MONTHS[date.getMonth()].slice(0, 3);
803
- return lower.length === 2 ? pad2(date.getMonth() + 1) : String(date.getMonth() + 1);
804
- }).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"));
805
2322
  }
806
2323
 
807
2324
  // src/spreadsheet/formula/functions/helpers.ts
@@ -1806,7 +3323,7 @@ var TEXT_FUNCTIONS = [
1806
3323
  if (isFormulaError(value)) return value;
1807
3324
  if (typeof value === "number") return value;
1808
3325
  if (isBlank(value)) return 0;
1809
- const num = parseNumericText(toText(value));
3326
+ const num = _nullishCoalesce(parseNumericText(toText(value)), () => ( parseNumberText(toText(value))));
1810
3327
  if (num === null) return ctx.argError(0, "#VALUE!", `("${toText(value)}") can't be converted to a number.`);
1811
3328
  return num;
1812
3329
  }
@@ -1814,15 +3331,19 @@ var TEXT_FUNCTIONS = [
1814
3331
  {
1815
3332
  name: "TEXT",
1816
3333
  category: "text",
1817
- 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".',
1818
3335
  args: [arg("value", "The number or date to format."), arg("format_text", "The format code.", "text")],
1819
3336
  evaluate: (ctx) => {
1820
3337
  const value = ctx.scalar(0);
1821
3338
  if (isFormulaError(value)) return value;
1822
3339
  const format = ctx.text(1);
1823
3340
  if (failed(format)) return format;
1824
- const result = formatValueWithCode(value, format);
1825
- 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;
1826
3347
  }
1827
3348
  }
1828
3349
  ];
@@ -1887,15 +3408,15 @@ function tableLookup(ctx, vertical) {
1887
3408
  if (failed(table)) return table;
1888
3409
  const index = ctx.integer(2);
1889
3410
  if (failed(index)) return index;
1890
- const approximate = ctx.boolean(3, true);
1891
- if (failed(approximate)) return approximate;
3411
+ const approximate2 = ctx.boolean(3, true);
3412
+ if (failed(approximate2)) return approximate2;
1892
3413
  const span = vertical ? table.cols : table.rows;
1893
3414
  if (index < 1) return ctx.argError(2, "#VALUE!", "must be 1 or more.");
1894
3415
  if (index > span) {
1895
3416
  return ctx.argError(2, "#REF!", `is larger than the number of ${vertical ? "columns" : "rows"} in the table (${span}).`);
1896
3417
  }
1897
3418
  const keys = vertical ? sliceRange(table, 0, table.rows, 0, 1) : sliceRange(table, 0, 1, 0, table.cols);
1898
- const position = lookupIndex(keys, target, approximate ? "sorted-asc" : "wildcard");
3419
+ const position = lookupIndex(keys, target, approximate2 ? "sorted-asc" : "wildcard");
1899
3420
  if (position === -1) return notFound(ctx, target);
1900
3421
  return vertical ? rangeGet(table, position, index - 1) : rangeGet(table, index - 1, position);
1901
3422
  }
@@ -2661,17 +4182,17 @@ function layoutOf(def) {
2661
4182
  return { fixed: def.args.slice(0, groupStart), group: def.args.slice(groupStart), groupStart };
2662
4183
  }
2663
4184
  function getFormulaArgumentSpecIndex(def, argIndex) {
2664
- const { fixed, group, groupStart } = layoutOf(def);
2665
- if (argIndex < fixed.length) return argIndex;
4185
+ const { fixed: fixed2, group, groupStart } = layoutOf(def);
4186
+ if (argIndex < fixed2.length) return argIndex;
2666
4187
  if (group.length === 0) return -1;
2667
4188
  return groupStart + (argIndex - groupStart) % group.length;
2668
4189
  }
2669
4190
  function checkFormulaArgumentCount(def, count) {
2670
- const { fixed, group } = layoutOf(def);
2671
- const requiredFixed = fixed.filter((arg2) => !arg2.optional).length;
4191
+ const { fixed: fixed2, group } = layoutOf(def);
4192
+ const requiredFixed = fixed2.filter((arg2) => !arg2.optional).length;
2672
4193
  const groupRequired = group.length > 0 && !group[0].optional;
2673
4194
  const min2 = requiredFixed + (groupRequired ? group.length : 0);
2674
- const max2 = group.length > 0 ? Infinity : fixed.length;
4195
+ const max2 = group.length > 0 ? Infinity : fixed2.length;
2675
4196
  const given = `${count} ${count === 1 ? "was" : "were"} given`;
2676
4197
  const plural = (n) => `${n} argument${n === 1 ? "" : "s"}`;
2677
4198
  if (count < min2) {
@@ -2682,8 +4203,8 @@ function checkFormulaArgumentCount(def, count) {
2682
4203
  const expected = min2 === max2 ? plural(max2) : `at most ${plural(max2)}`;
2683
4204
  return max2 === 0 ? `${def.name} takes no arguments, but ${given}.` : `${def.name} takes ${expected}, but ${given}.`;
2684
4205
  }
2685
- if (group.length > 1 && count > fixed.length) {
2686
- const extra = (count - fixed.length) % group.length;
4206
+ if (group.length > 1 && count > fixed2.length) {
4207
+ const extra = (count - fixed2.length) % group.length;
2687
4208
  if (extra !== 0 && !(def.allowTrailingArgument && extra === 1)) {
2688
4209
  const names = group.map((arg2) => arg2.name).join(", ");
2689
4210
  return `${def.name} expects its repeating arguments (${names}) in complete groups.`;
@@ -2694,7 +4215,7 @@ function checkFormulaArgumentCount(def, count) {
2694
4215
  function getFormulaSignatureParts(nameOrDef, activeArgIndex) {
2695
4216
  const def = typeof nameOrDef === "string" ? getFormulaFunction(nameOrDef) : nameOrDef;
2696
4217
  if (!def) return [];
2697
- const { fixed, group, groupStart } = layoutOf(def);
4218
+ const { fixed: fixed2, group, groupStart } = layoutOf(def);
2698
4219
  let activeSpec = -1;
2699
4220
  let activeRepeat = 0;
2700
4221
  if (activeArgIndex !== void 0 && activeArgIndex !== null && activeArgIndex >= 0) {
@@ -2708,7 +4229,7 @@ function getFormulaSignatureParts(nameOrDef, activeArgIndex) {
2708
4229
  if (parts.length > 1) parts.push({ text: ", ", specIndex: null, active: false });
2709
4230
  parts.push({ text, specIndex, active: specIndex === activeSpec && repeat === activeRepeat });
2710
4231
  };
2711
- 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));
2712
4233
  if (group.length > 0) {
2713
4234
  const groupOptional = !!group[0].optional;
2714
4235
  group.forEach((arg2, i) => {
@@ -2768,12 +4289,12 @@ function buildArray(rows, cols, fn) {
2768
4289
  }
2769
4290
  var isMultiArray = (value) => Array.isArray(value) && value.length > 1;
2770
4291
  var firstValue = (value) => Array.isArray(value) ? value.length ? value[0] : "" : value;
2771
- var FormulaEvaluator = (_class2 = class {
4292
+ var FormulaEvaluator = (_class3 = class {
2772
4293
 
2773
- __init3() {this.diagnostics = []}
4294
+ __init5() {this.diagnostics = []}
2774
4295
  // LET variables, innermost scope last.
2775
- __init4() {this.scopes = []}
2776
- 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);
2777
4298
  this.context = context;
2778
4299
  }
2779
4300
  /**
@@ -2808,14 +4329,14 @@ var FormulaEvaluator = (_class2 = class {
2808
4329
  const result = {
2809
4330
  value,
2810
4331
  error: code,
2811
- message: _nullishCoalesce(_optionalChain([diagnostic, 'optionalAccess', _13 => _13.message]), () => ( describeFormulaError(code)))
4332
+ message: _nullishCoalesce(_optionalChain([diagnostic, 'optionalAccess', _38 => _38.message]), () => ( describeFormulaError(code)))
2812
4333
  };
2813
4334
  if (array) result.array = array;
2814
4335
  return result;
2815
4336
  }
2816
4337
  return array ? { value, array } : { value };
2817
4338
  } catch (err) {
2818
- 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" };
2819
4340
  } finally {
2820
4341
  this.diagnostics = saved;
2821
4342
  this.scopes = savedScopes;
@@ -2996,7 +4517,7 @@ var FormulaEvaluator = (_class2 = class {
2996
4517
  const value = this.evaluateNode(argument);
2997
4518
  if (!Array.isArray(value)) return value;
2998
4519
  if (value.length <= 1) return firstValue(value);
2999
- 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()]);
3000
4521
  if (argument.type === "Range" && cell) {
3001
4522
  const range = toFormulaRange(value);
3002
4523
  const top = Math.min(argument.startRow, argument.endRow);
@@ -3078,7 +4599,7 @@ var FormulaEvaluator = (_class2 = class {
3078
4599
  * multi-value array.
3079
4600
  */
3080
4601
  liftOverArrays(def, args) {
3081
- 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";
3082
4603
  const triggers = def.elementwise === true ? args.map((a) => a.index) : def.elementwise;
3083
4604
  if (!triggers.some((i) => i < args.length && liftable(i) && isMultiArray(args[i].value()))) return void 0;
3084
4605
  let rows = 1;
@@ -3198,7 +4719,27 @@ var FormulaEvaluator = (_class2 = class {
3198
4719
  }
3199
4720
  };
3200
4721
  }
3201
- }, _class2);
4722
+ }, _class3);
4723
+
4724
+
4725
+
4726
+
4727
+
4728
+
4729
+
4730
+
4731
+
4732
+
4733
+
4734
+
4735
+
4736
+
4737
+
4738
+
4739
+
4740
+
4741
+
4742
+
3202
4743
 
3203
4744
 
3204
4745
 
@@ -3226,5 +4767,5 @@ var FormulaEvaluator = (_class2 = class {
3226
4767
 
3227
4768
 
3228
4769
 
3229
- 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.FORMULA_ERRORS = FORMULA_ERRORS; exports.isFormulaError = isFormulaError; exports.colNameToIndex = colNameToIndex; exports.indexToColName = indexToColName; exports.wildcardToRegExp = wildcardToRegExp; exports.parseCriteria = parseCriteria; 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;
3230
- //# sourceMappingURL=chunk-SAZRENEZ.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