wysiwygido 1.0.0 → 1.2.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,24 @@
2
2
 
3
3
  All notable changes to this project are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses [Semantic Versioning](https://semver.org/). Before 1.0.0 minor versions could contain breaking changes. From 1.0.0 on, only a major version may break the public API (see "Stability and versioning" in the README); changes are listed under "Changed" or "Removed".
4
4
 
5
+ ## 1.2.0
6
+
7
+ - Added: **collapsible headings** (`CollapsibleHeadings`, in `defaultPlugins`): an arrow in the margin of every top-level heading hides the text under it up to the next heading of the same or a higher level, like Word. Commands `toggleHeadingFold`, `collapseHeadings`, `expandHeadings`, `showHeadingLevel(n)`; right-click menu, ribbon (View → Headings) and shortcuts included. The document is not changed and the pages are laid out again without the hidden text.
8
+
9
+ ## 1.1.0
10
+
11
+ The first release published to npm since 0.4.0: it contains everything in 1.0.0 below plus the following.
12
+
13
+ - Added: a **browser support** section on the demo site: 17 real browser builds (Chrome / Edge 94 to 141, Firefox 91 to 142, Safari 16.4 to 26) each ran the same 34 checks, and every one passes. The runner is in `scripts/compat` (`probe.cjs`, `run-matrix.sh`, `aggregate.mjs`).
14
+ - Fixed: progress bars in a data table (`bar: true`) were wiped out on striped, hovered and selected rows, and under a highlight; the row styles now set only the background colour.
15
+ - Fixed: the data table's highlights and bars had no colour in browsers without `color-mix()` (before Chrome 111, Firefox 113, Safari 16.2); they now have plain-colour fallbacks.
16
+ - Changed: no longer uses `Object.hasOwn` or `Array.prototype.at`, which lowers the oldest working browsers (Chrome 93 and Safari 15.4 were the floor; the oldest tested builds are now Chrome 94, Firefox 91 and Safari 16.4).
17
+ - Added: **add, edit and delete from dialogs** for the data table (`crud` option, in the editor plugin and in `createDataTable`): a "New…" button, Edit and Delete buttons on every row, a confirmation before deleting, and the same in the right-click menu. `onCreate`, `onUpdate` and `onDelete` save to your server first (an error shows in the dialog; the server may return the saved row), and they also work for tables that load rows from a source.
18
+ - Added: **a guard by role or permission** for those actions (`crud.user`, `crud.access`, `setUser`, `hasDataTableAccess`): a rule is a role, a permission (`'orders.*'` wildcards), a list, `{ roles, permissions }` or a function that sees the row. Buttons a person may not use are not drawn, and cell editing, the keyboard and the API are refused too. This is a convenience for the interface; enforce the same rules on your server.
19
+ - Added: `DataTableRowAction.when` (show a row button only on some rows).
20
+ - Changed: the "Table options" dialog is tidier: labelled fields in a grid and the switches grouped under Look, Tools and Rows, each with a short explanation.
21
+ - Added: a "Data table" section on the demo site with six new examples (roles, 5,000 rows from a server, budget, stock, directory, import and export).
22
+
5
23
  ## 1.0.0
6
24
 
7
25
  The first stable release. The public API (the exported names, the plugin contract, the stored document formats and the `--wy-*` colour variables) now follows semantic versioning, and tests guard it. New since 0.4.0: the data table and its stand-alone version.
package/README.md CHANGED
@@ -161,6 +161,8 @@ Markdown), so exports show it. A reference to a deleted caption says "Missing re
161
161
 
162
162
  **Columns**: `Columns()` flows blocks into 2–4 newspaper columns (`insertColumns(n)` wraps the selection, `setColumns({ count, rule, gap })`, `removeColumns`). `setDocumentColumns(count)` puts the whole page (below a leading heading) in columns and `insertColumnBreak` starts the next column. Columns collapse to one on narrow screens. Word export writes every top-level columns block as its own continuous **section** with the real column count, gap and rule (text before and after stays single-column; headers and footers stay on the first section); Markdown flows the text in one column. Columns nested inside columns are flattened in Word.
163
163
 
164
+ **Collapsible headings**: `CollapsibleHeadings` (in `defaultPlugins`) puts a small arrow in the margin left of every top-level heading, as in Word: a click hides everything up to the next heading of the same or a higher level and shows "…" after the title, and a click again opens it. Commands: `toggleHeadingFold` (the heading at the cursor, or the nearest one above it), `collapseHeadings`, `expandHeadings` and `showHeadingLevel(n)` (only the headings down to level `n` stay open); they are also in the right-click menu on a heading and in the ribbon under View → Headings. Shortcuts: Ctrl/Cmd + Alt + Up collapses, Ctrl/Cmd + Alt + Down expands everything. Nothing is removed from the document: the HTML, undo, export and print are unchanged, the pages are laid out again without the hidden text, and a cursor that moves into hidden text (search, undo, the outline) opens that section. Which headings are collapsed is view state: it is not saved with the document.
165
+
164
166
  **Charts**: `Charts()` draws bar, line and pie charts as SVG. With the cursor in a table, `insertChart('bar' | 'line' | 'pie')` uses the first row as series and the first column as labels (numbers like `1,200`, `$40` or `12%` are understood); `insertChart(type, { labels, series })` takes data directly and `setChart` changes the selected chart. The chart is saved as validated data (never markup) and redrawn on load; Word export writes it as a picture (needs a browser canvas) and Markdown as a table.
165
167
 
166
168
  **Recording and dictation**: `Recording()` adds `recordAudio`, `recordScreen`, `stopRecording`, `cancelRecording` and `toggleDictation`. The browser asks permission each time, a bar shows the time while recording, Esc cancels and the tracks are always released. A recording becomes a player in the text, embedded as a data URL (capped by `maxBytes`) or stored by your `upload(blob, kind)` function (recommended for anything long); `maxSeconds` stops it automatically. Dictation uses the browser's speech recognition (Chrome, Edge, Safari; not Firefox), types only text at the cursor, and can be set to a language with `dictationLang`. Word and Markdown export keep a link or label, not the media.
@@ -341,7 +343,7 @@ The package follows [semantic versioning](https://semver.org/). Since 1.0.0 only
341
343
  - **What is stored in documents**: the HTML attributes (`data-data-table`, `data-chart`, `data-cover-page`…) and the JSON they hold. Each stored format is read by every later version; the data table's format carries a version number (`v`), and a table saved by a *newer* version than the one reading it is shown, kept untouched and not editable, so an older copy can never lose data. Golden files for these formats are tests (`tests/formats.test.ts`).
342
344
  - **The CSS custom properties** (`--wy-*`) used for theming.
343
345
 
344
- Not part of it: the `wy-*` class names and the exact DOM the editor builds, internal modules not exported from an entry point, and the exact wording of interface text and error messages. `defaultPlugins` may gain plugins in a minor release. Anything deprecated keeps working for at least one minor release and is listed in the changelog. Supported browsers are the current versions of Chrome, Edge, Firefox and Safari (all four are tested); the pure functions (`dataTableToCSV`, `dataTableToXlsx`, `queryDataTable`…) also run on Node 18+.
346
+ Not part of it: the `wy-*` class names and the exact DOM the editor builds, internal modules not exported from an entry point, and the exact wording of interface text and error messages. `defaultPlugins` may gain plugins in a minor release. Anything deprecated keeps working for at least one minor release and is listed in the changelog. Supported browsers are the current versions of Chrome, Edge, Firefox and Safari (all four are tested), and the oldest builds that were run with every check passing are Chrome / Edge 94, Firefox 91 and Safari 16.4 (the table of tested builds and what older browsers lack is on the demo site under "Browser support"; `scripts/compat` runs it again); the pure functions (`dataTableToCSV`, `dataTableToXlsx`, `queryDataTable`…) also run on Node 18+.
345
347
 
346
348
  ## Endpoints your app provides
347
349
 
@@ -537,6 +539,28 @@ editor.execute('insertDataTable', { columns: [...], rows: [], options: { source:
537
539
 
538
540
  The pure parts (`dataTableToCSV`, `dataTableToXlsx`, `dataTableToPrintHTML`, `queryDataTable`, `cleanDataTable`, `dataTableWithFormulas`, `parseXlsx`) are exported too, so a server can build the same files.
539
541
 
542
+ ### Add, edit and delete, with a guard
543
+
544
+ ```ts
545
+ createDataTable({
546
+ element, table,
547
+ crud: {
548
+ user: { id: 'eka', roles: ['editor'], permissions: ['tickets.create'] }, // or a function that returns the person
549
+ access: {
550
+ create: ['editor', 'admin'], // a role or a permission; 'tickets.*' matches a family
551
+ update: (user, row) => hasDataTableAccess('admin', user) || row?.owner === user?.id,
552
+ delete: { roles: ['admin'] }, // roles: one of them; permissions: all of them
553
+ },
554
+ onCreate: async (row) => (await api.post('/tickets', row)).data, // return the saved row (its new id)
555
+ onUpdate: (row, before) => api.put(`/tickets/${before.id}`, row),
556
+ onDelete: (rows) => api.delete('/tickets', rows.map((r) => r.id)), // throw to refuse: the message shows in the dialog
557
+ },
558
+ });
559
+ app.setUser(otherUser); // after sign-in or sign-out (`editor.extensions.dataTable.setUser` in the editor)
560
+ ```
561
+
562
+ `crud` adds a **New…** button, **Edit** and **Delete** on every row and a confirmation before anything is deleted; the dialogs have a field for every column that is not calculated. Without a rule an action is open to everyone; `create: false`, `update: false` or `delete: false` remove it altogether, and `confirmDelete: false` skips the question. A button the person may not use is not drawn, and typing in a cell, the keyboard and the API are refused as well. A save that fails keeps the dialog open with the message. This only shapes the interface: enforce the same rules on your server. The examples are on the demo site under "Data table" (roles, 5,000 rows from a server, budget, stock, directory, import and export).
563
+
540
564
  ### Without the editor
541
565
 
542
566
  The same table works on its own: no editor, no ProseMirror. Import `wysiwygido/data-table` (a small entry point that pulls in nothing else; the build checks that) and the stylesheet.
package/dist/adapter.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as createEditor } from "./src-ByAIGOkX.js";
1
+ import { t as createEditor } from "./src-BNH7F1TH.js";
2
2
  //#region src/adapter.ts
3
3
  /**
4
4
  * Framework-neutral binding for anything that needs a "value in, value out" control: Angular's `ControlValueAccessor`, Svelte, Solid,
@@ -617,7 +617,7 @@ function cleanSpec(raw) {
617
617
  if (!columns.length) return null;
618
618
  const rows = [];
619
619
  for (const r of (Array.isArray(data.rows) ? data.rows : []).slice(0, MAX_ROWS)) {
620
- const src = Array.isArray(r) ? r : r && typeof r === "object" ? columns.map((c) => Object.hasOwn(r, c.key) ? r[c.key] : void 0) : [];
620
+ const src = Array.isArray(r) ? r : r && typeof r === "object" ? columns.map((c) => Object.prototype.hasOwnProperty.call(r, c.key) ? r[c.key] : void 0) : [];
621
621
  rows.push(columns.map((c, i) => coerceCell(c.type, src[i])));
622
622
  }
623
623
  const o = data.options && typeof data.options === "object" ? data.options : {};
@@ -1442,4 +1442,4 @@ async function parseXlsx(input) {
1442
1442
  //#endregion
1443
1443
  export { checkFormula as S, toCSV as _, PAGE_SIZES as a, withFormulas as b, coerceCell as c, normalizeRows as d, parseCSV as f, specFromRows as g, ruleLooks as h, MAX_ROWS as i, formatCell as l, queryRows as m, COLUMN_TYPES as n, aggregate as o, parseXlsx as p, LOOKS as r, cleanSpec as s, AGGREGATES as t, groupDisplay as u, toPrintHTML as v, FORMULA_FUNCTIONS as x, toXlsx as y };
1444
1444
 
1445
- //# sourceMappingURL=data-table-BKO1Z_Ug.js.map
1445
+ //# sourceMappingURL=data-table-C972cOYM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-table-C972cOYM.js","names":["MAX_TEXT","num","truthy"],"sources":["../src/data-table-formula.ts","../src/data-table.ts"],"sourcesContent":["/**\n * Formulas for the columns of a data table: `[Price] * [Qty]`, `IF([Stock] < 5, \"Reorder\", \"OK\")`.\n * A small parser and evaluator (no `eval`, no loops), so a formula saved in a document can do nothing but calculate from its own row.\n */\n\nexport type FormulaValue = number | string | boolean | null;\n\nclass FormulaError extends Error {\n constructor(public code: string) { super(code); }\n}\n\ntype Node =\n | { t: 'num'; v: number }\n | { t: 'str'; v: string }\n | { t: 'ref'; name: string }\n | { t: 'un'; op: '-' | '!'; a: Node }\n | { t: 'bin'; op: string; a: Node; b: Node }\n | { t: 'call'; fn: string; args: Node[] };\n\ntype Tok = { k: 'num'; v: number } | { k: 'str'; v: string } | { k: 'ref'; v: string } | { k: 'id'; v: string } | { k: 'op'; v: string };\n\nconst MAX_LENGTH = 500;\nconst MAX_TOKENS = 300;\nconst MAX_DEPTH = 40;\nconst MAX_TEXT = 5000;\n\nfunction tokenize(src: string): Tok[] {\n const out: Tok[] = [];\n let i = 0;\n while (i < src.length) {\n const ch = src[i];\n if (/\\s/.test(ch)) { i++; continue; }\n if (out.length >= MAX_TOKENS) throw new FormulaError('#SYNTAX!');\n let m: RegExpExecArray | null;\n const rest = src.slice(i);\n if ((m = /^(\\d+\\.?\\d*|\\.\\d+)(e[+-]?\\d+)?/i.exec(rest))) { out.push({ k: 'num', v: Number(m[0]) }); i += m[0].length; }\n else if (ch === '\"' || ch === \"'\") {\n let j = i + 1; let s = '';\n while (j < src.length && src[j] !== ch) { if (src[j] === '\\\\' && j + 1 < src.length) j++; s += src[j]; j++; }\n if (j >= src.length) throw new FormulaError('#SYNTAX!');\n out.push({ k: 'str', v: s }); i = j + 1;\n }\n else if (ch === '[') { const j = src.indexOf(']', i); if (j < 0) throw new FormulaError('#SYNTAX!'); out.push({ k: 'ref', v: src.slice(i + 1, j).trim() }); i = j + 1; }\n else if (ch === '{') { const j = src.indexOf('}', i); if (j < 0) throw new FormulaError('#SYNTAX!'); out.push({ k: 'ref', v: src.slice(i + 1, j).trim() }); i = j + 1; }\n else if ((m = /^[A-Za-z_][\\w.]*/.exec(rest))) { out.push({ k: 'id', v: m[0] }); i += m[0].length; }\n else if ((m = /^(<=|>=|<>|!=|==|&&|\\|\\|)/.exec(rest))) { out.push({ k: 'op', v: m[0] }); i += 2; }\n else if ('+-*/%^&()<>=,!'.includes(ch)) { out.push({ k: 'op', v: ch }); i++; }\n else throw new FormulaError('#SYNTAX!');\n }\n return out;\n}\n\nfunction parse(src: string): Node {\n if (src.length > MAX_LENGTH) throw new FormulaError('#SYNTAX!');\n const toks = tokenize(src);\n let p = 0;\n const peek = () => toks[p];\n const isOp = (...ops: string[]) => { const t = toks[p]; return t?.k === 'op' && ops.includes(t.v); };\n const next = () => toks[p++];\n const expr = (d: number): Node => {\n if (d > MAX_DEPTH) throw new FormulaError('#SYNTAX!');\n return compare(d);\n };\n const compare = (d: number): Node => {\n let a = concat(d);\n while (isOp('=', '==', '<>', '!=', '<', '<=', '>', '>=')) { const op = String(next().v); a = { t: 'bin', op: op === '==' ? '=' : op === '!=' ? '<>' : op, a, b: concat(d) }; }\n return a;\n };\n const concat = (d: number): Node => {\n let a = add(d);\n while (isOp('&')) { next(); a = { t: 'bin', op: '&', a, b: add(d) }; }\n return a;\n };\n const add = (d: number): Node => {\n let a = mul(d);\n while (isOp('+', '-')) { const op = String(next().v); a = { t: 'bin', op, a, b: mul(d) }; }\n return a;\n };\n const mul = (d: number): Node => {\n let a = pow(d);\n while (isOp('*', '/', '%')) { const op = String(next().v); a = { t: 'bin', op, a, b: pow(d) }; }\n return a;\n };\n const pow = (d: number): Node => {\n const a = unary(d);\n if (isOp('^')) { next(); return { t: 'bin', op: '^', a, b: pow(d + 1) }; }\n return a;\n };\n const unary = (d: number): Node => {\n if (d > MAX_DEPTH) throw new FormulaError('#SYNTAX!');\n if (isOp('-')) { next(); return { t: 'un', op: '-', a: unary(d + 1) }; }\n if (isOp('+')) { next(); return unary(d + 1); }\n if (isOp('!')) { next(); return { t: 'un', op: '!', a: unary(d + 1) }; }\n return primary(d);\n };\n const primary = (d: number): Node => {\n const t = next();\n if (!t) throw new FormulaError('#SYNTAX!');\n if (t.k === 'num') return { t: 'num', v: t.v };\n if (t.k === 'str') return { t: 'str', v: t.v };\n if (t.k === 'ref') return { t: 'ref', name: t.v };\n if (t.k === 'id') {\n if (isOp('(')) {\n next();\n const args: Node[] = [];\n if (!isOp(')')) { do { args.push(expr(d + 1)); } while (isOp(',') && next()); }\n if (!isOp(')')) throw new FormulaError('#SYNTAX!');\n next();\n return { t: 'call', fn: t.v.toUpperCase(), args };\n }\n return { t: 'ref', name: t.v };\n }\n if (t.v === '(') { const e = expr(d + 1); if (!isOp(')')) throw new FormulaError('#SYNTAX!'); next(); return e; }\n throw new FormulaError('#SYNTAX!');\n };\n const tree = expr(0);\n if (peek()) throw new FormulaError('#SYNTAX!');\n return tree;\n}\n\n// ---- evaluation\n\nconst num = (v: FormulaValue): number => {\n if (typeof v === 'number') return v;\n if (v === null || v === '') return 0;\n if (typeof v === 'boolean') return v ? 1 : 0;\n const n = Number(String(v).replace(/,/g, ''));\n if (!Number.isFinite(n)) throw new FormulaError('#VALUE!');\n return n;\n};\nconst text = (v: FormulaValue): string => (v === null ? '' : typeof v === 'boolean' ? (v ? 'TRUE' : 'FALSE') : String(v));\nconst truthy = (v: FormulaValue): boolean => (typeof v === 'string' ? v !== '' && !/^(false|no|0)$/i.test(v) : Boolean(v));\nconst clip = (s: string) => (s.length > MAX_TEXT ? s.slice(0, MAX_TEXT) : s);\nconst isoDate = (v: FormulaValue): number => {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(text(v));\n if (!m) throw new FormulaError('#VALUE!');\n return Date.UTC(+m[1], +m[2] - 1, +m[3]);\n};\nconst check = (n: number) => { if (!Number.isFinite(n)) throw new FormulaError('#VALUE!'); return n; };\n\nfunction compareValues(a: FormulaValue, b: FormulaValue): number {\n const numeric = (v: FormulaValue) => typeof v === 'number' || (typeof v === 'string' && v.trim() !== '' && Number.isFinite(Number(v)));\n if ((numeric(a) || a === null) && (numeric(b) || b === null)) return num(a) - num(b);\n return text(a).toLowerCase() < text(b).toLowerCase() ? -1 : text(a).toLowerCase() > text(b).toLowerCase() ? 1 : 0;\n}\n\ntype Fn = (args: FormulaValue[], lazy: Node[], ev: (n: Node) => FormulaValue) => FormulaValue;\nconst flat = (a: FormulaValue[]) => a.filter((v) => v !== null && v !== '').map(num);\nconst FUNCTIONS: Record<string, Fn> = {\n IF: (_a, n, ev) => { if (n.length < 2 || n.length > 3) throw new FormulaError('#VALUE!'); return truthy(ev(n[0])) ? ev(n[1]) : n[2] ? ev(n[2]) : ''; },\n AND: (a) => a.every(truthy),\n OR: (a) => a.some(truthy),\n NOT: (a) => !truthy(a[0] ?? null),\n ROUND: (a) => { const d = Math.max(0, Math.min(10, Math.trunc(num(a[1] ?? 0)))); const f = 10 ** d; return Math.round((num(a[0] ?? null) + Number.EPSILON) * f) / f; },\n FLOOR: (a) => Math.floor(num(a[0] ?? null)),\n CEIL: (a) => Math.ceil(num(a[0] ?? null)),\n ABS: (a) => Math.abs(num(a[0] ?? null)),\n SQRT: (a) => { const n = num(a[0] ?? null); if (n < 0) throw new FormulaError('#VALUE!'); return Math.sqrt(n); },\n POWER: (a) => check(num(a[0] ?? null) ** num(a[1] ?? null)),\n MOD: (a) => { const d = num(a[1] ?? null); if (d === 0) throw new FormulaError('#DIV/0!'); return ((num(a[0] ?? null) % d) + d) % d; },\n MIN: (a) => { const n = flat(a); return n.length ? Math.min(...n) : 0; },\n MAX: (a) => { const n = flat(a); return n.length ? Math.max(...n) : 0; },\n SUM: (a) => flat(a).reduce((x, y) => x + y, 0),\n AVERAGE: (a) => { const n = flat(a); if (!n.length) throw new FormulaError('#DIV/0!'); return n.reduce((x, y) => x + y, 0) / n.length; },\n COUNT: (a) => a.filter((v) => typeof v === 'number').length,\n LEN: (a) => text(a[0] ?? null).length,\n UPPER: (a) => text(a[0] ?? null).toUpperCase(),\n LOWER: (a) => text(a[0] ?? null).toLowerCase(),\n TRIM: (a) => text(a[0] ?? null).trim(),\n LEFT: (a) => text(a[0] ?? null).slice(0, Math.max(0, num(a[1] ?? 1))),\n RIGHT: (a) => { const s = text(a[0] ?? null); const n = Math.max(0, num(a[1] ?? 1)); return n ? s.slice(-n) : ''; },\n CONCAT: (a) => clip(a.map(text).join('')),\n CONTAINS: (a) => text(a[0] ?? null).toLowerCase().includes(text(a[1] ?? null).toLowerCase()),\n ISEMPTY: (a) => a[0] === null || a[0] === '',\n TODAY: () => new Date().toISOString().slice(0, 10),\n YEAR: (a) => new Date(isoDate(a[0] ?? null)).getUTCFullYear(),\n MONTH: (a) => new Date(isoDate(a[0] ?? null)).getUTCMonth() + 1,\n DAY: (a) => new Date(isoDate(a[0] ?? null)).getUTCDate(),\n DAYS: (a) => Math.round((isoDate(a[0] ?? null) - isoDate(a[1] ?? null)) / 86400000),\n};\nconst KNOWN = new Set(Object.keys(FUNCTIONS));\n\nfunction evaluate(node: Node, resolve: (name: string) => FormulaValue): FormulaValue {\n const ev = (n: Node): FormulaValue => {\n switch (n.t) {\n case 'num': return n.v;\n case 'str': return n.v;\n case 'ref': {\n const u = n.name.toUpperCase();\n const v = resolve(n.name);\n if (v === undefined as unknown) {\n if (u === 'TRUE') return true;\n if (u === 'FALSE') return false;\n if (u === 'PI') return Math.PI;\n throw new FormulaError('#REF!');\n }\n return v;\n }\n case 'un': return n.op === '-' ? -num(ev(n.a)) : !truthy(ev(n.a));\n case 'bin': {\n if (n.op === '&') return clip(text(ev(n.a)) + text(ev(n.b)));\n const a = ev(n.a); const b = ev(n.b);\n switch (n.op) {\n case '+': return check(num(a) + num(b));\n case '-': return check(num(a) - num(b));\n case '*': return check(num(a) * num(b));\n case '/': { const d = num(b); if (d === 0) throw new FormulaError('#DIV/0!'); return check(num(a) / d); }\n case '%': { const d = num(b); if (d === 0) throw new FormulaError('#DIV/0!'); return check(num(a) % d); }\n case '^': return check(num(a) ** num(b));\n case '=': return compareValues(a, b) === 0;\n case '<>': return compareValues(a, b) !== 0;\n case '<': return compareValues(a, b) < 0;\n case '<=': return compareValues(a, b) <= 0;\n case '>': return compareValues(a, b) > 0;\n default: return compareValues(a, b) >= 0;\n }\n }\n case 'call': {\n const fn = FUNCTIONS[n.fn];\n if (!fn) throw new FormulaError('#NAME?');\n return fn(n.fn === 'IF' ? [] : n.args.map(ev), n.args, ev);\n }\n }\n };\n return ev(node);\n}\n\nconst cache = new Map<string, Node | string>();\nfunction compile(src: string): Node {\n let hit = cache.get(src);\n if (hit === undefined) {\n try { hit = parse(src); } catch (e) { hit = e instanceof FormulaError ? e.code : '#SYNTAX!'; }\n if (cache.size > 500) cache.clear();\n cache.set(src, hit);\n }\n if (typeof hit === 'string') throw new FormulaError(hit);\n return hit;\n}\n\n/** Runs a formula. `resolve` gives the value of a column by its name (or undefined when there is none). Errors come back as `#CODE!` text. */\nexport function runFormula(src: string, resolve: (name: string) => FormulaValue | undefined): FormulaValue {\n try {\n return evaluate(compile(src), resolve as (name: string) => FormulaValue);\n } catch (e) {\n return e instanceof FormulaError ? e.code : '#ERR';\n }\n}\n\n/** Why a formula cannot be used (a mistake in it, an unknown function or column), or null when it is fine. `names` are the column titles and keys. */\nexport function checkFormula(src: string, names: string[]): string | null {\n let tree: Node;\n try { tree = compile(src); } catch (e) { return e instanceof FormulaError && e.code === '#SYNTAX!' ? 'This formula has a mistake in it (a missing bracket, quote or operator).' : 'This formula cannot be used.'; }\n const known = new Set(names.map((n) => n.toLowerCase()));\n let problem: string | null = null;\n const walk = (n: Node) => {\n if (problem) return;\n if (n.t === 'ref') { if (!known.has(n.name.toLowerCase()) && !['TRUE', 'FALSE', 'PI'].includes(n.name.toUpperCase())) problem = `There is no column called “${n.name}”.`; }\n else if (n.t === 'un') walk(n.a);\n else if (n.t === 'bin') { walk(n.a); walk(n.b); }\n else if (n.t === 'call') { if (!KNOWN.has(n.fn)) problem = `“${n.fn}” is not a known function.`; n.args.forEach(walk); }\n };\n walk(tree);\n return problem;\n}\n\nexport const FORMULA_FUNCTIONS = [...KNOWN].sort();\n","import { runFormula } from './data-table-formula';\n\n/**\n * The data behind a data table, and everything that can be done with it without a screen: validation, search, filter, sort, totals,\n * CSV, a small .xlsx writer and the HTML used for PDF. Pure functions, so they are easy to test and to use on the server.\n */\n\nexport type ColumnType = 'text' | 'number' | 'currency' | 'date' | 'boolean' | 'select';\nexport type Aggregate = 'sum' | 'avg' | 'count' | 'min' | 'max';\nexport type Cell = string | number | boolean | null;\n\nexport interface DataColumn {\n /** Stable id of the column (not shown). */\n key: string;\n title: string;\n type: ColumnType;\n width?: number;\n align?: 'left' | 'center' | 'right';\n /** Digits after the decimal point, for number and currency. */\n decimals?: number;\n /** ISO 4217 code for currency columns (USD, EUR, IDR…). */\n currency?: string;\n /** Allowed values of a select column. */\n options?: string[];\n /** Shown in the footer row. */\n total?: Aggregate;\n hidden?: boolean;\n /** A formula over the other columns of the same row (`[Price] * [Qty]`). The cells of this column are calculated, never stored. */\n formula?: string;\n /** Draw a bar in each cell, as long as the value is compared with the largest one. Number and currency columns. */\n bar?: boolean;\n}\n\nexport type Look = 'red' | 'green' | 'amber' | 'blue' | 'gray' | 'bold';\nexport const LOOKS: Look[] = ['red', 'green', 'amber', 'blue', 'gray', 'bold'];\n/** Fill colours (RRGGBB) for files that cannot use the editor's theme colours. */\nexport const LOOK_FILL: Record<Look, string | null> = { red: 'F8D7DA', green: 'D4EDDA', amber: 'FFF3CD', blue: 'DCE9FB', gray: 'E5E7EB', bold: null };\n\n/** Highlight cells (or the whole row) that match a condition, written like a filter box: `>100`, `5..10`, `Overdue`, `empty`. */\nexport interface FormatRule {\n /** Column key, or '' for any column. */\n column: string;\n test: string;\n look: Look;\n /** Colour the whole row, not just the cell. */\n row: boolean;\n}\n\n/** A named set of search, filters, sort, grouping and hidden columns. */\nexport interface SavedView {\n name: string;\n search: string;\n filters: Record<string, string>;\n sort: { key: string; dir: 'asc' | 'desc' }[];\n groupBy: string[];\n hidden: string[];\n pageSize: number;\n}\n\nexport interface DataTableOptions {\n title: string;\n /** Rows per page; 0 shows every row. */\n pageSize: number;\n search: boolean;\n filters: boolean;\n striped: boolean;\n bordered: boolean;\n selectable: boolean;\n density: 'compact' | 'normal' | 'comfortable';\n /** Height in pixels after which the table scrolls with a fixed header; 0 for none. */\n height: number;\n /** Column keys to group the rows by (up to three levels). */\n groupBy: string[];\n /** Rows can be opened to show their details. */\n detail: boolean;\n /** Rows can be dragged (or moved with Alt+Up and Alt+Down) to change their order. Only while no sort, search or filter is on. */\n reorder: boolean;\n /** Name of a data source given to the plugin: the rows are then loaded page by page instead of stored in the document. Empty = the rows are in the document. */\n source: string;\n}\n\nexport interface DataTableSpec {\n /** Version of the stored format; see `DATA_TABLE_VERSION`. */\n v: number;\n /** Saved by a newer version of the editor than this one: read-only here. */\n future?: boolean;\n columns: DataColumn[];\n rows: Cell[][];\n options: DataTableOptions;\n rules: FormatRule[];\n views: SavedView[];\n}\n\n/**\n * Version of the stored format of a data table (the JSON in the document). It only goes up when a change cannot be read by the earlier\n * code. Every version stays readable: a table saved by this version or an older one always opens. A table saved by a *newer* version\n * is shown but not edited (`future`), so that saving it here cannot drop what this version does not know.\n */\nexport const DATA_TABLE_VERSION = 1;\nexport const MAX_ROWS = 20000;\nexport const MAX_COLUMNS = 100;\nexport const MAX_TEXT = 5000;\nexport const COLUMN_TYPES: ColumnType[] = ['text', 'number', 'currency', 'date', 'boolean', 'select'];\nexport const AGGREGATES: Aggregate[] = ['sum', 'avg', 'count', 'min', 'max'];\nexport const PAGE_SIZES = [10, 25, 50, 100, 0];\n\nexport const defaultOptions = (): DataTableOptions => ({ title: '', pageSize: 10, search: true, filters: false, striped: true, bordered: false, selectable: false, density: 'normal', height: 0, detail: false, reorder: false, groupBy: [], source: '' });\n\n// ---- values\n\n/** Reads \"1,234.56\", \"1.234,56\", \"12%\", \"$5\" and plain numbers. Returns null when there is no number in it. */\nexport function parseNumber(input: unknown): number | null {\n if (typeof input === 'number') return Number.isFinite(input) ? input : null;\n if (typeof input !== 'string') return null;\n let s = input.trim().replace(/[\\s ]/g, '').replace(/^[^\\d+\\-.,]+|[^\\d.,]+$/g, '');\n if (!/\\d/.test(s)) return null;\n const dot = s.lastIndexOf('.');\n const comma = s.lastIndexOf(',');\n if (dot >= 0 && comma >= 0) s = dot > comma ? s.replace(/,/g, '') : s.replace(/\\./g, '').replace(',', '.');\n else if (comma >= 0) s = /^[+-]?\\d{1,3}(,\\d{3})+$/.test(s) ? s.replace(/,/g, '') : s.replace(',', '.');\n else if ((s.match(/\\./g) ?? []).length > 1) s = s.replace(/\\./g, '');\n const n = Number(s);\n return Number.isFinite(n) ? n : null;\n}\n\nconst pad = (n: number, w = 2) => String(n).padStart(w, '0');\n\n/** An ISO date (YYYY-MM-DD) from an ISO string, D/M/YYYY, a Date or a timestamp. Null when it is not a real date. */\nexport function parseDate(input: unknown): string | null {\n if (input instanceof Date) return Number.isNaN(input.getTime()) ? null : `${pad(input.getUTCFullYear(), 4)}-${pad(input.getUTCMonth() + 1)}-${pad(input.getUTCDate())}`;\n if (typeof input !== 'string') return null;\n const s = input.trim();\n let y: number, m: number, d: number;\n let hit = /^(\\d{4})-(\\d{1,2})-(\\d{1,2})(?:$|[T\\s])/.exec(s);\n if (hit) [y, m, d] = [+hit[1], +hit[2], +hit[3]];\n else if ((hit = /^(\\d{1,2})[/.](\\d{1,2})[/.](\\d{4})$/.exec(s))) [d, m, y] = [+hit[1], +hit[2], +hit[3]];\n else return null;\n const t = new Date(Date.UTC(y, m - 1, d));\n return t.getUTCFullYear() === y && t.getUTCMonth() === m - 1 && t.getUTCDate() === d ? `${pad(y, 4)}-${pad(m)}-${pad(d)}` : null;\n}\n\nconst truthy = /^(true|yes|y|1|on|ya|✓|✔)$/i;\nconst falsy = /^(false|no|n|0|off|tidak|)$/i;\n\n/** Makes any value fit a column of this type. Whatever cannot be read becomes empty (null) rather than wrong. */\nexport function coerceCell(type: ColumnType, v: unknown): Cell {\n if (v === null || v === undefined) return type === 'text' || type === 'select' ? '' : type === 'boolean' ? false : null;\n switch (type) {\n case 'number':\n case 'currency':\n return parseNumber(v);\n case 'date':\n return parseDate(v);\n case 'boolean':\n return typeof v === 'boolean' ? v : truthy.test(String(v).trim()) ? true : falsy.test(String(v).trim()) ? false : Boolean(v);\n default:\n return String(v).slice(0, MAX_TEXT);\n }\n}\n\nconst NUMBER_FORMATS = new Map<string, Intl.NumberFormat>();\nfunction numberFormat(locale: string | undefined, o: Intl.NumberFormatOptions): Intl.NumberFormat {\n const key = `${locale ?? ''}|${JSON.stringify(o)}`;\n let f = NUMBER_FORMATS.get(key);\n if (!f) {\n try { f = new Intl.NumberFormat(locale, o); } catch { f = new Intl.NumberFormat(undefined, { ...o, style: 'decimal', currency: undefined }); }\n NUMBER_FORMATS.set(key, f);\n }\n return f;\n}\n\n/** The text shown for a value. */\nexport function formatCell(col: DataColumn, v: Cell, locale?: string): string {\n if (v === null || v === undefined || v === '') return '';\n switch (col.type) {\n case 'number':\n return typeof v === 'number' ? numberFormat(locale, col.decimals === undefined ? { maximumFractionDigits: 6 } : { minimumFractionDigits: col.decimals, maximumFractionDigits: col.decimals }).format(v) : String(v);\n case 'currency':\n return typeof v === 'number' ? numberFormat(locale, { style: 'currency', currency: col.currency || 'USD', ...(col.decimals === undefined ? {} : { minimumFractionDigits: col.decimals, maximumFractionDigits: col.decimals }) }).format(v) : String(v);\n case 'date': {\n const iso = parseDate(String(v));\n if (!iso) return String(v);\n return new Date(`${iso}T00:00:00Z`).toLocaleDateString(locale, { timeZone: 'UTC', year: 'numeric', month: 'short', day: 'numeric' });\n }\n case 'boolean':\n return v ? 'Yes' : 'No';\n default:\n return String(v);\n }\n}\n\n// ---- validation\n\nconst cleanString = (v: unknown, max: number) => (typeof v === 'string' ? v : v == null ? '' : String(v)).slice(0, max);\nconst oneOf = <T extends string>(v: unknown, list: readonly T[], fallback: T): T => (list.includes(v as T) ? (v as T) : fallback);\n\n/** Accepts the stored JSON (string or object) and returns a spec that is safe to draw, or null when it is not a data table. */\nexport function cleanSpec(raw: unknown): DataTableSpec | null {\n let data: any = raw;\n if (typeof raw === 'string') {\n try { data = JSON.parse(raw); } catch { return null; }\n }\n if (!data || typeof data !== 'object' || !Array.isArray(data.columns)) return null;\n const used = new Set<string>();\n const columns: DataColumn[] = [];\n for (const c of data.columns.slice(0, MAX_COLUMNS)) {\n if (!c || typeof c !== 'object') continue;\n let key = cleanString(c.key, 40).replace(/[^\\w-]/g, '') || `c${columns.length + 1}`;\n while (used.has(key)) key += '_';\n used.add(key);\n const type = oneOf<ColumnType>(c.type, COLUMN_TYPES, 'text');\n const col: DataColumn = { key, title: cleanString(c.title, 200), type };\n const width = Math.round(Number(c.width));\n if (width >= 40 && width <= 1200) col.width = width;\n if (c.align === 'left' || c.align === 'center' || c.align === 'right') col.align = c.align;\n const decimals = Number(c.decimals);\n if (Number.isInteger(decimals) && decimals >= 0 && decimals <= 10 && (type === 'number' || type === 'currency')) col.decimals = decimals;\n if (type === 'currency') { const code = cleanString(c.currency, 3).toUpperCase(); col.currency = /^[A-Z]{3}$/.test(code) ? code : 'USD'; }\n if (type === 'select') col.options = (Array.isArray(c.options) ? c.options : []).map((o: unknown) => cleanString(o, 200)).filter(Boolean).slice(0, 200);\n if (AGGREGATES.includes(c.total) && (type === 'number' || type === 'currency' || c.total === 'count')) col.total = c.total;\n if (c.hidden === true) col.hidden = true;\n const formula = cleanString(c.formula, 500).trim();\n if (formula && type !== 'boolean' && type !== 'select') col.formula = formula;\n if (c.bar === true && (type === 'number' || type === 'currency')) col.bar = true;\n columns.push(col);\n }\n if (!columns.length) return null;\n const rows: Cell[][] = [];\n for (const r of (Array.isArray(data.rows) ? data.rows : []).slice(0, MAX_ROWS)) {\n // a row is an array in column order, or an object by column key (handy when some columns are calculated)\n const src: unknown[] = Array.isArray(r) ? r : r && typeof r === 'object' ? columns.map((c) => (Object.prototype.hasOwnProperty.call(r, c.key) ? (r as Record<string, unknown>)[c.key] : undefined)) : [];\n rows.push(columns.map((c, i) => coerceCell(c.type, src[i])));\n }\n const o = data.options && typeof data.options === 'object' ? data.options : {};\n const d = defaultOptions();\n const pageSize = Math.round(Number(o.pageSize));\n const height = Math.round(Number(o.height));\n const options: DataTableOptions = {\n title: cleanString(o.title, 300),\n pageSize: Number.isFinite(pageSize) && pageSize >= 0 && pageSize <= 1000 ? pageSize : d.pageSize,\n search: o.search === undefined ? d.search : o.search === true,\n filters: o.filters === true,\n striped: o.striped === undefined ? d.striped : o.striped === true,\n bordered: o.bordered === true,\n selectable: o.selectable === true,\n density: oneOf(o.density, ['compact', 'normal', 'comfortable'] as const, 'normal'),\n height: Number.isFinite(height) && height >= 120 && height <= 4000 ? height : 0,\n detail: o.detail === true,\n reorder: o.reorder === true,\n groupBy: (Array.isArray(o.groupBy) ? o.groupBy : []).filter((k: unknown) => typeof k === 'string' && columns.some((c) => c.key === k)).filter((k: string, i: number, a: string[]) => a.indexOf(k) === i).slice(0, 3),\n source: cleanString(o.source, 60).replace(/[^\\w.-]/g, ''),\n };\n const keys = new Set(columns.map((c) => c.key));\n const rules: FormatRule[] = (Array.isArray(data.rules) ? data.rules : []).slice(0, 30).flatMap((r: any): FormatRule[] => {\n const test = cleanString(r?.test, 100).trim();\n const column = typeof r?.column === 'string' && keys.has(r.column) ? r.column : '';\n return test && (r?.column === '' || r?.column === undefined || keys.has(r?.column)) ? [{ column, test, look: oneOf(r?.look, LOOKS, 'amber'), row: r?.row === true }] : [];\n });\n const views: SavedView[] = (Array.isArray(data.views) ? data.views : []).slice(0, 20).flatMap((v: any): SavedView[] => {\n const name = cleanString(v?.name, 60).trim();\n if (!name) return [];\n const size = Math.round(Number(v?.pageSize));\n return [{\n name,\n search: cleanString(v?.search, 200),\n filters: Object.fromEntries(Object.entries(v?.filters && typeof v.filters === 'object' ? v.filters : {}).filter(([k, x]) => keys.has(k) && typeof x === 'string' && x.trim()).map(([k, x]) => [k, (x as string).slice(0, 100)])),\n sort: (Array.isArray(v?.sort) ? v.sort : []).filter((x: any) => keys.has(x?.key)).slice(0, 4).map((x: any) => ({ key: x.key, dir: x.dir === 'desc' ? 'desc' : 'asc' })),\n groupBy: (Array.isArray(v?.groupBy) ? v.groupBy : []).filter((k: unknown) => typeof k === 'string' && keys.has(k)).slice(0, 3),\n hidden: (Array.isArray(v?.hidden) ? v.hidden : []).filter((k: unknown) => typeof k === 'string' && keys.has(k)),\n pageSize: Number.isFinite(size) && size >= 0 && size <= 1000 ? size : 10,\n }];\n });\n const stored = Math.floor(Number(data.v));\n const version = Number.isFinite(stored) && stored >= 1 ? stored : 1; // a table saved before versions existed is version 1\n return version > DATA_TABLE_VERSION ? { v: version, future: true, columns, rows, options, rules, views } : { v: DATA_TABLE_VERSION, columns, rows, options, rules, views };\n}\n\n/** A new spec from plain rows: the first row names the columns and each column's type is guessed from its values. */\nexport function specFromRows(rows: unknown[][], options: Partial<DataTableOptions> = {}): DataTableSpec {\n const head = (rows[0] ?? []).map((v) => cleanString(v, 200));\n const body = rows.slice(1);\n const width = Math.max(head.length, ...body.map((r) => r.length), 1);\n const columns: DataColumn[] = Array.from({ length: Math.min(width, MAX_COLUMNS) }, (_, i) => ({ key: `c${i + 1}`, title: head[i] || `Column ${i + 1}`, type: guessType(body.map((r) => r[i])) }));\n return cleanSpec({ columns, rows: body, options: { ...defaultOptions(), ...options } }) as DataTableSpec;\n}\n\n/** The type that fits every non-empty value in a column. Text when in doubt. */\nexport function guessType(values: unknown[]): ColumnType {\n const filled = values.map((v) => (typeof v === 'string' ? v.trim() : v)).filter((v) => v !== '' && v !== null && v !== undefined);\n if (!filled.length) return 'text';\n if (filled.every((v) => typeof v === 'boolean' || (typeof v === 'string' && /^(true|false|yes|no)$/i.test(v)))) return 'boolean';\n if (filled.every((v) => parseDate(v) !== null && typeof v !== 'number')) return 'date';\n // a number only when the text is nothing but a number (a phone or a code with letters stays text, and so does anything with a leading zero)\n if (filled.every((v) => (typeof v === 'number' && Number.isFinite(v)) || (typeof v === 'string' && /^[-+]?(\\d{1,3}([.,]\\d{3})+|\\d+)([.,]\\d+)?$/.test(v) && !/^[-+]?0\\d/.test(v)))) return 'number';\n return 'text';\n}\n\n// ---- formula columns\n\nconst COMPUTED = new WeakMap<Cell[][], { columns: DataColumn[]; out: Cell[][] }>();\n\n/** The same table with every formula column filled in. Without formula columns it is returned as it is. Results are remembered per rows array. */\nexport function withFormulas(spec: DataTableSpec, rows: Cell[][] = spec.rows): DataTableSpec {\n if (!spec.columns.some((c) => c.formula)) return rows === spec.rows ? spec : { ...spec, rows };\n const memo = COMPUTED.get(rows);\n if (memo && memo.columns === spec.columns) return { ...spec, rows: memo.out };\n const cols = spec.columns;\n const byName = new Map<string, number>();\n cols.forEach((c, i) => { byName.set(c.key.toLowerCase(), i); if (c.title) byName.set(c.title.toLowerCase(), byName.get(c.title.toLowerCase()) ?? i); });\n const out = rows.map((row) => {\n const done = new Map<number, Cell>();\n const busy = new Set<number>();\n const value = (i: number): Cell => {\n const col = cols[i];\n if (!col.formula) return row[i] ?? null;\n if (done.has(i)) return done.get(i)!;\n if (busy.has(i)) return '#CYCLE!';\n busy.add(i);\n const res = runFormula(col.formula, (name) => { const at = byName.get(name.toLowerCase()); return at === undefined ? undefined : (value(at) as number | string | boolean | null); });\n busy.delete(i);\n const cell: Cell = typeof res === 'string' && res.startsWith('#') ? res : coerceCell(col.type, res);\n done.set(i, cell);\n return cell;\n };\n return cols.map((_, i) => value(i));\n });\n COMPUTED.set(rows, { columns: spec.columns, out });\n return { ...spec, rows: out };\n}\n\n// ---- highlight rules\n\nconst isBlank = (v: Cell) => v === null || v === undefined || v === '';\n\n/** What the highlight rules say about each row: a look for the whole row and one per cell (the first matching rule wins). */\nexport function ruleLooks(spec: DataTableSpec, locale?: string): (row: Cell[]) => { row: Look | null; cells: (Look | null)[] } {\n const keyAt = new Map(spec.columns.map((c, i) => [c.key, i]));\n const rules = spec.rules.map((r) => {\n const word = r.test.trim().toLowerCase();\n const tests = spec.columns.map((c, i): Test | null => (r.column && keyAt.get(r.column) !== i ? null : word === 'empty' || word === 'blank' ? isBlank : word === '!empty' || word === 'notempty' ? (v) => !isBlank(v) : filterTest(c, r.test, locale)));\n return { rule: r, tests };\n });\n return (row) => {\n const cells: (Look | null)[] = spec.columns.map(() => null);\n let whole: Look | null = null;\n for (const { rule, tests } of rules) {\n tests.forEach((t, i) => {\n if (!t || !t(row[i] ?? null)) return;\n if (rule.row) whole = whole ?? rule.look;\n else cells[i] = cells[i] ?? rule.look;\n });\n }\n return { row: whole, cells };\n };\n}\n\n// ---- view: search, filter, sort\n\nexport interface ViewState {\n search: string;\n filters: Record<string, string>;\n sort: { key: string; dir: 'asc' | 'desc' }[];\n}\n\ntype Test = (v: Cell) => boolean;\nconst num = (col: DataColumn, s: string): number | null => (col.type === 'date' ? (parseDate(s) ? Date.parse(`${parseDate(s)}T00:00:00Z`) : null) : parseNumber(s));\nconst val = (col: DataColumn, v: Cell): number | null => (col.type === 'date' ? (typeof v === 'string' && parseDate(v) ? Date.parse(`${parseDate(v)}T00:00:00Z`) : null) : typeof v === 'number' ? v : null);\n\n/** One filter box: text is \"contains\"; numbers and dates take `>5`, `>=5`, `<5`, `<=5`, `=5`, `!=5`, `5..10` or a plain value. */\nexport function filterTest(col: DataColumn, expr: string, locale?: string): Test | null {\n const e = expr.trim();\n if (!e) return null;\n if (col.type === 'boolean') return (v) => (truthy.test(e) ? v === true : falsy.test(e) ? v !== true : true);\n if (col.type === 'select') return (v) => String(v ?? '') === e;\n if (col.type === 'text') {\n const q = e.toLowerCase();\n return (v) => String(v ?? '').toLowerCase().includes(q);\n }\n const range = /^(.+?)\\.\\.(.+)$/.exec(e);\n if (range) {\n const [a, b] = [num(col, range[1]), num(col, range[2])];\n if (a === null || b === null) return () => false;\n return (v) => { const x = val(col, v); return x !== null && x >= Math.min(a, b) && x <= Math.max(a, b); };\n }\n const op = /^(>=|<=|!=|=|>|<)?\\s*(.*)$/.exec(e)!;\n const target = num(col, op[2]);\n if (target === null) {\n // not a number: fall back to the shown text, so typing \"Mar\" still finds March dates\n const q = e.toLowerCase();\n return (v) => formatCell(col, v, locale).toLowerCase().includes(q);\n }\n return (v) => {\n const x = val(col, v);\n if (x === null) return op[1] === '!=';\n switch (op[1]) {\n case '>': return x > target;\n case '>=': return x >= target;\n case '<': return x < target;\n case '<=': return x <= target;\n case '!=': return x !== target;\n default: return x === target;\n }\n };\n}\n\nfunction compare(col: DataColumn, a: Cell, b: Cell): number {\n switch (col.type) {\n case 'number':\n case 'currency':\n return (a as number) - (b as number);\n case 'boolean':\n return Number(a) - Number(b);\n case 'date':\n return String(a) < String(b) ? -1 : String(a) > String(b) ? 1 : 0;\n default:\n return String(a).localeCompare(String(b), undefined, { numeric: true, sensitivity: 'base' });\n }\n}\n\nconst isEmpty = (c: DataColumn, v: Cell) => v === null || v === undefined || (v === '' && c.type !== 'boolean');\n\n/** Indexes of the rows to show, in order: searched, filtered, then sorted (empty values always last). */\nexport function queryRows(source: DataTableSpec, view: ViewState, locale?: string): number[] {\n const spec = withFormulas(source);\n const cols = spec.columns;\n const visible = cols.map((c, i) => (c.hidden ? -1 : i)).filter((i) => i >= 0);\n const tests: { i: number; t: Test }[] = [];\n cols.forEach((c, i) => { const t = filterTest(c, view.filters[c.key] ?? '', locale); if (t) tests.push({ i, t }); });\n const q = view.search.trim().toLowerCase();\n let out: number[] = [];\n spec.rows.forEach((row, r) => {\n if (tests.some(({ i, t }) => !t(row[i]))) return;\n if (q && !visible.some((i) => formatCell(cols[i], row[i], locale).toLowerCase().includes(q) || String(row[i] ?? '').toLowerCase().includes(q))) return;\n out.push(r);\n });\n // grouped rows keep each group together: the group columns sort first (in the direction chosen for them, else ascending)\n const groups = spec.options.groupBy.map((key) => view.sort.find((s) => s.key === key) ?? { key, dir: 'asc' as const });\n const effective = [...groups, ...view.sort.filter((s) => !spec.options.groupBy.includes(s.key))];\n const keys = effective.map((s) => ({ i: cols.findIndex((c) => c.key === s.key), dir: s.dir === 'desc' ? -1 : 1 })).filter((k) => k.i >= 0);\n if (keys.length) {\n out = out\n .map((r, n) => ({ r, n }))\n .sort((x, y) => {\n for (const k of keys) {\n const [a, b] = [spec.rows[x.r][k.i], spec.rows[y.r][k.i]];\n const [ea, eb] = [isEmpty(cols[k.i], a), isEmpty(cols[k.i], b)];\n if (ea || eb) { if (ea && eb) continue; return ea ? 1 : -1; }\n const d = compare(cols[k.i], a, b);\n if (d) return d * k.dir;\n }\n return x.n - y.n;\n })\n .map((x) => x.r);\n }\n return out;\n}\n\n/** A footer value over the given rows, or null when there is nothing to total. */\nexport function aggregate(col: DataColumn, kind: Aggregate, rows: Cell[][], index: number[], at: number): number | null {\n if (kind === 'count') return index.filter((r) => !isEmpty(col, rows[r][at])).length;\n const xs = index.map((r) => rows[r][at]).filter((v): v is number => typeof v === 'number');\n if (!xs.length) return null;\n switch (kind) {\n case 'sum': return xs.reduce((a, b) => a + b, 0);\n case 'avg': return xs.reduce((a, b) => a + b, 0) / xs.length;\n case 'min': return Math.min(...xs);\n default: return Math.max(...xs);\n }\n}\n\n// ---- groups\n\nexport interface GroupInfo {\n /** Unique id of this group (path of column and value), used to remember which are collapsed. */\n key: string;\n depth: number;\n col: number;\n value: Cell;\n label: string;\n /** Every row of the group (not only those on the current page). */\n rows: number[];\n}\n\n/** One line of the table body: a data row with the groups it sits in, or (r = -1) a whole group that is folded away. */\nexport interface DisplayRow { r: number; path: GroupInfo[] }\n\n/** Splits the ordered rows into groups (the order of `index` is kept) and drops the rows of folded groups. */\nexport function groupDisplay(spec: DataTableSpec, index: number[], collapsed: ReadonlySet<string> = new Set(), locale?: string, rows: Cell[][] = spec.rows): DisplayRow[] {\n const by = spec.options.groupBy.map((k) => spec.columns.findIndex((c) => c.key === k)).filter((i) => i >= 0);\n if (!by.length) return index.map((r) => ({ r, path: [] }));\n const groups = new Map<string, GroupInfo>();\n const paths = index.map((r) => {\n const path: GroupInfo[] = [];\n let id = '';\n by.forEach((col, depth) => {\n const v = rows[r][col];\n id += `${depth}:${spec.columns[col].key}=${JSON.stringify(v)}|`;\n let g = groups.get(id);\n if (!g) { g = { key: id, depth, col, value: v, label: `${spec.columns[col].title}: ${formatCell(spec.columns[col], v, locale) || '(empty)'}`, rows: [] }; groups.set(id, g); }\n g.rows.push(r);\n path.push(g);\n });\n return path;\n });\n const out: DisplayRow[] = [];\n let folded: string | null = null;\n index.forEach((r, n) => {\n const path = paths[n];\n const hit = path.find((g) => collapsed.has(g.key));\n if (hit) {\n if (folded === hit.key) return;\n folded = hit.key;\n out.push({ r: -1, path: path.slice(0, hit.depth + 1) });\n return;\n }\n folded = null;\n out.push({ r, path });\n });\n return out;\n}\n\n// ---- remote data\n\n/** What a data source is asked for. Filters are the text typed in each column's filter box, by column key. */\nexport interface DataQuery {\n page: number;\n pageSize: number;\n search: string;\n filters: Record<string, string>;\n sort: { key: string; dir: 'asc' | 'desc' }[];\n groupBy: string[];\n}\n\n/** What a data source answers: one page of rows (arrays in column order, or objects by column key) and the total matching rows. */\nexport interface DataPage {\n rows: unknown[];\n total: number;\n /** Footer values by column key, over all matching rows (the page alone cannot give a sum). */\n totals?: Record<string, number | null>;\n}\n\n/** Turns a data source's rows into cells of the right type; rows from outside are never trusted. */\nexport function normalizeRows(columns: DataColumn[], rows: unknown): Cell[][] {\n if (!Array.isArray(rows)) return [];\n return rows.slice(0, MAX_ROWS).map((r) => {\n const get = (c: DataColumn, i: number) => (Array.isArray(r) ? r[i] : r && typeof r === 'object' ? (r as Record<string, unknown>)[c.key] : undefined);\n return columns.map((c, i) => coerceCell(c.type, get(c, i)));\n });\n}\n\n// ---- export\n\nexport interface ExportOptions {\n /** Row indexes to export, in order. Default: every row. */\n rows?: number[];\n /** Include hidden columns. Default false. */\n hidden?: boolean;\n /** CSV: put the shown text (1,234.50) in the file instead of the plain value (1234.5). */\n formatted?: boolean;\n /** .xlsx and PDF: colour the cells the highlight rules match. Default true. */\n formatting?: boolean;\n /** CSV delimiter. Default \",\". */\n delimiter?: string;\n /** CSV: start the file with a byte-order mark so Excel reads it as UTF-8. Default true. */\n bom?: boolean;\n locale?: string;\n title?: string;\n}\n\nconst exported = (spec: DataTableSpec, o: ExportOptions) => ({\n columns: spec.columns.map((c, i) => ({ c, i })).filter(({ c }) => o.hidden || !c.hidden),\n index: o.rows ?? spec.rows.map((_, r) => r),\n});\n\nfunction csvCell(col: DataColumn, v: Cell, o: ExportOptions, delim: string): string {\n let s: string;\n if (v === null || v === undefined) s = '';\n else if (o.formatted) s = formatCell(col, v, o.locale);\n else if (typeof v === 'boolean') s = v ? 'TRUE' : 'FALSE';\n else s = String(v);\n // A spreadsheet runs text that starts with these as a formula; the quote stops that. Numbers are written as they are.\n if (typeof v === 'string' && /^[=+\\-@\\t\\r]/.test(s)) s = `'${s}`;\n return /[\",\\r\\n]/.test(s) || s.includes(delim) || /^\\s|\\s$/.test(s) ? `\"${s.replace(/\"/g, '\"\"')}\"` : s;\n}\n\n/** The table as CSV text (CRLF line ends, quotes doubled). */\nexport function toCSV(source: DataTableSpec, o: ExportOptions = {}): string {\n const spec = withFormulas(source);\n const delim = o.delimiter ?? ',';\n const { columns, index } = exported(spec, o);\n const head = columns.map(({ c }) => csvCell({ ...c, type: 'text' }, c.title, { ...o, formatted: false }, delim));\n const body = index.map((r) => columns.map(({ c, i }) => csvCell(c, spec.rows[r][i], o, delim)).join(delim));\n return `${o.bom === false ? '' : ''}${[head.join(delim), ...body].join('\\r\\n')}\\r\\n`;\n}\n\n/** Reads CSV or TSV text (quoted fields, doubled quotes, line breaks inside quotes). The delimiter is guessed from the first line. */\nexport function parseCSV(text: string, delimiter?: string): string[][] {\n const src = text.replace(/^/, '');\n const first = src.split(/\\r?\\n/, 1)[0] ?? '';\n const delim = delimiter ?? ([',', ';', '\\t'].map((d) => ({ d, n: first.split(d).length })).sort((a, b) => b.n - a.n)[0].d);\n const rows: string[][] = [];\n let row: string[] = [];\n let field = '';\n let quoted = false;\n for (let i = 0; i < src.length; i++) {\n const ch = src[i];\n if (quoted) {\n if (ch === '\"') { if (src[i + 1] === '\"') { field += '\"'; i++; } else quoted = false; } else field += ch;\n } else if (ch === '\"' && field === '') quoted = true;\n else if (ch === delim) { row.push(field); field = ''; }\n else if (ch === '\\n' || ch === '\\r') {\n if (ch === '\\r' && src[i + 1] === '\\n') i++;\n row.push(field); field = '';\n rows.push(row); row = [];\n } else field += ch;\n }\n if (field !== '' || row.length) { row.push(field); rows.push(row); }\n return rows.filter((r) => r.length > 1 || r[0] !== '').slice(0, MAX_ROWS + 1);\n}\n\n// ---- .xlsx (a zip of XML files, written here with no library)\n\nconst CRC_TABLE = (() => {\n const t = new Uint32Array(256);\n for (let n = 0; n < 256; n++) { let c = n; for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1; t[n] = c >>> 0; }\n return t;\n})();\n\nexport function crc32(data: Uint8Array): number {\n let c = 0xffffffff;\n for (let i = 0; i < data.length; i++) c = CRC_TABLE[(c ^ data[i]) & 0xff] ^ (c >>> 8);\n return (c ^ 0xffffffff) >>> 0;\n}\n\n/** A zip archive with the files stored uncompressed. Same input, same bytes. */\nexport function zipStore(files: { name: string; data: Uint8Array }[]): Uint8Array {\n const enc = new TextEncoder();\n const parts: Uint8Array[] = [];\n const central: Uint8Array[] = [];\n let offset = 0;\n const u16 = (v: DataView, at: number, n: number) => v.setUint16(at, n, true);\n const u32 = (v: DataView, at: number, n: number) => v.setUint32(at, n >>> 0, true);\n for (const f of files) {\n const name = enc.encode(f.name);\n const crc = crc32(f.data);\n const local = new Uint8Array(30 + name.length);\n const lv = new DataView(local.buffer);\n u32(lv, 0, 0x04034b50); u16(lv, 4, 20); u16(lv, 6, 0x0800); u16(lv, 8, 0); u16(lv, 10, 0); u16(lv, 12, 0x21);\n u32(lv, 14, crc); u32(lv, 18, f.data.length); u32(lv, 22, f.data.length); u16(lv, 26, name.length); u16(lv, 28, 0);\n local.set(name, 30);\n const dir = new Uint8Array(46 + name.length);\n const dv = new DataView(dir.buffer);\n u32(dv, 0, 0x02014b50); u16(dv, 4, 20); u16(dv, 6, 20); u16(dv, 8, 0x0800); u16(dv, 10, 0); u16(dv, 12, 0); u16(dv, 14, 0x21);\n u32(dv, 16, crc); u32(dv, 20, f.data.length); u32(dv, 24, f.data.length); u16(dv, 28, name.length);\n u32(dv, 42, offset);\n dir.set(name, 46);\n parts.push(local, f.data);\n central.push(dir);\n offset += local.length + f.data.length;\n }\n const size = central.reduce((n, d) => n + d.length, 0);\n const end = new Uint8Array(22);\n const ev = new DataView(end.buffer);\n u32(ev, 0, 0x06054b50); u16(ev, 8, files.length); u16(ev, 10, files.length); u32(ev, 12, size); u32(ev, 16, offset);\n const out = new Uint8Array(offset + size + 22);\n let at = 0;\n for (const p of [...parts, ...central, end]) { out.set(p, at); at += p.length; }\n return out;\n}\n\nconst xml = (s: string) => s.replace(/[\\u0000-\\u0008\\u000b\\u000c\\u000e-\\u001f￾￿]/g, '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n\nfunction columnName(i: number): string {\n let s = '';\n for (let n = i + 1; n > 0; n = Math.floor((n - 1) / 26)) s = String.fromCharCode(65 + ((n - 1) % 26)) + s;\n return s;\n}\n\nconst sheetName = (s: string) => s.replace(/[[\\]:*?/\\\\]/g, ' ').replace(/^['\\s]+|['\\s]+$/g, '').slice(0, 31) || 'Sheet1';\n\n/** Days since 1899-12-30, which is how a spreadsheet stores a date. */\nconst serial = (iso: string) => Math.round((Date.parse(`${iso}T00:00:00Z`) - Date.UTC(1899, 11, 30)) / 86400000);\n\nfunction currencySymbol(code: string): string {\n try {\n return new Intl.NumberFormat('en', { style: 'currency', currency: code, currencyDisplay: 'narrowSymbol' }).formatToParts(0).find((p) => p.type === 'currency')?.value ?? code;\n } catch { return code; }\n}\n\n/** The table as a real Excel workbook: one sheet, a bold header row that stays in view, number and date formats, filter buttons, column widths. */\nexport function toXlsx(source: DataTableSpec, o: ExportOptions = {}): Uint8Array {\n const spec = withFormulas(source);\n const { columns, index } = exported(spec, o);\n const formats: string[] = []; // custom number formats, ids start at 164\n const fmtId = (code: string) => { let i = formats.indexOf(code); if (i < 0) i = formats.push(code) - 1; return 164 + i; };\n const styles: { numFmtId: number; look: Look | null }[] = [];\n const style = (numFmtId: number, look: Look | null = null) => {\n if (!numFmtId && !look) return 0;\n let i = styles.findIndex((s) => s.numFmtId === numFmtId && s.look === look);\n if (i < 0) i = styles.push({ numFmtId, look }) - 1;\n return i + 2; // 0 normal, 1 header\n };\n const formatOf = (c: DataColumn): number => {\n if (c.type === 'date') return fmtId('yyyy-mm-dd');\n if (c.type === 'number' || c.type === 'currency') {\n const dec = c.decimals ?? (c.type === 'currency' ? 2 : -1);\n const body = dec < 0 ? '#,##0.######' : dec === 0 ? '#,##0' : `#,##0.${'0'.repeat(dec)}`;\n return fmtId(c.type === 'currency' ? `\"${currencySymbol(c.currency || 'USD').replace(/\"/g, '')}\"${body}` : body);\n }\n return 0;\n };\n const numFmts0 = columns.map(({ c }) => formatOf(c));\n const looks = o.formatting === false || !spec.rules.length ? null : ruleLooks(spec, o.locale);\n\n const rows: string[] = [];\n rows.push(`<row r=\"1\">${columns.map(({ c }, k) => `<c r=\"${columnName(k)}1\" s=\"1\" t=\"inlineStr\"><is><t xml:space=\"preserve\">${xml(c.title)}</t></is></c>`).join('')}</row>`);\n index.forEach((r, n) => {\n const lk = looks?.(spec.rows[r]);\n const cells = columns.map(({ c, i }, k) => {\n const v = spec.rows[r][i];\n const ref = `${columnName(k)}${n + 2}`;\n const look = lk ? lk.cells[i] ?? lk.row : null;\n const st = style(numFmts0[k], look);\n const sAttr = st ? ` s=\"${st}\"` : '';\n if (v === null || v === undefined || (v === '' && c.type !== 'boolean')) return look ? `<c r=\"${ref}\"${sAttr}/>` : '';\n if (c.type === 'boolean') return `<c r=\"${ref}\"${sAttr} t=\"b\"><v>${v ? 1 : 0}</v></c>`;\n if ((c.type === 'number' || c.type === 'currency') && typeof v === 'number') return `<c r=\"${ref}\"${sAttr}><v>${v}</v></c>`;\n if (c.type === 'date' && typeof v === 'string' && parseDate(v)) return `<c r=\"${ref}\"${sAttr}><v>${serial(parseDate(v)!)}</v></c>`;\n return `<c r=\"${ref}\"${sAttr} t=\"inlineStr\"><is><t xml:space=\"preserve\">${xml(String(v))}</t></is></c>`;\n });\n rows.push(`<row r=\"${n + 2}\">${cells.join('')}</row>`);\n });\n\n const widths = columns.map(({ c, i }) => {\n const longest = Math.max(c.title.length, ...index.slice(0, 200).map((r) => formatCell(c, spec.rows[r][i], o.locale).length));\n return Math.min(60, Math.max(8, Math.round(c.width ? c.width / 7 : longest + 2)));\n });\n const last = `${columnName(columns.length - 1)}${index.length + 1}`;\n const sheet = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\\n<worksheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"><sheetViews><sheetView workbookViewId=\"0\"><pane ySplit=\"1\" topLeftCell=\"A2\" activePane=\"bottomLeft\" state=\"frozen\"/></sheetView></sheetViews><sheetFormatPr defaultRowHeight=\"15\"/><cols>${widths.map((w, k) => `<col min=\"${k + 1}\" max=\"${k + 1}\" width=\"${w}\" customWidth=\"1\"/>`).join('')}</cols><sheetData>${rows.join('')}</sheetData><autoFilter ref=\"A1:${last}\"/></worksheet>`;\n const numFmts = formats.length ? `<numFmts count=\"${formats.length}\">${formats.map((f, i) => `<numFmt numFmtId=\"${164 + i}\" formatCode=\"${xml(f)}\"/>`).join('')}</numFmts>` : '';\n const stylesXml = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\\n<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\">${numFmts}<fonts count=\"2\"><font><sz val=\"11\"/><name val=\"Calibri\"/></font><font><b/><sz val=\"11\"/><name val=\"Calibri\"/></font></fonts><fills count=\"8\"><fill><patternFill patternType=\"none\"/></fill><fill><patternFill patternType=\"gray125\"/></fill><fill><patternFill patternType=\"solid\"><fgColor rgb=\"FFE7ECF3\"/><bgColor indexed=\"64\"/></patternFill></fill>${(['red', 'green', 'amber', 'blue', 'gray'] as Look[]).map((l) => `<fill><patternFill patternType=\"solid\"><fgColor rgb=\"FF${LOOK_FILL[l]}\"/><bgColor indexed=\"64\"/></patternFill></fill>`).join('')}</fills><borders count=\"1\"><border><left/><right/><top/><bottom/><diagonal/></border></borders><cellStyleXfs count=\"1\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/></cellStyleXfs><cellXfs count=\"${2 + styles.length}\"><xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/><xf numFmtId=\"0\" fontId=\"1\" fillId=\"2\" borderId=\"0\" xfId=\"0\" applyFont=\"1\" applyFill=\"1\"/>${styles.map((s) => { const fill = s.look && s.look !== 'bold' ? 3 + ['red', 'green', 'amber', 'blue', 'gray'].indexOf(s.look) : 0; return `<xf numFmtId=\"${s.numFmtId}\" fontId=\"${s.look === 'bold' ? 1 : 0}\" fillId=\"${fill}\" borderId=\"0\" xfId=\"0\" applyNumberFormat=\"1\"${fill ? ' applyFill=\"1\"' : ''}${s.look === 'bold' ? ' applyFont=\"1\"' : ''}/>`; }).join('')}</cellXfs><cellStyles count=\"1\"><cellStyle name=\"Normal\" xfId=\"0\" builtinId=\"0\"/></cellStyles></styleSheet>`;\n const name = sheetName(o.title || spec.options.title || 'Sheet1');\n const head = '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\\n';\n const text = (s: string) => new TextEncoder().encode(s);\n return zipStore([\n { name: '[Content_Types].xml', data: text(`${head}<Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\"><Default Extension=\"rels\" ContentType=\"application/vnd.openxmlformats-package.relationships+xml\"/><Default Extension=\"xml\" ContentType=\"application/xml\"/><Override PartName=\"/xl/workbook.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml\"/><Override PartName=\"/xl/worksheets/sheet1.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml\"/><Override PartName=\"/xl/styles.xml\" ContentType=\"application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml\"/></Types>`) },\n { name: '_rels/.rels', data: text(`${head}<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\" Target=\"xl/workbook.xml\"/></Relationships>`) },\n { name: 'xl/workbook.xml', data: text(`${head}<workbook xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"><sheets><sheet name=\"${xml(name)}\" sheetId=\"1\" r:id=\"rId1\"/></sheets></workbook>`) },\n { name: 'xl/_rels/workbook.xml.rels', data: text(`${head}<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\"><Relationship Id=\"rId1\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet\" Target=\"worksheets/sheet1.xml\"/><Relationship Id=\"rId2\" Type=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\" Target=\"styles.xml\"/></Relationships>`) },\n { name: 'xl/styles.xml', data: text(stylesXml) },\n { name: 'xl/worksheets/sheet1.xml', data: text(sheet) },\n ]);\n}\n\n// ---- PDF (through the browser's print dialog, so every script and font works)\n\nconst esc = (s: string) => s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n\n/** A standalone page with just the table, ready to print or save as PDF. Header row repeats on every page. */\nexport function toPrintHTML(source: DataTableSpec, o: ExportOptions = {}): string {\n const spec = withFormulas(source);\n const { columns, index } = exported(spec, o);\n const looks = o.formatting === false || !spec.rules.length ? null : ruleLooks(spec, o.locale);\n const lookCss = (l: Look | null | undefined) => (!l ? '' : l === 'bold' ? ';font-weight:700' : `;background:#${LOOK_FILL[l]}`);\n const align = (c: DataColumn) => c.align ?? (c.type === 'number' || c.type === 'currency' ? 'right' : 'left');\n const head = columns.map(({ c }) => `<th style=\"text-align:${align(c)}\">${esc(c.title)}</th>`).join('');\n const body = index.map((r) => { const lk = looks?.(spec.rows[r]); return `<tr>${columns.map(({ c, i }) => `<td style=\"text-align:${align(c)}${lookCss(lk ? lk.cells[i] ?? lk.row : null)}\">${esc(formatCell(c, spec.rows[r][i], o.locale))}</td>`).join('')}</tr>`; }).join('');\n const totals = columns.some(({ c }) => c.total)\n ? `<tfoot><tr>${columns.map(({ c, i }, k) => { const t = c.total ? aggregate(c, c.total, spec.rows, index, i) : null; return `<td style=\"text-align:${align(c)}\">${t === null ? (k === 0 ? 'Total' : '') : esc(formatCell(c.total === 'count' ? { ...c, type: 'number', decimals: 0 } : c, t, o.locale))}</td>`; }).join('')}</tr></tfoot>`\n : '';\n const title = o.title ?? spec.options.title;\n return `<!doctype html><html><head><meta charset=\"utf-8\"><title>${esc(title || 'Table')}</title><style>@page{margin:14mm}body{font:12px/1.4 system-ui,sans-serif;color:#111;margin:0}h1{font-size:16px;margin:0 0 8px}table{border-collapse:collapse;width:100%}th,td{border:1px solid #888;padding:4px 8px;vertical-align:top}th{background:#e7ecf3;font-weight:600}thead{display:table-header-group}tfoot{display:table-footer-group;font-weight:600}tr{break-inside:avoid}*{-webkit-print-color-adjust:exact;print-color-adjust:exact}</style></head><body>${title ? `<h1>${esc(title)}</h1>` : ''}<table><thead><tr>${head}</tr></thead><tbody>${body}</tbody>${totals}</table></body></html>`;\n}\n\n// ---- reading .xlsx (also with no library: a zip reader, the browser's own inflate, and a few XML parts)\n\nconst MAX_UNZIPPED = 64 * 1024 * 1024;\n\nasync function inflateRaw(data: Uint8Array, limit: number): Promise<Uint8Array> {\n if (typeof DecompressionStream === 'undefined') throw new Error('This browser cannot unpack compressed files.');\n const ds = new DecompressionStream('deflate-raw');\n const writer = ds.writable.getWriter();\n writer.write(data as BufferSource).catch(() => {});\n writer.close().catch(() => {});\n const reader = ds.readable.getReader();\n const chunks: Uint8Array[] = [];\n let size = 0;\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n size += value.length;\n if (size > limit) { await reader.cancel(); throw new Error('The file is too large to open.'); }\n chunks.push(value);\n }\n const out = new Uint8Array(size);\n let at = 0;\n for (const c of chunks) { out.set(c, at); at += c.length; }\n return out;\n}\n\n/** Reads the entries of a zip archive. Entries are unpacked on demand, and each one is size-checked. */\nfunction openZip(bytes: Uint8Array): { names: string[]; read(name: string): Promise<string | null> } {\n const v = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n let end = -1;\n for (let i = bytes.length - 22; i >= Math.max(0, bytes.length - 22 - 65535); i--) if (v.getUint32(i, true) === 0x06054b50) { end = i; break; }\n if (end < 0) throw new Error('This is not a spreadsheet file.');\n const count = v.getUint16(end + 10, true);\n let at = v.getUint32(end + 16, true);\n const entries = new Map<string, { method: number; csize: number; usize: number; offset: number }>();\n let total = 0;\n for (let i = 0; i < count && at + 46 <= bytes.length; i++) {\n if (v.getUint32(at, true) !== 0x02014b50) break;\n const method = v.getUint16(at + 10, true), csize = v.getUint32(at + 20, true), usize = v.getUint32(at + 24, true);\n const nl = v.getUint16(at + 28, true), el = v.getUint16(at + 30, true), cl = v.getUint16(at + 32, true), offset = v.getUint32(at + 42, true);\n const name = new TextDecoder().decode(bytes.subarray(at + 46, at + 46 + nl));\n total += usize;\n if (usize > MAX_UNZIPPED || total > MAX_UNZIPPED * 2) throw new Error('The file is too large to open.');\n entries.set(name, { method, csize, usize, offset });\n at += 46 + nl + el + cl;\n }\n return {\n names: [...entries.keys()],\n async read(name) {\n const e = entries.get(name);\n if (!e) return null;\n const start = e.offset + 30 + v.getUint16(e.offset + 26, true) + v.getUint16(e.offset + 28, true);\n const raw = bytes.subarray(start, start + e.csize);\n const data = e.method === 0 ? raw : e.method === 8 ? await inflateRaw(raw, Math.min(MAX_UNZIPPED, e.usize + 1024)) : null;\n if (!data) throw new Error('This spreadsheet uses a compression method that is not supported.');\n return new TextDecoder().decode(data);\n },\n };\n}\n\nconst BUILTIN_DATE_FORMATS = new Set([14, 15, 16, 17, 18, 19, 20, 21, 22, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 45, 46, 47, 50, 51, 52, 53, 54, 55, 56, 57, 58]);\nconst isDateFormat = (id: number, custom: Map<number, string>) => BUILTIN_DATE_FORMATS.has(id) || /[dmyhs]/i.test((custom.get(id) ?? '').replace(/\"[^\"]*\"|\\[[^\\]]*\\]|\\\\./g, ''));\nconst colIndex = (ref: string) => { let n = 0; for (const ch of /^[A-Z]+/i.exec(ref)?.[0] ?? '') n = n * 26 + (ch.toUpperCase().charCodeAt(0) - 64); return n - 1; };\nconst fromSerial = (n: number) => new Date(Date.UTC(1899, 11, 30) + Math.floor(n) * 86400000).toISOString().slice(0, 10);\n\n/**\n * The first visible sheet of an .xlsx file as plain rows: text, numbers, true/false and dates (as YYYY-MM-DD). Formulas give their last\n * calculated value. Needs `DOMParser` and `DecompressionStream`, which every current browser has.\n */\nexport async function parseXlsx(input: ArrayBuffer | Uint8Array): Promise<{ rows: unknown[][]; sheet: string }> {\n const zip = openZip(input instanceof Uint8Array ? input : new Uint8Array(input));\n const parse = (xmlText: string | null) => {\n if (xmlText === null) return null;\n const doc = new DOMParser().parseFromString(xmlText, 'application/xml');\n return doc.getElementsByTagName('parsererror').length ? null : doc;\n };\n const all = (node: ParentNode, tag: string) => Array.from((node as Element).getElementsByTagName(tag));\n const book = parse(await zip.read('xl/workbook.xml'));\n if (!book) throw new Error('This is not a spreadsheet file.');\n const sheets = all(book, 'sheet').filter((s) => s.getAttribute('state') !== 'hidden' && s.getAttribute('state') !== 'veryHidden');\n const first = sheets[0];\n if (!first) throw new Error('The workbook has no sheets.');\n const rid = first.getAttribute('r:id') ?? first.getAttributeNS('http://schemas.openxmlformats.org/officeDocument/2006/relationships', 'id');\n const rels = parse(await zip.read('xl/_rels/workbook.xml.rels'));\n const target = rels && all(rels, 'Relationship').find((r) => r.getAttribute('Id') === rid)?.getAttribute('Target');\n const path = target ? (target.startsWith('/') ? target.slice(1) : `xl/${target}`) : 'xl/worksheets/sheet1.xml';\n const sheet = parse(await zip.read(path));\n if (!sheet) throw new Error('The first sheet could not be read.');\n\n const strings: string[] = [];\n const sst = parse(await zip.read('xl/sharedStrings.xml'));\n if (sst) for (const si of all(sst, 'si')) strings.push(all(si, 't').filter((t) => !t.closest('rPh')).map((t) => t.textContent ?? '').join(''));\n\n const custom = new Map<number, string>();\n const dateStyle: boolean[] = [];\n const styles = parse(await zip.read('xl/styles.xml'));\n if (styles) {\n for (const n of all(styles, 'numFmt')) custom.set(Number(n.getAttribute('numFmtId')), n.getAttribute('formatCode') ?? '');\n const xfs = all(styles, 'cellXfs')[0];\n if (xfs) for (const xf of Array.from(xfs.children)) dateStyle.push(isDateFormat(Number(xf.getAttribute('numFmtId')), custom));\n }\n\n const rows: unknown[][] = [];\n let next = 0;\n for (const row of all(sheet, 'row')) {\n const at = Number(row.getAttribute('r')) - 1;\n const r = Number.isInteger(at) && at >= 0 ? at : next;\n if (r > MAX_ROWS) break;\n while (rows.length < r) rows.push([]);\n const cells: unknown[] = [];\n let col = 0;\n for (const c of Array.from(row.children).filter((x) => x.tagName === 'c')) {\n const ref = c.getAttribute('r');\n col = ref ? colIndex(ref) : col;\n if (col >= MAX_COLUMNS) { col++; continue; }\n const v = c.getElementsByTagName('v')[0]?.textContent ?? '';\n const type = c.getAttribute('t');\n let value: unknown = '';\n if (type === 's') value = strings[Number(v)] ?? '';\n else if (type === 'str') value = v;\n else if (type === 'inlineStr') value = all(c, 't').map((t) => t.textContent ?? '').join('');\n else if (type === 'b') value = v === '1';\n else if (type === 'e') value = '';\n else if (type === 'd') value = parseDate(v) ?? v;\n else if (v !== '') { const n = Number(v); value = Number.isFinite(n) ? (dateStyle[Number(c.getAttribute('s'))] && n >= 1 && n < 2958466 ? fromSerial(n) : n) : v; }\n cells[col] = value;\n col++;\n }\n rows.push(Array.from(cells, (x) => x ?? ''));\n next = r + 1;\n }\n return { rows, sheet: first.getAttribute('name') ?? 'Sheet1' };\n}\n"],"mappings":"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"}