ppt-dsl-renderer 1.1.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 (49) hide show
  1. package/AGENT_PPTX_EXPORT.md +81 -0
  2. package/AGENT_USAGE.md +87 -0
  3. package/LICENSE +21 -0
  4. package/README.md +112 -0
  5. package/THIRD_PARTY_NOTICES.md +43 -0
  6. package/dist/browser/renderer.css +1 -0
  7. package/dist/browser/renderer.js +80 -0
  8. package/dist/cli.js +243 -0
  9. package/dist/index.js +140 -0
  10. package/dist/pptx/exporter.js +129 -0
  11. package/dist/pptx/index.js +7437 -0
  12. package/dist/vue/renderer.css +1 -0
  13. package/dist/vue/renderer.js +577 -0
  14. package/docs/AGENT.md +36 -0
  15. package/docs/DSL.md +60 -0
  16. package/docs/VUE.md +231 -0
  17. package/examples/deck.json +302 -0
  18. package/package.json +85 -0
  19. package/src/index.d.ts +24 -0
  20. package/src/pptx.d.ts +30 -0
  21. package/src/types/ppt-dsl.d.ts +241 -0
  22. package/src/types/vue.d.ts +40 -0
  23. package/src/vue.d.ts +16 -0
  24. package/third-party-licenses/core-util-is/LICENSE +19 -0
  25. package/third-party-licenses/dompurify/LICENSE +568 -0
  26. package/third-party-licenses/echarts/LICENSE +222 -0
  27. package/third-party-licenses/echarts/LICENSE-d3 +27 -0
  28. package/third-party-licenses/echarts/NOTICE +5 -0
  29. package/third-party-licenses/immediate/LICENSE.txt +20 -0
  30. package/third-party-licenses/inherits/LICENSE +16 -0
  31. package/third-party-licenses/isarray/LICENSE +22 -0
  32. package/third-party-licenses/jszip/LICENSE.markdown +651 -0
  33. package/third-party-licenses/lie/license.md +7 -0
  34. package/third-party-licenses/pako/LICENSE +21 -0
  35. package/third-party-licenses/pptxgenjs/LICENSE +21 -0
  36. package/third-party-licenses/readable-stream/LICENSE +47 -0
  37. package/third-party-licenses/safe-buffer/LICENSE +21 -0
  38. package/third-party-licenses/setimmediate/LICENSE.txt +20 -0
  39. package/third-party-licenses/string_decoder/LICENSE +48 -0
  40. package/third-party-licenses/svg-pathdata/LICENSE +20 -0
  41. package/third-party-licenses/tinycolor2/LICENSE +20 -0
  42. package/third-party-licenses/tslib/LICENSE.txt +12 -0
  43. package/third-party-licenses/util-deprecate/LICENSE +24 -0
  44. package/third-party-licenses/vue/LICENSE +21 -0
  45. package/third-party-licenses/vue-reactivity/LICENSE +21 -0
  46. package/third-party-licenses/vue-runtime-core/LICENSE +21 -0
  47. package/third-party-licenses/vue-runtime-dom/LICENSE +21 -0
  48. package/third-party-licenses/vue-shared/LICENSE +21 -0
  49. package/third-party-licenses/zrender/LICENSE +29 -0
package/dist/cli.js ADDED
@@ -0,0 +1,243 @@
1
+ #!/usr/bin/env node
2
+ import { parseArgs as U } from "node:util";
3
+ import { readFile as $, mkdir as T, writeFile as L, rename as B, rm as _ } from "node:fs/promises";
4
+ import { resolve as f, dirname as N, join as S } from "node:path";
5
+ import { fileURLToPath as k } from "node:url";
6
+ import { randomUUID as C } from "node:crypto";
7
+ function J(t) {
8
+ const e = { status: "loading", errors: [] };
9
+ t.__PPT_DSL_RENDER__ = e;
10
+ const s = (i) => {
11
+ e.status = "error", e.errors.push(i);
12
+ };
13
+ t.addEventListener("error", (i) => {
14
+ var a;
15
+ i.message ? s(i.message) : (a = i.target) != null && a.src && s(`资源加载失败:${i.target.src}`);
16
+ }, !0), t.addEventListener("unhandledrejection", (i) => {
17
+ var a;
18
+ s(((a = i.reason) == null ? void 0 : a.message) || String(i.reason));
19
+ }), t.setTimeout(() => {
20
+ e.status === "loading" && s("渲染超过 30 秒仍未完成");
21
+ }, 3e4);
22
+ }
23
+ function H(t) {
24
+ const { width: e, height: s } = JSON.parse(t.document.getElementById("ppt-dsl-data").textContent), i = t.document.getElementById("ppt-stage"), a = t.document.getElementById("ppt-root");
25
+ a.style.width = `${e}px`, a.style.height = `${s}px`;
26
+ const l = () => {
27
+ const d = Math.min(1, t.innerWidth / e, t.innerHeight / s);
28
+ i.style.width = `${e * d}px`, i.style.height = `${s * d}px`, a.style.transform = `scale(${d})`;
29
+ };
30
+ l(), t.addEventListener("resize", l);
31
+ }
32
+ function X(t, e, s) {
33
+ const i = t.replaceAll("<", "\\u003c").replaceAll("\u2028", "\\u2028").replaceAll("\u2029", "\\u2029");
34
+ return `<!doctype html>
35
+ <html lang="zh-CN">
36
+ <head>
37
+ <meta charset="utf-8">
38
+ <meta name="viewport" content="width=device-width, initial-scale=1">
39
+ <title>PPT DSL</title>
40
+ <style>${s.replace(/<\/style/gi, "<\\/style")}
41
+ html, body { width: 100%; height: 100%; overflow: hidden; }
42
+ #ppt-viewport { position: fixed; inset: 0; display: grid; place-items: center; background: #f2f4f6; }
43
+ #ppt-stage { position: relative; }
44
+ #ppt-root { position: absolute; top: 0; left: 0; transform-origin: top left; }
45
+ </style>
46
+ </head>
47
+ <body>
48
+ <div id="ppt-viewport"><div id="ppt-stage"><div id="ppt-root"></div></div></div>
49
+ <script id="ppt-dsl-data" type="application/json">${i}<\/script>
50
+ <script>(${J.toString()})(window);(${H.toString()})(window);<\/script>
51
+ <script>${e.replace(/<\/script/gi, "<\\/script")}<\/script>
52
+ </body>
53
+ </html>`;
54
+ }
55
+ const z = /* @__PURE__ */ new Set(["text", "image", "shape", "line", "chart", "table", "latex", "video", "audio"]), M = /* @__PURE__ */ new Set(["area", "bar", "column", "line", "pie", "radar", "ring", "scatter"]), b = (t) => t !== null && typeof t == "object" && !Array.isArray(t), h = (t) => typeof t == "string", v = (t) => Array.isArray(t) && t.length === 2 && t.every(Number.isFinite);
56
+ function n(t, e) {
57
+ if (!t)
58
+ throw new Error(e);
59
+ }
60
+ function E(t, e) {
61
+ n(h(t) && /^(https?:\/\/|data:)/i.test(t), `${e} 必须使用 HTTP(S) URL 或 data URL`);
62
+ const s = new URL(t);
63
+ n(["http:", "https:", "data:"].includes(s.protocol), `${e} 资源协议不受支持`);
64
+ }
65
+ function D(t) {
66
+ n(b(t), "DSL 顶层必须是对象"), n(h(t.title) && t.title.length > 0, "DSL 缺少 title"), n(Number.isFinite(t.width) && t.width > 0, "DSL width 必须是大于 0 的有限数值"), n(Number.isFinite(t.height) && t.height > 0, "DSL height 必须是大于 0 的有限数值"), n(Array.isArray(t.slides) && t.slides.length > 0, "DSL slides 不能为空"), t.slides.forEach((e, s) => {
67
+ var l, d;
68
+ const i = `第 ${s + 1} 页`;
69
+ n(b(e) && h(e.id) && e.id && Array.isArray(e.elements), `${i}结构无效`), ((l = e.background) == null ? void 0 : l.type) === "image" && E((d = e.background.image) == null ? void 0 : d.src, `${i}背景图`);
70
+ const a = /* @__PURE__ */ new Set();
71
+ e.elements.forEach((r) => {
72
+ var g;
73
+ n(b(r) && h(r.id) && r.id && z.has(r.type), `${i}存在无效元素`);
74
+ const p = `${i}元素 ${r.id}`;
75
+ n(!a.has(r.id), `${p} ID 重复`), a.add(r.id), n([r.left, r.top].every(Number.isFinite), `${p}缺少有效坐标`);
76
+ for (const o of ["width", "height", "rotate", "opacity"])
77
+ r[o] !== void 0 && n(Number.isFinite(r[o]), `${p}.${o} 必须是有限数值`);
78
+ switch (r.type) {
79
+ case "text":
80
+ n(h(r.content), `${p}.content 必须是字符串`);
81
+ break;
82
+ case "image":
83
+ case "audio":
84
+ case "video":
85
+ E(r.src, `${p}.src`), r.poster !== void 0 && E(r.poster, `${p}.poster`);
86
+ break;
87
+ case "shape":
88
+ n(h(r.path) && v(r.viewBox), `${p}缺少 path 或有效 viewBox`), r.text !== void 0 && n(h((g = r.text) == null ? void 0 : g.content), `${p}.text.content 必须是字符串`);
89
+ break;
90
+ case "line":
91
+ n(v(r.start) && v(r.end) && h(r.color), `${p}缺少 start、end 或 color`);
92
+ break;
93
+ case "chart": {
94
+ const o = r.data;
95
+ n(M.has(r.chartType), `${p}.chartType 不受支持`), n(b(o) && Array.isArray(o.labels) && o.labels.every(h) && Array.isArray(o.legends) && o.legends.every(h) && Array.isArray(o.series) && o.series.every((c) => Array.isArray(c) && c.every(Number.isFinite)), `${p}.data 结构无效`);
96
+ break;
97
+ }
98
+ case "table":
99
+ n(Array.isArray(r.data) && r.data.every((o) => Array.isArray(o) && o.every((c) => b(c) && h(c.id) && c.id && h(c.text))), `${p}.data 结构无效`);
100
+ break;
101
+ case "latex":
102
+ n(h(r.latex), `${p}.latex 必须是字符串`);
103
+ break;
104
+ }
105
+ });
106
+ });
107
+ }
108
+ function F(t, e) {
109
+ return e === void 0 ? Array.from({ length: t }, (s, i) => i + 1) : (n(Array.isArray(e) && e.length > 0, "pages 必须是非空页码数组"), n(e.every((s) => Number.isInteger(s) && s >= 1 && s <= t), `页码必须是 1 到 ${t} 的整数`), [...new Set(e)].sort((s, i) => s - i));
110
+ }
111
+ const P = f(N(k(import.meta.url)), "..");
112
+ async function q(t, e = {}) {
113
+ D(t);
114
+ const i = F(t.slides.length, e.pages).map((d) => ({
115
+ pageNumber: d,
116
+ slideId: t.slides[d - 1].id,
117
+ width: t.width,
118
+ height: t.height,
119
+ payload: JSON.stringify({
120
+ title: t.title,
121
+ width: t.width,
122
+ height: t.height,
123
+ pageNumber: d,
124
+ slide: t.slides[d - 1]
125
+ })
126
+ }));
127
+ let a, l;
128
+ try {
129
+ [a, l] = await Promise.all([
130
+ $(S(P, "dist/browser/renderer.js"), "utf8"),
131
+ $(S(P, "dist/browser/renderer.css"), "utf8")
132
+ ]);
133
+ } catch (d) {
134
+ throw d.code !== "ENOENT" ? d : new Error("缺少预编译浏览器资源。源码仓库请先显式执行 yarn build;npm 安装包应包含 dist/browser。", { cause: d });
135
+ }
136
+ return i.map(({ payload: d, ...r }) => ({
137
+ ...r,
138
+ html: X(d, a, l)
139
+ }));
140
+ }
141
+ const V = f(N(k(import.meta.url)), "..");
142
+ async function W(t, e, { pages: s, executablePath: i, timeout: a = 12e4 } = {}) {
143
+ D(t);
144
+ const l = F(t.slides.length, s), d = await $(S(V, "dist/pptx/exporter.js"), "utf8").catch((u) => {
145
+ throw u.code !== "ENOENT" ? u : new Error("安装包缺少 PPTX 运行产物,请使用完整构建的 ppt-dsl-renderer 包。", { cause: u });
146
+ }), { chromium: r } = await import("playwright-core"), p = await r.launch({ headless: !0, ...i ? { executablePath: i } : { channel: "chrome" }, timeout: a });
147
+ let g, o;
148
+ try {
149
+ const u = (async () => {
150
+ const w = await p.newPage();
151
+ w.on("console", (y) => console.error(y.text())), w.on("pageerror", (y) => console.error(y.message)), await w.addScriptTag({ content: d });
152
+ const A = await w.evaluate(async ({ document: y, pages: j }) => {
153
+ const I = await window.exportToPptx(y, { pages: j });
154
+ return new Promise((O, R) => {
155
+ const m = new FileReader();
156
+ m.onload = () => O(m.result.split(",", 2)[1]), m.onerror = () => R(m.error), m.readAsDataURL(new Blob([I]));
157
+ });
158
+ }, { document: t, pages: l });
159
+ return Buffer.from(A, "base64");
160
+ })();
161
+ o = await Promise.race([
162
+ u,
163
+ new Promise((w, A) => {
164
+ g = setTimeout(() => A(new Error(`PPTX 导出超时(${a}ms)`)), a);
165
+ })
166
+ ]);
167
+ } finally {
168
+ clearTimeout(g), await p.close();
169
+ }
170
+ await T(N(e), { recursive: !0 });
171
+ const c = `${e}.${C()}.tmp`;
172
+ try {
173
+ await L(c, o, { flag: "wx" }), await B(c, e);
174
+ } finally {
175
+ await _(c, { force: !0 });
176
+ }
177
+ return { file: e, pages: l.map((u) => ({ pageNumber: u, slideId: t.slides[u - 1].id })), bytes: o.length };
178
+ }
179
+ const x = `Usage:
180
+ ppt-dsl-renderer render <deck.json> --out-dir <directory> [--pages 1,3]
181
+ ppt-dsl-renderer export-pptx <deck.json> --out <file.pptx> [--pages 1,3]
182
+
183
+ PPTX options:
184
+ --browser-executable <path> Use an existing Chromium executable (default: installed Chrome).
185
+ --timeout <milliseconds> Browser launch/export timeout (default: 120000).
186
+
187
+ Page numbers start at 1. Success writes a JSON file manifest to stdout.
188
+ Errors and browser diagnostics go to stderr; failure exits with code 1.
189
+ render generates HTML without launching a browser.
190
+ export-pptx requires Chrome or Chromium installed at deployment time; it never downloads a browser.`;
191
+ async function G() {
192
+ var g;
193
+ const { values: t, positionals: e } = U({
194
+ allowPositionals: !0,
195
+ options: {
196
+ "out-dir": { type: "string" },
197
+ out: { type: "string" },
198
+ pages: { type: "string" },
199
+ "browser-executable": { type: "string" },
200
+ timeout: { type: "string" },
201
+ help: { type: "boolean", short: "h" }
202
+ }
203
+ });
204
+ if (t.help) {
205
+ console.log(x);
206
+ return;
207
+ }
208
+ const [s, i] = e;
209
+ if (e.length !== 2 || !["render", "export-pptx"].includes(s))
210
+ throw new Error(x);
211
+ if (s === "render" && (!t["out-dir"] || t.out !== void 0 || t["browser-executable"] !== void 0 || t.timeout !== void 0))
212
+ throw new Error(x);
213
+ if (s === "export-pptx" && (!t.out || t["out-dir"] !== void 0))
214
+ throw new Error(x);
215
+ if (t.pages !== void 0 && !/^\d+(,\d+)*$/.test(t.pages))
216
+ throw new Error("--pages 格式必须为 1,3 这样的页码列表");
217
+ const a = (g = t.pages) == null ? void 0 : g.split(",").map(Number);
218
+ if (t.timeout !== void 0 && (!/^\d+$/.test(t.timeout) || !Number.isSafeInteger(Number(t.timeout)) || Number(t.timeout) <= 0))
219
+ throw new Error("--timeout 必须是正整数毫秒");
220
+ if (s === "export-pptx" && f(i) === f(t.out))
221
+ throw new Error("--out 不能覆盖输入 DSL 文件");
222
+ const l = JSON.parse(await $(f(i), "utf8"));
223
+ if (s === "export-pptx") {
224
+ const o = await W(l, f(t.out), {
225
+ pages: a,
226
+ executablePath: t["browser-executable"] ? f(t["browser-executable"]) : void 0,
227
+ timeout: t.timeout === void 0 ? void 0 : Number(t.timeout)
228
+ });
229
+ console.log(JSON.stringify(o, null, 2));
230
+ return;
231
+ }
232
+ const d = await q(l, { pages: a }), r = f(t["out-dir"]);
233
+ await T(r, { recursive: !0 });
234
+ const p = [];
235
+ for (const { html: o, ...c } of d) {
236
+ const u = S(r, `slide-${String(c.pageNumber).padStart(3, "0")}.html`);
237
+ await L(u, o, "utf8"), p.push({ ...c, file: u });
238
+ }
239
+ console.log(JSON.stringify({ pages: p }, null, 2));
240
+ }
241
+ G().catch((t) => {
242
+ console.error(t.message), process.exitCode = 1;
243
+ });
package/dist/index.js ADDED
@@ -0,0 +1,140 @@
1
+ import { readFile as $ } from "node:fs/promises";
2
+ import { resolve as A, dirname as S, join as b } from "node:path";
3
+ import { fileURLToPath as v } from "node:url";
4
+ function x(t) {
5
+ const r = { status: "loading", errors: [] };
6
+ t.__PPT_DSL_RENDER__ = r;
7
+ const s = (e) => {
8
+ r.status = "error", r.errors.push(e);
9
+ };
10
+ t.addEventListener("error", (e) => {
11
+ var n;
12
+ e.message ? s(e.message) : (n = e.target) != null && n.src && s(`资源加载失败:${e.target.src}`);
13
+ }, !0), t.addEventListener("unhandledrejection", (e) => {
14
+ var n;
15
+ s(((n = e.reason) == null ? void 0 : n.message) || String(e.reason));
16
+ }), t.setTimeout(() => {
17
+ r.status === "loading" && s("渲染超过 30 秒仍未完成");
18
+ }, 3e4);
19
+ }
20
+ function E(t) {
21
+ const { width: r, height: s } = JSON.parse(t.document.getElementById("ppt-dsl-data").textContent), e = t.document.getElementById("ppt-stage"), n = t.document.getElementById("ppt-root");
22
+ n.style.width = `${r}px`, n.style.height = `${s}px`;
23
+ const p = () => {
24
+ const o = Math.min(1, t.innerWidth / r, t.innerHeight / s);
25
+ e.style.width = `${r * o}px`, e.style.height = `${s * o}px`, n.style.transform = `scale(${o})`;
26
+ };
27
+ p(), t.addEventListener("resize", p);
28
+ }
29
+ function L(t, r, s) {
30
+ const e = t.replaceAll("<", "\\u003c").replaceAll("\u2028", "\\u2028").replaceAll("\u2029", "\\u2029");
31
+ return `<!doctype html>
32
+ <html lang="zh-CN">
33
+ <head>
34
+ <meta charset="utf-8">
35
+ <meta name="viewport" content="width=device-width, initial-scale=1">
36
+ <title>PPT DSL</title>
37
+ <style>${s.replace(/<\/style/gi, "<\\/style")}
38
+ html, body { width: 100%; height: 100%; overflow: hidden; }
39
+ #ppt-viewport { position: fixed; inset: 0; display: grid; place-items: center; background: #f2f4f6; }
40
+ #ppt-stage { position: relative; }
41
+ #ppt-root { position: absolute; top: 0; left: 0; transform-origin: top left; }
42
+ </style>
43
+ </head>
44
+ <body>
45
+ <div id="ppt-viewport"><div id="ppt-stage"><div id="ppt-root"></div></div></div>
46
+ <script id="ppt-dsl-data" type="application/json">${e}<\/script>
47
+ <script>(${x.toString()})(window);(${E.toString()})(window);<\/script>
48
+ <script>${r.replace(/<\/script/gi, "<\\/script")}<\/script>
49
+ </body>
50
+ </html>`;
51
+ }
52
+ const T = /* @__PURE__ */ new Set(["text", "image", "shape", "line", "chart", "table", "latex", "video", "audio"]), k = /* @__PURE__ */ new Set(["area", "bar", "column", "line", "pie", "radar", "ring", "scatter"]), y = (t) => t !== null && typeof t == "object" && !Array.isArray(t), c = (t) => typeof t == "string", g = (t) => Array.isArray(t) && t.length === 2 && t.every(Number.isFinite);
53
+ function a(t, r) {
54
+ if (!t)
55
+ throw new Error(r);
56
+ }
57
+ function f(t, r) {
58
+ a(c(t) && /^(https?:\/\/|data:)/i.test(t), `${r} 必须使用 HTTP(S) URL 或 data URL`);
59
+ const s = new URL(t);
60
+ a(["http:", "https:", "data:"].includes(s.protocol), `${r} 资源协议不受支持`);
61
+ }
62
+ function N(t) {
63
+ a(y(t), "DSL 顶层必须是对象"), a(c(t.title) && t.title.length > 0, "DSL 缺少 title"), a(Number.isFinite(t.width) && t.width > 0, "DSL width 必须是大于 0 的有限数值"), a(Number.isFinite(t.height) && t.height > 0, "DSL height 必须是大于 0 的有限数值"), a(Array.isArray(t.slides) && t.slides.length > 0, "DSL slides 不能为空"), t.slides.forEach((r, s) => {
64
+ var p, o;
65
+ const e = `第 ${s + 1} 页`;
66
+ a(y(r) && c(r.id) && r.id && Array.isArray(r.elements), `${e}结构无效`), ((p = r.background) == null ? void 0 : p.type) === "image" && f((o = r.background.image) == null ? void 0 : o.src, `${e}背景图`);
67
+ const n = /* @__PURE__ */ new Set();
68
+ r.elements.forEach((i) => {
69
+ var w;
70
+ a(y(i) && c(i.id) && i.id && T.has(i.type), `${e}存在无效元素`);
71
+ const h = `${e}元素 ${i.id}`;
72
+ a(!n.has(i.id), `${h} ID 重复`), n.add(i.id), a([i.left, i.top].every(Number.isFinite), `${h}缺少有效坐标`);
73
+ for (const d of ["width", "height", "rotate", "opacity"])
74
+ i[d] !== void 0 && a(Number.isFinite(i[d]), `${h}.${d} 必须是有限数值`);
75
+ switch (i.type) {
76
+ case "text":
77
+ a(c(i.content), `${h}.content 必须是字符串`);
78
+ break;
79
+ case "image":
80
+ case "audio":
81
+ case "video":
82
+ f(i.src, `${h}.src`), i.poster !== void 0 && f(i.poster, `${h}.poster`);
83
+ break;
84
+ case "shape":
85
+ a(c(i.path) && g(i.viewBox), `${h}缺少 path 或有效 viewBox`), i.text !== void 0 && a(c((w = i.text) == null ? void 0 : w.content), `${h}.text.content 必须是字符串`);
86
+ break;
87
+ case "line":
88
+ a(g(i.start) && g(i.end) && c(i.color), `${h}缺少 start、end 或 color`);
89
+ break;
90
+ case "chart": {
91
+ const d = i.data;
92
+ a(k.has(i.chartType), `${h}.chartType 不受支持`), a(y(d) && Array.isArray(d.labels) && d.labels.every(c) && Array.isArray(d.legends) && d.legends.every(c) && Array.isArray(d.series) && d.series.every((l) => Array.isArray(l) && l.every(Number.isFinite)), `${h}.data 结构无效`);
93
+ break;
94
+ }
95
+ case "table":
96
+ a(Array.isArray(i.data) && i.data.every((d) => Array.isArray(d) && d.every((l) => y(l) && c(l.id) && l.id && c(l.text))), `${h}.data 结构无效`);
97
+ break;
98
+ case "latex":
99
+ a(c(i.latex), `${h}.latex 必须是字符串`);
100
+ break;
101
+ }
102
+ });
103
+ });
104
+ }
105
+ function D(t, r) {
106
+ return r === void 0 ? Array.from({ length: t }, (s, e) => e + 1) : (a(Array.isArray(r) && r.length > 0, "pages 必须是非空页码数组"), a(r.every((s) => Number.isInteger(s) && s >= 1 && s <= t), `页码必须是 1 到 ${t} 的整数`), [...new Set(r)].sort((s, e) => s - e));
107
+ }
108
+ const u = A(S(v(import.meta.url)), "..");
109
+ async function R(t, r = {}) {
110
+ N(t);
111
+ const e = D(t.slides.length, r.pages).map((o) => ({
112
+ pageNumber: o,
113
+ slideId: t.slides[o - 1].id,
114
+ width: t.width,
115
+ height: t.height,
116
+ payload: JSON.stringify({
117
+ title: t.title,
118
+ width: t.width,
119
+ height: t.height,
120
+ pageNumber: o,
121
+ slide: t.slides[o - 1]
122
+ })
123
+ }));
124
+ let n, p;
125
+ try {
126
+ [n, p] = await Promise.all([
127
+ $(b(u, "dist/browser/renderer.js"), "utf8"),
128
+ $(b(u, "dist/browser/renderer.css"), "utf8")
129
+ ]);
130
+ } catch (o) {
131
+ throw o.code !== "ENOENT" ? o : new Error("缺少预编译浏览器资源。源码仓库请先显式执行 yarn build;npm 安装包应包含 dist/browser。", { cause: o });
132
+ }
133
+ return e.map(({ payload: o, ...i }) => ({
134
+ ...i,
135
+ html: L(o, n, p)
136
+ }));
137
+ }
138
+ export {
139
+ R as renderToHtml
140
+ };