reamkit 1.10.0 → 1.12.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.
Files changed (48) hide show
  1. package/README.md +3 -3
  2. package/dist/esm/core/converter/facade.js +1 -1
  3. package/dist/esm/core/converter/project.js +1 -0
  4. package/dist/esm/core/document-model/index.d.ts +1 -1
  5. package/dist/esm/core/document-model/types.d.ts +23 -0
  6. package/dist/esm/core/font/measure.d.ts +1 -1
  7. package/dist/esm/core/font/measure.js +5 -3
  8. package/dist/esm/core/font/ttf-parser.d.ts +9 -0
  9. package/dist/esm/core/font/ttf-parser.js +27 -2
  10. package/dist/esm/core/fonts/provider.d.ts +2 -1
  11. package/dist/esm/core/fonts/provider.js +2 -1
  12. package/dist/esm/core/fonts/remote-fonts.d.ts +1 -1
  13. package/dist/esm/core/fonts/remote-fonts.js +32 -11
  14. package/dist/esm/core/ir/features.d.ts +1 -0
  15. package/dist/esm/core/ir/features.js +1 -0
  16. package/dist/esm/core/ir/flow.d.ts +3 -1
  17. package/dist/esm/core/line-breaker/greedy.d.ts +2 -0
  18. package/dist/esm/core/line-breaker/greedy.js +67 -0
  19. package/dist/esm/core/line-breaker/index.d.ts +1 -0
  20. package/dist/esm/core/line-breaker/knuth-plass.d.ts +1 -0
  21. package/dist/esm/core/line-breaker/knuth-plass.js +3 -3
  22. package/dist/esm/core/po-helpers.d.ts +2 -0
  23. package/dist/esm/core/po-helpers.js +14 -1
  24. package/dist/esm/core/spreadsheet-model/index.d.ts +1 -1
  25. package/dist/esm/core/spreadsheet-model/types.d.ts +16 -0
  26. package/dist/esm/excel/pivot-table-parser.d.ts +2 -0
  27. package/dist/esm/excel/pivot-table-parser.js +68 -0
  28. package/dist/esm/excel/print-model.js +28 -6
  29. package/dist/esm/excel/xlsx-reader.js +33 -2
  30. package/dist/esm/excel/xlsx-to-pdf.js +1 -1
  31. package/dist/esm/html/html-writer.js +52 -2
  32. package/dist/esm/layout/page-doc.d.ts +3 -0
  33. package/dist/esm/layout/styled-layout.d.ts +10 -1
  34. package/dist/esm/layout/styled-layout.js +156 -15
  35. package/dist/esm/pdf/styled-page-emitter.js +38 -0
  36. package/dist/esm/pptx/pptx-reader.d.ts +2 -0
  37. package/dist/esm/pptx/pptx-reader.js +30 -3
  38. package/dist/esm/pptx/slide-parser.d.ts +8 -2
  39. package/dist/esm/pptx/slide-parser.js +80 -12
  40. package/dist/esm/word/document-parser.d.ts +17 -2
  41. package/dist/esm/word/document-parser.js +178 -18
  42. package/dist/esm/word/docx-reader.js +54 -4
  43. package/dist/esm/word/docx-to-pdf.js +2 -2
  44. package/dist/esm/word/docx-writer.js +84 -1
  45. package/dist/esm/word/drawing-parser.d.ts +7 -0
  46. package/dist/esm/word/drawing-parser.js +13 -0
  47. package/dist/esm/word/index.d.ts +2 -1
  48. package/package.json +1 -1
@@ -3,8 +3,8 @@ import { ResourceStore } from "../core/ir/resources.js";
3
3
  import { FEATURES } from "../core/ir/features.js";
4
4
  import { EMPTY_STYLE_SHEET, resolveBodyStyles } from "../core/style-cascade/resolver.js";
5
5
  import "../core/style-cascade/index.js";
6
+ import { poAttr, poChildren, poFindDescendant, poIntAttr, poIs } from "../core/po-helpers.js";
6
7
  import { bytesInclude } from "../core/bytes.js";
7
- import { poAttr, poChildren, poIntAttr, poIs } from "../core/po-helpers.js";
8
8
  import { DEFAULT_THEME_PALETTE, defaultColorResolver, makeColorResolver } from "../core/drawingml/colors.js";
9
9
  import { parseChart, withChartColorStyle } from "../core/drawingml/chart-parser.js";
10
10
  import { parseTheme } from "../core/drawingml/theme-parser.js";
@@ -81,7 +81,12 @@ function readPptx(bytes) {
81
81
  colors: styles.colors,
82
82
  resolveImage: makeSlideImageResolver(pkg, part.path, resources),
83
83
  resolveChart: makeSlideChartResolver(pkg, part.path, charts, styles.colors),
84
- resolveHyperlink: makeHyperlinkResolver(pkg, part.path)
84
+ resolveHyperlink: makeHyperlinkResolver(pkg, part.path),
85
+ resolveDiagram: makeSlideDiagramResolver(pkg, part.path),
86
+ onLoss: (loss) => losses.push(loss.where ? loss : {
87
+ ...loss,
88
+ where: `slide ${i + 1}`
89
+ })
85
90
  };
86
91
  body.push(...parseSlide(part.data, ctx, styles.background, pageW, pageH));
87
92
  }
@@ -167,6 +172,28 @@ function makeSlideChartResolver(pkg, slidePath, charts, colors) {
167
172
  return key;
168
173
  };
169
174
  }
175
+ function makeSlideDiagramResolver(pkg, slidePath) {
176
+ const cache = /* @__PURE__ */ new Map();
177
+ return (relId) => {
178
+ if (cache.has(relId)) return cache.get(relId);
179
+ let spTree;
180
+ const dataRel = pkg.getPartRelationships(slidePath).find((r) => r.id === relId);
181
+ const data = dataRel ? pkg.resolveRelatedPart(slidePath, dataRel) : void 0;
182
+ if (data) {
183
+ const drawRel = pkg.getPartRelationships(data.path).find((r) => r.type.endsWith("/diagramDrawing"));
184
+ const draw = drawRel ? pkg.resolveRelatedPart(data.path, drawRel) : void 0;
185
+ if (draw) for (const root of parseXml(draw.data)) {
186
+ const found = poFindDescendant(root, "dsp:spTree");
187
+ if (found) {
188
+ spTree = found;
189
+ break;
190
+ }
191
+ }
192
+ }
193
+ cache.set(relId, spTree);
194
+ return spTree;
195
+ };
196
+ }
170
197
  function slideStylesFor(pkg, slidePath, cache) {
171
198
  const layoutRel = pkg.getPartRelationships(slidePath).find((r) => r.type.endsWith("/slideLayout"));
172
199
  const layout = layoutRel ? pkg.resolveRelatedPart(slidePath, layoutRel) : void 0;
@@ -210,4 +237,4 @@ var pptxReader = {
210
237
  read: (bytes) => readPptx(bytes)
211
238
  };
212
239
  //#endregion
213
- export { pptxReader };
240
+ export { parseXml, pptxReader };
@@ -1,6 +1,6 @@
1
- import { BodyElement, ShapeFill } from '../core/document-model/index.js';
1
+ import { BodyElement, FloatAnchor, ShapeBlock, ShapeFill } from '../core/document-model/index.js';
2
2
  import { ColorResolver } from '../core/drawingml/colors.js';
3
- import { Pt, ResourceId } from '../core/ir/index.js';
3
+ import { Loss, Pt, ResourceId } from '../core/ir/index.js';
4
4
  import { PoNode } from '../core/po-helpers.js';
5
5
  import { PlaceholderCascade } from './placeholder-cascade.js';
6
6
  import { ShapeBoxEmu } from './sp-helpers.js';
@@ -10,9 +10,15 @@ export interface SlideContext {
10
10
  readonly resolveChart?: (relId: string) => string | undefined;
11
11
  readonly colors?: ColorResolver;
12
12
  readonly resolveHyperlink?: (relId: string) => string | undefined;
13
+ readonly resolveDiagram?: (relId: string) => PoNode | undefined;
14
+ readonly onLoss?: (loss: Loss) => void;
13
15
  }
16
+ type LinkResolver = ((relId: string) => string | undefined) | undefined;
14
17
  type GroupTransform = (box: ShapeBoxEmu) => ShapeBoxEmu;
15
18
  export declare function parseSlideShapes(container: PoNode, ctx?: SlideContext, transform?: GroupTransform): Array<BodyElement>;
19
+ export declare function diagramTransform(spTree: PoNode, frame: ShapeBoxEmu): GroupTransform;
20
+ export declare function noDiagramOverrideLoss(where?: string): Loss;
21
+ export declare function parseDiagramDrawing(spTree: PoNode, transform: GroupTransform, makeFloat: (box: ShapeBoxEmu) => FloatAnchor, colors: ColorResolver, resolveLink: LinkResolver): Array<ShapeBlock>;
16
22
  export declare function parseBackgroundFill(bg: PoNode, colors: ColorResolver): ShapeFill | undefined;
17
23
  export declare function backdropElement(fill: ShapeFill, widthPt: Pt, heightPt: Pt): BodyElement;
18
24
  export {};
@@ -1,11 +1,13 @@
1
1
  import { emuToPt } from "../core/ir/units.js";
2
+ import { FEATURES } from "../core/ir/features.js";
2
3
  import { poAttr, poChildren, poFindDescendant, poIntAttr, poIs, poText } from "../core/po-helpers.js";
3
4
  import { defaultColorResolver, resolveColorNode } from "../core/drawingml/colors.js";
4
- import { parseCustGeom, parseFill, parseLine, parsePrstGeom } from "../word/drawing-parser.js";
5
5
  import { boxFromXfrm, parsePh, parseXfrmBox, rPrToRunProps } from "./sp-helpers.js";
6
+ import { parseCustGeom, parseFill, parseLine, parsePrstGeom } from "../word/drawing-parser.js";
6
7
  //#region src/pptx/slide-parser.ts
7
8
  var CHART_URI = "http://schemas.openxmlformats.org/drawingml/2006/chart";
8
9
  var TABLE_URI = "http://schemas.openxmlformats.org/drawingml/2006/table";
10
+ var DIAGRAM_URI = "http://schemas.openxmlformats.org/drawingml/2006/diagram";
9
11
  var ALGN_TO_ALIGNMENT = {
10
12
  l: "left",
11
13
  ctr: "center",
@@ -33,10 +35,8 @@ function parseSlideShapes(container, ctx = {}, transform = IDENTITY_TRANSFORM) {
33
35
  kind: "image",
34
36
  image
35
37
  });
36
- } else if (poIs(child, "p:graphicFrame")) {
37
- const el = parseGraphicFrame(child, ctx, transform);
38
- if (el) out.push(el);
39
- } else if (poIs(child, "p:grpSp")) out.push(...parseSlideShapes(child, ctx, composeGroupTransform(child, transform)));
38
+ } else if (poIs(child, "p:graphicFrame")) out.push(...parseGraphicFrame(child, ctx, transform));
39
+ else if (poIs(child, "p:grpSp")) out.push(...parseSlideShapes(child, ctx, composeGroupTransform(child, transform)));
40
40
  return out;
41
41
  }
42
42
  function composeGroupTransform(grpSp, parent) {
@@ -106,7 +106,7 @@ function parseSp(sp, ctx, transform) {
106
106
  }
107
107
  function parseGraphicFrame(gf, ctx, transform) {
108
108
  const own = boxFromXfrm(poChildren(gf).find((c) => poIs(c, "p:xfrm")));
109
- if (!own) return void 0;
109
+ if (!own) return [];
110
110
  const box = transform(own);
111
111
  const graphicData = poFindDescendant(gf, "a:graphicData");
112
112
  const uri = graphicData ? poAttr(graphicData, "uri") : void 0;
@@ -114,8 +114,8 @@ function parseGraphicFrame(gf, ctx, transform) {
114
114
  const cChart = poFindDescendant(gf, "c:chart");
115
115
  const relId = cChart ? poAttr(cChart, "id") : void 0;
116
116
  const key = relId !== void 0 ? ctx.resolveChart?.(relId) : void 0;
117
- if (key === void 0) return void 0;
118
- return {
117
+ if (key === void 0) return [];
118
+ return [{
119
119
  kind: "chart",
120
120
  chart: {
121
121
  float: floatAt(box),
@@ -124,15 +124,83 @@ function parseGraphicFrame(gf, ctx, transform) {
124
124
  height: emuToPt(box.cy),
125
125
  paragraphProperties: {}
126
126
  }
127
- };
127
+ }];
128
128
  }
129
129
  if (uri === TABLE_URI) {
130
130
  const tbl = poFindDescendant(gf, "a:tbl");
131
- return tbl ? {
131
+ return tbl ? [{
132
132
  kind: "table",
133
133
  table: parseTable(tbl, ctx.colors ?? defaultColorResolver)
134
- } : void 0;
134
+ }] : [];
135
135
  }
136
+ if (uri === DIAGRAM_URI) {
137
+ const relIds = poFindDescendant(gf, "dgm:relIds");
138
+ const dmRelId = relIds ? poAttr(relIds, "dm") : void 0;
139
+ const spTree = dmRelId !== void 0 ? ctx.resolveDiagram?.(dmRelId) : void 0;
140
+ if (!spTree) {
141
+ if (dmRelId !== void 0) ctx.onLoss?.(noDiagramOverrideLoss());
142
+ return [];
143
+ }
144
+ return parseDiagramDrawing(spTree, diagramTransform(spTree, box), floatAt, ctx.colors ?? defaultColorResolver, ctx.resolveHyperlink).map((shape) => ({
145
+ kind: "shape",
146
+ shape
147
+ }));
148
+ }
149
+ return [];
150
+ }
151
+ function diagramTransform(spTree, frame) {
152
+ const grpSpPr = poChildren(spTree).find((c) => poIs(c, "dsp:grpSpPr"));
153
+ const xfrm = grpSpPr ? poChildren(grpSpPr).find((c) => poIs(c, "a:xfrm")) : void 0;
154
+ const chOff = xfrm ? poChildren(xfrm).find((c) => poIs(c, "a:chOff")) : void 0;
155
+ const chExt = xfrm ? poChildren(xfrm).find((c) => poIs(c, "a:chExt")) : void 0;
156
+ const chExtCx = chExt ? poIntAttr(chExt, "cx") : void 0;
157
+ const chExtCy = chExt ? poIntAttr(chExt, "cy") : void 0;
158
+ const chOffX = (chOff ? poIntAttr(chOff, "x") : void 0) ?? 0;
159
+ const chOffY = (chOff ? poIntAttr(chOff, "y") : void 0) ?? 0;
160
+ const sx = chExtCx && chExtCx > 0 ? frame.cx / chExtCx : 1;
161
+ const sy = chExtCy && chExtCy > 0 ? frame.cy / chExtCy : 1;
162
+ return (b) => ({
163
+ x: frame.x + (b.x - chOffX) * sx,
164
+ y: frame.y + (b.y - chOffY) * sy,
165
+ cx: b.cx * sx,
166
+ cy: b.cy * sy
167
+ });
168
+ }
169
+ function noDiagramOverrideLoss(where) {
170
+ return {
171
+ severity: "dropped",
172
+ feature: FEATURES.smartArt,
173
+ detail: "SmartArt diagram has no pre-rendered drawing override; its layout is not reconstructed",
174
+ ...where ? { where } : {}
175
+ };
176
+ }
177
+ function parseDiagramDrawing(spTree, transform, makeFloat, colors, resolveLink) {
178
+ const out = [];
179
+ for (const sp of poChildren(spTree)) {
180
+ if (!poIs(sp, "dsp:sp")) continue;
181
+ const spPr = poChildren(sp).find((c) => poIs(c, "dsp:spPr"));
182
+ const own = parseXfrmBox(spPr);
183
+ if (!own) continue;
184
+ const box = transform(own);
185
+ const txBody = poChildren(sp).find((c) => poIs(c, "dsp:txBody"));
186
+ const text = txBody ? parseTxBody(txBody, void 0, void 0, colors, resolveLink) : void 0;
187
+ const geometry = parseGeometry(spPr);
188
+ const fill = spPr ? parseFill(spPr, colors) : { kind: "none" };
189
+ const line = spPr ? parseLine(spPr, colors) : void 0;
190
+ const visibleLine = line !== void 0 && line.fill !== "none";
191
+ if (!text && fill.kind === "none" && !visibleLine) continue;
192
+ out.push({
193
+ float: makeFloat(box),
194
+ width: emuToPt(box.cx),
195
+ height: emuToPt(box.cy),
196
+ geometry,
197
+ fill,
198
+ ...line ? { line } : {},
199
+ ...text ? { text } : {},
200
+ paragraphProperties: {}
201
+ });
202
+ }
203
+ return out;
136
204
  }
137
205
  function parseBackgroundFill(bg, colors) {
138
206
  const bgPr = poChildren(bg).find((c) => poIs(c, "p:bgPr"));
@@ -356,4 +424,4 @@ function cellFillHex(tcPr, colors) {
356
424
  }
357
425
  }
358
426
  //#endregion
359
- export { backdropElement, parseBackgroundFill, parseSlideShapes };
427
+ export { backdropElement, diagramTransform, noDiagramOverrideLoss, parseBackgroundFill, parseDiagramDrawing, parseSlideShapes };
@@ -1,6 +1,6 @@
1
- import { BodyElement, Section, SectionProperties } from '../core/document-model/index.js';
1
+ import { BodyElement, Comment, Section, SectionProperties } from '../core/document-model/index.js';
2
2
  import { ColorResolver } from '../core/drawingml/colors.js';
3
- import { ResourceId } from '../core/ir/index.js';
3
+ import { Loss, ResourceId } from '../core/ir/index.js';
4
4
  import { PoNode } from '../core/po-helpers.js';
5
5
  export type ImageResolver = (relId: string) => ResourceId | undefined;
6
6
  export type HyperlinkResolver = (relId: string) => string | undefined;
@@ -8,6 +8,9 @@ export interface ParseContext {
8
8
  readonly resolveColor: ColorResolver;
9
9
  readonly resolveImage?: ImageResolver;
10
10
  readonly resolveHyperlink?: HyperlinkResolver;
11
+ readonly resolveDiagram?: (relId: string) => PoNode | undefined;
12
+ readonly onLoss?: (loss: Loss) => void;
13
+ readonly openCommentRanges?: Set<string>;
11
14
  }
12
15
  export declare const DEFAULT_PARSE_CONTEXT: ParseContext;
13
16
  export declare function parseDocument(documentXml: Uint8Array, ctx?: ParseContext): Array<BodyElement>;
@@ -17,3 +20,15 @@ export declare function parseSections(documentXml: Uint8Array): Array<Section>;
17
20
  export declare function parseHeaderFooter(xml: Uint8Array, ctx?: ParseContext): Array<BodyElement>;
18
21
  export declare function parseBodyElements(children: ReadonlyArray<PoNode>, ctx?: ParseContext): Array<BodyElement>;
19
22
  export declare function parseNotes(notesXml: Uint8Array, rootTag: 'w:footnotes' | 'w:endnotes', noteTag: 'w:footnote' | 'w:endnote', ctx?: ParseContext): Map<string, Array<BodyElement>>;
23
+ export declare function parseComments(commentsXml: Uint8Array, ctx?: ParseContext): Map<string, Comment>;
24
+ /** A commentsExtended entry, keyed by the comment's last-paragraph w14:paraId. */
25
+ export interface CommentExtension {
26
+ /** The parent comment's paraId — present when this comment is a reply. */
27
+ readonly paraIdParent?: string;
28
+ /** w15:done — the thread is resolved. */
29
+ readonly done: boolean;
30
+ }
31
+ export declare function parseCommentsExtended(xml: Uint8Array): Map<string, CommentExtension>;
32
+ export declare function parseCommentThreads(commentsXml: Uint8Array, commentsExtendedXml: Uint8Array | undefined, ctx?: ParseContext): Map<string, Comment>;
33
+ export declare function parsePeople(xml: Uint8Array): Map<string, string>;
34
+ export declare function applyAuthorIds(comments: Map<string, Comment>, people: Map<string, string>): Map<string, Comment>;
@@ -1,8 +1,9 @@
1
- import { twipsToPt } from "../core/ir/units.js";
2
- import { poAttr, poChildren, poFindByPath, poFindDescendant, poIntAttr, poIs, poText } from "../core/po-helpers.js";
1
+ import { emuToPt, twipsToPt } from "../core/ir/units.js";
2
+ import { poAttr, poAttrLocal, poChildren, poFindByPath, poFindDescendant, poIntAttr, poIs, poIsLocal, poText } from "../core/po-helpers.js";
3
3
  import { defaultColorResolver } from "../core/drawingml/colors.js";
4
- import { parseOMath } from "./omml-parser.js";
5
4
  import { expandMcChildren, parseDrawing, parseVmlPicture } from "./drawing-parser.js";
5
+ import { diagramTransform, noDiagramOverrideLoss, parseDiagramDrawing } from "../pptx/slide-parser.js";
6
+ import { parseOMath } from "./omml-parser.js";
6
7
  import { parseRunProperties } from "./run-properties.js";
7
8
  import { parseParagraphProperties } from "./paragraph-properties.js";
8
9
  import { poElementToFlat } from "./po-to-flat.js";
@@ -162,12 +163,15 @@ function parseBodyElements(children, ctx = DEFAULT_PARSE_CONTEXT) {
162
163
  const bookmarkName = poAttr(child, "name");
163
164
  if (bookmarkName !== void 0 && bookmarkName !== "" && bookmarkName !== "_GoBack") (pendingBookmarks ??= []).push(bookmarkName);
164
165
  } else if (poIs(child, "w:p")) {
165
- const drawing = tryExtractDrawingFromParagraph(child, ctx);
166
- out.push(drawing ?? {
167
- kind: "paragraph",
168
- paragraph: parseParagraph(child, ctx, pendingBookmarks)
169
- });
170
- if (!drawing) pendingBookmarks = void 0;
166
+ const drawings = tryExtractDrawingFromParagraph(child, ctx);
167
+ if (drawings) out.push(...drawings);
168
+ else {
169
+ out.push({
170
+ kind: "paragraph",
171
+ paragraph: parseParagraph(child, ctx, pendingBookmarks)
172
+ });
173
+ pendingBookmarks = void 0;
174
+ }
171
175
  } else if (poIs(child, "w:tbl")) out.push({
172
176
  kind: "table",
173
177
  table: parseTable(child, ctx)
@@ -220,7 +224,7 @@ function tryExtractDrawingFromParagraph(p, ctx) {
220
224
  const paragraphProperties = pPrNode ? parseParagraphProperties(poElementToFlat(pPrNode)) : {};
221
225
  if (content.kind === "image") {
222
226
  const resource = ctx.resolveImage?.(content.imageId);
223
- return {
227
+ return [{
224
228
  kind: "image",
225
229
  image: {
226
230
  ...resource ? { resource } : {},
@@ -230,9 +234,9 @@ function tryExtractDrawingFromParagraph(p, ctx) {
230
234
  ...content.altText ? { altText: content.altText } : {},
231
235
  ...content.float ? { float: content.float } : {}
232
236
  }
233
- };
237
+ }];
234
238
  }
235
- if (content.kind === "chart") return {
239
+ if (content.kind === "chart") return [{
236
240
  kind: "chart",
237
241
  chart: {
238
242
  chartRelId: content.chartRelId,
@@ -242,8 +246,35 @@ function tryExtractDrawingFromParagraph(p, ctx) {
242
246
  ...content.altText ? { altText: content.altText } : {},
243
247
  ...content.float ? { float: content.float } : {}
244
248
  }
245
- };
246
- return {
249
+ }];
250
+ if (content.kind === "diagram") {
251
+ const spTree = ctx.resolveDiagram?.(content.dmRelId);
252
+ if (!spTree) {
253
+ ctx.onLoss?.(noDiagramOverrideLoss());
254
+ return null;
255
+ }
256
+ const shapes = parseDiagramDrawing(spTree, diagramTransform(spTree, {
257
+ x: 0,
258
+ y: 0,
259
+ cx: content.widthEmu,
260
+ cy: content.heightEmu
261
+ }), (box) => ({
262
+ wrap: "none",
263
+ posH: {
264
+ relativeFrom: "column",
265
+ offsetPt: emuToPt(box.x)
266
+ },
267
+ posV: {
268
+ relativeFrom: "paragraph",
269
+ offsetPt: emuToPt(box.y)
270
+ }
271
+ }), ctx.resolveColor, void 0);
272
+ return shapes.length > 0 ? shapes.map((shape) => ({
273
+ kind: "shape",
274
+ shape
275
+ })) : null;
276
+ }
277
+ return [{
247
278
  kind: "shape",
248
279
  shape: {
249
280
  ...content.data,
@@ -251,7 +282,7 @@ function tryExtractDrawingFromParagraph(p, ctx) {
251
282
  ...content.altText ? { altText: content.altText } : {},
252
283
  ...content.float ? { float: content.float } : {}
253
284
  }
254
- };
285
+ }];
255
286
  }
256
287
  function parseParagraph(p, ctx, extraBookmarks) {
257
288
  const bookmarks = [...extraBookmarks ?? []];
@@ -349,12 +380,24 @@ function applyFieldFsm(collected) {
349
380
  function collectRuns(container, out, ctx, href, anchor) {
350
381
  for (const child of poChildren(container)) {
351
382
  if (poIs(child, "w:pPr")) continue;
383
+ if (poIs(child, "w:commentRangeStart")) {
384
+ const id = poAttr(child, "id");
385
+ if (id !== void 0) ctx.openCommentRanges?.add(id);
386
+ continue;
387
+ }
388
+ if (poIs(child, "w:commentRangeEnd")) {
389
+ const id = poAttr(child, "id");
390
+ if (id !== void 0) ctx.openCommentRanges?.delete(id);
391
+ continue;
392
+ }
352
393
  if (poIs(child, "w:r")) {
353
394
  const parsed = parseRun(child, ctx);
354
- const run = href !== void 0 || anchor !== void 0 ? {
395
+ const ranges = ctx.openCommentRanges && ctx.openCommentRanges.size > 0 ? [...ctx.openCommentRanges] : void 0;
396
+ const run = href !== void 0 || anchor !== void 0 || ranges !== void 0 ? {
355
397
  ...parsed.run,
356
398
  ...href !== void 0 ? { href } : {},
357
- ...anchor !== void 0 ? { anchor } : {}
399
+ ...anchor !== void 0 ? { anchor } : {},
400
+ ...ranges !== void 0 ? { commentRangeRefs: ranges } : {}
358
401
  } : parsed.run;
359
402
  out.push({
360
403
  run,
@@ -417,6 +460,7 @@ function parseRun(r, ctx) {
417
460
  let instrText;
418
461
  let footnoteRef;
419
462
  let endnoteRef;
463
+ let commentRef;
420
464
  let noteNumber = false;
421
465
  for (const child of expandMcChildren(poChildren(r))) {
422
466
  if (poIs(child, "w:rPr")) continue;
@@ -439,6 +483,11 @@ function parseRun(r, ctx) {
439
483
  if (id !== void 0) endnoteRef = id;
440
484
  continue;
441
485
  }
486
+ if (poIs(child, "w:commentReference")) {
487
+ const id = poAttr(child, "id");
488
+ if (id !== void 0) commentRef = id;
489
+ continue;
490
+ }
442
491
  if (poIs(child, "w:footnoteRef") || poIs(child, "w:endnoteRef")) {
443
492
  noteNumber = true;
444
493
  continue;
@@ -479,6 +528,7 @@ function parseRun(r, ctx) {
479
528
  ...pageBreak ? { pageBreak: true } : {},
480
529
  ...footnoteRef !== void 0 ? { footnoteRef } : {},
481
530
  ...endnoteRef !== void 0 ? { endnoteRef } : {},
531
+ ...commentRef !== void 0 ? { commentRef } : {},
482
532
  ...noteNumber ? { noteNumber: true } : {}
483
533
  },
484
534
  ...fldChar ? { fldChar } : {},
@@ -503,5 +553,115 @@ function parseNotes(notesXml, rootTag, noteTag, ctx = DEFAULT_PARSE_CONTEXT) {
503
553
  }
504
554
  return out;
505
555
  }
556
+ function parseCommentsRaw(commentsXml, ctx) {
557
+ const xml = decoder.decode(commentsXml);
558
+ const root = poFindByPath(parser.parse(xml), ["w:comments"]);
559
+ const comments = /* @__PURE__ */ new Map();
560
+ const paraIds = /* @__PURE__ */ new Map();
561
+ if (!root) return {
562
+ comments,
563
+ paraIds
564
+ };
565
+ for (const c of poChildren(root)) {
566
+ if (!poIs(c, "w:comment")) continue;
567
+ const id = poAttr(c, "id");
568
+ if (id === void 0) continue;
569
+ const author = poAttr(c, "author");
570
+ const initials = poAttr(c, "initials");
571
+ const date = poAttr(c, "date");
572
+ comments.set(id, {
573
+ content: parseBodyElements(poChildren(c), ctx),
574
+ ...author !== void 0 ? { author } : {},
575
+ ...initials !== void 0 ? { initials } : {},
576
+ ...date !== void 0 ? { date } : {}
577
+ });
578
+ let paraId;
579
+ for (const child of poChildren(c)) {
580
+ if (!poIs(child, "w:p")) continue;
581
+ const pid = poAttrLocal(child, "paraId");
582
+ if (pid !== void 0) paraId = pid;
583
+ }
584
+ if (paraId !== void 0) paraIds.set(id, paraId);
585
+ }
586
+ return {
587
+ comments,
588
+ paraIds
589
+ };
590
+ }
591
+ function parseCommentsExtended(xml) {
592
+ const tree = parser.parse(decoder.decode(xml));
593
+ const out = /* @__PURE__ */ new Map();
594
+ const root = tree.find((n) => poIsLocal(n, "commentsEx"));
595
+ if (!root) return out;
596
+ for (const ex of poChildren(root)) {
597
+ if (!poIsLocal(ex, "commentEx")) continue;
598
+ const paraId = poAttrLocal(ex, "paraId");
599
+ if (paraId === void 0) continue;
600
+ const paraIdParent = poAttrLocal(ex, "paraIdParent");
601
+ const done = poAttrLocal(ex, "done");
602
+ out.set(paraId, {
603
+ ...paraIdParent !== void 0 ? { paraIdParent } : {},
604
+ done: done === "1" || done === "true"
605
+ });
606
+ }
607
+ return out;
608
+ }
609
+ function linkCommentThreads(comments, paraIdByComment, ext) {
610
+ if (ext.size === 0) return comments;
611
+ const commentByParaId = /* @__PURE__ */ new Map();
612
+ for (const [id, pid] of paraIdByComment) commentByParaId.set(pid, id);
613
+ const out = /* @__PURE__ */ new Map();
614
+ for (const [id, c] of comments) {
615
+ const pid = paraIdByComment.get(id);
616
+ const e = pid !== void 0 ? ext.get(pid) : void 0;
617
+ if (!e) {
618
+ out.set(id, c);
619
+ continue;
620
+ }
621
+ const parentId = e.paraIdParent !== void 0 ? commentByParaId.get(e.paraIdParent) : void 0;
622
+ out.set(id, {
623
+ ...c,
624
+ ...parentId !== void 0 ? { parentId } : {},
625
+ ...e.done ? { done: true } : {}
626
+ });
627
+ }
628
+ return out;
629
+ }
630
+ function parseCommentThreads(commentsXml, commentsExtendedXml, ctx = DEFAULT_PARSE_CONTEXT) {
631
+ const { comments, paraIds } = parseCommentsRaw(commentsXml, ctx);
632
+ if (!commentsExtendedXml) return comments;
633
+ return linkCommentThreads(comments, paraIds, parseCommentsExtended(commentsExtendedXml));
634
+ }
635
+ function parsePeople(xml) {
636
+ const tree = parser.parse(decoder.decode(xml));
637
+ const out = /* @__PURE__ */ new Map();
638
+ const root = tree.find((n) => poIsLocal(n, "people"));
639
+ if (!root) return out;
640
+ for (const person of poChildren(root)) {
641
+ if (!poIsLocal(person, "person")) continue;
642
+ const author = poAttrLocal(person, "author");
643
+ if (author === void 0) continue;
644
+ let userId;
645
+ for (const child of poChildren(person)) {
646
+ if (!poIsLocal(child, "presenceInfo")) continue;
647
+ const uid = poAttrLocal(child, "userId");
648
+ if (uid !== void 0) userId = uid;
649
+ }
650
+ if (userId !== void 0) out.set(author, userId);
651
+ }
652
+ return out;
653
+ }
654
+ function applyAuthorIds(comments, people) {
655
+ if (people.size === 0) return comments;
656
+ const out = /* @__PURE__ */ new Map();
657
+ for (const [id, c] of comments) {
658
+ const userId = c.author !== void 0 ? people.get(c.author) : void 0;
659
+ out.set(id, userId !== void 0 ? {
660
+ ...c,
661
+ authorId: userId
662
+ } : c);
663
+ }
664
+ return out;
665
+ }
506
666
  //#endregion
507
- export { DEFAULT_PARSE_CONTEXT, EMPTY_SECTION, parseBodyElements, parseDocument, parseHeaderFooter, parseNotes, parseSections };
667
+ export { DEFAULT_PARSE_CONTEXT, EMPTY_SECTION, applyAuthorIds, parseBodyElements, parseCommentThreads, parseCommentsExtended, parseDocument, parseHeaderFooter, parseNotes, parsePeople, parseSections };
@@ -4,6 +4,7 @@ import { applyNumbering, applyNumberingToHeadersFooters } from "../core/numberin
4
4
  import { EMPTY_STYLE_SHEET, resolveBodyStyles, resolveHeadersFootersStyles } from "../core/style-cascade/resolver.js";
5
5
  import { resolveTableStyles } from "../core/style-cascade/table.js";
6
6
  import "../core/style-cascade/index.js";
7
+ import { poFindDescendant } from "../core/po-helpers.js";
7
8
  import { bytesInclude } from "../core/bytes.js";
8
9
  import { DEFAULT_THEME_PALETTE, makeColorResolver } from "../core/drawingml/colors.js";
9
10
  import { parseChart, withChartColorStyle } from "../core/drawingml/chart-parser.js";
@@ -12,7 +13,8 @@ import { isOoxmlRel } from "../core/opc/relationship-types.js";
12
13
  import { OpcPackage } from "../core/opc/package.js";
13
14
  import { parseCoreProperties } from "../core/opc/core-properties.js";
14
15
  import "../core/opc/index.js";
15
- import { EMPTY_SECTION, parseDocument, parseHeaderFooter, parseNotes, parseSections } from "./document-parser.js";
16
+ import { parseXml } from "../pptx/pptx-reader.js";
17
+ import { EMPTY_SECTION, applyAuthorIds, parseCommentThreads, parseDocument, parseHeaderFooter, parseNotes, parsePeople, parseSections } from "./document-parser.js";
16
18
  import { parseStyles } from "./styles-parser.js";
17
19
  import { loadEmbeddedFonts } from "./font-table.js";
18
20
  import { EMPTY_NUMBERING, parseNumbering } from "./numbering-parser.js";
@@ -22,6 +24,9 @@ import "./index.js";
22
24
  var STYLES_PART = "word/styles.xml";
23
25
  var FOOTNOTES_PART = "word/footnotes.xml";
24
26
  var ENDNOTES_PART = "word/endnotes.xml";
27
+ var COMMENTS_PART = "word/comments.xml";
28
+ var COMMENTS_EXTENDED_PART = "word/commentsExtended.xml";
29
+ var PEOPLE_PART = "word/people.xml";
25
30
  var NUMBERING_PART = "word/numbering.xml";
26
31
  var SETTINGS_PART = "word/settings.xml";
27
32
  var CORE_PROPS_PART = "docProps/core.xml";
@@ -33,10 +38,16 @@ function readDocx(docx) {
33
38
  const main = pkg.getMainDocument();
34
39
  const resolveColor = buildColorResolver(pkg);
35
40
  const resources = new ResourceStore();
41
+ const resolveImage = makeImageResolver(pkg, resources);
42
+ const resolveHyperlink = makeHyperlinkResolver(pkg);
43
+ const losses = [];
36
44
  const ctx = {
37
45
  resolveColor,
38
- resolveImage: makeImageResolver(pkg, resources),
39
- resolveHyperlink: makeHyperlinkResolver(pkg)
46
+ resolveImage,
47
+ resolveHyperlink,
48
+ resolveDiagram: makeDiagramResolver(pkg, MAIN_DOCUMENT_PART),
49
+ onLoss: (loss) => losses.push(loss),
50
+ openCommentRanges: /* @__PURE__ */ new Set()
40
51
  };
41
52
  const body = parseDocument(main.data, ctx);
42
53
  const rawSections = parseSections(main.data);
@@ -53,6 +64,11 @@ function readDocx(docx) {
53
64
  const rawFootnotes = footnotesData ? parseNotes(footnotesData, "w:footnotes", "w:footnote", noteCtx(FOOTNOTES_PART)) : void 0;
54
65
  const endnotesData = pkg.getPart(ENDNOTES_PART);
55
66
  const rawEndnotes = endnotesData ? parseNotes(endnotesData, "w:endnotes", "w:endnote", noteCtx(ENDNOTES_PART)) : void 0;
67
+ const commentsData = pkg.getPart(COMMENTS_PART);
68
+ const commentsExtendedData = pkg.getPart(COMMENTS_EXTENDED_PART);
69
+ const peopleData = pkg.getPart(PEOPLE_PART);
70
+ let rawComments = commentsData ? parseCommentThreads(commentsData, commentsExtendedData, noteCtx(COMMENTS_PART)) : void 0;
71
+ if (rawComments && peopleData) rawComments = applyAuthorIds(rawComments, parsePeople(peopleData));
56
72
  const settingsData = pkg.getPart(SETTINGS_PART);
57
73
  const settings = settingsData ? parseSettings(settingsData) : EMPTY_SETTINGS;
58
74
  const sections = rawSections.length > 0 ? rawSections.map((s) => ({
@@ -83,6 +99,7 @@ function readDocx(docx) {
83
99
  numbering,
84
100
  ...rawFootnotes && rawFootnotes.size > 0 ? { footnotes: transformNotes(rawFootnotes, styles, numbering) } : {},
85
101
  ...rawEndnotes && rawEndnotes.size > 0 ? { endnotes: transformNotes(rawEndnotes, styles, numbering) } : {},
102
+ ...rawComments && rawComments.size > 0 ? { comments: transformComments(rawComments, styles, numbering) } : {},
86
103
  headersFooters: resolveHeadersFootersStyles(applyNumberingToHeadersFooters(headersFooters, numbering), styles),
87
104
  charts,
88
105
  resources,
@@ -90,7 +107,7 @@ function readDocx(docx) {
90
107
  ...info ? { info } : {},
91
108
  ...language ? { language } : {}
92
109
  },
93
- losses: []
110
+ losses
94
111
  };
95
112
  }
96
113
  var docxReader = {
@@ -125,6 +142,28 @@ function infoFromCore(core) {
125
142
  ...core.modified ? { modificationDate: core.modified } : {}
126
143
  };
127
144
  }
145
+ function makeDiagramResolver(pkg, partName) {
146
+ const cache = /* @__PURE__ */ new Map();
147
+ return (relId) => {
148
+ if (cache.has(relId)) return cache.get(relId);
149
+ let spTree;
150
+ const dataRel = pkg.getPartRelationships(partName).find((r) => r.id === relId);
151
+ const data = dataRel ? pkg.resolveRelatedPart(partName, dataRel) : void 0;
152
+ if (data) {
153
+ const drawRel = pkg.getPartRelationships(data.path).find((r) => r.type.endsWith("/diagramDrawing"));
154
+ const draw = drawRel ? pkg.resolveRelatedPart(data.path, drawRel) : void 0;
155
+ if (draw) for (const root of parseXml(draw.data)) {
156
+ const found = poFindDescendant(root, "dsp:spTree");
157
+ if (found) {
158
+ spTree = found;
159
+ break;
160
+ }
161
+ }
162
+ }
163
+ cache.set(relId, spTree);
164
+ return spTree;
165
+ };
166
+ }
128
167
  function makeImageResolver(pkg, store, partName = MAIN_DOCUMENT_PART) {
129
168
  const byRelId = /* @__PURE__ */ new Map();
130
169
  for (const rel of pkg.getPartRelationships(partName)) {
@@ -145,6 +184,17 @@ function transformNotes(notes, styles, numbering) {
145
184
  for (const content of notes.values()) resolveTableStyles(content, styles);
146
185
  return resolveHeadersFootersStyles(applyNumberingToHeadersFooters(notes, numbering), styles);
147
186
  }
187
+ function transformComments(comments, styles, numbering) {
188
+ const contentById = /* @__PURE__ */ new Map();
189
+ for (const [id, c] of comments) contentById.set(id, [...c.content]);
190
+ const transformed = transformNotes(contentById, styles, numbering);
191
+ const out = /* @__PURE__ */ new Map();
192
+ for (const [id, c] of comments) out.set(id, {
193
+ ...c,
194
+ content: transformed.get(id) ?? c.content
195
+ });
196
+ return out;
197
+ }
148
198
  function makeHyperlinkResolver(pkg, partName = MAIN_DOCUMENT_PART) {
149
199
  const byRelId = /* @__PURE__ */ new Map();
150
200
  for (const rel of pkg.getPartRelationships(partName)) if (rel.type === REL_HYPERLINK && rel.targetMode === "External") byRelId.set(rel.id, rel.target);
@@ -49,7 +49,7 @@ function prepareDocxStyledRender(docx, options) {
49
49
  };
50
50
  }
51
51
  function detectDocxFamilyKeys(docx) {
52
- const keys = new Set(["roboto"]);
52
+ const keys = new Set(["arimo"]);
53
53
  let pkg;
54
54
  try {
55
55
  pkg = OpcPackage.open(docx);
@@ -111,7 +111,7 @@ async function resolveDocxAutoFonts(docx, options = {}) {
111
111
  ...fetchOpt
112
112
  });
113
113
  registriesByFamily.set(key, FontRegistry.fromBytes(bytes));
114
- if (key === "roboto" || !baseBytes) baseBytes = bytes;
114
+ if (key === "arimo" || !baseBytes) baseBytes = bytes;
115
115
  }
116
116
  return {
117
117
  fonts: baseBytes,