@taloswork/ose-shared 0.1.6 → 0.1.8
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/package.json +3 -3
- package/skills/document/SKILL.md +32 -17
- package/skills/document/art-directions/base.css +23 -0
- package/skills/document/art-directions/cinematic-depth.css +6 -0
- package/skills/document/art-directions/collage-paper.css +8 -0
- package/skills/document/art-directions/editorial-cut.css +8 -0
- package/skills/document/art-directions/geometric-pop.css +9 -0
- package/skills/document/art-directions/gradient-mesh.css +6 -0
- package/skills/document/art-directions/illustrated-doodle.css +8 -0
- package/skills/document/art-directions/luxury-ornament.css +6 -0
- package/skills/document/art-directions/maximalist-blocks.css +9 -0
- package/skills/document/art-directions/technical-grid.css +6 -0
- package/skills/document/assets/fonts/fonts.json +2 -2
- package/skills/document/bin/deck-build.cjs +266 -10
- package/skills/document/bin/doc-convert.cjs +66 -28
- package/skills/document/bin/doc-gen.cjs +8 -9
- package/skills/document/bin/html2pptx.cjs +243 -24
- package/skills/document/bin/pptx-clone.cjs +41 -30
- package/skills/document/bin/pptx-embed-fonts.cjs +6 -2
- package/skills/document/bin/pptx-slide.cjs +46 -50
- package/skills/document/catalog.json +11 -0
- package/skills/document/components/base.css +45 -0
- package/skills/document/components/profiles/clean.css +2 -0
- package/skills/document/components/profiles/editorial.css +3 -0
- package/skills/document/components/profiles/glass.css +2 -0
- package/skills/document/components/profiles/luxury.css +3 -0
- package/skills/document/components/profiles/organic.css +2 -0
- package/skills/document/components/profiles/poster.css +3 -0
- package/skills/document/content-pipeline.md +110 -54
- package/skills/document/deck-design.md +24 -15
- package/skills/document/layouts/README.md +41 -12
- package/skills/document/layouts/blocks-2x2.tpl +19 -9
- package/skills/document/layouts/business-model.tpl +6 -0
- package/skills/document/layouts/cards-3.tpl +1 -1
- package/skills/document/layouts/customer-proof.tpl +6 -0
- package/skills/document/layouts/funding-ask.tpl +5 -0
- package/skills/document/layouts/market-rings.tpl +5 -0
- package/skills/document/layouts/org-tree.tpl +1 -1
- package/skills/document/layouts/pitch-problem.tpl +6 -0
- package/skills/document/layouts/pitch-solution.tpl +5 -0
- package/skills/document/layouts/pricing-tiers.tpl +5 -0
- package/skills/document/layouts/product-device.tpl +6 -0
- package/skills/document/layouts/profiles.json +24 -0
- package/skills/document/layouts/slots.json +1 -1
- package/skills/document/layouts/steps-vertical.tpl +1 -1
- package/skills/document/layouts/team-founders.tpl +5 -0
- package/skills/document/layouts/traction-milestones.tpl +6 -0
- package/skills/document/media-styles/cinematic.css +2 -0
- package/skills/document/media-styles/clean-product.css +2 -0
- package/skills/document/media-styles/cutout-collage.css +3 -0
- package/skills/document/media-styles/device-stage.css +3 -0
- package/skills/document/media-styles/editorial-photo.css +3 -0
- package/skills/document/media-styles/illustrated.css +2 -0
- package/skills/document/media-styles/spatial-3d.css +3 -0
- package/skills/document/motion/mckinsey-photo.json +22 -0
- package/skills/document/motion/prismatic-3d.json +31 -0
- package/skills/document/packs/README.md +7 -3
- package/skills/document/packs/mckinsey-photo/backdrop.html +6 -0
- package/skills/document/packs/mckinsey-photo/layouts/cover-image.tpl +5 -0
- package/skills/document/packs/mckinsey-photo/layouts/cover.tpl +5 -0
- package/skills/document/packs/mckinsey-photo/layouts/image-left.tpl +5 -0
- package/skills/document/packs/mckinsey-photo/layouts/numbered-brief.tpl +5 -0
- package/skills/document/packs/mckinsey-photo/pack.css +27 -0
- package/skills/document/packs/prismatic-3d/backdrop.html +4 -0
- package/skills/document/packs/prismatic-3d/layouts/big-stat.tpl +6 -0
- package/skills/document/packs/prismatic-3d/layouts/cover.tpl +9 -0
- package/skills/document/packs/prismatic-3d/layouts/section-image.tpl +6 -0
- package/skills/document/packs/prismatic-3d/pack.css +28 -0
- package/skills/document/recipes/agency-pitch.json +13 -0
- package/skills/document/recipes/product-launch.json +13 -0
- package/skills/document/recipes/startup-fundraising.json +19 -0
- package/skills/document/styles/README.md +13 -6
- package/skills/document/styles/_contract-defaults.css +1 -1
- package/skills/document/styles/_samples/_groups/biz-premium.webp +0 -0
- package/skills/document/styles/_samples/_groups/creative.webp +0 -0
- package/skills/document/styles/_samples/_groups/editorial.webp +0 -0
- package/skills/document/styles/_samples/_groups/minimal.webp +0 -0
- package/skills/document/styles/_samples/_groups/natural.webp +0 -0
- package/skills/document/styles/_samples/_groups/tech-future.webp +0 -0
- package/skills/document/styles/_samples/bistro-warm.webp +0 -0
- package/skills/document/styles/_samples/board-brief.webp +0 -0
- package/skills/document/styles/_samples/bold-clash.webp +0 -0
- package/skills/document/styles/_samples/campus-teal.webp +0 -0
- package/skills/document/styles/_samples/clinic-care.webp +0 -0
- package/skills/document/styles/_samples/dark-glass.webp +0 -0
- package/skills/document/styles/_samples/gov-brief.webp +0 -0
- package/skills/document/styles/_samples/grid-tech.webp +0 -0
- package/skills/document/styles/_samples/legal-slate.webp +0 -0
- package/skills/document/styles/_samples/mckinsey-photo.webp +0 -0
- package/skills/document/styles/_samples/memphis.webp +0 -0
- package/skills/document/styles/_samples/neon-cyber.webp +0 -0
- package/skills/document/styles/_samples/organic-earth.webp +0 -0
- package/skills/document/styles/_samples/pastel-saas.webp +0 -0
- package/skills/document/styles/_samples/portfolio-noir.webp +0 -0
- package/skills/document/styles/_samples/press-room.webp +0 -0
- package/skills/document/styles/_samples/prismatic-3d.webp +0 -0
- package/skills/document/styles/_samples/retro-press.webp +0 -0
- package/skills/document/styles/_samples/sport-arena.webp +0 -0
- package/skills/document/styles/_samples/wedding-blush.webp +0 -0
- package/skills/document/styles/dark-glass/backdrop.html +7 -3
- package/skills/document/styles/dark-glass/skin.css +1 -0
- package/skills/document/styles/portfolio-noir/skin.css +3 -0
- package/skills/document/theme-system.json +68 -0
- package/skills/document/theme-system.md +101 -0
|
@@ -69412,7 +69412,7 @@ var require_dir_writer = __commonJS({
|
|
|
69412
69412
|
module2.exports = DirWriter;
|
|
69413
69413
|
var Writer = require_writer();
|
|
69414
69414
|
var inherits2 = require_inherits();
|
|
69415
|
-
var
|
|
69415
|
+
var mkdir2 = require_mkdirp();
|
|
69416
69416
|
var path = require("path");
|
|
69417
69417
|
var collect = require_collect();
|
|
69418
69418
|
inherits2(DirWriter, Writer);
|
|
@@ -69428,7 +69428,7 @@ var require_dir_writer = __commonJS({
|
|
|
69428
69428
|
}
|
|
69429
69429
|
DirWriter.prototype._create = function() {
|
|
69430
69430
|
var self2 = this;
|
|
69431
|
-
|
|
69431
|
+
mkdir2(self2._path, Writer.dirmode, function(er) {
|
|
69432
69432
|
if (er) return self2.error(er);
|
|
69433
69433
|
self2.ready = true;
|
|
69434
69434
|
self2.emit("ready");
|
|
@@ -69773,7 +69773,7 @@ var require_writer = __commonJS({
|
|
|
69773
69773
|
var fs = require_graceful_fs();
|
|
69774
69774
|
var inherits2 = require_inherits();
|
|
69775
69775
|
var rimraf = require_rimraf();
|
|
69776
|
-
var
|
|
69776
|
+
var mkdir2 = require_mkdirp();
|
|
69777
69777
|
var path = require("path");
|
|
69778
69778
|
var umask = process.platform === "win32" ? 0 : process.umask();
|
|
69779
69779
|
var getType = require_get_type();
|
|
@@ -69879,7 +69879,7 @@ var require_writer = __commonJS({
|
|
|
69879
69879
|
}
|
|
69880
69880
|
};
|
|
69881
69881
|
function create(self2) {
|
|
69882
|
-
|
|
69882
|
+
mkdir2(path.dirname(self2._path), Writer.dirmode, function(er, made) {
|
|
69883
69883
|
if (er) return self2.error(er);
|
|
69884
69884
|
self2._madeDir = made;
|
|
69885
69885
|
return self2._create();
|
|
@@ -146935,7 +146935,7 @@ function themeCssVars(theme) {
|
|
|
146935
146935
|
`--secondary:${c.secondary}`,
|
|
146936
146936
|
`--text:${c.text}`,
|
|
146937
146937
|
`--muted:${c.muted}`,
|
|
146938
|
-
`--card
|
|
146938
|
+
`--surface-card:${c.tableHeaderBg}`,
|
|
146939
146939
|
`--border:${c.tableBorder}`,
|
|
146940
146940
|
`--slide-bg:${theme.pptx.background}`,
|
|
146941
146941
|
`--title-color:${theme.pptx.titleColor}`,
|
|
@@ -147823,8 +147823,14 @@ var LAYOUT_WALKER_JS = `
|
|
|
147823
147823
|
})()
|
|
147824
147824
|
`;
|
|
147825
147825
|
|
|
147826
|
+
// packages/core/dist/shared/async.js
|
|
147827
|
+
function sleep(ms) {
|
|
147828
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
147829
|
+
}
|
|
147830
|
+
|
|
147826
147831
|
// packages/core/dist/document/html-pptx-headless.js
|
|
147827
|
-
var
|
|
147832
|
+
var configuredSettleMs = Number(process.env.TALOS_CAPTURE_SETTLE_MS ?? 16);
|
|
147833
|
+
var CAPTURE_SETTLE_MS = Number.isFinite(configuredSettleMs) ? Math.max(0, Math.min(250, configuredSettleMs)) : 16;
|
|
147828
147834
|
var pngDataUri = (bytes) => "data:image/png;base64," + Buffer.from(bytes).toString("base64");
|
|
147829
147835
|
var isolateSlide = (si) => `new Promise((done) => { const secs = document.querySelectorAll("section.slide"); secs.forEach((s, j) => { s.style.display = j === ${si} ? "" : "none"; }); window.scrollTo(0, 0); requestAnimationFrame(() => requestAnimationFrame(() => done(true))); })`;
|
|
147830
147836
|
var showAllSlides = `document.querySelectorAll("section.slide").forEach((s) => { s.style.display = ""; }); document.getElementById("__talos_hide")?.remove(); true`;
|
|
@@ -147839,7 +147845,7 @@ async function snapshotHeadless(page, opts = {}) {
|
|
|
147839
147845
|
await page.evaluate(`(() => { document.querySelectorAll("*").forEach((el) => { const bake = getComputedStyle(el).getPropertyValue("--talos-bake").trim() === "1" || (el.closest && el.closest("[data-bake]")); if (bake) { const c = getComputedStyle(el).color; el.style.setProperty("color", c, "important"); el.style.setProperty("-webkit-text-fill-color", c, "important"); } }); const s = document.createElement("style"); s.id = "__talos_hide"; s.textContent = "*{color:transparent !important;-webkit-text-fill-color:transparent !important;text-shadow:none !important}"; document.head.appendChild(s); return true; })()`);
|
|
147840
147846
|
for (let si = 0; si < snapshot.slides.length; si++) {
|
|
147841
147847
|
await page.evaluate(isolateSlide(si));
|
|
147842
|
-
await sleep(
|
|
147848
|
+
await sleep(CAPTURE_SETTLE_MS);
|
|
147843
147849
|
const png = await page.screenshot({ x: 0, y: 0, width: 1280, height: 720 });
|
|
147844
147850
|
const backdropEl = { kind: "image", frame: { x: 0, y: 0, w: 1280, h: 720 }, data: pngDataUri(png) };
|
|
147845
147851
|
const keepEls = snapshot.slides[si].elements.filter((e) => e && (e.kind === "text" || e.kind === "chart"));
|
|
@@ -147854,7 +147860,7 @@ async function snapshotHeadless(page, opts = {}) {
|
|
|
147854
147860
|
if (!Array.isArray(els) || !els.some((e) => e && e.kind === "capture"))
|
|
147855
147861
|
continue;
|
|
147856
147862
|
await page.evaluate(isolateSlide(si));
|
|
147857
|
-
await sleep(
|
|
147863
|
+
await sleep(CAPTURE_SETTLE_MS);
|
|
147858
147864
|
for (const el of els) {
|
|
147859
147865
|
if (!el || el.kind !== "capture")
|
|
147860
147866
|
continue;
|
|
@@ -147883,12 +147889,16 @@ async function snapshotHeadless(page, opts = {}) {
|
|
|
147883
147889
|
}
|
|
147884
147890
|
return snapshot;
|
|
147885
147891
|
}
|
|
147886
|
-
async function rasterizeHeadless(page) {
|
|
147892
|
+
async function rasterizeHeadless(page, slideIndexes) {
|
|
147887
147893
|
const count = Number(await page.evaluate('document.querySelectorAll("section.slide").length'));
|
|
147888
147894
|
if (!count)
|
|
147889
147895
|
throw new Error('no <section class="slide"> found');
|
|
147896
|
+
const indexes = slideIndexes ?? Array.from({ length: count }, (_2, i) => i);
|
|
147897
|
+
if (indexes.length === 0 || indexes.some((i) => !Number.isInteger(i) || i < 0 || i >= count)) {
|
|
147898
|
+
throw new Error(`preview page is out of bounds (deck has ${count} slide${count === 1 ? "" : "s"})`);
|
|
147899
|
+
}
|
|
147890
147900
|
const shots = [];
|
|
147891
|
-
for (
|
|
147901
|
+
for (const i of indexes) {
|
|
147892
147902
|
await page.evaluate(`new Promise((done) => { window.scrollTo(0, document.querySelectorAll("section.slide")[${i}].offsetTop); requestAnimationFrame(() => requestAnimationFrame(() => done(true))); })`);
|
|
147893
147903
|
const png = await page.screenshot({ x: 0, y: 0, width: 1280, height: 720 });
|
|
147894
147904
|
shots.push(Buffer.from(png).toString("base64"));
|
|
@@ -147948,7 +147958,9 @@ async function inlineHtmlImages(html, resolve) {
|
|
|
147948
147958
|
// packages/core/dist/document/deck-catalog.js
|
|
147949
147959
|
var KINDS = ["skin", "pack"];
|
|
147950
147960
|
var MODES = ["light", "dark"];
|
|
147961
|
+
var RENDER_MODES = ["classic-v1", "theme-v2"];
|
|
147951
147962
|
var ID_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
147963
|
+
var COMMIT_RE = /^[0-9a-f]{7,40}$/;
|
|
147952
147964
|
function isStr(v) {
|
|
147953
147965
|
return typeof v === "string" && v.length > 0;
|
|
147954
147966
|
}
|
|
@@ -147978,6 +147990,35 @@ function parseCatalog(raw) {
|
|
|
147978
147990
|
groups.push({ id: g.id, name_cn: g.name_cn, sample: g.sample, scenarios: g.scenarios });
|
|
147979
147991
|
}
|
|
147980
147992
|
});
|
|
147993
|
+
const collections = [];
|
|
147994
|
+
const rawCollections = o.collections === void 0 ? [] : Array.isArray(o.collections) ? o.collections : [];
|
|
147995
|
+
if (o.collections !== void 0 && !Array.isArray(o.collections))
|
|
147996
|
+
errors.push("catalog.collections must be an array when present");
|
|
147997
|
+
rawCollections.forEach((c, i) => {
|
|
147998
|
+
const at = `collection[${i}]`;
|
|
147999
|
+
const before = errors.length;
|
|
148000
|
+
if (!isStr(c?.id) || !ID_RE.test(c.id))
|
|
148001
|
+
errors.push(`${at}: bad id`);
|
|
148002
|
+
if (!isStr(c?.name_cn))
|
|
148003
|
+
errors.push(`${at}: missing name_cn`);
|
|
148004
|
+
if (!isStr(c?.renderMode) || !RENDER_MODES.includes(c.renderMode))
|
|
148005
|
+
errors.push(`${at}: bad renderMode`);
|
|
148006
|
+
if (!isStrArr(c?.entryIds) || c.entryIds.length === 0)
|
|
148007
|
+
errors.push(`${at}: entryIds must be a non-empty string array`);
|
|
148008
|
+
if (c?.sourceCommit !== void 0 && (!isStr(c.sourceCommit) || !COMMIT_RE.test(c.sourceCommit)))
|
|
148009
|
+
errors.push(`${at}: bad sourceCommit`);
|
|
148010
|
+
if (c?.renderMode === "classic-v1" && c?.sourceCommit === void 0)
|
|
148011
|
+
errors.push(`${at}: classic-v1 requires sourceCommit`);
|
|
148012
|
+
if (errors.length === before) {
|
|
148013
|
+
collections.push({
|
|
148014
|
+
id: c.id,
|
|
148015
|
+
name_cn: c.name_cn,
|
|
148016
|
+
renderMode: c.renderMode,
|
|
148017
|
+
entryIds: c.entryIds,
|
|
148018
|
+
...c.sourceCommit !== void 0 ? { sourceCommit: c.sourceCommit } : {}
|
|
148019
|
+
});
|
|
148020
|
+
}
|
|
148021
|
+
});
|
|
147981
148022
|
const entries = [];
|
|
147982
148023
|
const rawEntries = Array.isArray(o.entries) ? o.entries : [];
|
|
147983
148024
|
if (!Array.isArray(o.entries))
|
|
@@ -148017,11 +148058,14 @@ function parseCatalog(raw) {
|
|
|
148017
148058
|
});
|
|
148018
148059
|
}
|
|
148019
148060
|
});
|
|
148020
|
-
return { catalog: errors.length ? null : { groups, entries }, errors };
|
|
148061
|
+
return { catalog: errors.length ? null : { groups, ...collections.length ? { collections } : {}, entries }, errors };
|
|
148021
148062
|
}
|
|
148022
148063
|
function resolveEntry(catalog, id) {
|
|
148023
148064
|
return catalog.entries.find((e) => e.id === id) ?? null;
|
|
148024
148065
|
}
|
|
148066
|
+
function renderModeOf(catalog, id) {
|
|
148067
|
+
return catalog.collections?.find((c) => c.entryIds.includes(id))?.renderMode ?? "theme-v2";
|
|
148068
|
+
}
|
|
148025
148069
|
function assetDirOf(entry) {
|
|
148026
148070
|
return entry.kind === "skin" ? `styles/${entry.id}` : `packs/${entry.id}`;
|
|
148027
148071
|
}
|
|
@@ -148029,6 +148073,108 @@ function cssFileOf(entry) {
|
|
|
148029
148073
|
return entry.kind === "skin" ? "skin.css" : "pack.css";
|
|
148030
148074
|
}
|
|
148031
148075
|
|
|
148076
|
+
// packages/core/dist/shared/guards.js
|
|
148077
|
+
function isRecord(value) {
|
|
148078
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
148079
|
+
}
|
|
148080
|
+
|
|
148081
|
+
// packages/core/dist/document/deck-theme-system.js
|
|
148082
|
+
var ID_RE2 = /^[a-z0-9][a-z0-9-]*$/;
|
|
148083
|
+
var PATH_RE = /^[a-z0-9_./-]+\.css$/i;
|
|
148084
|
+
function isSafeCssPath(v) {
|
|
148085
|
+
return typeof v === "string" && PATH_RE.test(v) && !v.startsWith("/") && !v.includes("..");
|
|
148086
|
+
}
|
|
148087
|
+
function parsePathMap(value, at, errors) {
|
|
148088
|
+
if (!isRecord(value)) {
|
|
148089
|
+
errors.push(`${at} must be an object`);
|
|
148090
|
+
return {};
|
|
148091
|
+
}
|
|
148092
|
+
const out = {};
|
|
148093
|
+
for (const [id, path] of Object.entries(value)) {
|
|
148094
|
+
if (!ID_RE2.test(id))
|
|
148095
|
+
errors.push(`${at}.${id}: bad id`);
|
|
148096
|
+
if (!isSafeCssPath(path)) {
|
|
148097
|
+
errors.push(`${at}.${id}: must be a safe relative .css path`);
|
|
148098
|
+
continue;
|
|
148099
|
+
}
|
|
148100
|
+
out[id] = path;
|
|
148101
|
+
}
|
|
148102
|
+
return out;
|
|
148103
|
+
}
|
|
148104
|
+
function parseThemeSystem(raw) {
|
|
148105
|
+
const errors = [];
|
|
148106
|
+
if (!isRecord(raw))
|
|
148107
|
+
return { system: null, errors: ["theme system is not an object"] };
|
|
148108
|
+
if (raw.version !== 2)
|
|
148109
|
+
errors.push("theme system version must be 2");
|
|
148110
|
+
if (!isSafeCssPath(raw.componentBase)) {
|
|
148111
|
+
errors.push("componentBase must be a safe relative .css path");
|
|
148112
|
+
}
|
|
148113
|
+
if (!isSafeCssPath(raw.artBase)) {
|
|
148114
|
+
errors.push("artBase must be a safe relative .css path");
|
|
148115
|
+
}
|
|
148116
|
+
const componentProfiles = parsePathMap(raw.componentProfiles, "componentProfiles", errors);
|
|
148117
|
+
const mediaStyles = parsePathMap(raw.mediaStyles, "mediaStyles", errors);
|
|
148118
|
+
const artDirections = parsePathMap(raw.artDirections, "artDirections", errors);
|
|
148119
|
+
const bindings = {};
|
|
148120
|
+
if (!isRecord(raw.bindings))
|
|
148121
|
+
errors.push("bindings must be an object");
|
|
148122
|
+
else {
|
|
148123
|
+
for (const [id, value] of Object.entries(raw.bindings)) {
|
|
148124
|
+
const at = `bindings.${id}`;
|
|
148125
|
+
if (!ID_RE2.test(id))
|
|
148126
|
+
errors.push(`${at}: bad id`);
|
|
148127
|
+
if (!isRecord(value)) {
|
|
148128
|
+
errors.push(`${at} must be an object`);
|
|
148129
|
+
continue;
|
|
148130
|
+
}
|
|
148131
|
+
const componentProfile = value.componentProfile;
|
|
148132
|
+
const mediaStyle = value.mediaStyle;
|
|
148133
|
+
const artDirection = value.artDirection;
|
|
148134
|
+
if (typeof componentProfile !== "string" || !ID_RE2.test(componentProfile))
|
|
148135
|
+
errors.push(`${at}: bad componentProfile`);
|
|
148136
|
+
if (typeof mediaStyle !== "string" || !ID_RE2.test(mediaStyle))
|
|
148137
|
+
errors.push(`${at}: bad mediaStyle`);
|
|
148138
|
+
if (typeof artDirection !== "string" || !ID_RE2.test(artDirection))
|
|
148139
|
+
errors.push(`${at}: bad artDirection`);
|
|
148140
|
+
if (typeof componentProfile === "string" && typeof mediaStyle === "string" && typeof artDirection === "string") {
|
|
148141
|
+
bindings[id] = { componentProfile, mediaStyle, artDirection };
|
|
148142
|
+
}
|
|
148143
|
+
}
|
|
148144
|
+
}
|
|
148145
|
+
if (errors.length)
|
|
148146
|
+
return { system: null, errors };
|
|
148147
|
+
return {
|
|
148148
|
+
system: {
|
|
148149
|
+
version: 2,
|
|
148150
|
+
componentBase: raw.componentBase,
|
|
148151
|
+
artBase: raw.artBase,
|
|
148152
|
+
componentProfiles,
|
|
148153
|
+
mediaStyles,
|
|
148154
|
+
artDirections,
|
|
148155
|
+
bindings
|
|
148156
|
+
},
|
|
148157
|
+
errors
|
|
148158
|
+
};
|
|
148159
|
+
}
|
|
148160
|
+
function resolveThemeLayers(system, styleId, mediaOverride) {
|
|
148161
|
+
const binding = system.bindings[styleId];
|
|
148162
|
+
if (!binding)
|
|
148163
|
+
return null;
|
|
148164
|
+
const mediaStyle = mediaOverride ?? binding.mediaStyle;
|
|
148165
|
+
const componentPath = system.componentProfiles[binding.componentProfile];
|
|
148166
|
+
const mediaPath = system.mediaStyles[mediaStyle];
|
|
148167
|
+
const artPath = system.artDirections[binding.artDirection];
|
|
148168
|
+
if (!componentPath || !mediaPath || !artPath)
|
|
148169
|
+
return null;
|
|
148170
|
+
return {
|
|
148171
|
+
paths: [system.componentBase, componentPath, mediaPath, system.artBase, artPath],
|
|
148172
|
+
componentProfile: binding.componentProfile,
|
|
148173
|
+
mediaStyle,
|
|
148174
|
+
artDirection: binding.artDirection
|
|
148175
|
+
};
|
|
148176
|
+
}
|
|
148177
|
+
|
|
148032
148178
|
// apps/admin/data/skills.lib/document/bin-src/html2pptx.mjs
|
|
148033
148179
|
function imageResolver(baseDir) {
|
|
148034
148180
|
return async (src) => {
|
|
@@ -148047,6 +148193,19 @@ function die(msg, code = 1) {
|
|
|
148047
148193
|
`);
|
|
148048
148194
|
process.exit(code);
|
|
148049
148195
|
}
|
|
148196
|
+
function parsePreviewPages(spec) {
|
|
148197
|
+
if (!spec || spec.trim().toLowerCase() === "all") return null;
|
|
148198
|
+
const pages = [];
|
|
148199
|
+
for (const part of spec.split(",")) {
|
|
148200
|
+
const match = /^(\d+)(?:-(\d+))?$/.exec(part.trim());
|
|
148201
|
+
if (!match) die(`bad preview page spec: ${spec} (use all or N,N-M)`, 64);
|
|
148202
|
+
const from = Number(match[1]);
|
|
148203
|
+
const to = match[2] ? Number(match[2]) : from;
|
|
148204
|
+
if (from < 1 || to < from) die(`bad preview page range: ${part}`, 64);
|
|
148205
|
+
for (let p = from; p <= to; p++) if (!pages.includes(p - 1)) pages.push(p - 1);
|
|
148206
|
+
}
|
|
148207
|
+
return pages;
|
|
148208
|
+
}
|
|
148050
148209
|
var _tailwindCss;
|
|
148051
148210
|
async function tailwindCss() {
|
|
148052
148211
|
if (_tailwindCss !== void 0) return _tailwindCss;
|
|
@@ -148102,7 +148261,7 @@ async function latinFontFaceCss(doc) {
|
|
|
148102
148261
|
}
|
|
148103
148262
|
return _latinFontCss;
|
|
148104
148263
|
}
|
|
148105
|
-
async function withHeadlessPage(html, fn) {
|
|
148264
|
+
async function withHeadlessPage(html, fn, density = DOCUMENT_CAPTURE_DENSITY) {
|
|
148106
148265
|
const headless = (process.env.TALOS_HTML2PPTX_HEADLESS ?? "").trim().toLowerCase();
|
|
148107
148266
|
if (headless === "off" || headless === "none" || headless === "0" || headless === "false") return null;
|
|
148108
148267
|
let pw;
|
|
@@ -148121,7 +148280,7 @@ async function withHeadlessPage(html, fn) {
|
|
|
148121
148280
|
try {
|
|
148122
148281
|
const page = await browser2.newPage({
|
|
148123
148282
|
viewport: { width: 1280, height: 720 },
|
|
148124
|
-
deviceScaleFactor:
|
|
148283
|
+
deviceScaleFactor: density
|
|
148125
148284
|
});
|
|
148126
148285
|
await page.setContent(html, { waitUntil: "load" });
|
|
148127
148286
|
await page.evaluate("document.fonts && document.fonts.ready").catch(() => {
|
|
@@ -148131,7 +148290,7 @@ async function withHeadlessPage(html, fn) {
|
|
|
148131
148290
|
screenshot: async (clip) => {
|
|
148132
148291
|
const png = await page.screenshot({ clip });
|
|
148133
148292
|
const w = png.readUInt32BE(16), h = png.readUInt32BE(20);
|
|
148134
|
-
const want = [clip.width *
|
|
148293
|
+
const want = [clip.width * density, clip.height * density];
|
|
148135
148294
|
if (w !== want[0] || h !== want[1]) throw new Error(`captured ${w}x${h}, expected ${want[0]}x${want[1]}`);
|
|
148136
148295
|
return png;
|
|
148137
148296
|
}
|
|
@@ -148197,19 +148356,38 @@ async function main() {
|
|
|
148197
148356
|
const themePath = themeIdx >= 0 ? args[themeIdx + 1] : void 0;
|
|
148198
148357
|
const styleIdx = args.indexOf("--style");
|
|
148199
148358
|
const styleArg = styleIdx >= 0 ? args[styleIdx + 1] : void 0;
|
|
148359
|
+
const themeV2 = args.includes("--theme-v2");
|
|
148360
|
+
const mediaIdx = args.indexOf("--media-style");
|
|
148361
|
+
const mediaStyleArg = mediaIdx >= 0 ? args[mediaIdx + 1] : void 0;
|
|
148200
148362
|
const bdIdx = args.indexOf("--backdrop");
|
|
148201
148363
|
const bdVariant = bdIdx >= 0 ? args[bdIdx + 1] : void 0;
|
|
148202
148364
|
const lineIdx = args.indexOf("--line");
|
|
148203
148365
|
const lineArg = lineIdx >= 0 ? args[lineIdx + 1] : void 0;
|
|
148204
148366
|
const notesIdx = args.indexOf("--notes-doc");
|
|
148205
148367
|
const notesDocPath = notesIdx >= 0 ? args[notesIdx + 1] : void 0;
|
|
148206
|
-
const
|
|
148207
|
-
const
|
|
148368
|
+
const previewIdx = args.indexOf("--preview-dir");
|
|
148369
|
+
const previewDir = previewIdx >= 0 ? args[previewIdx + 1] : void 0;
|
|
148370
|
+
const previewPagesIdx = args.indexOf("--preview-pages");
|
|
148371
|
+
const previewPagesArg = previewPagesIdx >= 0 ? args[previewPagesIdx + 1] : void 0;
|
|
148372
|
+
const previewIndexes = parsePreviewPages(previewPagesArg);
|
|
148373
|
+
const previewDensityIdx = args.indexOf("--preview-density");
|
|
148374
|
+
const previewDensityArg = previewDensityIdx >= 0 ? args[previewDensityIdx + 1] : void 0;
|
|
148375
|
+
const previewDensity = previewDensityArg === void 0 ? DOCUMENT_CAPTURE_DENSITY : Number(previewDensityArg);
|
|
148376
|
+
const consumed = /* @__PURE__ */ new Set([themeIdx, themeIdx >= 0 ? themeIdx + 1 : -1, styleIdx, styleIdx >= 0 ? styleIdx + 1 : -1, mediaIdx, mediaIdx >= 0 ? mediaIdx + 1 : -1, bdIdx, bdIdx >= 0 ? bdIdx + 1 : -1, lineIdx, lineIdx >= 0 ? lineIdx + 1 : -1, modeIdx, modeIdx >= 0 ? modeIdx + 1 : -1, notesIdx, notesIdx >= 0 ? notesIdx + 1 : -1, previewIdx, previewIdx >= 0 ? previewIdx + 1 : -1, previewPagesIdx, previewPagesIdx >= 0 ? previewPagesIdx + 1 : -1, previewDensityIdx, previewDensityIdx >= 0 ? previewDensityIdx + 1 : -1]);
|
|
148377
|
+
const positional = args.filter((a, i) => a !== "--rasterize" && a !== "--editable" && a !== "--theme-v2" && !consumed.has(i));
|
|
148208
148378
|
const [input, out] = positional;
|
|
148209
|
-
if (!input || !out) die("usage: html2pptx <in.html|in.layout.json>
|
|
148210
|
-
if (
|
|
148379
|
+
if (!input || !out && !previewDir) die("usage: html2pptx <in.html|in.layout.json> [out.pptx] [--theme <theme.json>] [--style <name|dir>] [--theme-v2] [--media-style <id>] [--backdrop <variant>] [--line <name|none>] [--editable] [--rasterize] [--notes-doc <out.md>] [--preview-dir <dir>] [--preview-pages <all|N,N-M>] [--preview-density <1..4>]", 64);
|
|
148380
|
+
if (previewPagesArg && !previewDir) die("--preview-pages requires --preview-dir", 64);
|
|
148381
|
+
if (previewDensityArg !== void 0 && !previewDir) die("--preview-density requires --preview-dir", 64);
|
|
148382
|
+
if (!(previewDensity > 0 && previewDensity <= 4)) die("--preview-density must be a number in (0, 4]", 64);
|
|
148383
|
+
if (previewDir && out) die("--preview-dir is preview-only; omit the .pptx output", 64);
|
|
148384
|
+
if (previewDir && (rasterize || forceEditable || notesDocPath)) die("--preview-dir cannot be combined with --rasterize, --editable/--mode, or --notes-doc", 64);
|
|
148385
|
+
if (themeV2 && !styleArg) die("--theme-v2 requires --style <catalog-id>", 64);
|
|
148386
|
+
if (mediaStyleArg && !themeV2) die("--media-style requires --theme-v2", 64);
|
|
148387
|
+
if (!previewDir && !/\.pptx$/i.test(out)) die("output must be a .pptx path", 64);
|
|
148211
148388
|
const raw = await (0, import_promises.readFile)(input, "utf8").catch((e) => die(`cannot read ${input}: ${e.message}`, 66));
|
|
148212
148389
|
if (/\.json$/i.test(input)) {
|
|
148390
|
+
if (previewDir) die("--preview-dir requires HTML input", 64);
|
|
148213
148391
|
let snapshot2;
|
|
148214
148392
|
try {
|
|
148215
148393
|
snapshot2 = JSON.parse(raw);
|
|
@@ -148249,18 +148427,17 @@ async function main() {
|
|
|
148249
148427
|
let skinCss = "", backdropHtml = "", skinAccent = "", skinAxis = "", skinChart1 = "";
|
|
148250
148428
|
if (styleArg) {
|
|
148251
148429
|
const skillDir = (0, import_node_path.dirname)((0, import_node_path.dirname)(process.argv[1] || ""));
|
|
148252
|
-
let styleDir, cssName = "skin.css";
|
|
148430
|
+
let styleDir, cssName = "skin.css", entry = null, catalog = null;
|
|
148253
148431
|
if ((0, import_node_fs.existsSync)((0, import_node_path.join)(styleArg, "skin.css"))) {
|
|
148254
148432
|
styleDir = styleArg;
|
|
148255
148433
|
} else if ((0, import_node_fs.existsSync)((0, import_node_path.join)(styleArg, "pack.css"))) {
|
|
148256
148434
|
styleDir = styleArg;
|
|
148257
148435
|
cssName = "pack.css";
|
|
148258
148436
|
} else {
|
|
148259
|
-
let entry = null;
|
|
148260
148437
|
const catalogPath = (0, import_node_path.join)(skillDir, "catalog.json");
|
|
148261
148438
|
if ((0, import_node_fs.existsSync)(catalogPath)) {
|
|
148262
148439
|
try {
|
|
148263
|
-
|
|
148440
|
+
({ catalog } = parseCatalog(JSON.parse((0, import_node_fs.readFileSync)(catalogPath, "utf8"))));
|
|
148264
148441
|
if (catalog) entry = resolveEntry(catalog, styleArg);
|
|
148265
148442
|
} catch {
|
|
148266
148443
|
}
|
|
@@ -148275,7 +148452,27 @@ async function main() {
|
|
|
148275
148452
|
die(`cannot read style ${skinPath}: ${e.message}`, 66);
|
|
148276
148453
|
}
|
|
148277
148454
|
const defaultsPath = (0, import_node_path.join)(skillDir, "styles", "_contract-defaults.css");
|
|
148278
|
-
|
|
148455
|
+
let v2Css = "";
|
|
148456
|
+
if (themeV2) {
|
|
148457
|
+
if (!entry) die("--theme-v2 requires a catalog style id (explicit style directories are V1 only)", 64);
|
|
148458
|
+
if (catalog && renderModeOf(catalog, entry.id) === "classic-v1") {
|
|
148459
|
+
die(`style "${entry.id}" is frozen in collection "original-13" as classic-v1; omit --theme-v2 and --media-style`, 64);
|
|
148460
|
+
}
|
|
148461
|
+
const registryPath = (0, import_node_path.join)(skillDir, "theme-system.json");
|
|
148462
|
+
let parsed;
|
|
148463
|
+
try {
|
|
148464
|
+
parsed = parseThemeSystem(JSON.parse(await (0, import_promises.readFile)(registryPath, "utf8")));
|
|
148465
|
+
} catch (e) {
|
|
148466
|
+
die(`cannot read Theme V2 registry ${registryPath}: ${e.message}`, 66);
|
|
148467
|
+
}
|
|
148468
|
+
if (!parsed.system) die(`invalid Theme V2 registry: ${parsed.errors.join("; ")}`, 66);
|
|
148469
|
+
const layers = resolveThemeLayers(parsed.system, entry.id, mediaStyleArg);
|
|
148470
|
+
if (!layers) die(`Theme V2 cannot resolve style "${entry.id}"${mediaStyleArg ? ` with media style "${mediaStyleArg}"` : ""}`, 66);
|
|
148471
|
+
for (const rel of layers.paths) v2Css += await (0, import_promises.readFile)((0, import_node_path.join)(skillDir, rel), "utf8") + "\n";
|
|
148472
|
+
process.stderr.write(`html2pptx: Theme V2 ${entry.id} = components:${layers.componentProfile} + media:${layers.mediaStyle} + art:${layers.artDirection}
|
|
148473
|
+
`);
|
|
148474
|
+
}
|
|
148475
|
+
skinCss = ((0, import_node_fs.existsSync)(defaultsPath) ? await (0, import_promises.readFile)(defaultsPath, "utf8") + "\n" : "") + v2Css + skinCss;
|
|
148279
148476
|
const sharedBackdropsDir = (0, import_node_path.join)(skillDir, "styles", "_backdrops");
|
|
148280
148477
|
const NO_AUTO_BACKDROP_VARIETY = /* @__PURE__ */ new Set(["mckinsey", "mono", "cinereel"]);
|
|
148281
148478
|
let bdPath;
|
|
@@ -148289,7 +148486,7 @@ async function main() {
|
|
|
148289
148486
|
`);
|
|
148290
148487
|
bdPath = (0, import_node_path.join)(styleDir, "backdrop.html");
|
|
148291
148488
|
}
|
|
148292
|
-
} else if (NO_AUTO_BACKDROP_VARIETY.has((0, import_node_path.basename)(styleDir))) {
|
|
148489
|
+
} else if (themeV2 || NO_AUTO_BACKDROP_VARIETY.has((0, import_node_path.basename)(styleDir))) {
|
|
148293
148490
|
bdPath = (0, import_node_path.join)(styleDir, "backdrop.html");
|
|
148294
148491
|
} else {
|
|
148295
148492
|
const ownVariants = (0, import_node_fs.existsSync)(styleDir) ? (0, import_node_fs.readdirSync)(styleDir).filter((f) => /^backdrop.*\.html$/.test(f)).map((f) => (0, import_node_path.join)(styleDir, f)) : [];
|
|
@@ -148323,7 +148520,8 @@ async function main() {
|
|
|
148323
148520
|
for (const s of skipped) process.stderr.write(`html2pptx: <img src="${s}"> not found/unfetchable \u2014 the render will drop it
|
|
148324
148521
|
`);
|
|
148325
148522
|
if (styleArg) {
|
|
148326
|
-
|
|
148523
|
+
const artLayer = themeV2 ? '<div class="theme-art-layer" aria-hidden="true"><i class="art-shape art-a"></i><i class="art-shape art-b"></i><i class="art-shape art-c"></i><i class="art-pattern"></i></div>' : "";
|
|
148524
|
+
if (backdropHtml || artLayer) rawInlined = rawInlined.replace(/<div class="slide-backdrop">\s*<\/div>/g, `<div class="slide-backdrop">${backdropHtml}${artLayer}</div>`);
|
|
148327
148525
|
if (skinAccent) rawInlined = rawInlined.replaceAll("__ACCENT__", skinAccent);
|
|
148328
148526
|
if (skinAxis) rawInlined = rawInlined.replaceAll("__AXIS__", skinAxis);
|
|
148329
148527
|
if (skinChart1) rawInlined = rawInlined.replaceAll("__CHART1__", skinChart1);
|
|
@@ -148333,6 +148531,27 @@ async function main() {
|
|
|
148333
148531
|
const latin = await latinFontFaceCss(rawInlined + skinCss);
|
|
148334
148532
|
const fontCss = cjk + latin;
|
|
148335
148533
|
const html = injectHead(rawInlined, `${fontCss ? `<style>${fontCss}</style>` : ""}${tw ? `<style>${tw}</style>` : ""}<style>${themeCss}${SKELETON_CSS}${skinCss}</style>`);
|
|
148534
|
+
if (previewDir) {
|
|
148535
|
+
let images;
|
|
148536
|
+
if (hasService) ({ images } = await callService("/shot", html, {
|
|
148537
|
+
...previewIndexes ? { pages: previewIndexes } : {},
|
|
148538
|
+
...previewDensityArg !== void 0 ? { density: previewDensity } : {}
|
|
148539
|
+
}).catch((e) => die(e.message, 1)));
|
|
148540
|
+
else {
|
|
148541
|
+
images = await withHeadlessPage(html, (p) => rasterizeHeadless(p, previewIndexes ?? void 0), previewDensity).catch((e) => die(e.message, 1));
|
|
148542
|
+
if (images == null) die(NO_BROWSER, 69);
|
|
148543
|
+
}
|
|
148544
|
+
await (0, import_promises.mkdir)(previewDir, { recursive: true });
|
|
148545
|
+
const pageNumbers = previewIndexes ? previewIndexes.map((i) => i + 1) : images.map((_2, i) => i + 1);
|
|
148546
|
+
const files = [];
|
|
148547
|
+
for (let i = 0; i < images.length; i++) {
|
|
148548
|
+
const path = (0, import_node_path.join)(previewDir, `slide-${String(pageNumbers[i]).padStart(3, "0")}.png`);
|
|
148549
|
+
await (0, import_promises.writeFile)(path, Buffer.from(images[i], "base64"));
|
|
148550
|
+
files.push(path);
|
|
148551
|
+
}
|
|
148552
|
+
process.stdout.write(JSON.stringify({ ok: true, engine: hasService ? "preview" : "preview (headless)", slides: images.length, pages: pageNumbers, density: previewDensity, files }, null, 1) + "\n");
|
|
148553
|
+
return;
|
|
148554
|
+
}
|
|
148336
148555
|
if (rasterize) {
|
|
148337
148556
|
let images;
|
|
148338
148557
|
if (hasService) ({ images } = await callService("/shot", html).catch((e) => die(e.message, 1)));
|
|
@@ -9860,9 +9860,9 @@ function unescXml(s) {
|
|
|
9860
9860
|
}
|
|
9861
9861
|
});
|
|
9862
9862
|
}
|
|
9863
|
-
function visualWidth(
|
|
9863
|
+
function visualWidth(text3) {
|
|
9864
9864
|
let w = 0;
|
|
9865
|
-
for (const ch of
|
|
9865
|
+
for (const ch of text3) {
|
|
9866
9866
|
const cp = ch.codePointAt(0);
|
|
9867
9867
|
if (ch === " " || ch === " ")
|
|
9868
9868
|
w += 0.35;
|
|
@@ -9891,9 +9891,9 @@ function replaceTextAcrossRuns(xml, find, replacement, opts) {
|
|
|
9891
9891
|
const segs = [];
|
|
9892
9892
|
let flat = "";
|
|
9893
9893
|
for (const m of para.matchAll(textRe)) {
|
|
9894
|
-
const
|
|
9895
|
-
segs.push({ el: m[0], attrs: m[1] ?? "", text:
|
|
9896
|
-
flat +=
|
|
9894
|
+
const text3 = unescXml(m[2]);
|
|
9895
|
+
segs.push({ el: m[0], attrs: m[1] ?? "", text: text3, start: flat.length });
|
|
9896
|
+
flat += text3;
|
|
9897
9897
|
}
|
|
9898
9898
|
if (!flat.includes(find))
|
|
9899
9899
|
return para;
|
|
@@ -9936,9 +9936,36 @@ function replaceTextAcrossRuns(xml, find, replacement, opts) {
|
|
|
9936
9936
|
return { xml: rewritten, count };
|
|
9937
9937
|
}
|
|
9938
9938
|
|
|
9939
|
-
// packages/core/dist/document/pptx-
|
|
9939
|
+
// packages/core/dist/document/pptx-register-slide.js
|
|
9940
9940
|
var SLIDE_CT = "application/vnd.openxmlformats-officedocument.presentationml.slide+xml";
|
|
9941
9941
|
var SLIDE_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide";
|
|
9942
|
+
async function text(zip, path) {
|
|
9943
|
+
const f = zip.file(path);
|
|
9944
|
+
if (!f)
|
|
9945
|
+
throw new Error(`not a PowerPoint file (${path} missing)`);
|
|
9946
|
+
return f.async("string");
|
|
9947
|
+
}
|
|
9948
|
+
async function registerSlidePart(zip, newNum, newXmlPath) {
|
|
9949
|
+
const ctPath = "[Content_Types].xml";
|
|
9950
|
+
const ct = await text(zip, ctPath);
|
|
9951
|
+
if (!ct.includes(`PartName="/${newXmlPath}"`)) {
|
|
9952
|
+
zip.file(ctPath, ct.replace("</Types>", `<Override PartName="/${newXmlPath}" ContentType="${SLIDE_CT}"/></Types>`));
|
|
9953
|
+
}
|
|
9954
|
+
const presRelsPath = "ppt/_rels/presentation.xml.rels";
|
|
9955
|
+
const presRels = await text(zip, presRelsPath);
|
|
9956
|
+
const maxRid = Math.max(0, ...[...presRels.matchAll(/Id="rId(\d+)"/g)].map((m) => Number(m[1])));
|
|
9957
|
+
const newRid = `rId${maxRid + 1}`;
|
|
9958
|
+
zip.file(presRelsPath, presRels.replace("</Relationships>", `<Relationship Id="${newRid}" Type="${SLIDE_REL_TYPE}" Target="slides/slide${newNum}.xml"/></Relationships>`));
|
|
9959
|
+
const presPath = "ppt/presentation.xml";
|
|
9960
|
+
const pres = await text(zip, presPath);
|
|
9961
|
+
const maxSldId = Math.max(255, ...[...pres.matchAll(/<p:sldId id="(\d+)"/g)].map((m) => Number(m[1])));
|
|
9962
|
+
const updated = pres.replace("</p:sldIdLst>", `<p:sldId id="${maxSldId + 1}" r:id="${newRid}"/></p:sldIdLst>`);
|
|
9963
|
+
if (updated === pres)
|
|
9964
|
+
throw new Error("could not locate the slide list in presentation.xml");
|
|
9965
|
+
zip.file(presPath, updated);
|
|
9966
|
+
}
|
|
9967
|
+
|
|
9968
|
+
// packages/core/dist/document/pptx-clone.js
|
|
9942
9969
|
var EMU_PER_PT = 12700;
|
|
9943
9970
|
function capacityWarning(slideXml, token, value) {
|
|
9944
9971
|
const idx = slideXml.indexOf(token);
|
|
@@ -9971,7 +9998,7 @@ function capacityWarning(slideXml, token, value) {
|
|
|
9971
9998
|
return void 0;
|
|
9972
9999
|
return `${token}: replacement is ~${Math.ceil(width)} width-units, slot fits ~${Math.floor(capacity)} (${Math.round(widthPt)}\xD7${Math.round(heightPt)}pt box @ ${fontPt}pt) \u2014 likely overflow. Shorten the wording; do NOT shrink the font to make it fit.`;
|
|
9973
10000
|
}
|
|
9974
|
-
async function
|
|
10001
|
+
async function text2(zip, path) {
|
|
9975
10002
|
const f = zip.file(path);
|
|
9976
10003
|
if (!f)
|
|
9977
10004
|
throw new Error(`not a PowerPoint file (${path} missing)`);
|
|
@@ -9996,7 +10023,7 @@ async function clonePptxSlide(bytes, slideNumber, replacements = {}) {
|
|
|
9996
10023
|
const newNum = Math.max(...slideNums) + 1;
|
|
9997
10024
|
const srcXmlPath = `ppt/slides/slide${slideNumber}.xml`;
|
|
9998
10025
|
const newXmlPath = `ppt/slides/slide${newNum}.xml`;
|
|
9999
|
-
let slideXml = await
|
|
10026
|
+
let slideXml = await text2(zip, srcXmlPath);
|
|
10000
10027
|
const replaced = [];
|
|
10001
10028
|
const missing = [];
|
|
10002
10029
|
const warnings = [];
|
|
@@ -10024,23 +10051,7 @@ async function clonePptxSlide(bytes, slideNumber, replacements = {}) {
|
|
|
10024
10051
|
const rels = removeElement(await srcRels.async("string"), "Relationship", (el) => /Type="[^"]*\/notesSlide"/.test(el)).xml;
|
|
10025
10052
|
zip.file(`ppt/slides/_rels/slide${newNum}.xml.rels`, rels);
|
|
10026
10053
|
}
|
|
10027
|
-
|
|
10028
|
-
const ct = await text(zip, ctPath);
|
|
10029
|
-
if (!ct.includes(`PartName="/${newXmlPath}"`)) {
|
|
10030
|
-
zip.file(ctPath, ct.replace("</Types>", `<Override PartName="/${newXmlPath}" ContentType="${SLIDE_CT}"/></Types>`));
|
|
10031
|
-
}
|
|
10032
|
-
const presRelsPath = "ppt/_rels/presentation.xml.rels";
|
|
10033
|
-
const presRels = await text(zip, presRelsPath);
|
|
10034
|
-
const maxRid = Math.max(0, ...[...presRels.matchAll(/Id="rId(\d+)"/g)].map((m) => Number(m[1])));
|
|
10035
|
-
const newRid = `rId${maxRid + 1}`;
|
|
10036
|
-
zip.file(presRelsPath, presRels.replace("</Relationships>", `<Relationship Id="${newRid}" Type="${SLIDE_REL_TYPE}" Target="slides/slide${newNum}.xml"/></Relationships>`));
|
|
10037
|
-
const presPath = "ppt/presentation.xml";
|
|
10038
|
-
const pres = await text(zip, presPath);
|
|
10039
|
-
const maxSldId = Math.max(255, ...[...pres.matchAll(/<p:sldId id="(\d+)"/g)].map((m) => Number(m[1])));
|
|
10040
|
-
const updated = pres.replace("</p:sldIdLst>", `<p:sldId id="${maxSldId + 1}" r:id="${newRid}"/></p:sldIdLst>`);
|
|
10041
|
-
if (updated === pres)
|
|
10042
|
-
throw new Error("could not locate the slide list in presentation.xml");
|
|
10043
|
-
zip.file(presPath, updated);
|
|
10054
|
+
await registerSlidePart(zip, newNum, newXmlPath);
|
|
10044
10055
|
const out = await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" });
|
|
10045
10056
|
return { bytes: new Uint8Array(out), newSlideNumber: newNum, replaced, missing, warnings };
|
|
10046
10057
|
}
|
|
@@ -10065,7 +10076,7 @@ async function removePptxSlide(bytes, slideNumber) {
|
|
|
10065
10076
|
const xmlPath = `ppt/slides/slide${slideNumber}.xml`;
|
|
10066
10077
|
const relsPath = `ppt/slides/_rels/slide${slideNumber}.xml.rels`;
|
|
10067
10078
|
const presRelsPath = "ppt/_rels/presentation.xml.rels";
|
|
10068
|
-
const presRels = await
|
|
10079
|
+
const presRels = await text2(zip, presRelsPath);
|
|
10069
10080
|
const targetRe = new RegExp(`Target="(/ppt/)?slides/slide${slideNumber}\\.xml"`);
|
|
10070
10081
|
const relMatch = findElement(presRels, "Relationship", (r) => r.includes(SLIDE_REL_TYPE) && targetRe.test(r));
|
|
10071
10082
|
if (!relMatch)
|
|
@@ -10075,19 +10086,19 @@ async function removePptxSlide(bytes, slideNumber) {
|
|
|
10075
10086
|
throw new Error(`slide ${slideNumber}'s relationship carries no Id (corrupt deck?)`);
|
|
10076
10087
|
zip.file(presRelsPath, presRels.replace(relMatch, ""));
|
|
10077
10088
|
const presPath = "ppt/presentation.xml";
|
|
10078
|
-
const pres = await
|
|
10089
|
+
const pres = await text2(zip, presPath);
|
|
10079
10090
|
const sld = removeElement(pres, "p:sldId", (el) => el.includes(`r:id="${rId}"`));
|
|
10080
10091
|
if (!sld.removed)
|
|
10081
10092
|
throw new Error(`slide ${slideNumber} (${rId}) not found in the slide list (corrupt deck?)`);
|
|
10082
10093
|
zip.file(presPath, sld.xml);
|
|
10083
|
-
const slideRels = zip.file(relsPath) ? await
|
|
10094
|
+
const slideRels = zip.file(relsPath) ? await text2(zip, relsPath) : "";
|
|
10084
10095
|
const notesTarget = /<Relationship\b[^>]*Type="[^"]*\/notesSlide"[^>]*Target="\.\.\/(notesSlides\/notesSlide\d+\.xml)"/.exec(slideRels)?.[1];
|
|
10085
10096
|
const removedParts = [xmlPath, relsPath];
|
|
10086
10097
|
if (notesTarget) {
|
|
10087
10098
|
const otherSlideRels = Object.keys(zip.files).filter((p) => /^ppt\/slides\/_rels\/slide\d+\.xml\.rels$/.test(p) && p !== relsPath);
|
|
10088
10099
|
let shared = false;
|
|
10089
10100
|
for (const p of otherSlideRels) {
|
|
10090
|
-
if ((await
|
|
10101
|
+
if ((await text2(zip, p)).includes(notesTarget)) {
|
|
10091
10102
|
shared = true;
|
|
10092
10103
|
break;
|
|
10093
10104
|
}
|
|
@@ -10095,7 +10106,7 @@ async function removePptxSlide(bytes, slideNumber) {
|
|
|
10095
10106
|
if (!shared)
|
|
10096
10107
|
removedParts.push(`ppt/${notesTarget}`, `ppt/notesSlides/_rels/${notesTarget.split("/")[1]}.rels`);
|
|
10097
10108
|
}
|
|
10098
|
-
let ct = await
|
|
10109
|
+
let ct = await text2(zip, "[Content_Types].xml");
|
|
10099
10110
|
for (const part of removedParts) {
|
|
10100
10111
|
zip.remove(part);
|
|
10101
10112
|
ct = removeElement(ct, "Override", (el) => el.includes(`PartName="/${part}"`)).xml;
|
|
@@ -9820,10 +9820,14 @@ var import_promises = require("node:fs/promises");
|
|
|
9820
9820
|
|
|
9821
9821
|
// packages/core/dist/document/pptx-fonts.js
|
|
9822
9822
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
9823
|
-
|
|
9823
|
+
|
|
9824
|
+
// packages/core/dist/document/ooxml-util.js
|
|
9824
9825
|
function escXml(s) {
|
|
9825
|
-
return s.replace(
|
|
9826
|
+
return s.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
|
9826
9827
|
}
|
|
9828
|
+
|
|
9829
|
+
// packages/core/dist/document/pptx-fonts.js
|
|
9830
|
+
var FONT_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/font";
|
|
9827
9831
|
async function text(zip, path) {
|
|
9828
9832
|
const f = zip.file(path);
|
|
9829
9833
|
if (!f)
|