reamkit 1.32.0 → 1.33.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 (157) hide show
  1. package/README.md +5 -4
  2. package/dist/esm/core/bidi/algorithm.js +2 -2
  3. package/dist/esm/core/bidi/char-types.js +1 -1
  4. package/dist/esm/core/bidi/index.js +3 -3
  5. package/dist/esm/core/bytes.js +1 -1
  6. package/dist/esm/core/converter/facade.js +3 -2
  7. package/dist/esm/core/converter/ream.js +12 -5
  8. package/dist/esm/core/crypto/asn1.js +2 -2
  9. package/dist/esm/core/crypto/cms.js +5 -3
  10. package/dist/esm/core/crypto/index.js +2 -1
  11. package/dist/esm/core/crypto/offcrypto.js +64 -19
  12. package/dist/esm/core/crypto/primitives.js +16 -16
  13. package/dist/esm/core/document-model/index.d.ts +1 -1
  14. package/dist/esm/core/document-model/types.d.ts +174 -2
  15. package/dist/esm/core/drawingml/chart-geometry.d.ts +45 -17
  16. package/dist/esm/core/drawingml/chart-geometry.js +1090 -257
  17. package/dist/esm/core/drawingml/chart-parser.d.ts +24 -1
  18. package/dist/esm/core/drawingml/chart-parser.js +334 -41
  19. package/dist/esm/core/drawingml/chart-text.d.ts +41 -0
  20. package/dist/esm/core/drawingml/chart-text.js +93 -0
  21. package/dist/esm/core/drawingml/colors.js +5 -5
  22. package/dist/esm/core/drawingml/diagram/layout-engine.js +1 -4
  23. package/dist/esm/core/drawingml/diagram/run.js +2 -1
  24. package/dist/esm/core/drawingml/preset-geometry.js +4 -6
  25. package/dist/esm/core/drawingml/shape-render.js +1 -1
  26. package/dist/esm/core/drawingml/text-warp.js +4 -16
  27. package/dist/esm/core/drawingml/theme-parser.js +14 -8
  28. package/dist/esm/core/font/arabic-joining.js +2 -2
  29. package/dist/esm/core/font/binary-reader.js +2 -0
  30. package/dist/esm/core/font/font-registry.js +1 -0
  31. package/dist/esm/core/font/ligatures.js +1 -1
  32. package/dist/esm/core/font/opentype-layout.js +11 -5
  33. package/dist/esm/core/font/ttf-build.js +6 -10
  34. package/dist/esm/core/font/ttf-parser.js +2 -1
  35. package/dist/esm/core/font/ttf-subset.js +8 -8
  36. package/dist/esm/core/fonts/families.js +1 -1
  37. package/dist/esm/core/fonts/remote-fonts.js +4 -4
  38. package/dist/esm/core/hyphenation/index.js +1 -1
  39. package/dist/esm/core/images.js +8 -8
  40. package/dist/esm/core/ir/loss.js +1 -0
  41. package/dist/esm/core/line-breaker/cjk.js +1 -1
  42. package/dist/esm/core/line-breaker/index.js +4 -3
  43. package/dist/esm/core/links.js +1 -1
  44. package/dist/esm/core/lzw.js +1 -1
  45. package/dist/esm/core/metafile/blit.js +1 -1
  46. package/dist/esm/core/metafile/emf.js +5 -7
  47. package/dist/esm/core/metafile/picture.js +1 -1
  48. package/dist/esm/core/metafile/symbol-fonts.js +7 -7
  49. package/dist/esm/core/metafile/wmf.js +5 -7
  50. package/dist/esm/core/number-format.d.ts +40 -15
  51. package/dist/esm/core/number-format.js +284 -79
  52. package/dist/esm/core/numbering/index.js +3 -2
  53. package/dist/esm/core/ole/cfb.js +4 -4
  54. package/dist/esm/core/ole/escher-blip.js +1 -1
  55. package/dist/esm/core/opc/index.js +5 -4
  56. package/dist/esm/core/opc/package.js +3 -1
  57. package/dist/esm/core/opc/tag-scan.d.ts +15 -0
  58. package/dist/esm/core/opc/tag-scan.js +41 -0
  59. package/dist/esm/core/opc/xml-entities.js +40 -3
  60. package/dist/esm/core/outline.js +1 -1
  61. package/dist/esm/core/png-encode.js +3 -3
  62. package/dist/esm/core/po-helpers.js +1 -1
  63. package/dist/esm/core/spreadsheet-model/types.d.ts +6 -0
  64. package/dist/esm/core/style-cascade/index.js +4 -3
  65. package/dist/esm/core/tiff.js +3 -1
  66. package/dist/esm/excel/activex-parser.js +1 -1
  67. package/dist/esm/excel/conditional-format.js +7 -7
  68. package/dist/esm/excel/formula/functions.js +45 -18
  69. package/dist/esm/excel/formula/index.js +3 -3
  70. package/dist/esm/excel/formula/lexer.js +2 -2
  71. package/dist/esm/excel/formula/parser.js +4 -3
  72. package/dist/esm/excel/formula/value.js +1 -1
  73. package/dist/esm/excel/index.js +7 -6
  74. package/dist/esm/excel/print-model.js +18 -7
  75. package/dist/esm/excel/printer-settings.js +6 -7
  76. package/dist/esm/excel/rich-value.js +1 -1
  77. package/dist/esm/excel/sheet-shape-parser.js +4 -2
  78. package/dist/esm/excel/sheet-to-flow.js +13 -11
  79. package/dist/esm/excel/styles-parser.js +5 -3
  80. package/dist/esm/excel/tint.js +5 -5
  81. package/dist/esm/excel/vml-drawing.js +3 -3
  82. package/dist/esm/excel/worksheet-parser.js +5 -5
  83. package/dist/esm/excel/xls/biff-chart.js +1 -3
  84. package/dist/esm/excel/xls/biff-reader.js +10 -11
  85. package/dist/esm/excel/xls/xls-reader.js +1 -1
  86. package/dist/esm/excel/xlsx-reader.js +56 -9
  87. package/dist/esm/excel/xlsx-to-pdf.js +1 -1
  88. package/dist/esm/excel/xlsx-writer.js +2 -2
  89. package/dist/esm/html/html-writer.js +18 -10
  90. package/dist/esm/layout/line-paint.js +1 -1
  91. package/dist/esm/layout/math-layout.js +5 -8
  92. package/dist/esm/layout/styled-layout.js +104 -32
  93. package/dist/esm/layout/turned-section.js +2 -2
  94. package/dist/esm/markdown/markdown-writer.js +59 -8
  95. package/dist/esm/pdf/encryption.js +9 -9
  96. package/dist/esm/pdf/icc-profile.js +2 -2
  97. package/dist/esm/pdf/index.js +3 -2
  98. package/dist/esm/pdf/objects.js +7 -0
  99. package/dist/esm/pdf/serialize.js +1 -1
  100. package/dist/esm/pdf/struct-tree.js +3 -1
  101. package/dist/esm/pdf/styled-page-emitter.js +23 -15
  102. package/dist/esm/pdf/styled-page-renderer.js +9 -5
  103. package/dist/esm/pdf-reader/annot-draw.js +5 -5
  104. package/dist/esm/pdf-reader/annots.js +3 -1
  105. package/dist/esm/pdf-reader/ccitt.js +2 -1
  106. package/dist/esm/pdf-reader/cff-outline.js +1 -4
  107. package/dist/esm/pdf-reader/content.js +13 -15
  108. package/dist/esm/pdf-reader/decrypt.js +5 -4
  109. package/dist/esm/pdf-reader/document.js +6 -2
  110. package/dist/esm/pdf-reader/encodings.js +1 -1
  111. package/dist/esm/pdf-reader/flow-build.js +4 -6
  112. package/dist/esm/pdf-reader/font.js +4 -4
  113. package/dist/esm/pdf-reader/function.js +8 -7
  114. package/dist/esm/pdf-reader/icc.js +1 -1
  115. package/dist/esm/pdf-reader/images.js +1 -1
  116. package/dist/esm/pdf-reader/jbig2.js +36 -38
  117. package/dist/esm/pdf-reader/jpeg.js +14 -13
  118. package/dist/esm/pdf-reader/layout.js +13 -10
  119. package/dist/esm/pdf-reader/lexer.js +2 -1
  120. package/dist/esm/pdf-reader/math-rows.js +2 -2
  121. package/dist/esm/pdf-reader/optional-content.js +1 -1
  122. package/dist/esm/pdf-reader/page-numbers.js +1 -1
  123. package/dist/esm/pdf-reader/pattern-tint.js +1 -2
  124. package/dist/esm/pdf-reader/reader.js +2 -2
  125. package/dist/esm/pdf-reader/struct-tree.js +1 -1
  126. package/dist/esm/pdf-reader/tagged.js +3 -2
  127. package/dist/esm/pdf-reader/text.js +2 -2
  128. package/dist/esm/pdf-reader/type1-outline.js +1 -3
  129. package/dist/esm/pptx/embedded-fonts.js +3 -5
  130. package/dist/esm/pptx/placeholder-cascade.js +1 -1
  131. package/dist/esm/pptx/ppt/ppt-reader.js +5 -4
  132. package/dist/esm/pptx/ppt/ppt-text.js +9 -10
  133. package/dist/esm/pptx/pptx-reader.js +6 -5
  134. package/dist/esm/pptx/preset-table-styles.js +1 -1
  135. package/dist/esm/pptx/slide-parser.js +6 -4
  136. package/dist/esm/pptx/sp-helpers.js +1 -1
  137. package/dist/esm/pptx/table-style.js +2 -1
  138. package/dist/esm/svg/svg-writer.js +1 -1
  139. package/dist/esm/word/doc/doc-reader.js +2 -2
  140. package/dist/esm/word/doc/doc-text.js +20 -22
  141. package/dist/esm/word/document-parser.js +27 -22
  142. package/dist/esm/word/docx-reader.js +15 -10
  143. package/dist/esm/word/docx-to-pdf.js +6 -6
  144. package/dist/esm/word/docx-writer.js +10 -6
  145. package/dist/esm/word/drawing-parser.js +18 -18
  146. package/dist/esm/word/font-table.js +90 -11
  147. package/dist/esm/word/index.js +6 -5
  148. package/dist/esm/word/numbering-parser.js +5 -4
  149. package/dist/esm/word/omml-parser.js +1 -1
  150. package/dist/esm/word/paragraph-properties.js +11 -10
  151. package/dist/esm/word/run-properties.js +4 -4
  152. package/dist/esm/word/settings-parser.js +2 -1
  153. package/dist/esm/word/shading.js +1 -1
  154. package/dist/esm/word/styles-parser.js +5 -4
  155. package/dist/esm/word/table-parser.js +4 -4
  156. package/dist/esm/word/theme-fonts.js +1 -1
  157. package/package.json +10 -4
@@ -3,17 +3,54 @@
3
3
  var MAX_EXPANSION = 65536;
4
4
  /** Longest total the substitutions may add to one part. */
5
5
  var MAX_TOTAL = 1048576;
6
- var DOCTYPE = /<!DOCTYPE\s[^[>]*(?:\[[\s\S]*?\]\s*)?>/;
6
+ var DOCTYPE = /<!DOCTYPE\s[^[>]*(?:\[[\s\S]*?\]\s*)?>/y;
7
7
  var ENTITY_DECL = /<!ENTITY\s+([^\s%<>&;]+)\s+(?:"([^"]*)"|'([^']*)')\s*>/g;
8
8
  var REFERENCE = /&([^\s;&<>]+);/g;
9
9
  /** The five entities XML predefines; a declaration never overrides them. */
10
- var PREDEFINED = new Set([
10
+ var PREDEFINED = /* @__PURE__ */ new Set([
11
11
  "lt",
12
12
  "gt",
13
13
  "amp",
14
14
  "apos",
15
15
  "quot"
16
16
  ]);
17
+ /**
18
+ * The first `<!DOCTYPE …>` of a part — what {@link DOCTYPE} finds searching
19
+ * from the start — tried only where it holds. A search tries every
20
+ * `<!DOCTYPE`, reads on to the first `[` or `>` after it, and from a `[` on to
21
+ * a `]` a `>` follows: a part of `<!DOCTYPE ` written over and over with none
22
+ * of those sent it to the end of the part from each one, before the parser
23
+ * ever saw the part. Every `<!DOCTYPE` before the same first `[` or `>` fares
24
+ * as the one before it, and a `[` that no `]…>` follows fails every one that
25
+ * reaches it, so those are passed over and the expression runs once.
26
+ */
27
+ function findDoctype(xml) {
28
+ let stop = -1;
29
+ let close;
30
+ for (let at = xml.indexOf("<!DOCTYPE"); at >= 0; at = xml.indexOf("<!DOCTYPE", at + 1)) {
31
+ if (!/\s/.test(xml[at + 9] ?? "")) continue;
32
+ if (stop < at + 10) stop = firstBracketOrEnd(xml, at + 10);
33
+ if (stop < 0) return null;
34
+ if (xml[stop] === "[") {
35
+ close ??= lastBracketClose(xml);
36
+ if (close < stop) continue;
37
+ }
38
+ DOCTYPE.lastIndex = at;
39
+ return DOCTYPE.exec(xml);
40
+ }
41
+ return null;
42
+ }
43
+ /** The first `[` or `>` at or after `from`, or -1. */
44
+ function firstBracketOrEnd(xml, from) {
45
+ for (let i = from; i < xml.length; i++) if (xml[i] === "[" || xml[i] === ">") return i;
46
+ return -1;
47
+ }
48
+ /** Where the last `]` stands that, past some whitespace, a `>` follows; or -1. */
49
+ function lastBracketClose(xml) {
50
+ let last = -1;
51
+ for (const m of xml.matchAll(/\]\s*>/g)) last = m.index;
52
+ return last;
53
+ }
17
54
  /** Escape resolved text so it re-enters the document as characters, not markup. */
18
55
  function escape(text) {
19
56
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
@@ -74,7 +111,7 @@ function expander(declared) {
74
111
  */
75
112
  function resolveInternalEntities(xml) {
76
113
  if (!xml.includes("<!DOCTYPE")) return xml;
77
- const doctype = DOCTYPE.exec(xml);
114
+ const doctype = findDoctype(xml);
78
115
  if (!doctype) return xml;
79
116
  const declared = /* @__PURE__ */ new Map();
80
117
  for (const decl of doctype[0].matchAll(ENTITY_DECL)) {
@@ -27,4 +27,4 @@ function headingLevelFromStyleId(styleId) {
27
27
  if (/^(Title|Subtitle)$/i.test(styleId)) return 1;
28
28
  }
29
29
  //#endregion
30
- export { headingLevelOf };
30
+ export { headingLevelFromStyleId, headingLevelOf };
@@ -39,7 +39,7 @@ function encodePng(width, height, color, samples) {
39
39
  raw.set(samples.subarray(y * stride, y * stride + stride), dst + 1);
40
40
  }
41
41
  const idat = zlibSync(raw);
42
- const ihdr = new Uint8Array(13);
42
+ const ihdr = /* @__PURE__ */ new Uint8Array(13);
43
43
  writeU32(ihdr, 0, width);
44
44
  writeU32(ihdr, 4, height);
45
45
  ihdr[8] = 8;
@@ -51,7 +51,7 @@ function encodePng(width, height, color, samples) {
51
51
  SIGNATURE,
52
52
  chunk("IHDR", ihdr),
53
53
  chunk("IDAT", idat),
54
- chunk("IEND", new Uint8Array(0))
54
+ chunk("IEND", /* @__PURE__ */ new Uint8Array(0))
55
55
  ]);
56
56
  }
57
57
  function chunk(type, data) {
@@ -91,7 +91,7 @@ function concat(parts) {
91
91
  var crcTable;
92
92
  function crc32(bytes) {
93
93
  if (!crcTable) {
94
- crcTable = new Uint32Array(256);
94
+ crcTable = /* @__PURE__ */ new Uint32Array(256);
95
95
  for (let n = 0; n < 256; n++) {
96
96
  let c = n;
97
97
  for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
@@ -68,7 +68,7 @@ function poIntAttr(node, name) {
68
68
  if (Number.isFinite(n)) return n;
69
69
  return universalMeasureTwips(v);
70
70
  }
71
- var MEASURE_TWIPS = new Map([
71
+ var MEASURE_TWIPS = /* @__PURE__ */ new Map([
72
72
  ["pt", 20],
73
73
  ["pc", 240],
74
74
  ["pi", 240],
@@ -380,6 +380,12 @@ export interface XlsxFont {
380
380
  */
381
381
  readonly colorRef?: string;
382
382
  readonly name?: string;
383
+ /**
384
+ * §18.8.35 `<scheme>` — the theme font this font stands for, whatever its
385
+ * `name` says. Excel draws such a font in the theme's: a workbook without a
386
+ * theme part writes Calibri this way and is set in Office 2023's Aptos Narrow.
387
+ */
388
+ readonly scheme?: 'major' | 'minor';
383
389
  }
384
390
  /** §18.8.20 `<fill>` — one fill record: pattern type plus foreground/background colours. */
385
391
  export interface XlsxFill {
@@ -1,3 +1,4 @@
1
- import "./types.js";
2
- import "./resolver.js";
3
- import "./table.js";
1
+ import { DEFAULT_RESOLVED_PARAGRAPH, DEFAULT_RESOLVED_RUN } from "./types.js";
2
+ import { EMPTY_STYLE_SHEET, resolveBodyStyles, resolveHeadersFootersStyles, resolveParagraphProperties, resolveRunProperties } from "./resolver.js";
3
+ import { resolveTableStyles } from "./table.js";
4
+ export { DEFAULT_RESOLVED_PARAGRAPH, DEFAULT_RESOLVED_RUN, EMPTY_STYLE_SHEET, resolveBodyStyles, resolveHeadersFootersStyles, resolveParagraphProperties, resolveRunProperties, resolveTableStyles };
@@ -91,7 +91,7 @@ function decodeTiff(bytes) {
91
91
  extra: list(ifd, TAG.extraSamples, [])
92
92
  });
93
93
  }
94
- var TYPE_SIZE = new Map([
94
+ var TYPE_SIZE = /* @__PURE__ */ new Map([
95
95
  [1, 1],
96
96
  [2, 1],
97
97
  [3, 2],
@@ -106,6 +106,8 @@ var TYPE_SIZE = new Map([
106
106
  [12, 8]
107
107
  ]);
108
108
  var Reader = class {
109
+ b;
110
+ le;
109
111
  constructor(b, le) {
110
112
  this.b = b;
111
113
  this.le = le;
@@ -63,7 +63,7 @@ function strAttr(obj, key) {
63
63
  const v = obj[`@_${key}`];
64
64
  return typeof v === "string" ? v : void 0;
65
65
  }
66
- var ACTIVEX_CLASS_TYPES = new Map([["8BD21D40-EC42-11CE-9E0D-00AA006002F3", "checkbox"], ["8BD21D50-EC42-11CE-9E0D-00AA006002F3", "option"]]);
66
+ var ACTIVEX_CLASS_TYPES = /* @__PURE__ */ new Map([["8BD21D40-EC42-11CE-9E0D-00AA006002F3", "checkbox"], ["8BD21D50-EC42-11CE-9E0D-00AA006002F3", "option"]]);
67
67
  /**
68
68
  * The affordance key for an `<ax:ocx ax:classid>`, for controls reached through
69
69
  * §18.3.1.19 `<control>` rather than `<oleObject progId>` — the `<control>`
@@ -152,17 +152,16 @@ function buildConditionalFormatter(conditionalFormats, styles, cells, resolveTex
152
152
  break;
153
153
  case "expression":
154
154
  if (!textClaimed && compiled && ctx && origin) {
155
- if (evaluateToBool(compiled, ctx, {
155
+ const shift = {
156
156
  dRow: row - origin.row,
157
157
  dCol: col - origin.col,
158
158
  curRow: row,
159
159
  curCol: col
160
- })) claim(rule);
160
+ };
161
+ if (evaluateToBool(compiled, ctx, shift)) claim(rule);
161
162
  }
162
163
  break;
163
- case "timePeriod":
164
- if (!textClaimed && value !== void 0 && nowSerial !== void 0 && timePeriodMatches(rule.timePeriod, value, nowSerial, date1904)) claim(rule);
165
- break;
164
+ case "timePeriod": if (!textClaimed && value !== void 0 && nowSerial !== void 0 && timePeriodMatches(rule.timePeriod, value, nowSerial, date1904)) claim(rule);
166
165
  }
167
166
  }
168
167
  if (!bar && !icon) return textFmt;
@@ -248,7 +247,8 @@ function buildEvalContext(cells, resolveText, nowSerial, date1904, cross) {
248
247
  const key = rawName.toLowerCase();
249
248
  const dn = nameMap.get(key);
250
249
  if (!dn || resolving.has(key)) return void 0;
251
- const compiled = compileFormula(dn.value.startsWith("=") ? dn.value.slice(1) : dn.value);
250
+ const value = dn.value.startsWith("=") ? dn.value.slice(1) : dn.value;
251
+ const compiled = compileFormula(value);
252
252
  if (!compiled) return void 0;
253
253
  const ast = compiled.ast;
254
254
  if (ast.k === "num") return num(ast.v);
@@ -278,7 +278,7 @@ function cellToScalar(cell, resolveText) {
278
278
  default: return cell.rawValue.length > 0 ? str(cell.rawValue) : BLANK;
279
279
  }
280
280
  }
281
- var FERRS = new Set([
281
+ var FERRS = /* @__PURE__ */ new Set([
282
282
  "#NULL!",
283
283
  "#DIV/0!",
284
284
  "#VALUE!",
@@ -463,7 +463,8 @@ function edate(args, ev, ctx, endOfMonth) {
463
463
  const ty = Math.floor(idx / 12);
464
464
  const tm = idx % 12 + 1;
465
465
  const dim = daysInMonth(ty, tm);
466
- const serial = serialFromYmd(ty, tm, endOfMonth ? dim : Math.min(p.day, dim), ctx.date1904);
466
+ const day = endOfMonth ? dim : Math.min(p.day, dim);
467
+ const serial = serialFromYmd(ty, tm, day, ctx.date1904);
467
468
  return serial < 0 ? err("#NUM!") : num(serial);
468
469
  }
469
470
  function daysInMonth(year, month1) {
@@ -537,7 +538,7 @@ function parseCriteria(s) {
537
538
  return {
538
539
  kind: "text",
539
540
  negate: op === "<>",
540
- re: wildcardToRegExp(text)
541
+ wildcard: wildcard(text)
541
542
  };
542
543
  }
543
544
  function matchCriteria(cell, crit) {
@@ -555,22 +556,45 @@ function matchCriteria(cell, crit) {
555
556
  }
556
557
  const text = cell.t === "str" ? cell.v : cell.t === "blank" ? "" : void 0;
557
558
  if (text === void 0) return false;
558
- const hit = crit.re.test(text);
559
+ const hit = crit.wildcard.test(text);
559
560
  return crit.negate ? !hit : hit;
560
561
  }
561
- function wildcardToRegExp(pattern) {
562
- let out = "^";
562
+ function wildcard(pattern) {
563
+ const pieces = [[]];
563
564
  for (let i = 0; i < pattern.length; i++) {
564
565
  const ch = pattern[i];
566
+ const atoms = pieces[pieces.length - 1];
565
567
  if (ch === "~" && (pattern[i + 1] === "*" || pattern[i + 1] === "?" || pattern[i + 1] === "~")) {
566
- out += escapeRe(pattern[i + 1]);
568
+ atoms.push(escapeRe(pattern[i + 1]));
567
569
  i++;
568
- } else if (ch === "*") out += ".*";
569
- else if (ch === "?") out += ".";
570
- else out += escapeRe(ch);
570
+ } else if (ch === "*") pieces.push([]);
571
+ else atoms.push(ch === "?" ? "." : escapeRe(ch));
571
572
  }
572
- out += "$";
573
- return new RegExp(out, "is");
573
+ const all = pieces.map((atoms) => ({
574
+ at: new RegExp(atoms.join(""), "isy"),
575
+ search: new RegExp(atoms.join(""), "gis"),
576
+ width: atoms.length
577
+ }));
578
+ const fits = (piece, text, at) => {
579
+ piece.at.lastIndex = at;
580
+ return piece.at.test(text);
581
+ };
582
+ const first = all[0];
583
+ if (all.length === 1) return { test: (text) => text.length === first.width && fits(first, text, 0) };
584
+ const last = all[all.length - 1];
585
+ const between = all.slice(1, -1).filter((piece) => piece.width > 0);
586
+ return { test(text) {
587
+ const end = text.length - last.width;
588
+ if (end < first.width || !fits(first, text, 0) || !fits(last, text, end)) return false;
589
+ let at = first.width;
590
+ for (const piece of between) {
591
+ piece.search.lastIndex = at;
592
+ const found = piece.search.exec(text);
593
+ if (found === null || found.index + piece.width > end) return false;
594
+ at = found.index + piece.width;
595
+ }
596
+ return true;
597
+ } };
574
598
  }
575
599
  function escapeRe(ch) {
576
600
  return /[.*+?^${}()|[\]\\]/.test(ch) ? `\\${ch}` : ch;
@@ -739,7 +763,8 @@ function largeSmall(args, ev, ctx, large) {
739
763
  if (typeof k !== "number") return err(k.e);
740
764
  const ki = Math.trunc(k);
741
765
  if (ki < 1 || ki > ns.length) return err("#NUM!");
742
- return num([...ns].sort((a, b) => large ? b - a : a - b)[ki - 1]);
766
+ const s = [...ns].sort((a, b) => large ? b - a : a - b);
767
+ return num(s[ki - 1]);
743
768
  }
744
769
  function countBlank(args, ev, ctx) {
745
770
  if (args.length !== 1) return err("#VALUE!");
@@ -1019,7 +1044,8 @@ function timeFn(args, ev, ctx) {
1019
1044
  if (typeof m !== "number") return err(m.e);
1020
1045
  const s = numArg(args, ev, ctx, 2);
1021
1046
  if (typeof s !== "number") return err(s.e);
1022
- return num(((Math.trunc(h) * 3600 + Math.trunc(m) * 60 + Math.trunc(s)) % 86400 + 86400) % 86400 / 86400);
1047
+ const total = Math.trunc(h) * 3600 + Math.trunc(m) * 60 + Math.trunc(s);
1048
+ return num((total % 86400 + 86400) % 86400 / 86400);
1023
1049
  }
1024
1050
  function weekStartDow(type) {
1025
1051
  switch (type) {
@@ -1051,7 +1077,8 @@ function weekNum(args, ev, ctx, iso) {
1051
1077
  if (type === 21) return num(isoWeek(serial, ctx.date1904));
1052
1078
  const firstDow = weekStartDow(type);
1053
1079
  if (firstDow === void 0) return err("#NUM!");
1054
- const jan1 = serialFromYmd(serialToParts(serial, ctx.date1904).year, 1, 1, ctx.date1904);
1080
+ const parts = serialToParts(serial, ctx.date1904);
1081
+ const jan1 = serialFromYmd(parts.year, 1, 1, ctx.date1904);
1055
1082
  const offset = (serialToParts(jan1, ctx.date1904).dow - firstDow + 7) % 7;
1056
1083
  const dayOfYear = serial - jan1 + 1;
1057
1084
  return num(Math.floor((dayOfYear + offset - 1) / 7) + 1);
@@ -1090,10 +1117,10 @@ function matchFn(args, ev, ctx) {
1090
1117
  if (len > MAX_SCAN) return err("#N/A");
1091
1118
  const at = (i) => horizontal ? refGet(range.sheet, ctx, rect.r0, rect.c0 + i) : refGet(range.sheet, ctx, rect.r0 + i, rect.c0);
1092
1119
  if (type === 0) {
1093
- const re = target.t === "str" ? wildcardToRegExp(target.v) : void 0;
1120
+ const wild = target.t === "str" ? wildcard(target.v) : void 0;
1094
1121
  for (let i = 0; i < len; i++) {
1095
1122
  const cell = at(i);
1096
- if (re ? cell.t === "str" && re.test(cell.v) : scalarEquals(cell, target)) return num(i + 1);
1123
+ if (wild ? cell.t === "str" && wild.test(cell.v) : scalarEquals(cell, target)) return num(i + 1);
1097
1124
  }
1098
1125
  return err("#N/A");
1099
1126
  }
@@ -1156,10 +1183,10 @@ function lookupFn(args, ev, ctx, vh) {
1156
1183
  const keyAt = (i) => vertical ? refGet(sh, ctx, rect.r0 + i, rect.c0) : refGet(sh, ctx, rect.r0, rect.c0 + i);
1157
1184
  const resultAt = (i) => vertical ? refGet(sh, ctx, rect.r0 + i, rect.c0 + line - 1) : refGet(sh, ctx, rect.r0 + line - 1, rect.c0 + i);
1158
1185
  if (!approx) {
1159
- const re = target.t === "str" ? wildcardToRegExp(target.v) : void 0;
1186
+ const wild = target.t === "str" ? wildcard(target.v) : void 0;
1160
1187
  for (let i = 0; i < vecLen; i++) {
1161
1188
  const k = keyAt(i);
1162
- if (re ? k.t === "str" && re.test(k.v) : scalarEquals(k, target)) return resultAt(i);
1189
+ if (wild ? k.t === "str" && wild.test(k.v) : scalarEquals(k, target)) return resultAt(i);
1163
1190
  }
1164
1191
  return err("#N/A");
1165
1192
  }
@@ -1,6 +1,6 @@
1
1
  import { parse } from "./parser.js";
2
- import "./dates.js";
3
- import { toBool } from "./value.js";
2
+ import { serialFromDate, timePeriodMatches } from "./dates.js";
3
+ import { BLANK, bool, err, num, str, toBool, toNumber } from "./value.js";
4
4
  import { NO_SHIFT, evaluate } from "./eval.js";
5
5
  //#region src/excel/formula/index.ts
6
6
  /**
@@ -30,4 +30,4 @@ function evaluateToBool(compiled, ctx, shift = NO_SHIFT) {
30
30
  return toBool(evaluate(compiled.ast, ctx, shift), ctx) === true;
31
31
  }
32
32
  //#endregion
33
- export { compileFormula, evaluateToBool };
33
+ export { BLANK, NO_SHIFT, bool, compileFormula, err, evaluate, evaluateToBool, num, serialFromDate, str, timePeriodMatches, toNumber };
@@ -1,6 +1,6 @@
1
1
  //#region src/excel/formula/lexer.ts
2
2
  var MAX_SOURCE = 8192;
3
- var KNOWN_ERRORS = new Set([
3
+ var KNOWN_ERRORS = /* @__PURE__ */ new Set([
4
4
  "#NULL!",
5
5
  "#DIV/0!",
6
6
  "#VALUE!",
@@ -211,4 +211,4 @@ function tokenize(src) {
211
211
  return out;
212
212
  }
213
213
  //#endregion
214
- export { tokenize };
214
+ export { LexError, tokenize };
@@ -16,7 +16,7 @@ var PREC = {
16
16
  "/": 4,
17
17
  "^": 5
18
18
  };
19
- var RIGHT_ASSOC = new Set(["^"]);
19
+ var RIGHT_ASSOC = /* @__PURE__ */ new Set(["^"]);
20
20
  var MAX_DEPTH = 64;
21
21
  var MAX_ARGS = 255;
22
22
  var CELL_RE = /^(\$?)([A-Za-z]{1,3})(\$?)([0-9]{1,7})$/;
@@ -39,6 +39,7 @@ function parse(src) {
39
39
  }
40
40
  /** A precedence-climbing (Pratt) parser over a {@link tokenize} token stream. */
41
41
  var Parser = class {
42
+ toks;
42
43
  pos = 0;
43
44
  depth = 0;
44
45
  /** @param toks The token stream to parse (must end with an `eof` token). */
@@ -327,7 +328,7 @@ function columnToIndex(letters) {
327
328
  for (let i = 0; i < up.length; i++) idx = idx * 26 + (up.charCodeAt(i) - 64);
328
329
  return idx - 1;
329
330
  }
330
- var AREAS = new Map([
331
+ var AREAS = /* @__PURE__ */ new Map([
331
332
  ["#all", "#All"],
332
333
  ["#data", "#Data"],
333
334
  ["#headers", "#Headers"],
@@ -419,4 +420,4 @@ function unescapeName(name) {
419
420
  return name.trim().replace(/'(.)/g, "$1");
420
421
  }
421
422
  //#endregion
422
- export { parse };
423
+ export { ParseError, parse, parseStructuredRef };
@@ -129,4 +129,4 @@ function numToText(n) {
129
129
  return String(n);
130
130
  }
131
131
  //#endregion
132
- export { BLANK, arrEach, bool, deref, err, isErr, num, refEach, refGet, str, toBool, toNumber, toText };
132
+ export { BLANK, FALSE, TRUE, arrEach, bool, deref, err, isErr, num, refEach, refGet, str, toBool, toNumber, toText };
@@ -1,7 +1,8 @@
1
- import "../core/number-format.js";
1
+ import { applyNumberFormat, generalToWidth, numberFormatColorHex } from "../core/number-format.js";
2
2
  import "./cell-reference.js";
3
- import "./defined-name-ref.js";
4
- import "./shared-strings-parser.js";
5
- import "./workbook-parser.js";
6
- import "./styles-parser.js";
7
- import "./worksheet-parser.js";
3
+ import { parseAreaRef, parseTitleRowRange } from "./defined-name-ref.js";
4
+ import { parseSharedStrings } from "./shared-strings-parser.js";
5
+ import { parseWorkbook } from "./workbook-parser.js";
6
+ import { EMPTY_XLSX_STYLES, parseXlsxStyles } from "./styles-parser.js";
7
+ import { parseWorksheet } from "./worksheet-parser.js";
8
+ export { EMPTY_XLSX_STYLES, applyNumberFormat, generalToWidth, numberFormatColorHex, parseAreaRef, parseSharedStrings, parseTitleRowRange, parseWorkbook, parseWorksheet, parseXlsxStyles };
@@ -233,7 +233,7 @@ var EXCEL_DEFAULT_ROW_HEIGHT_PT = 15;
233
233
  * and every one of its rows is 12.75pt: tdf100709.xlsx fits twenty of them on
234
234
  * the page where our 15pt fitted fourteen and pushed the rest onto a second.
235
235
  */
236
- var EXCEL_ROW_HEIGHT_BY_FONT_PT = new Map([
236
+ var EXCEL_ROW_HEIGHT_BY_FONT_PT = /* @__PURE__ */ new Map([
237
237
  [8, 11],
238
238
  [9, 12],
239
239
  [10, 12.75],
@@ -257,7 +257,7 @@ function defaultRowHeightPtFor(fontPt) {
257
257
  }
258
258
  var TWIPS_PER_POINT = 20;
259
259
  var TWIPS_PER_INCH = 1440;
260
- var PAPER_SIZES_TWIPS = new Map([
260
+ var PAPER_SIZES_TWIPS = /* @__PURE__ */ new Map([
261
261
  [1, [12240, 15840]],
262
262
  [3, [15840, 24480]],
263
263
  [5, [12240, 20160]],
@@ -813,12 +813,23 @@ function gridBody(worksheet, sharedStrings, styles, date1904, print) {
813
813
  }
814
814
  const ws = cellMatrix[r]?.[c];
815
815
  let text = ws ? resolveCellText(ws, sharedStrings, styles, date1904) : "";
816
+ let generalOverflow = false;
816
817
  if (ws?.type === "n" && ws.rawValue.length > 0 && (styles.cellXfs[ws.styleIndex ?? 0]?.numFmtId ?? 0) === 0) {
817
818
  const unit = charTwips(styles.cellXfs[ws.styleIndex ?? 0], styles, textTwipsUnit);
818
819
  const digit = charWidthUnits("0");
819
820
  if (unit > 0 && digit > 0) {
820
- const room = columnWidths[c] / unit;
821
- text = generalToWidth(ws.rawValue, (candidate) => estimateChars(candidate) / digit <= room);
821
+ let widthTwips = columnWidths[c];
822
+ if (merge) {
823
+ widthTwips = 0;
824
+ for (let a = merge.startColumn; a <= Math.min(merge.endColumn, colWindowEnd); a++) {
825
+ const i = a - colStart;
826
+ if (i >= 0 && i < colCount && !hiddenCols.has(i)) widthTwips += columnWidths[i];
827
+ }
828
+ }
829
+ const room = (widthTwips - 75) / unit;
830
+ const fits = (candidate) => estimateChars(candidate) / digit <= room;
831
+ text = generalToWidth(ws.rawValue, fits);
832
+ generalOverflow = !fits(text);
822
833
  }
823
834
  }
824
835
  const cfText = text.length > 0 ? text : void 0;
@@ -875,7 +886,7 @@ function gridBody(worksheet, sharedStrings, styles, date1904, print) {
875
886
  if (over) {
876
887
  if (over.fillHex) shading = { colorHex: over.fillHex };
877
888
  if (over.dataBar) dataBar = over.dataBar;
878
- if (over.numberFormat !== void 0 && ws.type === "n" && ws.rawValue.length > 0) text = applyNumberFormat(ws.rawValue, CF_NUMBER_FORMAT_ID, new Map([[CF_NUMBER_FORMAT_ID, over.numberFormat]]), date1904);
889
+ if (over.numberFormat !== void 0 && ws.type === "n" && ws.rawValue.length > 0) text = applyNumberFormat(ws.rawValue, CF_NUMBER_FORMAT_ID, /* @__PURE__ */ new Map([[CF_NUMBER_FORMAT_ID, over.numberFormat]]), date1904);
879
890
  if (over.hideValue) text = "";
880
891
  if (over.icon) icon = over.icon;
881
892
  if (over.border) borders = {
@@ -964,7 +975,7 @@ function gridBody(worksheet, sharedStrings, styles, date1904, print) {
964
975
  ...dropdown ? { dropdown: true } : {},
965
976
  ...noteFlag ? { noteFlag } : {},
966
977
  ...!wrapText && !rotated ? { noWrap: true } : {},
967
- ...!wrapText && !rotated && !shrinkToFit && !merge && ws?.type === "n" && (xf?.numFmtId ?? 0) !== 0 && text.length > 0 && tooWideToShow(text, charTwips(xf, styles, textTwipsUnit), columnWidths[c]) ? { hashOnOverflow: true } : {},
978
+ ...!wrapText && !rotated && !shrinkToFit && !merge && ws?.type === "n" && text.length > 0 && (generalOverflow || (xf?.numFmtId ?? 0) !== 0 && tooWideToShow(text, charTwips(xf, styles, textTwipsUnit), columnWidths[c])) ? { hashOnOverflow: true } : {},
968
979
  verticalAlign: verticalAlignOf(xf)
969
980
  };
970
981
  const indentLevels = xf?.alignment?.indent ?? 0;
@@ -2247,4 +2258,4 @@ function slicerParagraph(text, runProps) {
2247
2258
  };
2248
2259
  }
2249
2260
  //#endregion
2250
- export { cellPaintsVisibly, columnTwips, columnUnitTwips, defaultColumnTwips, noteKey, printableHeightPt, printableWidthPt, resolveCellText, resolvePrintArea, resolvePrintTitleRows, sectionFromWorksheet, slicerTable, worksheetToBody };
2261
+ export { cellPaintsSomething, cellPaintsVisibly, columnTwips, columnUnitTwips, defaultColumnTwips, defaultRowHeightPtFor, noteKey, printableHeightPt, printableWidthPt, resolveCellText, resolvePrintArea, resolvePrintTitleRows, sectionFromWorksheet, slicerTable, worksheetToBody };
@@ -1,8 +1,7 @@
1
1
  //#region src/excel/printer-settings.ts
2
- var DEVICE_NAME_BYTES = 64;
3
- var OFFSET_SIZE = DEVICE_NAME_BYTES + 4;
4
- var OFFSET_ORIENTATION = DEVICE_NAME_BYTES + 12;
5
- var OFFSET_PAPER_SIZE = DEVICE_NAME_BYTES + 14;
2
+ var OFFSET_SIZE = 68;
3
+ var OFFSET_ORIENTATION = 76;
4
+ var OFFSET_PAPER_SIZE = 78;
6
5
  var DM_ORIENTATION = 1;
7
6
  var DM_PAPERSIZE = 2;
8
7
  /**
@@ -15,11 +14,11 @@ var DM_PAPERSIZE = 2;
15
14
  * @param data The raw part bytes.
16
15
  */
17
16
  function parsePrinterSettings(data) {
18
- if (data.byteLength < OFFSET_PAPER_SIZE + 2) return {};
17
+ if (data.byteLength < 80) return {};
19
18
  const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
20
19
  const dmSize = view.getUint16(OFFSET_SIZE, true);
21
- if (dmSize < OFFSET_PAPER_SIZE + 2 || dmSize > data.byteLength) return {};
22
- const fields = view.getUint32(DEVICE_NAME_BYTES + 8, true);
20
+ if (dmSize < 80 || dmSize > data.byteLength) return {};
21
+ const fields = view.getUint32(72, true);
23
22
  const out = {};
24
23
  if (fields & DM_PAPERSIZE) {
25
24
  const paper = view.getInt16(OFFSET_PAPER_SIZE, true);
@@ -21,7 +21,7 @@ var RICH_VALUE_TYPE = "XLRICHVALUE";
21
21
  * error is worse than the stand-in the file already provides, so an unmapped
22
22
  * code resolves to nothing.
23
23
  */
24
- var ERROR_TYPES = new Map([[8, "#SPILL!"]]);
24
+ var ERROR_TYPES = /* @__PURE__ */ new Map([[8, "#SPILL!"]]);
25
25
  function nodes(parent, name) {
26
26
  if (typeof parent !== "object" || parent === null) return [];
27
27
  const child = parent[name];
@@ -148,7 +148,8 @@ function parseDiagramFrames(drawingXml, worksheet, colUnitTwips) {
148
148
  if (!ANCHOR_KINDS.some((k) => poIs(anchor, k))) continue;
149
149
  const frame = poChildren(anchor).find((c) => poIs(c, "xdr:graphicFrame"));
150
150
  if (!frame) continue;
151
- if (!poFirstChild(poFirstChild(poFirstChild(frame, "a:graphic"), "a:graphicData"), "dgm:relIds")) continue;
151
+ const data = poFirstChild(poFirstChild(frame, "a:graphic"), "a:graphicData");
152
+ if (!poFirstChild(data, "dgm:relIds")) continue;
152
153
  const box = anchorBox(anchor, colWidthPt, rowHeightPt);
153
154
  if (box) out.push(box);
154
155
  }
@@ -340,9 +341,10 @@ function styleLine(sp, ns, colors, themeLineWidths) {
340
341
  const colorHex = child ? resolveColorNode(child, colors) : void 0;
341
342
  if (colorHex === void 0) return void 0;
342
343
  const idx = Number(poAttr(lnRef, "idx") ?? "");
344
+ const width = Number.isFinite(idx) ? themeLineWidths[idx - 1] : void 0;
343
345
  return {
344
346
  colorHex,
345
- width: pt((Number.isFinite(idx) ? themeLineWidths[idx - 1] : void 0) ?? .75)
347
+ width: pt(width ?? .75)
346
348
  };
347
349
  }
348
350
  /**
@@ -193,21 +193,23 @@ function projectSheetDoc(sheet, options = {}) {
193
193
  table: slicerTable(slicer)
194
194
  });
195
195
  const listComments = !screen && ws.grid.pageSetup?.cellComments === "atEnd";
196
- if (ws.comments && ws.comments.length > 0) if (listComments) body.push(...commentBlocks(ws.comments));
197
- else if (!notesShown) options.losses?.push({
198
- severity: "dropped",
199
- feature: "comments",
200
- detail: `${ws.comments.length} cell note(s) not printed — <pageSetup cellComments> is "${ws.grid.pageSetup?.cellComments ?? "none"}"`,
201
- where: `sheet "${ws.name}"`
202
- });
203
- else {
204
- const hidden = ws.comments.filter((c) => c.shown === void 0).length;
205
- if (hidden > 0) options.losses?.push({
196
+ if (ws.comments && ws.comments.length > 0) {
197
+ if (listComments) body.push(...commentBlocks(ws.comments));
198
+ else if (!notesShown) options.losses?.push({
206
199
  severity: "dropped",
207
200
  feature: "comments",
208
- detail: screen ? `${hidden} cell note(s) not shown — a hidden note shows only while its cell is pointed at` : `${hidden} cell note(s) not printed — "asDisplayed" prints the notes the sheet shows`,
201
+ detail: `${ws.comments.length} cell note(s) not printed — <pageSetup cellComments> is "${ws.grid.pageSetup?.cellComments ?? "none"}"`,
209
202
  where: `sheet "${ws.name}"`
210
203
  });
204
+ else {
205
+ const hidden = ws.comments.filter((c) => c.shown === void 0).length;
206
+ if (hidden > 0) options.losses?.push({
207
+ severity: "dropped",
208
+ feature: "comments",
209
+ detail: screen ? `${hidden} cell note(s) not shown — a hidden note shows only while its cell is pointed at` : `${hidden} cell note(s) not printed — "asDisplayed" prints the notes the sheet shows`,
210
+ where: `sheet "${ws.name}"`
211
+ });
212
+ }
211
213
  }
212
214
  if (ws.formControls && ws.formControls.length > 0) body.push(...formControlBlocks(ws.formControls));
213
215
  if (ws.activeXControls && ws.activeXControls.length > 0) body.push(...activeXBlocks(ws.activeXControls));
@@ -54,7 +54,7 @@ function parseXlsxStyles(data, theme) {
54
54
  ...tableStyles.size > 0 ? { tableStyles } : {}
55
55
  };
56
56
  }
57
- var TABLE_STYLE_TYPES = new Set([
57
+ var TABLE_STYLE_TYPES = /* @__PURE__ */ new Set([
58
58
  "wholeTable",
59
59
  "firstColumnStripe",
60
60
  "secondColumnStripe",
@@ -155,7 +155,7 @@ function parseDxf(item, colors) {
155
155
  return dxf;
156
156
  }
157
157
  }
158
- var VALID_BORDER_STYLES = new Set([
158
+ var VALID_BORDER_STYLES = /* @__PURE__ */ new Set([
159
159
  "none",
160
160
  "thin",
161
161
  "medium",
@@ -250,6 +250,8 @@ function parseFonts(root, colors) {
250
250
  if (colorRef !== void 0) font.colorRef = colorRef;
251
251
  const nameVal = childValAttr(obj, "name");
252
252
  if (nameVal) font.name = nameVal;
253
+ const scheme = childValAttr(obj, "scheme");
254
+ if (scheme === "minor" || scheme === "major") font.scheme = scheme;
253
255
  out.push(font);
254
256
  }
255
257
  return out;
@@ -495,4 +497,4 @@ var THEME_SLOTS = [
495
497
  "folHlink"
496
498
  ];
497
499
  //#endregion
498
- export { EMPTY_XLSX_STYLES, parseDxf, parseXlsxStyles, workbookColorHex };
500
+ export { EMPTY_XLSX_STYLES, INDEXED_COLORS, parseDxf, parseXlsxStyles, workbookColorHex };
@@ -10,16 +10,16 @@ function toHls(r, g, b) {
10
10
  const max = Math.max(r, g, b);
11
11
  const min = Math.min(r, g, b);
12
12
  const sum = max + min;
13
- const l = div(sum * HLS_MAX + RGB_MAX, 2 * RGB_MAX);
13
+ const l = div(sum * HLS_MAX + RGB_MAX, 510);
14
14
  if (max === min) return [
15
- HLS_MAX * 2 / 3,
15
+ 160,
16
16
  l,
17
17
  0
18
18
  ];
19
19
  const range = max - min;
20
- const s = l <= HLS_MAX / 2 ? div(range * HLS_MAX + div(sum, 2), sum) : div(range * HLS_MAX + div(2 * RGB_MAX - sum, 2), 2 * RGB_MAX - sum);
20
+ const s = l <= HLS_MAX / 2 ? div(range * HLS_MAX + div(sum, 2), sum) : div(range * HLS_MAX + div(510 - sum, 2), 510 - sum);
21
21
  const away = (c) => div((max - c) * (HLS_MAX / 6) + div(range, 2), range);
22
- let h = r === max ? away(b) - away(g) : g === max ? HLS_MAX / 3 + away(r) - away(b) : HLS_MAX * 2 / 3 + away(g) - away(r);
22
+ let h = r === max ? away(b) - away(g) : g === max ? HLS_MAX / 3 + away(r) - away(b) : 160 + away(g) - away(r);
23
23
  if (h < 0) h += HLS_MAX;
24
24
  if (h > HLS_MAX) h -= HLS_MAX;
25
25
  return [
@@ -45,7 +45,7 @@ function toRgb(h, l, s) {
45
45
  const x = hue < 0 ? hue + HLS_MAX : hue > HLS_MAX ? hue - HLS_MAX : hue;
46
46
  if (x < HLS_MAX / 6) return lo + div((hi - lo) * x + HLS_MAX / 12, HLS_MAX / 6);
47
47
  if (x < HLS_MAX / 2) return hi;
48
- if (x < HLS_MAX * 2 / 3) return lo + div((hi - lo) * (HLS_MAX * 2 / 3 - x) + HLS_MAX / 12, HLS_MAX / 6);
48
+ if (x < 160) return lo + div((hi - lo) * (160 - x) + HLS_MAX / 12, HLS_MAX / 6);
49
49
  return lo;
50
50
  };
51
51
  return [