pptx-glimpse 1.1.0 → 1.1.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 CHANGED
@@ -4399,11 +4399,10 @@ function parseParagraph(p, colorResolver, rels, fontScheme, lstStyle, orderedPCh
4399
4399
  const lstLevelProps = lstStyle?.levels[level];
4400
4400
  const { bullet, bulletFont, bulletColor, bulletSizePct } = parseBullet(pPr, colorResolver);
4401
4401
  const lnSpc = pPr?.lnSpc;
4402
- const lnSpcSpcPct = lnSpc?.spcPct;
4403
4402
  const tabStops = parseTabStops(pPr);
4404
4403
  const properties = {
4405
4404
  alignment: pPr?.["@_algn"] ?? lstLevelProps?.alignment ?? null,
4406
- lineSpacing: lnSpcSpcPct ? Number(lnSpcSpcPct["@_val"]) : null,
4405
+ lineSpacing: lnSpc?.spcPts || lnSpc?.spcPct ? parseSpacing(lnSpc) : null,
4407
4406
  spaceBefore: parseSpacing(pPr?.spcBef),
4408
4407
  spaceAfter: parseSpacing(pPr?.spcAft),
4409
4408
  level,
@@ -8165,7 +8164,11 @@ function renderTextBody(textBody, transform) {
8165
8164
  const paragraphGapPx = Math.max(prevSpaceAfterPx, spaceBeforePx);
8166
8165
  if (para.runs.length === 0 || !para.runs.some((r) => r.text.length > 0)) {
8167
8166
  const emptyParaHeightPt = paraFontSizePt > 0 ? paraFontSizePt : defaultNaturalHeightPt;
8168
- const dy = computeDy(isFirstLine, emptyParaHeightPt, DEFAULT_LINE_SPACING, paragraphGapPx);
8167
+ const dy = computeDy(
8168
+ isFirstLine,
8169
+ getLineHeightPx(para, emptyParaHeightPt, lnSpcReduction),
8170
+ paragraphGapPx
8171
+ );
8169
8172
  tspans.push(`<tspan x="${xPos}" dy="${dy}" text-anchor="${anchorValue}"> </tspan>`);
8170
8173
  isFirstLine = false;
8171
8174
  prevSpaceAfterPx = resolveSpacingPx(para.properties.spaceAfter, paraFontSizePt);
@@ -8184,8 +8187,7 @@ function renderTextBody(textBody, transform) {
8184
8187
  if (line.segments.length === 0) {
8185
8188
  const dy = computeDy(
8186
8189
  isFirstLine,
8187
- defaultNaturalHeightPt,
8188
- getLineSpacing(para, lnSpcReduction),
8190
+ getLineHeightPx(para, defaultNaturalHeightPt, lnSpcReduction),
8189
8191
  lineGapPx
8190
8192
  );
8191
8193
  tspans.push(`<tspan x="${xPos}" dy="${dy}" text-anchor="${anchorValue}"> </tspan>`);
@@ -8201,8 +8203,7 @@ function renderTextBody(textBody, transform) {
8201
8203
  );
8202
8204
  const dy = computeDy(
8203
8205
  isFirstLine,
8204
- lineNaturalHeightPt,
8205
- getLineSpacing(para, lnSpcReduction),
8206
+ getLineHeightPx(para, lineNaturalHeightPt, lnSpcReduction),
8206
8207
  paragraphGapPx
8207
8208
  );
8208
8209
  const firstSeg = line.segments[0];
@@ -8237,8 +8238,7 @@ function renderTextBody(textBody, transform) {
8237
8238
  );
8238
8239
  const dy = computeDy(
8239
8240
  isFirstLine,
8240
- lineNaturalHeightPt,
8241
- getLineSpacing(para, lnSpcReduction),
8241
+ getLineHeightPx(para, lineNaturalHeightPt, lnSpcReduction),
8242
8242
  lineGapPx
8243
8243
  );
8244
8244
  const prefix = `x="${xPos}" dy="${dy}" text-anchor="${anchorValue}" `;
@@ -8258,8 +8258,7 @@ function renderTextBody(textBody, transform) {
8258
8258
  const naturalHeightPt = computeLineNaturalHeight(para.runs, defaultFontSize, fontScale);
8259
8259
  const dy = computeDy(
8260
8260
  isFirstLine,
8261
- naturalHeightPt,
8262
- getLineSpacing(para, lnSpcReduction),
8261
+ getLineHeightPx(para, naturalHeightPt, lnSpcReduction),
8263
8262
  paragraphGapPx
8264
8263
  );
8265
8264
  const bulletFontChain = buildBulletFontChain(
@@ -8289,8 +8288,7 @@ function renderTextBody(textBody, transform) {
8289
8288
  const naturalHeightPt = computeLineNaturalHeight(para.runs, defaultFontSize, fontScale);
8290
8289
  const dy = computeDy(
8291
8290
  isFirstLine,
8292
- naturalHeightPt,
8293
- getLineSpacing(para, lnSpcReduction),
8291
+ getLineHeightPx(para, naturalHeightPt, lnSpcReduction),
8294
8292
  paragraphGapPx
8295
8293
  );
8296
8294
  const prefix = `x="${xPos}" dy="${dy}" text-anchor="${anchorValue}" `;
@@ -8440,15 +8438,13 @@ function getAlignmentInfo(alignment, marginLeftPx, textWidth, width, marginRight
8440
8438
  return { xPos: marginLeftPx, anchorValue: "start" };
8441
8439
  }
8442
8440
  }
8443
- function getLineSpacing(para, lnSpcReduction = 0) {
8444
- let spacing;
8445
- if (para.properties.lineSpacing !== null) {
8446
- const factor = para.properties.lineSpacing / 1e5;
8447
- spacing = Math.max(0.5, factor);
8448
- } else {
8449
- spacing = DEFAULT_LINE_SPACING;
8441
+ function getLineHeightPx(para, naturalHeightPt, lnSpcReduction = 0) {
8442
+ const lineSpacing = para.properties.lineSpacing;
8443
+ if (lineSpacing?.type === "pts") {
8444
+ return lineSpacing.value / 100 * PX_PER_PT3 * (1 - lnSpcReduction);
8450
8445
  }
8451
- return spacing * (1 - lnSpcReduction);
8446
+ const factor = lineSpacing !== null ? Math.max(0.5, lineSpacing.value / 1e5) : DEFAULT_LINE_SPACING;
8447
+ return naturalHeightPt * PX_PER_PT3 * factor * (1 - lnSpcReduction);
8452
8448
  }
8453
8449
  function resolveSpacingPx(spacing, fontSizePt) {
8454
8450
  if (spacing.type === "pts") {
@@ -8467,11 +8463,9 @@ function getParagraphFontSize(para, defaultFontSize) {
8467
8463
  }
8468
8464
  return defaultFontSize;
8469
8465
  }
8470
- function computeDy(isFirstLine, fontSizePt, lineSpacingFactor, paragraphGapPx) {
8466
+ function computeDy(isFirstLine, lineHeightPx, paragraphGapPx) {
8471
8467
  if (isFirstLine) return "0";
8472
- const lineHeight = fontSizePt * PX_PER_PT3 * lineSpacingFactor;
8473
- const dy = lineHeight + paragraphGapPx;
8474
- return dy.toFixed(2);
8468
+ return (lineHeightPx + paragraphGapPx).toFixed(2);
8475
8469
  }
8476
8470
  function getLineFontSize(segments, defaultFontSize) {
8477
8471
  for (const seg of segments) {
@@ -8707,10 +8701,13 @@ function estimateTextHeight(paragraphs, defaultFontSize, shouldWrap, textWidth,
8707
8701
  const scaledDefaultForWrap = defaultFontSize * fontScale;
8708
8702
  for (let pIdx = 0; pIdx < paragraphs.length; pIdx++) {
8709
8703
  const para = paragraphs[pIdx];
8710
- const lineSpacing = getLineSpacing(para, lnSpcReduction);
8711
8704
  const isEmpty = !para.runs.some((r) => r.text.length > 0);
8712
8705
  const naturalHeightPt = isEmpty && para.endParaRunProperties?.fontSize ? para.endParaRunProperties.fontSize * fontScale * defaultRatio : computeLineNaturalHeight(para.runs, defaultFontSize, fontScale);
8713
- const lineHeight = (naturalHeightPt > 0 ? naturalHeightPt : defaultFontSize * fontScale * defaultRatio) * PX_PER_PT3 * lineSpacing;
8706
+ const lineHeight = getLineHeightPx(
8707
+ para,
8708
+ naturalHeightPt > 0 ? naturalHeightPt : defaultFontSize * fontScale * defaultRatio,
8709
+ lnSpcReduction
8710
+ );
8714
8711
  let lineCount;
8715
8712
  if (shouldWrap && para.runs.length > 0 && para.runs.some((r) => r.text.length > 0)) {
8716
8713
  const wrappedLines = wrapParagraph(para, textWidth, scaledDefaultForWrap, fontScale);
@@ -8977,7 +8974,7 @@ function renderTextBodyAsPath(textBody, transform, fontResolver) {
8977
8974
  if (para.runs.length === 0 || !para.runs.some((r) => r.text.length > 0)) {
8978
8975
  if (!isFirstLine) {
8979
8976
  const emptyParaHeightPt = paraFontSizePt > 0 ? paraFontSizePt : defaultNaturalHeightPt;
8980
- currentY += emptyParaHeightPt * PX_PER_PT3 * DEFAULT_LINE_SPACING + paragraphGapPx;
8977
+ currentY += getLineHeightPx(para, emptyParaHeightPt, lnSpcReduction) + paragraphGapPx;
8981
8978
  }
8982
8979
  isFirstLine = false;
8983
8980
  prevSpaceAfterPx = resolveSpacingPx(para.properties.spaceAfter, paraFontSizePt);
@@ -8995,7 +8992,7 @@ function renderTextBodyAsPath(textBody, transform, fontResolver) {
8995
8992
  const lineGapPx = lineIdx === 0 ? paragraphGapPx : 0;
8996
8993
  if (line.segments.length === 0) {
8997
8994
  if (!isFirstLine) {
8998
- currentY += defaultNaturalHeightPt * PX_PER_PT3 * getLineSpacing(para, lnSpcReduction) + lineGapPx;
8995
+ currentY += getLineHeightPx(para, defaultNaturalHeightPt, lnSpcReduction) + lineGapPx;
8999
8996
  }
9000
8997
  isFirstLine = false;
9001
8998
  continue;
@@ -9006,7 +9003,7 @@ function renderTextBodyAsPath(textBody, transform, fontResolver) {
9006
9003
  fontScale
9007
9004
  );
9008
9005
  if (!isFirstLine) {
9009
- currentY += lineNaturalHeightPt * PX_PER_PT3 * getLineSpacing(para, lnSpcReduction) + lineGapPx;
9006
+ currentY += getLineHeightPx(para, lineNaturalHeightPt, lnSpcReduction) + lineGapPx;
9010
9007
  }
9011
9008
  const lineWidth = measureLineWidth(line.segments, defaultFontSize, fontScale, fontResolver);
9012
9009
  const lineStartX = computePathLineX(
@@ -9054,7 +9051,7 @@ function renderTextBodyAsPath(textBody, transform, fontResolver) {
9054
9051
  } else {
9055
9052
  const naturalHeightPt = computeLineNaturalHeight(para.runs, defaultFontSize, fontScale);
9056
9053
  if (!isFirstLine) {
9057
- currentY += naturalHeightPt * PX_PER_PT3 * getLineSpacing(para, lnSpcReduction) + paragraphGapPx;
9054
+ currentY += getLineHeightPx(para, naturalHeightPt, lnSpcReduction) + paragraphGapPx;
9058
9055
  }
9059
9056
  const runsAsSegments = para.runs.filter((r) => r.text.length > 0).map((r) => ({ text: r.text, properties: r.properties }));
9060
9057
  const lineWidth = measureLineWidth(runsAsSegments, defaultFontSize, fontScale, fontResolver);
package/dist/index.js CHANGED
@@ -4361,11 +4361,10 @@ function parseParagraph(p, colorResolver, rels, fontScheme, lstStyle, orderedPCh
4361
4361
  const lstLevelProps = lstStyle?.levels[level];
4362
4362
  const { bullet, bulletFont, bulletColor, bulletSizePct } = parseBullet(pPr, colorResolver);
4363
4363
  const lnSpc = pPr?.lnSpc;
4364
- const lnSpcSpcPct = lnSpc?.spcPct;
4365
4364
  const tabStops = parseTabStops(pPr);
4366
4365
  const properties = {
4367
4366
  alignment: pPr?.["@_algn"] ?? lstLevelProps?.alignment ?? null,
4368
- lineSpacing: lnSpcSpcPct ? Number(lnSpcSpcPct["@_val"]) : null,
4367
+ lineSpacing: lnSpc?.spcPts || lnSpc?.spcPct ? parseSpacing(lnSpc) : null,
4369
4368
  spaceBefore: parseSpacing(pPr?.spcBef),
4370
4369
  spaceAfter: parseSpacing(pPr?.spcAft),
4371
4370
  level,
@@ -8127,7 +8126,11 @@ function renderTextBody(textBody, transform) {
8127
8126
  const paragraphGapPx = Math.max(prevSpaceAfterPx, spaceBeforePx);
8128
8127
  if (para.runs.length === 0 || !para.runs.some((r) => r.text.length > 0)) {
8129
8128
  const emptyParaHeightPt = paraFontSizePt > 0 ? paraFontSizePt : defaultNaturalHeightPt;
8130
- const dy = computeDy(isFirstLine, emptyParaHeightPt, DEFAULT_LINE_SPACING, paragraphGapPx);
8129
+ const dy = computeDy(
8130
+ isFirstLine,
8131
+ getLineHeightPx(para, emptyParaHeightPt, lnSpcReduction),
8132
+ paragraphGapPx
8133
+ );
8131
8134
  tspans.push(`<tspan x="${xPos}" dy="${dy}" text-anchor="${anchorValue}"> </tspan>`);
8132
8135
  isFirstLine = false;
8133
8136
  prevSpaceAfterPx = resolveSpacingPx(para.properties.spaceAfter, paraFontSizePt);
@@ -8146,8 +8149,7 @@ function renderTextBody(textBody, transform) {
8146
8149
  if (line.segments.length === 0) {
8147
8150
  const dy = computeDy(
8148
8151
  isFirstLine,
8149
- defaultNaturalHeightPt,
8150
- getLineSpacing(para, lnSpcReduction),
8152
+ getLineHeightPx(para, defaultNaturalHeightPt, lnSpcReduction),
8151
8153
  lineGapPx
8152
8154
  );
8153
8155
  tspans.push(`<tspan x="${xPos}" dy="${dy}" text-anchor="${anchorValue}"> </tspan>`);
@@ -8163,8 +8165,7 @@ function renderTextBody(textBody, transform) {
8163
8165
  );
8164
8166
  const dy = computeDy(
8165
8167
  isFirstLine,
8166
- lineNaturalHeightPt,
8167
- getLineSpacing(para, lnSpcReduction),
8168
+ getLineHeightPx(para, lineNaturalHeightPt, lnSpcReduction),
8168
8169
  paragraphGapPx
8169
8170
  );
8170
8171
  const firstSeg = line.segments[0];
@@ -8199,8 +8200,7 @@ function renderTextBody(textBody, transform) {
8199
8200
  );
8200
8201
  const dy = computeDy(
8201
8202
  isFirstLine,
8202
- lineNaturalHeightPt,
8203
- getLineSpacing(para, lnSpcReduction),
8203
+ getLineHeightPx(para, lineNaturalHeightPt, lnSpcReduction),
8204
8204
  lineGapPx
8205
8205
  );
8206
8206
  const prefix = `x="${xPos}" dy="${dy}" text-anchor="${anchorValue}" `;
@@ -8220,8 +8220,7 @@ function renderTextBody(textBody, transform) {
8220
8220
  const naturalHeightPt = computeLineNaturalHeight(para.runs, defaultFontSize, fontScale);
8221
8221
  const dy = computeDy(
8222
8222
  isFirstLine,
8223
- naturalHeightPt,
8224
- getLineSpacing(para, lnSpcReduction),
8223
+ getLineHeightPx(para, naturalHeightPt, lnSpcReduction),
8225
8224
  paragraphGapPx
8226
8225
  );
8227
8226
  const bulletFontChain = buildBulletFontChain(
@@ -8251,8 +8250,7 @@ function renderTextBody(textBody, transform) {
8251
8250
  const naturalHeightPt = computeLineNaturalHeight(para.runs, defaultFontSize, fontScale);
8252
8251
  const dy = computeDy(
8253
8252
  isFirstLine,
8254
- naturalHeightPt,
8255
- getLineSpacing(para, lnSpcReduction),
8253
+ getLineHeightPx(para, naturalHeightPt, lnSpcReduction),
8256
8254
  paragraphGapPx
8257
8255
  );
8258
8256
  const prefix = `x="${xPos}" dy="${dy}" text-anchor="${anchorValue}" `;
@@ -8402,15 +8400,13 @@ function getAlignmentInfo(alignment, marginLeftPx, textWidth, width, marginRight
8402
8400
  return { xPos: marginLeftPx, anchorValue: "start" };
8403
8401
  }
8404
8402
  }
8405
- function getLineSpacing(para, lnSpcReduction = 0) {
8406
- let spacing;
8407
- if (para.properties.lineSpacing !== null) {
8408
- const factor = para.properties.lineSpacing / 1e5;
8409
- spacing = Math.max(0.5, factor);
8410
- } else {
8411
- spacing = DEFAULT_LINE_SPACING;
8403
+ function getLineHeightPx(para, naturalHeightPt, lnSpcReduction = 0) {
8404
+ const lineSpacing = para.properties.lineSpacing;
8405
+ if (lineSpacing?.type === "pts") {
8406
+ return lineSpacing.value / 100 * PX_PER_PT3 * (1 - lnSpcReduction);
8412
8407
  }
8413
- return spacing * (1 - lnSpcReduction);
8408
+ const factor = lineSpacing !== null ? Math.max(0.5, lineSpacing.value / 1e5) : DEFAULT_LINE_SPACING;
8409
+ return naturalHeightPt * PX_PER_PT3 * factor * (1 - lnSpcReduction);
8414
8410
  }
8415
8411
  function resolveSpacingPx(spacing, fontSizePt) {
8416
8412
  if (spacing.type === "pts") {
@@ -8429,11 +8425,9 @@ function getParagraphFontSize(para, defaultFontSize) {
8429
8425
  }
8430
8426
  return defaultFontSize;
8431
8427
  }
8432
- function computeDy(isFirstLine, fontSizePt, lineSpacingFactor, paragraphGapPx) {
8428
+ function computeDy(isFirstLine, lineHeightPx, paragraphGapPx) {
8433
8429
  if (isFirstLine) return "0";
8434
- const lineHeight = fontSizePt * PX_PER_PT3 * lineSpacingFactor;
8435
- const dy = lineHeight + paragraphGapPx;
8436
- return dy.toFixed(2);
8430
+ return (lineHeightPx + paragraphGapPx).toFixed(2);
8437
8431
  }
8438
8432
  function getLineFontSize(segments, defaultFontSize) {
8439
8433
  for (const seg of segments) {
@@ -8669,10 +8663,13 @@ function estimateTextHeight(paragraphs, defaultFontSize, shouldWrap, textWidth,
8669
8663
  const scaledDefaultForWrap = defaultFontSize * fontScale;
8670
8664
  for (let pIdx = 0; pIdx < paragraphs.length; pIdx++) {
8671
8665
  const para = paragraphs[pIdx];
8672
- const lineSpacing = getLineSpacing(para, lnSpcReduction);
8673
8666
  const isEmpty = !para.runs.some((r) => r.text.length > 0);
8674
8667
  const naturalHeightPt = isEmpty && para.endParaRunProperties?.fontSize ? para.endParaRunProperties.fontSize * fontScale * defaultRatio : computeLineNaturalHeight(para.runs, defaultFontSize, fontScale);
8675
- const lineHeight = (naturalHeightPt > 0 ? naturalHeightPt : defaultFontSize * fontScale * defaultRatio) * PX_PER_PT3 * lineSpacing;
8668
+ const lineHeight = getLineHeightPx(
8669
+ para,
8670
+ naturalHeightPt > 0 ? naturalHeightPt : defaultFontSize * fontScale * defaultRatio,
8671
+ lnSpcReduction
8672
+ );
8676
8673
  let lineCount;
8677
8674
  if (shouldWrap && para.runs.length > 0 && para.runs.some((r) => r.text.length > 0)) {
8678
8675
  const wrappedLines = wrapParagraph(para, textWidth, scaledDefaultForWrap, fontScale);
@@ -8939,7 +8936,7 @@ function renderTextBodyAsPath(textBody, transform, fontResolver) {
8939
8936
  if (para.runs.length === 0 || !para.runs.some((r) => r.text.length > 0)) {
8940
8937
  if (!isFirstLine) {
8941
8938
  const emptyParaHeightPt = paraFontSizePt > 0 ? paraFontSizePt : defaultNaturalHeightPt;
8942
- currentY += emptyParaHeightPt * PX_PER_PT3 * DEFAULT_LINE_SPACING + paragraphGapPx;
8939
+ currentY += getLineHeightPx(para, emptyParaHeightPt, lnSpcReduction) + paragraphGapPx;
8943
8940
  }
8944
8941
  isFirstLine = false;
8945
8942
  prevSpaceAfterPx = resolveSpacingPx(para.properties.spaceAfter, paraFontSizePt);
@@ -8957,7 +8954,7 @@ function renderTextBodyAsPath(textBody, transform, fontResolver) {
8957
8954
  const lineGapPx = lineIdx === 0 ? paragraphGapPx : 0;
8958
8955
  if (line.segments.length === 0) {
8959
8956
  if (!isFirstLine) {
8960
- currentY += defaultNaturalHeightPt * PX_PER_PT3 * getLineSpacing(para, lnSpcReduction) + lineGapPx;
8957
+ currentY += getLineHeightPx(para, defaultNaturalHeightPt, lnSpcReduction) + lineGapPx;
8961
8958
  }
8962
8959
  isFirstLine = false;
8963
8960
  continue;
@@ -8968,7 +8965,7 @@ function renderTextBodyAsPath(textBody, transform, fontResolver) {
8968
8965
  fontScale
8969
8966
  );
8970
8967
  if (!isFirstLine) {
8971
- currentY += lineNaturalHeightPt * PX_PER_PT3 * getLineSpacing(para, lnSpcReduction) + lineGapPx;
8968
+ currentY += getLineHeightPx(para, lineNaturalHeightPt, lnSpcReduction) + lineGapPx;
8972
8969
  }
8973
8970
  const lineWidth = measureLineWidth(line.segments, defaultFontSize, fontScale, fontResolver);
8974
8971
  const lineStartX = computePathLineX(
@@ -9016,7 +9013,7 @@ function renderTextBodyAsPath(textBody, transform, fontResolver) {
9016
9013
  } else {
9017
9014
  const naturalHeightPt = computeLineNaturalHeight(para.runs, defaultFontSize, fontScale);
9018
9015
  if (!isFirstLine) {
9019
- currentY += naturalHeightPt * PX_PER_PT3 * getLineSpacing(para, lnSpcReduction) + paragraphGapPx;
9016
+ currentY += getLineHeightPx(para, naturalHeightPt, lnSpcReduction) + paragraphGapPx;
9020
9017
  }
9021
9018
  const runsAsSegments = para.runs.filter((r) => r.text.length > 0).map((r) => ({ text: r.text, properties: r.properties }));
9022
9019
  const lineWidth = measureLineWidth(runsAsSegments, defaultFontSize, fontScale, fontResolver);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pptx-glimpse",
3
- "version": "1.1.0",
3
+ "version": "1.1.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",