@bendyline/squisq-formats 2.5.0 → 2.6.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 (42) hide show
  1. package/NOTICE.md +10 -9
  2. package/dist/{chunk-2LT3JL7U.js → chunk-3ITGQRL5.js} +8 -8
  3. package/dist/{chunk-FMQWNPCV.js → chunk-AGGNLRHV.js} +6 -6
  4. package/dist/{chunk-AONELFLA.js → chunk-B7GEAZBI.js} +6 -1
  5. package/dist/chunk-CKSTGNVZ.js +724 -0
  6. package/dist/chunk-DXYWKZ52.js +57 -0
  7. package/dist/{chunk-T4PX33AG.js → chunk-EEDQRZ2M.js} +17 -1
  8. package/dist/chunk-FLR2ARKC.js +240 -0
  9. package/dist/{chunk-JTGWQK5V.js → chunk-GRKQTQOF.js} +64 -12
  10. package/dist/{chunk-A6LSCIO5.js → chunk-OBADJV7C.js} +286 -420
  11. package/dist/{chunk-AD2WT564.js → chunk-Q77KNJIN.js} +45 -0
  12. package/dist/{chunk-5PUIFU5I.js → chunk-VDTGQ4MW.js} +1 -1
  13. package/dist/{chunk-6RQOV3B3.js → chunk-VPWPEMZJ.js} +1 -1
  14. package/dist/{chunk-FIOSE4BO.js → chunk-XJNOZTAY.js} +6 -6
  15. package/dist/csv/index.d.ts +67 -1
  16. package/dist/csv/index.js +10 -3
  17. package/dist/data/index.d.ts +78 -0
  18. package/dist/data/index.js +30 -0
  19. package/dist/docx/index.js +3 -3
  20. package/dist/epub/index.js +4 -4
  21. package/dist/export-6iQXd-lQ.d.ts +366 -0
  22. package/dist/html/index.d.ts +2 -8
  23. package/dist/html/index.js +3 -3
  24. package/dist/{images-ESPQKVTW.js → images-JLBFCDD4.js} +1 -1
  25. package/dist/{import-B0gBYUmd.d.ts → import-C7c9tQHK.d.ts} +5 -2
  26. package/dist/index.d.ts +3 -3
  27. package/dist/index.js +33 -26
  28. package/dist/infer/index.js +6 -6
  29. package/dist/materialize-A34OZGEU.js +11 -0
  30. package/dist/outside-in/index.d.ts +3 -3
  31. package/dist/outside-in/index.js +2 -2
  32. package/dist/pdf/index.js +2 -2
  33. package/dist/pptx/index.js +3 -3
  34. package/dist/registry/index.d.ts +4 -4
  35. package/dist/registry/index.js +1 -1
  36. package/dist/{types-DByrrXeB.d.ts → types-Dzd_5H2A.d.ts} +5 -5
  37. package/dist/xlsx/index.d.ts +85 -4
  38. package/dist/xlsx/index.js +25 -4
  39. package/package.json +18 -3
  40. package/dist/export-m0tr9r9d.d.ts +0 -130
  41. package/dist/{chunk-KMBBO5H7.js → chunk-7DQP2I57.js} +4 -4
  42. package/dist/{chunk-M7XPXGXW.js → chunk-ROF7SSQP.js} +3 -3
@@ -1,8 +1,19 @@
1
+ import {
2
+ planDataSidecar,
3
+ sidecarReferenceDoc
4
+ } from "./chunk-DXYWKZ52.js";
5
+
1
6
  // src/csv/index.ts
2
7
  import { markdownToDoc } from "@bendyline/squisq/doc";
8
+ import { stringifyMarkdown } from "@bendyline/squisq/markdown";
9
+ import { MemoryContentContainer } from "@bendyline/squisq/storage";
3
10
  var DEFAULT_MAX_CSV_CELLS = 1e5;
4
11
  var DEFAULT_MAX_CSV_ROWS = 1e4;
5
12
  var DEFAULT_MAX_CSV_FIELD_CHARS = 1024 * 1024;
13
+ var SIDECAR_CSV_LIMITS = Object.freeze({
14
+ maxCells: 2e7,
15
+ maxRows: 2e6
16
+ });
6
17
  async function toText(data) {
7
18
  if (typeof data === "string") return data;
8
19
  if (typeof Blob !== "undefined" && data instanceof Blob) return data.text();
@@ -122,6 +133,37 @@ async function csvToMarkdownDoc(data, options = {}) {
122
133
  async function csvToDoc(data, options = {}) {
123
134
  return markdownToDoc(await csvToMarkdownDoc(data, options));
124
135
  }
136
+ async function csvToContainer(data, options = {}) {
137
+ const plan = planDataSidecar(options.sourceName, "data.csv");
138
+ const mode = options.sidecar ?? "auto";
139
+ const text = (await toText(data)).replace(/^\uFEFF/, "");
140
+ const maxInlineRows = options.maxInlineRows ?? 100;
141
+ const maxInlineBytes = options.maxInlineBytes ?? 256 * 1024;
142
+ const originalBytes = typeof data === "string" ? new TextEncoder().encode(data).buffer : data instanceof Blob ? await data.arrayBuffer() : data;
143
+ let spillNeeded = mode === "always";
144
+ if (!spillNeeded && mode === "auto") {
145
+ const hasHeader = options.hasHeader ?? true;
146
+ const lineCount = (text.match(/\n/g) ?? []).length + (text.endsWith("\n") || !text ? 0 : 1);
147
+ const dataRows = Math.max(lineCount - (hasHeader ? 1 : 0), 0);
148
+ spillNeeded = originalBytes.byteLength > maxInlineBytes || dataRows > maxInlineRows;
149
+ }
150
+ const markdownDoc = spillNeeded ? sidecarReferenceDoc(plan) : await csvToMarkdownDoc(text, options);
151
+ const container = new MemoryContentContainer();
152
+ await container.writeDocument(stringifyMarkdown(markdownDoc), plan.markdownFilename);
153
+ if (spillNeeded) {
154
+ await container.writeFile(plan.sidecarPath, originalBytes, "text/csv");
155
+ }
156
+ return container;
157
+ }
158
+ function serializeCsvRows(rows, options = {}) {
159
+ const delimiter = validateDelimiter(options.delimiter ?? ",");
160
+ const newline = options.newline ?? "\n";
161
+ const handling = options.formulaHandling ?? "preserve";
162
+ const body = rows.map(
163
+ (row) => row.map((cell) => escapeCsvField(neutralizeSpreadsheetFormula(cell, handling), delimiter)).join(delimiter)
164
+ ).join(newline);
165
+ return options.trailingNewline === false ? body : `${body}${newline}`;
166
+ }
125
167
  function escapeCsvField(value, delimiter) {
126
168
  if (value.includes('"') || value.includes(delimiter) || /[\r\n]/.test(value)) {
127
169
  return `"${value.replace(/"/g, '""')}"`;
@@ -166,8 +208,11 @@ function markdownDocToCsv(doc, options = {}) {
166
208
  }
167
209
 
168
210
  export {
211
+ SIDECAR_CSV_LIMITS,
169
212
  parseCsv,
170
213
  csvToMarkdownDoc,
171
214
  csvToDoc,
215
+ csvToContainer,
216
+ serializeCsvRows,
172
217
  markdownDocToCsv
173
218
  };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  convert,
3
3
  defaultRegistry
4
- } from "./chunk-JTGWQK5V.js";
4
+ } from "./chunk-GRKQTQOF.js";
5
5
  import {
6
6
  ConversionError
7
7
  } from "./chunk-KXOZMWBS.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  extToMime
3
- } from "./chunk-AONELFLA.js";
3
+ } from "./chunk-B7GEAZBI.js";
4
4
 
5
5
  // src/html/imageUtils.ts
6
6
  function inferMimeType(filename) {
@@ -5,6 +5,9 @@ import {
5
5
  normalizeOoxmlHex,
6
6
  sanitizeOfficeHyperlink
7
7
  } from "./chunk-A6N6IN3I.js";
8
+ import {
9
+ extToMime
10
+ } from "./chunk-B7GEAZBI.js";
8
11
  import {
9
12
  stripHtmlTags
10
13
  } from "./chunk-AVOZAKGP.js";
@@ -47,6 +50,9 @@ import {
47
50
  requireMainPartPath,
48
51
  resolveTarget
49
52
  } from "./chunk-S5PCVMKU.js";
53
+ import {
54
+ renumberFootnotes
55
+ } from "./chunk-BXWNU4T5.js";
50
56
  import {
51
57
  buildContainer
52
58
  } from "./chunk-IIQYS2YH.js";
@@ -56,12 +62,6 @@ import {
56
62
  fontAwesomeGlyph,
57
63
  obfuscateDocxFont
58
64
  } from "./chunk-USU6HTKB.js";
59
- import {
60
- extToMime
61
- } from "./chunk-AONELFLA.js";
62
- import {
63
- renumberFootnotes
64
- } from "./chunk-BXWNU4T5.js";
65
65
 
66
66
  // src/docx/export.ts
67
67
  import { resolveFontFamily } from "@bendyline/squisq/schemas";
@@ -1,5 +1,6 @@
1
1
  import { MarkdownDocument } from '@bendyline/squisq/markdown';
2
2
  import { Doc } from '@bendyline/squisq/schemas';
3
+ import { ContentContainer } from '@bendyline/squisq/storage';
3
4
 
4
5
  /**
5
6
  * @bendyline/squisq-formats CSV Module
@@ -28,6 +29,27 @@ interface CsvImportOptions {
28
29
  maxFieldChars?: number;
29
30
  /** Cancel during parsing checkpoints. */
30
31
  signal?: AbortSignal;
32
+ /**
33
+ * Sidecar spill mode — only honored by `csvToContainer`, which can actually
34
+ * write the sidecar file. `'auto'` (default) spills past the inline
35
+ * thresholds; `'always'` always sidecars (the CSV-open-as-document mode:
36
+ * opening a data file means the FILE is the content); `'never'` keeps the
37
+ * inline table (`csvToMarkdownDoc`'s only behavior).
38
+ */
39
+ sidecar?: 'auto' | 'always' | 'never';
40
+ /** Max data rows kept inline before spilling (container import). Default 100. */
41
+ maxInlineRows?: number;
42
+ /** Max source bytes kept inline before spilling (container import). Default 256 KiB. */
43
+ maxInlineBytes?: number;
44
+ }
45
+ /** Options for {@link csvToContainer}. */
46
+ interface CsvContainerOptions extends CsvImportOptions {
47
+ /**
48
+ * Source file name (e.g. `'Q3 Transactions.csv'`) — names the document
49
+ * (`q3-transactions.md`) and the sidecar path
50
+ * (`q3-transactions_files/data/Q3 Transactions.csv`). Default `'data.csv'`.
51
+ */
52
+ sourceName?: string;
31
53
  }
32
54
  interface CsvExportOptions {
33
55
  /** Field delimiter. Default `,`. */
@@ -56,12 +78,56 @@ interface CsvSafetyLimits {
56
78
  maxFieldChars?: number;
57
79
  signal?: AbortSignal;
58
80
  }
81
+ /**
82
+ * Generous caps for the DATA-SIDECAR tier — the grid ingest and the
83
+ * full-body sidecar readers. The conservative `parseCsv` defaults protect
84
+ * the INLINE pipeline (a 100k-cell markdown table can't reparse anyway),
85
+ * but sidecar data exists precisely because it is big: it renders windowed
86
+ * and virtualized, so the ceiling here is the columnar store's ~20M-cell
87
+ * design wall, not the editor debounce. Every sidecar-path caller passes
88
+ * these; without them a 20 MB upload silently dead-ends at the parser cap.
89
+ */
90
+ declare const SIDECAR_CSV_LIMITS: CsvSafetyLimits;
59
91
  /** Parse CSV text into a grid of string cells (RFC 4180: quotes, escaped quotes). */
60
92
  declare function parseCsv(text: string, delimiter?: string, limits?: CsvSafetyLimits): string[][];
61
93
  /** Convert CSV to a MarkdownDocument containing a single table. */
62
94
  declare function csvToMarkdownDoc(data: ArrayBuffer | Blob | string, options?: CsvImportOptions): Promise<MarkdownDocument>;
63
95
  /** Convert CSV to a squisq Doc. */
64
96
  declare function csvToDoc(data: ArrayBuffer | Blob | string, options?: CsvImportOptions): Promise<Doc>;
97
+ /**
98
+ * Import a CSV into a ContentContainer: the markdown document plus, when the
99
+ * data crosses the inline thresholds (or `sidecar: 'always'`), the ORIGINAL
100
+ * bytes as a `<docbasename>_files/data/<name>` sidecar referenced via
101
+ * `{[dataTable src=…]}` with a body link.
102
+ *
103
+ * Below the thresholds the markdown is byte-identical to `csvToMarkdownDoc`'s
104
+ * output and no sidecar is written.
105
+ */
106
+ declare function csvToContainer(data: ArrayBuffer | Blob | string, options?: CsvContainerOptions): Promise<ContentContainer>;
107
+ /** Options for {@link serializeCsvRows}. */
108
+ interface SerializeCsvRowsOptions {
109
+ /** Field delimiter. Default `,`. */
110
+ delimiter?: string;
111
+ /** Line terminator. Default `\n`. */
112
+ newline?: '\r\n' | '\n';
113
+ /** Emit a terminating newline after the last row. Default true. */
114
+ trailingNewline?: boolean;
115
+ /**
116
+ * Formula neutralization. Default **`'preserve'`** — the OPPOSITE of the
117
+ * export default, deliberately: this API re-serializes EXISTING data (the
118
+ * grid's save path), and `SPREADSHEET_FORMULA_PREFIX` matches a leading
119
+ * `-`/`+`, so blanket escaping would corrupt every negative number in a
120
+ * re-saved file. Callers neutralize specific cells themselves (the grid
121
+ * escapes only journal-edited, non-numeric cells).
122
+ */
123
+ formulaHandling?: 'escape' | 'preserve';
124
+ }
125
+ /**
126
+ * Serialize a plain row matrix to CSV text — the write half of `parseCsv`,
127
+ * used by the grid's sidecar save. RFC-4180 quoting via the same escaper
128
+ * the exporter uses.
129
+ */
130
+ declare function serializeCsvRows(rows: readonly (readonly string[])[], options?: SerializeCsvRowsOptions): string;
65
131
  /**
66
132
  * Serialize one table in a MarkdownDocument to CSV text.
67
133
  *
@@ -72,4 +138,4 @@ declare function csvToDoc(data: ArrayBuffer | Blob | string, options?: CsvImport
72
138
  */
73
139
  declare function markdownDocToCsv(doc: MarkdownDocument, options?: CsvExportOptions): string;
74
140
 
75
- export { type CsvExportOptions, type CsvImportOptions, type CsvSafetyLimits, csvToDoc, csvToMarkdownDoc, markdownDocToCsv, parseCsv };
141
+ export { type CsvContainerOptions, type CsvExportOptions, type CsvImportOptions, type CsvSafetyLimits, SIDECAR_CSV_LIMITS, type SerializeCsvRowsOptions, csvToContainer, csvToDoc, csvToMarkdownDoc, markdownDocToCsv, parseCsv, serializeCsvRows };
package/dist/csv/index.js CHANGED
@@ -1,12 +1,19 @@
1
1
  import {
2
+ SIDECAR_CSV_LIMITS,
3
+ csvToContainer,
2
4
  csvToDoc,
3
5
  csvToMarkdownDoc,
4
6
  markdownDocToCsv,
5
- parseCsv
6
- } from "../chunk-AD2WT564.js";
7
+ parseCsv,
8
+ serializeCsvRows
9
+ } from "../chunk-Q77KNJIN.js";
10
+ import "../chunk-DXYWKZ52.js";
7
11
  export {
12
+ SIDECAR_CSV_LIMITS,
13
+ csvToContainer,
8
14
  csvToDoc,
9
15
  csvToMarkdownDoc,
10
16
  markdownDocToCsv,
11
- parseCsv
17
+ parseCsv,
18
+ serializeCsvRows
12
19
  };
@@ -0,0 +1,78 @@
1
+ import { DataSourceReader } from '@bendyline/squisq/doc';
2
+ import { ContentContainer } from '@bendyline/squisq/storage';
3
+ import { MarkdownDocument } from '@bendyline/squisq/markdown';
4
+
5
+ /**
6
+ * Sidecar data readers — the format implementations behind core's
7
+ * `DataSourceReader` seam (`resolveDataReferences`).
8
+ *
9
+ * Core stays parser-free; these readers decode the actual bytes of a
10
+ * `{[dataTable src=…]}` sidecar into the bounded `DataSourceTable` window the
11
+ * projections render. CSV/TSV wrap the RFC-4180 parser, XLSX reuses the
12
+ * import pipeline's typed region detection (`xlsxToTables`), and parquet
13
+ * loads hyparquet lazily so its bytes never reach consumers that don't
14
+ * reference parquet files.
15
+ */
16
+
17
+ declare const csvDataReader: DataSourceReader;
18
+ declare const xlsxDataReader: DataSourceReader;
19
+ declare const parquetDataReader: DataSourceReader;
20
+ /** The full reader set for `resolveDataReferences({ readers })`. */
21
+ declare function defaultDataReaders(): DataSourceReader[];
22
+
23
+ /**
24
+ * Materialize `{[dataTable src=…]}` sidecar references into inline markdown
25
+ * tables — the FULL data, not the bounded preview. Used by exports that
26
+ * embed values (XLSX: a src-referenced block would otherwise contribute no
27
+ * table and silently vanish from the workbook).
28
+ *
29
+ * Never throws: a missing container, unreadable file, or absent reader
30
+ * degrades to an `onWarning` message and the reference block is left as-is
31
+ * (its body link simply doesn't survive a tables-only export).
32
+ */
33
+
34
+ /**
35
+ * Returns a copy of `markdownDoc` where every heading annotated with a
36
+ * resolvable data `src` is followed by the full source table. The input
37
+ * document is returned unchanged (same object) when nothing materialized.
38
+ */
39
+ declare function materializeDataReferences(markdownDoc: MarkdownDocument, container: ContentContainer | null | undefined, onWarning?: (message: string) => void): Promise<MarkdownDocument>;
40
+
41
+ /**
42
+ * Sidecar naming shared by the spill-capable importers (`xlsxToContainer`,
43
+ * `csvToContainer`): one place decides the document filename and the
44
+ * `<docbasename>_files/data/<file>` path a spilled reference points at, so
45
+ * the markdown `src` param and the container write can never disagree.
46
+ */
47
+
48
+ /** Strip any path components from a user-supplied source file name. */
49
+ declare function sanitizeSourceFileName(name: string | undefined, fallback: string): string;
50
+ /**
51
+ * Doc basename slug for a source file name — the outside-in `slugStem`
52
+ * rules (NFKD, strip marks, lowercase, non-alphanumeric → `-`), applied to
53
+ * the name without its extension. `'Q3 Report.xlsx'` → `'q3-report'`.
54
+ */
55
+ declare function docSlugForFileName(fileName: string): string;
56
+ /** Where a spill-capable import writes its document and sidecar. */
57
+ interface DataSidecarPlan {
58
+ /** Doc basename slug, e.g. `'q3-report'`. */
59
+ slug: string;
60
+ /** Document filename inside the container, e.g. `'q3-report.md'`. */
61
+ markdownFilename: string;
62
+ /** Sidecar file name (source name, path components stripped). */
63
+ fileName: string;
64
+ /** Container path the `src` param references, e.g. `'q3-report_files/data/Q3 Report.xlsx'`. */
65
+ sidecarPath: string;
66
+ }
67
+ declare function planDataSidecar(sourceName: string | undefined, fallbackName: string): DataSidecarPlan;
68
+ /**
69
+ * The reference block a fully-sidecarred data file becomes: an annotated
70
+ * heading (`# <title> {[dataTable src=…]}`) plus the graceful-degradation
71
+ * body link. Built as an AST so annotation quoting and link escaping go
72
+ * through the one stringifier that knows the rules.
73
+ */
74
+ declare function sidecarReferenceDoc(plan: DataSidecarPlan): MarkdownDocument;
75
+ /** {@link sidecarReferenceDoc} as serialized markdown source. */
76
+ declare function sidecarReferenceMarkdown(plan: DataSidecarPlan): string;
77
+
78
+ export { type DataSidecarPlan, csvDataReader, defaultDataReaders, docSlugForFileName, materializeDataReferences, parquetDataReader, planDataSidecar, sanitizeSourceFileName, sidecarReferenceDoc, sidecarReferenceMarkdown, xlsxDataReader };
@@ -0,0 +1,30 @@
1
+ import {
2
+ csvDataReader,
3
+ defaultDataReaders,
4
+ materializeDataReferences,
5
+ parquetDataReader,
6
+ xlsxDataReader
7
+ } from "../chunk-FLR2ARKC.js";
8
+ import "../chunk-OBADJV7C.js";
9
+ import "../chunk-Q77KNJIN.js";
10
+ import {
11
+ docSlugForFileName,
12
+ planDataSidecar,
13
+ sanitizeSourceFileName,
14
+ sidecarReferenceDoc,
15
+ sidecarReferenceMarkdown
16
+ } from "../chunk-DXYWKZ52.js";
17
+ import "../chunk-S5PCVMKU.js";
18
+ import "../chunk-7AWFHP5U.js";
19
+ export {
20
+ csvDataReader,
21
+ defaultDataReaders,
22
+ docSlugForFileName,
23
+ materializeDataReferences,
24
+ parquetDataReader,
25
+ planDataSidecar,
26
+ sanitizeSourceFileName,
27
+ sidecarReferenceDoc,
28
+ sidecarReferenceMarkdown,
29
+ xlsxDataReader
30
+ };
@@ -4,17 +4,17 @@ import {
4
4
  docxToDoc,
5
5
  docxToMarkdownDoc,
6
6
  markdownDocToDocx
7
- } from "../chunk-FIOSE4BO.js";
7
+ } from "../chunk-XJNOZTAY.js";
8
8
  import "../chunk-A6N6IN3I.js";
9
+ import "../chunk-B7GEAZBI.js";
9
10
  import "../chunk-AVOZAKGP.js";
10
11
  import "../chunk-ILCJ3WFD.js";
11
12
  import "../chunk-JU2RHXUB.js";
12
13
  import "../chunk-S5PCVMKU.js";
13
14
  import "../chunk-7AWFHP5U.js";
15
+ import "../chunk-BXWNU4T5.js";
14
16
  import "../chunk-IIQYS2YH.js";
15
17
  import "../chunk-USU6HTKB.js";
16
- import "../chunk-AONELFLA.js";
17
- import "../chunk-BXWNU4T5.js";
18
18
  export {
19
19
  docToDocx,
20
20
  docxToContainer,
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  docToEpub,
3
3
  markdownDocToEpub
4
- } from "../chunk-2LT3JL7U.js";
4
+ } from "../chunk-3ITGQRL5.js";
5
+ import "../chunk-VPWPEMZJ.js";
6
+ import "../chunk-B7GEAZBI.js";
5
7
  import "../chunk-AVOZAKGP.js";
6
8
  import "../chunk-JU2RHXUB.js";
7
- import "../chunk-USU6HTKB.js";
8
- import "../chunk-6RQOV3B3.js";
9
- import "../chunk-AONELFLA.js";
10
9
  import "../chunk-BXWNU4T5.js";
10
+ import "../chunk-USU6HTKB.js";
11
11
  export {
12
12
  docToEpub,
13
13
  markdownDocToEpub