@bendyline/squisq-formats 2.0.1 → 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.
Files changed (195) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +20 -0
  3. package/README.md +1 -1
  4. package/dist/{chunk-CRAVSMPZ.js → chunk-26ISNJ7Y.js} +356 -114
  5. package/dist/{chunk-NKAJPJ4G.js → chunk-2JJ5RFDZ.js} +0 -1
  6. package/dist/{chunk-HTW2M27H.js → chunk-3NKXBZSR.js} +193 -42
  7. package/dist/{chunk-U32AG3G3.js → chunk-4V3KCHAP.js} +3 -4
  8. package/dist/{chunk-MLX2BOJC.js → chunk-6RQOV3B3.js} +1 -2
  9. package/dist/{chunk-QRVN6A6E.js → chunk-6S6GU3ZG.js} +5 -6
  10. package/dist/{chunk-FE6OJV6O.js → chunk-7AWFHP5U.js} +1 -1
  11. package/dist/{chunk-RFAPOKHJ.js → chunk-AD2WT564.js} +59 -9
  12. package/dist/{chunk-O3GVVND4.js → chunk-AONELFLA.js} +0 -1
  13. package/dist/{chunk-XKUMNGBW.js → chunk-EJTNGKEA.js} +5 -8
  14. package/dist/chunk-GX7RAUME.js +121 -0
  15. package/dist/{chunk-SSUPBUF5.js → chunk-IIQYS2YH.js} +0 -1
  16. package/dist/{chunk-ABVI556T.js → chunk-IPN56VLW.js} +83 -58
  17. package/dist/{chunk-LXYLOOST.js → chunk-JE6LSIHE.js} +83 -22
  18. package/dist/{chunk-U4MRIFKL.js → chunk-JU2RHXUB.js} +0 -1
  19. package/dist/{chunk-4VUWTSGM.js → chunk-K6XRMVPW.js} +64 -31
  20. package/dist/{chunk-ODL3SSPT.js → chunk-KXOZMWBS.js} +0 -1
  21. package/dist/chunk-OGS5VCGJ.js +446 -0
  22. package/dist/{chunk-GVS2XXV6.js → chunk-PJXJI2LY.js} +449 -57
  23. package/dist/{chunk-2KPARF2P.js → chunk-PU7REGWV.js} +5 -8
  24. package/dist/{chunk-PN52A5AA.js → chunk-SBUW7NHR.js} +0 -1
  25. package/dist/{chunk-VSYHZECT.js → chunk-TAAENIRB.js} +5 -8
  26. package/dist/{chunk-WC7WULGV.js → chunk-X2DEAXNK.js} +62 -2
  27. package/dist/container/index.js +1 -2
  28. package/dist/csv/index.d.ts +27 -2
  29. package/dist/csv/index.js +1 -2
  30. package/dist/docx/index.d.ts +5 -1
  31. package/dist/docx/index.js +9 -10
  32. package/dist/epub/index.d.ts +2 -0
  33. package/dist/epub/index.js +5 -6
  34. package/dist/{export-D2NkylDT.d.ts → export-D9msROJS.d.ts} +18 -6
  35. package/dist/extract-MN7LA3NL.js +13 -0
  36. package/dist/html/index.d.ts +11 -4
  37. package/dist/html/index.js +3 -4
  38. package/dist/images-ESPQKVTW.js +6 -0
  39. package/dist/{import-K8mfc0fz.d.ts → import-C3htUTss.d.ts} +5 -1
  40. package/dist/{import-DTkDxHmZ.d.ts → import-C8whCC7_.d.ts} +6 -0
  41. package/dist/index.d.ts +7 -7
  42. package/dist/index.js +28 -26
  43. package/dist/infer/index.d.ts +3 -3
  44. package/dist/infer/index.js +7 -9
  45. package/dist/{layouts-BHrgZ5FS.d.ts → layouts-CTdPlB-u.d.ts} +1 -1
  46. package/dist/layouts-DRWZGSPD.js +10 -0
  47. package/dist/{mapTheme-IR27S6IV.js → mapTheme-4TWH25FT.js} +1 -2
  48. package/dist/ooxml/index.d.ts +3 -3
  49. package/dist/ooxml/index.js +14 -13
  50. package/dist/pdf/index.d.ts +18 -0
  51. package/dist/pdf/index.js +2 -3
  52. package/dist/pptx/index.d.ts +4 -4
  53. package/dist/pptx/index.js +11 -13
  54. package/dist/{reader-B9L8Ucbj.d.ts → reader-B_m1aKZC.d.ts} +30 -1
  55. package/dist/registry/index.d.ts +21 -5
  56. package/dist/registry/index.js +9 -6
  57. package/dist/{themeReader-DJKErl_j.d.ts → themeReader-DCtwC83Q.d.ts} +1 -1
  58. package/dist/xlsx/index.d.ts +3 -3
  59. package/dist/xlsx/index.js +6 -7
  60. package/package.json +6 -3
  61. package/dist/chunk-2KPARF2P.js.map +0 -1
  62. package/dist/chunk-4VUWTSGM.js.map +0 -1
  63. package/dist/chunk-6M7Z25LA.js +0 -46
  64. package/dist/chunk-6M7Z25LA.js.map +0 -1
  65. package/dist/chunk-ABVI556T.js.map +0 -1
  66. package/dist/chunk-CRAVSMPZ.js.map +0 -1
  67. package/dist/chunk-FE6OJV6O.js.map +0 -1
  68. package/dist/chunk-GVS2XXV6.js.map +0 -1
  69. package/dist/chunk-HTW2M27H.js.map +0 -1
  70. package/dist/chunk-LXYLOOST.js.map +0 -1
  71. package/dist/chunk-MLX2BOJC.js.map +0 -1
  72. package/dist/chunk-NKAJPJ4G.js.map +0 -1
  73. package/dist/chunk-O3GVVND4.js.map +0 -1
  74. package/dist/chunk-ODL3SSPT.js.map +0 -1
  75. package/dist/chunk-PN52A5AA.js.map +0 -1
  76. package/dist/chunk-QRVN6A6E.js.map +0 -1
  77. package/dist/chunk-RFAPOKHJ.js.map +0 -1
  78. package/dist/chunk-SSUPBUF5.js.map +0 -1
  79. package/dist/chunk-U32AG3G3.js.map +0 -1
  80. package/dist/chunk-U4MRIFKL.js.map +0 -1
  81. package/dist/chunk-VJJM2SSH.js +0 -275
  82. package/dist/chunk-VJJM2SSH.js.map +0 -1
  83. package/dist/chunk-VSYHZECT.js.map +0 -1
  84. package/dist/chunk-WC7WULGV.js.map +0 -1
  85. package/dist/chunk-XKUMNGBW.js.map +0 -1
  86. package/dist/chunk-YRT7GQ5Y.js +0 -28
  87. package/dist/chunk-YRT7GQ5Y.js.map +0 -1
  88. package/dist/container/index.js.map +0 -1
  89. package/dist/csv/index.js.map +0 -1
  90. package/dist/docx/index.js.map +0 -1
  91. package/dist/epub/index.js.map +0 -1
  92. package/dist/extract-H6RXJMHP.js +0 -15
  93. package/dist/extract-H6RXJMHP.js.map +0 -1
  94. package/dist/html/index.js.map +0 -1
  95. package/dist/images-7FBWPKE3.js +0 -7
  96. package/dist/images-7FBWPKE3.js.map +0 -1
  97. package/dist/index.js.map +0 -1
  98. package/dist/infer/index.js.map +0 -1
  99. package/dist/layouts-QVPK3ZCU.js +0 -12
  100. package/dist/layouts-QVPK3ZCU.js.map +0 -1
  101. package/dist/mapTheme-IR27S6IV.js.map +0 -1
  102. package/dist/ooxml/index.js.map +0 -1
  103. package/dist/pdf/index.js.map +0 -1
  104. package/dist/pptx/index.js.map +0 -1
  105. package/dist/registry/index.js.map +0 -1
  106. package/dist/xlsx/index.js.map +0 -1
  107. package/src/__tests__/container.test.ts +0 -230
  108. package/src/__tests__/convert.test.ts +0 -495
  109. package/src/__tests__/csvImport.test.ts +0 -84
  110. package/src/__tests__/docxExport.test.ts +0 -457
  111. package/src/__tests__/docxImport.test.ts +0 -410
  112. package/src/__tests__/epub.test.ts +0 -649
  113. package/src/__tests__/exportThemeReconciliation.test.ts +0 -87
  114. package/src/__tests__/formatRegistry.test.ts +0 -174
  115. package/src/__tests__/html.test.ts +0 -435
  116. package/src/__tests__/htmlImport.test.ts +0 -57
  117. package/src/__tests__/inferTheme.test.ts +0 -135
  118. package/src/__tests__/lossyWarnings.test.ts +0 -146
  119. package/src/__tests__/ooxml.test.ts +0 -271
  120. package/src/__tests__/ooxmlCancellation.test.ts +0 -113
  121. package/src/__tests__/ooxmlThemeReader.test.ts +0 -92
  122. package/src/__tests__/pdfExport.test.ts +0 -322
  123. package/src/__tests__/pdfImport.test.ts +0 -384
  124. package/src/__tests__/plainHtml.test.ts +0 -417
  125. package/src/__tests__/plainHtmlBundle.test.ts +0 -253
  126. package/src/__tests__/pptxExport.test.ts +0 -138
  127. package/src/__tests__/pptxImport.test.ts +0 -145
  128. package/src/__tests__/pptxInferFixtures.ts +0 -314
  129. package/src/__tests__/pptxLayoutInfer.test.ts +0 -395
  130. package/src/__tests__/roundTrip.test.ts +0 -201
  131. package/src/__tests__/roundTripAssets.test.ts +0 -50
  132. package/src/__tests__/roundTripMatrix.fixtures.ts +0 -86
  133. package/src/__tests__/roundTripMatrix.helpers.ts +0 -154
  134. package/src/__tests__/roundTripMatrix.test.ts +0 -142
  135. package/src/__tests__/sharedContainer.test.ts +0 -41
  136. package/src/__tests__/sharedImages.test.ts +0 -61
  137. package/src/__tests__/xlsxExport.test.ts +0 -164
  138. package/src/__tests__/xlsxImport.test.ts +0 -80
  139. package/src/__tests__/zipSafety.test.ts +0 -317
  140. package/src/container/index.ts +0 -94
  141. package/src/csv/index.ts +0 -188
  142. package/src/docx/export.ts +0 -1267
  143. package/src/docx/import.ts +0 -995
  144. package/src/docx/index.ts +0 -26
  145. package/src/docx/styles.ts +0 -145
  146. package/src/epub/export.ts +0 -968
  147. package/src/epub/index.ts +0 -20
  148. package/src/html/docsHtmlBundle.ts +0 -373
  149. package/src/html/htmlTemplate.ts +0 -385
  150. package/src/html/imageUtils.ts +0 -61
  151. package/src/html/import.ts +0 -297
  152. package/src/html/index.ts +0 -212
  153. package/src/html/plainHtml.ts +0 -790
  154. package/src/html/plainHtmlBundle.ts +0 -421
  155. package/src/index.ts +0 -109
  156. package/src/infer/extract.ts +0 -127
  157. package/src/infer/index.ts +0 -199
  158. package/src/infer/mapTheme.ts +0 -176
  159. package/src/infer/types.ts +0 -27
  160. package/src/ooxml/index.ts +0 -111
  161. package/src/ooxml/namespaces.ts +0 -196
  162. package/src/ooxml/readUtils.ts +0 -44
  163. package/src/ooxml/reader.ts +0 -318
  164. package/src/ooxml/themeReader.ts +0 -197
  165. package/src/ooxml/types.ts +0 -103
  166. package/src/ooxml/writer.ts +0 -339
  167. package/src/ooxml/xmlUtils.ts +0 -123
  168. package/src/pdf/export.ts +0 -1084
  169. package/src/pdf/import.ts +0 -1164
  170. package/src/pdf/index.ts +0 -29
  171. package/src/pdf/styles.ts +0 -180
  172. package/src/pptx/export.ts +0 -1184
  173. package/src/pptx/import.ts +0 -455
  174. package/src/pptx/index.ts +0 -52
  175. package/src/pptx/layouts.ts +0 -1222
  176. package/src/pptx/styles.ts +0 -96
  177. package/src/pptx/templates.ts +0 -187
  178. package/src/registry/convert.ts +0 -433
  179. package/src/registry/defaultFormats.ts +0 -413
  180. package/src/registry/errors.ts +0 -46
  181. package/src/registry/index.ts +0 -43
  182. package/src/registry/registry.ts +0 -48
  183. package/src/registry/types.ts +0 -170
  184. package/src/shared/boundedZipArchive.ts +0 -383
  185. package/src/shared/container.ts +0 -28
  186. package/src/shared/fidelity.ts +0 -130
  187. package/src/shared/images.ts +0 -44
  188. package/src/shared/inlineRuns.ts +0 -99
  189. package/src/shared/text.ts +0 -41
  190. package/src/shared/zipEntryCount.ts +0 -151
  191. package/src/shared/zipLimits.ts +0 -296
  192. package/src/shared/zipSafety.ts +0 -19
  193. package/src/xlsx/export.ts +0 -253
  194. package/src/xlsx/import.ts +0 -160
  195. 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
- } from "./chunk-WC7WULGV.js";
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-XKUMNGBW.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
+ };
@@ -12,4 +12,3 @@ async function buildContainer(markdown, images) {
12
12
  export {
13
13
  buildContainer
14
14
  };
15
- //# sourceMappingURL=chunk-SSUPBUF5.js.map
@@ -1,23 +1,21 @@
1
1
  import {
2
+ RelIdAllocator,
2
3
  inlineNodeToRuns,
3
- inlineNodesToRuns
4
- } from "./chunk-6M7Z25LA.js";
4
+ inlineNodesToRuns,
5
+ sanitizeOfficeHyperlink,
6
+ toOoxmlHex
7
+ } from "./chunk-GX7RAUME.js";
5
8
  import {
6
9
  extractPlainText,
7
10
  stripHtmlTags
8
- } from "./chunk-PN52A5AA.js";
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-U32AG3G3.js";
14
+ } from "./chunk-4V3KCHAP.js";
17
15
  import {
18
16
  escapeXml,
19
17
  xmlDeclaration
20
- } from "./chunk-U4MRIFKL.js";
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
- } from "./chunk-WC7WULGV.js";
42
+ openPackage,
43
+ requireMainPartPath,
44
+ resolveTarget
45
+ } from "./chunk-X2DEAXNK.js";
44
46
  import {
45
47
  buildContainer
46
- } from "./chunk-SSUPBUF5.js";
48
+ } from "./chunk-IIQYS2YH.js";
47
49
  import {
48
50
  inferMimeType
49
- } from "./chunk-MLX2BOJC.js";
51
+ } from "./chunk-6RQOV3B3.js";
50
52
  import {
51
53
  extToMime
52
- } from "./chunk-O3GVVND4.js";
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
- const ctx = new SlideContext(style, options.images, i);
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: stripHash(c.background),
138
- text: stripHash(c.text),
139
- titleColor: stripHash(c.highlight || c.secondary || c.text),
140
- mutedColor: stripHash(c.textMuted || c.text),
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: stripHash(c.textMuted || c.text),
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
- // 1=group, 2=title, 3=body
176
- constructor(style, images, slideIndex) {
177
- this.nextRelId = 1;
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 `rId${this.nextRelId++ + 1}`;
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: url,
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:latin typeface="${escapeXml(ctx.style.codeFont)}"/><a:solidFill><a:srgbClr val="${ctx.style.codeColor}"/></a:solidFill></a:rPr><a:t>${escapeXml(line || " ")}</a:t></a:r></a:p>`
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 slideMasterRelId = "rId100";
656
- const themeRelId = "rId101";
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(`rId${i + 1}`);
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 = "rId1";
712
+ const layoutMasterRelId = relIds.alloc(SLIDE_LAYOUT_PART);
690
713
  const slideLayoutXml = buildSlideLayoutXml(layoutMasterRelId);
691
- pkg.addPart("ppt/slideLayouts/slideLayout1.xml", slideLayoutXml, CONTENT_TYPE_PPTX_SLIDE_LAYOUT);
692
- pkg.addRelationship("ppt/slideLayouts/slideLayout1.xml", {
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 = "rId1";
698
- const masterThemeRelId = "rId2";
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("ppt/slideMasters/slideMaster1.xml", slideMasterXml, CONTENT_TYPE_PPTX_SLIDE_MASTER);
701
- pkg.addRelationship("ppt/slideMasters/slideMaster1.xml", {
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("ppt/slideMasters/slideMaster1.xml", {
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
- async function orderedSlidePaths(pkg) {
759
- const pres = await getPartXml(pkg, "ppt/presentation.xml");
760
- if (!pres) return [];
761
- const rels = await getPartRelationships(pkg, "ppt/presentation.xml");
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("ppt", target));
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-H6RXJMHP.js");
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-IR27S6IV.js");
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-QVPK3ZCU.js");
980
- const { colorHintsFromExtraction } = await import("./mapTheme-IR27S6IV.js");
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-ABVI556T.js.map