pptx-glimpse 0.3.1 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +240 -95
- package/dist/index.js +240 -95
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -1540,8 +1540,8 @@ var standardParser = new import_fast_xml_parser.XMLParser({
|
|
|
1540
1540
|
attributeNamePrefix: "@_",
|
|
1541
1541
|
removeNSPrefix: true,
|
|
1542
1542
|
htmlEntities: true,
|
|
1543
|
-
isArray: (_name, jpath) => {
|
|
1544
|
-
const tag = jpath.split(".").pop() ?? "";
|
|
1543
|
+
isArray: (_name, jpath, _isLeafNode, _isAttribute) => {
|
|
1544
|
+
const tag = String(jpath).split(".").pop() ?? "";
|
|
1545
1545
|
return ARRAY_TAGS.has(tag);
|
|
1546
1546
|
}
|
|
1547
1547
|
});
|
|
@@ -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 = [
|
|
@@ -6141,7 +6276,8 @@ var presetGeometries = {
|
|
|
6141
6276
|
rect: (w, h) => `<rect width="${w}" height="${h}"/>`,
|
|
6142
6277
|
ellipse: (w, h) => `<ellipse cx="${w / 2}" cy="${h / 2}" rx="${w / 2}" ry="${h / 2}"/>`,
|
|
6143
6278
|
roundRect: (w, h, adj) => {
|
|
6144
|
-
const
|
|
6279
|
+
const a = Math.min(5e4, Math.max(0, adj["adj"] ?? 16667));
|
|
6280
|
+
const r = a / 1e5 * Math.min(w, h);
|
|
6145
6281
|
return `<rect width="${w}" height="${h}" rx="${r}" ry="${r}"/>`;
|
|
6146
6282
|
},
|
|
6147
6283
|
triangle: (w, h, adj) => {
|
|
@@ -6787,17 +6923,22 @@ var presetGeometries = {
|
|
|
6787
6923
|
return `<path d="M ${r} 0 L ${w - d} 0 L ${w} ${d} L ${w} ${h} L 0 ${h} L 0 ${r} A ${r} ${r} 0 0 1 ${r} 0 Z"/>`;
|
|
6788
6924
|
},
|
|
6789
6925
|
round1Rect: (w, h, adj) => {
|
|
6790
|
-
const
|
|
6926
|
+
const a = Math.min(5e4, Math.max(0, adj["adj"] ?? 16667));
|
|
6927
|
+
const r = a / 1e5 * Math.min(w, h);
|
|
6791
6928
|
return `<path d="M 0 0 L ${w - r} 0 A ${r} ${r} 0 0 1 ${w} ${r} L ${w} ${h} L 0 ${h} Z"/>`;
|
|
6792
6929
|
},
|
|
6793
6930
|
round2SameRect: (w, h, adj) => {
|
|
6794
|
-
const
|
|
6795
|
-
const
|
|
6931
|
+
const a1 = Math.min(5e4, Math.max(0, adj["adj1"] ?? 16667));
|
|
6932
|
+
const a2 = Math.min(5e4, Math.max(0, adj["adj2"] ?? 0));
|
|
6933
|
+
const r1 = a1 / 1e5 * Math.min(w, h);
|
|
6934
|
+
const r2 = a2 / 1e5 * Math.min(w, h);
|
|
6796
6935
|
return `<path d="M ${r1} 0 L ${w - r1} 0 A ${r1} ${r1} 0 0 1 ${w} ${r1} L ${w} ${h - r2} A ${r2} ${r2} 0 0 1 ${w - r2} ${h} L ${r2} ${h} A ${r2} ${r2} 0 0 1 0 ${h - r2} L 0 ${r1} A ${r1} ${r1} 0 0 1 ${r1} 0 Z"/>`;
|
|
6797
6936
|
},
|
|
6798
6937
|
round2DiagRect: (w, h, adj) => {
|
|
6799
|
-
const
|
|
6800
|
-
const
|
|
6938
|
+
const a1 = Math.min(5e4, Math.max(0, adj["adj1"] ?? 16667));
|
|
6939
|
+
const a2 = Math.min(5e4, Math.max(0, adj["adj2"] ?? 0));
|
|
6940
|
+
const r1 = a1 / 1e5 * Math.min(w, h);
|
|
6941
|
+
const r2 = a2 / 1e5 * Math.min(w, h);
|
|
6801
6942
|
return `<path d="M ${r1} 0 L ${w} 0 L ${w} ${h - r2} A ${r2} ${r2} 0 0 1 ${w - r2} ${h} L 0 ${h} L 0 ${r1} A ${r1} ${r1} 0 0 1 ${r1} 0 Z"/>`;
|
|
6802
6943
|
},
|
|
6803
6944
|
// Brackets and braces
|
|
@@ -8458,8 +8599,8 @@ async function convertPptxToSvg(input, options) {
|
|
|
8458
8599
|
for (const { slideNumber, path } of targetSlides) {
|
|
8459
8600
|
const parsed = parseSlideWithLayout(slideNumber, path, data);
|
|
8460
8601
|
if (!parsed) continue;
|
|
8461
|
-
const { slide, layoutElements, layoutShowMasterSp } = parsed;
|
|
8462
|
-
const effectiveMasterElements = slide.showMasterSp && layoutShowMasterSp ?
|
|
8602
|
+
const { slide, layoutElements, layoutShowMasterSp, masterElements } = parsed;
|
|
8603
|
+
const effectiveMasterElements = slide.showMasterSp && layoutShowMasterSp ? masterElements : [];
|
|
8463
8604
|
slide.elements = mergeElements(effectiveMasterElements, layoutElements, slide.elements);
|
|
8464
8605
|
const svg = renderSlideToSvg(slide, data.presInfo.slideSize);
|
|
8465
8606
|
results.push({ slideNumber, svg });
|
|
@@ -8508,12 +8649,16 @@ function collectUsedFonts(input) {
|
|
|
8508
8649
|
const fontScheme = data.theme.fontScheme;
|
|
8509
8650
|
const fonts = /* @__PURE__ */ new Set();
|
|
8510
8651
|
collectThemeFonts(fontScheme, fonts);
|
|
8652
|
+
const collectedMasters = /* @__PURE__ */ new Set();
|
|
8511
8653
|
for (const { slideNumber, path } of data.slidePaths) {
|
|
8512
8654
|
const parsed = parseSlideWithLayout(slideNumber, path, data);
|
|
8513
8655
|
if (!parsed) continue;
|
|
8514
8656
|
collectFontsFromElements(parsed.slide.elements, fonts);
|
|
8657
|
+
if (!collectedMasters.has(parsed.masterElements)) {
|
|
8658
|
+
collectedMasters.add(parsed.masterElements);
|
|
8659
|
+
collectFontsFromElements(parsed.masterElements, fonts);
|
|
8660
|
+
}
|
|
8515
8661
|
}
|
|
8516
|
-
collectFontsFromElements(data.masterElements, fonts);
|
|
8517
8662
|
return {
|
|
8518
8663
|
theme: {
|
|
8519
8664
|
majorFont: fontScheme.majorFont,
|
package/dist/index.js
CHANGED
|
@@ -1495,8 +1495,8 @@ var standardParser = new XMLParser({
|
|
|
1495
1495
|
attributeNamePrefix: "@_",
|
|
1496
1496
|
removeNSPrefix: true,
|
|
1497
1497
|
htmlEntities: true,
|
|
1498
|
-
isArray: (_name, jpath) => {
|
|
1499
|
-
const tag = jpath.split(".").pop() ?? "";
|
|
1498
|
+
isArray: (_name, jpath, _isLeafNode, _isAttribute) => {
|
|
1499
|
+
const tag = String(jpath).split(".").pop() ?? "";
|
|
1500
1500
|
return ARRAY_TAGS.has(tag);
|
|
1501
1501
|
}
|
|
1502
1502
|
});
|
|
@@ -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 = [
|
|
@@ -6096,7 +6231,8 @@ var presetGeometries = {
|
|
|
6096
6231
|
rect: (w, h) => `<rect width="${w}" height="${h}"/>`,
|
|
6097
6232
|
ellipse: (w, h) => `<ellipse cx="${w / 2}" cy="${h / 2}" rx="${w / 2}" ry="${h / 2}"/>`,
|
|
6098
6233
|
roundRect: (w, h, adj) => {
|
|
6099
|
-
const
|
|
6234
|
+
const a = Math.min(5e4, Math.max(0, adj["adj"] ?? 16667));
|
|
6235
|
+
const r = a / 1e5 * Math.min(w, h);
|
|
6100
6236
|
return `<rect width="${w}" height="${h}" rx="${r}" ry="${r}"/>`;
|
|
6101
6237
|
},
|
|
6102
6238
|
triangle: (w, h, adj) => {
|
|
@@ -6742,17 +6878,22 @@ var presetGeometries = {
|
|
|
6742
6878
|
return `<path d="M ${r} 0 L ${w - d} 0 L ${w} ${d} L ${w} ${h} L 0 ${h} L 0 ${r} A ${r} ${r} 0 0 1 ${r} 0 Z"/>`;
|
|
6743
6879
|
},
|
|
6744
6880
|
round1Rect: (w, h, adj) => {
|
|
6745
|
-
const
|
|
6881
|
+
const a = Math.min(5e4, Math.max(0, adj["adj"] ?? 16667));
|
|
6882
|
+
const r = a / 1e5 * Math.min(w, h);
|
|
6746
6883
|
return `<path d="M 0 0 L ${w - r} 0 A ${r} ${r} 0 0 1 ${w} ${r} L ${w} ${h} L 0 ${h} Z"/>`;
|
|
6747
6884
|
},
|
|
6748
6885
|
round2SameRect: (w, h, adj) => {
|
|
6749
|
-
const
|
|
6750
|
-
const
|
|
6886
|
+
const a1 = Math.min(5e4, Math.max(0, adj["adj1"] ?? 16667));
|
|
6887
|
+
const a2 = Math.min(5e4, Math.max(0, adj["adj2"] ?? 0));
|
|
6888
|
+
const r1 = a1 / 1e5 * Math.min(w, h);
|
|
6889
|
+
const r2 = a2 / 1e5 * Math.min(w, h);
|
|
6751
6890
|
return `<path d="M ${r1} 0 L ${w - r1} 0 A ${r1} ${r1} 0 0 1 ${w} ${r1} L ${w} ${h - r2} A ${r2} ${r2} 0 0 1 ${w - r2} ${h} L ${r2} ${h} A ${r2} ${r2} 0 0 1 0 ${h - r2} L 0 ${r1} A ${r1} ${r1} 0 0 1 ${r1} 0 Z"/>`;
|
|
6752
6891
|
},
|
|
6753
6892
|
round2DiagRect: (w, h, adj) => {
|
|
6754
|
-
const
|
|
6755
|
-
const
|
|
6893
|
+
const a1 = Math.min(5e4, Math.max(0, adj["adj1"] ?? 16667));
|
|
6894
|
+
const a2 = Math.min(5e4, Math.max(0, adj["adj2"] ?? 0));
|
|
6895
|
+
const r1 = a1 / 1e5 * Math.min(w, h);
|
|
6896
|
+
const r2 = a2 / 1e5 * Math.min(w, h);
|
|
6756
6897
|
return `<path d="M ${r1} 0 L ${w} 0 L ${w} ${h - r2} A ${r2} ${r2} 0 0 1 ${w - r2} ${h} L 0 ${h} L 0 ${r1} A ${r1} ${r1} 0 0 1 ${r1} 0 Z"/>`;
|
|
6757
6898
|
},
|
|
6758
6899
|
// Brackets and braces
|
|
@@ -8413,8 +8554,8 @@ async function convertPptxToSvg(input, options) {
|
|
|
8413
8554
|
for (const { slideNumber, path } of targetSlides) {
|
|
8414
8555
|
const parsed = parseSlideWithLayout(slideNumber, path, data);
|
|
8415
8556
|
if (!parsed) continue;
|
|
8416
|
-
const { slide, layoutElements, layoutShowMasterSp } = parsed;
|
|
8417
|
-
const effectiveMasterElements = slide.showMasterSp && layoutShowMasterSp ?
|
|
8557
|
+
const { slide, layoutElements, layoutShowMasterSp, masterElements } = parsed;
|
|
8558
|
+
const effectiveMasterElements = slide.showMasterSp && layoutShowMasterSp ? masterElements : [];
|
|
8418
8559
|
slide.elements = mergeElements(effectiveMasterElements, layoutElements, slide.elements);
|
|
8419
8560
|
const svg = renderSlideToSvg(slide, data.presInfo.slideSize);
|
|
8420
8561
|
results.push({ slideNumber, svg });
|
|
@@ -8463,12 +8604,16 @@ function collectUsedFonts(input) {
|
|
|
8463
8604
|
const fontScheme = data.theme.fontScheme;
|
|
8464
8605
|
const fonts = /* @__PURE__ */ new Set();
|
|
8465
8606
|
collectThemeFonts(fontScheme, fonts);
|
|
8607
|
+
const collectedMasters = /* @__PURE__ */ new Set();
|
|
8466
8608
|
for (const { slideNumber, path } of data.slidePaths) {
|
|
8467
8609
|
const parsed = parseSlideWithLayout(slideNumber, path, data);
|
|
8468
8610
|
if (!parsed) continue;
|
|
8469
8611
|
collectFontsFromElements(parsed.slide.elements, fonts);
|
|
8612
|
+
if (!collectedMasters.has(parsed.masterElements)) {
|
|
8613
|
+
collectedMasters.add(parsed.masterElements);
|
|
8614
|
+
collectFontsFromElements(parsed.masterElements, fonts);
|
|
8615
|
+
}
|
|
8470
8616
|
}
|
|
8471
|
-
collectFontsFromElements(data.masterElements, fonts);
|
|
8472
8617
|
return {
|
|
8473
8618
|
theme: {
|
|
8474
8619
|
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.1",
|
|
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
|
},
|