@bendyline/squisq-formats 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/NOTICE.md +20 -0
- package/README.md +1 -1
- package/dist/{chunk-NNHKUXKA.js → chunk-26ISNJ7Y.js} +85 -65
- package/dist/{chunk-NKAJPJ4G.js → chunk-2JJ5RFDZ.js} +0 -1
- package/dist/{chunk-WQSHGBLN.js → chunk-3NKXBZSR.js} +193 -42
- package/dist/{chunk-KURGXM4I.js → chunk-4V3KCHAP.js} +3 -4
- package/dist/{chunk-MLX2BOJC.js → chunk-6RQOV3B3.js} +1 -2
- package/dist/{chunk-EW54IRRS.js → chunk-6S6GU3ZG.js} +5 -6
- package/dist/{chunk-FE6OJV6O.js → chunk-7AWFHP5U.js} +1 -1
- package/dist/{chunk-RFAPOKHJ.js → chunk-AD2WT564.js} +59 -9
- package/dist/{chunk-O3GVVND4.js → chunk-AONELFLA.js} +0 -1
- package/dist/{chunk-SC67HYQJ.js → chunk-EJTNGKEA.js} +5 -8
- package/dist/chunk-GX7RAUME.js +121 -0
- package/dist/{chunk-SSUPBUF5.js → chunk-IIQYS2YH.js} +0 -1
- package/dist/{chunk-RLU7UFYU.js → chunk-IPN56VLW.js} +83 -58
- package/dist/{chunk-DTDF6QDP.js → chunk-JE6LSIHE.js} +81 -20
- package/dist/{chunk-U4MRIFKL.js → chunk-JU2RHXUB.js} +0 -1
- package/dist/{chunk-4VUWTSGM.js → chunk-K6XRMVPW.js} +64 -31
- package/dist/{chunk-ODL3SSPT.js → chunk-KXOZMWBS.js} +0 -1
- package/dist/chunk-OGS5VCGJ.js +446 -0
- package/dist/{chunk-GVS2XXV6.js → chunk-PJXJI2LY.js} +449 -57
- package/dist/{chunk-74GO3FVS.js → chunk-PU7REGWV.js} +5 -8
- package/dist/{chunk-PN52A5AA.js → chunk-SBUW7NHR.js} +0 -1
- package/dist/{chunk-QFLDYKCR.js → chunk-TAAENIRB.js} +5 -8
- package/dist/{chunk-7ARKUCQT.js → chunk-X2DEAXNK.js} +54 -2
- package/dist/container/index.js +1 -2
- package/dist/csv/index.d.ts +27 -2
- package/dist/csv/index.js +1 -2
- package/dist/docx/index.d.ts +5 -1
- package/dist/docx/index.js +9 -11
- package/dist/epub/index.d.ts +2 -0
- package/dist/epub/index.js +5 -6
- package/dist/{export-D2NkylDT.d.ts → export-D9msROJS.d.ts} +18 -6
- package/dist/extract-MN7LA3NL.js +13 -0
- package/dist/html/index.d.ts +11 -4
- package/dist/html/index.js +3 -4
- package/dist/images-ESPQKVTW.js +6 -0
- package/dist/{import-K8mfc0fz.d.ts → import-C3htUTss.d.ts} +5 -1
- package/dist/{import-DTkDxHmZ.d.ts → import-C8whCC7_.d.ts} +6 -0
- package/dist/index.d.ts +7 -7
- package/dist/index.js +28 -26
- package/dist/infer/index.d.ts +3 -3
- package/dist/infer/index.js +7 -9
- package/dist/{layouts-BHrgZ5FS.d.ts → layouts-CTdPlB-u.d.ts} +1 -1
- package/dist/layouts-DRWZGSPD.js +10 -0
- package/dist/{mapTheme-IR27S6IV.js → mapTheme-4TWH25FT.js} +1 -2
- package/dist/ooxml/index.d.ts +3 -3
- package/dist/ooxml/index.js +14 -13
- package/dist/pdf/index.d.ts +18 -0
- package/dist/pdf/index.js +2 -3
- package/dist/pptx/index.d.ts +4 -4
- package/dist/pptx/index.js +11 -13
- package/dist/{reader-B9L8Ucbj.d.ts → reader-B_m1aKZC.d.ts} +30 -1
- package/dist/registry/index.d.ts +21 -5
- package/dist/registry/index.js +9 -6
- package/dist/{themeReader-DJKErl_j.d.ts → themeReader-DCtwC83Q.d.ts} +1 -1
- package/dist/xlsx/index.d.ts +3 -3
- package/dist/xlsx/index.js +6 -7
- package/package.json +6 -3
- package/dist/chunk-4VUWTSGM.js.map +0 -1
- package/dist/chunk-6M7Z25LA.js +0 -46
- package/dist/chunk-6M7Z25LA.js.map +0 -1
- package/dist/chunk-74GO3FVS.js.map +0 -1
- package/dist/chunk-7ARKUCQT.js.map +0 -1
- package/dist/chunk-DTDF6QDP.js.map +0 -1
- package/dist/chunk-EW54IRRS.js.map +0 -1
- package/dist/chunk-FE6OJV6O.js.map +0 -1
- package/dist/chunk-GVS2XXV6.js.map +0 -1
- package/dist/chunk-KURGXM4I.js.map +0 -1
- package/dist/chunk-MLX2BOJC.js.map +0 -1
- package/dist/chunk-NKAJPJ4G.js.map +0 -1
- package/dist/chunk-NNHKUXKA.js.map +0 -1
- package/dist/chunk-O3GVVND4.js.map +0 -1
- package/dist/chunk-ODL3SSPT.js.map +0 -1
- package/dist/chunk-PN52A5AA.js.map +0 -1
- package/dist/chunk-QFLDYKCR.js.map +0 -1
- package/dist/chunk-RFAPOKHJ.js.map +0 -1
- package/dist/chunk-RLU7UFYU.js.map +0 -1
- package/dist/chunk-SC67HYQJ.js.map +0 -1
- package/dist/chunk-SSUPBUF5.js.map +0 -1
- package/dist/chunk-U4MRIFKL.js.map +0 -1
- package/dist/chunk-UGYF5AZE.js +0 -275
- package/dist/chunk-UGYF5AZE.js.map +0 -1
- package/dist/chunk-WQSHGBLN.js.map +0 -1
- package/dist/chunk-YRT7GQ5Y.js +0 -28
- package/dist/chunk-YRT7GQ5Y.js.map +0 -1
- package/dist/container/index.js.map +0 -1
- package/dist/csv/index.js.map +0 -1
- package/dist/docx/index.js.map +0 -1
- package/dist/epub/index.js.map +0 -1
- package/dist/extract-OJ7ZQV6P.js +0 -15
- package/dist/extract-OJ7ZQV6P.js.map +0 -1
- package/dist/html/index.js.map +0 -1
- package/dist/images-7FBWPKE3.js +0 -7
- package/dist/images-7FBWPKE3.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/infer/index.js.map +0 -1
- package/dist/layouts-5VDIRPIJ.js +0 -12
- package/dist/layouts-5VDIRPIJ.js.map +0 -1
- package/dist/mapTheme-IR27S6IV.js.map +0 -1
- package/dist/ooxml/index.js.map +0 -1
- package/dist/pdf/index.js.map +0 -1
- package/dist/pptx/index.js.map +0 -1
- package/dist/registry/index.js.map +0 -1
- package/dist/xlsx/index.js.map +0 -1
- package/src/__tests__/container.test.ts +0 -230
- package/src/__tests__/convert.test.ts +0 -495
- package/src/__tests__/csvImport.test.ts +0 -84
- package/src/__tests__/docxExport.test.ts +0 -491
- package/src/__tests__/docxImport.test.ts +0 -531
- package/src/__tests__/epub.test.ts +0 -649
- package/src/__tests__/exportThemeReconciliation.test.ts +0 -87
- package/src/__tests__/formatRegistry.test.ts +0 -174
- package/src/__tests__/html.test.ts +0 -439
- package/src/__tests__/htmlImport.test.ts +0 -57
- package/src/__tests__/inferTheme.test.ts +0 -135
- package/src/__tests__/lossyWarnings.test.ts +0 -146
- package/src/__tests__/ooxml.test.ts +0 -271
- package/src/__tests__/ooxmlCancellation.test.ts +0 -113
- package/src/__tests__/ooxmlThemeReader.test.ts +0 -92
- package/src/__tests__/pdfExport.test.ts +0 -322
- package/src/__tests__/pdfImport.test.ts +0 -384
- package/src/__tests__/plainHtml.test.ts +0 -417
- package/src/__tests__/plainHtmlBundle.test.ts +0 -253
- package/src/__tests__/pptxExport.test.ts +0 -138
- package/src/__tests__/pptxImport.test.ts +0 -145
- package/src/__tests__/pptxInferFixtures.ts +0 -314
- package/src/__tests__/pptxLayoutInfer.test.ts +0 -395
- package/src/__tests__/roundTrip.test.ts +0 -201
- package/src/__tests__/roundTripAssets.test.ts +0 -50
- package/src/__tests__/roundTripMatrix.fixtures.ts +0 -86
- package/src/__tests__/roundTripMatrix.helpers.ts +0 -154
- package/src/__tests__/roundTripMatrix.test.ts +0 -142
- package/src/__tests__/sharedContainer.test.ts +0 -41
- package/src/__tests__/sharedImages.test.ts +0 -61
- package/src/__tests__/xlsxExport.test.ts +0 -164
- package/src/__tests__/xlsxImport.test.ts +0 -80
- package/src/__tests__/zipSafety.test.ts +0 -317
- package/src/container/index.ts +0 -94
- package/src/csv/index.ts +0 -188
- package/src/docx/export.ts +0 -1375
- package/src/docx/import.ts +0 -1250
- package/src/docx/index.ts +0 -26
- package/src/docx/styles.ts +0 -145
- package/src/epub/export.ts +0 -968
- package/src/epub/index.ts +0 -20
- package/src/html/docsHtmlBundle.ts +0 -373
- package/src/html/htmlTemplate.ts +0 -385
- package/src/html/imageUtils.ts +0 -61
- package/src/html/import.ts +0 -297
- package/src/html/index.ts +0 -212
- package/src/html/plainHtml.ts +0 -790
- package/src/html/plainHtmlBundle.ts +0 -421
- package/src/index.ts +0 -109
- package/src/infer/extract.ts +0 -127
- package/src/infer/index.ts +0 -199
- package/src/infer/mapTheme.ts +0 -176
- package/src/infer/types.ts +0 -27
- package/src/ooxml/index.ts +0 -111
- package/src/ooxml/namespaces.ts +0 -217
- package/src/ooxml/readUtils.ts +0 -44
- package/src/ooxml/reader.ts +0 -318
- package/src/ooxml/themeReader.ts +0 -197
- package/src/ooxml/types.ts +0 -103
- package/src/ooxml/writer.ts +0 -339
- package/src/ooxml/xmlUtils.ts +0 -123
- package/src/pdf/export.ts +0 -1084
- package/src/pdf/import.ts +0 -1164
- package/src/pdf/index.ts +0 -29
- package/src/pdf/styles.ts +0 -180
- package/src/pptx/export.ts +0 -1184
- package/src/pptx/import.ts +0 -455
- package/src/pptx/index.ts +0 -52
- package/src/pptx/layouts.ts +0 -1222
- package/src/pptx/styles.ts +0 -96
- package/src/pptx/templates.ts +0 -187
- package/src/registry/convert.ts +0 -433
- package/src/registry/defaultFormats.ts +0 -413
- package/src/registry/errors.ts +0 -46
- package/src/registry/index.ts +0 -43
- package/src/registry/registry.ts +0 -48
- package/src/registry/types.ts +0 -170
- package/src/shared/boundedZipArchive.ts +0 -383
- package/src/shared/container.ts +0 -28
- package/src/shared/fidelity.ts +0 -130
- package/src/shared/images.ts +0 -44
- package/src/shared/inlineRuns.ts +0 -99
- package/src/shared/text.ts +0 -41
- package/src/shared/zipEntryCount.ts +0 -151
- package/src/shared/zipLimits.ts +0 -296
- package/src/shared/zipSafety.ts +0 -19
- package/src/xlsx/export.ts +0 -253
- package/src/xlsx/import.ts +0 -160
- package/src/xlsx/index.ts +0 -35
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
baseDirOf,
|
|
3
|
-
findRelByType,
|
|
4
|
-
resolveTarget
|
|
5
|
-
} from "./chunk-YRT7GQ5Y.js";
|
|
6
1
|
import {
|
|
7
2
|
NS_DRAWINGML,
|
|
8
3
|
REL_THEME,
|
|
4
|
+
baseDirOf,
|
|
5
|
+
findRelByType,
|
|
9
6
|
getPartRelationships,
|
|
10
|
-
getPartXml
|
|
11
|
-
|
|
7
|
+
getPartXml,
|
|
8
|
+
resolveTarget
|
|
9
|
+
} from "./chunk-X2DEAXNK.js";
|
|
12
10
|
|
|
13
11
|
// src/ooxml/themeReader.ts
|
|
14
12
|
var HEX6_RE = /^[0-9a-fA-F]{6}$/;
|
|
@@ -128,4 +126,3 @@ export {
|
|
|
128
126
|
parseThemeXml,
|
|
129
127
|
readThemePart
|
|
130
128
|
};
|
|
131
|
-
//# sourceMappingURL=chunk-SC67HYQJ.js.map
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import {
|
|
2
|
+
stripHtmlTags
|
|
3
|
+
} from "./chunk-SBUW7NHR.js";
|
|
4
|
+
|
|
5
|
+
// src/ooxml/relIds.ts
|
|
6
|
+
var RelIdAllocator = class {
|
|
7
|
+
constructor() {
|
|
8
|
+
/** part path → next free numeric suffix */
|
|
9
|
+
this.next = /* @__PURE__ */ new Map();
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Allocate the next free relationship id for `part`'s rels file.
|
|
13
|
+
*
|
|
14
|
+
* @param part - Zip path of the part that owns the relationship
|
|
15
|
+
* (e.g. `"word/document.xml"`). Use `""` for the package root.
|
|
16
|
+
* Ids are only unique per `part`, which is exactly the OOXML rule.
|
|
17
|
+
*/
|
|
18
|
+
alloc(part = "") {
|
|
19
|
+
const n = this.next.get(part) ?? 1;
|
|
20
|
+
this.next.set(part, n + 1);
|
|
21
|
+
return `rId${n}`;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// src/shared/ooxmlColor.ts
|
|
26
|
+
var HEX3_RE = /^#?([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])$/;
|
|
27
|
+
var HEX6_RE = /^#?([0-9a-fA-F]{6})$/;
|
|
28
|
+
var HEX8_RE = /^#?([0-9a-fA-F]{6})[0-9a-fA-F]{2}$/;
|
|
29
|
+
function toOoxmlHex(color, fallback = "000000") {
|
|
30
|
+
const normalized = normalizeOoxmlHex(color);
|
|
31
|
+
if (normalized) return normalized;
|
|
32
|
+
return normalizeOoxmlHex(fallback) ?? "000000";
|
|
33
|
+
}
|
|
34
|
+
function normalizeOoxmlHex(color) {
|
|
35
|
+
if (typeof color !== "string") return void 0;
|
|
36
|
+
const trimmed = color.trim();
|
|
37
|
+
const six = HEX6_RE.exec(trimmed);
|
|
38
|
+
if (six) return six[1].toUpperCase();
|
|
39
|
+
const eight = HEX8_RE.exec(trimmed);
|
|
40
|
+
if (eight) return eight[1].toUpperCase();
|
|
41
|
+
const three = HEX3_RE.exec(trimmed);
|
|
42
|
+
if (three) {
|
|
43
|
+
const [, r, g, b] = three;
|
|
44
|
+
return `${r}${r}${g}${g}${b}${b}`.toUpperCase();
|
|
45
|
+
}
|
|
46
|
+
return void 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/shared/officeHyperlinks.ts
|
|
50
|
+
import { sanitizeUrl } from "@bendyline/squisq/markdown";
|
|
51
|
+
function sanitizeOfficeHyperlink(input, policy = {}) {
|
|
52
|
+
if (typeof input !== "string") return null;
|
|
53
|
+
const value = input.trim();
|
|
54
|
+
if (!value || hasControls(value)) return null;
|
|
55
|
+
if (value.startsWith("#")) return /^#[^\s]*$/.test(value) ? value : null;
|
|
56
|
+
if (/^(?:\\\\|\/\/|\/|[a-z]:[\\/])/i.test(value)) return null;
|
|
57
|
+
const hasScheme = /^[a-z][a-z0-9+.-]*:/i.test(value);
|
|
58
|
+
if (hasScheme) return sanitizeUrl(value);
|
|
59
|
+
if (!policy.allowRelative || value.includes("\\")) return null;
|
|
60
|
+
let decoded;
|
|
61
|
+
try {
|
|
62
|
+
decoded = decodeURIComponent(value);
|
|
63
|
+
} catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
if (hasControls(decoded) || decoded.includes("\\") || decoded.startsWith("//")) return null;
|
|
67
|
+
return value;
|
|
68
|
+
}
|
|
69
|
+
function hasControls(value) {
|
|
70
|
+
for (const char of value) {
|
|
71
|
+
const code = char.charCodeAt(0);
|
|
72
|
+
if (code <= 31 || code === 127) return true;
|
|
73
|
+
}
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/shared/inlineRuns.ts
|
|
78
|
+
function inlineNodesToRuns(nodes, handlers, format = {}) {
|
|
79
|
+
let out = "";
|
|
80
|
+
for (const node of nodes) {
|
|
81
|
+
out += inlineNodeToRuns(node, handlers, format);
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
function inlineNodeToRuns(node, handlers, format) {
|
|
86
|
+
switch (node.type) {
|
|
87
|
+
case "text":
|
|
88
|
+
return handlers.run(node.value, format);
|
|
89
|
+
case "strong":
|
|
90
|
+
return inlineNodesToRuns(node.children, handlers, { ...format, bold: true });
|
|
91
|
+
case "emphasis":
|
|
92
|
+
return inlineNodesToRuns(node.children, handlers, { ...format, italic: true });
|
|
93
|
+
case "delete":
|
|
94
|
+
return inlineNodesToRuns(node.children, handlers, { ...format, strike: true });
|
|
95
|
+
case "inlineCode":
|
|
96
|
+
return handlers.run(node.value, { ...format, code: true });
|
|
97
|
+
case "inlineMath":
|
|
98
|
+
return handlers.run(node.value, { ...format, code: true });
|
|
99
|
+
case "htmlInline":
|
|
100
|
+
return handlers.run(stripHtmlTags(node.rawHtml), format);
|
|
101
|
+
case "link":
|
|
102
|
+
return handlers.link(node, format);
|
|
103
|
+
case "image":
|
|
104
|
+
return handlers.image(node, format);
|
|
105
|
+
case "break":
|
|
106
|
+
return handlers.lineBreak();
|
|
107
|
+
case "footnoteReference":
|
|
108
|
+
return handlers.footnoteRef ? handlers.footnoteRef(node) : "";
|
|
109
|
+
default:
|
|
110
|
+
return "";
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export {
|
|
115
|
+
RelIdAllocator,
|
|
116
|
+
toOoxmlHex,
|
|
117
|
+
normalizeOoxmlHex,
|
|
118
|
+
sanitizeOfficeHyperlink,
|
|
119
|
+
inlineNodesToRuns,
|
|
120
|
+
inlineNodeToRuns
|
|
121
|
+
};
|
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
|
+
RelIdAllocator,
|
|
2
3
|
inlineNodeToRuns,
|
|
3
|
-
inlineNodesToRuns
|
|
4
|
-
|
|
4
|
+
inlineNodesToRuns,
|
|
5
|
+
sanitizeOfficeHyperlink,
|
|
6
|
+
toOoxmlHex
|
|
7
|
+
} from "./chunk-GX7RAUME.js";
|
|
5
8
|
import {
|
|
6
9
|
extractPlainText,
|
|
7
10
|
stripHtmlTags
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import {
|
|
10
|
-
attrNS,
|
|
11
|
-
baseDirOf,
|
|
12
|
-
resolveTarget
|
|
13
|
-
} from "./chunk-YRT7GQ5Y.js";
|
|
11
|
+
} from "./chunk-SBUW7NHR.js";
|
|
14
12
|
import {
|
|
15
13
|
createPackage
|
|
16
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-4V3KCHAP.js";
|
|
17
15
|
import {
|
|
18
16
|
escapeXml,
|
|
19
17
|
xmlDeclaration
|
|
20
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-JU2RHXUB.js";
|
|
21
19
|
import {
|
|
22
20
|
CONTENT_TYPE_PPTX_PRESENTATION,
|
|
23
21
|
CONTENT_TYPE_PPTX_SLIDE,
|
|
@@ -36,20 +34,24 @@ import {
|
|
|
36
34
|
REL_SLIDE_LAYOUT,
|
|
37
35
|
REL_SLIDE_MASTER,
|
|
38
36
|
REL_THEME,
|
|
37
|
+
attrNS,
|
|
38
|
+
baseDirOf,
|
|
39
39
|
getPartBinary,
|
|
40
40
|
getPartRelationships,
|
|
41
41
|
getPartXml,
|
|
42
|
-
openPackage
|
|
43
|
-
|
|
42
|
+
openPackage,
|
|
43
|
+
requireMainPartPath,
|
|
44
|
+
resolveTarget
|
|
45
|
+
} from "./chunk-X2DEAXNK.js";
|
|
44
46
|
import {
|
|
45
47
|
buildContainer
|
|
46
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-IIQYS2YH.js";
|
|
47
49
|
import {
|
|
48
50
|
inferMimeType
|
|
49
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-6RQOV3B3.js";
|
|
50
52
|
import {
|
|
51
53
|
extToMime
|
|
52
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-AONELFLA.js";
|
|
53
55
|
|
|
54
56
|
// src/pptx/export.ts
|
|
55
57
|
import { resolveFontFamily } from "@bendyline/squisq/schemas";
|
|
@@ -94,6 +96,7 @@ function buildThemeXml() {
|
|
|
94
96
|
|
|
95
97
|
// src/pptx/export.ts
|
|
96
98
|
async function markdownDocToPptx(doc, options = {}) {
|
|
99
|
+
options.signal?.throwIfAborted();
|
|
97
100
|
const themeId = options.themeId ?? readFrontmatterThemeId(doc.frontmatter);
|
|
98
101
|
const style = resolveSlideStyle(themeId, options, doc);
|
|
99
102
|
const slides = segmentIntoSlides(doc.children, options.slideBreak ?? "h2");
|
|
@@ -103,7 +106,14 @@ async function markdownDocToPptx(doc, options = {}) {
|
|
|
103
106
|
const slideXmls = [];
|
|
104
107
|
const slideContexts = [];
|
|
105
108
|
for (let i = 0; i < slides.length; i++) {
|
|
106
|
-
|
|
109
|
+
if ((i & 31) === 0) options.signal?.throwIfAborted();
|
|
110
|
+
const ctx = new SlideContext(
|
|
111
|
+
style,
|
|
112
|
+
options.images,
|
|
113
|
+
i,
|
|
114
|
+
options.allowRelativeHyperlinks ?? false,
|
|
115
|
+
options.signal
|
|
116
|
+
);
|
|
107
117
|
const xml = buildSlideXml(slides[i], ctx);
|
|
108
118
|
slideXmls.push(xml);
|
|
109
119
|
slideContexts.push(ctx);
|
|
@@ -134,20 +144,17 @@ function resolveSlideStyle(themeId, options, doc) {
|
|
|
134
144
|
const theme = resolveThemeForDoc(doc, themeId, options.themeRegistry);
|
|
135
145
|
const c = theme.colors;
|
|
136
146
|
return {
|
|
137
|
-
background:
|
|
138
|
-
text:
|
|
139
|
-
titleColor:
|
|
140
|
-
mutedColor:
|
|
147
|
+
background: toOoxmlHex(c.background, "FFFFFF"),
|
|
148
|
+
text: toOoxmlHex(c.text, "333333"),
|
|
149
|
+
titleColor: toOoxmlHex(c.highlight || c.secondary || c.text, "333333"),
|
|
150
|
+
mutedColor: toOoxmlHex(c.textMuted || c.text, "666666"),
|
|
141
151
|
titleFont: resolveFontFamily(theme.typography?.titleFont, DEFAULT_TITLE_FONT),
|
|
142
152
|
bodyFont: resolveFontFamily(theme.typography?.bodyFont, options.defaultFont || DEFAULT_FONT),
|
|
143
153
|
codeFont: resolveFontFamily(theme.typography?.monoFont, DEFAULT_CODE_FONT),
|
|
144
|
-
codeColor:
|
|
154
|
+
codeColor: toOoxmlHex(c.textMuted || c.text, "333333"),
|
|
145
155
|
hasTheme: true
|
|
146
156
|
};
|
|
147
157
|
}
|
|
148
|
-
function stripHash(color) {
|
|
149
|
-
return color.startsWith("#") ? color.slice(1) : color;
|
|
150
|
-
}
|
|
151
158
|
function segmentIntoSlides(children, slideBreak) {
|
|
152
159
|
const maxDepth = slideBreak === "h1" ? 1 : slideBreak === "h2" ? 2 : 6;
|
|
153
160
|
const slides = [];
|
|
@@ -172,28 +179,44 @@ function segmentIntoSlides(children, slideBreak) {
|
|
|
172
179
|
return slides;
|
|
173
180
|
}
|
|
174
181
|
var SlideContext = class {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
182
|
+
constructor(style, images, slideIndex, allowRelativeHyperlinks, signal) {
|
|
183
|
+
/**
|
|
184
|
+
* One id source for this slide's rels part — see `RelIdAllocator`. There is
|
|
185
|
+
* exactly one SlideContext per `ppt/slides/slideN.xml`, and EVERY rel on
|
|
186
|
+
* that part (layout, hyperlinks, images) is allocated here, so duplicate
|
|
187
|
+
* `Id`s are impossible by construction.
|
|
188
|
+
*/
|
|
189
|
+
this.relIds = new RelIdAllocator();
|
|
178
190
|
this.relationships = [];
|
|
179
191
|
this.embeddedImages = [];
|
|
180
192
|
this.nextShapeId = 4;
|
|
181
193
|
this.style = style;
|
|
182
194
|
this.images = images;
|
|
183
195
|
this.slideIndex = slideIndex;
|
|
196
|
+
this.allowRelativeHyperlinks = allowRelativeHyperlinks;
|
|
197
|
+
this.signal = signal;
|
|
198
|
+
this.relationships.push({
|
|
199
|
+
id: this.allocRelId(),
|
|
200
|
+
type: REL_SLIDE_LAYOUT,
|
|
201
|
+
target: "../slideLayouts/slideLayout1.xml"
|
|
202
|
+
});
|
|
184
203
|
}
|
|
185
204
|
allocRelId() {
|
|
186
|
-
return
|
|
205
|
+
return this.relIds.alloc();
|
|
187
206
|
}
|
|
188
207
|
allocShapeId() {
|
|
189
208
|
return this.nextShapeId++;
|
|
190
209
|
}
|
|
191
210
|
addHyperlink(url) {
|
|
211
|
+
const target = sanitizeOfficeHyperlink(url, {
|
|
212
|
+
allowRelative: this.allowRelativeHyperlinks
|
|
213
|
+
});
|
|
214
|
+
if (!target) return null;
|
|
192
215
|
const id = this.allocRelId();
|
|
193
216
|
this.relationships.push({
|
|
194
217
|
id,
|
|
195
218
|
type: REL_HYPERLINK,
|
|
196
|
-
target
|
|
219
|
+
target,
|
|
197
220
|
targetMode: "External"
|
|
198
221
|
});
|
|
199
222
|
return id;
|
|
@@ -556,7 +579,7 @@ function convertCodeBlock(node, ctx) {
|
|
|
556
579
|
const parts = [];
|
|
557
580
|
for (const line of lines) {
|
|
558
581
|
parts.push(
|
|
559
|
-
`<a:p><a:r><a:rPr lang="en-US" sz="${DEFAULT_CODE_SIZE}" dirty="0"><a:
|
|
582
|
+
`<a:p><a:r><a:rPr lang="en-US" sz="${DEFAULT_CODE_SIZE}" dirty="0"><a:solidFill><a:srgbClr val="${ctx.style.codeColor}"/></a:solidFill><a:latin typeface="${escapeXml(ctx.style.codeFont)}"/></a:rPr><a:t>${escapeXml(line || " ")}</a:t></a:r></a:p>`
|
|
560
583
|
);
|
|
561
584
|
}
|
|
562
585
|
return parts.join("");
|
|
@@ -611,8 +634,8 @@ function makeRun(text, format, style) {
|
|
|
611
634
|
if (format.strike) rPrParts.push(`strike="sngStrike"`);
|
|
612
635
|
let innerParts = "";
|
|
613
636
|
if (format.code) {
|
|
614
|
-
innerParts += `<a:latin typeface="${escapeXml(style.codeFont)}"/>`;
|
|
615
637
|
innerParts += `<a:solidFill><a:srgbClr val="${style.codeColor}"/></a:solidFill>`;
|
|
638
|
+
innerParts += `<a:latin typeface="${escapeXml(style.codeFont)}"/>`;
|
|
616
639
|
rPrParts.push(`sz="${DEFAULT_CODE_SIZE}"`);
|
|
617
640
|
} else if (style.hasTheme) {
|
|
618
641
|
innerParts += `<a:solidFill><a:srgbClr val="${style.text}"/></a:solidFill>`;
|
|
@@ -621,6 +644,7 @@ function makeRun(text, format, style) {
|
|
|
621
644
|
}
|
|
622
645
|
function convertLink(node, ctx, format) {
|
|
623
646
|
const rId = ctx.addHyperlink(node.url);
|
|
647
|
+
if (!rId) return convertInlines(node.children, ctx, format);
|
|
624
648
|
const parts = [];
|
|
625
649
|
for (const child of node.children) {
|
|
626
650
|
if (child.type === "text") {
|
|
@@ -652,12 +676,16 @@ function convertImage(node, format, ctx) {
|
|
|
652
676
|
async function buildPptxPackage(slideXmls, slideContexts, options) {
|
|
653
677
|
const pkg = createPackage();
|
|
654
678
|
const slideCount = slideXmls.length;
|
|
655
|
-
const
|
|
656
|
-
const
|
|
679
|
+
const relIds = new RelIdAllocator();
|
|
680
|
+
const PRESENTATION_PART = "ppt/presentation.xml";
|
|
681
|
+
const SLIDE_MASTER_PART = "ppt/slideMasters/slideMaster1.xml";
|
|
682
|
+
const SLIDE_LAYOUT_PART = "ppt/slideLayouts/slideLayout1.xml";
|
|
657
683
|
const slideRelIds = [];
|
|
658
684
|
for (let i = 0; i < slideCount; i++) {
|
|
659
|
-
slideRelIds.push(
|
|
685
|
+
slideRelIds.push(relIds.alloc(PRESENTATION_PART));
|
|
660
686
|
}
|
|
687
|
+
const slideMasterRelId = relIds.alloc(PRESENTATION_PART);
|
|
688
|
+
const themeRelId = relIds.alloc(PRESENTATION_PART);
|
|
661
689
|
const presentationXml = buildPresentationXml(
|
|
662
690
|
slideCount,
|
|
663
691
|
slideRelIds,
|
|
@@ -668,11 +696,6 @@ async function buildPptxPackage(slideXmls, slideContexts, options) {
|
|
|
668
696
|
for (let i = 0; i < slideCount; i++) {
|
|
669
697
|
const slidePath = `ppt/slides/slide${i + 1}.xml`;
|
|
670
698
|
pkg.addPart(slidePath, slideXmls[i], CONTENT_TYPE_PPTX_SLIDE);
|
|
671
|
-
pkg.addRelationship(slidePath, {
|
|
672
|
-
id: "rId1",
|
|
673
|
-
type: REL_SLIDE_LAYOUT,
|
|
674
|
-
target: "../slideLayouts/slideLayout1.xml"
|
|
675
|
-
});
|
|
676
699
|
const ctx = slideContexts[i];
|
|
677
700
|
for (const rel of ctx.relationships) {
|
|
678
701
|
pkg.addRelationship(slidePath, {
|
|
@@ -686,24 +709,24 @@ async function buildPptxPackage(slideXmls, slideContexts, options) {
|
|
|
686
709
|
pkg.addBinaryPart(img.mediaPath, img.data, img.contentType);
|
|
687
710
|
}
|
|
688
711
|
}
|
|
689
|
-
const layoutMasterRelId =
|
|
712
|
+
const layoutMasterRelId = relIds.alloc(SLIDE_LAYOUT_PART);
|
|
690
713
|
const slideLayoutXml = buildSlideLayoutXml(layoutMasterRelId);
|
|
691
|
-
pkg.addPart(
|
|
692
|
-
pkg.addRelationship(
|
|
714
|
+
pkg.addPart(SLIDE_LAYOUT_PART, slideLayoutXml, CONTENT_TYPE_PPTX_SLIDE_LAYOUT);
|
|
715
|
+
pkg.addRelationship(SLIDE_LAYOUT_PART, {
|
|
693
716
|
id: layoutMasterRelId,
|
|
694
717
|
type: REL_SLIDE_MASTER,
|
|
695
718
|
target: "../slideMasters/slideMaster1.xml"
|
|
696
719
|
});
|
|
697
|
-
const masterLayoutRelId =
|
|
698
|
-
const masterThemeRelId =
|
|
720
|
+
const masterLayoutRelId = relIds.alloc(SLIDE_MASTER_PART);
|
|
721
|
+
const masterThemeRelId = relIds.alloc(SLIDE_MASTER_PART);
|
|
699
722
|
const slideMasterXml = buildSlideMasterXml(masterLayoutRelId);
|
|
700
|
-
pkg.addPart(
|
|
701
|
-
pkg.addRelationship(
|
|
723
|
+
pkg.addPart(SLIDE_MASTER_PART, slideMasterXml, CONTENT_TYPE_PPTX_SLIDE_MASTER);
|
|
724
|
+
pkg.addRelationship(SLIDE_MASTER_PART, {
|
|
702
725
|
id: masterLayoutRelId,
|
|
703
726
|
type: REL_SLIDE_LAYOUT,
|
|
704
727
|
target: "../slideLayouts/slideLayout1.xml"
|
|
705
728
|
});
|
|
706
|
-
pkg.addRelationship(
|
|
729
|
+
pkg.addRelationship(SLIDE_MASTER_PART, {
|
|
707
730
|
id: masterThemeRelId,
|
|
708
731
|
type: REL_THEME,
|
|
709
732
|
target: "../theme/theme1.xml"
|
|
@@ -755,17 +778,20 @@ import { markdownToDoc } from "@bendyline/squisq/doc";
|
|
|
755
778
|
|
|
756
779
|
// src/pptx/import.ts
|
|
757
780
|
import { stringifyMarkdown } from "@bendyline/squisq/markdown";
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
781
|
+
var PPTX_MAIN_PART = "ppt/presentation.xml";
|
|
782
|
+
async function orderedSlidePaths(pkg, mainPart) {
|
|
783
|
+
const pres = await getPartXml(pkg, mainPart);
|
|
784
|
+
if (!pres) {
|
|
785
|
+
throw new Error(`Invalid PPTX package: presentation part "${mainPart}" could not be parsed.`);
|
|
786
|
+
}
|
|
787
|
+
const rels = await getPartRelationships(pkg, mainPart);
|
|
762
788
|
const relById = new Map(rels.map((r) => [r.id, r.target]));
|
|
763
789
|
const out = [];
|
|
764
790
|
const ids = pres.getElementsByTagNameNS(NS_PML, "sldId");
|
|
765
791
|
for (let i = 0; i < ids.length; i++) {
|
|
766
792
|
const rid = attrNS(ids[i], NS_R, "id", "r:id");
|
|
767
793
|
const target = rid ? relById.get(rid) : void 0;
|
|
768
|
-
if (target) out.push(resolveTarget(
|
|
794
|
+
if (target) out.push(resolveTarget(baseDirOf(mainPart), target));
|
|
769
795
|
}
|
|
770
796
|
return out;
|
|
771
797
|
}
|
|
@@ -959,7 +985,7 @@ async function importDocument(pkg, options) {
|
|
|
959
985
|
let extraction = null;
|
|
960
986
|
if (inferTheme || inferLayouts) {
|
|
961
987
|
try {
|
|
962
|
-
const { extractPptxTheme } = await import("./extract-
|
|
988
|
+
const { extractPptxTheme } = await import("./extract-MN7LA3NL.js");
|
|
963
989
|
extraction = await extractPptxTheme(pkg);
|
|
964
990
|
} catch (err) {
|
|
965
991
|
warnInferenceFailure("theme extraction", err);
|
|
@@ -968,7 +994,7 @@ async function importDocument(pkg, options) {
|
|
|
968
994
|
let theme;
|
|
969
995
|
if (inferTheme && extraction) {
|
|
970
996
|
try {
|
|
971
|
-
const { compileExtractedTheme } = await import("./mapTheme-
|
|
997
|
+
const { compileExtractedTheme } = await import("./mapTheme-4TWH25FT.js");
|
|
972
998
|
theme = compileExtractedTheme(extraction).theme;
|
|
973
999
|
} catch (err) {
|
|
974
1000
|
warnInferenceFailure("theme compilation", err);
|
|
@@ -976,8 +1002,8 @@ async function importDocument(pkg, options) {
|
|
|
976
1002
|
}
|
|
977
1003
|
if (inferLayouts) {
|
|
978
1004
|
try {
|
|
979
|
-
const { analyzePptxLayouts: analyzePptxLayouts2 } = await import("./layouts-
|
|
980
|
-
const { colorHintsFromExtraction } = await import("./mapTheme-
|
|
1005
|
+
const { analyzePptxLayouts: analyzePptxLayouts2 } = await import("./layouts-DRWZGSPD.js");
|
|
1006
|
+
const { colorHintsFromExtraction } = await import("./mapTheme-4TWH25FT.js");
|
|
981
1007
|
ctx.inference = await analyzePptxLayouts2(pkg, {
|
|
982
1008
|
colors: extraction ? colorHintsFromExtraction(extraction) : {}
|
|
983
1009
|
});
|
|
@@ -985,7 +1011,7 @@ async function importDocument(pkg, options) {
|
|
|
985
1011
|
warnInferenceFailure("layout inference", err);
|
|
986
1012
|
}
|
|
987
1013
|
}
|
|
988
|
-
const paths = await orderedSlidePaths(pkg);
|
|
1014
|
+
const paths = await orderedSlidePaths(pkg, requireMainPartPath(pkg, PPTX_MAIN_PART, "PPTX"));
|
|
989
1015
|
const children = [];
|
|
990
1016
|
for (let i = 0; i < paths.length; i++) {
|
|
991
1017
|
children.push(...await convertSlide(paths[i], i, ctx));
|
|
@@ -1037,4 +1063,3 @@ export {
|
|
|
1037
1063
|
pptxToContainer,
|
|
1038
1064
|
pptxToDoc
|
|
1039
1065
|
};
|
|
1040
|
-
//# sourceMappingURL=chunk-RLU7UFYU.js.map
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
arrayBufferToBase64DataUrl,
|
|
3
3
|
extractFilename,
|
|
4
4
|
inferMimeType
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-6RQOV3B3.js";
|
|
6
6
|
|
|
7
7
|
// src/html/index.ts
|
|
8
8
|
import JSZip3 from "jszip";
|
|
@@ -119,7 +119,23 @@ function scanTemplateImageFields(obj, paths) {
|
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
function escapeForScript(str) {
|
|
122
|
-
return str.replace(
|
|
122
|
+
return str.replace(/<(?=!--|\/?script)/gi, "\\u003c");
|
|
123
|
+
}
|
|
124
|
+
function buildInlineImageMaps(images) {
|
|
125
|
+
const imageMap = {};
|
|
126
|
+
const imageAliases = {};
|
|
127
|
+
if (!images) return { imageMap, imageAliases };
|
|
128
|
+
const canonicalKeyFor = /* @__PURE__ */ new Map();
|
|
129
|
+
for (const [path, buffer] of images.entries()) {
|
|
130
|
+
const canonical = canonicalKeyFor.get(buffer);
|
|
131
|
+
if (canonical !== void 0) {
|
|
132
|
+
imageAliases[path] = canonical;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
canonicalKeyFor.set(buffer, path);
|
|
136
|
+
imageMap[path] = arrayBufferToBase64DataUrl(buffer, inferMimeType(path));
|
|
137
|
+
}
|
|
138
|
+
return { imageMap, imageAliases };
|
|
123
139
|
}
|
|
124
140
|
function generateInlineHtml(doc, options) {
|
|
125
141
|
const {
|
|
@@ -132,15 +148,10 @@ function generateInlineHtml(doc, options) {
|
|
|
132
148
|
themeRegistry
|
|
133
149
|
} = options;
|
|
134
150
|
doc = applyThemeSelection(doc, themeId, themeRegistry);
|
|
135
|
-
const imageMap =
|
|
136
|
-
if (images) {
|
|
137
|
-
for (const [path, buffer] of images.entries()) {
|
|
138
|
-
const mimeType = inferMimeType(path);
|
|
139
|
-
imageMap[path] = arrayBufferToBase64DataUrl(buffer, mimeType);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
151
|
+
const { imageMap, imageAliases } = buildInlineImageMaps(images);
|
|
142
152
|
const docJson = escapeForScript(JSON.stringify(doc));
|
|
143
153
|
const imageMapJson = escapeForScript(JSON.stringify(imageMap));
|
|
154
|
+
const imageAliasJson = escapeForScript(JSON.stringify(imageAliases));
|
|
144
155
|
return `<!DOCTYPE html>
|
|
145
156
|
<html lang="en">
|
|
146
157
|
<head>
|
|
@@ -161,6 +172,14 @@ ${mode === "static" ? "#squisq-root{display:block}" : ""}
|
|
|
161
172
|
(function(){
|
|
162
173
|
var doc = JSON.parse(${JSON.stringify(docJson)});
|
|
163
174
|
var images = JSON.parse(${JSON.stringify(imageMapJson)});
|
|
175
|
+
// Re-expand path/basename aliases that share a payload (see
|
|
176
|
+
// buildInlineImageMaps) so \`images\` has every key the resolver may ask for.
|
|
177
|
+
var aliases = JSON.parse(${JSON.stringify(imageAliasJson)});
|
|
178
|
+
for (var alias in aliases) {
|
|
179
|
+
if (Object.prototype.hasOwnProperty.call(aliases, alias)) {
|
|
180
|
+
images[alias] = images[aliases[alias]];
|
|
181
|
+
}
|
|
182
|
+
}
|
|
164
183
|
SquisqPlayer.mount(document.getElementById("squisq-root"), doc, {
|
|
165
184
|
mode: ${JSON.stringify(mode)},
|
|
166
185
|
images: images,
|
|
@@ -248,21 +267,31 @@ import {
|
|
|
248
267
|
import { resolveFontFamily, buildGoogleFontsUrl } from "@bendyline/squisq/schemas";
|
|
249
268
|
import { resolveThemeForDoc } from "@bendyline/squisq/doc";
|
|
250
269
|
function markdownDocToPlainHtml(doc, options = {}) {
|
|
251
|
-
const {
|
|
270
|
+
const {
|
|
271
|
+
title = "Document",
|
|
272
|
+
images,
|
|
273
|
+
links,
|
|
274
|
+
themeId,
|
|
275
|
+
iconsCss,
|
|
276
|
+
htmlPolicy = "sanitize",
|
|
277
|
+
externalResources = "deny"
|
|
278
|
+
} = options;
|
|
252
279
|
const resolveId = themeId ?? readFrontmatterThemeId2(doc.frontmatter);
|
|
253
280
|
const theme = options.theme ?? (resolveId ? resolveThemeForDoc(doc, resolveId, options.themeRegistry) : void 0);
|
|
254
281
|
const ctx = { images, links, htmlPolicy };
|
|
255
282
|
const body = renderTopLevel(doc.children, ctx);
|
|
256
|
-
const fontsLink = theme ? renderFontsLink(theme) : "";
|
|
283
|
+
const fontsLink = theme && externalResources === "allow" ? renderFontsLink(theme) : "";
|
|
257
284
|
const usesIcons = docUsesIcons(doc);
|
|
258
285
|
let iconsLink = "";
|
|
259
286
|
if (usesIcons) {
|
|
260
287
|
iconsLink = iconsCss ? `<style data-fa-inline>
|
|
261
|
-
${iconsCss}
|
|
288
|
+
${escapeStyleText(iconsCss)}
|
|
262
289
|
</style>
|
|
263
|
-
` : FONT_AWESOME_LINK;
|
|
290
|
+
` : externalResources === "allow" ? FONT_AWESOME_LINK : "";
|
|
264
291
|
}
|
|
265
292
|
const themedCss = theme ? renderThemedCss(theme) : DEFAULT_CSS;
|
|
293
|
+
const safeCss = escapeStyleText(`${themedCss}
|
|
294
|
+
${FEATURE_CSS}`);
|
|
266
295
|
return `<!DOCTYPE html>
|
|
267
296
|
<html lang="en">
|
|
268
297
|
<head>
|
|
@@ -270,8 +299,7 @@ ${iconsCss}
|
|
|
270
299
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
271
300
|
<title>${escapeHtml2(title)}</title>
|
|
272
301
|
${fontsLink}${iconsLink}<style>
|
|
273
|
-
${
|
|
274
|
-
${FEATURE_CSS}
|
|
302
|
+
${safeCss}
|
|
275
303
|
</style>
|
|
276
304
|
</head>
|
|
277
305
|
<body>
|
|
@@ -279,7 +307,10 @@ ${body}
|
|
|
279
307
|
</body>
|
|
280
308
|
</html>`;
|
|
281
309
|
}
|
|
282
|
-
|
|
310
|
+
function escapeStyleText(css) {
|
|
311
|
+
return css.replace(/</g, "\\3c ");
|
|
312
|
+
}
|
|
313
|
+
var FONT_AWESOME_LINK = `<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.2.0/css/all.min.css" crossorigin="anonymous" referrerpolicy="no-referrer">
|
|
283
314
|
`;
|
|
284
315
|
function docUsesIcons(doc) {
|
|
285
316
|
function visit(node) {
|
|
@@ -1379,6 +1410,14 @@ function toHtmlString(data) {
|
|
|
1379
1410
|
return new TextDecoder("utf-8").decode(bytes);
|
|
1380
1411
|
}
|
|
1381
1412
|
function htmlToMarkdownDocSync(html, options = {}) {
|
|
1413
|
+
options.signal?.throwIfAborted();
|
|
1414
|
+
const maxInputChars = options.maxInputChars ?? 16 * 1024 * 1024;
|
|
1415
|
+
if (!Number.isSafeInteger(maxInputChars) || maxInputChars < 0) {
|
|
1416
|
+
throw new RangeError("maxInputChars must be a non-negative safe integer");
|
|
1417
|
+
}
|
|
1418
|
+
if (html.length > maxInputChars) {
|
|
1419
|
+
throw new RangeError(`HTML exceeds the ${maxInputChars}-character safety limit`);
|
|
1420
|
+
}
|
|
1382
1421
|
let nodes = parseHtmlToNodes(html);
|
|
1383
1422
|
if (options.sanitize !== false) nodes = sanitizeHtmlNodes2(nodes);
|
|
1384
1423
|
return { type: "document", children: blocksFromNodes(nodes) };
|
|
@@ -1387,7 +1426,7 @@ async function htmlToMarkdownDoc(data, options = {}) {
|
|
|
1387
1426
|
return htmlToMarkdownDocSync(toHtmlString(data), options);
|
|
1388
1427
|
}
|
|
1389
1428
|
function htmlToMarkdown(html, options = {}) {
|
|
1390
|
-
return stringifyMarkdown(htmlToMarkdownDocSync(html, options));
|
|
1429
|
+
return stringifyMarkdown(htmlToMarkdownDocSync(html, options), { signal: options.signal });
|
|
1391
1430
|
}
|
|
1392
1431
|
|
|
1393
1432
|
// src/html/index.ts
|
|
@@ -1397,10 +1436,21 @@ function sanitizeZipPath3(path) {
|
|
|
1397
1436
|
if (normalized.split("/").some((seg) => seg === "..")) return null;
|
|
1398
1437
|
return normalized;
|
|
1399
1438
|
}
|
|
1439
|
+
function uniqueFilename(filename, used) {
|
|
1440
|
+
if (!used.has(filename)) return filename;
|
|
1441
|
+
const dot = filename.lastIndexOf(".");
|
|
1442
|
+
const base = dot > 0 ? filename.slice(0, dot) : filename;
|
|
1443
|
+
const ext = dot > 0 ? filename.slice(dot) : "";
|
|
1444
|
+
let suffix = 2;
|
|
1445
|
+
while (used.has(`${base}-${suffix}${ext}`)) suffix++;
|
|
1446
|
+
return `${base}-${suffix}${ext}`;
|
|
1447
|
+
}
|
|
1400
1448
|
function docToHtml(doc, options) {
|
|
1449
|
+
options.signal?.throwIfAborted();
|
|
1401
1450
|
return generateInlineHtml(doc, options);
|
|
1402
1451
|
}
|
|
1403
1452
|
async function docToHtmlZip(doc, options) {
|
|
1453
|
+
options.signal?.throwIfAborted();
|
|
1404
1454
|
const {
|
|
1405
1455
|
playerScript,
|
|
1406
1456
|
images,
|
|
@@ -1415,18 +1465,30 @@ async function docToHtmlZip(doc, options) {
|
|
|
1415
1465
|
zip.file("squisq-player.js", playerScript);
|
|
1416
1466
|
const imagePathMap = {};
|
|
1417
1467
|
if (images) {
|
|
1468
|
+
let imageIndex = 0;
|
|
1418
1469
|
for (const [originalPath, buffer] of images.entries()) {
|
|
1470
|
+
if ((imageIndex++ & 63) === 0) options.signal?.throwIfAborted();
|
|
1419
1471
|
const zipPath = sanitizeZipPath3(originalPath);
|
|
1420
|
-
if (!zipPath)
|
|
1472
|
+
if (!zipPath) {
|
|
1473
|
+
console.warn(
|
|
1474
|
+
`[squisq] docToHtmlZip: skipped image with unsafe path "${originalPath}" \u2014 the exported document will have a broken reference to it.`
|
|
1475
|
+
);
|
|
1476
|
+
continue;
|
|
1477
|
+
}
|
|
1421
1478
|
zip.file(zipPath, buffer);
|
|
1422
1479
|
imagePathMap[originalPath] = zipPath;
|
|
1423
1480
|
}
|
|
1424
1481
|
}
|
|
1425
1482
|
const audioPathMap = {};
|
|
1426
1483
|
if (audio) {
|
|
1484
|
+
let audioIndex = 0;
|
|
1485
|
+
const usedAudioNames = /* @__PURE__ */ new Set();
|
|
1427
1486
|
for (const [segmentKey, buffer] of audio.entries()) {
|
|
1487
|
+
if ((audioIndex++ & 63) === 0) options.signal?.throwIfAborted();
|
|
1428
1488
|
const filename = extractFilename(segmentKey);
|
|
1429
|
-
const
|
|
1489
|
+
const named = filename.includes(".") ? filename : `${filename}.mp3`;
|
|
1490
|
+
const finalName = uniqueFilename(named, usedAudioNames);
|
|
1491
|
+
usedAudioNames.add(finalName);
|
|
1430
1492
|
const zipPath = `audio/${finalName}`;
|
|
1431
1493
|
zip.file(zipPath, buffer);
|
|
1432
1494
|
audioPathMap[segmentKey] = zipPath;
|
|
@@ -1462,4 +1524,3 @@ export {
|
|
|
1462
1524
|
docToHtml,
|
|
1463
1525
|
docToHtmlZip
|
|
1464
1526
|
};
|
|
1465
|
-
//# sourceMappingURL=chunk-DTDF6QDP.js.map
|