@bendyline/squisq-formats 1.2.3 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/dist/chunk-33YRFXZZ.js +1187 -0
  2. package/dist/chunk-33YRFXZZ.js.map +1 -0
  3. package/dist/{chunk-EUQQYBZZ.js → chunk-ERZ627GR.js} +4 -4
  4. package/dist/chunk-ERZ627GR.js.map +1 -0
  5. package/dist/{chunk-MEZF76JA.js → chunk-UDS45KUJ.js} +68 -25
  6. package/dist/chunk-UDS45KUJ.js.map +1 -0
  7. package/dist/{chunk-NGWHV77G.js → chunk-VN2KEOYB.js} +7 -6
  8. package/dist/chunk-VN2KEOYB.js.map +1 -0
  9. package/dist/container/index.d.ts +7 -5
  10. package/dist/container/index.js +39 -70
  11. package/dist/container/index.js.map +1 -1
  12. package/dist/docx/index.d.ts +128 -15
  13. package/dist/docx/index.js +17 -22
  14. package/dist/docx/index.js.map +1 -1
  15. package/dist/epub/index.d.ts +66 -11
  16. package/dist/epub/index.js +10 -18
  17. package/dist/epub/index.js.map +1 -1
  18. package/dist/html/index.d.ts +278 -9
  19. package/dist/html/index.js +26 -137
  20. package/dist/html/index.js.map +1 -1
  21. package/dist/index.d.ts +9 -38
  22. package/dist/index.js +62 -37
  23. package/dist/index.js.map +1 -1
  24. package/dist/ooxml/index.d.ts +353 -14
  25. package/dist/ooxml/index.js +116 -22
  26. package/dist/ooxml/index.js.map +1 -1
  27. package/dist/pdf/index.d.ts +143 -17
  28. package/dist/pdf/index.js +16 -25
  29. package/dist/pdf/index.js.map +1 -1
  30. package/dist/pptx/index.d.ts +83 -8
  31. package/dist/pptx/index.js +14 -34
  32. package/dist/pptx/index.js.map +1 -1
  33. package/dist/xlsx/index.d.ts +12 -9
  34. package/dist/xlsx/index.js +12 -44
  35. package/dist/xlsx/index.js.map +1 -1
  36. package/package.json +3 -2
  37. package/src/__tests__/html.test.ts +82 -4
  38. package/src/__tests__/pdfExport.test.ts +1 -1
  39. package/src/__tests__/plainHtml.test.ts +372 -0
  40. package/src/__tests__/plainHtmlBundle.test.ts +235 -0
  41. package/src/docx/export.ts +163 -22
  42. package/src/epub/export.ts +3 -3
  43. package/src/html/docsHtmlBundle.ts +369 -0
  44. package/src/html/htmlTemplate.ts +40 -0
  45. package/src/html/index.ts +32 -3
  46. package/src/html/plainHtml.ts +736 -0
  47. package/src/html/plainHtmlBundle.ts +419 -0
  48. package/src/pptx/export.ts +10 -9
  49. package/dist/__tests__/container.test.d.ts +0 -8
  50. package/dist/__tests__/container.test.d.ts.map +0 -1
  51. package/dist/__tests__/container.test.js +0 -147
  52. package/dist/__tests__/container.test.js.map +0 -1
  53. package/dist/__tests__/docxExport.test.d.ts +0 -8
  54. package/dist/__tests__/docxExport.test.d.ts.map +0 -1
  55. package/dist/__tests__/docxExport.test.js +0 -383
  56. package/dist/__tests__/docxExport.test.js.map +0 -1
  57. package/dist/__tests__/docxImport.test.d.ts +0 -8
  58. package/dist/__tests__/docxImport.test.d.ts.map +0 -1
  59. package/dist/__tests__/docxImport.test.js +0 -309
  60. package/dist/__tests__/docxImport.test.js.map +0 -1
  61. package/dist/__tests__/epub.test.d.ts +0 -8
  62. package/dist/__tests__/epub.test.d.ts.map +0 -1
  63. package/dist/__tests__/epub.test.js +0 -472
  64. package/dist/__tests__/epub.test.js.map +0 -1
  65. package/dist/__tests__/html.test.d.ts +0 -8
  66. package/dist/__tests__/html.test.d.ts.map +0 -1
  67. package/dist/__tests__/html.test.js +0 -243
  68. package/dist/__tests__/html.test.js.map +0 -1
  69. package/dist/__tests__/ooxml.test.d.ts +0 -5
  70. package/dist/__tests__/ooxml.test.d.ts.map +0 -1
  71. package/dist/__tests__/ooxml.test.js +0 -152
  72. package/dist/__tests__/ooxml.test.js.map +0 -1
  73. package/dist/__tests__/pdfExport.test.d.ts +0 -8
  74. package/dist/__tests__/pdfExport.test.d.ts.map +0 -1
  75. package/dist/__tests__/pdfExport.test.js +0 -275
  76. package/dist/__tests__/pdfExport.test.js.map +0 -1
  77. package/dist/__tests__/pdfImport.test.d.ts +0 -11
  78. package/dist/__tests__/pdfImport.test.d.ts.map +0 -1
  79. package/dist/__tests__/pdfImport.test.js +0 -254
  80. package/dist/__tests__/pdfImport.test.js.map +0 -1
  81. package/dist/__tests__/roundTrip.test.d.ts +0 -7
  82. package/dist/__tests__/roundTrip.test.d.ts.map +0 -1
  83. package/dist/__tests__/roundTrip.test.js +0 -173
  84. package/dist/__tests__/roundTrip.test.js.map +0 -1
  85. package/dist/chunk-EUQQYBZZ.js.map +0 -1
  86. package/dist/chunk-MEZF76JA.js.map +0 -1
  87. package/dist/chunk-NGWHV77G.js.map +0 -1
  88. package/dist/chunk-UM5V2XZG.js +0 -242
  89. package/dist/chunk-UM5V2XZG.js.map +0 -1
  90. package/dist/container/index.d.ts.map +0 -1
  91. package/dist/docx/export.d.ts +0 -69
  92. package/dist/docx/export.d.ts.map +0 -1
  93. package/dist/docx/export.js +0 -854
  94. package/dist/docx/export.js.map +0 -1
  95. package/dist/docx/import.d.ts +0 -65
  96. package/dist/docx/import.d.ts.map +0 -1
  97. package/dist/docx/import.js +0 -779
  98. package/dist/docx/import.js.map +0 -1
  99. package/dist/docx/index.d.ts.map +0 -1
  100. package/dist/docx/styles.d.ts +0 -68
  101. package/dist/docx/styles.d.ts.map +0 -1
  102. package/dist/docx/styles.js +0 -125
  103. package/dist/docx/styles.js.map +0 -1
  104. package/dist/epub/export.d.ts +0 -72
  105. package/dist/epub/export.d.ts.map +0 -1
  106. package/dist/epub/export.js +0 -698
  107. package/dist/epub/export.js.map +0 -1
  108. package/dist/epub/index.d.ts.map +0 -1
  109. package/dist/html/htmlTemplate.d.ts +0 -70
  110. package/dist/html/htmlTemplate.d.ts.map +0 -1
  111. package/dist/html/htmlTemplate.js +0 -239
  112. package/dist/html/htmlTemplate.js.map +0 -1
  113. package/dist/html/imageUtils.d.ts +0 -29
  114. package/dist/html/imageUtils.d.ts.map +0 -1
  115. package/dist/html/imageUtils.js +0 -63
  116. package/dist/html/imageUtils.js.map +0 -1
  117. package/dist/html/index.d.ts.map +0 -1
  118. package/dist/index.d.ts.map +0 -1
  119. package/dist/ooxml/index.d.ts.map +0 -1
  120. package/dist/ooxml/namespaces.d.ts +0 -77
  121. package/dist/ooxml/namespaces.d.ts.map +0 -1
  122. package/dist/ooxml/namespaces.js +0 -104
  123. package/dist/ooxml/namespaces.js.map +0 -1
  124. package/dist/ooxml/reader.d.ts +0 -52
  125. package/dist/ooxml/reader.d.ts.map +0 -1
  126. package/dist/ooxml/reader.js +0 -190
  127. package/dist/ooxml/reader.js.map +0 -1
  128. package/dist/ooxml/types.d.ts +0 -82
  129. package/dist/ooxml/types.d.ts.map +0 -1
  130. package/dist/ooxml/types.js +0 -9
  131. package/dist/ooxml/types.js.map +0 -1
  132. package/dist/ooxml/writer.d.ts +0 -71
  133. package/dist/ooxml/writer.d.ts.map +0 -1
  134. package/dist/ooxml/writer.js +0 -200
  135. package/dist/ooxml/writer.js.map +0 -1
  136. package/dist/ooxml/xmlUtils.d.ts +0 -76
  137. package/dist/ooxml/xmlUtils.d.ts.map +0 -1
  138. package/dist/ooxml/xmlUtils.js +0 -108
  139. package/dist/ooxml/xmlUtils.js.map +0 -1
  140. package/dist/pdf/export.d.ts +0 -56
  141. package/dist/pdf/export.d.ts.map +0 -1
  142. package/dist/pdf/export.js +0 -768
  143. package/dist/pdf/export.js.map +0 -1
  144. package/dist/pdf/import.d.ts +0 -94
  145. package/dist/pdf/import.d.ts.map +0 -1
  146. package/dist/pdf/import.js +0 -796
  147. package/dist/pdf/import.js.map +0 -1
  148. package/dist/pdf/index.d.ts.map +0 -1
  149. package/dist/pdf/styles.d.ts +0 -142
  150. package/dist/pdf/styles.d.ts.map +0 -1
  151. package/dist/pdf/styles.js +0 -145
  152. package/dist/pdf/styles.js.map +0 -1
  153. package/dist/pptx/export.d.ts +0 -75
  154. package/dist/pptx/export.d.ts.map +0 -1
  155. package/dist/pptx/export.js +0 -722
  156. package/dist/pptx/export.js.map +0 -1
  157. package/dist/pptx/index.d.ts.map +0 -1
  158. package/dist/pptx/styles.d.ts +0 -54
  159. package/dist/pptx/styles.d.ts.map +0 -1
  160. package/dist/pptx/styles.js +0 -73
  161. package/dist/pptx/styles.js.map +0 -1
  162. package/dist/pptx/templates.d.ts +0 -24
  163. package/dist/pptx/templates.d.ts.map +0 -1
  164. package/dist/pptx/templates.js +0 -158
  165. package/dist/pptx/templates.js.map +0 -1
  166. package/dist/xlsx/index.d.ts.map +0 -1
@@ -1,26 +1,152 @@
1
+ import { Doc } from '@bendyline/squisq/schemas';
2
+ import { MarkdownDocument } from '@bendyline/squisq/markdown';
3
+ import { ContentContainer } from '@bendyline/squisq/storage';
4
+
1
5
  /**
2
- * @bendyline/squisq-formats PDF Module
6
+ * PDF Export
3
7
  *
4
- * Import and export squisq documents (MarkdownDocument / Doc)
5
- * to/from PDF files.
8
+ * Converts a squisq MarkdownDocument (or Doc) into a PDF file
9
+ * using pdf-lib. Generates paginated, styled output with support for
10
+ * headings, paragraphs, inline formatting, lists, code blocks,
11
+ * blockquotes, tables, thematic breaks, and hyperlinks.
6
12
  *
7
- * - **Export** uses pdf-lib (zero dependencies, standard fonts, pure JS).
8
- * - **Import** uses pdfjs-dist (Mozilla pdf.js) with heuristic structure detection.
13
+ * Uses only the 14 standard PDF fonts (no font embedding required),
14
+ * keeping output size small and rendering fast.
9
15
  *
10
- * All operations run in the browser — no server required.
16
+ * @example
17
+ * ```ts
18
+ * import { parseMarkdown } from '@bendyline/squisq/markdown';
19
+ * import { markdownDocToPdf } from '@bendyline/squisq-formats/pdf';
20
+ *
21
+ * const md = parseMarkdown('# Hello\n\nWorld **bold** text');
22
+ * const buffer = await markdownDocToPdf(md);
23
+ * ```
24
+ */
25
+
26
+ /** Page size presets. */
27
+ type PdfPageSize = 'letter' | 'a4';
28
+ /**
29
+ * Options for PDF export.
30
+ */
31
+ interface PdfExportOptions {
32
+ /** Document title (PDF metadata). */
33
+ title?: string;
34
+ /** Document author (PDF metadata). */
35
+ author?: string;
36
+ /** Page size preset. Default: "letter". */
37
+ pageSize?: PdfPageSize;
38
+ /** Page margins in points. Default: 72 (1 inch). */
39
+ margin?: number;
40
+ /** Default body font size in points. Default: 11. */
41
+ defaultFontSize?: number;
42
+ /**
43
+ * Squisq theme ID to apply (e.g., 'documentary', 'cinematic').
44
+ * When set, overrides heading, text, and link colors with the theme palette.
45
+ * Font changes are not supported (pdf-lib uses standard 14 PDF fonts only).
46
+ */
47
+ themeId?: string;
48
+ }
49
+ /**
50
+ * Convert a MarkdownDocument to a PDF ArrayBuffer.
51
+ */
52
+ declare function markdownDocToPdf(doc: MarkdownDocument, options?: PdfExportOptions): Promise<ArrayBuffer>;
53
+ /**
54
+ * Convert a squisq Doc to a PDF ArrayBuffer.
55
+ *
56
+ * Convenience wrapper: Doc → MarkdownDocument → PDF.
57
+ */
58
+ declare function docToPdf(doc: Doc, options?: PdfExportOptions): Promise<ArrayBuffer>;
59
+
60
+ /**
61
+ * PDF Import
62
+ *
63
+ * Parses a PDF file and converts its content into a squisq
64
+ * MarkdownDocument (or Doc) using heuristic detection of headings,
65
+ * lists, code blocks, tables, blockquotes, and hyperlinks.
66
+ *
67
+ * Uses pdfjs-dist (Mozilla pdf.js) for text extraction — a battle-tested,
68
+ * browser-compatible PDF parser. Since PDFs encode positioned glyphs
69
+ * rather than semantic structure, all structure detection is inherently
70
+ * heuristic and works best on simply-formatted documents.
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * import { pdfToMarkdownDoc } from '@bendyline/squisq-formats/pdf';
75
+ *
76
+ * const response = await fetch('document.pdf');
77
+ * const data = await response.arrayBuffer();
78
+ * const doc = await pdfToMarkdownDoc(data);
79
+ * ```
80
+ */
81
+
82
+ /**
83
+ * Options for PDF import.
84
+ */
85
+ interface PdfImportOptions {
86
+ /**
87
+ * Hint for the body font size used in the PDF (in points).
88
+ * Text items larger than this are considered headings.
89
+ * If not provided, the importer detects the most common font size.
90
+ */
91
+ bodyFontSize?: number;
92
+ /** Whether to detect tables from column-aligned text. Default: true. */
93
+ detectTables?: boolean;
94
+ /** Whether to detect code blocks from monospace fonts. Default: true. */
95
+ detectCodeBlocks?: boolean;
96
+ /** Whether to detect blockquotes from indentation. Default: true. */
97
+ detectBlockquotes?: boolean;
98
+ /** Whether to detect URLs in text and convert to links. Default: true. */
99
+ detectLinks?: boolean;
100
+ }
101
+ /**
102
+ * Convert a PDF file to a MarkdownDocument.
103
+ *
104
+ * Structure detection is heuristic — results are best-effort.
105
+ *
106
+ * @param data - The raw PDF file as ArrayBuffer, Uint8Array, or Blob
107
+ * @param options - Import options
108
+ * @returns A MarkdownDocument representing the detected content
109
+ */
110
+ declare function pdfToMarkdownDoc(data: ArrayBuffer | Uint8Array | Blob, options?: PdfImportOptions): Promise<MarkdownDocument>;
111
+ /**
112
+ * Convert a PDF file to a squisq Doc.
113
+ *
114
+ * Convenience wrapper: PDF → MarkdownDocument → Doc.
115
+ */
116
+ declare function pdfToDoc(data: ArrayBuffer | Uint8Array | Blob, options?: PdfImportOptions): Promise<Doc>;
117
+ /**
118
+ * Convert a PDF file to a ContentContainer with markdown + extracted images.
119
+ *
120
+ * The container will contain:
121
+ * - The primary markdown document (index.md)
122
+ * - Any embedded images under images/ (e.g., images/image1.png)
123
+ *
124
+ * Image extraction uses pdfjs-dist's operator list API and requires a browser
125
+ * environment (canvas is used to encode pixel data to PNG).
126
+ *
127
+ * @param data - The raw PDF file as ArrayBuffer, Uint8Array, or Blob
128
+ * @param options - Import options
129
+ * @returns A ContentContainer with the document and its media
130
+ */
131
+ declare function pdfToContainer(data: ArrayBuffer | Uint8Array | Blob, options?: PdfImportOptions): Promise<ContentContainer>;
132
+ /**
133
+ * Configure the pdfjs-dist PDF worker source URL.
134
+ *
135
+ * pdfjs-dist requires a worker for PDF parsing. In the **browser**, bundlers
136
+ * (Vite, webpack) typically handle this automatically, or you can point to a
137
+ * CDN-hosted worker script. In **Node.js / SSR / test** environments, call
138
+ * this with a `file://` URL to the worker module **before** any import call.
11
139
  *
12
140
  * @example
13
141
  * ```ts
14
- * import {
15
- * markdownDocToPdf,
16
- * docToPdf,
17
- * pdfToMarkdownDoc,
18
- * pdfToDoc,
19
- * } from '@bendyline/squisq-formats/pdf';
142
+ * // Browser — CDN
143
+ * configurePdfWorker('https://cdn.jsdelivr.net/npm/pdfjs-dist@4/legacy/build/pdf.worker.min.mjs');
144
+ *
145
+ * // Node / vitest — file URL
146
+ * import { pathToFileURL } from 'url';
147
+ * configurePdfWorker(pathToFileURL(require.resolve('pdfjs-dist/legacy/build/pdf.worker.mjs')).href);
20
148
  * ```
21
149
  */
22
- export { markdownDocToPdf, docToPdf } from './export.js';
23
- export type { PdfExportOptions } from './export.js';
24
- export { pdfToMarkdownDoc, pdfToDoc, pdfToContainer, configurePdfWorker } from './import.js';
25
- export type { PdfImportOptions } from './import.js';
26
- //# sourceMappingURL=index.d.ts.map
150
+ declare function configurePdfWorker(workerSrc: string): void;
151
+
152
+ export { type PdfExportOptions, type PdfImportOptions, configurePdfWorker, docToPdf, markdownDocToPdf, pdfToContainer, pdfToDoc, pdfToMarkdownDoc };
package/dist/pdf/index.js CHANGED
@@ -1,26 +1,17 @@
1
- /**
2
- * @bendyline/squisq-formats PDF Module
3
- *
4
- * Import and export squisq documents (MarkdownDocument / Doc)
5
- * to/from PDF files.
6
- *
7
- * - **Export** uses pdf-lib (zero dependencies, standard fonts, pure JS).
8
- * - **Import** uses pdfjs-dist (Mozilla pdf.js) with heuristic structure detection.
9
- *
10
- * All operations run in the browser — no server required.
11
- *
12
- * @example
13
- * ```ts
14
- * import {
15
- * markdownDocToPdf,
16
- * docToPdf,
17
- * pdfToMarkdownDoc,
18
- * pdfToDoc,
19
- * } from '@bendyline/squisq-formats/pdf';
20
- * ```
21
- */
22
- // Export
23
- export { markdownDocToPdf, docToPdf } from './export.js';
24
- // Import
25
- export { pdfToMarkdownDoc, pdfToDoc, pdfToContainer, configurePdfWorker } from './import.js';
1
+ import {
2
+ configurePdfWorker,
3
+ docToPdf,
4
+ markdownDocToPdf,
5
+ pdfToContainer,
6
+ pdfToDoc,
7
+ pdfToMarkdownDoc
8
+ } from "../chunk-S3Y7H2BK.js";
9
+ export {
10
+ configurePdfWorker,
11
+ docToPdf,
12
+ markdownDocToPdf,
13
+ pdfToContainer,
14
+ pdfToDoc,
15
+ pdfToMarkdownDoc
16
+ };
26
17
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pdf/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,SAAS;AACT,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGzD,SAAS;AACT,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,3 +1,80 @@
1
+ import { Doc } from '@bendyline/squisq/schemas';
2
+ import { MarkdownDocument } from '@bendyline/squisq/markdown';
3
+
4
+ /**
5
+ * PPTX Export
6
+ *
7
+ * Converts a squisq MarkdownDocument (or Doc) into a .pptx file
8
+ * by generating PresentationML + DrawingML XML and assembling the
9
+ * OOXML package.
10
+ *
11
+ * Slide segmentation: each H1 or H2 heading starts a new slide.
12
+ * The heading becomes the slide title; content below becomes the body.
13
+ *
14
+ * Supports:
15
+ * - Theme-based styling (background, text colors, fonts from squisq themes)
16
+ * - Image embedding (pass images as ArrayBuffers via options)
17
+ * - Inline formatting (bold, italic, strikethrough, code, links)
18
+ * - Lists, code blocks, blockquotes, tables, math
19
+ *
20
+ * No third-party pptx library — all XML is generated directly using
21
+ * the shared ooxml/ infrastructure.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * import { parseMarkdown } from '@bendyline/squisq/markdown';
26
+ * import { markdownDocToPptx } from '@bendyline/squisq-formats/pptx';
27
+ *
28
+ * const md = parseMarkdown('# Slide 1\n\nHello world\n\n## Slide 2\n\nMore content');
29
+ * const blob = await markdownDocToPptx(md, { themeId: 'documentary' });
30
+ * ```
31
+ */
32
+
33
+ /**
34
+ * Options for PPTX export.
35
+ */
36
+ interface PptxExportOptions {
37
+ /** Presentation title (appears in core properties) */
38
+ title?: string;
39
+ /** Presentation author */
40
+ author?: string;
41
+ /** Presentation description */
42
+ description?: string;
43
+ /**
44
+ * Which heading depth triggers a new slide.
45
+ * - `'h1'` — only H1 headings start slides
46
+ * - `'h2'` — H1 and H2 headings start slides (default)
47
+ * - `'heading'` — any heading (H1–H6) starts a slide
48
+ */
49
+ slideBreak?: 'h1' | 'h2' | 'heading';
50
+ /** Default body font family. Default: "Calibri" */
51
+ defaultFont?: string;
52
+ /** Default body font size in points. Default: 18 */
53
+ defaultFontSize?: number;
54
+ /**
55
+ * Squisq theme ID to apply (e.g., 'documentary', 'cinematic', 'bold').
56
+ * Controls slide background, text colors, and fonts.
57
+ * Falls back to the document's frontmatter `themeId` if not set here.
58
+ */
59
+ themeId?: string;
60
+ /**
61
+ * Image data keyed by the path/URL used in markdown.
62
+ * When provided, images are embedded as picture shapes instead of
63
+ * showing `[Image: alt]` placeholders.
64
+ */
65
+ images?: Map<string, ArrayBuffer>;
66
+ }
67
+ /**
68
+ * Convert a MarkdownDocument to a .pptx ArrayBuffer.
69
+ */
70
+ declare function markdownDocToPptx(doc: MarkdownDocument, options?: PptxExportOptions): Promise<ArrayBuffer>;
71
+ /**
72
+ * Convert a squisq Doc to a .pptx ArrayBuffer.
73
+ *
74
+ * Convenience wrapper: Doc -> MarkdownDocument -> PPTX.
75
+ */
76
+ declare function docToPptx(doc: Doc, options?: PptxExportOptions): Promise<ArrayBuffer>;
77
+
1
78
  /**
2
79
  * @bendyline/squisq-formats PPTX Module
3
80
  *
@@ -14,14 +91,11 @@
14
91
  * import { markdownDocToPptx } from '@bendyline/squisq-formats/pptx';
15
92
  * ```
16
93
  */
17
- export { markdownDocToPptx, docToPptx } from './export.js';
18
- export type { PptxExportOptions } from './export.js';
19
- import type { MarkdownDocument } from '@bendyline/squisq/markdown';
20
- import type { Doc } from '@bendyline/squisq/schemas';
94
+
21
95
  /**
22
96
  * Options for PPTX import (placeholder).
23
97
  */
24
- export interface PptxImportOptions {
98
+ interface PptxImportOptions {
25
99
  /** Whether to extract embedded images as data URIs */
26
100
  extractImages?: boolean;
27
101
  }
@@ -30,11 +104,12 @@ export interface PptxImportOptions {
30
104
  *
31
105
  * @throws Error — PPTX import is not yet implemented
32
106
  */
33
- export declare function pptxToMarkdownDoc(_data: ArrayBuffer | Blob, _options?: PptxImportOptions): Promise<MarkdownDocument>;
107
+ declare function pptxToMarkdownDoc(_data: ArrayBuffer | Blob, _options?: PptxImportOptions): Promise<MarkdownDocument>;
34
108
  /**
35
109
  * Convert a .pptx file to a squisq Doc.
36
110
  *
37
111
  * @throws Error — PPTX import is not yet implemented
38
112
  */
39
- export declare function pptxToDoc(_data: ArrayBuffer | Blob, _options?: PptxImportOptions): Promise<Doc>;
40
- //# sourceMappingURL=index.d.ts.map
113
+ declare function pptxToDoc(_data: ArrayBuffer | Blob, _options?: PptxImportOptions): Promise<Doc>;
114
+
115
+ export { type PptxExportOptions, type PptxImportOptions, docToPptx, markdownDocToPptx, pptxToDoc, pptxToMarkdownDoc };
@@ -1,35 +1,15 @@
1
- /**
2
- * @bendyline/squisq-formats PPTX Module
3
- *
4
- * PowerPoint .pptx export support using PresentationML (`<p:presentation>`,
5
- * `<p:sld>`) via the shared ooxml/ infrastructure.
6
- *
7
- * Slide segmentation: each H1/H2 heading starts a new slide by default.
8
- * Inline formatting (bold, italic, code, links) is preserved as DrawingML runs.
9
- *
10
- * Import is not yet implemented.
11
- *
12
- * @example
13
- * ```ts
14
- * import { markdownDocToPptx } from '@bendyline/squisq-formats/pptx';
15
- * ```
16
- */
17
- // Export
18
- export { markdownDocToPptx, docToPptx } from './export.js';
19
- /**
20
- * Convert a .pptx file to a MarkdownDocument.
21
- *
22
- * @throws Error — PPTX import is not yet implemented
23
- */
24
- export async function pptxToMarkdownDoc(_data, _options) {
25
- throw new Error('PPTX import is not yet implemented');
26
- }
27
- /**
28
- * Convert a .pptx file to a squisq Doc.
29
- *
30
- * @throws Error — PPTX import is not yet implemented
31
- */
32
- export async function pptxToDoc(_data, _options) {
33
- throw new Error('PPTX import is not yet implemented');
34
- }
1
+ import {
2
+ docToPptx,
3
+ markdownDocToPptx,
4
+ pptxToDoc,
5
+ pptxToMarkdownDoc
6
+ } from "../chunk-VN2KEOYB.js";
7
+ import "../chunk-7DEUGIOO.js";
8
+ import "../chunk-U4MRIFKL.js";
9
+ export {
10
+ docToPptx,
11
+ markdownDocToPptx,
12
+ pptxToDoc,
13
+ pptxToMarkdownDoc
14
+ };
35
15
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pptx/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,SAAS;AACT,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAe3D;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAyB,EACzB,QAA4B;IAE5B,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;AACxD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,KAAyB,EACzB,QAA4B;IAE5B,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;AACxD,CAAC"}
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,3 +1,6 @@
1
+ import { MarkdownDocument } from '@bendyline/squisq/markdown';
2
+ import { Doc } from '@bendyline/squisq/schemas';
3
+
1
4
  /**
2
5
  * @bendyline/squisq-formats XLSX Module (Stub)
3
6
  *
@@ -10,12 +13,11 @@
10
13
  * import { markdownDocToXlsx } from '@bendyline/squisq-formats/xlsx';
11
14
  * ```
12
15
  */
13
- import type { MarkdownDocument } from '@bendyline/squisq/markdown';
14
- import type { Doc } from '@bendyline/squisq/schemas';
16
+
15
17
  /**
16
18
  * Options for XLSX export (placeholder).
17
19
  */
18
- export interface XlsxExportOptions {
20
+ interface XlsxExportOptions {
19
21
  /** Workbook title */
20
22
  title?: string;
21
23
  /** Workbook author */
@@ -24,7 +26,7 @@ export interface XlsxExportOptions {
24
26
  /**
25
27
  * Options for XLSX import (placeholder).
26
28
  */
27
- export interface XlsxImportOptions {
29
+ interface XlsxImportOptions {
28
30
  /** Which sheet to import (0-based index or name). Default: 0 */
29
31
  sheet?: number | string;
30
32
  }
@@ -33,23 +35,24 @@ export interface XlsxImportOptions {
33
35
  *
34
36
  * @throws Error — XLSX support is not yet implemented
35
37
  */
36
- export declare function markdownDocToXlsx(_doc: MarkdownDocument, _options?: XlsxExportOptions): Promise<Blob>;
38
+ declare function markdownDocToXlsx(_doc: MarkdownDocument, _options?: XlsxExportOptions): Promise<Blob>;
37
39
  /**
38
40
  * Convert a squisq Doc to a .xlsx Blob.
39
41
  *
40
42
  * @throws Error — XLSX support is not yet implemented
41
43
  */
42
- export declare function docToXlsx(_doc: Doc, _options?: XlsxExportOptions): Promise<Blob>;
44
+ declare function docToXlsx(_doc: Doc, _options?: XlsxExportOptions): Promise<Blob>;
43
45
  /**
44
46
  * Convert a .xlsx file to a MarkdownDocument.
45
47
  *
46
48
  * @throws Error — XLSX support is not yet implemented
47
49
  */
48
- export declare function xlsxToMarkdownDoc(_data: ArrayBuffer | Blob, _options?: XlsxImportOptions): Promise<MarkdownDocument>;
50
+ declare function xlsxToMarkdownDoc(_data: ArrayBuffer | Blob, _options?: XlsxImportOptions): Promise<MarkdownDocument>;
49
51
  /**
50
52
  * Convert a .xlsx file to a squisq Doc.
51
53
  *
52
54
  * @throws Error — XLSX support is not yet implemented
53
55
  */
54
- export declare function xlsxToDoc(_data: ArrayBuffer | Blob, _options?: XlsxImportOptions): Promise<Doc>;
55
- //# sourceMappingURL=index.d.ts.map
56
+ declare function xlsxToDoc(_data: ArrayBuffer | Blob, _options?: XlsxImportOptions): Promise<Doc>;
57
+
58
+ export { type XlsxExportOptions, type XlsxImportOptions, docToXlsx, markdownDocToXlsx, xlsxToDoc, xlsxToMarkdownDoc };
@@ -1,45 +1,13 @@
1
- /**
2
- * @bendyline/squisq-formats XLSX Module (Stub)
3
- *
4
- * Placeholder for Excel .xlsx import/export support.
5
- * Will use SpreadsheetML (`<spreadsheet>`, `<worksheet>`, `<sheetData>`)
6
- * via the shared ooxml/ infrastructure.
7
- *
8
- * @example
9
- * ```ts
10
- * import { markdownDocToXlsx } from '@bendyline/squisq-formats/xlsx';
11
- * ```
12
- */
13
- /**
14
- * Convert a MarkdownDocument to a .xlsx Blob.
15
- *
16
- * @throws Error — XLSX support is not yet implemented
17
- */
18
- export async function markdownDocToXlsx(_doc, _options) {
19
- throw new Error('XLSX export is not yet implemented');
20
- }
21
- /**
22
- * Convert a squisq Doc to a .xlsx Blob.
23
- *
24
- * @throws Error — XLSX support is not yet implemented
25
- */
26
- export async function docToXlsx(_doc, _options) {
27
- throw new Error('XLSX export is not yet implemented');
28
- }
29
- /**
30
- * Convert a .xlsx file to a MarkdownDocument.
31
- *
32
- * @throws Error — XLSX support is not yet implemented
33
- */
34
- export async function xlsxToMarkdownDoc(_data, _options) {
35
- throw new Error('XLSX import is not yet implemented');
36
- }
37
- /**
38
- * Convert a .xlsx file to a squisq Doc.
39
- *
40
- * @throws Error — XLSX support is not yet implemented
41
- */
42
- export async function xlsxToDoc(_data, _options) {
43
- throw new Error('XLSX import is not yet implemented');
44
- }
1
+ import {
2
+ docToXlsx,
3
+ markdownDocToXlsx,
4
+ xlsxToDoc,
5
+ xlsxToMarkdownDoc
6
+ } from "../chunk-67KIJHV2.js";
7
+ export {
8
+ docToXlsx,
9
+ markdownDocToXlsx,
10
+ xlsxToDoc,
11
+ xlsxToMarkdownDoc
12
+ };
45
13
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/xlsx/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAuBH;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,IAAsB,EACtB,QAA4B;IAE5B,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;AACxD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAS,EAAE,QAA4B;IACrE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;AACxD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAyB,EACzB,QAA4B;IAE5B,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;AACxD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,KAAyB,EACzB,QAA4B;IAE5B,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;AACxD,CAAC"}
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bendyline/squisq-formats",
3
- "version": "1.2.3",
3
+ "version": "1.3.1",
4
4
  "description": "Document format converters — DOCX, PDF, OOXML import/export",
5
5
  "license": "MIT",
6
6
  "author": "Bendyline",
@@ -80,10 +80,11 @@
80
80
  },
81
81
  "scripts": {
82
82
  "build": "tsup",
83
+ "dev": "concurrently -n js,dts -c blue,gray -r \"tsup --watch --no-dts --no-clean\" \"tsup --watch --dts-only --no-clean\"",
83
84
  "typecheck": "tsc --noEmit"
84
85
  },
85
86
  "dependencies": {
86
- "@bendyline/squisq": "1.3.0",
87
+ "@bendyline/squisq": "1.4.1",
87
88
  "jszip": "3.10.1",
88
89
  "pdf-lib": "1.17.1",
89
90
  "pdfjs-dist": "4.10.38"
@@ -138,6 +138,61 @@ describe('collectImagePaths', () => {
138
138
  const paths = collectImagePaths(doc);
139
139
  expect(paths.has('cover.jpg')).toBe(true);
140
140
  });
141
+
142
+ it('collects markdown image refs from block contents', () => {
143
+ const doc = makeDoc({
144
+ blocks: [
145
+ {
146
+ id: 'b1',
147
+ startTime: 0,
148
+ duration: 5,
149
+ audioSegment: 0,
150
+ contents: [
151
+ {
152
+ type: 'paragraph',
153
+ children: [{ type: 'image', url: 'body.jpg', alt: '' }],
154
+ },
155
+ ] as unknown as Block['contents'],
156
+ },
157
+ ],
158
+ });
159
+ const paths = collectImagePaths(doc);
160
+ expect(paths.has('body.jpg')).toBe(true);
161
+ });
162
+
163
+ it('collects raw HTML <img> refs from block contents (WYSIWYG resize case)', () => {
164
+ // When the WYSIWYG editor serializes a resized image, it emits a raw
165
+ // `<img src width>` tag because markdown shorthand has no width syntax.
166
+ // The parser produces an htmlBlock node with htmlChildren rather than
167
+ // an image node — earlier this was invisible to the export pipeline.
168
+ const doc = makeDoc({
169
+ blocks: [
170
+ {
171
+ id: 'b1',
172
+ startTime: 0,
173
+ duration: 5,
174
+ audioSegment: 0,
175
+ contents: [
176
+ {
177
+ type: 'htmlBlock',
178
+ rawHtml: '<img alt="resized" src="resized.jpg" width="194">',
179
+ htmlChildren: [
180
+ {
181
+ type: 'htmlElement',
182
+ tagName: 'img',
183
+ attributes: { src: 'resized.jpg', alt: 'resized', width: '194' },
184
+ children: [],
185
+ selfClosing: true,
186
+ },
187
+ ],
188
+ },
189
+ ] as unknown as Block['contents'],
190
+ },
191
+ ],
192
+ });
193
+ const paths = collectImagePaths(doc);
194
+ expect(paths.has('resized.jpg')).toBe(true);
195
+ });
141
196
  });
142
197
 
143
198
  // ============================================
@@ -255,13 +310,36 @@ describe('docToHtmlZip', () => {
255
310
  expect(html).not.toContain(MOCK_PLAYER_SCRIPT);
256
311
  });
257
312
 
258
- it('includes images in images/ folder', async () => {
259
- const doc = makeDoc({ blocks: [makeImageBlock('hero.png')] });
260
- const images = new Map([['hero.png', makeImageBuffer()]]);
313
+ it('preserves the original image path inside the zip', async () => {
314
+ // Direct `<img src="folder/file.png">` references in the rendered HTML
315
+ // resolve only if the zip mirrors the doc's path layout — flattening
316
+ // to `images/<basename>` would 404 in the static renderer (which does
317
+ // not rewrite paths through imagePathMap).
318
+ const doc = makeDoc({ blocks: [makeImageBlock('mikehome_files/hero.png')] });
319
+ const images = new Map([['mikehome_files/hero.png', makeImageBuffer()]]);
320
+ const blob = await docToHtmlZip(doc, { playerScript: MOCK_PLAYER_SCRIPT, images });
321
+
322
+ const zip = await JSZip.loadAsync(await blobToUint8Array(blob));
323
+ expect(zip.file('mikehome_files/hero.png')).not.toBeNull();
324
+ expect(zip.file('images/hero.png')).toBeNull();
325
+ });
326
+
327
+ it('strips leading slashes and rejects parent-traversal paths', async () => {
328
+ const doc = makeDoc();
329
+ const buffer = makeImageBuffer();
330
+ const images = new Map([
331
+ ['/leading/slash.png', buffer],
332
+ ['../escape.png', buffer],
333
+ ['nested/../sneaky.png', buffer],
334
+ ['ok/path.png', buffer],
335
+ ]);
261
336
  const blob = await docToHtmlZip(doc, { playerScript: MOCK_PLAYER_SCRIPT, images });
262
337
 
263
338
  const zip = await JSZip.loadAsync(await blobToUint8Array(blob));
264
- expect(zip.file('images/hero.png')).not.toBeNull();
339
+ expect(zip.file('leading/slash.png')).not.toBeNull();
340
+ expect(zip.file('ok/path.png')).not.toBeNull();
341
+ expect(zip.file('../escape.png')).toBeNull();
342
+ expect(zip.file('nested/../sneaky.png')).toBeNull();
265
343
  });
266
344
 
267
345
  it('includes audio in audio/ folder when provided', async () => {
@@ -311,7 +311,7 @@ describe('docToPdf', () => {
311
311
  startTime: 0,
312
312
  duration: 3,
313
313
  audioSegment: 0,
314
- template: 'titleBlock',
314
+ template: 'title',
315
315
  },
316
316
  ],
317
317
  };