pptx-glimpse 0.3.1 → 0.4.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/dist/index.cjs +226 -87
- package/dist/index.js +226 -87
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -1819,18 +1819,48 @@ function extractAlpha(node) {
|
|
|
1819
1819
|
|
|
1820
1820
|
// src/parser/pptx-reader.ts
|
|
1821
1821
|
var import_fflate = require("fflate");
|
|
1822
|
+
var LazyMediaMap = class {
|
|
1823
|
+
rawInput;
|
|
1824
|
+
cache = /* @__PURE__ */ new Map();
|
|
1825
|
+
entryIndex;
|
|
1826
|
+
constructor(rawInput, mediaEntryNames) {
|
|
1827
|
+
this.rawInput = rawInput;
|
|
1828
|
+
this.entryIndex = mediaEntryNames;
|
|
1829
|
+
}
|
|
1830
|
+
get(path) {
|
|
1831
|
+
if (!this.entryIndex.has(path)) return void 0;
|
|
1832
|
+
const cached = this.cache.get(path);
|
|
1833
|
+
if (cached) return cached;
|
|
1834
|
+
const result = (0, import_fflate.unzipSync)(this.rawInput, {
|
|
1835
|
+
filter: (file) => file.name === path
|
|
1836
|
+
});
|
|
1837
|
+
const data = result[path];
|
|
1838
|
+
if (data) {
|
|
1839
|
+
this.cache.set(path, data);
|
|
1840
|
+
}
|
|
1841
|
+
return data;
|
|
1842
|
+
}
|
|
1843
|
+
};
|
|
1822
1844
|
function readPptx(input) {
|
|
1823
|
-
const
|
|
1845
|
+
const rawInput = new Uint8Array(input);
|
|
1846
|
+
const mediaEntryNames = /* @__PURE__ */ new Set();
|
|
1847
|
+
const unzipped = (0, import_fflate.unzipSync)(rawInput, {
|
|
1848
|
+
filter: (file) => {
|
|
1849
|
+
if (file.name.startsWith("ppt/media/")) {
|
|
1850
|
+
mediaEntryNames.add(file.name);
|
|
1851
|
+
return false;
|
|
1852
|
+
}
|
|
1853
|
+
return true;
|
|
1854
|
+
}
|
|
1855
|
+
});
|
|
1824
1856
|
const files = /* @__PURE__ */ new Map();
|
|
1825
|
-
const media = /* @__PURE__ */ new Map();
|
|
1826
1857
|
for (const [relativePath, data] of Object.entries(unzipped)) {
|
|
1827
1858
|
if (relativePath.endsWith("/")) continue;
|
|
1828
|
-
if (relativePath.
|
|
1829
|
-
media.set(relativePath, data);
|
|
1830
|
-
} else if (relativePath.endsWith(".xml") || relativePath.endsWith(".rels") || relativePath === "[Content_Types].xml") {
|
|
1859
|
+
if (relativePath.endsWith(".xml") || relativePath.endsWith(".rels") || relativePath === "[Content_Types].xml") {
|
|
1831
1860
|
files.set(relativePath, (0, import_fflate.strFromU8)(data));
|
|
1832
1861
|
}
|
|
1833
1862
|
}
|
|
1863
|
+
const media = new LazyMediaMap(rawInput, mediaEntryNames);
|
|
1834
1864
|
return { files, media };
|
|
1835
1865
|
}
|
|
1836
1866
|
|
|
@@ -2270,13 +2300,11 @@ function parseBlipEffects(blipNode, colorResolver) {
|
|
|
2270
2300
|
const blur = parseBlur(blipNode.blur);
|
|
2271
2301
|
const lum = parseLum(blipNode.lum);
|
|
2272
2302
|
const duotone = parseDuotone(blipNode.duotone, colorResolver);
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
}
|
|
2276
|
-
if (!grayscale && !biLevel && !blur && !lum && !duotone) {
|
|
2303
|
+
const clrChange = parseClrChange(blipNode.clrChange, colorResolver);
|
|
2304
|
+
if (!grayscale && !biLevel && !blur && !lum && !duotone && !clrChange) {
|
|
2277
2305
|
return null;
|
|
2278
2306
|
}
|
|
2279
|
-
return { grayscale, biLevel, blur, lum, duotone };
|
|
2307
|
+
return { grayscale, biLevel, blur, lum, duotone, clrChange };
|
|
2280
2308
|
}
|
|
2281
2309
|
function parseBiLevel(node) {
|
|
2282
2310
|
if (!node) return null;
|
|
@@ -2312,6 +2340,16 @@ function parseDuotone(node, colorResolver) {
|
|
|
2312
2340
|
if (colors.length < 2) return null;
|
|
2313
2341
|
return { color1: colors[0], color2: colors[1] };
|
|
2314
2342
|
}
|
|
2343
|
+
function parseClrChange(node, colorResolver) {
|
|
2344
|
+
if (!node) return null;
|
|
2345
|
+
const clrFrom = node.clrFrom;
|
|
2346
|
+
const clrTo = node.clrTo;
|
|
2347
|
+
if (!clrFrom || !clrTo) return null;
|
|
2348
|
+
const from = colorResolver.resolve(clrFrom);
|
|
2349
|
+
const to = colorResolver.resolve(clrTo);
|
|
2350
|
+
if (!from || !to) return null;
|
|
2351
|
+
return { clrFrom: from, clrTo: to };
|
|
2352
|
+
}
|
|
2315
2353
|
function resolveColorNode(key, node, colorResolver) {
|
|
2316
2354
|
if (key === "prstClr") {
|
|
2317
2355
|
const val = node["@_val"];
|
|
@@ -4586,38 +4624,21 @@ function parsePptxData(input) {
|
|
|
4586
4624
|
break;
|
|
4587
4625
|
}
|
|
4588
4626
|
}
|
|
4589
|
-
|
|
4590
|
-
let
|
|
4627
|
+
const masterCache = /* @__PURE__ */ new Map();
|
|
4628
|
+
let firstMasterPath = null;
|
|
4591
4629
|
for (const [, rel] of presRels) {
|
|
4592
4630
|
if (rel.type.includes("slideMaster")) {
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
colorMap = parseSlideMasterColorMap(masterXml2);
|
|
4597
|
-
}
|
|
4598
|
-
break;
|
|
4631
|
+
const mPath = resolveRelationshipTarget("ppt/presentation.xml", rel.target);
|
|
4632
|
+
if (!firstMasterPath) firstMasterPath = mPath;
|
|
4633
|
+
parseMasterDataCached(mPath, archive, theme, masterCache);
|
|
4599
4634
|
}
|
|
4600
4635
|
}
|
|
4601
|
-
const
|
|
4602
|
-
const
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
const masterRels = masterRelsXml ? parseRelationships(masterRelsXml) : /* @__PURE__ */ new Map();
|
|
4608
|
-
masterFillContext = { rels: masterRels, archive, basePath: masterPath };
|
|
4609
|
-
}
|
|
4610
|
-
const masterBackground = masterXml ? parseSlideMasterBackground(masterXml, colorResolver, masterFillContext) : null;
|
|
4611
|
-
const masterElements = masterPath && masterXml ? parseSlideMasterElements(
|
|
4612
|
-
masterXml,
|
|
4613
|
-
masterPath,
|
|
4614
|
-
archive,
|
|
4615
|
-
colorResolver,
|
|
4616
|
-
theme.fontScheme,
|
|
4617
|
-
theme.fmtScheme
|
|
4618
|
-
) : [];
|
|
4619
|
-
const masterTxStyles = masterXml ? parseSlideMasterTxStyles(masterXml, colorResolver) : void 0;
|
|
4620
|
-
const masterPlaceholderStyles = masterXml ? parseSlideMasterPlaceholderStyles(masterXml, colorResolver) : [];
|
|
4636
|
+
const defaultMaster = firstMasterPath ? masterCache.get(firstMasterPath) : void 0;
|
|
4637
|
+
const colorResolver = defaultMaster?.colorResolver ?? new ColorResolver(theme.colorScheme, defaultColorMap2());
|
|
4638
|
+
const masterBackground = defaultMaster?.background ?? null;
|
|
4639
|
+
const masterElements = defaultMaster?.elements ?? [];
|
|
4640
|
+
const masterTxStyles = defaultMaster?.txStyles;
|
|
4641
|
+
const masterPlaceholderStyles = defaultMaster?.placeholderStyles ?? [];
|
|
4621
4642
|
const slidePaths = [];
|
|
4622
4643
|
for (let i = 0; i < presInfo.slideRIds.length; i++) {
|
|
4623
4644
|
const rId = presInfo.slideRIds[i];
|
|
@@ -4636,77 +4657,100 @@ function parsePptxData(input) {
|
|
|
4636
4657
|
masterTxStyles,
|
|
4637
4658
|
masterPlaceholderStyles,
|
|
4638
4659
|
slidePaths,
|
|
4639
|
-
archive
|
|
4660
|
+
archive,
|
|
4661
|
+
masterCache
|
|
4640
4662
|
};
|
|
4641
4663
|
}
|
|
4642
4664
|
function parseSlideWithLayout(slideNumber, path, data) {
|
|
4643
4665
|
const slideXml = data.archive.files.get(path);
|
|
4644
4666
|
if (!slideXml) return null;
|
|
4667
|
+
const slideRelsPath = buildRelsPath(path);
|
|
4668
|
+
const slideRelsXml = data.archive.files.get(slideRelsPath);
|
|
4669
|
+
const slideRels = slideRelsXml ? parseRelationships(slideRelsXml) : /* @__PURE__ */ new Map();
|
|
4670
|
+
let layoutPath = null;
|
|
4671
|
+
let layoutXml;
|
|
4672
|
+
let layoutRels = /* @__PURE__ */ new Map();
|
|
4673
|
+
for (const [, rel] of slideRels) {
|
|
4674
|
+
if (rel.type.includes("slideLayout")) {
|
|
4675
|
+
layoutPath = resolveRelationshipTarget(path, rel.target);
|
|
4676
|
+
layoutXml = data.archive.files.get(layoutPath);
|
|
4677
|
+
if (layoutXml) {
|
|
4678
|
+
const layoutRelsPath = buildRelsPath(layoutPath);
|
|
4679
|
+
const layoutRelsXml = data.archive.files.get(layoutRelsPath);
|
|
4680
|
+
layoutRels = layoutRelsXml ? parseRelationships(layoutRelsXml) : /* @__PURE__ */ new Map();
|
|
4681
|
+
}
|
|
4682
|
+
break;
|
|
4683
|
+
}
|
|
4684
|
+
}
|
|
4685
|
+
let slideMasterData;
|
|
4686
|
+
for (const [, rel] of layoutRels) {
|
|
4687
|
+
if (rel.type.includes("slideMaster") && layoutPath) {
|
|
4688
|
+
const masterPath = resolveRelationshipTarget(layoutPath, rel.target);
|
|
4689
|
+
slideMasterData = parseMasterDataCached(
|
|
4690
|
+
masterPath,
|
|
4691
|
+
data.archive,
|
|
4692
|
+
data.theme,
|
|
4693
|
+
data.masterCache
|
|
4694
|
+
);
|
|
4695
|
+
break;
|
|
4696
|
+
}
|
|
4697
|
+
}
|
|
4698
|
+
const slideColorResolver = resolveSlideColorResolver(
|
|
4699
|
+
slideXml,
|
|
4700
|
+
layoutXml,
|
|
4701
|
+
slideMasterData,
|
|
4702
|
+
data.theme
|
|
4703
|
+
);
|
|
4645
4704
|
const slide = parseSlide(
|
|
4646
4705
|
slideXml,
|
|
4647
4706
|
path,
|
|
4648
4707
|
slideNumber,
|
|
4649
4708
|
data.archive,
|
|
4650
|
-
|
|
4709
|
+
slideColorResolver,
|
|
4651
4710
|
data.theme.fontScheme,
|
|
4652
4711
|
data.theme.fmtScheme
|
|
4653
4712
|
);
|
|
4654
4713
|
let layoutElements = [];
|
|
4655
4714
|
let layoutPlaceholderStyles = [];
|
|
4656
4715
|
let layoutShowMasterSp = true;
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
const layoutRels = layoutRelsXml ? parseRelationships(layoutRelsXml) : /* @__PURE__ */ new Map();
|
|
4670
|
-
const layoutFillContext = {
|
|
4671
|
-
rels: layoutRels,
|
|
4672
|
-
archive: data.archive,
|
|
4673
|
-
basePath: layoutPath
|
|
4674
|
-
};
|
|
4675
|
-
slide.background = parseSlideLayoutBackground(
|
|
4676
|
-
layoutXml,
|
|
4677
|
-
data.colorResolver,
|
|
4678
|
-
layoutFillContext
|
|
4679
|
-
);
|
|
4680
|
-
}
|
|
4681
|
-
layoutElements = parseSlideLayoutElements(
|
|
4682
|
-
layoutXml,
|
|
4683
|
-
layoutPath,
|
|
4684
|
-
data.archive,
|
|
4685
|
-
data.colorResolver,
|
|
4686
|
-
data.theme.fontScheme,
|
|
4687
|
-
data.theme.fmtScheme
|
|
4688
|
-
);
|
|
4689
|
-
layoutPlaceholderStyles = parseSlideLayoutPlaceholderStyles(
|
|
4690
|
-
layoutXml,
|
|
4691
|
-
data.colorResolver
|
|
4692
|
-
);
|
|
4693
|
-
layoutShowMasterSp = parseSlideLayoutShowMasterSp(layoutXml);
|
|
4694
|
-
}
|
|
4695
|
-
break;
|
|
4696
|
-
}
|
|
4716
|
+
if (layoutXml && layoutPath) {
|
|
4717
|
+
if (!slide.background) {
|
|
4718
|
+
const layoutFillContext = {
|
|
4719
|
+
rels: layoutRels,
|
|
4720
|
+
archive: data.archive,
|
|
4721
|
+
basePath: layoutPath
|
|
4722
|
+
};
|
|
4723
|
+
slide.background = parseSlideLayoutBackground(
|
|
4724
|
+
layoutXml,
|
|
4725
|
+
slideColorResolver,
|
|
4726
|
+
layoutFillContext
|
|
4727
|
+
);
|
|
4697
4728
|
}
|
|
4729
|
+
layoutElements = parseSlideLayoutElements(
|
|
4730
|
+
layoutXml,
|
|
4731
|
+
layoutPath,
|
|
4732
|
+
data.archive,
|
|
4733
|
+
slideColorResolver,
|
|
4734
|
+
data.theme.fontScheme,
|
|
4735
|
+
data.theme.fmtScheme
|
|
4736
|
+
);
|
|
4737
|
+
layoutPlaceholderStyles = parseSlideLayoutPlaceholderStyles(layoutXml, slideColorResolver);
|
|
4738
|
+
layoutShowMasterSp = parseSlideLayoutShowMasterSp(layoutXml);
|
|
4698
4739
|
}
|
|
4699
4740
|
if (!slide.background) {
|
|
4700
|
-
slide.background = data.masterBackground;
|
|
4741
|
+
slide.background = slideMasterData?.background ?? data.masterBackground;
|
|
4701
4742
|
}
|
|
4743
|
+
const masterPlaceholderStyles = slideMasterData?.placeholderStyles ?? data.masterPlaceholderStyles;
|
|
4744
|
+
const masterTxStyles = slideMasterData?.txStyles ?? data.masterTxStyles;
|
|
4702
4745
|
applyTextStyleInheritance(slide.elements, {
|
|
4703
4746
|
layoutPlaceholderStyles,
|
|
4704
|
-
masterPlaceholderStyles
|
|
4705
|
-
txStyles:
|
|
4747
|
+
masterPlaceholderStyles,
|
|
4748
|
+
txStyles: masterTxStyles,
|
|
4706
4749
|
defaultTextStyle: data.presInfo.defaultTextStyle,
|
|
4707
4750
|
fontScheme: data.theme.fontScheme
|
|
4708
4751
|
});
|
|
4709
|
-
|
|
4752
|
+
const masterElements = slideMasterData?.elements ?? data.masterElements;
|
|
4753
|
+
return { slide, layoutElements, layoutShowMasterSp, masterElements };
|
|
4710
4754
|
}
|
|
4711
4755
|
function defaultColorScheme2() {
|
|
4712
4756
|
return {
|
|
@@ -4740,6 +4784,88 @@ function defaultColorMap2() {
|
|
|
4740
4784
|
folHlink: "folHlink"
|
|
4741
4785
|
};
|
|
4742
4786
|
}
|
|
4787
|
+
function parseMasterDataCached(masterPath, archive, theme, cache) {
|
|
4788
|
+
const cached = cache.get(masterPath);
|
|
4789
|
+
if (cached) return cached;
|
|
4790
|
+
const masterXml = archive.files.get(masterPath);
|
|
4791
|
+
if (!masterXml) return void 0;
|
|
4792
|
+
const colorMap = parseSlideMasterColorMap(masterXml);
|
|
4793
|
+
const colorResolver = new ColorResolver(theme.colorScheme, colorMap);
|
|
4794
|
+
const masterRelsPath = buildRelsPath(masterPath);
|
|
4795
|
+
const masterRelsXml = archive.files.get(masterRelsPath);
|
|
4796
|
+
const masterRels = masterRelsXml ? parseRelationships(masterRelsXml) : /* @__PURE__ */ new Map();
|
|
4797
|
+
const masterFillContext = { rels: masterRels, archive, basePath: masterPath };
|
|
4798
|
+
const background = parseSlideMasterBackground(masterXml, colorResolver, masterFillContext);
|
|
4799
|
+
const elements = parseSlideMasterElements(
|
|
4800
|
+
masterXml,
|
|
4801
|
+
masterPath,
|
|
4802
|
+
archive,
|
|
4803
|
+
colorResolver,
|
|
4804
|
+
theme.fontScheme,
|
|
4805
|
+
theme.fmtScheme
|
|
4806
|
+
);
|
|
4807
|
+
const txStyles = parseSlideMasterTxStyles(masterXml, colorResolver);
|
|
4808
|
+
const placeholderStyles = parseSlideMasterPlaceholderStyles(masterXml, colorResolver);
|
|
4809
|
+
const data = {
|
|
4810
|
+
colorMap,
|
|
4811
|
+
colorResolver,
|
|
4812
|
+
background,
|
|
4813
|
+
elements,
|
|
4814
|
+
txStyles,
|
|
4815
|
+
placeholderStyles
|
|
4816
|
+
};
|
|
4817
|
+
cache.set(masterPath, data);
|
|
4818
|
+
return data;
|
|
4819
|
+
}
|
|
4820
|
+
function resolveSlideColorResolver(slideXml, layoutXml, masterData, theme) {
|
|
4821
|
+
const baseColorMap = masterData?.colorMap ?? defaultColorMap2();
|
|
4822
|
+
const layoutOverride = layoutXml ? parseClrMapOverride(layoutXml) : null;
|
|
4823
|
+
const slideOverride = parseClrMapOverride(slideXml);
|
|
4824
|
+
let effectiveColorMap = baseColorMap;
|
|
4825
|
+
if (layoutOverride) {
|
|
4826
|
+
effectiveColorMap = { ...effectiveColorMap, ...layoutOverride };
|
|
4827
|
+
}
|
|
4828
|
+
if (slideOverride) {
|
|
4829
|
+
effectiveColorMap = { ...effectiveColorMap, ...slideOverride };
|
|
4830
|
+
}
|
|
4831
|
+
if (!layoutOverride && !slideOverride && masterData) {
|
|
4832
|
+
return masterData.colorResolver;
|
|
4833
|
+
}
|
|
4834
|
+
return new ColorResolver(theme.colorScheme, effectiveColorMap);
|
|
4835
|
+
}
|
|
4836
|
+
function parseClrMapOverride(xml) {
|
|
4837
|
+
if (!xml.includes("clrMapOvr")) return null;
|
|
4838
|
+
const parsed = parseXml(xml);
|
|
4839
|
+
const root = parsed.sld ?? parsed.sldLayout;
|
|
4840
|
+
if (!root) return null;
|
|
4841
|
+
const clrMapOvr = root.clrMapOvr;
|
|
4842
|
+
if (!clrMapOvr) return null;
|
|
4843
|
+
if (clrMapOvr.masterClrMapping !== void 0) return null;
|
|
4844
|
+
const override = clrMapOvr.overrideClrMapping;
|
|
4845
|
+
if (!override) return null;
|
|
4846
|
+
const result = {};
|
|
4847
|
+
const keys = [
|
|
4848
|
+
"bg1",
|
|
4849
|
+
"tx1",
|
|
4850
|
+
"bg2",
|
|
4851
|
+
"tx2",
|
|
4852
|
+
"accent1",
|
|
4853
|
+
"accent2",
|
|
4854
|
+
"accent3",
|
|
4855
|
+
"accent4",
|
|
4856
|
+
"accent5",
|
|
4857
|
+
"accent6",
|
|
4858
|
+
"hlink",
|
|
4859
|
+
"folHlink"
|
|
4860
|
+
];
|
|
4861
|
+
for (const key of keys) {
|
|
4862
|
+
const val = override[`@_${key}`];
|
|
4863
|
+
if (val) {
|
|
4864
|
+
result[key] = val;
|
|
4865
|
+
}
|
|
4866
|
+
}
|
|
4867
|
+
return Object.keys(result).length > 0 ? result : null;
|
|
4868
|
+
}
|
|
4743
4869
|
|
|
4744
4870
|
// src/renderer/transform.ts
|
|
4745
4871
|
function buildTransformAttr(t) {
|
|
@@ -5906,6 +6032,15 @@ function renderBlipEffects(blipEffects) {
|
|
|
5906
6032
|
);
|
|
5907
6033
|
lastResult = "duotoneResult";
|
|
5908
6034
|
}
|
|
6035
|
+
if (blipEffects.clrChange && blipEffects.clrChange.clrTo.alpha === 0) {
|
|
6036
|
+
const { clrFrom } = blipEffects.clrChange;
|
|
6037
|
+
const [rf, gf, bf] = hexToRgbNorm(clrFrom.hex);
|
|
6038
|
+
const scale = 20;
|
|
6039
|
+
primitives.push(
|
|
6040
|
+
`<feColorMatrix in="${lastResult}" type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 ${round2(scale)} ${round2(scale)} ${round2(scale)} 0 ${round2(-scale * (rf + gf + bf))}" result="clrChangeResult"/>`
|
|
6041
|
+
);
|
|
6042
|
+
lastResult = "clrChangeResult";
|
|
6043
|
+
}
|
|
5909
6044
|
if (primitives.length === 0) return { filterAttr: "", filterDefs: "" };
|
|
5910
6045
|
const id = `blip-effect-${crypto.randomUUID()}`;
|
|
5911
6046
|
const filterDefs = [
|
|
@@ -8458,8 +8593,8 @@ async function convertPptxToSvg(input, options) {
|
|
|
8458
8593
|
for (const { slideNumber, path } of targetSlides) {
|
|
8459
8594
|
const parsed = parseSlideWithLayout(slideNumber, path, data);
|
|
8460
8595
|
if (!parsed) continue;
|
|
8461
|
-
const { slide, layoutElements, layoutShowMasterSp } = parsed;
|
|
8462
|
-
const effectiveMasterElements = slide.showMasterSp && layoutShowMasterSp ?
|
|
8596
|
+
const { slide, layoutElements, layoutShowMasterSp, masterElements } = parsed;
|
|
8597
|
+
const effectiveMasterElements = slide.showMasterSp && layoutShowMasterSp ? masterElements : [];
|
|
8463
8598
|
slide.elements = mergeElements(effectiveMasterElements, layoutElements, slide.elements);
|
|
8464
8599
|
const svg = renderSlideToSvg(slide, data.presInfo.slideSize);
|
|
8465
8600
|
results.push({ slideNumber, svg });
|
|
@@ -8508,12 +8643,16 @@ function collectUsedFonts(input) {
|
|
|
8508
8643
|
const fontScheme = data.theme.fontScheme;
|
|
8509
8644
|
const fonts = /* @__PURE__ */ new Set();
|
|
8510
8645
|
collectThemeFonts(fontScheme, fonts);
|
|
8646
|
+
const collectedMasters = /* @__PURE__ */ new Set();
|
|
8511
8647
|
for (const { slideNumber, path } of data.slidePaths) {
|
|
8512
8648
|
const parsed = parseSlideWithLayout(slideNumber, path, data);
|
|
8513
8649
|
if (!parsed) continue;
|
|
8514
8650
|
collectFontsFromElements(parsed.slide.elements, fonts);
|
|
8651
|
+
if (!collectedMasters.has(parsed.masterElements)) {
|
|
8652
|
+
collectedMasters.add(parsed.masterElements);
|
|
8653
|
+
collectFontsFromElements(parsed.masterElements, fonts);
|
|
8654
|
+
}
|
|
8515
8655
|
}
|
|
8516
|
-
collectFontsFromElements(data.masterElements, fonts);
|
|
8517
8656
|
return {
|
|
8518
8657
|
theme: {
|
|
8519
8658
|
majorFont: fontScheme.majorFont,
|
package/dist/index.js
CHANGED
|
@@ -1774,18 +1774,48 @@ function extractAlpha(node) {
|
|
|
1774
1774
|
|
|
1775
1775
|
// src/parser/pptx-reader.ts
|
|
1776
1776
|
import { strFromU8, unzipSync } from "fflate";
|
|
1777
|
+
var LazyMediaMap = class {
|
|
1778
|
+
rawInput;
|
|
1779
|
+
cache = /* @__PURE__ */ new Map();
|
|
1780
|
+
entryIndex;
|
|
1781
|
+
constructor(rawInput, mediaEntryNames) {
|
|
1782
|
+
this.rawInput = rawInput;
|
|
1783
|
+
this.entryIndex = mediaEntryNames;
|
|
1784
|
+
}
|
|
1785
|
+
get(path) {
|
|
1786
|
+
if (!this.entryIndex.has(path)) return void 0;
|
|
1787
|
+
const cached = this.cache.get(path);
|
|
1788
|
+
if (cached) return cached;
|
|
1789
|
+
const result = unzipSync(this.rawInput, {
|
|
1790
|
+
filter: (file) => file.name === path
|
|
1791
|
+
});
|
|
1792
|
+
const data = result[path];
|
|
1793
|
+
if (data) {
|
|
1794
|
+
this.cache.set(path, data);
|
|
1795
|
+
}
|
|
1796
|
+
return data;
|
|
1797
|
+
}
|
|
1798
|
+
};
|
|
1777
1799
|
function readPptx(input) {
|
|
1778
|
-
const
|
|
1800
|
+
const rawInput = new Uint8Array(input);
|
|
1801
|
+
const mediaEntryNames = /* @__PURE__ */ new Set();
|
|
1802
|
+
const unzipped = unzipSync(rawInput, {
|
|
1803
|
+
filter: (file) => {
|
|
1804
|
+
if (file.name.startsWith("ppt/media/")) {
|
|
1805
|
+
mediaEntryNames.add(file.name);
|
|
1806
|
+
return false;
|
|
1807
|
+
}
|
|
1808
|
+
return true;
|
|
1809
|
+
}
|
|
1810
|
+
});
|
|
1779
1811
|
const files = /* @__PURE__ */ new Map();
|
|
1780
|
-
const media = /* @__PURE__ */ new Map();
|
|
1781
1812
|
for (const [relativePath, data] of Object.entries(unzipped)) {
|
|
1782
1813
|
if (relativePath.endsWith("/")) continue;
|
|
1783
|
-
if (relativePath.
|
|
1784
|
-
media.set(relativePath, data);
|
|
1785
|
-
} else if (relativePath.endsWith(".xml") || relativePath.endsWith(".rels") || relativePath === "[Content_Types].xml") {
|
|
1814
|
+
if (relativePath.endsWith(".xml") || relativePath.endsWith(".rels") || relativePath === "[Content_Types].xml") {
|
|
1786
1815
|
files.set(relativePath, strFromU8(data));
|
|
1787
1816
|
}
|
|
1788
1817
|
}
|
|
1818
|
+
const media = new LazyMediaMap(rawInput, mediaEntryNames);
|
|
1789
1819
|
return { files, media };
|
|
1790
1820
|
}
|
|
1791
1821
|
|
|
@@ -2225,13 +2255,11 @@ function parseBlipEffects(blipNode, colorResolver) {
|
|
|
2225
2255
|
const blur = parseBlur(blipNode.blur);
|
|
2226
2256
|
const lum = parseLum(blipNode.lum);
|
|
2227
2257
|
const duotone = parseDuotone(blipNode.duotone, colorResolver);
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
}
|
|
2231
|
-
if (!grayscale && !biLevel && !blur && !lum && !duotone) {
|
|
2258
|
+
const clrChange = parseClrChange(blipNode.clrChange, colorResolver);
|
|
2259
|
+
if (!grayscale && !biLevel && !blur && !lum && !duotone && !clrChange) {
|
|
2232
2260
|
return null;
|
|
2233
2261
|
}
|
|
2234
|
-
return { grayscale, biLevel, blur, lum, duotone };
|
|
2262
|
+
return { grayscale, biLevel, blur, lum, duotone, clrChange };
|
|
2235
2263
|
}
|
|
2236
2264
|
function parseBiLevel(node) {
|
|
2237
2265
|
if (!node) return null;
|
|
@@ -2267,6 +2295,16 @@ function parseDuotone(node, colorResolver) {
|
|
|
2267
2295
|
if (colors.length < 2) return null;
|
|
2268
2296
|
return { color1: colors[0], color2: colors[1] };
|
|
2269
2297
|
}
|
|
2298
|
+
function parseClrChange(node, colorResolver) {
|
|
2299
|
+
if (!node) return null;
|
|
2300
|
+
const clrFrom = node.clrFrom;
|
|
2301
|
+
const clrTo = node.clrTo;
|
|
2302
|
+
if (!clrFrom || !clrTo) return null;
|
|
2303
|
+
const from = colorResolver.resolve(clrFrom);
|
|
2304
|
+
const to = colorResolver.resolve(clrTo);
|
|
2305
|
+
if (!from || !to) return null;
|
|
2306
|
+
return { clrFrom: from, clrTo: to };
|
|
2307
|
+
}
|
|
2270
2308
|
function resolveColorNode(key, node, colorResolver) {
|
|
2271
2309
|
if (key === "prstClr") {
|
|
2272
2310
|
const val = node["@_val"];
|
|
@@ -4541,38 +4579,21 @@ function parsePptxData(input) {
|
|
|
4541
4579
|
break;
|
|
4542
4580
|
}
|
|
4543
4581
|
}
|
|
4544
|
-
|
|
4545
|
-
let
|
|
4582
|
+
const masterCache = /* @__PURE__ */ new Map();
|
|
4583
|
+
let firstMasterPath = null;
|
|
4546
4584
|
for (const [, rel] of presRels) {
|
|
4547
4585
|
if (rel.type.includes("slideMaster")) {
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
colorMap = parseSlideMasterColorMap(masterXml2);
|
|
4552
|
-
}
|
|
4553
|
-
break;
|
|
4586
|
+
const mPath = resolveRelationshipTarget("ppt/presentation.xml", rel.target);
|
|
4587
|
+
if (!firstMasterPath) firstMasterPath = mPath;
|
|
4588
|
+
parseMasterDataCached(mPath, archive, theme, masterCache);
|
|
4554
4589
|
}
|
|
4555
4590
|
}
|
|
4556
|
-
const
|
|
4557
|
-
const
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
const masterRels = masterRelsXml ? parseRelationships(masterRelsXml) : /* @__PURE__ */ new Map();
|
|
4563
|
-
masterFillContext = { rels: masterRels, archive, basePath: masterPath };
|
|
4564
|
-
}
|
|
4565
|
-
const masterBackground = masterXml ? parseSlideMasterBackground(masterXml, colorResolver, masterFillContext) : null;
|
|
4566
|
-
const masterElements = masterPath && masterXml ? parseSlideMasterElements(
|
|
4567
|
-
masterXml,
|
|
4568
|
-
masterPath,
|
|
4569
|
-
archive,
|
|
4570
|
-
colorResolver,
|
|
4571
|
-
theme.fontScheme,
|
|
4572
|
-
theme.fmtScheme
|
|
4573
|
-
) : [];
|
|
4574
|
-
const masterTxStyles = masterXml ? parseSlideMasterTxStyles(masterXml, colorResolver) : void 0;
|
|
4575
|
-
const masterPlaceholderStyles = masterXml ? parseSlideMasterPlaceholderStyles(masterXml, colorResolver) : [];
|
|
4591
|
+
const defaultMaster = firstMasterPath ? masterCache.get(firstMasterPath) : void 0;
|
|
4592
|
+
const colorResolver = defaultMaster?.colorResolver ?? new ColorResolver(theme.colorScheme, defaultColorMap2());
|
|
4593
|
+
const masterBackground = defaultMaster?.background ?? null;
|
|
4594
|
+
const masterElements = defaultMaster?.elements ?? [];
|
|
4595
|
+
const masterTxStyles = defaultMaster?.txStyles;
|
|
4596
|
+
const masterPlaceholderStyles = defaultMaster?.placeholderStyles ?? [];
|
|
4576
4597
|
const slidePaths = [];
|
|
4577
4598
|
for (let i = 0; i < presInfo.slideRIds.length; i++) {
|
|
4578
4599
|
const rId = presInfo.slideRIds[i];
|
|
@@ -4591,77 +4612,100 @@ function parsePptxData(input) {
|
|
|
4591
4612
|
masterTxStyles,
|
|
4592
4613
|
masterPlaceholderStyles,
|
|
4593
4614
|
slidePaths,
|
|
4594
|
-
archive
|
|
4615
|
+
archive,
|
|
4616
|
+
masterCache
|
|
4595
4617
|
};
|
|
4596
4618
|
}
|
|
4597
4619
|
function parseSlideWithLayout(slideNumber, path, data) {
|
|
4598
4620
|
const slideXml = data.archive.files.get(path);
|
|
4599
4621
|
if (!slideXml) return null;
|
|
4622
|
+
const slideRelsPath = buildRelsPath(path);
|
|
4623
|
+
const slideRelsXml = data.archive.files.get(slideRelsPath);
|
|
4624
|
+
const slideRels = slideRelsXml ? parseRelationships(slideRelsXml) : /* @__PURE__ */ new Map();
|
|
4625
|
+
let layoutPath = null;
|
|
4626
|
+
let layoutXml;
|
|
4627
|
+
let layoutRels = /* @__PURE__ */ new Map();
|
|
4628
|
+
for (const [, rel] of slideRels) {
|
|
4629
|
+
if (rel.type.includes("slideLayout")) {
|
|
4630
|
+
layoutPath = resolveRelationshipTarget(path, rel.target);
|
|
4631
|
+
layoutXml = data.archive.files.get(layoutPath);
|
|
4632
|
+
if (layoutXml) {
|
|
4633
|
+
const layoutRelsPath = buildRelsPath(layoutPath);
|
|
4634
|
+
const layoutRelsXml = data.archive.files.get(layoutRelsPath);
|
|
4635
|
+
layoutRels = layoutRelsXml ? parseRelationships(layoutRelsXml) : /* @__PURE__ */ new Map();
|
|
4636
|
+
}
|
|
4637
|
+
break;
|
|
4638
|
+
}
|
|
4639
|
+
}
|
|
4640
|
+
let slideMasterData;
|
|
4641
|
+
for (const [, rel] of layoutRels) {
|
|
4642
|
+
if (rel.type.includes("slideMaster") && layoutPath) {
|
|
4643
|
+
const masterPath = resolveRelationshipTarget(layoutPath, rel.target);
|
|
4644
|
+
slideMasterData = parseMasterDataCached(
|
|
4645
|
+
masterPath,
|
|
4646
|
+
data.archive,
|
|
4647
|
+
data.theme,
|
|
4648
|
+
data.masterCache
|
|
4649
|
+
);
|
|
4650
|
+
break;
|
|
4651
|
+
}
|
|
4652
|
+
}
|
|
4653
|
+
const slideColorResolver = resolveSlideColorResolver(
|
|
4654
|
+
slideXml,
|
|
4655
|
+
layoutXml,
|
|
4656
|
+
slideMasterData,
|
|
4657
|
+
data.theme
|
|
4658
|
+
);
|
|
4600
4659
|
const slide = parseSlide(
|
|
4601
4660
|
slideXml,
|
|
4602
4661
|
path,
|
|
4603
4662
|
slideNumber,
|
|
4604
4663
|
data.archive,
|
|
4605
|
-
|
|
4664
|
+
slideColorResolver,
|
|
4606
4665
|
data.theme.fontScheme,
|
|
4607
4666
|
data.theme.fmtScheme
|
|
4608
4667
|
);
|
|
4609
4668
|
let layoutElements = [];
|
|
4610
4669
|
let layoutPlaceholderStyles = [];
|
|
4611
4670
|
let layoutShowMasterSp = true;
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
const layoutRels = layoutRelsXml ? parseRelationships(layoutRelsXml) : /* @__PURE__ */ new Map();
|
|
4625
|
-
const layoutFillContext = {
|
|
4626
|
-
rels: layoutRels,
|
|
4627
|
-
archive: data.archive,
|
|
4628
|
-
basePath: layoutPath
|
|
4629
|
-
};
|
|
4630
|
-
slide.background = parseSlideLayoutBackground(
|
|
4631
|
-
layoutXml,
|
|
4632
|
-
data.colorResolver,
|
|
4633
|
-
layoutFillContext
|
|
4634
|
-
);
|
|
4635
|
-
}
|
|
4636
|
-
layoutElements = parseSlideLayoutElements(
|
|
4637
|
-
layoutXml,
|
|
4638
|
-
layoutPath,
|
|
4639
|
-
data.archive,
|
|
4640
|
-
data.colorResolver,
|
|
4641
|
-
data.theme.fontScheme,
|
|
4642
|
-
data.theme.fmtScheme
|
|
4643
|
-
);
|
|
4644
|
-
layoutPlaceholderStyles = parseSlideLayoutPlaceholderStyles(
|
|
4645
|
-
layoutXml,
|
|
4646
|
-
data.colorResolver
|
|
4647
|
-
);
|
|
4648
|
-
layoutShowMasterSp = parseSlideLayoutShowMasterSp(layoutXml);
|
|
4649
|
-
}
|
|
4650
|
-
break;
|
|
4651
|
-
}
|
|
4671
|
+
if (layoutXml && layoutPath) {
|
|
4672
|
+
if (!slide.background) {
|
|
4673
|
+
const layoutFillContext = {
|
|
4674
|
+
rels: layoutRels,
|
|
4675
|
+
archive: data.archive,
|
|
4676
|
+
basePath: layoutPath
|
|
4677
|
+
};
|
|
4678
|
+
slide.background = parseSlideLayoutBackground(
|
|
4679
|
+
layoutXml,
|
|
4680
|
+
slideColorResolver,
|
|
4681
|
+
layoutFillContext
|
|
4682
|
+
);
|
|
4652
4683
|
}
|
|
4684
|
+
layoutElements = parseSlideLayoutElements(
|
|
4685
|
+
layoutXml,
|
|
4686
|
+
layoutPath,
|
|
4687
|
+
data.archive,
|
|
4688
|
+
slideColorResolver,
|
|
4689
|
+
data.theme.fontScheme,
|
|
4690
|
+
data.theme.fmtScheme
|
|
4691
|
+
);
|
|
4692
|
+
layoutPlaceholderStyles = parseSlideLayoutPlaceholderStyles(layoutXml, slideColorResolver);
|
|
4693
|
+
layoutShowMasterSp = parseSlideLayoutShowMasterSp(layoutXml);
|
|
4653
4694
|
}
|
|
4654
4695
|
if (!slide.background) {
|
|
4655
|
-
slide.background = data.masterBackground;
|
|
4696
|
+
slide.background = slideMasterData?.background ?? data.masterBackground;
|
|
4656
4697
|
}
|
|
4698
|
+
const masterPlaceholderStyles = slideMasterData?.placeholderStyles ?? data.masterPlaceholderStyles;
|
|
4699
|
+
const masterTxStyles = slideMasterData?.txStyles ?? data.masterTxStyles;
|
|
4657
4700
|
applyTextStyleInheritance(slide.elements, {
|
|
4658
4701
|
layoutPlaceholderStyles,
|
|
4659
|
-
masterPlaceholderStyles
|
|
4660
|
-
txStyles:
|
|
4702
|
+
masterPlaceholderStyles,
|
|
4703
|
+
txStyles: masterTxStyles,
|
|
4661
4704
|
defaultTextStyle: data.presInfo.defaultTextStyle,
|
|
4662
4705
|
fontScheme: data.theme.fontScheme
|
|
4663
4706
|
});
|
|
4664
|
-
|
|
4707
|
+
const masterElements = slideMasterData?.elements ?? data.masterElements;
|
|
4708
|
+
return { slide, layoutElements, layoutShowMasterSp, masterElements };
|
|
4665
4709
|
}
|
|
4666
4710
|
function defaultColorScheme2() {
|
|
4667
4711
|
return {
|
|
@@ -4695,6 +4739,88 @@ function defaultColorMap2() {
|
|
|
4695
4739
|
folHlink: "folHlink"
|
|
4696
4740
|
};
|
|
4697
4741
|
}
|
|
4742
|
+
function parseMasterDataCached(masterPath, archive, theme, cache) {
|
|
4743
|
+
const cached = cache.get(masterPath);
|
|
4744
|
+
if (cached) return cached;
|
|
4745
|
+
const masterXml = archive.files.get(masterPath);
|
|
4746
|
+
if (!masterXml) return void 0;
|
|
4747
|
+
const colorMap = parseSlideMasterColorMap(masterXml);
|
|
4748
|
+
const colorResolver = new ColorResolver(theme.colorScheme, colorMap);
|
|
4749
|
+
const masterRelsPath = buildRelsPath(masterPath);
|
|
4750
|
+
const masterRelsXml = archive.files.get(masterRelsPath);
|
|
4751
|
+
const masterRels = masterRelsXml ? parseRelationships(masterRelsXml) : /* @__PURE__ */ new Map();
|
|
4752
|
+
const masterFillContext = { rels: masterRels, archive, basePath: masterPath };
|
|
4753
|
+
const background = parseSlideMasterBackground(masterXml, colorResolver, masterFillContext);
|
|
4754
|
+
const elements = parseSlideMasterElements(
|
|
4755
|
+
masterXml,
|
|
4756
|
+
masterPath,
|
|
4757
|
+
archive,
|
|
4758
|
+
colorResolver,
|
|
4759
|
+
theme.fontScheme,
|
|
4760
|
+
theme.fmtScheme
|
|
4761
|
+
);
|
|
4762
|
+
const txStyles = parseSlideMasterTxStyles(masterXml, colorResolver);
|
|
4763
|
+
const placeholderStyles = parseSlideMasterPlaceholderStyles(masterXml, colorResolver);
|
|
4764
|
+
const data = {
|
|
4765
|
+
colorMap,
|
|
4766
|
+
colorResolver,
|
|
4767
|
+
background,
|
|
4768
|
+
elements,
|
|
4769
|
+
txStyles,
|
|
4770
|
+
placeholderStyles
|
|
4771
|
+
};
|
|
4772
|
+
cache.set(masterPath, data);
|
|
4773
|
+
return data;
|
|
4774
|
+
}
|
|
4775
|
+
function resolveSlideColorResolver(slideXml, layoutXml, masterData, theme) {
|
|
4776
|
+
const baseColorMap = masterData?.colorMap ?? defaultColorMap2();
|
|
4777
|
+
const layoutOverride = layoutXml ? parseClrMapOverride(layoutXml) : null;
|
|
4778
|
+
const slideOverride = parseClrMapOverride(slideXml);
|
|
4779
|
+
let effectiveColorMap = baseColorMap;
|
|
4780
|
+
if (layoutOverride) {
|
|
4781
|
+
effectiveColorMap = { ...effectiveColorMap, ...layoutOverride };
|
|
4782
|
+
}
|
|
4783
|
+
if (slideOverride) {
|
|
4784
|
+
effectiveColorMap = { ...effectiveColorMap, ...slideOverride };
|
|
4785
|
+
}
|
|
4786
|
+
if (!layoutOverride && !slideOverride && masterData) {
|
|
4787
|
+
return masterData.colorResolver;
|
|
4788
|
+
}
|
|
4789
|
+
return new ColorResolver(theme.colorScheme, effectiveColorMap);
|
|
4790
|
+
}
|
|
4791
|
+
function parseClrMapOverride(xml) {
|
|
4792
|
+
if (!xml.includes("clrMapOvr")) return null;
|
|
4793
|
+
const parsed = parseXml(xml);
|
|
4794
|
+
const root = parsed.sld ?? parsed.sldLayout;
|
|
4795
|
+
if (!root) return null;
|
|
4796
|
+
const clrMapOvr = root.clrMapOvr;
|
|
4797
|
+
if (!clrMapOvr) return null;
|
|
4798
|
+
if (clrMapOvr.masterClrMapping !== void 0) return null;
|
|
4799
|
+
const override = clrMapOvr.overrideClrMapping;
|
|
4800
|
+
if (!override) return null;
|
|
4801
|
+
const result = {};
|
|
4802
|
+
const keys = [
|
|
4803
|
+
"bg1",
|
|
4804
|
+
"tx1",
|
|
4805
|
+
"bg2",
|
|
4806
|
+
"tx2",
|
|
4807
|
+
"accent1",
|
|
4808
|
+
"accent2",
|
|
4809
|
+
"accent3",
|
|
4810
|
+
"accent4",
|
|
4811
|
+
"accent5",
|
|
4812
|
+
"accent6",
|
|
4813
|
+
"hlink",
|
|
4814
|
+
"folHlink"
|
|
4815
|
+
];
|
|
4816
|
+
for (const key of keys) {
|
|
4817
|
+
const val = override[`@_${key}`];
|
|
4818
|
+
if (val) {
|
|
4819
|
+
result[key] = val;
|
|
4820
|
+
}
|
|
4821
|
+
}
|
|
4822
|
+
return Object.keys(result).length > 0 ? result : null;
|
|
4823
|
+
}
|
|
4698
4824
|
|
|
4699
4825
|
// src/renderer/transform.ts
|
|
4700
4826
|
function buildTransformAttr(t) {
|
|
@@ -5861,6 +5987,15 @@ function renderBlipEffects(blipEffects) {
|
|
|
5861
5987
|
);
|
|
5862
5988
|
lastResult = "duotoneResult";
|
|
5863
5989
|
}
|
|
5990
|
+
if (blipEffects.clrChange && blipEffects.clrChange.clrTo.alpha === 0) {
|
|
5991
|
+
const { clrFrom } = blipEffects.clrChange;
|
|
5992
|
+
const [rf, gf, bf] = hexToRgbNorm(clrFrom.hex);
|
|
5993
|
+
const scale = 20;
|
|
5994
|
+
primitives.push(
|
|
5995
|
+
`<feColorMatrix in="${lastResult}" type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 ${round2(scale)} ${round2(scale)} ${round2(scale)} 0 ${round2(-scale * (rf + gf + bf))}" result="clrChangeResult"/>`
|
|
5996
|
+
);
|
|
5997
|
+
lastResult = "clrChangeResult";
|
|
5998
|
+
}
|
|
5864
5999
|
if (primitives.length === 0) return { filterAttr: "", filterDefs: "" };
|
|
5865
6000
|
const id = `blip-effect-${crypto.randomUUID()}`;
|
|
5866
6001
|
const filterDefs = [
|
|
@@ -8413,8 +8548,8 @@ async function convertPptxToSvg(input, options) {
|
|
|
8413
8548
|
for (const { slideNumber, path } of targetSlides) {
|
|
8414
8549
|
const parsed = parseSlideWithLayout(slideNumber, path, data);
|
|
8415
8550
|
if (!parsed) continue;
|
|
8416
|
-
const { slide, layoutElements, layoutShowMasterSp } = parsed;
|
|
8417
|
-
const effectiveMasterElements = slide.showMasterSp && layoutShowMasterSp ?
|
|
8551
|
+
const { slide, layoutElements, layoutShowMasterSp, masterElements } = parsed;
|
|
8552
|
+
const effectiveMasterElements = slide.showMasterSp && layoutShowMasterSp ? masterElements : [];
|
|
8418
8553
|
slide.elements = mergeElements(effectiveMasterElements, layoutElements, slide.elements);
|
|
8419
8554
|
const svg = renderSlideToSvg(slide, data.presInfo.slideSize);
|
|
8420
8555
|
results.push({ slideNumber, svg });
|
|
@@ -8463,12 +8598,16 @@ function collectUsedFonts(input) {
|
|
|
8463
8598
|
const fontScheme = data.theme.fontScheme;
|
|
8464
8599
|
const fonts = /* @__PURE__ */ new Set();
|
|
8465
8600
|
collectThemeFonts(fontScheme, fonts);
|
|
8601
|
+
const collectedMasters = /* @__PURE__ */ new Set();
|
|
8466
8602
|
for (const { slideNumber, path } of data.slidePaths) {
|
|
8467
8603
|
const parsed = parseSlideWithLayout(slideNumber, path, data);
|
|
8468
8604
|
if (!parsed) continue;
|
|
8469
8605
|
collectFontsFromElements(parsed.slide.elements, fonts);
|
|
8606
|
+
if (!collectedMasters.has(parsed.masterElements)) {
|
|
8607
|
+
collectedMasters.add(parsed.masterElements);
|
|
8608
|
+
collectFontsFromElements(parsed.masterElements, fonts);
|
|
8609
|
+
}
|
|
8470
8610
|
}
|
|
8471
|
-
collectFontsFromElements(data.masterElements, fonts);
|
|
8472
8611
|
return {
|
|
8473
8612
|
theme: {
|
|
8474
8613
|
majorFont: fontScheme.majorFont,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pptx-glimpse",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "A lightweight JavaScript library for rendering PowerPoint (.pptx) files as SVG or PNG in Node.js. No LibreOffice required.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"files": [
|
|
43
43
|
"dist"
|
|
44
44
|
],
|
|
45
|
+
"packageManager": "npm@10.9.6",
|
|
45
46
|
"engines": {
|
|
46
47
|
"node": ">=20"
|
|
47
48
|
},
|