@bendyline/squisq 2.10.0 → 2.11.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 (32) hide show
  1. package/dist/{Doc-DTyeaFuW.d.ts → Doc-CRPQCkHn.d.ts} +34 -2
  2. package/dist/{ImageEditDoc-dFEclQ9l.d.ts → ImageEditDoc-MbvJM1HE.d.ts} +1 -1
  3. package/dist/{chunk-IO5XO6XH.js → chunk-64I44JAP.js} +1 -1
  4. package/dist/{chunk-XSW4QTMB.js → chunk-EH4S7HXE.js} +193 -3
  5. package/dist/{chunk-7YEZFHLS.js → chunk-O7HLQ22N.js} +11 -0
  6. package/dist/{chunk-NBKAXPSX.js → chunk-TMOHAFYE.js} +1 -0
  7. package/dist/{chunk-MIKKUKOD.js → chunk-UBFT2CDQ.js} +30 -15
  8. package/dist/{chunk-FCG3BIZN.js → chunk-UNVHAK3A.js} +5 -1
  9. package/dist/{chunk-NFHMHYUV.js → chunk-ZWID3HM5.js} +1 -1
  10. package/dist/{chunk-DRFJU4MK.js → chunk-ZYCSRDSX.js} +352 -2
  11. package/dist/doc/index.d.ts +123 -6
  12. package/dist/doc/index.js +12 -4
  13. package/dist/fence/index.d.ts +1 -1
  14. package/dist/generate/index.d.ts +1 -1
  15. package/dist/imageEdit/index.d.ts +3 -3
  16. package/dist/index.d.ts +7 -6
  17. package/dist/index.js +20 -8
  18. package/dist/jsonForm/index.d.ts +1 -1
  19. package/dist/markdown/index.js +3 -3
  20. package/dist/{materializePageSection-BRNIINlU.d.ts → materializePageSection-BeUPHeCl.d.ts} +1 -1
  21. package/dist/narration/index.d.ts +1 -1
  22. package/dist/narration/index.js +3 -3
  23. package/dist/schemas/index.d.ts +4 -4
  24. package/dist/storage/index.js +1 -1
  25. package/dist/table/index.d.ts +123 -0
  26. package/dist/table/index.js +298 -0
  27. package/dist/{themeLibrary-xaxN5UYu.d.ts → themeLibrary-BG3jr6mT.d.ts} +1 -1
  28. package/dist/transform/index.d.ts +2 -2
  29. package/dist/versions/index.d.ts +15 -1
  30. package/dist/versions/index.js +5 -1
  31. package/dist/viewState-lTZS-hP_.d.ts +91 -0
  32. package/package.json +6 -1
@@ -0,0 +1,298 @@
1
+ // src/table/viewState.ts
2
+ var TEXT_FILTER_OPS = ["=", "!=", "~", "!~", "^~", "$~"];
3
+ var EMPTY_TABLE_VIEW_STATE = Object.freeze({
4
+ sort: [],
5
+ filter: []
6
+ });
7
+ function isEmptyViewState(view) {
8
+ return view.sort.length === 0 && view.filter.length === 0;
9
+ }
10
+ function isNumericCellText(value) {
11
+ const trimmed = value.trim();
12
+ if (trimmed === "") return false;
13
+ if (/^0\d/.test(trimmed)) return false;
14
+ return Number.isFinite(Number(trimmed));
15
+ }
16
+ function inferNumericColumn(rows, col) {
17
+ let sawValue = false;
18
+ for (const row of rows) {
19
+ const cell = row[col] ?? "";
20
+ if (cell.trim() === "") continue;
21
+ if (!isNumericCellText(cell)) return false;
22
+ sawValue = true;
23
+ }
24
+ return sawValue;
25
+ }
26
+ function makeTableCollator() {
27
+ return new Intl.Collator(void 0, { numeric: true });
28
+ }
29
+ var NEEDS_INNER_QUOTING_RE = /[,:;=!<>~"^$*]|^\s|\s$/;
30
+ function quoteViewToken(text) {
31
+ if (text === "" || NEEDS_INNER_QUOTING_RE.test(text)) {
32
+ return `"${text.replace(/"/g, '""')}"`;
33
+ }
34
+ return text;
35
+ }
36
+ function readQuoted(scanner) {
37
+ let out = "";
38
+ let i = scanner.pos + 1;
39
+ const { text } = scanner;
40
+ while (i < text.length) {
41
+ const ch = text[i];
42
+ if (ch === '"') {
43
+ if (text[i + 1] === '"') {
44
+ out += '"';
45
+ i += 2;
46
+ continue;
47
+ }
48
+ scanner.pos = i + 1;
49
+ return out;
50
+ }
51
+ out += ch;
52
+ i++;
53
+ }
54
+ return null;
55
+ }
56
+ function readBare(scanner, stops) {
57
+ const { text } = scanner;
58
+ let i = scanner.pos;
59
+ while (i < text.length && !stops.includes(text[i])) i++;
60
+ const out = text.slice(scanner.pos, i);
61
+ scanner.pos = i;
62
+ return out.trim();
63
+ }
64
+ function skipSpaces(scanner) {
65
+ while (scanner.text[scanner.pos] === " ") scanner.pos++;
66
+ }
67
+ var FILTER_OP_TOKENS = [
68
+ { token: ">=", op: ">=", caseSensitive: false },
69
+ { token: "<=", op: "<=", caseSensitive: false },
70
+ { token: "!~*", op: "!~", caseSensitive: true },
71
+ { token: "!~", op: "!~", caseSensitive: false },
72
+ { token: "!=*", op: "!=", caseSensitive: true },
73
+ { token: "!=", op: "!=", caseSensitive: false },
74
+ { token: "^~*", op: "^~", caseSensitive: true },
75
+ { token: "^~", op: "^~", caseSensitive: false },
76
+ { token: "$~*", op: "$~", caseSensitive: true },
77
+ { token: "$~", op: "$~", caseSensitive: false },
78
+ { token: "~*", op: "~", caseSensitive: true },
79
+ { token: "~", op: "~", caseSensitive: false },
80
+ { token: "=*", op: "=", caseSensitive: true },
81
+ { token: "=", op: "=", caseSensitive: false },
82
+ { token: ">", op: ">", caseSensitive: false },
83
+ { token: "<", op: "<", caseSensitive: false }
84
+ ];
85
+ function parseSortParam(raw) {
86
+ const scanner = { text: raw, pos: 0 };
87
+ const terms = [];
88
+ for (; ; ) {
89
+ skipSpaces(scanner);
90
+ const column = scanner.text[scanner.pos] === '"' ? readQuoted(scanner) : readBare(scanner, ":,");
91
+ if (column === null || column === "") return null;
92
+ let dir = "asc";
93
+ skipSpaces(scanner);
94
+ if (scanner.text[scanner.pos] === ":") {
95
+ scanner.pos++;
96
+ skipSpaces(scanner);
97
+ const dirToken = readBare(scanner, ",").toLowerCase();
98
+ if (dirToken !== "asc" && dirToken !== "desc") return null;
99
+ dir = dirToken;
100
+ }
101
+ terms.push({ column, dir });
102
+ skipSpaces(scanner);
103
+ if (scanner.pos >= scanner.text.length) return terms;
104
+ if (scanner.text[scanner.pos] !== ",") return null;
105
+ scanner.pos++;
106
+ }
107
+ }
108
+ function parseFilterParam(raw) {
109
+ const scanner = { text: raw, pos: 0 };
110
+ const clauses = [];
111
+ for (; ; ) {
112
+ skipSpaces(scanner);
113
+ const column = scanner.text[scanner.pos] === '"' ? readQuoted(scanner) : readBare(scanner, "=!<>~^$;");
114
+ if (column === null || column === "") return null;
115
+ skipSpaces(scanner);
116
+ const rest = scanner.text.slice(scanner.pos);
117
+ const match = FILTER_OP_TOKENS.find((candidate) => rest.startsWith(candidate.token));
118
+ if (!match) return null;
119
+ scanner.pos += match.token.length;
120
+ skipSpaces(scanner);
121
+ const value = scanner.text[scanner.pos] === '"' ? readQuoted(scanner) : readBare(scanner, ";");
122
+ if (value === null) return null;
123
+ const clause = { column, op: match.op, value };
124
+ if (match.caseSensitive) clause.caseSensitive = true;
125
+ clauses.push(clause);
126
+ skipSpaces(scanner);
127
+ if (scanner.pos >= scanner.text.length) return clauses;
128
+ if (scanner.text[scanner.pos] !== ";") return null;
129
+ scanner.pos++;
130
+ }
131
+ }
132
+ function parseTableViewState(sortRaw, filterRaw, headers) {
133
+ const issues = [];
134
+ const known = new Set(headers);
135
+ let sort = [];
136
+ if (sortRaw !== void 0 && sortRaw.trim() !== "") {
137
+ const parsed = parseSortParam(sortRaw);
138
+ if (parsed === null) {
139
+ issues.push({ code: "data-view-invalid", message: `sort "${sortRaw}" could not be parsed` });
140
+ } else {
141
+ sort = parsed.filter((term) => {
142
+ if (known.has(term.column)) return true;
143
+ issues.push({
144
+ code: "data-view-unknown-column",
145
+ message: `sort column "${term.column}" is not a header`
146
+ });
147
+ return false;
148
+ });
149
+ }
150
+ }
151
+ let filter = [];
152
+ if (filterRaw !== void 0 && filterRaw.trim() !== "") {
153
+ const parsed = parseFilterParam(filterRaw);
154
+ if (parsed === null) {
155
+ issues.push({
156
+ code: "data-view-invalid",
157
+ message: `filter "${filterRaw}" could not be parsed`
158
+ });
159
+ } else {
160
+ filter = parsed.filter((clause) => {
161
+ if (known.has(clause.column)) return true;
162
+ issues.push({
163
+ code: "data-view-unknown-column",
164
+ message: `filter column "${clause.column}" is not a header`
165
+ });
166
+ return false;
167
+ });
168
+ }
169
+ }
170
+ return { view: { sort, filter }, issues };
171
+ }
172
+ function serializeTableViewState(view) {
173
+ const out = {};
174
+ if (view.sort.length > 0) {
175
+ out.sort = view.sort.map((term) => `${quoteViewToken(term.column)}${term.dir === "desc" ? ":desc" : ""}`).join(",");
176
+ }
177
+ if (view.filter.length > 0) {
178
+ out.filter = view.filter.map((clause) => {
179
+ const star = clause.caseSensitive === true && TEXT_FILTER_OPS.includes(clause.op) ? "*" : "";
180
+ return `${quoteViewToken(clause.column)}${clause.op}${star}${quoteViewToken(clause.value)}`;
181
+ }).join(";");
182
+ }
183
+ return out;
184
+ }
185
+
186
+ // src/table/applyTableViewState.ts
187
+ function matchesClause(cell, clause, numericColumn, collator) {
188
+ const cellTrim = cell.trim();
189
+ const valueTrim = clause.value.trim();
190
+ const blank = cellTrim === "";
191
+ const fold = (text) => clause.caseSensitive ? text : text.toLowerCase();
192
+ switch (clause.op) {
193
+ case "=":
194
+ if (valueTrim === "") return blank;
195
+ if (blank) return false;
196
+ if (numericColumn && isNumericCellText(valueTrim)) {
197
+ return Number(cellTrim) === Number(valueTrim);
198
+ }
199
+ return fold(cellTrim) === fold(valueTrim);
200
+ case "!=":
201
+ return !matchesClause(cell, { ...clause, op: "=" }, numericColumn, collator);
202
+ case "~":
203
+ return !blank && fold(cellTrim).includes(fold(valueTrim));
204
+ case "!~":
205
+ return !matchesClause(cell, { ...clause, op: "~" }, numericColumn, collator);
206
+ case "^~":
207
+ return !blank && fold(cellTrim).startsWith(fold(valueTrim));
208
+ case "$~":
209
+ return !blank && fold(cellTrim).endsWith(fold(valueTrim));
210
+ case ">":
211
+ case "<":
212
+ case ">=":
213
+ case "<=": {
214
+ if (blank) return false;
215
+ let comparison;
216
+ if (numericColumn && isNumericCellText(valueTrim)) {
217
+ comparison = Number(cellTrim) - Number(valueTrim);
218
+ } else {
219
+ comparison = collator.compare(cellTrim, valueTrim);
220
+ }
221
+ if (clause.op === ">") return comparison > 0;
222
+ if (clause.op === "<") return comparison < 0;
223
+ if (clause.op === ">=") return comparison >= 0;
224
+ return comparison <= 0;
225
+ }
226
+ }
227
+ }
228
+ function applyTableViewState(headers, rows, view) {
229
+ const asMutable = rows;
230
+ if (isEmptyViewState(view)) {
231
+ return {
232
+ rows: [...asMutable],
233
+ rowIds: rows.map((_, index) => index),
234
+ unfilteredRowCount: rows.length
235
+ };
236
+ }
237
+ const collator = makeTableCollator();
238
+ const columnIndex = new Map(headers.map((header, index) => [header, index]));
239
+ const numericByCol = /* @__PURE__ */ new Map();
240
+ const numericFor = (col) => {
241
+ let cached = numericByCol.get(col);
242
+ if (cached === void 0) {
243
+ cached = inferNumericColumn(rows, col);
244
+ numericByCol.set(col, cached);
245
+ }
246
+ return cached;
247
+ };
248
+ const clauses = view.filter.map((clause) => ({ clause, col: columnIndex.get(clause.column) })).filter((entry) => entry.col !== void 0);
249
+ let rowIds = [];
250
+ for (let index = 0; index < rows.length; index++) {
251
+ const row = rows[index];
252
+ let pass = true;
253
+ for (const { clause, col } of clauses) {
254
+ if (!matchesClause(row[col] ?? "", clause, numericFor(col), collator)) {
255
+ pass = false;
256
+ break;
257
+ }
258
+ }
259
+ if (pass) rowIds.push(index);
260
+ }
261
+ const terms = view.sort.map((term) => ({ term, col: columnIndex.get(term.column) })).filter(
262
+ (entry) => entry.col !== void 0
263
+ );
264
+ if (terms.length > 0) {
265
+ for (const { col } of terms) numericFor(col);
266
+ rowIds = [...rowIds].sort((a, b) => {
267
+ for (const { term, col } of terms) {
268
+ const left = (rows[a][col] ?? "").trim();
269
+ const right = (rows[b][col] ?? "").trim();
270
+ const leftBlank = left === "";
271
+ const rightBlank = right === "";
272
+ if (leftBlank || rightBlank) {
273
+ if (leftBlank && rightBlank) continue;
274
+ return leftBlank ? 1 : -1;
275
+ }
276
+ const comparison = numericByCol.get(col) ? Number(left) - Number(right) : collator.compare(left, right);
277
+ if (comparison !== 0) return term.dir === "desc" ? -comparison : comparison;
278
+ }
279
+ return a - b;
280
+ });
281
+ }
282
+ return {
283
+ rows: rowIds.map((id) => asMutable[id]),
284
+ rowIds,
285
+ unfilteredRowCount: rows.length
286
+ };
287
+ }
288
+ export {
289
+ EMPTY_TABLE_VIEW_STATE,
290
+ applyTableViewState,
291
+ inferNumericColumn,
292
+ isEmptyViewState,
293
+ isNumericCellText,
294
+ makeTableCollator,
295
+ parseTableViewState,
296
+ quoteViewToken,
297
+ serializeTableViewState
298
+ };
@@ -1,4 +1,4 @@
1
- import { bh as Theme, bl as ThemeRegistry } from './Doc-DTyeaFuW.js';
1
+ import { bh as Theme, bl as ThemeRegistry } from './Doc-CRPQCkHn.js';
2
2
 
3
3
  /**
4
4
  * Built-in Theme Library
@@ -1,5 +1,5 @@
1
- import { r as ColorScheme, O as Doc, k as Block } from '../Doc-DTyeaFuW.js';
2
- import { i as PageTransformHints } from '../materializePageSection-BRNIINlU.js';
1
+ import { r as ColorScheme, O as Doc, k as Block } from '../Doc-CRPQCkHn.js';
2
+ import { i as PageTransformHints } from '../materializePageSection-BeUPHeCl.js';
3
3
  import { d as ExtractionType, E as ExtractedElement, b as ExtractionOptions } from '../contentExtractor-BNfVJV2U.js';
4
4
  import '../types-Be6sBUBx.js';
5
5
 
@@ -128,5 +128,19 @@ declare function parseVersionPath(path: string): {
128
128
  timestamp: Date;
129
129
  collision: number;
130
130
  } | null;
131
+ /** Subfolder holding pre-save backups of DATA sidecar files. */
132
+ declare const DATA_BACKUP_PREFIX = ".versions/data/";
133
+ /**
134
+ * Build a pre-save backup path for a data sidecar file:
135
+ * `.versions/data/<path with '/' → '__'>.<stamp>[-n].<ext>`.
136
+ *
137
+ * The grid's save flow writes the ORIGINAL bytes here before overwriting a
138
+ * sidecar in place — the only cross-save undo the grid offers. Unlike
139
+ * `buildVersionPath` (markdown-only, single-basename), the flattened full
140
+ * path keeps same-named files in different folders distinct, and the
141
+ * extension follows the sidecar. The flattened name goes through the same
142
+ * safety rules as document snapshots (via a per-call strategy).
143
+ */
144
+ declare function buildDataBackupPath(sidecarPath: string, date: Date, collision?: number): string;
131
145
 
132
- export { CoalesceOptions, DocumentVersionManager, type DocumentVersionManagerOptions, PrunePolicy, RevertOptions, RevertResult, SaveVersionOptions, SaveVersionResult, VERSIONS_PREFIX, VERSION_TIMESTAMP_PATTERN, Version, buildVersionPath, coalesceVersions, formatVersionTimestamp, getDocBasename, listVersions, parseVersionPath, parseVersionTimestamp, pruneVersions, readVersion, revertToVersion, saveVersion };
146
+ export { CoalesceOptions, DATA_BACKUP_PREFIX, DocumentVersionManager, type DocumentVersionManagerOptions, PrunePolicy, RevertOptions, RevertResult, SaveVersionOptions, SaveVersionResult, VERSIONS_PREFIX, VERSION_TIMESTAMP_PATTERN, Version, buildDataBackupPath, buildVersionPath, coalesceVersions, formatVersionTimestamp, getDocBasename, listVersions, parseVersionPath, parseVersionTimestamp, pruneVersions, readVersion, revertToVersion, saveVersion };
@@ -1,6 +1,8 @@
1
1
  import {
2
+ DATA_BACKUP_PREFIX,
2
3
  DocumentVersionManager,
3
4
  VERSIONS_PREFIX,
5
+ buildDataBackupPath,
4
6
  buildVersionPath,
5
7
  coalesceVersions,
6
8
  getDocBasename,
@@ -10,16 +12,18 @@ import {
10
12
  readVersion,
11
13
  revertToVersion,
12
14
  saveVersion
13
- } from "../chunk-7YEZFHLS.js";
15
+ } from "../chunk-O7HLQ22N.js";
14
16
  import {
15
17
  VERSION_TIMESTAMP_PATTERN,
16
18
  formatVersionTimestamp,
17
19
  parseVersionTimestamp
18
20
  } from "../chunk-OPO5K4DZ.js";
19
21
  export {
22
+ DATA_BACKUP_PREFIX,
20
23
  DocumentVersionManager,
21
24
  VERSIONS_PREFIX,
22
25
  VERSION_TIMESTAMP_PATTERN,
26
+ buildDataBackupPath,
23
27
  buildVersionPath,
24
28
  coalesceVersions,
25
29
  formatVersionTimestamp,
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Table view state — the non-destructive sort/filter vocabulary that rides a
3
+ * `{[dataTable src=… sort=… filter=…]}` annotation. The data bytes are never
4
+ * touched; view state is part of the DOCUMENT (an author's sort shapes the
5
+ * bounded previews and exports), exactly like `sheet`/`anchor` are part of
6
+ * the reference.
7
+ *
8
+ * Grammar (inside the param value; the whole value then rides the ordinary
9
+ * `{[…]}` attr quoting):
10
+ *
11
+ * sort := term (',' term)*
12
+ * term := colName (':' ('asc'|'desc'))? // default asc
13
+ * filter := clause (';' clause)* // conjunction (AND) only
14
+ * clause := colName op value
15
+ * op := textOp '*'? | cmpOp
16
+ * textOp := '=' | '!=' | '~' | '!~' | '^~' | '$~'
17
+ * cmpOp := '>' | '<' | '>=' | '<='
18
+ *
19
+ * Text-matching ops (`= != ~ !~ ^~ $~`) are CASE-INSENSITIVE by default
20
+ * (Excel AutoFilter semantics); a `*` suffix makes the match case-sensitive
21
+ * (`Region=*West`). `~` is contains, `^~` starts-with, `$~` ends-with (the
22
+ * `~` marks the text family; `^`/`$` are the regex-anchor mnemonics).
23
+ * Comparison ops compare numerically on numeric columns and via the shared
24
+ * collator otherwise, and take no `*`. Column names address headers by exact
25
+ * text. Names/values containing structural characters are quoted CSV-style —
26
+ * double quotes with `""` doubling, NO backslashes (the outer `{[…]}` layer
27
+ * already owns backslash escaping inside quoted attr values; stacking a
28
+ * second backslash grammar inside would be unreadable and fragile):
29
+ *
30
+ * sort=Revenue:desc,Region
31
+ * sort="Ratio A:B":desc
32
+ * filter=Region=West;Revenue>=1000
33
+ * filter=Note~"a;b"
34
+ *
35
+ * Parsing NEVER throws: an unknown column drops that term/clause with a
36
+ * `data-view-unknown-column` issue; malformed syntax drops the whole param
37
+ * with `data-view-invalid`. Renderers fall back to natural order.
38
+ */
39
+ interface SortTerm {
40
+ column: string;
41
+ dir: 'asc' | 'desc';
42
+ }
43
+ type FilterOp = '=' | '!=' | '>' | '<' | '>=' | '<=' | '~' | '!~' | '^~' | '$~';
44
+ interface FilterClause {
45
+ column: string;
46
+ op: FilterOp;
47
+ value: string;
48
+ /**
49
+ * Case-sensitive matching for text ops (serialized as a `*` op suffix).
50
+ * Absent/false = the default case-insensitive match. Meaningless on the
51
+ * comparison ops and never serialized for them.
52
+ */
53
+ caseSensitive?: boolean;
54
+ }
55
+ interface TableViewState {
56
+ sort: SortTerm[];
57
+ filter: FilterClause[];
58
+ }
59
+ interface ViewIssue {
60
+ code: 'data-view-unknown-column' | 'data-view-invalid';
61
+ message: string;
62
+ }
63
+ interface ParsedTableViewState {
64
+ view: TableViewState;
65
+ issues: ViewIssue[];
66
+ }
67
+ declare const EMPTY_TABLE_VIEW_STATE: TableViewState;
68
+ /** True when the view state changes nothing. */
69
+ declare function isEmptyViewState(view: TableViewState): boolean;
70
+ /**
71
+ * A column is numeric iff every non-blank trimmed cell parses to a finite
72
+ * number AND is not a leading-zero string (`"007"` stays text — zip codes,
73
+ * ids). Blank cells don't vote.
74
+ */
75
+ declare function isNumericCellText(value: string): boolean;
76
+ declare function inferNumericColumn(rows: readonly (readonly string[])[], col: number): boolean;
77
+ /** The one collator both sides of the parity contract use. */
78
+ declare function makeTableCollator(): Intl.Collator;
79
+ declare function quoteViewToken(text: string): string;
80
+ /**
81
+ * Parse the raw `sort`/`filter` param values against real headers.
82
+ * Never throws; degradation is per the module contract.
83
+ */
84
+ declare function parseTableViewState(sortRaw: string | undefined, filterRaw: string | undefined, headers: readonly string[]): ParsedTableViewState;
85
+ /** Serialize to `{ sort?, filter? }` raw param values (undefined = omit). */
86
+ declare function serializeTableViewState(view: TableViewState): {
87
+ sort?: string;
88
+ filter?: string;
89
+ };
90
+
91
+ export { EMPTY_TABLE_VIEW_STATE as E, type FilterClause as F, type ParsedTableViewState as P, type SortTerm as S, type TableViewState as T, type ViewIssue as V, type FilterOp as a, isEmptyViewState as b, isNumericCellText as c, inferNumericColumn as i, makeTableCollator as m, parseTableViewState as p, quoteViewToken as q, serializeTableViewState as s };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bendyline/squisq",
3
- "version": "2.10.0",
3
+ "version": "2.11.0",
4
4
  "description": "Headless utilities for doc/block rendering, spatial math, Markdown, and storage",
5
5
  "license": "MIT",
6
6
  "author": "Bendyline",
@@ -131,6 +131,11 @@
131
131
  "types": "./dist/proof/index.d.ts",
132
132
  "import": "./dist/proof/index.js",
133
133
  "default": "./dist/proof/index.js"
134
+ },
135
+ "./table": {
136
+ "types": "./dist/table/index.d.ts",
137
+ "import": "./dist/table/index.js",
138
+ "default": "./dist/table/index.js"
134
139
  }
135
140
  },
136
141
  "scripts": {