documents.js 1.34.2 → 1.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -153,6 +153,7 @@ To run a single test file: `pnpm vitest run src/path/to/file.test.ts`.
153
153
  - **Table cell `colSpan`/`rowSpan` and pptx shape rotation are read from a `ContentDocument` but not yet written back** by `buildDocxPackage`/`buildPptxPackage` — a merged cell round-trips as an ordinary unmerged one, and a rotated shape round-trips unrotated. Both are bounded, tracked gaps (the cell's own text content and the shape's own position are still correct), not silent ones.
154
154
  - **docx headers/footers, live `PAGE`/`NUMPAGES` field substitution, and inline images are not read** by `readDocxContent` — a deliberate, tracked scope narrowing from the original design, not an oversight.
155
155
  - **pptx speaker notes survive `pptxToPdf`/`pdfToPptx`, but not through any real PDF feature.** PDF has no native concept of hidden presenter notes, so `convertPresentationToLayout` carries `ContentSlide.notes` as a hidden `/Subtype /Text` annotation on the page (the same construct Acrobat's own sticky-note tool uses, marked with the `Hidden` annotation flag so it never renders or prints), and `reconstructPresentation` reads it back via a `/T` marker that distinguishes this package's own notes annotation from a genuine third-party sticky note. This is a round-trip mechanism specific to this package's own writer/reader pair — a PDF produced by anything else will never carry it, and a PDF consumer other than this package's own `readPdf` will never see it as anything but an invisible, empty sticky note.
156
+ - **`sourcePath` traces a `LayoutItem` back to the `ContentDocument` node it came from, but only within one read+layout pass.** `ooxml.js`'s `readDocx`/`readPptx` stamp every `ContentRun`/`ContentImageBlock`/`ContentTable`/`ContentShape` with a positional path (`sections[0].blocks[2].runs[1]`, `slides[1].shapes[3].blocks[0]`); `convertWordprocessingToLayout`/`convertPresentationToLayout` copy that same string onto whichever `LayoutText`/`LayoutImage`/`LayoutLink`/`LayoutRect` item(s) it produces, so a positioned PDF-side item can be traced back to its semantic origin. When line-wrapping splits one run's word across a run boundary, every resulting fragment gets its own run's path (not a shared or merged one); when a single run is emergency-split across several lines or pages, every resulting fragment keeps that same one run's path unchanged. A table cell's background `LayoutRect` is attributed to its containing table's own `sourcePath`, since `ContentTableCell` carries none of its own. This is **not** an edit-tracking or incremental-relayout mechanism — the path is only valid against the exact `ContentDocument`/`Package` it was assigned from in that one read; editing the document, re-reading it, or reordering its blocks invalidates every previously-captured path, and nothing here recomputes or diffs paths across two versions of a document.
156
157
 
157
158
  ## Fidelity
158
159
 
package/dist/index.cjs CHANGED
@@ -6735,7 +6735,8 @@ function atomizeRuns(runs, measurer) {
6735
6735
  sizePt: run.sizePt,
6736
6736
  color: run.color,
6737
6737
  underline: run.underline,
6738
- hyperlink: run.hyperlink
6738
+ hyperlink: run.hyperlink,
6739
+ sourcePath: run.sourcePath
6739
6740
  });
6740
6741
  wordWidth += measurer.widthOfTextAtSize(token, run.font, run.sizePt);
6741
6742
  }
@@ -6923,7 +6924,8 @@ function toStyledRuns(runs, fontScale = 1) {
6923
6924
  sizePt: (run.sizePt ?? 18) * fontScale,
6924
6925
  color: run.color ?? document_content_model.COLOR_BLACK,
6925
6926
  underline: run.underline,
6926
- hyperlink: run.hyperlink
6927
+ hyperlink: run.hyperlink,
6928
+ sourcePath: run.sourcePath
6927
6929
  }));
6928
6930
  }
6929
6931
  function effectiveStyledRuns(runs, fontScale = 1) {
@@ -7038,7 +7040,8 @@ function layoutParagraphFlow(paragraph, section, pages, state, contentLeftXDown,
7038
7040
  font: fragment.font,
7039
7041
  sizePt: fragment.sizePt,
7040
7042
  color: fragment.color,
7041
- underline: fragment.underline
7043
+ underline: fragment.underline,
7044
+ sourcePath: fragment.sourcePath
7042
7045
  };
7043
7046
  state.items.push(textItem);
7044
7047
  if (fragment.hyperlink !== void 0) {
@@ -7049,7 +7052,8 @@ function layoutParagraphFlow(paragraph, section, pages, state, contentLeftXDown,
7049
7052
  xPt,
7050
7053
  yPt: section.pageSize.heightPt - baselineYDown + line.descentPt,
7051
7054
  widthPt: fragmentWidthPt,
7052
- heightPt: line.ascentPt - line.descentPt
7055
+ heightPt: line.ascentPt - line.descentPt,
7056
+ sourcePath: fragment.sourcePath
7053
7057
  };
7054
7058
  state.items.push(link);
7055
7059
  }
@@ -7077,7 +7081,8 @@ function layoutParagraphInCell(paragraph, cellLeftXDown, cellWidthPt, startYDown
7077
7081
  font: fragment.font,
7078
7082
  sizePt: fragment.sizePt,
7079
7083
  color: fragment.color,
7080
- underline: fragment.underline
7084
+ underline: fragment.underline,
7085
+ sourcePath: fragment.sourcePath
7081
7086
  });
7082
7087
  cursorYDown += lineHeightPt;
7083
7088
  });
@@ -7107,7 +7112,8 @@ function layoutTableFlow(table, section, pages, state, contentLeftXDown, content
7107
7112
  yPt: cellFrame.yPt,
7108
7113
  widthPt: cellFrame.widthPt,
7109
7114
  heightPt: cellFrame.heightPt,
7110
- fill: cell.background
7115
+ fill: cell.background,
7116
+ sourcePath: table.sourcePath
7111
7117
  });
7112
7118
  }
7113
7119
  let cellCursorYDown = state.cursorYDown;
@@ -7133,7 +7139,8 @@ function layoutImageFlow(block, section, pages, state, contentLeftXDown, content
7133
7139
  xPt: flippedFrame.xPt,
7134
7140
  yPt: flippedFrame.yPt,
7135
7141
  widthPt: flippedFrame.widthPt,
7136
- heightPt: flippedFrame.heightPt
7142
+ heightPt: flippedFrame.heightPt,
7143
+ sourcePath: block.sourcePath
7137
7144
  };
7138
7145
  state.items.push(imageItem);
7139
7146
  state.cursorYDown += block.heightPt;
@@ -7204,7 +7211,8 @@ function layoutParagraph(paragraph, contentLeftXDown, contentWidthPt, startYDown
7204
7211
  sizePt: fragment.sizePt,
7205
7212
  color: fragment.color,
7206
7213
  underline: fragment.underline,
7207
- rotationDeg: placement.layoutRotationDeg
7214
+ rotationDeg: placement.layoutRotationDeg,
7215
+ sourcePath: fragment.sourcePath
7208
7216
  };
7209
7217
  out.push(textItem);
7210
7218
  if (fragment.hyperlink !== void 0) {
@@ -7219,7 +7227,8 @@ function layoutParagraph(paragraph, contentLeftXDown, contentWidthPt, startYDown
7219
7227
  xPt: linkBottomLeft.x,
7220
7228
  yPt: linkBottomLeft.y,
7221
7229
  widthPt: fragmentWidthPt,
7222
- heightPt: line.ascentPt - line.descentPt
7230
+ heightPt: line.ascentPt - line.descentPt,
7231
+ sourcePath: fragment.sourcePath
7223
7232
  };
7224
7233
  out.push(link);
7225
7234
  }
@@ -7253,7 +7262,8 @@ function layoutTable(table, contentLeftXDown, contentWidthPt, startYDown, slideH
7253
7262
  yPt: cellFrame.yPt,
7254
7263
  widthPt: cellFrame.widthPt,
7255
7264
  heightPt: cellFrame.heightPt,
7256
- fill: cell.background
7265
+ fill: cell.background,
7266
+ sourcePath: table.sourcePath
7257
7267
  });
7258
7268
  }
7259
7269
  let cellCursorYDown = cursorYDown;
@@ -7287,7 +7297,8 @@ function convertShape(shape, slideHeightPt, measurer, images, out) {
7287
7297
  yPt: placed.y,
7288
7298
  widthPt: flippedFrame.widthPt,
7289
7299
  heightPt: flippedFrame.heightPt,
7290
- rotationDeg: placement.layoutRotationDeg
7300
+ rotationDeg: placement.layoutRotationDeg,
7301
+ sourcePath: block.sourcePath
7291
7302
  };
7292
7303
  out.push(imageItem);
7293
7304
  } else if (block.kind === "table") cursorYDown = layoutTable(block, contentLeftXDown, contentWidthPt, cursorYDown, slideHeightPt, placement, measurer, out);
package/dist/index.d.cts CHANGED
@@ -62,6 +62,7 @@ declare const ContentDocumentSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
62
62
  insetBottomPt: z.ZodNumber;
63
63
  fontScale: z.ZodOptional<z.ZodNumber>;
64
64
  lineSpacingReduction: z.ZodOptional<z.ZodNumber>;
65
+ sourcePath: z.ZodOptional<z.ZodString>;
65
66
  blocks: z.ZodArray<z.ZodCustom<import("document-content-model").ContentBlock, import("document-content-model").ContentBlock>>;
66
67
  }, z.core.$strip>>;
67
68
  notes: z.ZodString;
@@ -375,6 +376,7 @@ declare const pdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
375
376
  widthPt: z.ZodOptional<z.ZodNumber>;
376
377
  rotationDeg: z.ZodOptional<z.ZodNumber>;
377
378
  underline: z.ZodOptional<z.ZodBoolean>;
379
+ sourcePath: z.ZodOptional<z.ZodString>;
378
380
  }, z.core.$strip>, z.ZodObject<{
379
381
  kind: z.ZodLiteral<"image">;
380
382
  imageId: z.ZodString;
@@ -383,6 +385,7 @@ declare const pdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
383
385
  widthPt: z.ZodNumber;
384
386
  heightPt: z.ZodNumber;
385
387
  rotationDeg: z.ZodOptional<z.ZodNumber>;
388
+ sourcePath: z.ZodOptional<z.ZodString>;
386
389
  }, z.core.$strip>, z.ZodObject<{
387
390
  kind: z.ZodLiteral<"rect">;
388
391
  xPt: z.ZodNumber;
@@ -402,6 +405,7 @@ declare const pdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
402
405
  }, z.core.$strip>;
403
406
  widthPt: z.ZodNumber;
404
407
  }, z.core.$strip>>;
408
+ sourcePath: z.ZodOptional<z.ZodString>;
405
409
  }, z.core.$strip>, z.ZodObject<{
406
410
  kind: z.ZodLiteral<"line">;
407
411
  x1Pt: z.ZodNumber;
@@ -414,6 +418,7 @@ declare const pdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
414
418
  b: z.ZodNumber;
415
419
  }, z.core.$strip>;
416
420
  widthPt: z.ZodNumber;
421
+ sourcePath: z.ZodOptional<z.ZodString>;
417
422
  }, z.core.$strip>, z.ZodObject<{
418
423
  kind: z.ZodLiteral<"ellipse">;
419
424
  xPt: z.ZodNumber;
@@ -433,6 +438,7 @@ declare const pdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
433
438
  }, z.core.$strip>;
434
439
  widthPt: z.ZodNumber;
435
440
  }, z.core.$strip>>;
441
+ sourcePath: z.ZodOptional<z.ZodString>;
436
442
  }, z.core.$strip>, z.ZodObject<{
437
443
  kind: z.ZodLiteral<"link">;
438
444
  uri: z.ZodString;
@@ -440,6 +446,7 @@ declare const pdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
440
446
  yPt: z.ZodNumber;
441
447
  widthPt: z.ZodNumber;
442
448
  heightPt: z.ZodNumber;
449
+ sourcePath: z.ZodOptional<z.ZodString>;
443
450
  }, z.core.$strip>], "kind">>;
444
451
  notes: z.ZodOptional<z.ZodString>;
445
452
  }, z.core.$strip>>;
package/dist/index.d.ts CHANGED
@@ -62,6 +62,7 @@ declare const ContentDocumentSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
62
62
  insetBottomPt: z.ZodNumber;
63
63
  fontScale: z.ZodOptional<z.ZodNumber>;
64
64
  lineSpacingReduction: z.ZodOptional<z.ZodNumber>;
65
+ sourcePath: z.ZodOptional<z.ZodString>;
65
66
  blocks: z.ZodArray<z.ZodCustom<import("document-content-model").ContentBlock, import("document-content-model").ContentBlock>>;
66
67
  }, z.core.$strip>>;
67
68
  notes: z.ZodString;
@@ -375,6 +376,7 @@ declare const pdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
375
376
  widthPt: z.ZodOptional<z.ZodNumber>;
376
377
  rotationDeg: z.ZodOptional<z.ZodNumber>;
377
378
  underline: z.ZodOptional<z.ZodBoolean>;
379
+ sourcePath: z.ZodOptional<z.ZodString>;
378
380
  }, z.core.$strip>, z.ZodObject<{
379
381
  kind: z.ZodLiteral<"image">;
380
382
  imageId: z.ZodString;
@@ -383,6 +385,7 @@ declare const pdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
383
385
  widthPt: z.ZodNumber;
384
386
  heightPt: z.ZodNumber;
385
387
  rotationDeg: z.ZodOptional<z.ZodNumber>;
388
+ sourcePath: z.ZodOptional<z.ZodString>;
386
389
  }, z.core.$strip>, z.ZodObject<{
387
390
  kind: z.ZodLiteral<"rect">;
388
391
  xPt: z.ZodNumber;
@@ -402,6 +405,7 @@ declare const pdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
402
405
  }, z.core.$strip>;
403
406
  widthPt: z.ZodNumber;
404
407
  }, z.core.$strip>>;
408
+ sourcePath: z.ZodOptional<z.ZodString>;
405
409
  }, z.core.$strip>, z.ZodObject<{
406
410
  kind: z.ZodLiteral<"line">;
407
411
  x1Pt: z.ZodNumber;
@@ -414,6 +418,7 @@ declare const pdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
414
418
  b: z.ZodNumber;
415
419
  }, z.core.$strip>;
416
420
  widthPt: z.ZodNumber;
421
+ sourcePath: z.ZodOptional<z.ZodString>;
417
422
  }, z.core.$strip>, z.ZodObject<{
418
423
  kind: z.ZodLiteral<"ellipse">;
419
424
  xPt: z.ZodNumber;
@@ -433,6 +438,7 @@ declare const pdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
433
438
  }, z.core.$strip>;
434
439
  widthPt: z.ZodNumber;
435
440
  }, z.core.$strip>>;
441
+ sourcePath: z.ZodOptional<z.ZodString>;
436
442
  }, z.core.$strip>, z.ZodObject<{
437
443
  kind: z.ZodLiteral<"link">;
438
444
  uri: z.ZodString;
@@ -440,6 +446,7 @@ declare const pdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
440
446
  yPt: z.ZodNumber;
441
447
  widthPt: z.ZodNumber;
442
448
  heightPt: z.ZodNumber;
449
+ sourcePath: z.ZodOptional<z.ZodString>;
443
450
  }, z.core.$strip>], "kind">>;
444
451
  notes: z.ZodOptional<z.ZodString>;
445
452
  }, z.core.$strip>>;
package/dist/index.js CHANGED
@@ -6734,7 +6734,8 @@ function atomizeRuns(runs, measurer) {
6734
6734
  sizePt: run.sizePt,
6735
6735
  color: run.color,
6736
6736
  underline: run.underline,
6737
- hyperlink: run.hyperlink
6737
+ hyperlink: run.hyperlink,
6738
+ sourcePath: run.sourcePath
6738
6739
  });
6739
6740
  wordWidth += measurer.widthOfTextAtSize(token, run.font, run.sizePt);
6740
6741
  }
@@ -6922,7 +6923,8 @@ function toStyledRuns(runs, fontScale = 1) {
6922
6923
  sizePt: (run.sizePt ?? 18) * fontScale,
6923
6924
  color: run.color ?? COLOR_BLACK,
6924
6925
  underline: run.underline,
6925
- hyperlink: run.hyperlink
6926
+ hyperlink: run.hyperlink,
6927
+ sourcePath: run.sourcePath
6926
6928
  }));
6927
6929
  }
6928
6930
  function effectiveStyledRuns(runs, fontScale = 1) {
@@ -7037,7 +7039,8 @@ function layoutParagraphFlow(paragraph, section, pages, state, contentLeftXDown,
7037
7039
  font: fragment.font,
7038
7040
  sizePt: fragment.sizePt,
7039
7041
  color: fragment.color,
7040
- underline: fragment.underline
7042
+ underline: fragment.underline,
7043
+ sourcePath: fragment.sourcePath
7041
7044
  };
7042
7045
  state.items.push(textItem);
7043
7046
  if (fragment.hyperlink !== void 0) {
@@ -7048,7 +7051,8 @@ function layoutParagraphFlow(paragraph, section, pages, state, contentLeftXDown,
7048
7051
  xPt,
7049
7052
  yPt: section.pageSize.heightPt - baselineYDown + line.descentPt,
7050
7053
  widthPt: fragmentWidthPt,
7051
- heightPt: line.ascentPt - line.descentPt
7054
+ heightPt: line.ascentPt - line.descentPt,
7055
+ sourcePath: fragment.sourcePath
7052
7056
  };
7053
7057
  state.items.push(link);
7054
7058
  }
@@ -7076,7 +7080,8 @@ function layoutParagraphInCell(paragraph, cellLeftXDown, cellWidthPt, startYDown
7076
7080
  font: fragment.font,
7077
7081
  sizePt: fragment.sizePt,
7078
7082
  color: fragment.color,
7079
- underline: fragment.underline
7083
+ underline: fragment.underline,
7084
+ sourcePath: fragment.sourcePath
7080
7085
  });
7081
7086
  cursorYDown += lineHeightPt;
7082
7087
  });
@@ -7106,7 +7111,8 @@ function layoutTableFlow(table, section, pages, state, contentLeftXDown, content
7106
7111
  yPt: cellFrame.yPt,
7107
7112
  widthPt: cellFrame.widthPt,
7108
7113
  heightPt: cellFrame.heightPt,
7109
- fill: cell.background
7114
+ fill: cell.background,
7115
+ sourcePath: table.sourcePath
7110
7116
  });
7111
7117
  }
7112
7118
  let cellCursorYDown = state.cursorYDown;
@@ -7132,7 +7138,8 @@ function layoutImageFlow(block, section, pages, state, contentLeftXDown, content
7132
7138
  xPt: flippedFrame.xPt,
7133
7139
  yPt: flippedFrame.yPt,
7134
7140
  widthPt: flippedFrame.widthPt,
7135
- heightPt: flippedFrame.heightPt
7141
+ heightPt: flippedFrame.heightPt,
7142
+ sourcePath: block.sourcePath
7136
7143
  };
7137
7144
  state.items.push(imageItem);
7138
7145
  state.cursorYDown += block.heightPt;
@@ -7203,7 +7210,8 @@ function layoutParagraph(paragraph, contentLeftXDown, contentWidthPt, startYDown
7203
7210
  sizePt: fragment.sizePt,
7204
7211
  color: fragment.color,
7205
7212
  underline: fragment.underline,
7206
- rotationDeg: placement.layoutRotationDeg
7213
+ rotationDeg: placement.layoutRotationDeg,
7214
+ sourcePath: fragment.sourcePath
7207
7215
  };
7208
7216
  out.push(textItem);
7209
7217
  if (fragment.hyperlink !== void 0) {
@@ -7218,7 +7226,8 @@ function layoutParagraph(paragraph, contentLeftXDown, contentWidthPt, startYDown
7218
7226
  xPt: linkBottomLeft.x,
7219
7227
  yPt: linkBottomLeft.y,
7220
7228
  widthPt: fragmentWidthPt,
7221
- heightPt: line.ascentPt - line.descentPt
7229
+ heightPt: line.ascentPt - line.descentPt,
7230
+ sourcePath: fragment.sourcePath
7222
7231
  };
7223
7232
  out.push(link);
7224
7233
  }
@@ -7252,7 +7261,8 @@ function layoutTable(table, contentLeftXDown, contentWidthPt, startYDown, slideH
7252
7261
  yPt: cellFrame.yPt,
7253
7262
  widthPt: cellFrame.widthPt,
7254
7263
  heightPt: cellFrame.heightPt,
7255
- fill: cell.background
7264
+ fill: cell.background,
7265
+ sourcePath: table.sourcePath
7256
7266
  });
7257
7267
  }
7258
7268
  let cellCursorYDown = cursorYDown;
@@ -7286,7 +7296,8 @@ function convertShape(shape, slideHeightPt, measurer, images, out) {
7286
7296
  yPt: placed.y,
7287
7297
  widthPt: flippedFrame.widthPt,
7288
7298
  heightPt: flippedFrame.heightPt,
7289
- rotationDeg: placement.layoutRotationDeg
7299
+ rotationDeg: placement.layoutRotationDeg,
7300
+ sourcePath: block.sourcePath
7290
7301
  };
7291
7302
  out.push(imageItem);
7292
7303
  } else if (block.kind === "table") cursorYDown = layoutTable(block, contentLeftXDown, contentWidthPt, cursorYDown, slideHeightPt, placement, measurer, out);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "documents.js",
3
- "version": "1.34.2",
3
+ "version": "1.35.0",
4
4
  "description": "Bidirectional docx/pptx <-> PDF conversion and a read+write editable OOXML document model, built on ooxml.js and Zod 4 codecs.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -64,9 +64,9 @@
64
64
  "license": "MIT",
65
65
  "packageManager": "pnpm@11.6.0",
66
66
  "dependencies": {
67
- "document-content-model": "^1.0.0",
67
+ "document-content-model": "^1.1.0",
68
68
  "fflate": "^0.8.3",
69
- "ooxml.js": "^2.0.0",
69
+ "ooxml.js": "^2.1.0",
70
70
  "zod": "^4.4.3"
71
71
  },
72
72
  "devDependencies": {