pptx-glimpse 0.10.1 → 0.10.2

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 CHANGED
@@ -3911,6 +3911,114 @@ function findMatchingPlaceholder(placeholderType, placeholderIdx, styles) {
3911
3911
  }
3912
3912
  return void 0;
3913
3913
  }
3914
+ function hasMultipleBulletPPr(p, orderedChildren) {
3915
+ const rawPPr = p.pPr;
3916
+ const pPrList = Array.isArray(rawPPr) ? rawPPr : rawPPr ? [rawPPr] : [];
3917
+ let bulletPPrCount = 0;
3918
+ let pPrCounter = 0;
3919
+ for (const child of orderedChildren) {
3920
+ const tag = Object.keys(child).find((k) => k !== ":@");
3921
+ if (tag === "pPr") {
3922
+ const pPrNode = pPrList[pPrCounter];
3923
+ if (pPrNode && (pPrNode.buChar !== void 0 || pPrNode.buAutoNum !== void 0 || pPrNode.buBlip !== void 0)) {
3924
+ bulletPPrCount++;
3925
+ if (bulletPPrCount >= 2) return true;
3926
+ }
3927
+ pPrCounter++;
3928
+ }
3929
+ }
3930
+ return false;
3931
+ }
3932
+ function splitInterleavedParagraph(p, orderedPChildren, colorResolver, rels, fontScheme, lstStyle) {
3933
+ const rawPPr = p.pPr;
3934
+ const pPrList = Array.isArray(rawPPr) ? rawPPr : rawPPr ? [rawPPr] : [];
3935
+ const rList = p.r ?? [];
3936
+ const fldList = p.fld ?? [];
3937
+ const brList = p.br ?? [];
3938
+ const groups = [];
3939
+ let currentGroup = null;
3940
+ let pPrCounter = 0;
3941
+ const tagCounters = {};
3942
+ for (const child of orderedPChildren) {
3943
+ const tag = Object.keys(child).find((k) => k !== ":@");
3944
+ if (!tag) continue;
3945
+ if (tag === "pPr") {
3946
+ const pPrNode = pPrList[pPrCounter];
3947
+ const hasBullet = pPrNode && (pPrNode.buChar !== void 0 || pPrNode.buAutoNum !== void 0 || pPrNode.buBlip !== void 0);
3948
+ if (hasBullet || !currentGroup) {
3949
+ if (currentGroup) groups.push(currentGroup);
3950
+ currentGroup = {
3951
+ pPrIdx: pPrCounter,
3952
+ rIndices: [],
3953
+ fldIndices: [],
3954
+ brIndices: [],
3955
+ orderedChildren: [child]
3956
+ };
3957
+ } else {
3958
+ currentGroup.orderedChildren.push(child);
3959
+ }
3960
+ pPrCounter++;
3961
+ } else if (tag === "endParaRPr") {
3962
+ } else {
3963
+ const globalIdx = tagCounters[tag] ?? 0;
3964
+ tagCounters[tag] = globalIdx + 1;
3965
+ if (!currentGroup) {
3966
+ currentGroup = {
3967
+ pPrIdx: -1,
3968
+ rIndices: [],
3969
+ fldIndices: [],
3970
+ brIndices: [],
3971
+ orderedChildren: []
3972
+ };
3973
+ }
3974
+ if (tag === "r") currentGroup.rIndices.push(globalIdx);
3975
+ else if (tag === "fld") currentGroup.fldIndices.push(globalIdx);
3976
+ else if (tag === "br") currentGroup.brIndices.push(globalIdx);
3977
+ currentGroup.orderedChildren.push(child);
3978
+ }
3979
+ }
3980
+ if (currentGroup) groups.push(currentGroup);
3981
+ const results = [];
3982
+ for (let g = 0; g < groups.length; g++) {
3983
+ const group = groups[g];
3984
+ const isLast = g === groups.length - 1;
3985
+ const syntheticP = {};
3986
+ if (group.pPrIdx >= 0 && pPrList[group.pPrIdx]) {
3987
+ syntheticP.pPr = pPrList[group.pPrIdx];
3988
+ }
3989
+ if (group.rIndices.length > 0) {
3990
+ syntheticP.r = group.rIndices.map((i) => rList[i]);
3991
+ }
3992
+ if (group.fldIndices.length > 0) {
3993
+ syntheticP.fld = group.fldIndices.map((i) => fldList[i]);
3994
+ }
3995
+ if (group.brIndices.length > 0) {
3996
+ syntheticP.br = group.brIndices.map((i) => brList[i]);
3997
+ }
3998
+ if (isLast && p.endParaRPr) {
3999
+ syntheticP.endParaRPr = p.endParaRPr;
4000
+ }
4001
+ const paragraph = parseParagraph(
4002
+ syntheticP,
4003
+ colorResolver,
4004
+ rels,
4005
+ fontScheme,
4006
+ lstStyle,
4007
+ group.orderedChildren
4008
+ );
4009
+ if (!isLast && paragraph.runs.length > 0) {
4010
+ const lastRun = paragraph.runs[paragraph.runs.length - 1];
4011
+ if (lastRun.text.endsWith("\n")) {
4012
+ paragraph.runs[paragraph.runs.length - 1] = {
4013
+ ...lastRun,
4014
+ text: lastRun.text.slice(0, -1)
4015
+ };
4016
+ }
4017
+ }
4018
+ results.push(paragraph);
4019
+ }
4020
+ return results;
4021
+ }
3914
4022
  function parseTextBody(txBody, colorResolver, rels, fontScheme, lstStyleOverride, orderedTxBody) {
3915
4023
  if (!txBody) return null;
3916
4024
  const bodyPr = txBody.bodyPr;
@@ -3955,9 +4063,23 @@ function parseTextBody(txBody, colorResolver, rels, fontScheme, lstStyleOverride
3955
4063
  const paragraphs = [];
3956
4064
  const pList = txBody.p ?? [];
3957
4065
  for (let i = 0; i < pList.length; i++) {
3958
- paragraphs.push(
3959
- parseParagraph(pList[i], colorResolver, rels, fontScheme, lstStyle, orderedParagraphs[i])
3960
- );
4066
+ const orderedChildren = orderedParagraphs[i];
4067
+ if (orderedChildren && hasMultipleBulletPPr(pList[i], orderedChildren)) {
4068
+ paragraphs.push(
4069
+ ...splitInterleavedParagraph(
4070
+ pList[i],
4071
+ orderedChildren,
4072
+ colorResolver,
4073
+ rels,
4074
+ fontScheme,
4075
+ lstStyle
4076
+ )
4077
+ );
4078
+ } else {
4079
+ paragraphs.push(
4080
+ parseParagraph(pList[i], colorResolver, rels, fontScheme, lstStyle, orderedChildren)
4081
+ );
4082
+ }
3961
4083
  }
3962
4084
  if (paragraphs.length === 0) return null;
3963
4085
  return { paragraphs, bodyProperties };
package/dist/index.js CHANGED
@@ -3873,6 +3873,114 @@ function findMatchingPlaceholder(placeholderType, placeholderIdx, styles) {
3873
3873
  }
3874
3874
  return void 0;
3875
3875
  }
3876
+ function hasMultipleBulletPPr(p, orderedChildren) {
3877
+ const rawPPr = p.pPr;
3878
+ const pPrList = Array.isArray(rawPPr) ? rawPPr : rawPPr ? [rawPPr] : [];
3879
+ let bulletPPrCount = 0;
3880
+ let pPrCounter = 0;
3881
+ for (const child of orderedChildren) {
3882
+ const tag = Object.keys(child).find((k) => k !== ":@");
3883
+ if (tag === "pPr") {
3884
+ const pPrNode = pPrList[pPrCounter];
3885
+ if (pPrNode && (pPrNode.buChar !== void 0 || pPrNode.buAutoNum !== void 0 || pPrNode.buBlip !== void 0)) {
3886
+ bulletPPrCount++;
3887
+ if (bulletPPrCount >= 2) return true;
3888
+ }
3889
+ pPrCounter++;
3890
+ }
3891
+ }
3892
+ return false;
3893
+ }
3894
+ function splitInterleavedParagraph(p, orderedPChildren, colorResolver, rels, fontScheme, lstStyle) {
3895
+ const rawPPr = p.pPr;
3896
+ const pPrList = Array.isArray(rawPPr) ? rawPPr : rawPPr ? [rawPPr] : [];
3897
+ const rList = p.r ?? [];
3898
+ const fldList = p.fld ?? [];
3899
+ const brList = p.br ?? [];
3900
+ const groups = [];
3901
+ let currentGroup = null;
3902
+ let pPrCounter = 0;
3903
+ const tagCounters = {};
3904
+ for (const child of orderedPChildren) {
3905
+ const tag = Object.keys(child).find((k) => k !== ":@");
3906
+ if (!tag) continue;
3907
+ if (tag === "pPr") {
3908
+ const pPrNode = pPrList[pPrCounter];
3909
+ const hasBullet = pPrNode && (pPrNode.buChar !== void 0 || pPrNode.buAutoNum !== void 0 || pPrNode.buBlip !== void 0);
3910
+ if (hasBullet || !currentGroup) {
3911
+ if (currentGroup) groups.push(currentGroup);
3912
+ currentGroup = {
3913
+ pPrIdx: pPrCounter,
3914
+ rIndices: [],
3915
+ fldIndices: [],
3916
+ brIndices: [],
3917
+ orderedChildren: [child]
3918
+ };
3919
+ } else {
3920
+ currentGroup.orderedChildren.push(child);
3921
+ }
3922
+ pPrCounter++;
3923
+ } else if (tag === "endParaRPr") {
3924
+ } else {
3925
+ const globalIdx = tagCounters[tag] ?? 0;
3926
+ tagCounters[tag] = globalIdx + 1;
3927
+ if (!currentGroup) {
3928
+ currentGroup = {
3929
+ pPrIdx: -1,
3930
+ rIndices: [],
3931
+ fldIndices: [],
3932
+ brIndices: [],
3933
+ orderedChildren: []
3934
+ };
3935
+ }
3936
+ if (tag === "r") currentGroup.rIndices.push(globalIdx);
3937
+ else if (tag === "fld") currentGroup.fldIndices.push(globalIdx);
3938
+ else if (tag === "br") currentGroup.brIndices.push(globalIdx);
3939
+ currentGroup.orderedChildren.push(child);
3940
+ }
3941
+ }
3942
+ if (currentGroup) groups.push(currentGroup);
3943
+ const results = [];
3944
+ for (let g = 0; g < groups.length; g++) {
3945
+ const group = groups[g];
3946
+ const isLast = g === groups.length - 1;
3947
+ const syntheticP = {};
3948
+ if (group.pPrIdx >= 0 && pPrList[group.pPrIdx]) {
3949
+ syntheticP.pPr = pPrList[group.pPrIdx];
3950
+ }
3951
+ if (group.rIndices.length > 0) {
3952
+ syntheticP.r = group.rIndices.map((i) => rList[i]);
3953
+ }
3954
+ if (group.fldIndices.length > 0) {
3955
+ syntheticP.fld = group.fldIndices.map((i) => fldList[i]);
3956
+ }
3957
+ if (group.brIndices.length > 0) {
3958
+ syntheticP.br = group.brIndices.map((i) => brList[i]);
3959
+ }
3960
+ if (isLast && p.endParaRPr) {
3961
+ syntheticP.endParaRPr = p.endParaRPr;
3962
+ }
3963
+ const paragraph = parseParagraph(
3964
+ syntheticP,
3965
+ colorResolver,
3966
+ rels,
3967
+ fontScheme,
3968
+ lstStyle,
3969
+ group.orderedChildren
3970
+ );
3971
+ if (!isLast && paragraph.runs.length > 0) {
3972
+ const lastRun = paragraph.runs[paragraph.runs.length - 1];
3973
+ if (lastRun.text.endsWith("\n")) {
3974
+ paragraph.runs[paragraph.runs.length - 1] = {
3975
+ ...lastRun,
3976
+ text: lastRun.text.slice(0, -1)
3977
+ };
3978
+ }
3979
+ }
3980
+ results.push(paragraph);
3981
+ }
3982
+ return results;
3983
+ }
3876
3984
  function parseTextBody(txBody, colorResolver, rels, fontScheme, lstStyleOverride, orderedTxBody) {
3877
3985
  if (!txBody) return null;
3878
3986
  const bodyPr = txBody.bodyPr;
@@ -3917,9 +4025,23 @@ function parseTextBody(txBody, colorResolver, rels, fontScheme, lstStyleOverride
3917
4025
  const paragraphs = [];
3918
4026
  const pList = txBody.p ?? [];
3919
4027
  for (let i = 0; i < pList.length; i++) {
3920
- paragraphs.push(
3921
- parseParagraph(pList[i], colorResolver, rels, fontScheme, lstStyle, orderedParagraphs[i])
3922
- );
4028
+ const orderedChildren = orderedParagraphs[i];
4029
+ if (orderedChildren && hasMultipleBulletPPr(pList[i], orderedChildren)) {
4030
+ paragraphs.push(
4031
+ ...splitInterleavedParagraph(
4032
+ pList[i],
4033
+ orderedChildren,
4034
+ colorResolver,
4035
+ rels,
4036
+ fontScheme,
4037
+ lstStyle
4038
+ )
4039
+ );
4040
+ } else {
4041
+ paragraphs.push(
4042
+ parseParagraph(pList[i], colorResolver, rels, fontScheme, lstStyle, orderedChildren)
4043
+ );
4044
+ }
3923
4045
  }
3924
4046
  if (paragraphs.length === 0) return null;
3925
4047
  return { paragraphs, bodyProperties };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pptx-glimpse",
3
- "version": "0.10.1",
3
+ "version": "0.10.2",
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",