@bendyline/squisq-formats 1.4.2 → 2.0.1
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/README.md +48 -2
- package/dist/chunk-2KPARF2P.js +99 -0
- package/dist/chunk-2KPARF2P.js.map +1 -0
- package/dist/{chunk-5LSSWZPU.js → chunk-4VUWTSGM.js} +72 -25
- package/dist/chunk-4VUWTSGM.js.map +1 -0
- package/dist/{chunk-YESS7VY3.js → chunk-ABVI556T.js} +154 -39
- package/dist/chunk-ABVI556T.js.map +1 -0
- package/dist/{chunk-WWBIKRNP.js → chunk-CRAVSMPZ.js} +13 -11
- package/dist/chunk-CRAVSMPZ.js.map +1 -0
- package/dist/chunk-FE6OJV6O.js +560 -0
- package/dist/chunk-FE6OJV6O.js.map +1 -0
- package/dist/{chunk-D7IFPWNZ.js → chunk-GVS2XXV6.js} +27 -26
- package/dist/chunk-GVS2XXV6.js.map +1 -0
- package/dist/{chunk-RTS5XBZ7.js → chunk-HTW2M27H.js} +341 -100
- package/dist/chunk-HTW2M27H.js.map +1 -0
- package/dist/{chunk-46FMDOWZ.js → chunk-LXYLOOST.js} +49 -17
- package/dist/chunk-LXYLOOST.js.map +1 -0
- package/dist/{chunk-MJGRI6XR.js → chunk-MLX2BOJC.js} +12 -7
- package/dist/chunk-MLX2BOJC.js.map +1 -0
- package/dist/chunk-NKAJPJ4G.js +106 -0
- package/dist/chunk-NKAJPJ4G.js.map +1 -0
- package/dist/{chunk-DQAZR57U.js → chunk-O3GVVND4.js} +1 -1
- package/dist/chunk-ODL3SSPT.js +18 -0
- package/dist/chunk-ODL3SSPT.js.map +1 -0
- package/dist/chunk-QRVN6A6E.js +127 -0
- package/dist/chunk-QRVN6A6E.js.map +1 -0
- package/dist/chunk-U32AG3G3.js +195 -0
- package/dist/chunk-U32AG3G3.js.map +1 -0
- package/dist/{chunk-EHLGMSTE.js → chunk-VJJM2SSH.js} +10 -8
- package/dist/chunk-VJJM2SSH.js.map +1 -0
- package/dist/chunk-VSYHZECT.js +778 -0
- package/dist/chunk-VSYHZECT.js.map +1 -0
- package/dist/{chunk-SHLPSADL.js → chunk-WC7WULGV.js} +81 -189
- package/dist/chunk-WC7WULGV.js.map +1 -0
- package/dist/chunk-XKUMNGBW.js +131 -0
- package/dist/chunk-XKUMNGBW.js.map +1 -0
- package/dist/chunk-YRT7GQ5Y.js +28 -0
- package/dist/chunk-YRT7GQ5Y.js.map +1 -0
- package/dist/container/index.d.ts +13 -3
- package/dist/container/index.js +23 -20
- package/dist/container/index.js.map +1 -1
- package/dist/docx/index.d.ts +6 -2
- package/dist/docx/index.js +5 -3
- package/dist/epub/index.d.ts +3 -1
- package/dist/epub/index.js +3 -3
- package/dist/export-D2NkylDT.d.ts +69 -0
- package/dist/extract-H6RXJMHP.js +15 -0
- package/dist/extract-H6RXJMHP.js.map +1 -0
- package/dist/html/index.d.ts +15 -85
- package/dist/html/index.js +3 -3
- package/dist/images-7FBWPKE3.js +7 -0
- package/dist/images-7FBWPKE3.js.map +1 -0
- package/dist/import-DTkDxHmZ.d.ts +84 -0
- package/dist/import-K8mfc0fz.d.ts +136 -0
- package/dist/index.d.ts +14 -4
- package/dist/index.js +33 -12
- package/dist/infer/index.d.ts +138 -0
- package/dist/infer/index.js +28 -0
- package/dist/infer/index.js.map +1 -0
- package/dist/layouts-BHrgZ5FS.d.ts +150 -0
- package/dist/layouts-QVPK3ZCU.js +12 -0
- package/dist/layouts-QVPK3ZCU.js.map +1 -0
- package/dist/mapTheme-IR27S6IV.js +11 -0
- package/dist/mapTheme-IR27S6IV.js.map +1 -0
- package/dist/ooxml/index.d.ts +21 -127
- package/dist/ooxml/index.js +31 -9
- package/dist/pdf/index.d.ts +3 -1
- package/dist/pdf/index.js +1 -1
- package/dist/pptx/index.d.ts +8 -108
- package/dist/pptx/index.js +13 -4
- package/dist/reader-B9L8Ucbj.d.ts +140 -0
- package/dist/registry/index.d.ts +60 -8
- package/dist/registry/index.js +9 -4
- package/dist/themeReader-DJKErl_j.d.ts +56 -0
- package/dist/xlsx/index.d.ts +6 -66
- package/dist/xlsx/index.js +4 -2
- package/dist/zipLimits-BOKCB7qk.d.ts +31 -0
- package/package.json +8 -2
- package/src/__tests__/container.test.ts +41 -0
- package/src/__tests__/convert.test.ts +310 -1
- package/src/__tests__/epub.test.ts +102 -1
- package/src/__tests__/html.test.ts +62 -0
- package/src/__tests__/inferTheme.test.ts +135 -0
- package/src/__tests__/lossyWarnings.test.ts +41 -0
- package/src/__tests__/ooxml.test.ts +76 -2
- package/src/__tests__/ooxmlCancellation.test.ts +113 -0
- package/src/__tests__/ooxmlThemeReader.test.ts +92 -0
- package/src/__tests__/plainHtml.test.ts +15 -1
- package/src/__tests__/plainHtmlBundle.test.ts +18 -0
- package/src/__tests__/pptxImport.test.ts +30 -0
- package/src/__tests__/pptxInferFixtures.ts +314 -0
- package/src/__tests__/pptxLayoutInfer.test.ts +395 -0
- package/src/__tests__/zipSafety.test.ts +317 -0
- package/src/container/index.ts +37 -32
- package/src/docx/export.ts +4 -2
- package/src/docx/import.ts +4 -3
- package/src/epub/export.ts +94 -25
- package/src/html/docsHtmlBundle.ts +6 -2
- package/src/html/htmlTemplate.ts +31 -6
- package/src/html/imageUtils.ts +14 -5
- package/src/html/index.ts +12 -1
- package/src/html/plainHtml.ts +7 -3
- package/src/html/plainHtmlBundle.ts +11 -9
- package/src/index.ts +23 -0
- package/src/infer/extract.ts +127 -0
- package/src/infer/index.ts +199 -0
- package/src/infer/mapTheme.ts +176 -0
- package/src/infer/types.ts +27 -0
- package/src/ooxml/index.ts +14 -0
- package/src/ooxml/readUtils.ts +44 -0
- package/src/ooxml/reader.ts +129 -29
- package/src/ooxml/themeReader.ts +197 -0
- package/src/ooxml/types.ts +8 -9
- package/src/ooxml/writer.ts +28 -10
- package/src/pdf/export.ts +4 -2
- package/src/pdf/import.ts +40 -34
- package/src/pptx/export.ts +4 -2
- package/src/pptx/import.ts +214 -32
- package/src/pptx/index.ts +14 -0
- package/src/pptx/layouts.ts +1222 -0
- package/src/registry/convert.ts +168 -53
- package/src/registry/defaultFormats.ts +135 -45
- package/src/registry/index.ts +6 -1
- package/src/registry/types.ts +69 -6
- package/src/shared/boundedZipArchive.ts +383 -0
- package/src/shared/fidelity.ts +130 -0
- package/src/shared/zipEntryCount.ts +151 -0
- package/src/shared/zipLimits.ts +296 -0
- package/src/shared/zipSafety.ts +19 -0
- package/src/xlsx/import.ts +3 -2
- package/dist/chunk-46FMDOWZ.js.map +0 -1
- package/dist/chunk-5LSSWZPU.js.map +0 -1
- package/dist/chunk-D7IFPWNZ.js.map +0 -1
- package/dist/chunk-EHLGMSTE.js.map +0 -1
- package/dist/chunk-MJGRI6XR.js.map +0 -1
- package/dist/chunk-RTS5XBZ7.js.map +0 -1
- package/dist/chunk-SHLPSADL.js.map +0 -1
- package/dist/chunk-WWBIKRNP.js.map +0 -1
- package/dist/chunk-YESS7VY3.js.map +0 -1
- /package/dist/{chunk-DQAZR57U.js.map → chunk-O3GVVND4.js.map} +0 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { c as ZipSafetyLimits } from './zipLimits-BOKCB7qk.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* OOXML Types
|
|
5
|
+
*
|
|
6
|
+
* Shared type definitions for all Office Open XML formats (DOCX, PPTX, XLSX).
|
|
7
|
+
* These model the common structural elements of the OOXML package format:
|
|
8
|
+
* relationships, content types, and core properties.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* An opened OOXML package. Instances are created only by `openPackage`; the
|
|
12
|
+
* archive remains private so every part read goes through the bounded reader.
|
|
13
|
+
*/
|
|
14
|
+
declare const ooxmlPackageBrand: unique symbol;
|
|
15
|
+
interface OoxmlPackage {
|
|
16
|
+
/** Nominal brand: callers cannot manually construct a safety-bypassing package. */
|
|
17
|
+
readonly [ooxmlPackageBrand]: never;
|
|
18
|
+
/** Parsed [Content_Types].xml entries */
|
|
19
|
+
readonly contentTypes: ContentTypeMap;
|
|
20
|
+
/** Root-level relationships (_rels/.rels) */
|
|
21
|
+
readonly rootRelationships: readonly Relationship[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Content type map built from [Content_Types].xml.
|
|
25
|
+
* Maps part paths → content type strings plus extension defaults.
|
|
26
|
+
*/
|
|
27
|
+
interface ContentTypeMap {
|
|
28
|
+
/** Explicit overrides: partName → contentType */
|
|
29
|
+
overrides: Map<string, string>;
|
|
30
|
+
/** Default extensions: extension → contentType */
|
|
31
|
+
defaults: Map<string, string>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* An OOXML relationship entry (from any _rels/*.rels file).
|
|
35
|
+
*/
|
|
36
|
+
interface Relationship {
|
|
37
|
+
/** Relationship ID (e.g., "rId1") */
|
|
38
|
+
id: string;
|
|
39
|
+
/** Relationship type URI (e.g., "http://...officedocument/...") */
|
|
40
|
+
type: string;
|
|
41
|
+
/** Target path or URL */
|
|
42
|
+
target: string;
|
|
43
|
+
/** "Internal" (default) or "External" for hyperlinks */
|
|
44
|
+
targetMode?: 'Internal' | 'External';
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Document core properties from docProps/core.xml (Dublin Core metadata).
|
|
48
|
+
*/
|
|
49
|
+
interface CoreProperties {
|
|
50
|
+
title?: string;
|
|
51
|
+
subject?: string;
|
|
52
|
+
creator?: string;
|
|
53
|
+
keywords?: string;
|
|
54
|
+
description?: string;
|
|
55
|
+
lastModifiedBy?: string;
|
|
56
|
+
revision?: string;
|
|
57
|
+
created?: string;
|
|
58
|
+
modified?: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* A part (file) that will be written into an OOXML package.
|
|
62
|
+
*/
|
|
63
|
+
interface PackagePart {
|
|
64
|
+
/** Path within the ZIP (e.g., "word/document.xml") */
|
|
65
|
+
path: string;
|
|
66
|
+
/** XML or text content (mutually exclusive with binaryContent) */
|
|
67
|
+
content?: string;
|
|
68
|
+
/** Binary content (mutually exclusive with content) */
|
|
69
|
+
binaryContent?: ArrayBuffer | Uint8Array;
|
|
70
|
+
/** MIME content type for [Content_Types].xml */
|
|
71
|
+
contentType: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* A relationship to be written into a _rels/*.rels file.
|
|
75
|
+
* `sourcePart` identifies which part the relationship belongs to.
|
|
76
|
+
* Use "" (empty string) for root-level relationships (_rels/.rels).
|
|
77
|
+
*/
|
|
78
|
+
interface PendingRelationship {
|
|
79
|
+
/** The part this relationship belongs to ("" for root) */
|
|
80
|
+
sourcePart: string;
|
|
81
|
+
/** The relationship entry */
|
|
82
|
+
relationship: Relationship;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* OOXML Package Reader
|
|
87
|
+
*
|
|
88
|
+
* Opens OOXML archives (.docx, .pptx, .xlsx) and parses their
|
|
89
|
+
* structural metadata: [Content_Types].xml, relationships, and
|
|
90
|
+
* core properties.
|
|
91
|
+
*
|
|
92
|
+
* Uses bounded JSZip member streams and a platform DOMParser (with the
|
|
93
|
+
* package-owned xmldom parser in Node/SSR) to parse XML.
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
type OoxmlOpenOptions = ZipSafetyLimits;
|
|
97
|
+
/**
|
|
98
|
+
* Open an OOXML package from raw data.
|
|
99
|
+
*
|
|
100
|
+
* Parses the ZIP archive, [Content_Types].xml, and root relationships.
|
|
101
|
+
*
|
|
102
|
+
* @param data - The raw .docx/.pptx/.xlsx file as ArrayBuffer or Blob
|
|
103
|
+
* @param limits - Optional archive count, size, and compression-ratio limits
|
|
104
|
+
* @returns A parsed OoxmlPackage
|
|
105
|
+
*/
|
|
106
|
+
declare function openPackage(data: ArrayBuffer | Blob, limits?: OoxmlOpenOptions): Promise<OoxmlPackage>;
|
|
107
|
+
/**
|
|
108
|
+
* Parse relationships for a specific part.
|
|
109
|
+
*
|
|
110
|
+
* @param pkg - The OOXML package (or the zip directly)
|
|
111
|
+
* @param partPath - The part path (e.g., "word/document.xml").
|
|
112
|
+
* Use "" for root-level relationships (_rels/.rels).
|
|
113
|
+
* @returns Array of relationship entries
|
|
114
|
+
*/
|
|
115
|
+
declare function getPartRelationships(pkg: OoxmlPackage, partPath: string): Promise<Relationship[]>;
|
|
116
|
+
/**
|
|
117
|
+
* Extract an XML part from the package and parse it as a DOM Document.
|
|
118
|
+
*
|
|
119
|
+
* @param pkg - The OOXML package
|
|
120
|
+
* @param partPath - Path within the archive (e.g., "word/document.xml")
|
|
121
|
+
* @returns Parsed XML Document, or null if the part doesn't exist
|
|
122
|
+
*/
|
|
123
|
+
declare function getPartXml(pkg: OoxmlPackage, partPath: string): Promise<Document | null>;
|
|
124
|
+
/**
|
|
125
|
+
* Extract a binary part from the package (e.g., an image from word/media/).
|
|
126
|
+
*
|
|
127
|
+
* @param pkg - The OOXML package
|
|
128
|
+
* @param partPath - Path within the archive
|
|
129
|
+
* @returns The binary content, or null if the part doesn't exist
|
|
130
|
+
*/
|
|
131
|
+
declare function getPartBinary(pkg: OoxmlPackage, partPath: string): Promise<ArrayBuffer | null>;
|
|
132
|
+
/**
|
|
133
|
+
* Parse core document properties from docProps/core.xml.
|
|
134
|
+
*
|
|
135
|
+
* @param pkg - The OOXML package
|
|
136
|
+
* @returns Parsed core properties (all fields optional)
|
|
137
|
+
*/
|
|
138
|
+
declare function getCoreProperties(pkg: OoxmlPackage): Promise<CoreProperties>;
|
|
139
|
+
|
|
140
|
+
export { type CoreProperties as C, type OoxmlOpenOptions as O, type PackagePart as P, type Relationship as R, type OoxmlPackage as a, type ContentTypeMap as b, type PendingRelationship as c, getPartBinary as d, getPartRelationships as e, getPartXml as f, getCoreProperties as g, openPackage as o };
|
package/dist/registry/index.d.ts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
|
-
import { Doc } from '@bendyline/squisq/schemas';
|
|
2
|
-
import {
|
|
1
|
+
import { Doc, ThemeRegistry } from '@bendyline/squisq/schemas';
|
|
2
|
+
import { TransformStyleInput, TransformStyleRegistry } from '@bendyline/squisq/transform';
|
|
3
|
+
import { ParseOptions, StringifyOptions, MarkdownDocument } from '@bendyline/squisq/markdown';
|
|
3
4
|
import { ContentContainer } from '@bendyline/squisq/storage';
|
|
5
|
+
import { DocxImportOptions, DocxExportOptions } from '../docx/index.js';
|
|
6
|
+
import { a as PptxImportOptions, P as PptxExportOptions } from '../import-K8mfc0fz.js';
|
|
7
|
+
import { a as XlsxImportOptions, X as XlsxExportOptions } from '../export-D2NkylDT.js';
|
|
8
|
+
import { CsvImportOptions, CsvExportOptions } from '../csv/index.js';
|
|
9
|
+
import { PdfImportOptions, PdfExportOptions } from '../pdf/index.js';
|
|
10
|
+
import { a as HtmlImportOptions, H as HtmlExportOptions } from '../import-DTkDxHmZ.js';
|
|
11
|
+
import { EpubExportOptions } from '../epub/index.js';
|
|
12
|
+
import { ContainerToZipOptions } from '../container/index.js';
|
|
13
|
+
import { c as ZipSafetyLimits } from '../zipLimits-BOKCB7qk.js';
|
|
14
|
+
import '../reader-B9L8Ucbj.js';
|
|
4
15
|
|
|
5
16
|
/**
|
|
6
17
|
* Format registry — shared types.
|
|
@@ -27,6 +38,30 @@ interface ConversionResult {
|
|
|
27
38
|
/** Non-fatal notes accumulated during conversion (may be empty). */
|
|
28
39
|
warnings: string[];
|
|
29
40
|
}
|
|
41
|
+
interface MarkdownFormatOptions {
|
|
42
|
+
parse?: ParseOptions;
|
|
43
|
+
stringify?: StringifyOptions;
|
|
44
|
+
}
|
|
45
|
+
/** Resource limits applied when importing a DBK/ZIP container. */
|
|
46
|
+
type DbkFormatOptions = ZipSafetyLimits & ContainerToZipOptions;
|
|
47
|
+
/**
|
|
48
|
+
* Strongly typed option bags for built-in formats. Import and export options
|
|
49
|
+
* share a bag because a single conversion may use the format on either side.
|
|
50
|
+
* Custom registries may add arbitrary keys through the intersection used by
|
|
51
|
+
* {@link ConvertOptions.formatOptions}.
|
|
52
|
+
*/
|
|
53
|
+
interface BuiltinFormatOptions {
|
|
54
|
+
md: MarkdownFormatOptions;
|
|
55
|
+
docx: DocxImportOptions & DocxExportOptions;
|
|
56
|
+
pptx: PptxImportOptions & PptxExportOptions;
|
|
57
|
+
xlsx: XlsxImportOptions & XlsxExportOptions;
|
|
58
|
+
csv: CsvImportOptions & CsvExportOptions;
|
|
59
|
+
pdf: PdfImportOptions & PdfExportOptions;
|
|
60
|
+
html: HtmlImportOptions & Partial<Omit<HtmlExportOptions, 'playerScript'>>;
|
|
61
|
+
htmlzip: Partial<Omit<HtmlExportOptions, 'playerScript'>>;
|
|
62
|
+
epub: EpubExportOptions;
|
|
63
|
+
dbk: DbkFormatOptions;
|
|
64
|
+
}
|
|
30
65
|
/**
|
|
31
66
|
* A source normalized into every shape an exporter might need. `doc` is always
|
|
32
67
|
* present; `markdownDoc` is present when the source was markdown-shaped (an
|
|
@@ -40,22 +75,37 @@ interface NormalizedInput {
|
|
|
40
75
|
}
|
|
41
76
|
/** Options threaded through `convert()` and into every format method. */
|
|
42
77
|
interface ConvertOptions {
|
|
78
|
+
/** Cancel normalization, transformation, or export at the next bounded work boundary. */
|
|
79
|
+
signal?: AbortSignal;
|
|
43
80
|
/** Registry to resolve formats against. Defaults to `defaultRegistry()`. */
|
|
44
81
|
registry?: FormatRegistry;
|
|
45
82
|
/** Explicit source format id (skips extension/byte sniffing). */
|
|
46
83
|
from?: FormatId;
|
|
47
84
|
/** Theme id to apply to the exported document. */
|
|
48
85
|
themeId?: string;
|
|
49
|
-
/**
|
|
50
|
-
|
|
86
|
+
/** Explicit caller-owned registry for non-document custom themes. */
|
|
87
|
+
themeRegistry?: ThemeRegistry;
|
|
88
|
+
/** Built-in/registry id or call-scoped style to apply before export. */
|
|
89
|
+
transformStyle?: TransformStyleInput;
|
|
90
|
+
/** Explicit caller-owned registry used to resolve transform style ids. */
|
|
91
|
+
transformRegistry?: TransformStyleRegistry;
|
|
51
92
|
/** Content-aware auto-templating when deriving a Doc from markdown. */
|
|
52
93
|
autoTemplates?: boolean;
|
|
53
|
-
/** Title hint for exporters that
|
|
94
|
+
/** Title hint for exporters that expose document metadata. */
|
|
54
95
|
title?: string;
|
|
55
96
|
/** Lazily resolve the standalone player IIFE bundle (required for HTML export). */
|
|
56
97
|
resolvePlayerScript?: () => Promise<string>;
|
|
57
|
-
/**
|
|
58
|
-
formatOptions?:
|
|
98
|
+
/** Typed per-format options for built-ins; custom format ids remain extensible. */
|
|
99
|
+
formatOptions?: Partial<BuiltinFormatOptions> & Record<FormatId, unknown>;
|
|
100
|
+
}
|
|
101
|
+
/** Target-only options accepted after a source has already been normalized and transformed. */
|
|
102
|
+
type PreparedExportOptions = Pick<ConvertOptions, 'signal' | 'title' | 'resolvePlayerScript' | 'formatOptions'>;
|
|
103
|
+
/**
|
|
104
|
+
* An opaque normalized conversion snapshot. The source and transform pipeline
|
|
105
|
+
* has already completed; each call exports that same snapshot to one target.
|
|
106
|
+
*/
|
|
107
|
+
interface PreparedConversion {
|
|
108
|
+
convert(to: FormatId, options?: PreparedExportOptions): Promise<ConversionResult>;
|
|
59
109
|
}
|
|
60
110
|
/** Describes how a single format imports to / exports from the squisq model. */
|
|
61
111
|
interface FormatDefinition {
|
|
@@ -154,6 +204,8 @@ declare function defaultFormats(): FormatDefinition[];
|
|
|
154
204
|
* an optional transform, then hands off to the target format's exporter.
|
|
155
205
|
*/
|
|
156
206
|
|
|
207
|
+
/** Normalize and transform a source once, then safely export that snapshot many times. */
|
|
208
|
+
declare function prepareConversion(source: ConvertSource, options?: ConvertOptions): Promise<PreparedConversion>;
|
|
157
209
|
/**
|
|
158
210
|
* Convert a source document to a target format.
|
|
159
211
|
*
|
|
@@ -164,4 +216,4 @@ declare function defaultFormats(): FormatDefinition[];
|
|
|
164
216
|
*/
|
|
165
217
|
declare function convert(source: ConvertSource, to: FormatId, options?: ConvertOptions): Promise<ConversionResult>;
|
|
166
218
|
|
|
167
|
-
export { BUILTIN_FORMAT_IDS, ConversionError, type ConversionErrorCode, type ConversionErrorOptions, type ConversionResult, type ConvertOptions, type ConvertSource, type FormatDefinition, type FormatId, type FormatRegistry, type NormalizedInput, convert, createRegistry, defaultFormats, defaultRegistry };
|
|
219
|
+
export { BUILTIN_FORMAT_IDS, type BuiltinFormatOptions, ConversionError, type ConversionErrorCode, type ConversionErrorOptions, type ConversionResult, type ConvertOptions, type ConvertSource, type DbkFormatOptions, type FormatDefinition, type FormatId, type FormatRegistry, type MarkdownFormatOptions, type NormalizedInput, type PreparedConversion, type PreparedExportOptions, convert, createRegistry, defaultFormats, defaultRegistry, prepareConversion };
|
package/dist/registry/index.js
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BUILTIN_FORMAT_IDS,
|
|
3
|
-
ConversionError,
|
|
4
3
|
convert,
|
|
5
4
|
createRegistry,
|
|
6
5
|
defaultFormats,
|
|
7
|
-
defaultRegistry
|
|
8
|
-
|
|
6
|
+
defaultRegistry,
|
|
7
|
+
prepareConversion
|
|
8
|
+
} from "../chunk-HTW2M27H.js";
|
|
9
|
+
import {
|
|
10
|
+
ConversionError
|
|
11
|
+
} from "../chunk-ODL3SSPT.js";
|
|
12
|
+
import "../chunk-FE6OJV6O.js";
|
|
9
13
|
export {
|
|
10
14
|
BUILTIN_FORMAT_IDS,
|
|
11
15
|
ConversionError,
|
|
12
16
|
convert,
|
|
13
17
|
createRegistry,
|
|
14
18
|
defaultFormats,
|
|
15
|
-
defaultRegistry
|
|
19
|
+
defaultRegistry,
|
|
20
|
+
prepareConversion
|
|
16
21
|
};
|
|
17
22
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { a as OoxmlPackage } from './reader-B9L8Ucbj.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* OOXML theme reader — parses a `theme1.xml` part (DrawingML `a:theme`)
|
|
5
|
+
* into normalized color and font schemes.
|
|
6
|
+
*
|
|
7
|
+
* Shared by DOCX/PPTX/XLSX theme inference: all three formats carry the same
|
|
8
|
+
* theme part shape, differing only in where the part hangs (document/master/
|
|
9
|
+
* workbook relationships). This module never fails hard — unreadable slots
|
|
10
|
+
* degrade to fallbacks or absence, with a warning per degradation.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The clrScheme slots as normalized `#rrggbb` strings. The four surface/text
|
|
15
|
+
* slots always resolve (falling back to black/white when degraded); accent and
|
|
16
|
+
* hyperlink slots are omitted when unresolvable.
|
|
17
|
+
*/
|
|
18
|
+
interface OoxmlColorScheme {
|
|
19
|
+
dk1: string;
|
|
20
|
+
lt1: string;
|
|
21
|
+
dk2: string;
|
|
22
|
+
lt2: string;
|
|
23
|
+
accent1?: string;
|
|
24
|
+
accent2?: string;
|
|
25
|
+
accent3?: string;
|
|
26
|
+
accent4?: string;
|
|
27
|
+
accent5?: string;
|
|
28
|
+
accent6?: string;
|
|
29
|
+
hlink?: string;
|
|
30
|
+
folHlink?: string;
|
|
31
|
+
}
|
|
32
|
+
interface OoxmlFontScheme {
|
|
33
|
+
/** `a:fontScheme > a:majorFont > a:latin@typeface` (headings). */
|
|
34
|
+
majorLatin?: string;
|
|
35
|
+
/** `a:fontScheme > a:minorFont > a:latin@typeface` (body). */
|
|
36
|
+
minorLatin?: string;
|
|
37
|
+
}
|
|
38
|
+
interface OoxmlTheme {
|
|
39
|
+
/** `a:theme@name` (e.g. "Office Theme", "Ion"). */
|
|
40
|
+
name?: string;
|
|
41
|
+
/** Absent when the theme carries no parseable `a:clrScheme`. */
|
|
42
|
+
colors?: OoxmlColorScheme;
|
|
43
|
+
/** Absent when the theme carries no `a:fontScheme` latin typefaces. */
|
|
44
|
+
fonts?: OoxmlFontScheme;
|
|
45
|
+
warnings: string[];
|
|
46
|
+
}
|
|
47
|
+
/** Parse an already-loaded theme part Document. */
|
|
48
|
+
declare function parseThemeXml(themeDoc: Document): OoxmlTheme;
|
|
49
|
+
/**
|
|
50
|
+
* Resolve the theme part related from `fromPartPath` (via `REL_THEME`) and
|
|
51
|
+
* parse it. Returns null when the part has no theme relationship or the
|
|
52
|
+
* target part is missing — callers decide whether that's an error.
|
|
53
|
+
*/
|
|
54
|
+
declare function readThemePart(pkg: OoxmlPackage, fromPartPath: string): Promise<OoxmlTheme | null>;
|
|
55
|
+
|
|
56
|
+
export { type OoxmlColorScheme as O, type OoxmlFontScheme as a, type OoxmlTheme as b, parseThemeXml as p, readThemePart as r };
|
package/dist/xlsx/index.d.ts
CHANGED
|
@@ -1,69 +1,9 @@
|
|
|
1
1
|
import { Doc } from '@bendyline/squisq/schemas';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* Reuses the shared ooxml/ reader (zip + DOMParser). Reads the workbook's
|
|
8
|
-
* sheet list, resolves each sheet part via relationships, pulls shared strings,
|
|
9
|
-
* and turns each worksheet's cell grid into a markdown table (first row treated
|
|
10
|
-
* as the header). By default every sheet is imported, each preceded by an H1 of
|
|
11
|
-
* the sheet name; pass `options.sheet` (index or name) to import just one.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
interface XlsxImportOptions {
|
|
15
|
-
/** Which sheet to import (0-based index or sheet name). Default: all sheets. */
|
|
16
|
-
sheet?: number | string;
|
|
17
|
-
}
|
|
18
|
-
declare function xlsxToMarkdownDoc(data: ArrayBuffer | Blob, options?: XlsxImportOptions): Promise<MarkdownDocument>;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* XLSX export — MarkdownDocument → SpreadsheetML (.xlsx).
|
|
22
|
-
*
|
|
23
|
-
* Tables-only fidelity (honestly documented): every `table` node in the
|
|
24
|
-
* markdown AST becomes one worksheet; all other content (headings, prose,
|
|
25
|
-
* lists, images, …) is dropped except that the nearest preceding heading is
|
|
26
|
-
* used to name the sheet. This mirrors the import side (`xlsxToMarkdownDoc`),
|
|
27
|
-
* which turns each worksheet grid back into a markdown table.
|
|
28
|
-
*
|
|
29
|
-
* Cells are emitted as inline strings (`t="inlineStr"`) so no sharedStrings
|
|
30
|
-
* part is needed, except values matching a plain-number pattern, which are
|
|
31
|
-
* emitted as numeric cells. The package is assembled with the shared ooxml/
|
|
32
|
-
* writer (auto-generates `[Content_Types].xml` + `_rels`), so only the
|
|
33
|
-
* SpreadsheetML-specific parts (workbook, worksheets, styles) are written here.
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* ```ts
|
|
37
|
-
* import { parseMarkdown } from '@bendyline/squisq/markdown';
|
|
38
|
-
* import { markdownDocToXlsx } from '@bendyline/squisq-formats/xlsx';
|
|
39
|
-
*
|
|
40
|
-
* const md = parseMarkdown('# Metrics\n\n| A | B |\n| - | - |\n| 1 | 2 |');
|
|
41
|
-
* const buffer = await markdownDocToXlsx(md);
|
|
42
|
-
* ```
|
|
43
|
-
*/
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Options for XLSX export.
|
|
47
|
-
*/
|
|
48
|
-
interface XlsxExportOptions {
|
|
49
|
-
/** Workbook title (written to core properties). */
|
|
50
|
-
title?: string;
|
|
51
|
-
/** Workbook author (written to core properties). */
|
|
52
|
-
author?: string;
|
|
53
|
-
/** Prefix used for auto-named sheets when no heading precedes a table. Default: "Sheet". */
|
|
54
|
-
sheetNamePrefix?: string;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Convert a MarkdownDocument to a .xlsx file (tables-only fidelity).
|
|
58
|
-
*
|
|
59
|
-
* Each markdown `table` becomes one worksheet; a document with no tables
|
|
60
|
-
* yields a single empty sheet (a valid, openable file — never throws).
|
|
61
|
-
*/
|
|
62
|
-
declare function markdownDocToXlsx(doc: MarkdownDocument, options?: XlsxExportOptions): Promise<ArrayBuffer>;
|
|
63
|
-
/**
|
|
64
|
-
* Convert a squisq Doc to a .xlsx file (via the markdown table model).
|
|
65
|
-
*/
|
|
66
|
-
declare function docToXlsx(doc: Doc, options?: XlsxExportOptions): Promise<ArrayBuffer>;
|
|
2
|
+
import { a as XlsxImportOptions } from '../export-D2NkylDT.js';
|
|
3
|
+
export { X as XlsxExportOptions, d as docToXlsx, m as markdownDocToXlsx, x as xlsxToMarkdownDoc } from '../export-D2NkylDT.js';
|
|
4
|
+
import '@bendyline/squisq/markdown';
|
|
5
|
+
import '../reader-B9L8Ucbj.js';
|
|
6
|
+
import '../zipLimits-BOKCB7qk.js';
|
|
67
7
|
|
|
68
8
|
/**
|
|
69
9
|
* @bendyline/squisq-formats XLSX Module
|
|
@@ -86,4 +26,4 @@ declare function docToXlsx(doc: Doc, options?: XlsxExportOptions): Promise<Array
|
|
|
86
26
|
*/
|
|
87
27
|
declare function xlsxToDoc(data: ArrayBuffer | Blob, options?: XlsxImportOptions): Promise<Doc>;
|
|
88
28
|
|
|
89
|
-
export {
|
|
29
|
+
export { XlsxImportOptions, xlsxToDoc };
|
package/dist/xlsx/index.js
CHANGED
|
@@ -3,10 +3,12 @@ import {
|
|
|
3
3
|
markdownDocToXlsx,
|
|
4
4
|
xlsxToDoc,
|
|
5
5
|
xlsxToMarkdownDoc
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-VJJM2SSH.js";
|
|
7
7
|
import "../chunk-PN52A5AA.js";
|
|
8
|
-
import "../chunk-
|
|
8
|
+
import "../chunk-U32AG3G3.js";
|
|
9
9
|
import "../chunk-U4MRIFKL.js";
|
|
10
|
+
import "../chunk-WC7WULGV.js";
|
|
11
|
+
import "../chunk-FE6OJV6O.js";
|
|
10
12
|
export {
|
|
11
13
|
docToXlsx,
|
|
12
14
|
markdownDocToXlsx,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** ZIP safety policy, structured errors, path checks, and metadata validation. */
|
|
2
|
+
|
|
3
|
+
interface ZipSafetyLimits {
|
|
4
|
+
/** Cooperatively cancel archive opening, validation, and member traversal. */
|
|
5
|
+
signal?: AbortSignal;
|
|
6
|
+
/** Maximum number of archive records, including directories. Default: 10,000. */
|
|
7
|
+
maxEntries?: number;
|
|
8
|
+
/** Maximum uncompressed bytes for one member. Defaults to maxUncompressedBytes. */
|
|
9
|
+
maxEntryUncompressedBytes?: number;
|
|
10
|
+
/** Maximum total uncompressed bytes across the archive. Default: 512 MiB. */
|
|
11
|
+
maxUncompressedBytes?: number;
|
|
12
|
+
/** Maximum uncompressed/compressed ratio for a member. Default: 1,000. */
|
|
13
|
+
maxCompressionRatio?: number;
|
|
14
|
+
}
|
|
15
|
+
type ZipSafetyErrorCode = 'invalid-limit' | 'invalid-archive' | 'unsafe-path' | 'invalid-entry-metadata' | 'too-many-entries' | 'entry-too-large' | 'archive-too-large' | 'compression-ratio-exceeded' | 'size-mismatch' | 'crc-mismatch' | 'decompression-failed';
|
|
16
|
+
interface ZipSafetyErrorOptions {
|
|
17
|
+
path?: string;
|
|
18
|
+
limit?: number;
|
|
19
|
+
actual?: number;
|
|
20
|
+
cause?: unknown;
|
|
21
|
+
}
|
|
22
|
+
/** A stable, machine-readable error raised while validating or reading a ZIP. */
|
|
23
|
+
declare class ZipSafetyError extends Error {
|
|
24
|
+
readonly code: ZipSafetyErrorCode;
|
|
25
|
+
readonly path?: string;
|
|
26
|
+
readonly limit?: number;
|
|
27
|
+
readonly actual?: number;
|
|
28
|
+
constructor(code: ZipSafetyErrorCode, message: string, options?: ZipSafetyErrorOptions);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { ZipSafetyError as Z, type ZipSafetyErrorCode as a, type ZipSafetyErrorOptions as b, type ZipSafetyLimits as c };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bendyline/squisq-formats",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Document format converters — DOCX, PDF, OOXML import/export",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Bendyline",
|
|
@@ -86,6 +86,11 @@
|
|
|
86
86
|
"types": "./dist/registry/index.d.ts",
|
|
87
87
|
"import": "./dist/registry/index.js",
|
|
88
88
|
"default": "./dist/registry/index.js"
|
|
89
|
+
},
|
|
90
|
+
"./infer": {
|
|
91
|
+
"types": "./dist/infer/index.d.ts",
|
|
92
|
+
"import": "./dist/infer/index.js",
|
|
93
|
+
"default": "./dist/infer/index.js"
|
|
89
94
|
}
|
|
90
95
|
},
|
|
91
96
|
"scripts": {
|
|
@@ -94,7 +99,8 @@
|
|
|
94
99
|
"typecheck": "tsc --noEmit"
|
|
95
100
|
},
|
|
96
101
|
"dependencies": {
|
|
97
|
-
"@
|
|
102
|
+
"@xmldom/xmldom": "0.9.10",
|
|
103
|
+
"@bendyline/squisq": "2.0.1",
|
|
98
104
|
"jszip": "3.10.1",
|
|
99
105
|
"pdf-lib": "1.17.1",
|
|
100
106
|
"pdfjs-dist": "4.10.38"
|
|
@@ -78,6 +78,13 @@ describe('containerToZip', () => {
|
|
|
78
78
|
const data = await zip.file('image.png')!.async('uint8array');
|
|
79
79
|
expect(data).toEqual(binaryData);
|
|
80
80
|
});
|
|
81
|
+
|
|
82
|
+
it('refuses to create a ZIP with an unsafe container path', async () => {
|
|
83
|
+
const container = new MemoryContentContainer();
|
|
84
|
+
await container.writeFile('../outside.txt', new TextEncoder().encode('nope'));
|
|
85
|
+
|
|
86
|
+
await expect(containerToZip(container)).rejects.toThrow(/path is unsafe/i);
|
|
87
|
+
});
|
|
81
88
|
});
|
|
82
89
|
|
|
83
90
|
// ============================================
|
|
@@ -137,6 +144,40 @@ describe('zipToContainer', () => {
|
|
|
137
144
|
const container = await zipToContainer(ab);
|
|
138
145
|
expect(await container.readDocument()).toBe('# Read me');
|
|
139
146
|
});
|
|
147
|
+
|
|
148
|
+
it('rejects archives that exceed the configured entry limit', async () => {
|
|
149
|
+
const zip = new JSZip();
|
|
150
|
+
zip.file('one.txt', '1');
|
|
151
|
+
zip.file('two.txt', '2');
|
|
152
|
+
const data = await zip.generateAsync({ type: 'arraybuffer' });
|
|
153
|
+
await expect(zipToContainer(data, { maxEntries: 1 })).rejects.toThrow(/archive has 2 files/);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('rejects archives that exceed the configured uncompressed byte limit', async () => {
|
|
157
|
+
const zip = new JSZip();
|
|
158
|
+
zip.file('large.txt', '12345');
|
|
159
|
+
const data = await zip.generateAsync({ type: 'arraybuffer' });
|
|
160
|
+
await expect(zipToContainer(data, { maxUncompressedBytes: 4 })).rejects.toThrow(
|
|
161
|
+
/uncompressed content exceeds 4 byte limit/,
|
|
162
|
+
);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('rejects traversal paths even when JSZip sanitizes their loaded key', async () => {
|
|
166
|
+
const zip = new JSZip();
|
|
167
|
+
zip.file('../outside.txt', 'nope');
|
|
168
|
+
const data = await zip.generateAsync({ type: 'arraybuffer' });
|
|
169
|
+
|
|
170
|
+
await expect(zipToContainer(data)).rejects.toThrow(/unsafe path.*\.\.\/outside\.txt/i);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('rejects absolute and Windows-style archive paths', async () => {
|
|
174
|
+
for (const path of ['/absolute.txt', 'C:\\outside.txt']) {
|
|
175
|
+
const zip = new JSZip();
|
|
176
|
+
zip.file(path, 'nope');
|
|
177
|
+
const data = await zip.generateAsync({ type: 'arraybuffer' });
|
|
178
|
+
await expect(zipToContainer(data)).rejects.toThrow(/unsafe path/i);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
140
181
|
});
|
|
141
182
|
|
|
142
183
|
// ============================================
|