@aivorynet/slaide 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/LICENSE +201 -0
- package/README.md +87 -0
- package/bin/slaide.js +25 -0
- package/dist/assets.d.ts +10 -0
- package/dist/assets.js +54 -0
- package/dist/assets.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +433 -0
- package/dist/cli.js.map +1 -0
- package/dist/compare/index.d.ts +24 -0
- package/dist/compare/index.js +246 -0
- package/dist/compare/index.js.map +1 -0
- package/dist/compare/ssim.d.ts +2 -0
- package/dist/compare/ssim.js +46 -0
- package/dist/compare/ssim.js.map +1 -0
- package/dist/compiler/chrome.d.ts +7 -0
- package/dist/compiler/chrome.js +94 -0
- package/dist/compiler/chrome.js.map +1 -0
- package/dist/compiler/compile.d.ts +2 -0
- package/dist/compiler/compile.js +432 -0
- package/dist/compiler/compile.js.map +1 -0
- package/dist/compiler/markdown.d.ts +26 -0
- package/dist/compiler/markdown.js +439 -0
- package/dist/compiler/markdown.js.map +1 -0
- package/dist/compiler/tokens.d.ts +13 -0
- package/dist/compiler/tokens.js +127 -0
- package/dist/compiler/tokens.js.map +1 -0
- package/dist/container.d.ts +47 -0
- package/dist/container.js +309 -0
- package/dist/container.js.map +1 -0
- package/dist/engine-entry.d.ts +1 -0
- package/dist/engine-entry.js +71 -0
- package/dist/engine-entry.js.map +1 -0
- package/dist/export-keynote/keynote.d.ts +10 -0
- package/dist/export-keynote/keynote.js +58 -0
- package/dist/export-keynote/keynote.js.map +1 -0
- package/dist/export-pptx/embed-fonts.d.ts +5 -0
- package/dist/export-pptx/embed-fonts.js +159 -0
- package/dist/export-pptx/embed-fonts.js.map +1 -0
- package/dist/export-pptx/inject-anim.d.ts +28 -0
- package/dist/export-pptx/inject-anim.js +150 -0
- package/dist/export-pptx/inject-anim.js.map +1 -0
- package/dist/export-pptx/pptx.d.ts +10 -0
- package/dist/export-pptx/pptx.js +425 -0
- package/dist/export-pptx/pptx.js.map +1 -0
- package/dist/export-pptx/transitions.d.ts +16 -0
- package/dist/export-pptx/transitions.js +82 -0
- package/dist/export-pptx/transitions.js.map +1 -0
- package/dist/import/emit.d.ts +5 -0
- package/dist/import/emit.js +274 -0
- package/dist/import/emit.js.map +1 -0
- package/dist/import/index.d.ts +21 -0
- package/dist/import/index.js +192 -0
- package/dist/import/index.js.map +1 -0
- package/dist/import/pptx.d.ts +117 -0
- package/dist/import/pptx.js +1043 -0
- package/dist/import/pptx.js.map +1 -0
- package/dist/import/raster-com.d.ts +27 -0
- package/dist/import/raster-com.js +113 -0
- package/dist/import/raster-com.js.map +1 -0
- package/dist/import/raster-extension.d.ts +35 -0
- package/dist/import/raster-extension.js +27 -0
- package/dist/import/raster-extension.js.map +1 -0
- package/dist/index.d.ts +63 -0
- package/dist/index.js +174 -0
- package/dist/index.js.map +1 -0
- package/dist/install/detect.d.ts +17 -0
- package/dist/install/detect.js +82 -0
- package/dist/install/detect.js.map +1 -0
- package/dist/install/index.d.ts +20 -0
- package/dist/install/index.js +126 -0
- package/dist/install/index.js.map +1 -0
- package/dist/install/registry.d.ts +33 -0
- package/dist/install/registry.js +169 -0
- package/dist/install/registry.js.map +1 -0
- package/dist/install/skills.d.ts +17 -0
- package/dist/install/skills.js +72 -0
- package/dist/install/skills.js.map +1 -0
- package/dist/master-io.d.ts +7 -0
- package/dist/master-io.js +55 -0
- package/dist/master-io.js.map +1 -0
- package/dist/mcp/server.d.ts +3 -0
- package/dist/mcp/server.js +114 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/optimize/export-optimize.d.ts +21 -0
- package/dist/optimize/export-optimize.js +167 -0
- package/dist/optimize/export-optimize.js.map +1 -0
- package/dist/parser/frontmatter.d.ts +8 -0
- package/dist/parser/frontmatter.js +45 -0
- package/dist/parser/frontmatter.js.map +1 -0
- package/dist/parser/parse.d.ts +2 -0
- package/dist/parser/parse.js +184 -0
- package/dist/parser/parse.js.map +1 -0
- package/dist/render/anim.d.ts +50 -0
- package/dist/render/anim.js +213 -0
- package/dist/render/anim.js.map +1 -0
- package/dist/render/charts.d.ts +3 -0
- package/dist/render/charts.js +171 -0
- package/dist/render/charts.js.map +1 -0
- package/dist/render/css.d.ts +3 -0
- package/dist/render/css.js +183 -0
- package/dist/render/css.js.map +1 -0
- package/dist/render/echarts-lib.generated.d.ts +1 -0
- package/dist/render/echarts-lib.generated.js +7 -0
- package/dist/render/echarts-lib.generated.js.map +1 -0
- package/dist/render/html.d.ts +5 -0
- package/dist/render/html.js +186 -0
- package/dist/render/html.js.map +1 -0
- package/dist/render/inject.d.ts +12 -0
- package/dist/render/inject.js +19 -0
- package/dist/render/inject.js.map +1 -0
- package/dist/render/mermaid-lib.generated.d.ts +1 -0
- package/dist/render/mermaid-lib.generated.js +7 -0
- package/dist/render/mermaid-lib.generated.js.map +1 -0
- package/dist/render/runtime.d.ts +1 -0
- package/dist/render/runtime.js +393 -0
- package/dist/render/runtime.js.map +1 -0
- package/dist/render-pdf/pdf.d.ts +9 -0
- package/dist/render-pdf/pdf.js +53 -0
- package/dist/render-pdf/pdf.js.map +1 -0
- package/dist/render-png/montage.d.ts +14 -0
- package/dist/render-png/montage.js +75 -0
- package/dist/render-png/montage.js.map +1 -0
- package/dist/render-png/shoot.d.ts +25 -0
- package/dist/render-png/shoot.js +79 -0
- package/dist/render-png/shoot.js.map +1 -0
- package/dist/scaffold.d.ts +9 -0
- package/dist/scaffold.js +36 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/types.d.ts +212 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/util.d.ts +6 -0
- package/dist/util.js +28 -0
- package/dist/util.js.map +1 -0
- package/package.json +66 -0
- package/skills/slaide/SKILL.md +64 -0
- package/skills/slaide/agents/openai.yaml +12 -0
- package/skills/slaide/examples/branded-deck.slaide +198 -0
- package/skills/slaide/examples/branded-theme.slaide.yaml +187 -0
- package/skills/slaide/examples/sample.slaide +98 -0
- package/skills/slaide/reference.md +177 -0
- package/skills/slaide/themes.md +171 -0
- package/themes/aurora.slaide.yaml +136 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// Copyright 2026 AIVory, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
// Embed the deck's web fonts into the .pptx so it renders correctly on a machine that does not
|
|
4
|
+
// have them installed. PowerPoint embeds raw TTF/OTF (it rejects woff2 — what the browser
|
|
5
|
+
// actually downloads), so we re-fetch the Google Fonts CSS with a LEGACY User-Agent (which makes
|
|
6
|
+
// Google serve `.ttf` URLs), download each face, and splice the OOXML embedded-font parts into
|
|
7
|
+
// the generated zip in one pass (mirroring inject-anim.ts).
|
|
8
|
+
//
|
|
9
|
+
// PowerPoint holds at most four faces per typeface (regular/bold/italic/boldItalic). A deck that
|
|
10
|
+
// uses several weights of one family (e.g. Inter 400/500/600/700/800) collapses to two upright
|
|
11
|
+
// slots: runs are emitted bold when weight ≥ 600 (see pptx.ts), so 400/500 use `regular` and
|
|
12
|
+
// 600/700/800 use `bold`. Best-effort throughout: any network failure logs a warning and returns
|
|
13
|
+
// the deck unchanged rather than failing the export.
|
|
14
|
+
import JSZip from 'jszip';
|
|
15
|
+
const SLOTS = ['regular', 'bold', 'italic', 'boldItalic'];
|
|
16
|
+
// A pre-woff2 UA so Google Fonts serves direct TrueType (.ttf) URLs — for every requested
|
|
17
|
+
// weight — instead of woff2 (which PowerPoint rejects). An old-Android UA is the sweet spot:
|
|
18
|
+
// MSIE-era UAs get the obfuscated /l/font loader and only weight 400; modern UAs get woff2.
|
|
19
|
+
const LEGACY_UA = 'Mozilla/5.0 (Linux; U; Android 4.4; en-us) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0';
|
|
20
|
+
const FONT_REL = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/font';
|
|
21
|
+
/** Parse @font-face blocks from a Google Fonts CSS payload into ttf face descriptors. */
|
|
22
|
+
function parseFaces(css) {
|
|
23
|
+
const faces = [];
|
|
24
|
+
for (const m of css.matchAll(/@font-face\s*\{([^}]*)\}/g)) {
|
|
25
|
+
const block = m[1];
|
|
26
|
+
const family = block.match(/font-family:\s*['"]?([^;'"]+)['"]?/)?.[1];
|
|
27
|
+
const weight = parseInt(block.match(/font-weight:\s*(\d+)/)?.[1] ?? '400', 10);
|
|
28
|
+
const italic = /font-style:\s*italic/.test(block);
|
|
29
|
+
const url = block.match(/src:\s*url\(([^)]+\.ttf)\)/)?.[1];
|
|
30
|
+
if (family && url)
|
|
31
|
+
faces.push({ family: family.trim(), weight, italic, url: url.replace(/['"]/g, '') });
|
|
32
|
+
}
|
|
33
|
+
return faces;
|
|
34
|
+
}
|
|
35
|
+
async function fetchText(url) {
|
|
36
|
+
const r = await fetch(url, { headers: { 'User-Agent': LEGACY_UA } });
|
|
37
|
+
if (!r.ok)
|
|
38
|
+
throw new Error(`${url} -> ${r.status}`);
|
|
39
|
+
return r.text();
|
|
40
|
+
}
|
|
41
|
+
async function fetchBin(url) {
|
|
42
|
+
const r = await fetch(url);
|
|
43
|
+
if (!r.ok)
|
|
44
|
+
throw new Error(`${url} -> ${r.status}`);
|
|
45
|
+
return Buffer.from(await r.arrayBuffer());
|
|
46
|
+
}
|
|
47
|
+
/** Reduce all fetched faces of a family to the four slots PowerPoint can embed. */
|
|
48
|
+
function pickSlots(faces) {
|
|
49
|
+
const byFamily = new Map();
|
|
50
|
+
for (const f of faces)
|
|
51
|
+
(byFamily.get(f.family) ?? byFamily.set(f.family, []).get(f.family)).push(f);
|
|
52
|
+
const nearest = (list, target) => list.length ? list.reduce((a, b) => (Math.abs(b.weight - target) < Math.abs(a.weight - target) ? b : a)) : undefined;
|
|
53
|
+
const out = new Map();
|
|
54
|
+
for (const [family, fs] of byFamily) {
|
|
55
|
+
const upright = fs.filter((f) => !f.italic);
|
|
56
|
+
const ital = fs.filter((f) => f.italic);
|
|
57
|
+
const regular = nearest(upright, 400);
|
|
58
|
+
const bold = nearest(upright.filter((f) => f.weight >= 600).length ? upright.filter((f) => f.weight >= 600) : upright, 700);
|
|
59
|
+
const italic = nearest(ital, 400);
|
|
60
|
+
const boldItalic = nearest(ital.filter((f) => f.weight >= 600).length ? ital.filter((f) => f.weight >= 600) : ital, 700);
|
|
61
|
+
out.set(family, {
|
|
62
|
+
regular,
|
|
63
|
+
bold: bold && bold !== regular ? bold : undefined,
|
|
64
|
+
italic,
|
|
65
|
+
boldItalic: boldItalic && boldItalic !== italic ? boldItalic : undefined,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Embed the fonts referenced by `fontImports` (Google Fonts CSS URLs) into a pptx buffer.
|
|
72
|
+
* Returns the buffer unchanged when there's nothing to embed or any fetch fails.
|
|
73
|
+
*/
|
|
74
|
+
export async function embedFonts(pptxBuf, fontImports) {
|
|
75
|
+
const cssUrls = fontImports.filter((u) => /fonts\.googleapis\.com/.test(u));
|
|
76
|
+
if (!cssUrls.length)
|
|
77
|
+
return pptxBuf;
|
|
78
|
+
let faces = [];
|
|
79
|
+
try {
|
|
80
|
+
for (const url of cssUrls)
|
|
81
|
+
faces.push(...parseFaces(await fetchText(url)));
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
console.warn(`Font embed skipped (could not fetch font CSS): ${e.message}`);
|
|
85
|
+
return pptxBuf;
|
|
86
|
+
}
|
|
87
|
+
const slots = pickSlots(faces);
|
|
88
|
+
// flatten to the faces we will download, deduped by url
|
|
89
|
+
const chosen = [];
|
|
90
|
+
for (const [family, s] of slots)
|
|
91
|
+
for (const slot of SLOTS)
|
|
92
|
+
if (s[slot])
|
|
93
|
+
chosen.push({ family, slot, face: s[slot] });
|
|
94
|
+
if (!chosen.length)
|
|
95
|
+
return pptxBuf;
|
|
96
|
+
try {
|
|
97
|
+
const cache = new Map();
|
|
98
|
+
await Promise.all(chosen.map(async (c) => {
|
|
99
|
+
let p = cache.get(c.face.url);
|
|
100
|
+
if (!p)
|
|
101
|
+
cache.set(c.face.url, (p = fetchBin(c.face.url)));
|
|
102
|
+
c.face.data = await p;
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
console.warn(`Font embed skipped (could not download fonts): ${e.message}`);
|
|
107
|
+
return pptxBuf;
|
|
108
|
+
}
|
|
109
|
+
const dl = chosen.filter((c) => c.face.data && c.face.data.length > 0);
|
|
110
|
+
if (!dl.length)
|
|
111
|
+
return pptxBuf;
|
|
112
|
+
const zip = await JSZip.loadAsync(pptxBuf);
|
|
113
|
+
// 1. write font parts and assign relationship ids (above pptxgenjs's existing rIds)
|
|
114
|
+
const relsPath = 'ppt/_rels/presentation.xml.rels';
|
|
115
|
+
let rels = await zip.file(relsPath).async('string');
|
|
116
|
+
let maxId = 0;
|
|
117
|
+
for (const m of rels.matchAll(/Id="rId(\d+)"/g))
|
|
118
|
+
maxId = Math.max(maxId, parseInt(m[1], 10));
|
|
119
|
+
const relAdds = [];
|
|
120
|
+
const byFamilyRids = new Map();
|
|
121
|
+
let n = 0;
|
|
122
|
+
for (const c of dl) {
|
|
123
|
+
const file = `font${++n}.fntdata`;
|
|
124
|
+
zip.file(`ppt/fonts/${file}`, c.face.data);
|
|
125
|
+
const rid = `rId${++maxId}`;
|
|
126
|
+
relAdds.push(`<Relationship Id="${rid}" Type="${FONT_REL}" Target="fonts/${file}"/>`);
|
|
127
|
+
const m = byFamilyRids.get(c.family) ?? byFamilyRids.set(c.family, {}).get(c.family);
|
|
128
|
+
m[c.slot] = rid;
|
|
129
|
+
}
|
|
130
|
+
zip.file(relsPath, rels.replace('</Relationships>', relAdds.join('') + '</Relationships>'));
|
|
131
|
+
// 2. content-type default for .fntdata
|
|
132
|
+
const ctPath = '[Content_Types].xml';
|
|
133
|
+
let ct = await zip.file(ctPath).async('string');
|
|
134
|
+
if (!/Extension="fntdata"/.test(ct)) {
|
|
135
|
+
zip.file(ctPath, ct.replace('</Types>', '<Default Extension="fntdata" ContentType="application/x-fontdata"/></Types>'));
|
|
136
|
+
}
|
|
137
|
+
// 3. presentation.xml: enable embedding + add the embeddedFontLst (CT_Presentation requires it
|
|
138
|
+
// after sldSz/notesSz and before defaultTextStyle).
|
|
139
|
+
const presPath = 'ppt/presentation.xml';
|
|
140
|
+
let pres = await zip.file(presPath).async('string');
|
|
141
|
+
pres = pres.replace(/saveSubsetFonts="1"/, 'saveSubsetFonts="0"');
|
|
142
|
+
if (!/\bembedTrueTypeFonts=/.test(pres)) {
|
|
143
|
+
pres = pres.replace(/<p:presentation\b([^>]*)>/, (_full, attrs) => `<p:presentation${attrs} embedTrueTypeFonts="1">`);
|
|
144
|
+
}
|
|
145
|
+
const efl = '<p:embeddedFontLst>' +
|
|
146
|
+
[...byFamilyRids.entries()]
|
|
147
|
+
.map(([family, m]) => {
|
|
148
|
+
const inner = SLOTS.filter((s) => m[s]).map((s) => `<p:${s} r:id="${m[s]}"/>`).join('');
|
|
149
|
+
return `<p:embeddedFont><p:font typeface="${family}"/>${inner}</p:embeddedFont>`;
|
|
150
|
+
})
|
|
151
|
+
.join('') +
|
|
152
|
+
'</p:embeddedFontLst>';
|
|
153
|
+
pres = pres.includes('<p:defaultTextStyle')
|
|
154
|
+
? pres.replace('<p:defaultTextStyle', efl + '<p:defaultTextStyle')
|
|
155
|
+
: pres.replace('</p:presentation>', efl + '</p:presentation>');
|
|
156
|
+
zip.file(presPath, pres);
|
|
157
|
+
return zip.generateAsync({ type: 'nodebuffer', compression: 'DEFLATE' });
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=embed-fonts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embed-fonts.js","sourceRoot":"","sources":["../../src/export-pptx/embed-fonts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface TransitionSpec {
|
|
2
|
+
name: string;
|
|
3
|
+
durationMs?: number;
|
|
4
|
+
}
|
|
5
|
+
/** A text box that builds: one entry per paragraph, true if that paragraph reveals on click. */
|
|
6
|
+
export interface ShapeBuildSpec {
|
|
7
|
+
pBuilds: boolean[];
|
|
8
|
+
}
|
|
9
|
+
/** Per-slide animation to inject: a transition and/or the slide's build shapes. */
|
|
10
|
+
export interface SlideAnim {
|
|
11
|
+
transition?: TransitionSpec;
|
|
12
|
+
builds?: ShapeBuildSpec[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Inject transitions and per-paragraph builds into a pptx in a single zip pass (one
|
|
16
|
+
* loadAsync/generateAsync), in deck-slide order. Transitions go after <p:clrMapOvr>, build
|
|
17
|
+
* <p:timing> before </p:sld>, so the slide stays schema-valid. Build failures are swallowed
|
|
18
|
+
* per slide so a build never corrupts an otherwise-valid slide.
|
|
19
|
+
*/
|
|
20
|
+
export declare function injectAnim(pptxBuf: Buffer, anims: SlideAnim[], opts?: {
|
|
21
|
+
safe?: boolean;
|
|
22
|
+
}): Promise<Buffer>;
|
|
23
|
+
/** Transitions-only convenience wrapper (one zip pass). specs[i] applies to deck slide i. */
|
|
24
|
+
export declare function injectTransitions(pptxBuf: Buffer, specs: TransitionSpec[], opts?: {
|
|
25
|
+
safe?: boolean;
|
|
26
|
+
}): Promise<Buffer>;
|
|
27
|
+
/** Builds-only convenience wrapper (one zip pass). buildSpecs[i] lists deck slide i's text boxes. */
|
|
28
|
+
export declare function injectBuilds(pptxBuf: Buffer, buildSpecs: ShapeBuildSpec[][]): Promise<Buffer>;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
// Copyright 2026 AIVory, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
// Post-process a pptxgenjs-generated .pptx (a zip) to add what pptxgenjs cannot emit:
|
|
4
|
+
// slide transitions and per-paragraph build (entrance) animations. We splice small XML
|
|
5
|
+
// fragments into each slide part rather than reparse it, because a full parse/serialize
|
|
6
|
+
// round-trip of the DrawingML pptxgenjs writes risks reordering or re-encoding nodes and
|
|
7
|
+
// corrupting an otherwise-valid deck.
|
|
8
|
+
//
|
|
9
|
+
// OOXML slide child order is fixed: cSld, clrMapOvr, transition, timing, extLst. So a
|
|
10
|
+
// <p:transition> is injected right after </p:clrMapOvr>, and <p:timing> right before
|
|
11
|
+
// </p:sld>; pptxgenjs emits no extLst on slides, so this keeps every slide schema-valid.
|
|
12
|
+
import JSZip from 'jszip';
|
|
13
|
+
import { transitionXml } from './transitions.js';
|
|
14
|
+
/** Resolve slide part paths in presentation (deck) order, mirroring the importer. */
|
|
15
|
+
async function orderedSlidePaths(zip) {
|
|
16
|
+
const read = async (p) => {
|
|
17
|
+
const f = zip.file(p);
|
|
18
|
+
return f ? f.async('string') : '';
|
|
19
|
+
};
|
|
20
|
+
const pres = await read('ppt/presentation.xml');
|
|
21
|
+
const rels = await read('ppt/_rels/presentation.xml.rels');
|
|
22
|
+
const relMap = {};
|
|
23
|
+
for (const m of rels.matchAll(/<Relationship\b[^>]*\bId="([^"]+)"[^>]*\bTarget="([^"]+)"/g)) {
|
|
24
|
+
relMap[m[1]] = m[2];
|
|
25
|
+
}
|
|
26
|
+
const paths = [];
|
|
27
|
+
for (const m of pres.matchAll(/<p:sldId\b[^>]*\br:id="([^"]+)"/g)) {
|
|
28
|
+
const target = relMap[m[1]];
|
|
29
|
+
if (target)
|
|
30
|
+
paths.push('ppt/' + target.replace(/^\.\.\//, '').replace(/^\//, ''));
|
|
31
|
+
}
|
|
32
|
+
if (paths.length)
|
|
33
|
+
return paths;
|
|
34
|
+
// fallback: numeric slideN.xml order
|
|
35
|
+
return Object.keys(zip.files)
|
|
36
|
+
.filter((f) => /^ppt\/slides\/slide\d+\.xml$/.test(f))
|
|
37
|
+
.sort((a, b) => parseInt(a.match(/\d+/)[0], 10) - parseInt(b.match(/\d+/)[0], 10));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Inject transitions and per-paragraph builds into a pptx in a single zip pass (one
|
|
41
|
+
* loadAsync/generateAsync), in deck-slide order. Transitions go after <p:clrMapOvr>, build
|
|
42
|
+
* <p:timing> before </p:sld>, so the slide stays schema-valid. Build failures are swallowed
|
|
43
|
+
* per slide so a build never corrupts an otherwise-valid slide.
|
|
44
|
+
*/
|
|
45
|
+
export async function injectAnim(pptxBuf, anims, opts = {}) {
|
|
46
|
+
const zip = await JSZip.loadAsync(pptxBuf);
|
|
47
|
+
const paths = await orderedSlidePaths(zip);
|
|
48
|
+
for (let i = 0; i < paths.length; i++) {
|
|
49
|
+
const a = anims[i];
|
|
50
|
+
if (!a)
|
|
51
|
+
continue;
|
|
52
|
+
let xml = await zip.file(paths[i]).async('string');
|
|
53
|
+
let changed = false;
|
|
54
|
+
if (a.transition && !xml.includes('<p:transition') && !xml.includes('mc:AlternateContent')) {
|
|
55
|
+
const frag = transitionXml(a.transition.name, { durationMs: a.transition.durationMs, safe: opts.safe });
|
|
56
|
+
if (frag) {
|
|
57
|
+
xml = xml.replace('</p:clrMapOvr>', '</p:clrMapOvr>' + frag);
|
|
58
|
+
changed = true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (a.builds && a.builds.length && !xml.includes('<p:timing')) {
|
|
62
|
+
try {
|
|
63
|
+
const spids = textSpids(xml);
|
|
64
|
+
const shapes = a.builds
|
|
65
|
+
.map((s, j) => ({
|
|
66
|
+
spid: spids[j],
|
|
67
|
+
paras: s.pBuilds.map((b, p) => (b ? p : -1)).filter((p) => p >= 0),
|
|
68
|
+
}))
|
|
69
|
+
.filter((s) => s.spid !== undefined && s.paras.length);
|
|
70
|
+
const timing = timingXml(shapes);
|
|
71
|
+
if (timing) {
|
|
72
|
+
xml = xml.replace('</p:sld>', timing + '</p:sld>');
|
|
73
|
+
changed = true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// leave this slide's builds out rather than risk invalid XML
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (changed)
|
|
81
|
+
zip.file(paths[i], xml);
|
|
82
|
+
}
|
|
83
|
+
return zip.generateAsync({ type: 'nodebuffer', compression: 'DEFLATE' });
|
|
84
|
+
}
|
|
85
|
+
/** Transitions-only convenience wrapper (one zip pass). specs[i] applies to deck slide i. */
|
|
86
|
+
export function injectTransitions(pptxBuf, specs, opts = {}) {
|
|
87
|
+
return injectAnim(pptxBuf, specs.map((s) => ({ transition: s })), opts);
|
|
88
|
+
}
|
|
89
|
+
/** Builds-only convenience wrapper (one zip pass). buildSpecs[i] lists deck slide i's text boxes. */
|
|
90
|
+
export function injectBuilds(pptxBuf, buildSpecs) {
|
|
91
|
+
return injectAnim(pptxBuf, buildSpecs.map((b) => ({ builds: b })));
|
|
92
|
+
}
|
|
93
|
+
/** Collect the shape ids of text-bearing <p:sp> shapes, in document (= add) order. */
|
|
94
|
+
function textSpids(slideXml) {
|
|
95
|
+
const ids = [];
|
|
96
|
+
for (const m of slideXml.matchAll(/<p:sp\b[^>]*>([\s\S]*?)<\/p:sp>/g)) {
|
|
97
|
+
const block = m[1];
|
|
98
|
+
if (!block.includes('<a:t>'))
|
|
99
|
+
continue; // a fill/border rect has no <a:t>
|
|
100
|
+
const id = block.match(/<p:cNvPr\b[^>]*\bid="(\d+)"/);
|
|
101
|
+
if (id)
|
|
102
|
+
ids.push(parseInt(id[1], 10));
|
|
103
|
+
}
|
|
104
|
+
return ids;
|
|
105
|
+
}
|
|
106
|
+
let _idSeq = 0;
|
|
107
|
+
const nextId = () => ++_idSeq;
|
|
108
|
+
/** One click-reveal of a single paragraph (pRg st=end=para) of a shape, as a mainSeq <p:par>. */
|
|
109
|
+
function clickPar(spid, para) {
|
|
110
|
+
const a = nextId();
|
|
111
|
+
const b = nextId();
|
|
112
|
+
const c = nextId();
|
|
113
|
+
const d = nextId();
|
|
114
|
+
return (`<p:par><p:cTn id="${a}" fill="hold">` +
|
|
115
|
+
`<p:stCondLst><p:cond delay="indefinite"/></p:stCondLst><p:childTnLst>` +
|
|
116
|
+
`<p:par><p:cTn id="${b}" fill="hold">` +
|
|
117
|
+
`<p:stCondLst><p:cond delay="0"/></p:stCondLst><p:childTnLst>` +
|
|
118
|
+
`<p:par><p:cTn id="${c}" presetID="1" presetClass="entr" presetSubtype="0" fill="hold" grpId="0" nodeType="clickEffect">` +
|
|
119
|
+
`<p:stCondLst><p:cond delay="0"/></p:stCondLst><p:childTnLst>` +
|
|
120
|
+
`<p:set><p:cBhvr>` +
|
|
121
|
+
`<p:cTn id="${d}" dur="1" fill="hold"><p:stCondLst><p:cond delay="0"/></p:stCondLst></p:cTn>` +
|
|
122
|
+
`<p:tgtEl><p:spTgt spid="${spid}"><p:txEl><p:pRg st="${para}" end="${para}"/></p:txEl></p:spTgt></p:tgtEl>` +
|
|
123
|
+
`<p:attrNameLst><p:attrName>style.visibility</p:attrName></p:attrNameLst>` +
|
|
124
|
+
`</p:cBhvr><p:to><p:strVal val="visible"/></p:to></p:set>` +
|
|
125
|
+
`</p:childTnLst></p:cTn></p:par>` +
|
|
126
|
+
`</p:childTnLst></p:cTn></p:par>` +
|
|
127
|
+
`</p:childTnLst></p:cTn></p:par>`);
|
|
128
|
+
}
|
|
129
|
+
/** Build the full <p:timing> for a slide given which paragraphs of which shapes reveal. */
|
|
130
|
+
function timingXml(shapes) {
|
|
131
|
+
const active = shapes.filter((s) => s.paras.length);
|
|
132
|
+
if (!active.length)
|
|
133
|
+
return '';
|
|
134
|
+
_idSeq = 1; // tmRoot=1, mainSeq=2, then click effects
|
|
135
|
+
const root = nextId(); // 1
|
|
136
|
+
const main = nextId(); // 2
|
|
137
|
+
const clicks = active.flatMap((s) => s.paras.map((p) => clickPar(s.spid, p))).join('');
|
|
138
|
+
const bldp = active.map((s) => `<p:bldP spid="${s.spid}" grpId="0" build="p"/>`).join('');
|
|
139
|
+
return (`<p:timing><p:tnLst>` +
|
|
140
|
+
`<p:par><p:cTn id="${root}" dur="indefinite" restart="never" nodeType="tmRoot"><p:childTnLst>` +
|
|
141
|
+
`<p:seq concurrent="1" nextAc="seek"><p:cTn id="${main}" dur="indefinite" nodeType="mainSeq"><p:childTnLst>` +
|
|
142
|
+
clicks +
|
|
143
|
+
`</p:childTnLst></p:cTn>` +
|
|
144
|
+
`<p:prevCondLst><p:cond evt="onPrev" delay="0"><p:tgtEl><p:sldTgt/></p:tgtEl></p:cond></p:prevCondLst>` +
|
|
145
|
+
`<p:nextCondLst><p:cond evt="onNext" delay="0"><p:tgtEl><p:sldTgt/></p:tgtEl></p:cond></p:nextCondLst>` +
|
|
146
|
+
`</p:seq>` +
|
|
147
|
+
`</p:childTnLst></p:cTn></p:par>` +
|
|
148
|
+
`</p:tnLst><p:bldLst>${bldp}</p:bldLst></p:timing>`);
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=inject-anim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject-anim.js","sourceRoot":"","sources":["../../src/export-pptx/inject-anim.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface PptxOptions {
|
|
2
|
+
out: string;
|
|
3
|
+
/** inject slide transitions (default true). */
|
|
4
|
+
transitions?: boolean;
|
|
5
|
+
/** inject per-paragraph build/entrance animations (default true). */
|
|
6
|
+
builds?: boolean;
|
|
7
|
+
/** embed the deck's web fonts into the file so it renders without them installed (default true). */
|
|
8
|
+
embedFonts?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function exportPptx(deckPath: string, opts: PptxOptions, injected?: import('playwright').Browser): Promise<string>;
|