@bendyline/squisq-formats 1.4.1 → 2.0.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/README.md +48 -2
- package/dist/{chunk-WWBIKRNP.js → chunk-2CSZJEAL.js} +13 -11
- package/dist/chunk-2CSZJEAL.js.map +1 -0
- package/dist/{chunk-RTS5XBZ7.js → chunk-2EFDWKC6.js} +262 -84
- package/dist/chunk-2EFDWKC6.js.map +1 -0
- package/dist/chunk-2PRVLAU3.js +740 -0
- package/dist/chunk-2PRVLAU3.js.map +1 -0
- package/dist/{chunk-SHLPSADL.js → chunk-4HJ6AK2Q.js} +54 -193
- package/dist/chunk-4HJ6AK2Q.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-CVNVD7VH.js} +154 -39
- package/dist/chunk-CVNVD7VH.js.map +1 -0
- package/dist/chunk-CX3LH47J.js +99 -0
- package/dist/chunk-CX3LH47J.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-H7T5DXUU.js +479 -0
- package/dist/chunk-H7T5DXUU.js.map +1 -0
- package/dist/{chunk-EHLGMSTE.js → chunk-HBSCRS5P.js} +10 -8
- package/dist/chunk-HBSCRS5P.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-X4USWOQ2.js +131 -0
- package/dist/chunk-X4USWOQ2.js.map +1 -0
- package/dist/chunk-XTLQXR4U.js +195 -0
- package/dist/chunk-XTLQXR4U.js.map +1 -0
- package/dist/chunk-YRT7GQ5Y.js +28 -0
- package/dist/chunk-YRT7GQ5Y.js.map +1 -0
- package/dist/chunk-ZZ7D4DN6.js +97 -0
- package/dist/chunk-ZZ7D4DN6.js.map +1 -0
- package/dist/container/index.d.ts +6 -2
- package/dist/container/index.js +15 -17
- 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-Djev9BLU.d.ts +69 -0
- package/dist/extract-LNOA7DBK.js +15 -0
- package/dist/extract-LNOA7DBK.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-Yivc3kZM.d.ts +136 -0
- package/dist/index.d.ts +13 -4
- package/dist/index.js +30 -11
- 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-7OUUVAGU.js +12 -0
- package/dist/layouts-7OUUVAGU.js.map +1 -0
- package/dist/layouts-CZ0bdsNL.d.ts +150 -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-Gof6OrJX.d.ts +140 -0
- package/dist/registry/index.d.ts +46 -8
- package/dist/registry/index.js +5 -2
- package/dist/themeReader-DPw4J5Ss.d.ts +56 -0
- package/dist/xlsx/index.d.ts +6 -66
- package/dist/xlsx/index.js +4 -2
- package/dist/zipLimits-bGYMS9cI.d.ts +29 -0
- package/package.json +8 -2
- package/src/__tests__/container.test.ts +41 -0
- package/src/__tests__/convert.test.ts +167 -0
- 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 +59 -2
- 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 +20 -29
- 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 +20 -0
- package/src/infer/extract.ts +127 -0
- package/src/infer/index.ts +168 -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 +87 -28
- 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 +1168 -0
- package/src/registry/convert.ts +54 -23
- package/src/registry/defaultFormats.ts +131 -44
- package/src/registry/index.ts +3 -0
- package/src/registry/types.ts +52 -6
- package/src/shared/boundedZipArchive.ts +342 -0
- package/src/shared/fidelity.ts +130 -0
- package/src/shared/zipEntryCount.ts +97 -0
- package/src/shared/zipLimits.ts +286 -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
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConversionError
|
|
3
|
+
} from "./chunk-ODL3SSPT.js";
|
|
4
|
+
import {
|
|
5
|
+
ZipSafetyError,
|
|
6
|
+
openBoundedZipArchive
|
|
7
|
+
} from "./chunk-H7T5DXUU.js";
|
|
8
|
+
|
|
1
9
|
// src/registry/types.ts
|
|
2
10
|
var BUILTIN_FORMAT_IDS = [
|
|
3
11
|
"md",
|
|
@@ -12,19 +20,97 @@ var BUILTIN_FORMAT_IDS = [
|
|
|
12
20
|
"dbk"
|
|
13
21
|
];
|
|
14
22
|
|
|
15
|
-
// src/
|
|
16
|
-
var
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
// src/shared/fidelity.ts
|
|
24
|
+
var CONTENT_NODE_TYPES = {
|
|
25
|
+
heading: true,
|
|
26
|
+
paragraph: true,
|
|
27
|
+
blockquote: true,
|
|
28
|
+
list: true,
|
|
29
|
+
code: true,
|
|
30
|
+
thematicBreak: true,
|
|
31
|
+
table: true,
|
|
32
|
+
htmlBlock: true,
|
|
33
|
+
math: true,
|
|
34
|
+
definition: true,
|
|
35
|
+
footnoteDefinition: true,
|
|
36
|
+
containerDirective: true,
|
|
37
|
+
leafDirective: true,
|
|
38
|
+
definitionList: true,
|
|
39
|
+
text: true,
|
|
40
|
+
emphasis: true,
|
|
41
|
+
strong: true,
|
|
42
|
+
delete: true,
|
|
43
|
+
inlineCode: true,
|
|
44
|
+
link: true,
|
|
45
|
+
image: true,
|
|
46
|
+
break: true,
|
|
47
|
+
htmlInline: true,
|
|
48
|
+
inlineMath: true,
|
|
49
|
+
footnoteReference: true,
|
|
50
|
+
linkReference: true,
|
|
51
|
+
imageReference: true,
|
|
52
|
+
textDirective: true,
|
|
53
|
+
mention: true,
|
|
54
|
+
inlineIcon: true
|
|
27
55
|
};
|
|
56
|
+
var COMMON_SUPPORTED = [
|
|
57
|
+
"heading",
|
|
58
|
+
"paragraph",
|
|
59
|
+
"blockquote",
|
|
60
|
+
"list",
|
|
61
|
+
"code",
|
|
62
|
+
"thematicBreak",
|
|
63
|
+
"table",
|
|
64
|
+
"htmlBlock",
|
|
65
|
+
"math",
|
|
66
|
+
"text",
|
|
67
|
+
"emphasis",
|
|
68
|
+
"strong",
|
|
69
|
+
"delete",
|
|
70
|
+
"inlineCode",
|
|
71
|
+
"link",
|
|
72
|
+
"image",
|
|
73
|
+
"break",
|
|
74
|
+
"htmlInline",
|
|
75
|
+
"inlineMath"
|
|
76
|
+
];
|
|
77
|
+
var PROFILE_SUPPORT = {
|
|
78
|
+
docx: /* @__PURE__ */ new Set([...COMMON_SUPPORTED, "footnoteDefinition", "footnoteReference"]),
|
|
79
|
+
pdf: /* @__PURE__ */ new Set([...COMMON_SUPPORTED, "footnoteDefinition", "footnoteReference"]),
|
|
80
|
+
pptx: new Set(COMMON_SUPPORTED),
|
|
81
|
+
epub: new Set(COMMON_SUPPORTED)
|
|
82
|
+
};
|
|
83
|
+
var PROFILE_LABELS = {
|
|
84
|
+
docx: "DOCX",
|
|
85
|
+
pdf: "PDF",
|
|
86
|
+
pptx: "PPTX",
|
|
87
|
+
epub: "EPUB"
|
|
88
|
+
};
|
|
89
|
+
function markdownFidelityWarnings(document2, profile) {
|
|
90
|
+
const supported = PROFILE_SUPPORT[profile];
|
|
91
|
+
const omitted = /* @__PURE__ */ new Map();
|
|
92
|
+
const visit = (candidate) => {
|
|
93
|
+
if (!candidate || typeof candidate !== "object") return;
|
|
94
|
+
const node = candidate;
|
|
95
|
+
const type = node.type;
|
|
96
|
+
if (type && Object.prototype.hasOwnProperty.call(CONTENT_NODE_TYPES, type)) {
|
|
97
|
+
if (!supported.has(type)) {
|
|
98
|
+
omitted.set(type, (omitted.get(type) ?? 0) + 1);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (Array.isArray(node.children)) {
|
|
103
|
+
for (const child of node.children) visit(child);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
for (const child of document2.children) visit(child);
|
|
107
|
+
if (omitted.size === 0) return [];
|
|
108
|
+
const total = [...omitted.values()].reduce((sum, count) => sum + count, 0);
|
|
109
|
+
const details = [...omitted].map(([type, count]) => `${type} (${count})`).join(", ");
|
|
110
|
+
return [
|
|
111
|
+
`${PROFILE_LABELS[profile]} export omitted ${total} unsupported Markdown node(s): ${details}.`
|
|
112
|
+
];
|
|
113
|
+
}
|
|
28
114
|
|
|
29
115
|
// src/registry/defaultFormats.ts
|
|
30
116
|
var MIME = {
|
|
@@ -55,6 +141,9 @@ async function toBytes(data) {
|
|
|
55
141
|
function resolveThemeId(input, options) {
|
|
56
142
|
return options.themeId ?? input.doc.themeId;
|
|
57
143
|
}
|
|
144
|
+
function optionsFor(options, id) {
|
|
145
|
+
return options.formatOptions?.[id] ?? {};
|
|
146
|
+
}
|
|
58
147
|
async function markdownOf(input) {
|
|
59
148
|
if (input.markdownDoc) return input.markdownDoc;
|
|
60
149
|
const { docToMarkdown } = await import("@bendyline/squisq/doc");
|
|
@@ -73,6 +162,29 @@ async function collectContainerImages(container) {
|
|
|
73
162
|
}
|
|
74
163
|
return images;
|
|
75
164
|
}
|
|
165
|
+
async function collectContainerDocxImages(container) {
|
|
166
|
+
const images = await collectContainerImages(container);
|
|
167
|
+
const { extToMime } = await import("./images-7FBWPKE3.js");
|
|
168
|
+
return new Map(
|
|
169
|
+
[...images].map(([path, data]) => [
|
|
170
|
+
path,
|
|
171
|
+
{ data, contentType: extToMime(path.split(".").pop() ?? "") }
|
|
172
|
+
])
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
async function snapshotContainerWithDocument(input) {
|
|
176
|
+
const { MemoryContentContainer } = await import("@bendyline/squisq/storage");
|
|
177
|
+
const snapshot = new MemoryContentContainer();
|
|
178
|
+
const entries = await input.container.listFiles();
|
|
179
|
+
for (const entry of entries) {
|
|
180
|
+
const data = await input.container.readFile(entry.path);
|
|
181
|
+
if (data) await snapshot.writeFile(entry.path, new Uint8Array(data), entry.mimeType);
|
|
182
|
+
}
|
|
183
|
+
const { stringifyMarkdown } = await import("@bendyline/squisq/markdown");
|
|
184
|
+
const documentPath = await input.container.getDocumentPath() ?? "index.md";
|
|
185
|
+
await snapshot.writeDocument(stringifyMarkdown(await markdownOf(input)), documentPath);
|
|
186
|
+
return snapshot;
|
|
187
|
+
}
|
|
76
188
|
async function requirePlayerScript(options, format) {
|
|
77
189
|
const script = await options.resolvePlayerScript?.();
|
|
78
190
|
if (!script) {
|
|
@@ -86,19 +198,27 @@ async function requirePlayerScript(options, format) {
|
|
|
86
198
|
function ok(bytes, mimeType, warnings = []) {
|
|
87
199
|
return { bytes, mimeType, suggestedFilename: "", warnings };
|
|
88
200
|
}
|
|
201
|
+
function pptxImportOptionsFrom(options) {
|
|
202
|
+
const raw = optionsFor(options, "pptx");
|
|
203
|
+
return {
|
|
204
|
+
...raw,
|
|
205
|
+
inferTheme: raw?.inferTheme !== false,
|
|
206
|
+
inferLayouts: raw?.inferLayouts !== false
|
|
207
|
+
};
|
|
208
|
+
}
|
|
89
209
|
function defaultFormats() {
|
|
90
210
|
const md = {
|
|
91
211
|
id: "md",
|
|
92
212
|
label: "Markdown",
|
|
93
213
|
mimeType: MIME.md,
|
|
94
214
|
extensions: [".md", ".markdown"],
|
|
95
|
-
async importDoc(data) {
|
|
215
|
+
async importDoc(data, options) {
|
|
96
216
|
const { parseMarkdown } = await import("@bendyline/squisq/markdown");
|
|
97
|
-
return parseMarkdown(new TextDecoder().decode(data));
|
|
217
|
+
return parseMarkdown(new TextDecoder().decode(data), optionsFor(options, "md").parse);
|
|
98
218
|
},
|
|
99
|
-
async exportDoc(input) {
|
|
219
|
+
async exportDoc(input, options) {
|
|
100
220
|
const { stringifyMarkdown } = await import("@bendyline/squisq/markdown");
|
|
101
|
-
const text = stringifyMarkdown(await markdownOf(input));
|
|
221
|
+
const text = stringifyMarkdown(await markdownOf(input), optionsFor(options, "md").stringify);
|
|
102
222
|
return ok(new TextEncoder().encode(text), MIME.md);
|
|
103
223
|
}
|
|
104
224
|
};
|
|
@@ -107,20 +227,28 @@ function defaultFormats() {
|
|
|
107
227
|
label: "Word (DOCX)",
|
|
108
228
|
mimeType: MIME.docx,
|
|
109
229
|
extensions: [".docx"],
|
|
110
|
-
async importContainer(data) {
|
|
230
|
+
async importContainer(data, options) {
|
|
111
231
|
const { docxToContainer } = await import("./docx/index.js");
|
|
112
|
-
return docxToContainer(data);
|
|
232
|
+
return docxToContainer(data, optionsFor(options, "docx"));
|
|
113
233
|
},
|
|
114
|
-
async importDoc(data) {
|
|
234
|
+
async importDoc(data, options) {
|
|
115
235
|
const { docxToMarkdownDoc } = await import("./docx/index.js");
|
|
116
|
-
return docxToMarkdownDoc(data);
|
|
236
|
+
return docxToMarkdownDoc(data, optionsFor(options, "docx"));
|
|
117
237
|
},
|
|
118
238
|
async exportDoc(input, options) {
|
|
119
239
|
const { markdownDocToDocx } = await import("./docx/index.js");
|
|
120
|
-
const
|
|
121
|
-
|
|
240
|
+
const raw = optionsFor(options, "docx");
|
|
241
|
+
const markdownDoc = await markdownOf(input);
|
|
242
|
+
const containerImages = await collectContainerDocxImages(input.container);
|
|
243
|
+
const images = new Map([...containerImages, ...raw.images ?? /* @__PURE__ */ new Map()]);
|
|
244
|
+
const buf = await markdownDocToDocx(markdownDoc, {
|
|
245
|
+
...raw,
|
|
246
|
+
...options.title !== void 0 ? { title: options.title } : {},
|
|
247
|
+
themeId: resolveThemeId(input, options),
|
|
248
|
+
themeRegistry: options.themeRegistry ?? raw.themeRegistry,
|
|
249
|
+
images
|
|
122
250
|
});
|
|
123
|
-
return ok(await toBytes(buf), MIME.docx);
|
|
251
|
+
return ok(await toBytes(buf), MIME.docx, markdownFidelityWarnings(markdownDoc, "docx"));
|
|
124
252
|
}
|
|
125
253
|
};
|
|
126
254
|
const pdf = {
|
|
@@ -128,20 +256,25 @@ function defaultFormats() {
|
|
|
128
256
|
label: "PDF",
|
|
129
257
|
mimeType: MIME.pdf,
|
|
130
258
|
extensions: [".pdf"],
|
|
131
|
-
async importContainer(data) {
|
|
259
|
+
async importContainer(data, options) {
|
|
132
260
|
const { pdfToContainer } = await import("./pdf/index.js");
|
|
133
|
-
return pdfToContainer(data);
|
|
261
|
+
return pdfToContainer(data, optionsFor(options, "pdf"));
|
|
134
262
|
},
|
|
135
|
-
async importDoc(data) {
|
|
263
|
+
async importDoc(data, options) {
|
|
136
264
|
const { pdfToMarkdownDoc } = await import("./pdf/index.js");
|
|
137
|
-
return pdfToMarkdownDoc(data);
|
|
265
|
+
return pdfToMarkdownDoc(data, optionsFor(options, "pdf"));
|
|
138
266
|
},
|
|
139
267
|
async exportDoc(input, options) {
|
|
140
268
|
const { markdownDocToPdf } = await import("./pdf/index.js");
|
|
141
|
-
const
|
|
142
|
-
|
|
269
|
+
const raw = optionsFor(options, "pdf");
|
|
270
|
+
const markdownDoc = await markdownOf(input);
|
|
271
|
+
const buf = await markdownDocToPdf(markdownDoc, {
|
|
272
|
+
...raw,
|
|
273
|
+
...options.title !== void 0 ? { title: options.title } : {},
|
|
274
|
+
themeId: resolveThemeId(input, options),
|
|
275
|
+
themeRegistry: options.themeRegistry ?? raw.themeRegistry
|
|
143
276
|
});
|
|
144
|
-
return ok(await toBytes(buf), MIME.pdf);
|
|
277
|
+
return ok(await toBytes(buf), MIME.pdf, markdownFidelityWarnings(markdownDoc, "pdf"));
|
|
145
278
|
}
|
|
146
279
|
};
|
|
147
280
|
const pptx = {
|
|
@@ -149,22 +282,28 @@ function defaultFormats() {
|
|
|
149
282
|
label: "PowerPoint (PPTX)",
|
|
150
283
|
mimeType: MIME.pptx,
|
|
151
284
|
extensions: [".pptx"],
|
|
152
|
-
async importContainer(data) {
|
|
285
|
+
async importContainer(data, options) {
|
|
153
286
|
const { pptxToContainer } = await import("./pptx/index.js");
|
|
154
|
-
return pptxToContainer(data);
|
|
287
|
+
return pptxToContainer(data, pptxImportOptionsFrom(options));
|
|
155
288
|
},
|
|
156
|
-
async importDoc(data) {
|
|
289
|
+
async importDoc(data, options) {
|
|
157
290
|
const { pptxToMarkdownDoc } = await import("./pptx/index.js");
|
|
158
|
-
return pptxToMarkdownDoc(data);
|
|
291
|
+
return pptxToMarkdownDoc(data, pptxImportOptionsFrom(options));
|
|
159
292
|
},
|
|
160
293
|
async exportDoc(input, options) {
|
|
161
294
|
const { markdownDocToPptx } = await import("./pptx/index.js");
|
|
162
|
-
const
|
|
163
|
-
const
|
|
295
|
+
const raw = optionsFor(options, "pptx");
|
|
296
|
+
const markdownDoc = await markdownOf(input);
|
|
297
|
+
const containerImages = await collectContainerImages(input.container);
|
|
298
|
+
const images = new Map([...containerImages, ...raw.images ?? /* @__PURE__ */ new Map()]);
|
|
299
|
+
const buf = await markdownDocToPptx(markdownDoc, {
|
|
300
|
+
...raw,
|
|
301
|
+
...options.title !== void 0 ? { title: options.title } : {},
|
|
164
302
|
themeId: resolveThemeId(input, options),
|
|
303
|
+
themeRegistry: options.themeRegistry ?? raw.themeRegistry,
|
|
165
304
|
images
|
|
166
305
|
});
|
|
167
|
-
return ok(await toBytes(buf), MIME.pptx);
|
|
306
|
+
return ok(await toBytes(buf), MIME.pptx, markdownFidelityWarnings(markdownDoc, "pptx"));
|
|
168
307
|
}
|
|
169
308
|
};
|
|
170
309
|
const xlsx = {
|
|
@@ -172,18 +311,21 @@ function defaultFormats() {
|
|
|
172
311
|
label: "Excel (XLSX)",
|
|
173
312
|
mimeType: MIME.xlsx,
|
|
174
313
|
extensions: [".xlsx"],
|
|
175
|
-
async importDoc(data) {
|
|
314
|
+
async importDoc(data, options) {
|
|
176
315
|
const { xlsxToMarkdownDoc } = await import("./xlsx/index.js");
|
|
177
|
-
return xlsxToMarkdownDoc(data);
|
|
316
|
+
return xlsxToMarkdownDoc(data, optionsFor(options, "xlsx"));
|
|
178
317
|
},
|
|
179
|
-
async exportDoc(input) {
|
|
318
|
+
async exportDoc(input, options) {
|
|
180
319
|
const { markdownDocToXlsx } = await import("./xlsx/index.js");
|
|
181
320
|
const markdownDoc = await markdownOf(input);
|
|
182
321
|
const omitted = markdownDoc.children.filter(
|
|
183
322
|
(n) => n.type !== "table" && n.type !== "heading"
|
|
184
323
|
).length;
|
|
185
324
|
const warnings = omitted > 0 ? [`XLSX export is tables-only; ${omitted} non-table block(s) were omitted.`] : [];
|
|
186
|
-
const blob = await markdownDocToXlsx(markdownDoc
|
|
325
|
+
const blob = await markdownDocToXlsx(markdownDoc, {
|
|
326
|
+
...optionsFor(options, "xlsx"),
|
|
327
|
+
...options.title !== void 0 ? { title: options.title } : {}
|
|
328
|
+
});
|
|
187
329
|
return ok(await toBytes(blob), MIME.xlsx, warnings);
|
|
188
330
|
}
|
|
189
331
|
};
|
|
@@ -192,21 +334,22 @@ function defaultFormats() {
|
|
|
192
334
|
label: "CSV",
|
|
193
335
|
mimeType: MIME.csv,
|
|
194
336
|
extensions: [".csv"],
|
|
195
|
-
async importDoc(data) {
|
|
337
|
+
async importDoc(data, options) {
|
|
196
338
|
const { csvToMarkdownDoc } = await import("./csv/index.js");
|
|
197
|
-
return csvToMarkdownDoc(data);
|
|
339
|
+
return csvToMarkdownDoc(data, optionsFor(options, "csv"));
|
|
198
340
|
},
|
|
199
|
-
async exportDoc(input) {
|
|
341
|
+
async exportDoc(input, options) {
|
|
200
342
|
const { markdownDocToCsv } = await import("./csv/index.js");
|
|
201
343
|
const markdownDoc = await markdownOf(input);
|
|
344
|
+
const raw = optionsFor(options, "csv");
|
|
202
345
|
const tableCount = markdownDoc.children.filter((n) => n.type === "table").length;
|
|
203
346
|
const warnings = [];
|
|
204
|
-
if (tableCount > 1) {
|
|
347
|
+
if (tableCount > 1 && raw.tableIndex === void 0) {
|
|
205
348
|
warnings.push(
|
|
206
349
|
`Document has ${tableCount} tables; CSV export emitted only the first. Use the csv converter's tableIndex option to select another.`
|
|
207
350
|
);
|
|
208
351
|
}
|
|
209
|
-
const text = markdownDocToCsv(markdownDoc);
|
|
352
|
+
const text = markdownDocToCsv(markdownDoc, raw);
|
|
210
353
|
return ok(new TextEncoder().encode(text), MIME.csv, warnings);
|
|
211
354
|
}
|
|
212
355
|
};
|
|
@@ -215,22 +358,26 @@ function defaultFormats() {
|
|
|
215
358
|
label: "HTML (single file)",
|
|
216
359
|
mimeType: MIME.html,
|
|
217
360
|
extensions: [".html", ".htm"],
|
|
218
|
-
async importDoc(data) {
|
|
361
|
+
async importDoc(data, options) {
|
|
219
362
|
const { htmlToMarkdownDoc } = await import("./html/index.js");
|
|
220
|
-
return htmlToMarkdownDoc(data);
|
|
363
|
+
return htmlToMarkdownDoc(data, optionsFor(options, "html"));
|
|
221
364
|
},
|
|
222
365
|
// importContainer omitted: HTML import already inlines images as data URIs,
|
|
223
366
|
// so there is nothing to extract into a container this wave.
|
|
224
367
|
async exportDoc(input, options) {
|
|
225
368
|
const playerScript = await requirePlayerScript(options, "html");
|
|
226
369
|
const { docToHtml } = await import("./html/index.js");
|
|
227
|
-
const
|
|
370
|
+
const raw = optionsFor(options, "html");
|
|
371
|
+
const containerImages = await collectContainerImages(input.container);
|
|
372
|
+
const images = new Map([...containerImages, ...raw.images ?? /* @__PURE__ */ new Map()]);
|
|
228
373
|
const htmlText = docToHtml(input.doc, {
|
|
374
|
+
...raw,
|
|
229
375
|
playerScript,
|
|
230
376
|
images,
|
|
231
377
|
title: options.title ?? input.baseName,
|
|
232
|
-
mode: "static",
|
|
233
|
-
themeId: resolveThemeId(input, options)
|
|
378
|
+
mode: raw.mode ?? "static",
|
|
379
|
+
themeId: resolveThemeId(input, options),
|
|
380
|
+
themeRegistry: options.themeRegistry ?? raw.themeRegistry
|
|
234
381
|
});
|
|
235
382
|
return ok(new TextEncoder().encode(htmlText), MIME.html);
|
|
236
383
|
}
|
|
@@ -243,13 +390,17 @@ function defaultFormats() {
|
|
|
243
390
|
async exportDoc(input, options) {
|
|
244
391
|
const playerScript = await requirePlayerScript(options, "htmlzip");
|
|
245
392
|
const { docToHtmlZip } = await import("./html/index.js");
|
|
246
|
-
const
|
|
393
|
+
const raw = optionsFor(options, "htmlzip");
|
|
394
|
+
const containerImages = await collectContainerImages(input.container);
|
|
395
|
+
const images = new Map([...containerImages, ...raw.images ?? /* @__PURE__ */ new Map()]);
|
|
247
396
|
const blob = await docToHtmlZip(input.doc, {
|
|
397
|
+
...raw,
|
|
248
398
|
playerScript,
|
|
249
399
|
images,
|
|
250
400
|
title: options.title ?? input.baseName,
|
|
251
|
-
mode: "static",
|
|
252
|
-
themeId: resolveThemeId(input, options)
|
|
401
|
+
mode: raw.mode ?? "static",
|
|
402
|
+
themeId: resolveThemeId(input, options),
|
|
403
|
+
themeRegistry: options.themeRegistry ?? raw.themeRegistry
|
|
253
404
|
});
|
|
254
405
|
return ok(await toBytes(blob), MIME.zip);
|
|
255
406
|
}
|
|
@@ -261,13 +412,18 @@ function defaultFormats() {
|
|
|
261
412
|
extensions: [".epub"],
|
|
262
413
|
async exportDoc(input, options) {
|
|
263
414
|
const { markdownDocToEpub } = await import("./epub/index.js");
|
|
264
|
-
const
|
|
265
|
-
const
|
|
415
|
+
const raw = optionsFor(options, "epub");
|
|
416
|
+
const markdownDoc = await markdownOf(input);
|
|
417
|
+
const containerImages = await collectContainerImages(input.container);
|
|
418
|
+
const images = new Map([...containerImages, ...raw.images ?? /* @__PURE__ */ new Map()]);
|
|
419
|
+
const buf = await markdownDocToEpub(markdownDoc, {
|
|
420
|
+
...raw,
|
|
266
421
|
title: options.title ?? input.baseName,
|
|
267
422
|
themeId: resolveThemeId(input, options),
|
|
423
|
+
themeRegistry: options.themeRegistry ?? raw.themeRegistry,
|
|
268
424
|
images
|
|
269
425
|
});
|
|
270
|
-
return ok(await toBytes(buf), MIME.epub);
|
|
426
|
+
return ok(await toBytes(buf), MIME.epub, markdownFidelityWarnings(markdownDoc, "epub"));
|
|
271
427
|
}
|
|
272
428
|
};
|
|
273
429
|
const dbk = {
|
|
@@ -275,13 +431,13 @@ function defaultFormats() {
|
|
|
275
431
|
label: "Squisq container (DBK)",
|
|
276
432
|
mimeType: MIME.zip,
|
|
277
433
|
extensions: [".dbk", ".zip"],
|
|
278
|
-
async importContainer(data) {
|
|
434
|
+
async importContainer(data, options) {
|
|
279
435
|
const { zipToContainer } = await import("./container/index.js");
|
|
280
|
-
return zipToContainer(data);
|
|
436
|
+
return zipToContainer(data, optionsFor(options, "dbk"));
|
|
281
437
|
},
|
|
282
438
|
async exportDoc(input) {
|
|
283
439
|
const { containerToZip } = await import("./container/index.js");
|
|
284
|
-
const blob = await containerToZip(input
|
|
440
|
+
const blob = await containerToZip(await snapshotContainerWithDocument(input));
|
|
285
441
|
return ok(await toBytes(blob), MIME.zip);
|
|
286
442
|
}
|
|
287
443
|
};
|
|
@@ -323,6 +479,9 @@ function defaultRegistry() {
|
|
|
323
479
|
}
|
|
324
480
|
|
|
325
481
|
// src/registry/convert.ts
|
|
482
|
+
function markdownFormatOptions(options) {
|
|
483
|
+
return options.formatOptions?.md ?? {};
|
|
484
|
+
}
|
|
326
485
|
function hasPrefix(bytes, prefix) {
|
|
327
486
|
if (bytes.length < prefix.length) return false;
|
|
328
487
|
for (let i = 0; i < prefix.length; i++) {
|
|
@@ -333,13 +492,19 @@ function hasPrefix(bytes, prefix) {
|
|
|
333
492
|
var ZIP_MAGIC = [80, 75, 3, 4];
|
|
334
493
|
var PDF_MAGIC = [37, 80, 68, 70];
|
|
335
494
|
async function sniffZip(bytes) {
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
throw new ConversionError("invalid-input", "Input is not a readable ZIP archive.");
|
|
495
|
+
const archive = await openBoundedZipArchive(bytes).catch((cause) => {
|
|
496
|
+
if (cause instanceof ZipSafetyError && cause.code !== "invalid-archive") throw cause;
|
|
497
|
+
throw new ConversionError("invalid-input", "Input is not a readable ZIP archive.", { cause });
|
|
339
498
|
});
|
|
340
|
-
const contentTypes =
|
|
499
|
+
const contentTypes = archive.entries.find((entry) => entry.path === "[Content_Types].xml");
|
|
341
500
|
if (!contentTypes) return "dbk";
|
|
342
|
-
const
|
|
501
|
+
const maxContentTypesBytes = 1024 * 1024;
|
|
502
|
+
if ((contentTypes.declaredSize ?? 0) > maxContentTypesBytes) {
|
|
503
|
+
throw new ConversionError("invalid-input", "OOXML content-types metadata is too large.");
|
|
504
|
+
}
|
|
505
|
+
const xmlBytes = await archive.read(contentTypes.path, maxContentTypesBytes);
|
|
506
|
+
if (!xmlBytes) return "dbk";
|
|
507
|
+
const xml = new TextDecoder().decode(xmlBytes);
|
|
343
508
|
if (xml.includes("wordprocessingml")) return "docx";
|
|
344
509
|
if (xml.includes("presentationml")) return "pptx";
|
|
345
510
|
if (xml.includes("spreadsheetml")) return "xlsx";
|
|
@@ -357,13 +522,15 @@ async function detectByteFormat(bytes, filename, options, registry) {
|
|
|
357
522
|
return "md";
|
|
358
523
|
}
|
|
359
524
|
function extractExt(filename) {
|
|
360
|
-
const
|
|
525
|
+
const normalized = filename.replace(/\\/g, "/");
|
|
526
|
+
const base = normalized.split("/").pop() ?? normalized;
|
|
361
527
|
const dot = base.lastIndexOf(".");
|
|
362
528
|
if (dot <= 0) return "";
|
|
363
529
|
return base.slice(dot + 1).toLowerCase();
|
|
364
530
|
}
|
|
365
531
|
function baseNameOf(filename) {
|
|
366
|
-
const
|
|
532
|
+
const normalized = filename.replace(/\\/g, "/");
|
|
533
|
+
const base = normalized.split("/").pop() ?? normalized;
|
|
367
534
|
const dot = base.lastIndexOf(".");
|
|
368
535
|
return dot > 0 ? base.slice(0, dot) : base;
|
|
369
536
|
}
|
|
@@ -403,7 +570,7 @@ async function normalizeBytes(source, options, registry) {
|
|
|
403
570
|
);
|
|
404
571
|
}
|
|
405
572
|
const text = await container.readDocument();
|
|
406
|
-
markdownDoc = text ? parseMarkdown(text) : { type: "document", children: [] };
|
|
573
|
+
markdownDoc = text ? parseMarkdown(text, markdownFormatOptions(options).parse) : { type: "document", children: [] };
|
|
407
574
|
} else {
|
|
408
575
|
markdownDoc = await fromDef.importDoc(buffer, options);
|
|
409
576
|
const { MemoryContentContainer } = await import("@bendyline/squisq/storage");
|
|
@@ -422,7 +589,7 @@ async function normalizeMarkdown(source, options) {
|
|
|
422
589
|
const { markdownToDoc } = await import("@bendyline/squisq/doc");
|
|
423
590
|
const { parseMarkdown } = await import("@bendyline/squisq/markdown");
|
|
424
591
|
const { stringifyMarkdown } = await import("@bendyline/squisq/markdown");
|
|
425
|
-
const markdownDoc = typeof source.markdown === "string" ? parseMarkdown(source.markdown) : source.markdown;
|
|
592
|
+
const markdownDoc = typeof source.markdown === "string" ? parseMarkdown(source.markdown, markdownFormatOptions(options).parse) : source.markdown;
|
|
426
593
|
let container = source.container;
|
|
427
594
|
if (!container) {
|
|
428
595
|
const { MemoryContentContainer } = await import("@bendyline/squisq/storage");
|
|
@@ -457,11 +624,11 @@ async function normalize(source, options, registry) {
|
|
|
457
624
|
return normalizeDoc(source);
|
|
458
625
|
}
|
|
459
626
|
}
|
|
460
|
-
async function applyTransformStyle(input, transformStyle, themeId) {
|
|
627
|
+
async function applyTransformStyle(input, transformStyle, themeId, registry) {
|
|
461
628
|
const { applyTransform, extractDocImages } = await import("@bendyline/squisq/transform");
|
|
462
629
|
const { docToMarkdown, markdownToDoc } = await import("@bendyline/squisq/doc");
|
|
463
630
|
const images = extractDocImages(input.doc.blocks);
|
|
464
|
-
const result = applyTransform(input.doc, transformStyle, { themeId, images });
|
|
631
|
+
const result = applyTransform(input.doc, transformStyle, { themeId, images, registry });
|
|
465
632
|
input.doc = result.doc;
|
|
466
633
|
const markdownDoc = docToMarkdown(result.doc);
|
|
467
634
|
input.markdownDoc = markdownDoc;
|
|
@@ -486,21 +653,33 @@ async function convert(source, to, options = {}) {
|
|
|
486
653
|
{ format: to, hint: "This format is import-only." }
|
|
487
654
|
);
|
|
488
655
|
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
656
|
+
let normalized;
|
|
657
|
+
try {
|
|
658
|
+
normalized = await normalize(source, options, registry);
|
|
659
|
+
} catch (err) {
|
|
660
|
+
if (err instanceof ConversionError) throw err;
|
|
661
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
662
|
+
throw new ConversionError("invalid-input", message, {
|
|
663
|
+
format: options.from,
|
|
664
|
+
cause: err
|
|
665
|
+
});
|
|
492
666
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
input,
|
|
497
|
-
options.transformStyle,
|
|
498
|
-
options.themeId ?? input.doc.themeId
|
|
499
|
-
)
|
|
500
|
-
);
|
|
667
|
+
const { input, warnings } = normalized;
|
|
668
|
+
if (options.themeId && !input.doc.themeId) {
|
|
669
|
+
input.doc = { ...input.doc, themeId: options.themeId };
|
|
501
670
|
}
|
|
502
671
|
let result;
|
|
503
672
|
try {
|
|
673
|
+
if (options.transformStyle) {
|
|
674
|
+
warnings.push(
|
|
675
|
+
...await applyTransformStyle(
|
|
676
|
+
input,
|
|
677
|
+
options.transformStyle,
|
|
678
|
+
options.themeId ?? input.doc.themeId,
|
|
679
|
+
options.transformRegistry
|
|
680
|
+
)
|
|
681
|
+
);
|
|
682
|
+
}
|
|
504
683
|
result = await target.exportDoc(input, options);
|
|
505
684
|
} catch (err) {
|
|
506
685
|
if (err instanceof ConversionError) throw err;
|
|
@@ -517,10 +696,9 @@ async function convert(source, to, options = {}) {
|
|
|
517
696
|
|
|
518
697
|
export {
|
|
519
698
|
BUILTIN_FORMAT_IDS,
|
|
520
|
-
ConversionError,
|
|
521
699
|
defaultFormats,
|
|
522
700
|
createRegistry,
|
|
523
701
|
defaultRegistry,
|
|
524
702
|
convert
|
|
525
703
|
};
|
|
526
|
-
//# sourceMappingURL=chunk-
|
|
704
|
+
//# sourceMappingURL=chunk-2EFDWKC6.js.map
|