@docx4j/core-ts 0.4.0 → 0.6.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 (166) hide show
  1. package/NOTICE +4 -0
  2. package/README.md +34 -3
  3. package/dist/html/convert.mjs +40 -15
  4. package/dist/html/elements.mjs +2 -1
  5. package/dist/model/color/ColorMath.d.mts +29 -0
  6. package/dist/model/color/ColorMath.mjs +146 -0
  7. package/dist/model/color/ColorTables.d.mts +6 -0
  8. package/dist/model/color/ColorTables.mjs +83 -0
  9. package/dist/model/color/DrawingMLColors.d.mts +52 -0
  10. package/dist/model/color/DrawingMLColors.mjs +374 -0
  11. package/dist/model/color/ResolvedColor.d.mts +36 -0
  12. package/dist/model/color/ResolvedColor.mjs +65 -0
  13. package/dist/model/color/SpreadsheetColors.d.mts +36 -0
  14. package/dist/model/color/SpreadsheetColors.mjs +84 -0
  15. package/dist/model/color/StyleFill.d.mts +28 -0
  16. package/dist/model/color/StyleFill.mjs +21 -0
  17. package/dist/model/color/ThemeColors.d.mts +86 -0
  18. package/dist/model/color/ThemeColors.mjs +304 -0
  19. package/dist/model/color/WordColors.d.mts +71 -0
  20. package/dist/model/color/WordColors.mjs +121 -0
  21. package/dist/model/color/index.d.mts +6 -0
  22. package/dist/model/color/index.mjs +30 -0
  23. package/dist/model/content/Body.d.mts +153 -19
  24. package/dist/model/content/Body.mjs +570 -131
  25. package/dist/model/content/Comment.d.mts +21 -3
  26. package/dist/model/content/Comment.mjs +202 -19
  27. package/dist/model/content/ContentControl.d.mts +197 -18
  28. package/dist/model/content/ContentControl.mjs +664 -95
  29. package/dist/model/content/Font.d.mts +67 -17
  30. package/dist/model/content/Font.mjs +114 -35
  31. package/dist/model/content/InlinePicture.d.mts +82 -7
  32. package/dist/model/content/InlinePicture.mjs +221 -28
  33. package/dist/model/content/List.mjs +13 -1
  34. package/dist/model/content/Paragraph.d.mts +213 -14
  35. package/dist/model/content/Paragraph.mjs +936 -100
  36. package/dist/model/content/Range.d.mts +242 -11
  37. package/dist/model/content/Range.mjs +975 -119
  38. package/dist/model/content/ResolvedView.d.mts +104 -0
  39. package/dist/model/content/ResolvedView.mjs +596 -0
  40. package/dist/model/content/Table.d.mts +29 -3
  41. package/dist/model/content/Table.mjs +109 -33
  42. package/dist/model/content/TrackedChange.d.mts +301 -16
  43. package/dist/model/content/TrackedChange.mjs +1284 -158
  44. package/dist/model/content/binder.d.mts +2 -1
  45. package/dist/model/content/binder.mjs +48 -1
  46. package/dist/model/content/comments.d.mts +20 -6
  47. package/dist/model/content/comments.mjs +67 -57
  48. package/dist/model/content/generalException.d.mts +18 -0
  49. package/dist/model/content/generalException.mjs +24 -0
  50. package/dist/model/content/index.d.mts +8 -3
  51. package/dist/model/content/index.mjs +7 -2
  52. package/dist/model/content/mathText.d.mts +21 -0
  53. package/dist/model/content/mathText.mjs +267 -0
  54. package/dist/model/content/officeText.d.mts +27 -0
  55. package/dist/model/content/officeText.mjs +74 -0
  56. package/dist/model/content/outline.d.mts +5 -0
  57. package/dist/model/content/outline.mjs +13 -0
  58. package/dist/model/content/placeholders.d.mts +110 -0
  59. package/dist/model/content/placeholders.mjs +253 -0
  60. package/dist/model/content/relationships.d.mts +30 -0
  61. package/dist/model/content/relationships.mjs +133 -0
  62. package/dist/model/content/search.d.mts +72 -0
  63. package/dist/model/content/search.mjs +204 -2
  64. package/dist/model/content/spanEdits.d.mts +159 -0
  65. package/dist/model/content/spanEdits.mjs +728 -0
  66. package/dist/model/content/story.d.mts +44 -0
  67. package/dist/model/content/story.mjs +92 -0
  68. package/dist/model/content/tableColumns.d.mts +1 -1
  69. package/dist/model/content/tableColumns.mjs +108 -80
  70. package/dist/model/content/tableRevisions.d.mts +11 -3
  71. package/dist/model/content/tableRevisions.mjs +72 -42
  72. package/dist/model/content/tableRules.d.mts +30 -0
  73. package/dist/model/content/tableRules.mjs +100 -0
  74. package/dist/model/content/textBoxes.d.mts +18 -0
  75. package/dist/model/content/textBoxes.mjs +105 -0
  76. package/dist/model/content/trackedChangeFilter.d.mts +39 -0
  77. package/dist/model/content/trackedChangeFilter.mjs +81 -0
  78. package/dist/model/content/tracking.d.mts +28 -0
  79. package/dist/model/content/tracking.mjs +149 -10
  80. package/dist/model/content/tree.d.mts +212 -13
  81. package/dist/model/content/tree.mjs +356 -35
  82. package/dist/model/customxml/CustomXmlPartCollection.d.mts +8 -0
  83. package/dist/model/customxml/CustomXmlPartCollection.mjs +34 -11
  84. package/dist/model/customxml/XmlMapping.d.mts +1 -1
  85. package/dist/model/customxml/XmlMapping.mjs +11 -0
  86. package/dist/model/customxml/bindings.d.mts +21 -2
  87. package/dist/model/customxml/bindings.mjs +76 -32
  88. package/dist/model/customxml/kinds.d.mts +8 -3
  89. package/dist/model/customxml/kinds.mjs +26 -5
  90. package/dist/model/customxml/picturePlaceholder.d.mts +17 -0
  91. package/dist/model/customxml/picturePlaceholder.mjs +32 -0
  92. package/dist/model/customxml/pictures.d.mts +9 -5
  93. package/dist/model/customxml/pictures.mjs +31 -13
  94. package/dist/model/customxml/xhtml.mjs +8 -2
  95. package/dist/model/fonts/families.generated.mjs +2 -2
  96. package/dist/model/fonts/registry.mjs +7 -1
  97. package/dist/model/fonts/substitutions.generated.mjs +2 -2
  98. package/dist/model/fonts/themes.generated.mjs +1 -1
  99. package/dist/model/index.d.mts +2 -0
  100. package/dist/model/index.mjs +4 -0
  101. package/dist/model/listnumbering/Emulator.d.mts +37 -5
  102. package/dist/model/listnumbering/Emulator.mjs +63 -9
  103. package/dist/model/listnumbering/definitions.mjs +18 -0
  104. package/dist/model/properties/PropertyResolver.d.mts +87 -7
  105. package/dist/model/properties/PropertyResolver.mjs +197 -17
  106. package/dist/model/properties/catalogue.d.mts +32 -4
  107. package/dist/model/properties/catalogue.mjs +115 -36
  108. package/dist/model/properties/log.d.mts +1 -1
  109. package/dist/model/properties/log.mjs +5 -5
  110. package/dist/model/properties/table.d.mts +16 -2
  111. package/dist/model/properties/table.mjs +17 -5
  112. package/dist/model/text/Extractor.d.mts +289 -0
  113. package/dist/model/text/Extractor.mjs +2162 -0
  114. package/dist/model/text/LinkTargets.d.mts +45 -0
  115. package/dist/model/text/LinkTargets.mjs +170 -0
  116. package/dist/model/text/MarkdownExporter.d.mts +140 -0
  117. package/dist/model/text/MarkdownExporter.mjs +255 -0
  118. package/dist/model/text/PlainText.d.mts +29 -0
  119. package/dist/model/text/PlainText.mjs +539 -0
  120. package/dist/model/text/TextContext.d.mts +161 -0
  121. package/dist/model/text/TextContext.mjs +425 -0
  122. package/dist/model/text/TextOptions.d.mts +150 -0
  123. package/dist/model/text/TextOptions.mjs +278 -0
  124. package/dist/model/text/TextResult.d.mts +504 -0
  125. package/dist/model/text/TextResult.mjs +526 -0
  126. package/dist/model/text/Texts.d.mts +99 -0
  127. package/dist/model/text/Texts.mjs +187 -0
  128. package/dist/model/text/WmlToMarkdown.d.mts +120 -0
  129. package/dist/model/text/WmlToMarkdown.mjs +911 -0
  130. package/dist/model/text/commonmark.d.mts +121 -0
  131. package/dist/model/text/commonmark.mjs +655 -0
  132. package/dist/model/text/index.d.mts +7 -0
  133. package/dist/model/text/index.mjs +8 -0
  134. package/dist/model/text/normalize.d.mts +8 -0
  135. package/dist/model/text/normalize.mjs +13 -0
  136. package/dist/model/text/outline.d.mts +4 -0
  137. package/dist/model/text/outline.mjs +71 -0
  138. package/dist/office-js/fragment.d.mts +7 -5
  139. package/dist/office-js/fragment.mjs +63 -14
  140. package/dist/office-js/proxy.d.mts +8 -0
  141. package/dist/office-js/proxy.mjs +29 -0
  142. package/dist/office-js/run.mjs +2 -0
  143. package/dist/office-js/supported.generated.mjs +16 -0
  144. package/dist/office-js/toApiScript.mjs +21 -5
  145. package/dist/opc/Load.d.mts +9 -2
  146. package/dist/opc/Save.d.mts +17 -0
  147. package/dist/opc/Save.mjs +12 -2
  148. package/dist/opc/index.d.mts +3 -3
  149. package/dist/opc/index.mjs +2 -2
  150. package/dist/opc/mce/preprocessor.d.mts +88 -7
  151. package/dist/opc/mce/preprocessor.mjs +144 -37
  152. package/dist/opc/mce/understood.d.mts +34 -0
  153. package/dist/opc/mce/understood.mjs +55 -3
  154. package/dist/packages/OpcPackage.d.mts +20 -0
  155. package/dist/packages/OpcPackage.mjs +16 -3
  156. package/dist/packages/WordprocessingMLPackage.d.mts +77 -7
  157. package/dist/packages/WordprocessingMLPackage.mjs +242 -11
  158. package/dist/parts/DefaultXmlPart.mjs +2 -2
  159. package/dist/parts/Part.d.mts +10 -2
  160. package/dist/parts/XmlPart.d.mts +35 -32
  161. package/dist/parts/XmlPart.mjs +107 -107
  162. package/dist/parts/wml/comments.mjs +30 -0
  163. package/dist/parts/wml/index.mjs +12 -0
  164. package/dist/xml/dom.d.mts +7 -0
  165. package/dist/xml/dom.mjs +18 -0
  166. package/package.json +2 -2
@@ -0,0 +1,161 @@
1
+ import type * as wml from '@docx4j/generated-objects-ts/modules/org_docx4j_wml';
2
+ import type * as w15 from '@docx4j/generated-objects-ts/modules/org_docx4j_w15';
3
+ import type * as core from '@docx4j/generated-objects-ts/modules/org_docx4j_docProps_core';
4
+ import type * as extended from '@docx4j/generated-objects-ts/modules/org_docx4j_docProps_extended';
5
+ import type * as custom from '@docx4j/generated-objects-ts/modules/org_docx4j_docProps_custom';
6
+ import type { Part } from '../../parts/Part.mjs';
7
+ import type { XmlPart } from '../../parts/XmlPart.mjs';
8
+ import type { PropertyResolver } from '../properties/PropertyResolver.mjs';
9
+ import type { NumberingDefinitions } from '../listnumbering/definitions.mjs';
10
+ import type { NumberingPartLike } from '../listnumbering/Emulator.mjs';
11
+ import { NumberingStates } from '../listnumbering/state.mjs';
12
+ import { Body } from '../content/Body.mjs';
13
+ import { ResolvedView } from '../content/ResolvedView.mjs';
14
+ import type { XPathEngine } from '../customxml/xpath.mjs';
15
+ import type { NoteType } from './TextResult.mjs';
16
+ /** As much of a `WordprocessingMLPackage` as a reading uses, so that this module does not import the package. */
17
+ export interface TextPackage {
18
+ getMainDocumentPart(): MainLike;
19
+ getPropertyResolver(): Promise<PropertyResolver>;
20
+ getNumberingEmulator(): Promise<unknown>;
21
+ readonly propertyResolverOrUndefined?: PropertyResolver;
22
+ readonly docPropsCorePart?: XmlPart<core.CoreProperties>;
23
+ readonly docPropsExtendedPart?: XmlPart<extended.Properties>;
24
+ readonly docPropsCustomPart?: XmlPart<custom.Properties>;
25
+ readonly customXmlDataStorageParts: ReadonlyMap<string, {
26
+ parseDocument(): Promise<Document>;
27
+ }>;
28
+ xpathEngine: XPathEngine;
29
+ }
30
+ /** As much of a `MainDocumentPart` as a reading uses. */
31
+ export interface MainLike extends XmlPart<wml.Document> {
32
+ readonly styleDefinitionsPart?: Part;
33
+ readonly numberingDefinitionsPart?: XmlPart<wml.Numbering> & NumberingPartLike & {
34
+ getDefinitions(): Promise<NumberingDefinitions>;
35
+ };
36
+ readonly documentSettingsPart?: XmlPart<wml.CTSettings>;
37
+ readonly footnotesPart?: XmlPart<wml.CTFootnotes>;
38
+ readonly endnotesPart?: XmlPart<wml.CTEndnotes>;
39
+ readonly commentsPart?: XmlPart<wml.Comments>;
40
+ readonly commentsExtendedPart?: XmlPart<w15.CTCommentsEx>;
41
+ readonly glossaryDocumentPart?: XmlPart<wml.GlossaryDocument>;
42
+ readonly headerParts: XmlPart<wml.Hdr>[];
43
+ readonly footerParts: XmlPart<wml.Ftr>[];
44
+ }
45
+ /**
46
+ * The trees one reading walks, each read **privately** where its part was not unmarshalled
47
+ * (`XmlPart.readContents`), so that reading a document costs no part its byte-for-byte round trip
48
+ * (REQ-204), and the live tree where it was. Every story is read, so that the views' plan covers them
49
+ * all ("the view is the package's"); the glossary only when it is included.
50
+ */
51
+ export declare class PackageTrees {
52
+ readonly pkg: TextPackage | undefined;
53
+ main: {
54
+ part: MainLike;
55
+ document: wml.Document;
56
+ } | undefined;
57
+ footnotes: {
58
+ part: Part;
59
+ tree: wml.CTFootnotes;
60
+ } | undefined;
61
+ endnotes: {
62
+ part: Part;
63
+ tree: wml.CTEndnotes;
64
+ } | undefined;
65
+ comments: {
66
+ part: Part;
67
+ tree: wml.Comments;
68
+ } | undefined;
69
+ commentsExtended: w15.CTCommentsEx | undefined;
70
+ /** Each header and footer part related from the main document part, with its content. */
71
+ readonly headersAndFooters: Map<Part, wml.Ftr | wml.Hdr>;
72
+ glossary: {
73
+ part: Part;
74
+ tree: wml.GlossaryDocument;
75
+ } | undefined;
76
+ settings: wml.CTSettings | undefined;
77
+ /** The document properties under `core`, `app` and `custom` (REQ-515). */
78
+ properties: Record<string, unknown> | undefined;
79
+ /** The resolver, where the package has a styles part (docx4j makes none without one). */
80
+ resolver: PropertyResolver | undefined;
81
+ numberingPart: NumberingPartLike | undefined;
82
+ numbering: NumberingDefinitions | undefined;
83
+ /** Each binding store's DOM, by its upper-cased item id. */
84
+ private readonly stores;
85
+ private xpath;
86
+ private anchored;
87
+ private constructor();
88
+ /** The trees of a package. */
89
+ static read(pkg: TextPackage): Promise<PackageTrees>;
90
+ /** Trees with no package: content read as it stands (docx4j's planless `Texts.of(content)`). */
91
+ static none(): PackageTrees;
92
+ /** The glossary document, read when `include: glossary` first asks for it. */
93
+ readGlossary(): Promise<void>;
94
+ private readStores;
95
+ /**
96
+ * A data binding's value, docx4j `BoundValues`: the binding's XPath, with its own prefix mappings,
97
+ * against the custom XML part its `w:storeItemID` names (or the core or application properties); the
98
+ * string value of the first node selected. Undefined where the binding does not resolve.
99
+ */
100
+ boundValue(binding: wml.CTDataBinding): string | undefined;
101
+ /**
102
+ * The ids of the comments anchored in the document: a `w:commentReference` or a `w:commentRangeStart`
103
+ * in the main document, a header or footer, or a note, in any branch.
104
+ */
105
+ anchoredComments(): Set<string>;
106
+ /** Every story's body, over these trees, for the views' plan: the main document, each note and comment, the headers and footers. */
107
+ stories(): Body[];
108
+ /** The part whose tree holds an object, by its `PARENT`s, or undefined. */
109
+ partOf(object: unknown): Part | undefined;
110
+ }
111
+ /**
112
+ * What a story needs from the rest of the document (CR-012 section 4.4): the note references' order, for
113
+ * `[n]`; the numbering states per story, for list labels and `value`; the bookmarks, for `fields: update`;
114
+ * and, made once, each view's plan of what Accept All or Reject All would leave. A call given a context
115
+ * uses it and adds to it, so that the editor's calls over one part at a time, in the order the
116
+ * specification reads the stories (REQ-501), number the notes and count the lists as one reading of the
117
+ * whole package does; `TextResult.concat` assembles their results.
118
+ *
119
+ * A context is a snapshot of the package as it was read (`Texts.contextOf`): after the package changes,
120
+ * make another. It is for one reading, in one view: the calls under it take the same options, as the parts
121
+ * of one `Texts.of(pkg)` would.
122
+ */
123
+ export declare class TextContext {
124
+ readonly trees: PackageTrees;
125
+ /** Notes referenced, in reference order: id to number, 0 for a note with a custom mark. */
126
+ readonly footnotes: Map<string, number>;
127
+ readonly endnotes: Map<string, number>;
128
+ private footnoteCount;
129
+ private endnoteCount;
130
+ /** The numbering states, one per story (`Emulator`). */
131
+ readonly numberingStates: NumberingStates;
132
+ /** The `w:lastRenderedPageBreak`s of the main story so far (REQ-708). */
133
+ pageMarkers: number;
134
+ /** The bookmarks' text, by lower-cased name (REQ-506's REF, CR-012 phase 5a). */
135
+ readonly bookmarks: Map<string, string>;
136
+ /** Whether the main story has been read under this context, which numbers the notes. */
137
+ mainRead: boolean;
138
+ /**
139
+ * The view the context's first call read in: its note numbers and counts are that view's, so a call in
140
+ * another view is refused (`Texts.of`).
141
+ */
142
+ view: 'accepted' | 'original' | 'markup' | undefined;
143
+ private readonly plans;
144
+ /** Per container, then per options, what the blocks begin inside (`Extractor.fieldsAtBlocks`), made once; shared with siblings. */
145
+ private starts;
146
+ constructor(trees: PackageTrees);
147
+ /** What `make` gives for a container's blocks under options keyed `key`, made once in this context (CR-012 section 17.13). */
148
+ blockStarts<T>(container: object, key: string, make: () => T): T;
149
+ /** The package this context reads. */
150
+ get pkg(): TextPackage | undefined;
151
+ /** A note's number, given at its first reference: in reference order, footnotes and endnotes apart, 0 for a custom mark (REQ-503). */
152
+ noteNumber(type: NoteType, id: string, customMark: boolean): number;
153
+ /** The plan of Accept All (`accepted`) or Reject All, over every story, made once. */
154
+ plan(accepted: boolean): ResolvedView;
155
+ /** A context over the same trees and plans, its own notes and states: for a reading whose blocks are not the result's. */
156
+ sibling(): TextContext;
157
+ /** Adopts the note numbers another context gave (`sibling`'s, for a notes part read before its story). */
158
+ adoptNotes(other: TextContext): void;
159
+ }
160
+ /** An XML calendar as its lexical form. */
161
+ export declare function calendarText(date: unknown): string | undefined;
@@ -0,0 +1,425 @@
1
+ import { NumberingStates } from '../listnumbering/state.mjs';
2
+ import { Body } from '../content/Body.mjs';
3
+ import { ResolvedView } from '../content/ResolvedView.mjs';
4
+ import { parsePrefixMappings } from '../customxml/xpath.mjs';
5
+ import { parseXml, decodeXmlText } from '../../xml/dom.mjs';
6
+ import { walk } from '@docx4j/generated-objects-ts/builders/wml';
7
+ /** The `w:storeItemID`s of the core and application properties, which a control can be bound to (docx4j `BindingHandler`). */
8
+ const CORE_PROPERTIES_STOREITEMID = '{6C3C8BC8-F283-45AE-878A-BAB7291924A1}';
9
+ const EXTENDED_PROPERTIES_STOREITEMID = '{6668398D-A668-4E3E-A5EB-62B293D839F1}';
10
+ /** `readContents()`, undefined for a part that cannot be read. */
11
+ async function readQuietly(part) {
12
+ if (!part)
13
+ return undefined;
14
+ try {
15
+ return await part.readContents();
16
+ }
17
+ catch {
18
+ return undefined;
19
+ }
20
+ }
21
+ /**
22
+ * The trees one reading walks, each read **privately** where its part was not unmarshalled
23
+ * (`XmlPart.readContents`), so that reading a document costs no part its byte-for-byte round trip
24
+ * (REQ-204), and the live tree where it was. Every story is read, so that the views' plan covers them
25
+ * all ("the view is the package's"); the glossary only when it is included.
26
+ */
27
+ export class PackageTrees {
28
+ constructor(pkg) {
29
+ this.pkg = pkg;
30
+ /** Each header and footer part related from the main document part, with its content. */
31
+ this.headersAndFooters = new Map();
32
+ /** Each binding store's DOM, by its upper-cased item id. */
33
+ this.stores = new Map();
34
+ }
35
+ /** The trees of a package. */
36
+ static async read(pkg) {
37
+ const trees = new PackageTrees(pkg);
38
+ let main;
39
+ try {
40
+ main = pkg.getMainDocumentPart();
41
+ }
42
+ catch {
43
+ main = undefined;
44
+ }
45
+ if (main) {
46
+ trees.main = { part: main, document: await main.readContents() };
47
+ if (main.styleDefinitionsPart) {
48
+ try {
49
+ trees.resolver = await pkg.getPropertyResolver();
50
+ }
51
+ catch {
52
+ trees.resolver = undefined; // hidden text and indents not resolved through styles
53
+ }
54
+ }
55
+ const numbering = main.numberingDefinitionsPart;
56
+ if (numbering) {
57
+ try {
58
+ await pkg.getNumberingEmulator();
59
+ trees.numbering = await numbering.getDefinitions();
60
+ trees.numberingPart = numbering;
61
+ }
62
+ catch {
63
+ trees.numberingPart = undefined;
64
+ }
65
+ }
66
+ trees.settings = await readQuietly(main.documentSettingsPart);
67
+ const footnotes = await readQuietly(main.footnotesPart);
68
+ if (footnotes && main.footnotesPart)
69
+ trees.footnotes = { part: main.footnotesPart, tree: footnotes };
70
+ const endnotes = await readQuietly(main.endnotesPart);
71
+ if (endnotes && main.endnotesPart)
72
+ trees.endnotes = { part: main.endnotesPart, tree: endnotes };
73
+ const comments = await readQuietly(main.commentsPart);
74
+ if (comments && main.commentsPart)
75
+ trees.comments = { part: main.commentsPart, tree: comments };
76
+ trees.commentsExtended = await readQuietly(main.commentsExtendedPart);
77
+ for (const part of [...main.headerParts, ...main.footerParts]) {
78
+ const content = await readQuietly(part);
79
+ if (content)
80
+ trees.headersAndFooters.set(part, content);
81
+ }
82
+ }
83
+ trees.properties = await properties(pkg);
84
+ await trees.readStores(pkg);
85
+ return trees;
86
+ }
87
+ /** Trees with no package: content read as it stands (docx4j's planless `Texts.of(content)`). */
88
+ static none() {
89
+ return new PackageTrees(undefined);
90
+ }
91
+ /** The glossary document, read when `include: glossary` first asks for it. */
92
+ async readGlossary() {
93
+ var _a;
94
+ const part = (_a = this.main) === null || _a === void 0 ? void 0 : _a.part.glossaryDocumentPart;
95
+ if (this.glossary || !part)
96
+ return;
97
+ const tree = await readQuietly(part);
98
+ if (tree)
99
+ this.glossary = { part, tree };
100
+ }
101
+ // --- bound values (REQ-509) ---------------------------------------------------------------------
102
+ async readStores(pkg) {
103
+ let context;
104
+ for (const [id, part] of pkg.customXmlDataStorageParts) {
105
+ try {
106
+ const doc = await part.parseDocument();
107
+ this.stores.set(id.toUpperCase(), doc);
108
+ context !== null && context !== void 0 ? context : (context = doc);
109
+ }
110
+ catch {
111
+ this.stores.set(id.toUpperCase(), undefined);
112
+ }
113
+ }
114
+ for (const [id, part] of [[CORE_PROPERTIES_STOREITEMID, pkg.docPropsCorePart], [EXTENDED_PROPERTIES_STOREITEMID, pkg.docPropsExtendedPart]]) {
115
+ if (!part)
116
+ continue;
117
+ try {
118
+ // the part's XML as it would be saved, parsed apart from it: the part keeps its round trip
119
+ const doc = parseXml(decodeXmlText(await part.getBytes()));
120
+ this.stores.set(id, doc);
121
+ context !== null && context !== void 0 ? context : (context = doc);
122
+ }
123
+ catch {
124
+ this.stores.set(id, undefined);
125
+ }
126
+ }
127
+ if (context === undefined)
128
+ return;
129
+ try {
130
+ await pkg.xpathEngine.ready(context);
131
+ this.xpath = pkg.xpathEngine;
132
+ }
133
+ catch {
134
+ this.xpath = undefined; // no XPath here: every control's surface is read
135
+ }
136
+ }
137
+ /**
138
+ * A data binding's value, docx4j `BoundValues`: the binding's XPath, with its own prefix mappings,
139
+ * against the custom XML part its `w:storeItemID` names (or the core or application properties); the
140
+ * string value of the first node selected. Undefined where the binding does not resolve.
141
+ */
142
+ boundValue(binding) {
143
+ var _a;
144
+ if (!binding.xpath || !binding.storeItemID || !this.xpath)
145
+ return undefined;
146
+ const doc = this.stores.get(binding.storeItemID.toUpperCase());
147
+ if (!doc)
148
+ return undefined;
149
+ try {
150
+ const mappings = parsePrefixMappings(binding.prefixMappings);
151
+ delete mappings[''];
152
+ const nodes = this.xpath.select(binding.xpath, doc, mappings);
153
+ const node = nodes[0];
154
+ if (!node)
155
+ return undefined;
156
+ return node.nodeType === 2 ? node.value : ((_a = node.textContent) !== null && _a !== void 0 ? _a : '');
157
+ }
158
+ catch {
159
+ return undefined;
160
+ }
161
+ }
162
+ // --- the comments anchored in the document (REQ-504) -----------------------------------------------
163
+ /**
164
+ * The ids of the comments anchored in the document: a `w:commentReference` or a `w:commentRangeStart`
165
+ * in the main document, a header or footer, or a note, in any branch.
166
+ */
167
+ anchoredComments() {
168
+ var _a, _b, _c;
169
+ if (this.anchored)
170
+ return this.anchored;
171
+ const ids = new Set();
172
+ const roots = [(_a = this.main) === null || _a === void 0 ? void 0 : _a.document, ...this.headersAndFooters.values(), (_b = this.footnotes) === null || _b === void 0 ? void 0 : _b.tree, (_c = this.endnotes) === null || _c === void 0 ? void 0 : _c.tree];
173
+ for (const root of roots) {
174
+ if (root === undefined)
175
+ continue;
176
+ walk(root, (v) => {
177
+ const tn = v.TYPE_NAME;
178
+ if (tn === 'org_docx4j_wml.R.CommentReference' || tn === 'org_docx4j_wml.CommentRangeStart') {
179
+ const id = v.id;
180
+ if (id !== undefined && id !== null)
181
+ ids.add(String(id));
182
+ }
183
+ });
184
+ }
185
+ return (this.anchored = ids);
186
+ }
187
+ /** Every story's body, over these trees, for the views' plan: the main document, each note and comment, the headers and footers. */
188
+ stories() {
189
+ var _a, _b, _c, _d;
190
+ const pkg = this.pkg;
191
+ const out = [];
192
+ if ((_a = this.main) === null || _a === void 0 ? void 0 : _a.document.body)
193
+ out.push(new Body(this.main.part, this.main.document.body, 'body', pkg));
194
+ for (const [holder, kind] of [[this.footnotes, 'footnote'], [this.endnotes, 'endnote']]) {
195
+ if (!holder)
196
+ continue;
197
+ const notes = (_b = (kind === 'footnote' ? holder.tree.footnote : holder.tree.endnote)) !== null && _b !== void 0 ? _b : [];
198
+ for (const note of notes)
199
+ out.push(new Body(holder.part, note, `${kind}:${note.id}`, pkg));
200
+ }
201
+ for (const comment of (_d = (_c = this.comments) === null || _c === void 0 ? void 0 : _c.tree.comment) !== null && _d !== void 0 ? _d : []) {
202
+ out.push(new Body(this.comments.part, comment, `comment:${comment.id}`, pkg));
203
+ }
204
+ for (const [part, content] of this.headersAndFooters)
205
+ out.push(new Body(part, content, 'story', pkg));
206
+ return out;
207
+ }
208
+ /** The part whose tree holds an object, by its `PARENT`s, or undefined. */
209
+ partOf(object) {
210
+ let root = object;
211
+ for (let o = object; o; o = o.PARENT)
212
+ root = o;
213
+ if (this.main && (root === this.main.document || root === this.main.document.body))
214
+ return this.main.part;
215
+ for (const [part, content] of this.headersAndFooters)
216
+ if (root === content)
217
+ return part;
218
+ if (this.footnotes && root === this.footnotes.tree)
219
+ return this.footnotes.part;
220
+ if (this.endnotes && root === this.endnotes.tree)
221
+ return this.endnotes.part;
222
+ if (this.comments && root === this.comments.tree)
223
+ return this.comments.part;
224
+ if (this.glossary && root === this.glossary.tree)
225
+ return this.glossary.part;
226
+ return undefined;
227
+ }
228
+ }
229
+ /**
230
+ * What a story needs from the rest of the document (CR-012 section 4.4): the note references' order, for
231
+ * `[n]`; the numbering states per story, for list labels and `value`; the bookmarks, for `fields: update`;
232
+ * and, made once, each view's plan of what Accept All or Reject All would leave. A call given a context
233
+ * uses it and adds to it, so that the editor's calls over one part at a time, in the order the
234
+ * specification reads the stories (REQ-501), number the notes and count the lists as one reading of the
235
+ * whole package does; `TextResult.concat` assembles their results.
236
+ *
237
+ * A context is a snapshot of the package as it was read (`Texts.contextOf`): after the package changes,
238
+ * make another. It is for one reading, in one view: the calls under it take the same options, as the parts
239
+ * of one `Texts.of(pkg)` would.
240
+ */
241
+ export class TextContext {
242
+ constructor(trees) {
243
+ this.trees = trees;
244
+ /** Notes referenced, in reference order: id to number, 0 for a note with a custom mark. */
245
+ this.footnotes = new Map();
246
+ this.endnotes = new Map();
247
+ this.footnoteCount = 0;
248
+ this.endnoteCount = 0;
249
+ /** The numbering states, one per story (`Emulator`). */
250
+ this.numberingStates = new NumberingStates();
251
+ /** The `w:lastRenderedPageBreak`s of the main story so far (REQ-708). */
252
+ this.pageMarkers = 0;
253
+ /** The bookmarks' text, by lower-cased name (REQ-506's REF, CR-012 phase 5a). */
254
+ this.bookmarks = new Map();
255
+ /** Whether the main story has been read under this context, which numbers the notes. */
256
+ this.mainRead = false;
257
+ this.plans = new Map();
258
+ /** Per container, then per options, what the blocks begin inside (`Extractor.fieldsAtBlocks`), made once; shared with siblings. */
259
+ this.starts = new WeakMap();
260
+ }
261
+ /** What `make` gives for a container's blocks under options keyed `key`, made once in this context (CR-012 section 17.13). */
262
+ blockStarts(container, key, make) {
263
+ let byKey = this.starts.get(container);
264
+ if (!byKey)
265
+ this.starts.set(container, byKey = new Map());
266
+ if (!byKey.has(key))
267
+ byKey.set(key, make());
268
+ return byKey.get(key);
269
+ }
270
+ /** The package this context reads. */
271
+ get pkg() {
272
+ return this.trees.pkg;
273
+ }
274
+ /** A note's number, given at its first reference: in reference order, footnotes and endnotes apart, 0 for a custom mark (REQ-503). */
275
+ noteNumber(type, id, customMark) {
276
+ const numbers = type === 'footnote' ? this.footnotes : this.endnotes;
277
+ let n = numbers.get(id);
278
+ if (n === undefined) {
279
+ n = customMark ? 0 : type === 'footnote' ? ++this.footnoteCount : ++this.endnoteCount;
280
+ numbers.set(id, n);
281
+ }
282
+ return n;
283
+ }
284
+ /** The plan of Accept All (`accepted`) or Reject All, over every story, made once. */
285
+ plan(accepted) {
286
+ let plan = this.plans.get(accepted);
287
+ if (!plan) {
288
+ const stories = this.trees.stories();
289
+ plan = accepted ? ResolvedView.accepted(stories) : ResolvedView.original(stories);
290
+ this.plans.set(accepted, plan);
291
+ }
292
+ return plan;
293
+ }
294
+ /** A context over the same trees and plans, its own notes and states: for a reading whose blocks are not the result's. */
295
+ sibling() {
296
+ const c = new TextContext(this.trees);
297
+ for (const [k, v] of this.plans)
298
+ c.plans.set(k, v);
299
+ c.starts = this.starts;
300
+ return c;
301
+ }
302
+ /** Adopts the note numbers another context gave (`sibling`'s, for a notes part read before its story). */
303
+ adoptNotes(other) {
304
+ for (const [id, n] of other.footnotes)
305
+ if (!this.footnotes.has(id))
306
+ this.footnotes.set(id, n);
307
+ for (const [id, n] of other.endnotes)
308
+ if (!this.endnotes.has(id))
309
+ this.endnotes.set(id, n);
310
+ this.footnoteCount = Math.max(this.footnoteCount, other.footnoteCount);
311
+ this.endnoteCount = Math.max(this.endnoteCount, other.endnoteCount);
312
+ }
313
+ }
314
+ // --- the document properties (REQ-515; docx4j `Metadata`) --------------------------------------------
315
+ /** The properties under `core`, `app` and `custom`, each where the package has that part. */
316
+ async function properties(pkg) {
317
+ const out = {};
318
+ const c = await readQuietly(pkg.docPropsCorePart);
319
+ if (c)
320
+ out.core = coreProperties(c);
321
+ const a = await readQuietly(pkg.docPropsExtendedPart);
322
+ if (a)
323
+ out.app = appProperties(a);
324
+ const x = await readQuietly(pkg.docPropsCustomPart);
325
+ if (x)
326
+ out.custom = customProperties(x);
327
+ return out;
328
+ }
329
+ function put(m, name, value) {
330
+ if (value === undefined || value === null || value === '')
331
+ return;
332
+ m[name] = value;
333
+ }
334
+ function literal(o) {
335
+ const v = typeof o === 'object' && o !== null && 'value' in o && 'name' in o ? o.value : o;
336
+ const content = v === null || v === void 0 ? void 0 : v.content;
337
+ return content === undefined || content.length === 0 ? undefined : content.join('');
338
+ }
339
+ /** The core properties in the schema's order. */
340
+ function coreProperties(c) {
341
+ const m = {};
342
+ put(m, 'title', literal(c.title));
343
+ put(m, 'subject', literal(c.subject));
344
+ put(m, 'creator', literal(c.creator));
345
+ put(m, 'keywords', c.keywords);
346
+ put(m, 'description', literal(c.description));
347
+ put(m, 'category', c.category);
348
+ put(m, 'contentStatus', c.contentStatus);
349
+ put(m, 'language', literal(c.language));
350
+ put(m, 'identifier', literal(c.identifier));
351
+ put(m, 'version', c.version);
352
+ put(m, 'revision', c.revision);
353
+ put(m, 'lastModifiedBy', c.lastModifiedBy);
354
+ put(m, 'created', literal(c.created));
355
+ put(m, 'modified', literal(c.modified));
356
+ put(m, 'lastPrinted', calendarText(c.lastPrinted));
357
+ return m;
358
+ }
359
+ /** The application properties that describe the document; the statistics, which depend on layout, left out. */
360
+ function appProperties(p) {
361
+ const m = {};
362
+ put(m, 'Application', p.application);
363
+ put(m, 'AppVersion', p.appVersion);
364
+ put(m, 'Company', p.company);
365
+ put(m, 'Manager', p.manager);
366
+ put(m, 'Template', p.template);
367
+ put(m, 'HyperlinkBase', p.hyperlinkBase);
368
+ put(m, 'TotalTime', p.totalTime);
369
+ put(m, 'DocSecurity', p.docSecurity);
370
+ return m;
371
+ }
372
+ /** Each custom property's typed value, in the part's order; values of other types left out. */
373
+ function customProperties(p) {
374
+ var _a;
375
+ const m = {};
376
+ for (const property of (_a = p.property) !== null && _a !== void 0 ? _a : []) {
377
+ if (property.name === undefined)
378
+ continue;
379
+ put(m, property.name, customValue(property));
380
+ }
381
+ return m;
382
+ }
383
+ function customValue(p) {
384
+ for (const key of ['lpwstr', 'lpstr', 'bstr', 'bool', 'i1', 'i2', 'i4', 'i8', '_int', 'ui1', 'ui2', 'ui4', 'ui8', 'uint', 'r4', 'r8', 'decimal']) {
385
+ const v = p[key];
386
+ if (v !== undefined && v !== null)
387
+ return v;
388
+ }
389
+ if (p.filetime !== undefined)
390
+ return calendarText(p.filetime);
391
+ if (p.date !== undefined)
392
+ return calendarText(p.date);
393
+ if (p.cy !== undefined)
394
+ return p.cy;
395
+ if (p.error !== undefined)
396
+ return p.error;
397
+ return undefined;
398
+ }
399
+ /** An XML calendar as its lexical form. */
400
+ export function calendarText(date) {
401
+ if (date === undefined || date === null)
402
+ return undefined;
403
+ if (typeof date === 'string')
404
+ return date;
405
+ const c = date;
406
+ if (typeof c.year !== 'number')
407
+ return String(date);
408
+ const p2 = (n) => String(n !== null && n !== void 0 ? n : 0).padStart(2, '0');
409
+ let out = `${String(c.year).padStart(4, '0')}-${p2(c.month)}-${p2(c.day)}`;
410
+ if (c.hour !== undefined) {
411
+ out += `T${p2(c.hour)}:${p2(c.minute)}:${p2(c.second)}`;
412
+ if (c.fractionalSecond)
413
+ out += String(c.fractionalSecond).replace(/^0/, '');
414
+ }
415
+ if (c.timezone !== undefined) {
416
+ if (c.timezone === 0)
417
+ out += 'Z';
418
+ else {
419
+ const sign = c.timezone < 0 ? '-' : '+';
420
+ const minutes = Math.abs(c.timezone);
421
+ out += `${sign}${p2(Math.floor(minutes / 60))}:${p2(minutes % 60)}`;
422
+ }
423
+ }
424
+ return out;
425
+ }