pptx-viewer-core 1.6.6 → 1.6.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/dist/index.js CHANGED
@@ -497,14 +497,52 @@ function extractSourceOrders(xml) {
497
497
  }
498
498
  return orders;
499
499
  }
500
+ function ensureArrayLocal(value) {
501
+ return Array.isArray(value) ? value : value === void 0 ? [] : [value];
502
+ }
503
+ function countsSignature(counts) {
504
+ return [...counts.entries()].sort((a, b) => a[0] < b[0] ? -1 : 1).map(([name, count]) => `${name}:${count}`).join(",");
505
+ }
506
+ function pathSignature(path) {
507
+ const counts = /* @__PURE__ */ new Map();
508
+ for (const key of Object.keys(path)) {
509
+ const name = localName(key);
510
+ if (!PATH_COMMANDS.has(name)) {
511
+ continue;
512
+ }
513
+ counts.set(name, (counts.get(name) ?? 0) + ensureArrayLocal(path[key]).length);
514
+ }
515
+ return countsSignature(counts);
516
+ }
517
+ function orderSignature(order) {
518
+ const counts = /* @__PURE__ */ new Map();
519
+ for (const name of order) {
520
+ counts.set(name, (counts.get(name) ?? 0) + 1);
521
+ }
522
+ return countsSignature(counts);
523
+ }
500
524
  function annotateCustomGeometryCommandOrder(xml, parsed) {
501
525
  const orders = extractSourceOrders(xml);
502
526
  if (orders.length === 0) {
503
527
  return;
504
528
  }
505
529
  const paths = collectParsedPaths(parsed);
506
- for (let index = 0; index < Math.min(paths.length, orders.length); index++) {
507
- commandOrder.set(paths[index], orders[index]);
530
+ const ordersBySignature = /* @__PURE__ */ new Map();
531
+ for (const order of orders) {
532
+ const signature = orderSignature(order);
533
+ const bucket = ordersBySignature.get(signature);
534
+ if (bucket) {
535
+ bucket.push(order);
536
+ } else {
537
+ ordersBySignature.set(signature, [order]);
538
+ }
539
+ }
540
+ for (const path of paths) {
541
+ const bucket = ordersBySignature.get(pathSignature(path));
542
+ const order = bucket?.shift();
543
+ if (order) {
544
+ commandOrder.set(path, order);
545
+ }
508
546
  }
509
547
  }
510
548
  function orderedPathCommandEntries(path, ensureArray16) {
@@ -23135,15 +23173,15 @@ function getConnectorPathGeometry(element) {
23135
23173
  // src/core/geometry/transform-utils.ts
23136
23174
  function getElementTransform(element) {
23137
23175
  const transforms = [];
23176
+ if (element.rotation) {
23177
+ transforms.push(`rotate(${element.rotation}deg)`);
23178
+ }
23138
23179
  if (element.flipHorizontal) {
23139
23180
  transforms.push("scaleX(-1)");
23140
23181
  }
23141
23182
  if (element.flipVertical) {
23142
23183
  transforms.push("scaleY(-1)");
23143
23184
  }
23144
- if (element.rotation) {
23145
- transforms.push(`rotate(${element.rotation}deg)`);
23146
- }
23147
23185
  return transforms.length > 0 ? transforms.join(" ") : void 0;
23148
23186
  }
23149
23187
  function getTextCompensationTransform(element) {
@@ -61737,7 +61775,7 @@ var PptxHandlerRuntime59 = class extends PptxHandlerRuntime58 {
61737
61775
  pointsToPixels(points3) {
61738
61776
  return points3 * (96 / 72);
61739
61777
  }
61740
- parseParagraphSpacingPx(spacingNode) {
61778
+ parseParagraphSpacingPx(spacingNode, basisFontSizePx) {
61741
61779
  if (!spacingNode) {
61742
61780
  return void 0;
61743
61781
  }
@@ -61748,6 +61786,13 @@ var PptxHandlerRuntime59 = class extends PptxHandlerRuntime58 {
61748
61786
  if (Number.isFinite(spacingPointsRaw)) {
61749
61787
  return this.pointsToPixels(spacingPointsRaw / 100);
61750
61788
  }
61789
+ const spacingPercentRaw = Number.parseInt(
61790
+ String(spacingNode["a:spcPct"]?.["@_val"] || ""),
61791
+ 10
61792
+ );
61793
+ if (Number.isFinite(spacingPercentRaw) && typeof basisFontSizePx === "number" && basisFontSizePx > 0) {
61794
+ return spacingPercentRaw / 1e5 * basisFontSizePx;
61795
+ }
61751
61796
  return void 0;
61752
61797
  }
61753
61798
  parseLineSpacingMultiplier(lineSpacingNode) {
@@ -61827,7 +61872,7 @@ var PptxHandlerRuntime59 = class extends PptxHandlerRuntime58 {
61827
61872
 
61828
61873
  // src/core/core/runtime/PptxHandlerRuntimeBulletParsing.ts
61829
61874
  var PptxHandlerRuntime60 = class extends PptxHandlerRuntime59 {
61830
- resolveParagraphBulletInfo(paragraph, paragraphIndex, txBody, inheritedTxBody, isBodyPlaceholder = false, slidePath) {
61875
+ resolveParagraphBulletInfo(paragraph, paragraphIndex, txBody, inheritedTxBody, isBodyPlaceholder = false, slidePath, effectiveLevelStyles) {
61831
61876
  if (!paragraph) {
61832
61877
  return null;
61833
61878
  }
@@ -61863,11 +61908,8 @@ var PptxHandlerRuntime60 = class extends PptxHandlerRuntime59 {
61863
61908
  }
61864
61909
  }
61865
61910
  if (!resolvedBulletProps) {
61866
- if (isBodyPlaceholder) {
61867
- const presentationLevelStyle = this.presentationDefaultTextStyle?.levelStyles?.[normalizedLevel - 1] ?? this.presentationDefaultTextStyle?.levelStyles?.[-1];
61868
- return this.createBulletInfoFromLevelStyle(presentationLevelStyle, paragraphIndex);
61869
- }
61870
- return null;
61911
+ const fallbackLevelStyle = effectiveLevelStyles?.[normalizedLevel - 1] ?? effectiveLevelStyles?.[-1] ?? (isBodyPlaceholder ? this.presentationDefaultTextStyle?.levelStyles?.[normalizedLevel - 1] ?? this.presentationDefaultTextStyle?.levelStyles?.[-1] : void 0);
61912
+ return this.createBulletInfoFromLevelStyle(fallbackLevelStyle, paragraphIndex);
61871
61913
  }
61872
61914
  const buFont = resolvedBulletProps["a:buFont"];
61873
61915
  const fontFamily = buFont?.["@_typeface"] ? String(buFont["@_typeface"]) : void 0;
@@ -62357,16 +62399,21 @@ var PptxHandlerRuntime62 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
62357
62399
  textStyle.align = paraAlign;
62358
62400
  }
62359
62401
  }
62402
+ const spacingBasisPx = typeof textStyle.fontSize === "number" ? textStyle.fontSize : void 0;
62360
62403
  if (textStyle.paragraphSpacingBefore === void 0) {
62361
62404
  const spacingBefore = this.parseParagraphSpacingPx(
62362
- pPr?.["a:spcBef"]
62405
+ pPr?.["a:spcBef"],
62406
+ spacingBasisPx
62363
62407
  );
62364
62408
  if (spacingBefore !== void 0) {
62365
62409
  textStyle.paragraphSpacingBefore = spacingBefore;
62366
62410
  }
62367
62411
  }
62368
62412
  if (textStyle.paragraphSpacingAfter === void 0) {
62369
- const spacingAfter = this.parseParagraphSpacingPx(pPr?.["a:spcAft"]);
62413
+ const spacingAfter = this.parseParagraphSpacingPx(
62414
+ pPr?.["a:spcAft"],
62415
+ spacingBasisPx
62416
+ );
62370
62417
  if (spacingAfter !== void 0) {
62371
62418
  textStyle.paragraphSpacingAfter = spacingAfter;
62372
62419
  }
@@ -62540,7 +62587,8 @@ var PptxHandlerRuntime63 = class extends PptxHandlerRuntime62 {
62540
62587
  ctx.txBody,
62541
62588
  ctx.inheritedTxBody,
62542
62589
  isBodyPlaceholder,
62543
- ctx.slidePath
62590
+ ctx.slidePath,
62591
+ ctx.effectiveLevelStyles
62544
62592
  );
62545
62593
  if (paragraphBulletInfo && !paragraphBulletInfo.none) {
62546
62594
  let bulletText;
@@ -64143,6 +64191,7 @@ var PptxHandlerRuntime69 = class extends PptxHandlerRuntime68 {
64143
64191
  if (!normalized) {
64144
64192
  return void 0;
64145
64193
  }
64194
+ const canon = (key) => key.toLowerCase() === "folhlink" ? "folHlink" : key;
64146
64195
  if (normalized === "phclr") {
64147
64196
  const injected = this.themeColorMap["phclr"];
64148
64197
  if (injected) {
@@ -64152,17 +64201,18 @@ var PptxHandlerRuntime69 = class extends PptxHandlerRuntime68 {
64152
64201
  }
64153
64202
  const overrideMap = this.currentSlideClrMapOverride ?? this.currentMasterClrMap;
64154
64203
  if (overrideMap) {
64155
- const remapped = overrideMap[normalized];
64204
+ const remapped = overrideMap[canon(normalized)];
64156
64205
  if (remapped) {
64157
- return this.themeColorMap[remapped] || this.getDefaultSchemeColorMap()[remapped];
64206
+ const target = canon(remapped);
64207
+ return this.themeColorMap[target] || this.getDefaultSchemeColorMap()[target];
64158
64208
  }
64159
64209
  } else {
64160
64210
  const defaultAliasTarget = DEFAULT_CLR_MAP_ALIAS[normalized];
64161
64211
  if (defaultAliasTarget) {
64162
- return this.themeColorMap[defaultAliasTarget] || this.themeColorMap[normalized] || this.getDefaultSchemeColorMap()[normalized];
64212
+ return this.themeColorMap[defaultAliasTarget] || this.themeColorMap[canon(normalized)] || this.getDefaultSchemeColorMap()[canon(normalized)];
64163
64213
  }
64164
64214
  }
64165
- return this.themeColorMap[normalized] || this.getDefaultSchemeColorMap()[normalized];
64215
+ return this.themeColorMap[canon(normalized)] || this.getDefaultSchemeColorMap()[canon(normalized)];
64166
64216
  }
64167
64217
  normalizeStrokeDashType(value) {
64168
64218
  const normalized = String(value ?? "").trim();
@@ -64451,6 +64501,40 @@ var PptxHandlerRuntime70 = class extends PptxHandlerRuntime69 {
64451
64501
  }
64452
64502
  return void 0;
64453
64503
  }
64504
+ /**
64505
+ * Reuse the cached parse of a layout XML part, parsing (and caching) on a
64506
+ * miss. Background resolution runs per slide but the layout/master parts are
64507
+ * large (a themed master can be ~200 KB); re-parsing them for every slide
64508
+ * dominated load time, so share the same parsed object `getLayoutElements`
64509
+ * already populated.
64510
+ */
64511
+ async resolveCachedLayoutXml(layoutPath) {
64512
+ const cached = this.layoutXmlMap.get(layoutPath);
64513
+ if (cached) {
64514
+ return cached;
64515
+ }
64516
+ const xml = await this.zip.file(layoutPath)?.async("string");
64517
+ if (!xml) {
64518
+ return void 0;
64519
+ }
64520
+ const parsed = this.parser.parse(xml);
64521
+ this.layoutXmlMap.set(layoutPath, parsed);
64522
+ return parsed;
64523
+ }
64524
+ /** Reuse the cached parse of a master XML part, parsing (and caching) on a miss. */
64525
+ async resolveCachedMasterXml(masterPath) {
64526
+ const cached = this.masterXmlMap.get(masterPath);
64527
+ if (cached) {
64528
+ return cached;
64529
+ }
64530
+ const xml = await this.zip.file(masterPath)?.async("string");
64531
+ if (!xml) {
64532
+ return void 0;
64533
+ }
64534
+ const parsed = this.parser.parse(xml);
64535
+ this.masterXmlMap.set(masterPath, parsed);
64536
+ return parsed;
64537
+ }
64454
64538
  async getMasterBackgroundImage(layoutPath) {
64455
64539
  const layoutRels = this.slideRelsMap.get(layoutPath);
64456
64540
  if (!layoutRels) {
@@ -64461,9 +64545,8 @@ var PptxHandlerRuntime70 = class extends PptxHandlerRuntime69 {
64461
64545
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
64462
64546
  const masterPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${stripParentDirSegments(target)}`;
64463
64547
  try {
64464
- const masterXmlStr = await this.zip.file(masterPath)?.async("string");
64465
- if (masterXmlStr) {
64466
- const masterXmlObj = this.parser.parse(masterXmlStr);
64548
+ const masterXmlObj = await this.resolveCachedMasterXml(masterPath);
64549
+ if (masterXmlObj) {
64467
64550
  const masterRelsPath = `${masterPath.replace("slideMasters/", "slideMasters/_rels/")}.rels`;
64468
64551
  await this.loadSlideRelationships(masterPath, masterRelsPath);
64469
64552
  return this.extractBackgroundImage(masterXmlObj, masterPath, "p:sldMaster");
@@ -64485,9 +64568,8 @@ var PptxHandlerRuntime70 = class extends PptxHandlerRuntime69 {
64485
64568
  const slideDir = slidePath.substring(0, slidePath.lastIndexOf("/") + 1);
64486
64569
  const layoutPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${stripParentDirSegments(target)}`;
64487
64570
  try {
64488
- const layoutXmlStr = await this.zip.file(layoutPath)?.async("string");
64489
- if (layoutXmlStr) {
64490
- const layoutXmlObj = this.parser.parse(layoutXmlStr);
64571
+ const layoutXmlObj = await this.resolveCachedLayoutXml(layoutPath);
64572
+ if (layoutXmlObj) {
64491
64573
  const layoutRelsPath = `${layoutPath.replace("slideLayouts/", "slideLayouts/_rels/")}.rels`;
64492
64574
  await this.loadSlideRelationships(layoutPath, layoutRelsPath);
64493
64575
  const bg = this.extractBackgroundImage(layoutXmlObj, layoutPath, "p:sldLayout");
@@ -64513,9 +64595,8 @@ var PptxHandlerRuntime70 = class extends PptxHandlerRuntime69 {
64513
64595
  const slideDir = slidePath.substring(0, slidePath.lastIndexOf("/") + 1);
64514
64596
  const layoutPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${stripParentDirSegments(target)}`;
64515
64597
  try {
64516
- const layoutXmlStr = await this.zip.file(layoutPath)?.async("string");
64517
- if (layoutXmlStr) {
64518
- const layoutXmlObj = this.parser.parse(layoutXmlStr);
64598
+ const layoutXmlObj = await this.resolveCachedLayoutXml(layoutPath);
64599
+ if (layoutXmlObj) {
64519
64600
  const layoutBg = this.extractBackgroundColor(layoutXmlObj, "p:sldLayout");
64520
64601
  if (layoutBg) {
64521
64602
  return layoutBg;
@@ -64542,9 +64623,8 @@ var PptxHandlerRuntime70 = class extends PptxHandlerRuntime69 {
64542
64623
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
64543
64624
  const masterPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${stripParentDirSegments(target)}`;
64544
64625
  try {
64545
- const masterXmlStr = await this.zip.file(masterPath)?.async("string");
64546
- if (masterXmlStr) {
64547
- const masterXmlObj = this.parser.parse(masterXmlStr);
64626
+ const masterXmlObj = await this.resolveCachedMasterXml(masterPath);
64627
+ if (masterXmlObj) {
64548
64628
  return this.extractBackgroundColor(masterXmlObj, "p:sldMaster");
64549
64629
  }
64550
64630
  } catch {
@@ -64571,9 +64651,8 @@ var PptxHandlerRuntime71 = class extends PptxHandlerRuntime70 {
64571
64651
  const slideDir = slidePath.substring(0, slidePath.lastIndexOf("/") + 1);
64572
64652
  const layoutPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${stripParentDirSegments(target)}`;
64573
64653
  try {
64574
- const layoutXmlStr = await this.zip.file(layoutPath)?.async("string");
64575
- if (layoutXmlStr) {
64576
- const layoutXmlObj = this.parser.parse(layoutXmlStr);
64654
+ const layoutXmlObj = await this.resolveCachedLayoutXml(layoutPath);
64655
+ if (layoutXmlObj) {
64577
64656
  const layoutGrad = this.extractBackgroundGradient(layoutXmlObj, "p:sldLayout");
64578
64657
  if (layoutGrad) {
64579
64658
  return layoutGrad;
@@ -64600,9 +64679,8 @@ var PptxHandlerRuntime71 = class extends PptxHandlerRuntime70 {
64600
64679
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
64601
64680
  const masterPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${stripParentDirSegments(target)}`;
64602
64681
  try {
64603
- const masterXmlStr = await this.zip.file(masterPath)?.async("string");
64604
- if (masterXmlStr) {
64605
- const masterXmlObj = this.parser.parse(masterXmlStr);
64682
+ const masterXmlObj = await this.resolveCachedMasterXml(masterPath);
64683
+ if (masterXmlObj) {
64606
64684
  return this.extractBackgroundGradient(masterXmlObj, "p:sldMaster");
64607
64685
  }
64608
64686
  } catch {
@@ -64917,11 +64995,24 @@ var PptxHandlerRuntime72 = class _PptxHandlerRuntime extends PptxHandlerRuntime7
64917
64995
  }
64918
64996
  }
64919
64997
  }
64920
- const spcBef = this.parseParagraphSpacingPx(levelProps["a:spcBef"]);
64998
+ const defRPrSzRaw = Number.parseInt(
64999
+ String(
65000
+ levelProps["a:defRPr"]?.["@_sz"] || ""
65001
+ ),
65002
+ 10
65003
+ );
65004
+ const basisFontSizePx = Number.isFinite(defRPrSzRaw) ? this.pointsToPixels(defRPrSzRaw / 100) : void 0;
65005
+ const spcBef = this.parseParagraphSpacingPx(
65006
+ levelProps["a:spcBef"],
65007
+ basisFontSizePx
65008
+ );
64921
65009
  if (spcBef !== void 0) {
64922
65010
  style.spaceBefore = spcBef;
64923
65011
  }
64924
- const spcAft = this.parseParagraphSpacingPx(levelProps["a:spcAft"]);
65012
+ const spcAft = this.parseParagraphSpacingPx(
65013
+ levelProps["a:spcAft"],
65014
+ basisFontSizePx
65015
+ );
64925
65016
  if (spcAft !== void 0) {
64926
65017
  style.spaceAfter = spcAft;
64927
65018
  }
package/dist/index.mjs CHANGED
@@ -492,14 +492,52 @@ function extractSourceOrders(xml) {
492
492
  }
493
493
  return orders;
494
494
  }
495
+ function ensureArrayLocal(value) {
496
+ return Array.isArray(value) ? value : value === void 0 ? [] : [value];
497
+ }
498
+ function countsSignature(counts) {
499
+ return [...counts.entries()].sort((a, b) => a[0] < b[0] ? -1 : 1).map(([name, count]) => `${name}:${count}`).join(",");
500
+ }
501
+ function pathSignature(path) {
502
+ const counts = /* @__PURE__ */ new Map();
503
+ for (const key of Object.keys(path)) {
504
+ const name = localName(key);
505
+ if (!PATH_COMMANDS.has(name)) {
506
+ continue;
507
+ }
508
+ counts.set(name, (counts.get(name) ?? 0) + ensureArrayLocal(path[key]).length);
509
+ }
510
+ return countsSignature(counts);
511
+ }
512
+ function orderSignature(order) {
513
+ const counts = /* @__PURE__ */ new Map();
514
+ for (const name of order) {
515
+ counts.set(name, (counts.get(name) ?? 0) + 1);
516
+ }
517
+ return countsSignature(counts);
518
+ }
495
519
  function annotateCustomGeometryCommandOrder(xml, parsed) {
496
520
  const orders = extractSourceOrders(xml);
497
521
  if (orders.length === 0) {
498
522
  return;
499
523
  }
500
524
  const paths = collectParsedPaths(parsed);
501
- for (let index = 0; index < Math.min(paths.length, orders.length); index++) {
502
- commandOrder.set(paths[index], orders[index]);
525
+ const ordersBySignature = /* @__PURE__ */ new Map();
526
+ for (const order of orders) {
527
+ const signature = orderSignature(order);
528
+ const bucket = ordersBySignature.get(signature);
529
+ if (bucket) {
530
+ bucket.push(order);
531
+ } else {
532
+ ordersBySignature.set(signature, [order]);
533
+ }
534
+ }
535
+ for (const path of paths) {
536
+ const bucket = ordersBySignature.get(pathSignature(path));
537
+ const order = bucket?.shift();
538
+ if (order) {
539
+ commandOrder.set(path, order);
540
+ }
503
541
  }
504
542
  }
505
543
  function orderedPathCommandEntries(path, ensureArray16) {
@@ -23130,15 +23168,15 @@ function getConnectorPathGeometry(element) {
23130
23168
  // src/core/geometry/transform-utils.ts
23131
23169
  function getElementTransform(element) {
23132
23170
  const transforms = [];
23171
+ if (element.rotation) {
23172
+ transforms.push(`rotate(${element.rotation}deg)`);
23173
+ }
23133
23174
  if (element.flipHorizontal) {
23134
23175
  transforms.push("scaleX(-1)");
23135
23176
  }
23136
23177
  if (element.flipVertical) {
23137
23178
  transforms.push("scaleY(-1)");
23138
23179
  }
23139
- if (element.rotation) {
23140
- transforms.push(`rotate(${element.rotation}deg)`);
23141
- }
23142
23180
  return transforms.length > 0 ? transforms.join(" ") : void 0;
23143
23181
  }
23144
23182
  function getTextCompensationTransform(element) {
@@ -61732,7 +61770,7 @@ var PptxHandlerRuntime59 = class extends PptxHandlerRuntime58 {
61732
61770
  pointsToPixels(points3) {
61733
61771
  return points3 * (96 / 72);
61734
61772
  }
61735
- parseParagraphSpacingPx(spacingNode) {
61773
+ parseParagraphSpacingPx(spacingNode, basisFontSizePx) {
61736
61774
  if (!spacingNode) {
61737
61775
  return void 0;
61738
61776
  }
@@ -61743,6 +61781,13 @@ var PptxHandlerRuntime59 = class extends PptxHandlerRuntime58 {
61743
61781
  if (Number.isFinite(spacingPointsRaw)) {
61744
61782
  return this.pointsToPixels(spacingPointsRaw / 100);
61745
61783
  }
61784
+ const spacingPercentRaw = Number.parseInt(
61785
+ String(spacingNode["a:spcPct"]?.["@_val"] || ""),
61786
+ 10
61787
+ );
61788
+ if (Number.isFinite(spacingPercentRaw) && typeof basisFontSizePx === "number" && basisFontSizePx > 0) {
61789
+ return spacingPercentRaw / 1e5 * basisFontSizePx;
61790
+ }
61746
61791
  return void 0;
61747
61792
  }
61748
61793
  parseLineSpacingMultiplier(lineSpacingNode) {
@@ -61822,7 +61867,7 @@ var PptxHandlerRuntime59 = class extends PptxHandlerRuntime58 {
61822
61867
 
61823
61868
  // src/core/core/runtime/PptxHandlerRuntimeBulletParsing.ts
61824
61869
  var PptxHandlerRuntime60 = class extends PptxHandlerRuntime59 {
61825
- resolveParagraphBulletInfo(paragraph, paragraphIndex, txBody, inheritedTxBody, isBodyPlaceholder = false, slidePath) {
61870
+ resolveParagraphBulletInfo(paragraph, paragraphIndex, txBody, inheritedTxBody, isBodyPlaceholder = false, slidePath, effectiveLevelStyles) {
61826
61871
  if (!paragraph) {
61827
61872
  return null;
61828
61873
  }
@@ -61858,11 +61903,8 @@ var PptxHandlerRuntime60 = class extends PptxHandlerRuntime59 {
61858
61903
  }
61859
61904
  }
61860
61905
  if (!resolvedBulletProps) {
61861
- if (isBodyPlaceholder) {
61862
- const presentationLevelStyle = this.presentationDefaultTextStyle?.levelStyles?.[normalizedLevel - 1] ?? this.presentationDefaultTextStyle?.levelStyles?.[-1];
61863
- return this.createBulletInfoFromLevelStyle(presentationLevelStyle, paragraphIndex);
61864
- }
61865
- return null;
61906
+ const fallbackLevelStyle = effectiveLevelStyles?.[normalizedLevel - 1] ?? effectiveLevelStyles?.[-1] ?? (isBodyPlaceholder ? this.presentationDefaultTextStyle?.levelStyles?.[normalizedLevel - 1] ?? this.presentationDefaultTextStyle?.levelStyles?.[-1] : void 0);
61907
+ return this.createBulletInfoFromLevelStyle(fallbackLevelStyle, paragraphIndex);
61866
61908
  }
61867
61909
  const buFont = resolvedBulletProps["a:buFont"];
61868
61910
  const fontFamily = buFont?.["@_typeface"] ? String(buFont["@_typeface"]) : void 0;
@@ -62352,16 +62394,21 @@ var PptxHandlerRuntime62 = class _PptxHandlerRuntime extends PptxHandlerRuntime6
62352
62394
  textStyle.align = paraAlign;
62353
62395
  }
62354
62396
  }
62397
+ const spacingBasisPx = typeof textStyle.fontSize === "number" ? textStyle.fontSize : void 0;
62355
62398
  if (textStyle.paragraphSpacingBefore === void 0) {
62356
62399
  const spacingBefore = this.parseParagraphSpacingPx(
62357
- pPr?.["a:spcBef"]
62400
+ pPr?.["a:spcBef"],
62401
+ spacingBasisPx
62358
62402
  );
62359
62403
  if (spacingBefore !== void 0) {
62360
62404
  textStyle.paragraphSpacingBefore = spacingBefore;
62361
62405
  }
62362
62406
  }
62363
62407
  if (textStyle.paragraphSpacingAfter === void 0) {
62364
- const spacingAfter = this.parseParagraphSpacingPx(pPr?.["a:spcAft"]);
62408
+ const spacingAfter = this.parseParagraphSpacingPx(
62409
+ pPr?.["a:spcAft"],
62410
+ spacingBasisPx
62411
+ );
62365
62412
  if (spacingAfter !== void 0) {
62366
62413
  textStyle.paragraphSpacingAfter = spacingAfter;
62367
62414
  }
@@ -62535,7 +62582,8 @@ var PptxHandlerRuntime63 = class extends PptxHandlerRuntime62 {
62535
62582
  ctx.txBody,
62536
62583
  ctx.inheritedTxBody,
62537
62584
  isBodyPlaceholder,
62538
- ctx.slidePath
62585
+ ctx.slidePath,
62586
+ ctx.effectiveLevelStyles
62539
62587
  );
62540
62588
  if (paragraphBulletInfo && !paragraphBulletInfo.none) {
62541
62589
  let bulletText;
@@ -64138,6 +64186,7 @@ var PptxHandlerRuntime69 = class extends PptxHandlerRuntime68 {
64138
64186
  if (!normalized) {
64139
64187
  return void 0;
64140
64188
  }
64189
+ const canon = (key) => key.toLowerCase() === "folhlink" ? "folHlink" : key;
64141
64190
  if (normalized === "phclr") {
64142
64191
  const injected = this.themeColorMap["phclr"];
64143
64192
  if (injected) {
@@ -64147,17 +64196,18 @@ var PptxHandlerRuntime69 = class extends PptxHandlerRuntime68 {
64147
64196
  }
64148
64197
  const overrideMap = this.currentSlideClrMapOverride ?? this.currentMasterClrMap;
64149
64198
  if (overrideMap) {
64150
- const remapped = overrideMap[normalized];
64199
+ const remapped = overrideMap[canon(normalized)];
64151
64200
  if (remapped) {
64152
- return this.themeColorMap[remapped] || this.getDefaultSchemeColorMap()[remapped];
64201
+ const target = canon(remapped);
64202
+ return this.themeColorMap[target] || this.getDefaultSchemeColorMap()[target];
64153
64203
  }
64154
64204
  } else {
64155
64205
  const defaultAliasTarget = DEFAULT_CLR_MAP_ALIAS[normalized];
64156
64206
  if (defaultAliasTarget) {
64157
- return this.themeColorMap[defaultAliasTarget] || this.themeColorMap[normalized] || this.getDefaultSchemeColorMap()[normalized];
64207
+ return this.themeColorMap[defaultAliasTarget] || this.themeColorMap[canon(normalized)] || this.getDefaultSchemeColorMap()[canon(normalized)];
64158
64208
  }
64159
64209
  }
64160
- return this.themeColorMap[normalized] || this.getDefaultSchemeColorMap()[normalized];
64210
+ return this.themeColorMap[canon(normalized)] || this.getDefaultSchemeColorMap()[canon(normalized)];
64161
64211
  }
64162
64212
  normalizeStrokeDashType(value) {
64163
64213
  const normalized = String(value ?? "").trim();
@@ -64446,6 +64496,40 @@ var PptxHandlerRuntime70 = class extends PptxHandlerRuntime69 {
64446
64496
  }
64447
64497
  return void 0;
64448
64498
  }
64499
+ /**
64500
+ * Reuse the cached parse of a layout XML part, parsing (and caching) on a
64501
+ * miss. Background resolution runs per slide but the layout/master parts are
64502
+ * large (a themed master can be ~200 KB); re-parsing them for every slide
64503
+ * dominated load time, so share the same parsed object `getLayoutElements`
64504
+ * already populated.
64505
+ */
64506
+ async resolveCachedLayoutXml(layoutPath) {
64507
+ const cached = this.layoutXmlMap.get(layoutPath);
64508
+ if (cached) {
64509
+ return cached;
64510
+ }
64511
+ const xml = await this.zip.file(layoutPath)?.async("string");
64512
+ if (!xml) {
64513
+ return void 0;
64514
+ }
64515
+ const parsed = this.parser.parse(xml);
64516
+ this.layoutXmlMap.set(layoutPath, parsed);
64517
+ return parsed;
64518
+ }
64519
+ /** Reuse the cached parse of a master XML part, parsing (and caching) on a miss. */
64520
+ async resolveCachedMasterXml(masterPath) {
64521
+ const cached = this.masterXmlMap.get(masterPath);
64522
+ if (cached) {
64523
+ return cached;
64524
+ }
64525
+ const xml = await this.zip.file(masterPath)?.async("string");
64526
+ if (!xml) {
64527
+ return void 0;
64528
+ }
64529
+ const parsed = this.parser.parse(xml);
64530
+ this.masterXmlMap.set(masterPath, parsed);
64531
+ return parsed;
64532
+ }
64449
64533
  async getMasterBackgroundImage(layoutPath) {
64450
64534
  const layoutRels = this.slideRelsMap.get(layoutPath);
64451
64535
  if (!layoutRels) {
@@ -64456,9 +64540,8 @@ var PptxHandlerRuntime70 = class extends PptxHandlerRuntime69 {
64456
64540
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
64457
64541
  const masterPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${stripParentDirSegments(target)}`;
64458
64542
  try {
64459
- const masterXmlStr = await this.zip.file(masterPath)?.async("string");
64460
- if (masterXmlStr) {
64461
- const masterXmlObj = this.parser.parse(masterXmlStr);
64543
+ const masterXmlObj = await this.resolveCachedMasterXml(masterPath);
64544
+ if (masterXmlObj) {
64462
64545
  const masterRelsPath = `${masterPath.replace("slideMasters/", "slideMasters/_rels/")}.rels`;
64463
64546
  await this.loadSlideRelationships(masterPath, masterRelsPath);
64464
64547
  return this.extractBackgroundImage(masterXmlObj, masterPath, "p:sldMaster");
@@ -64480,9 +64563,8 @@ var PptxHandlerRuntime70 = class extends PptxHandlerRuntime69 {
64480
64563
  const slideDir = slidePath.substring(0, slidePath.lastIndexOf("/") + 1);
64481
64564
  const layoutPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${stripParentDirSegments(target)}`;
64482
64565
  try {
64483
- const layoutXmlStr = await this.zip.file(layoutPath)?.async("string");
64484
- if (layoutXmlStr) {
64485
- const layoutXmlObj = this.parser.parse(layoutXmlStr);
64566
+ const layoutXmlObj = await this.resolveCachedLayoutXml(layoutPath);
64567
+ if (layoutXmlObj) {
64486
64568
  const layoutRelsPath = `${layoutPath.replace("slideLayouts/", "slideLayouts/_rels/")}.rels`;
64487
64569
  await this.loadSlideRelationships(layoutPath, layoutRelsPath);
64488
64570
  const bg = this.extractBackgroundImage(layoutXmlObj, layoutPath, "p:sldLayout");
@@ -64508,9 +64590,8 @@ var PptxHandlerRuntime70 = class extends PptxHandlerRuntime69 {
64508
64590
  const slideDir = slidePath.substring(0, slidePath.lastIndexOf("/") + 1);
64509
64591
  const layoutPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${stripParentDirSegments(target)}`;
64510
64592
  try {
64511
- const layoutXmlStr = await this.zip.file(layoutPath)?.async("string");
64512
- if (layoutXmlStr) {
64513
- const layoutXmlObj = this.parser.parse(layoutXmlStr);
64593
+ const layoutXmlObj = await this.resolveCachedLayoutXml(layoutPath);
64594
+ if (layoutXmlObj) {
64514
64595
  const layoutBg = this.extractBackgroundColor(layoutXmlObj, "p:sldLayout");
64515
64596
  if (layoutBg) {
64516
64597
  return layoutBg;
@@ -64537,9 +64618,8 @@ var PptxHandlerRuntime70 = class extends PptxHandlerRuntime69 {
64537
64618
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
64538
64619
  const masterPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${stripParentDirSegments(target)}`;
64539
64620
  try {
64540
- const masterXmlStr = await this.zip.file(masterPath)?.async("string");
64541
- if (masterXmlStr) {
64542
- const masterXmlObj = this.parser.parse(masterXmlStr);
64621
+ const masterXmlObj = await this.resolveCachedMasterXml(masterPath);
64622
+ if (masterXmlObj) {
64543
64623
  return this.extractBackgroundColor(masterXmlObj, "p:sldMaster");
64544
64624
  }
64545
64625
  } catch {
@@ -64566,9 +64646,8 @@ var PptxHandlerRuntime71 = class extends PptxHandlerRuntime70 {
64566
64646
  const slideDir = slidePath.substring(0, slidePath.lastIndexOf("/") + 1);
64567
64647
  const layoutPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(slideDir, target) : `ppt/${stripParentDirSegments(target)}`;
64568
64648
  try {
64569
- const layoutXmlStr = await this.zip.file(layoutPath)?.async("string");
64570
- if (layoutXmlStr) {
64571
- const layoutXmlObj = this.parser.parse(layoutXmlStr);
64649
+ const layoutXmlObj = await this.resolveCachedLayoutXml(layoutPath);
64650
+ if (layoutXmlObj) {
64572
64651
  const layoutGrad = this.extractBackgroundGradient(layoutXmlObj, "p:sldLayout");
64573
64652
  if (layoutGrad) {
64574
64653
  return layoutGrad;
@@ -64595,9 +64674,8 @@ var PptxHandlerRuntime71 = class extends PptxHandlerRuntime70 {
64595
64674
  const layoutDir = layoutPath.substring(0, layoutPath.lastIndexOf("/") + 1);
64596
64675
  const masterPath = target.startsWith("/") ? target.substring(1) : target.startsWith("..") ? this.resolvePath(layoutDir, target) : `ppt/${stripParentDirSegments(target)}`;
64597
64676
  try {
64598
- const masterXmlStr = await this.zip.file(masterPath)?.async("string");
64599
- if (masterXmlStr) {
64600
- const masterXmlObj = this.parser.parse(masterXmlStr);
64677
+ const masterXmlObj = await this.resolveCachedMasterXml(masterPath);
64678
+ if (masterXmlObj) {
64601
64679
  return this.extractBackgroundGradient(masterXmlObj, "p:sldMaster");
64602
64680
  }
64603
64681
  } catch {
@@ -64912,11 +64990,24 @@ var PptxHandlerRuntime72 = class _PptxHandlerRuntime extends PptxHandlerRuntime7
64912
64990
  }
64913
64991
  }
64914
64992
  }
64915
- const spcBef = this.parseParagraphSpacingPx(levelProps["a:spcBef"]);
64993
+ const defRPrSzRaw = Number.parseInt(
64994
+ String(
64995
+ levelProps["a:defRPr"]?.["@_sz"] || ""
64996
+ ),
64997
+ 10
64998
+ );
64999
+ const basisFontSizePx = Number.isFinite(defRPrSzRaw) ? this.pointsToPixels(defRPrSzRaw / 100) : void 0;
65000
+ const spcBef = this.parseParagraphSpacingPx(
65001
+ levelProps["a:spcBef"],
65002
+ basisFontSizePx
65003
+ );
64916
65004
  if (spcBef !== void 0) {
64917
65005
  style.spaceBefore = spcBef;
64918
65006
  }
64919
- const spcAft = this.parseParagraphSpacingPx(levelProps["a:spcAft"]);
65007
+ const spcAft = this.parseParagraphSpacingPx(
65008
+ levelProps["a:spcAft"],
65009
+ basisFontSizePx
65010
+ );
64920
65011
  if (spcAft !== void 0) {
64921
65012
  style.spaceAfter = spcAft;
64922
65013
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pptx-viewer-core",
3
- "version": "1.6.6",
3
+ "version": "1.6.8",
4
4
  "description": "PowerPoint PPTX engine: parse, edit, serialize, and convert .pptx files. Framework-agnostic TypeScript SDK.",
5
5
  "keywords": [
6
6
  "angular",