@bendyline/squisq-formats 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -10
- package/dist/{chunk-MQHCXI56.js → chunk-6OVREALI.js} +31 -13
- package/dist/chunk-6OVREALI.js.map +1 -0
- package/dist/{chunk-ULLIPBEJ.js → chunk-743COJWQ.js} +6 -2
- package/dist/chunk-743COJWQ.js.map +1 -0
- package/dist/{chunk-KAK4V57E.js → chunk-BHHEDPRB.js} +16 -112
- package/dist/chunk-BHHEDPRB.js.map +1 -0
- package/dist/chunk-FIFCQN3W.js +630 -0
- package/dist/chunk-FIFCQN3W.js.map +1 -0
- package/dist/chunk-KJ4NS4DX.js +120 -0
- package/dist/chunk-KJ4NS4DX.js.map +1 -0
- package/dist/{chunk-TBPD5PCU.js → chunk-PP5N46YD.js} +33 -11
- package/dist/chunk-PP5N46YD.js.map +1 -0
- package/dist/docx/export.d.ts +6 -0
- package/dist/docx/export.d.ts.map +1 -1
- package/dist/docx/export.js +24 -7
- package/dist/docx/export.js.map +1 -1
- package/dist/html/htmlTemplate.d.ts +6 -0
- package/dist/html/htmlTemplate.d.ts.map +1 -1
- package/dist/html/htmlTemplate.js +5 -1
- package/dist/html/htmlTemplate.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/ooxml/index.d.ts +1 -1
- package/dist/ooxml/index.d.ts.map +1 -1
- package/dist/ooxml/index.js +1 -1
- package/dist/ooxml/index.js.map +1 -1
- package/dist/ooxml/namespaces.d.ts +10 -0
- package/dist/ooxml/namespaces.d.ts.map +1 -1
- package/dist/ooxml/namespaces.js +10 -0
- package/dist/ooxml/namespaces.js.map +1 -1
- package/dist/pdf/export.d.ts +6 -0
- package/dist/pdf/export.d.ts.map +1 -1
- package/dist/pdf/export.js +37 -9
- package/dist/pdf/export.js.map +1 -1
- package/dist/pptx/export.d.ts +75 -0
- package/dist/pptx/export.d.ts.map +1 -0
- package/dist/pptx/export.js +722 -0
- package/dist/pptx/export.js.map +1 -0
- package/dist/pptx/index.d.ts +12 -27
- package/dist/pptx/index.d.ts.map +1 -1
- package/dist/pptx/index.js +12 -22
- package/dist/pptx/index.js.map +1 -1
- package/dist/pptx/styles.d.ts +54 -0
- package/dist/pptx/styles.d.ts.map +1 -0
- package/dist/pptx/styles.js +73 -0
- package/dist/pptx/styles.js.map +1 -0
- package/dist/pptx/templates.d.ts +24 -0
- package/dist/pptx/templates.d.ts.map +1 -0
- package/dist/pptx/templates.js +158 -0
- package/dist/pptx/templates.js.map +1 -0
- package/package.json +2 -2
- package/src/docx/export.ts +36 -8
- package/src/html/htmlTemplate.ts +13 -0
- package/src/index.ts +2 -2
- package/src/ooxml/index.ts +7 -0
- package/src/ooxml/namespaces.ts +23 -0
- package/src/pdf/export.ts +57 -9
- package/src/pptx/export.ts +1041 -0
- package/src/pptx/index.ts +15 -37
- package/src/pptx/styles.ts +96 -0
- package/src/pptx/templates.ts +187 -0
- package/dist/chunk-532L4D5D.js +0 -21
- package/dist/chunk-532L4D5D.js.map +0 -1
- package/dist/chunk-KAK4V57E.js.map +0 -1
- package/dist/chunk-MQHCXI56.js.map +0 -1
- package/dist/chunk-TBPD5PCU.js.map +0 -1
- package/dist/chunk-ULLIPBEJ.js.map +0 -1
package/src/html/htmlTemplate.ts
CHANGED
|
@@ -41,6 +41,13 @@ export interface HtmlExportOptions {
|
|
|
41
41
|
|
|
42
42
|
/** Auto-play slideshow on load (default: false) */
|
|
43
43
|
autoPlay?: boolean;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Squisq theme ID to apply (e.g., 'documentary', 'cinematic').
|
|
47
|
+
* When set, the theme is assigned to the Doc before rendering,
|
|
48
|
+
* so the SquisqPlayer renders with that theme's colors and typography.
|
|
49
|
+
*/
|
|
50
|
+
themeId?: string;
|
|
44
51
|
}
|
|
45
52
|
|
|
46
53
|
// ── Image Path Collection ──────────────────────────────────────────
|
|
@@ -182,8 +189,14 @@ export function generateInlineHtml(doc: Doc, options: HtmlExportOptions): string
|
|
|
182
189
|
mode = 'slideshow',
|
|
183
190
|
title = 'Squisq Document',
|
|
184
191
|
autoPlay = false,
|
|
192
|
+
themeId,
|
|
185
193
|
} = options;
|
|
186
194
|
|
|
195
|
+
// Apply theme to doc if specified (the SquisqPlayer respects doc.themeId at render time)
|
|
196
|
+
if (themeId) {
|
|
197
|
+
doc = { ...doc, themeId };
|
|
198
|
+
}
|
|
199
|
+
|
|
187
200
|
// Build base64 image map
|
|
188
201
|
const imageMap: Record<string, string> = {};
|
|
189
202
|
if (images) {
|
package/src/index.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Supported formats:
|
|
8
8
|
* - **DOCX** — Microsoft Word (import + export) ✅
|
|
9
9
|
* - **PDF** — Portable Document Format (import + export) ✅
|
|
10
|
-
* - **PPTX** — Microsoft PowerPoint (planned)
|
|
10
|
+
* - **PPTX** — Microsoft PowerPoint (export ✅, import planned)
|
|
11
11
|
* - **XLSX** — Microsoft Excel (planned)
|
|
12
12
|
*
|
|
13
13
|
* All converters run in the browser — no server or native binaries required.
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
export { markdownDocToDocx, docToDocx, docxToMarkdownDoc, docxToDoc } from './docx/index.js';
|
|
29
29
|
export type { DocxExportOptions, DocxImportOptions } from './docx/index.js';
|
|
30
30
|
|
|
31
|
-
// PPTX (stub)
|
|
31
|
+
// PPTX (export implemented, import stub)
|
|
32
32
|
export { markdownDocToPptx, docToPptx, pptxToMarkdownDoc, pptxToDoc } from './pptx/index.js';
|
|
33
33
|
export type { PptxExportOptions, PptxImportOptions } from './pptx/index.js';
|
|
34
34
|
|
package/src/ooxml/index.ts
CHANGED
|
@@ -83,5 +83,12 @@ export {
|
|
|
83
83
|
CONTENT_TYPE_DOCX_FONT_TABLE,
|
|
84
84
|
CONTENT_TYPE_DOCX_FOOTNOTES,
|
|
85
85
|
CONTENT_TYPE_PPTX_PRESENTATION,
|
|
86
|
+
CONTENT_TYPE_PPTX_SLIDE,
|
|
87
|
+
CONTENT_TYPE_PPTX_SLIDE_LAYOUT,
|
|
88
|
+
CONTENT_TYPE_PPTX_SLIDE_MASTER,
|
|
89
|
+
CONTENT_TYPE_PPTX_THEME,
|
|
90
|
+
REL_SLIDE,
|
|
91
|
+
REL_SLIDE_LAYOUT,
|
|
92
|
+
REL_SLIDE_MASTER,
|
|
86
93
|
CONTENT_TYPE_XLSX_WORKBOOK,
|
|
87
94
|
} from './namespaces.js';
|
package/src/ooxml/namespaces.ts
CHANGED
|
@@ -156,5 +156,28 @@ export const CONTENT_TYPE_DOCX_FOOTNOTES =
|
|
|
156
156
|
export const CONTENT_TYPE_PPTX_PRESENTATION =
|
|
157
157
|
'application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml';
|
|
158
158
|
|
|
159
|
+
export const CONTENT_TYPE_PPTX_SLIDE =
|
|
160
|
+
'application/vnd.openxmlformats-officedocument.presentationml.slide+xml';
|
|
161
|
+
|
|
162
|
+
export const CONTENT_TYPE_PPTX_SLIDE_LAYOUT =
|
|
163
|
+
'application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml';
|
|
164
|
+
|
|
165
|
+
export const CONTENT_TYPE_PPTX_SLIDE_MASTER =
|
|
166
|
+
'application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml';
|
|
167
|
+
|
|
168
|
+
export const CONTENT_TYPE_PPTX_THEME = 'application/vnd.openxmlformats-officedocument.theme+xml';
|
|
169
|
+
|
|
170
|
+
/** Relationship type: Slide */
|
|
171
|
+
export const REL_SLIDE =
|
|
172
|
+
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide';
|
|
173
|
+
|
|
174
|
+
/** Relationship type: Slide layout */
|
|
175
|
+
export const REL_SLIDE_LAYOUT =
|
|
176
|
+
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout';
|
|
177
|
+
|
|
178
|
+
/** Relationship type: Slide master */
|
|
179
|
+
export const REL_SLIDE_MASTER =
|
|
180
|
+
'http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster';
|
|
181
|
+
|
|
159
182
|
export const CONTENT_TYPE_XLSX_WORKBOOK =
|
|
160
183
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml';
|
package/src/pdf/export.ts
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
import { PDFDocument, StandardFonts, rgb, PDFFont, PDFPage } from 'pdf-lib';
|
|
23
23
|
|
|
24
24
|
import type { Doc } from '@bendyline/squisq/schemas';
|
|
25
|
+
import { resolveTheme } from '@bendyline/squisq/schemas';
|
|
25
26
|
import { docToMarkdown } from '@bendyline/squisq/doc';
|
|
26
27
|
import type {
|
|
27
28
|
MarkdownDocument,
|
|
@@ -103,6 +104,12 @@ export interface PdfExportOptions {
|
|
|
103
104
|
margin?: number;
|
|
104
105
|
/** Default body font size in points. Default: 11. */
|
|
105
106
|
defaultFontSize?: number;
|
|
107
|
+
/**
|
|
108
|
+
* Squisq theme ID to apply (e.g., 'documentary', 'cinematic').
|
|
109
|
+
* When set, overrides heading, text, and link colors with the theme palette.
|
|
110
|
+
* Font changes are not supported (pdf-lib uses standard 14 PDF fonts only).
|
|
111
|
+
*/
|
|
112
|
+
themeId?: string;
|
|
106
113
|
}
|
|
107
114
|
|
|
108
115
|
/**
|
|
@@ -151,6 +158,12 @@ interface FontSet {
|
|
|
151
158
|
monoBold: PDFFont;
|
|
152
159
|
}
|
|
153
160
|
|
|
161
|
+
interface RgbColor {
|
|
162
|
+
r: number;
|
|
163
|
+
g: number;
|
|
164
|
+
b: number;
|
|
165
|
+
}
|
|
166
|
+
|
|
154
167
|
interface ExportContext {
|
|
155
168
|
pdfDoc: PDFDocument;
|
|
156
169
|
fonts: FontSet;
|
|
@@ -166,6 +179,12 @@ interface ExportContext {
|
|
|
166
179
|
contentWidth: number;
|
|
167
180
|
/** Bottom margin y position. */
|
|
168
181
|
bottomY: number;
|
|
182
|
+
/** Resolved colors (may be overridden by theme). */
|
|
183
|
+
colors: {
|
|
184
|
+
text: RgbColor;
|
|
185
|
+
heading: RgbColor;
|
|
186
|
+
link: RgbColor;
|
|
187
|
+
};
|
|
169
188
|
}
|
|
170
189
|
|
|
171
190
|
async function createExportContext(
|
|
@@ -189,6 +208,20 @@ async function createExportContext(
|
|
|
189
208
|
|
|
190
209
|
const page = pdfDoc.addPage([pageWidth, pageHeight]);
|
|
191
210
|
|
|
211
|
+
// Resolve theme colors if themeId is set
|
|
212
|
+
let colorText = COLOR_TEXT;
|
|
213
|
+
let colorHeading = COLOR_HEADING;
|
|
214
|
+
let colorLink = COLOR_LINK;
|
|
215
|
+
|
|
216
|
+
if (options.themeId) {
|
|
217
|
+
const theme = resolveTheme(options.themeId);
|
|
218
|
+
if (theme.colors) {
|
|
219
|
+
colorText = hexToRgb(theme.colors.text) ?? COLOR_TEXT;
|
|
220
|
+
colorHeading = hexToRgb(theme.colors.primary) ?? COLOR_HEADING;
|
|
221
|
+
colorLink = hexToRgb(theme.colors.highlight || theme.colors.secondary) ?? COLOR_LINK;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
192
225
|
return {
|
|
193
226
|
pdfDoc,
|
|
194
227
|
fonts: { regular, bold, italic, boldItalic, mono, monoBold },
|
|
@@ -200,6 +233,7 @@ async function createExportContext(
|
|
|
200
233
|
y: pageHeight - margin,
|
|
201
234
|
contentWidth: pageWidth - 2 * margin,
|
|
202
235
|
bottomY: margin,
|
|
236
|
+
colors: { text: colorText, heading: colorHeading, link: colorLink },
|
|
203
237
|
};
|
|
204
238
|
}
|
|
205
239
|
|
|
@@ -262,7 +296,7 @@ function flattenInlines(
|
|
|
262
296
|
text: (node as MarkdownText).value,
|
|
263
297
|
font,
|
|
264
298
|
fontSize: state.code ? CODE_FONT_SIZE : ctx.fontSize,
|
|
265
|
-
color: state.code ? COLOR_CODE_TEXT : (state.color ??
|
|
299
|
+
color: state.code ? COLOR_CODE_TEXT : (state.color ?? ctx.colors.text),
|
|
266
300
|
link: state.link,
|
|
267
301
|
strikethrough: state.strikethrough,
|
|
268
302
|
});
|
|
@@ -307,7 +341,7 @@ function flattenInlines(
|
|
|
307
341
|
...flattenInlines(linkNode.children, ctx, {
|
|
308
342
|
...state,
|
|
309
343
|
link: linkNode.url,
|
|
310
|
-
color:
|
|
344
|
+
color: ctx.colors.link,
|
|
311
345
|
}),
|
|
312
346
|
);
|
|
313
347
|
break;
|
|
@@ -329,7 +363,7 @@ function flattenInlines(
|
|
|
329
363
|
text: '\n',
|
|
330
364
|
font: ctx.fonts.regular,
|
|
331
365
|
fontSize: ctx.fontSize,
|
|
332
|
-
color:
|
|
366
|
+
color: ctx.colors.text,
|
|
333
367
|
});
|
|
334
368
|
break;
|
|
335
369
|
|
|
@@ -361,7 +395,7 @@ function flattenInlines(
|
|
|
361
395
|
text: `[${ref.identifier}]`,
|
|
362
396
|
font: ctx.fonts.regular,
|
|
363
397
|
fontSize: ctx.fontSize * 0.75,
|
|
364
|
-
color:
|
|
398
|
+
color: ctx.colors.link,
|
|
365
399
|
});
|
|
366
400
|
break;
|
|
367
401
|
}
|
|
@@ -376,7 +410,7 @@ function flattenInlines(
|
|
|
376
410
|
text: fallback.value,
|
|
377
411
|
font: pickFont(ctx, state.bold, state.italic),
|
|
378
412
|
fontSize: ctx.fontSize,
|
|
379
|
-
color: state.color ??
|
|
413
|
+
color: state.color ?? ctx.colors.text,
|
|
380
414
|
});
|
|
381
415
|
}
|
|
382
416
|
break;
|
|
@@ -601,7 +635,7 @@ function renderHeading(node: MarkdownHeading, ctx: ExportContext, extraIndent: n
|
|
|
601
635
|
bold: true,
|
|
602
636
|
italic: false,
|
|
603
637
|
code: false,
|
|
604
|
-
color:
|
|
638
|
+
color: ctx.colors.heading,
|
|
605
639
|
});
|
|
606
640
|
|
|
607
641
|
drawSpans(spans, ctx, w, x0);
|
|
@@ -704,7 +738,7 @@ function renderListItem(
|
|
|
704
738
|
y: ctx.y - ctx.fontSize,
|
|
705
739
|
size: ctx.fontSize,
|
|
706
740
|
font: bulletFont,
|
|
707
|
-
color: rgb(
|
|
741
|
+
color: rgb(ctx.colors.text.r, ctx.colors.text.g, ctx.colors.text.b),
|
|
708
742
|
});
|
|
709
743
|
|
|
710
744
|
const textIndent = indent + bulletWidth + 4;
|
|
@@ -969,7 +1003,7 @@ function renderFootnoteDefinition(
|
|
|
969
1003
|
y: ctx.y - ctx.fontSize * 0.75,
|
|
970
1004
|
size: ctx.fontSize * 0.75,
|
|
971
1005
|
font: ctx.fonts.bold,
|
|
972
|
-
color: rgb(
|
|
1006
|
+
color: rgb(ctx.colors.link.r, ctx.colors.link.g, ctx.colors.link.b),
|
|
973
1007
|
});
|
|
974
1008
|
|
|
975
1009
|
// Render children indented
|
|
@@ -1022,8 +1056,22 @@ function renderFallbackBlock(
|
|
|
1022
1056
|
y: ctx.y - ctx.fontSize,
|
|
1023
1057
|
size: ctx.fontSize,
|
|
1024
1058
|
font: ctx.fonts.regular,
|
|
1025
|
-
color: rgb(
|
|
1059
|
+
color: rgb(ctx.colors.text.r, ctx.colors.text.g, ctx.colors.text.b),
|
|
1026
1060
|
});
|
|
1027
1061
|
ctx.y -= lineH + PARAGRAPH_SPACING;
|
|
1028
1062
|
}
|
|
1029
1063
|
}
|
|
1064
|
+
|
|
1065
|
+
// ============================================
|
|
1066
|
+
// Color Helpers
|
|
1067
|
+
// ============================================
|
|
1068
|
+
|
|
1069
|
+
function hexToRgb(hex: string): RgbColor | undefined {
|
|
1070
|
+
const h = hex.startsWith('#') ? hex.slice(1) : hex;
|
|
1071
|
+
if (h.length !== 6) return undefined;
|
|
1072
|
+
const r = parseInt(h.slice(0, 2), 16);
|
|
1073
|
+
const g = parseInt(h.slice(2, 4), 16);
|
|
1074
|
+
const b = parseInt(h.slice(4, 6), 16);
|
|
1075
|
+
if (isNaN(r) || isNaN(g) || isNaN(b)) return undefined;
|
|
1076
|
+
return { r: r / 255, g: g / 255, b: b / 255 };
|
|
1077
|
+
}
|