reamkit 1.11.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 (32) hide show
  1. package/dist/esm/core/converter/facade.js +1 -1
  2. package/dist/esm/core/converter/project.js +1 -0
  3. package/dist/esm/core/document-model/index.d.ts +1 -1
  4. package/dist/esm/core/document-model/types.d.ts +23 -0
  5. package/dist/esm/core/ir/features.d.ts +1 -0
  6. package/dist/esm/core/ir/features.js +1 -0
  7. package/dist/esm/core/ir/flow.d.ts +3 -1
  8. package/dist/esm/core/po-helpers.d.ts +2 -0
  9. package/dist/esm/core/po-helpers.js +14 -1
  10. package/dist/esm/core/spreadsheet-model/index.d.ts +1 -1
  11. package/dist/esm/core/spreadsheet-model/types.d.ts +16 -0
  12. package/dist/esm/excel/pivot-table-parser.d.ts +2 -0
  13. package/dist/esm/excel/pivot-table-parser.js +68 -0
  14. package/dist/esm/excel/print-model.js +28 -6
  15. package/dist/esm/excel/xlsx-reader.js +33 -2
  16. package/dist/esm/html/html-writer.js +52 -2
  17. package/dist/esm/layout/page-doc.d.ts +1 -0
  18. package/dist/esm/layout/styled-layout.d.ts +8 -1
  19. package/dist/esm/layout/styled-layout.js +111 -5
  20. package/dist/esm/pdf/styled-page-emitter.js +38 -0
  21. package/dist/esm/pptx/pptx-reader.d.ts +2 -0
  22. package/dist/esm/pptx/pptx-reader.js +30 -3
  23. package/dist/esm/pptx/slide-parser.d.ts +8 -2
  24. package/dist/esm/pptx/slide-parser.js +80 -12
  25. package/dist/esm/word/document-parser.d.ts +17 -2
  26. package/dist/esm/word/document-parser.js +178 -18
  27. package/dist/esm/word/docx-reader.js +54 -4
  28. package/dist/esm/word/docx-writer.js +84 -1
  29. package/dist/esm/word/drawing-parser.d.ts +7 -0
  30. package/dist/esm/word/drawing-parser.js +13 -0
  31. package/dist/esm/word/index.d.ts +2 -1
  32. package/package.json +1 -1
@@ -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);
@@ -23,6 +23,14 @@ var FOOTNOTES_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.word
23
23
  var ENDNOTES_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml";
24
24
  var FOOTNOTES_PART = "word/footnotes.xml";
25
25
  var ENDNOTES_PART = "word/endnotes.xml";
26
+ var REL_COMMENTS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
27
+ var COMMENTS_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml";
28
+ var COMMENTS_PART = "word/comments.xml";
29
+ var REL_COMMENTS_EXTENDED = "http://schemas.microsoft.com/office/2011/relationships/commentsExtended";
30
+ var COMMENTS_EXTENDED_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml";
31
+ var COMMENTS_EXTENDED_PART = "word/commentsExtended.xml";
32
+ var W14_NS = "http://schemas.microsoft.com/office/word/2010/wordml";
33
+ var W15_NS = "http://schemas.microsoft.com/office/word/2012/wordml";
26
34
  var REL_CHART = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart";
27
35
  var CHART_CONTENT_TYPE = "application/vnd.openxmlformats-officedocument.drawingml.chart+xml";
28
36
  var EMU_PER_PT = 12700;
@@ -143,6 +151,8 @@ function writeDocx(flow) {
143
151
  relType: REL_ENDNOTES,
144
152
  target: "endnotes.xml"
145
153
  }, state, losses, docScope, extraParts, extraPartRels);
154
+ const commentParaIds = emitComments(flow.comments, state, losses, docScope, extraParts, extraPartRels);
155
+ emitCommentsExtended(flow.comments, commentParaIds, docScope, extraParts);
146
156
  const partRelationships = [...docScope.rels.length > 0 ? [{
147
157
  sourcePart: "word/document.xml",
148
158
  relationships: docScope.rels
@@ -199,6 +209,78 @@ function emitNotes(notes, cfg, state, losses, docScope, extraParts, extraPartRel
199
209
  targetMode: "Internal"
200
210
  });
201
211
  }
212
+ function paraIdFor(commentId) {
213
+ let h = 2166136261;
214
+ for (let i = 0; i < commentId.length; i++) {
215
+ h ^= commentId.charCodeAt(i);
216
+ h = Math.imul(h, 16777619);
217
+ }
218
+ return (h >>> 0 || 1).toString(16).toUpperCase().padStart(8, "0");
219
+ }
220
+ var PARA_OPEN = "<w:p>";
221
+ function injectParaId(paragraphXmlString, paraId) {
222
+ return paragraphXmlString.startsWith(PARA_OPEN) ? `<w:p w14:paraId="${paraId}">` + paragraphXmlString.slice(5) : paragraphXmlString;
223
+ }
224
+ function emitComments(comments, state, losses, docScope, extraParts, extraPartRels) {
225
+ const paraIds = /* @__PURE__ */ new Map();
226
+ if (!comments || comments.size === 0) return paraIds;
227
+ const scope = newScope();
228
+ const commentXmls = [];
229
+ for (const [id, c] of comments) {
230
+ let lastParaIdx = -1;
231
+ for (let i = 0; i < c.content.length; i++) if (c.content[i].kind === "paragraph") lastParaIdx = i;
232
+ const paraId = lastParaIdx >= 0 ? paraIdFor(id) : void 0;
233
+ const inner = [];
234
+ for (let i = 0; i < c.content.length; i++) if (i === lastParaIdx && paraId !== void 0) {
235
+ const buf = [];
236
+ emitBlock(buf, c.content[i], losses, state, scope);
237
+ inner.push(injectParaId(buf.join(""), paraId));
238
+ } else emitBlock(inner, c.content[i], losses, state, scope);
239
+ if (paraId !== void 0) paraIds.set(id, paraId);
240
+ const attrs = `w:id="${escapeAttr(id)}"` + (c.author !== void 0 ? ` w:author="${escapeAttr(c.author)}"` : "") + (c.date !== void 0 ? ` w:date="${escapeAttr(c.date)}"` : "") + (c.initials !== void 0 ? ` w:initials="${escapeAttr(c.initials)}"` : "");
241
+ commentXmls.push(`<w:comment ${attrs}>${inner.join("") || "<w:p/>"}</w:comment>`);
242
+ }
243
+ const xml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w:comments xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:w14="${W14_NS}">` + commentXmls.join("") + "</w:comments>";
244
+ extraParts.push({
245
+ path: COMMENTS_PART,
246
+ data: encoder.encode(xml),
247
+ contentType: COMMENTS_CONTENT_TYPE
248
+ });
249
+ if (scope.rels.length > 0) extraPartRels.push({
250
+ sourcePart: COMMENTS_PART,
251
+ relationships: scope.rels
252
+ });
253
+ docScope.rels.push({
254
+ id: `rId${++docScope.relSeq}`,
255
+ type: REL_COMMENTS,
256
+ target: "comments.xml",
257
+ targetMode: "Internal"
258
+ });
259
+ return paraIds;
260
+ }
261
+ function emitCommentsExtended(comments, paraIds, docScope, extraParts) {
262
+ if (!comments || paraIds.size === 0) return;
263
+ if (![...comments].some(([id, c]) => paraIds.has(id) && (c.parentId !== void 0 && paraIds.has(c.parentId) || c.done === true))) return;
264
+ const rows = [];
265
+ for (const [id, c] of comments) {
266
+ const pid = paraIds.get(id);
267
+ if (pid === void 0) continue;
268
+ const parentPid = c.parentId !== void 0 ? paraIds.get(c.parentId) : void 0;
269
+ rows.push(`<w15:commentEx w15:paraId="${pid}"` + (parentPid !== void 0 ? ` w15:paraIdParent="${parentPid}"` : "") + ` w15:done="${c.done === true ? "1" : "0"}"/>`);
270
+ }
271
+ const xml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?><w15:commentsEx xmlns:w15="${W15_NS}">` + rows.join("") + "</w15:commentsEx>";
272
+ extraParts.push({
273
+ path: COMMENTS_EXTENDED_PART,
274
+ data: encoder.encode(xml),
275
+ contentType: COMMENTS_EXTENDED_CONTENT_TYPE
276
+ });
277
+ docScope.rels.push({
278
+ id: `rId${++docScope.relSeq}`,
279
+ type: REL_COMMENTS_EXTENDED,
280
+ target: "commentsExtended.xml",
281
+ targetMode: "Internal"
282
+ });
283
+ }
202
284
  function emitHeadersFooters(flow, section, state, docScope, extraParts, extraPartRels, hfCache, losses) {
203
285
  const refs = {
204
286
  headers: [],
@@ -494,7 +576,7 @@ function cellMarginsXml(tag, margins) {
494
576
  return inner ? `<${tag}>${inner}</${tag}>` : "";
495
577
  }
496
578
  function paragraphXml(p, state, scope, closingSectPr) {
497
- const visible = p.runs.filter((run) => !run.listMarker && (run.math !== void 0 || run.text !== "" || run.inlineImage !== void 0 || run.pageBreak || run.footnoteRef !== void 0 || run.endnoteRef !== void 0 || run.noteNumber === true || run.href !== void 0 || run.anchor !== void 0));
579
+ const visible = p.runs.filter((run) => !run.listMarker && (run.math !== void 0 || run.text !== "" || run.inlineImage !== void 0 || run.pageBreak || run.footnoteRef !== void 0 || run.endnoteRef !== void 0 || run.noteNumber === true || run.commentRef !== void 0 || run.href !== void 0 || run.anchor !== void 0));
498
580
  const inner = [];
499
581
  let i = 0;
500
582
  while (i < visible.length) {
@@ -543,6 +625,7 @@ function runXml(run, state, scope) {
543
625
  if (run.footnoteRef !== void 0) return `<w:r>${rPr}<w:footnoteReference w:id="${escapeAttr(run.footnoteRef)}"/></w:r>`;
544
626
  if (run.endnoteRef !== void 0) return `<w:r>${rPr}<w:endnoteReference w:id="${escapeAttr(run.endnoteRef)}"/></w:r>`;
545
627
  if (run.noteNumber) return `<w:r>${rPr}<${scope.noteKind === "endnote" ? "w:endnoteRef" : "w:footnoteRef"}/></w:r>`;
628
+ if (run.commentRef !== void 0) return `<w:r>${rPr}<w:commentReference w:id="${escapeAttr(run.commentRef)}"/></w:r>`;
546
629
  const brk = run.pageBreak ? "<w:br w:type=\"page\"/>" : "";
547
630
  if (run.text === "") return brk ? `<w:r>${rPr}${brk}</w:r>` : "";
548
631
  return `<w:r>${rPr}<w:t xml:space="preserve">${escapeXml(run.text)}</w:t>${brk}</w:r>`;
@@ -31,6 +31,13 @@ export type DrawingContent = {
31
31
  readonly height: Pt;
32
32
  readonly altText?: string;
33
33
  readonly float?: FloatAnchor;
34
+ } | {
35
+ readonly kind: 'diagram';
36
+ readonly dmRelId: string;
37
+ readonly widthEmu: number;
38
+ readonly heightEmu: number;
39
+ readonly altText?: string;
40
+ readonly float?: FloatAnchor;
34
41
  };
35
42
  export declare function resolveMc(altContent: PoNode): ReadonlyArray<PoNode>;
36
43
  export declare function expandMcChildren(children: ReadonlyArray<PoNode>): Array<PoNode>;
@@ -4,6 +4,7 @@ import { resolveColorNode } from "../core/drawingml/colors.js";
4
4
  //#region src/word/drawing-parser.ts
5
5
  var WPS_URI = "http://schemas.microsoft.com/office/word/2010/wordprocessingShape";
6
6
  var CHART_URI = "http://schemas.openxmlformats.org/drawingml/2006/chart";
7
+ var DIAGRAM_URI = "http://schemas.openxmlformats.org/drawingml/2006/diagram";
7
8
  var UNDERSTOOD_NS = new Set(["wps"]);
8
9
  function parseFloatAnchor(anchor) {
9
10
  if (!poIs(anchor, "wp:anchor")) return void 0;
@@ -104,6 +105,18 @@ function parseDrawing(drawing, resolveColor, parseBody) {
104
105
  };
105
106
  return null;
106
107
  }
108
+ if (graphicData && uri === DIAGRAM_URI) {
109
+ const relIds = poFindDescendant(graphicData, "dgm:relIds");
110
+ const dmRelId = relIds ? poAttr(relIds, "dm") : void 0;
111
+ if (dmRelId && extentCx !== void 0 && extentCy !== void 0) return {
112
+ kind: "diagram",
113
+ dmRelId,
114
+ widthEmu: extentCx,
115
+ heightEmu: extentCy,
116
+ ...alt
117
+ };
118
+ return null;
119
+ }
107
120
  const blip = poFindDescendant(anchor, "a:blip");
108
121
  const rId = blip ? poAttr(blip, "embed") : void 0;
109
122
  if (extentCx !== void 0 && extentCy !== void 0 && rId) return {
@@ -1,6 +1,7 @@
1
1
  export type { HyperlinkResolver, ImageResolver, ParseContext } from './document-parser.js';
2
+ export type { CommentExtension } from './document-parser.js';
2
3
  export { extractParagraphs } from './text-extractor.js';
3
- export { parseDocument, parseBodyElements, parseSection, parseSections, parseHeaderFooter, parseNotes, EMPTY_SECTION, } from './document-parser.js';
4
+ export { parseDocument, parseBodyElements, parseSection, parseSections, parseHeaderFooter, parseNotes, parseComments, parseCommentThreads, parseCommentsExtended, parsePeople, applyAuthorIds, EMPTY_SECTION, } from './document-parser.js';
4
5
  export { parseRunProperties } from './run-properties.js';
5
6
  export { parseParagraphProperties } from './paragraph-properties.js';
6
7
  export { parseStyles } from './styles-parser.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reamkit",
3
- "version": "1.11.0",
3
+ "version": "1.12.0",
4
4
  "description": "Ream — convert DOCX, XLSX, PPTX and PDF to PDF, SVG, HTML, DOCX and XLSX, built from scratch on the ECMA-376 and ISO 32000 specifications. Parse once, convert anywhere.",
5
5
  "license": "MIT",
6
6
  "author": "Alex Krassavin <info@reamkit.dev>",