@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.
- package/NOTICE +4 -0
- package/README.md +34 -3
- package/dist/html/convert.mjs +40 -15
- package/dist/html/elements.mjs +2 -1
- package/dist/model/color/ColorMath.d.mts +29 -0
- package/dist/model/color/ColorMath.mjs +146 -0
- package/dist/model/color/ColorTables.d.mts +6 -0
- package/dist/model/color/ColorTables.mjs +83 -0
- package/dist/model/color/DrawingMLColors.d.mts +52 -0
- package/dist/model/color/DrawingMLColors.mjs +374 -0
- package/dist/model/color/ResolvedColor.d.mts +36 -0
- package/dist/model/color/ResolvedColor.mjs +65 -0
- package/dist/model/color/SpreadsheetColors.d.mts +36 -0
- package/dist/model/color/SpreadsheetColors.mjs +84 -0
- package/dist/model/color/StyleFill.d.mts +28 -0
- package/dist/model/color/StyleFill.mjs +21 -0
- package/dist/model/color/ThemeColors.d.mts +86 -0
- package/dist/model/color/ThemeColors.mjs +304 -0
- package/dist/model/color/WordColors.d.mts +71 -0
- package/dist/model/color/WordColors.mjs +121 -0
- package/dist/model/color/index.d.mts +6 -0
- package/dist/model/color/index.mjs +30 -0
- package/dist/model/content/Body.d.mts +153 -19
- package/dist/model/content/Body.mjs +570 -131
- package/dist/model/content/Comment.d.mts +21 -3
- package/dist/model/content/Comment.mjs +202 -19
- package/dist/model/content/ContentControl.d.mts +197 -18
- package/dist/model/content/ContentControl.mjs +664 -95
- package/dist/model/content/Font.d.mts +67 -17
- package/dist/model/content/Font.mjs +114 -35
- package/dist/model/content/InlinePicture.d.mts +82 -7
- package/dist/model/content/InlinePicture.mjs +221 -28
- package/dist/model/content/List.mjs +13 -1
- package/dist/model/content/Paragraph.d.mts +213 -14
- package/dist/model/content/Paragraph.mjs +936 -100
- package/dist/model/content/Range.d.mts +242 -11
- package/dist/model/content/Range.mjs +975 -119
- package/dist/model/content/ResolvedView.d.mts +104 -0
- package/dist/model/content/ResolvedView.mjs +596 -0
- package/dist/model/content/Table.d.mts +29 -3
- package/dist/model/content/Table.mjs +109 -33
- package/dist/model/content/TrackedChange.d.mts +301 -16
- package/dist/model/content/TrackedChange.mjs +1284 -158
- package/dist/model/content/binder.d.mts +2 -1
- package/dist/model/content/binder.mjs +48 -1
- package/dist/model/content/comments.d.mts +20 -6
- package/dist/model/content/comments.mjs +67 -57
- package/dist/model/content/generalException.d.mts +18 -0
- package/dist/model/content/generalException.mjs +24 -0
- package/dist/model/content/index.d.mts +8 -3
- package/dist/model/content/index.mjs +7 -2
- package/dist/model/content/mathText.d.mts +21 -0
- package/dist/model/content/mathText.mjs +267 -0
- package/dist/model/content/officeText.d.mts +27 -0
- package/dist/model/content/officeText.mjs +74 -0
- package/dist/model/content/outline.d.mts +5 -0
- package/dist/model/content/outline.mjs +13 -0
- package/dist/model/content/placeholders.d.mts +110 -0
- package/dist/model/content/placeholders.mjs +253 -0
- package/dist/model/content/relationships.d.mts +30 -0
- package/dist/model/content/relationships.mjs +133 -0
- package/dist/model/content/search.d.mts +72 -0
- package/dist/model/content/search.mjs +204 -2
- package/dist/model/content/spanEdits.d.mts +159 -0
- package/dist/model/content/spanEdits.mjs +728 -0
- package/dist/model/content/story.d.mts +44 -0
- package/dist/model/content/story.mjs +92 -0
- package/dist/model/content/tableColumns.d.mts +1 -1
- package/dist/model/content/tableColumns.mjs +108 -80
- package/dist/model/content/tableRevisions.d.mts +11 -3
- package/dist/model/content/tableRevisions.mjs +72 -42
- package/dist/model/content/tableRules.d.mts +30 -0
- package/dist/model/content/tableRules.mjs +100 -0
- package/dist/model/content/textBoxes.d.mts +18 -0
- package/dist/model/content/textBoxes.mjs +105 -0
- package/dist/model/content/trackedChangeFilter.d.mts +39 -0
- package/dist/model/content/trackedChangeFilter.mjs +81 -0
- package/dist/model/content/tracking.d.mts +28 -0
- package/dist/model/content/tracking.mjs +149 -10
- package/dist/model/content/tree.d.mts +212 -13
- package/dist/model/content/tree.mjs +356 -35
- package/dist/model/customxml/CustomXmlPartCollection.d.mts +8 -0
- package/dist/model/customxml/CustomXmlPartCollection.mjs +34 -11
- package/dist/model/customxml/XmlMapping.d.mts +1 -1
- package/dist/model/customxml/XmlMapping.mjs +11 -0
- package/dist/model/customxml/bindings.d.mts +21 -2
- package/dist/model/customxml/bindings.mjs +76 -32
- package/dist/model/customxml/kinds.d.mts +8 -3
- package/dist/model/customxml/kinds.mjs +26 -5
- package/dist/model/customxml/picturePlaceholder.d.mts +17 -0
- package/dist/model/customxml/picturePlaceholder.mjs +32 -0
- package/dist/model/customxml/pictures.d.mts +9 -5
- package/dist/model/customxml/pictures.mjs +31 -13
- package/dist/model/customxml/xhtml.mjs +8 -2
- package/dist/model/fonts/families.generated.mjs +2 -2
- package/dist/model/fonts/registry.mjs +7 -1
- package/dist/model/fonts/substitutions.generated.mjs +2 -2
- package/dist/model/fonts/themes.generated.mjs +1 -1
- package/dist/model/index.d.mts +2 -0
- package/dist/model/index.mjs +4 -0
- package/dist/model/listnumbering/Emulator.d.mts +37 -5
- package/dist/model/listnumbering/Emulator.mjs +63 -9
- package/dist/model/listnumbering/definitions.mjs +18 -0
- package/dist/model/properties/PropertyResolver.d.mts +87 -7
- package/dist/model/properties/PropertyResolver.mjs +197 -17
- package/dist/model/properties/catalogue.d.mts +32 -4
- package/dist/model/properties/catalogue.mjs +115 -36
- package/dist/model/properties/log.d.mts +1 -1
- package/dist/model/properties/log.mjs +5 -5
- package/dist/model/properties/table.d.mts +16 -2
- package/dist/model/properties/table.mjs +17 -5
- package/dist/model/text/Extractor.d.mts +289 -0
- package/dist/model/text/Extractor.mjs +2162 -0
- package/dist/model/text/LinkTargets.d.mts +45 -0
- package/dist/model/text/LinkTargets.mjs +170 -0
- package/dist/model/text/MarkdownExporter.d.mts +140 -0
- package/dist/model/text/MarkdownExporter.mjs +255 -0
- package/dist/model/text/PlainText.d.mts +29 -0
- package/dist/model/text/PlainText.mjs +539 -0
- package/dist/model/text/TextContext.d.mts +161 -0
- package/dist/model/text/TextContext.mjs +425 -0
- package/dist/model/text/TextOptions.d.mts +150 -0
- package/dist/model/text/TextOptions.mjs +278 -0
- package/dist/model/text/TextResult.d.mts +504 -0
- package/dist/model/text/TextResult.mjs +526 -0
- package/dist/model/text/Texts.d.mts +99 -0
- package/dist/model/text/Texts.mjs +187 -0
- package/dist/model/text/WmlToMarkdown.d.mts +120 -0
- package/dist/model/text/WmlToMarkdown.mjs +911 -0
- package/dist/model/text/commonmark.d.mts +121 -0
- package/dist/model/text/commonmark.mjs +655 -0
- package/dist/model/text/index.d.mts +7 -0
- package/dist/model/text/index.mjs +8 -0
- package/dist/model/text/normalize.d.mts +8 -0
- package/dist/model/text/normalize.mjs +13 -0
- package/dist/model/text/outline.d.mts +4 -0
- package/dist/model/text/outline.mjs +71 -0
- package/dist/office-js/fragment.d.mts +7 -5
- package/dist/office-js/fragment.mjs +63 -14
- package/dist/office-js/proxy.d.mts +8 -0
- package/dist/office-js/proxy.mjs +29 -0
- package/dist/office-js/run.mjs +2 -0
- package/dist/office-js/supported.generated.mjs +16 -0
- package/dist/office-js/toApiScript.mjs +21 -5
- package/dist/opc/Load.d.mts +9 -2
- package/dist/opc/Save.d.mts +17 -0
- package/dist/opc/Save.mjs +12 -2
- package/dist/opc/index.d.mts +3 -3
- package/dist/opc/index.mjs +2 -2
- package/dist/opc/mce/preprocessor.d.mts +88 -7
- package/dist/opc/mce/preprocessor.mjs +144 -37
- package/dist/opc/mce/understood.d.mts +34 -0
- package/dist/opc/mce/understood.mjs +55 -3
- package/dist/packages/OpcPackage.d.mts +20 -0
- package/dist/packages/OpcPackage.mjs +16 -3
- package/dist/packages/WordprocessingMLPackage.d.mts +77 -7
- package/dist/packages/WordprocessingMLPackage.mjs +242 -11
- package/dist/parts/DefaultXmlPart.mjs +2 -2
- package/dist/parts/Part.d.mts +10 -2
- package/dist/parts/XmlPart.d.mts +35 -32
- package/dist/parts/XmlPart.mjs +107 -107
- package/dist/parts/wml/comments.mjs +30 -0
- package/dist/parts/wml/index.mjs +12 -0
- package/dist/xml/dom.d.mts +7 -0
- package/dist/xml/dom.mjs +18 -0
- package/package.json +2 -2
|
@@ -64,10 +64,27 @@ export declare class Comment {
|
|
|
64
64
|
/** Removes the comment and its replies: the markers, the reference runs and every side-part entry. */
|
|
65
65
|
delete(): Promise<void>;
|
|
66
66
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
67
|
+
* @internal `delete()` once the side parts it touches are loaded: public so that a resolution's
|
|
68
|
+
* removals (`flushPendingRemovals`), which load only the parts the document has, take a comment away
|
|
69
|
+
* without creating any (CR-002 section 54).
|
|
69
70
|
*/
|
|
70
|
-
|
|
71
|
+
removeThread(): void;
|
|
72
|
+
/**
|
|
73
|
+
* The commented range: one `Range` from the comment's start to its end, across paragraphs where the comment
|
|
74
|
+
* spans them, as Office JS's `Comment.getRange()` (CR-014 phase 1, D2; check 52: a comment from one paragraph
|
|
75
|
+
* into the next reads `BODY1B\rLIST1A`). A start marker between blocks (Word writes one before a control's
|
|
76
|
+
* first paragraph) starts the range at the next paragraph, and an end marker between blocks ends it at the
|
|
77
|
+
* previous one's end. Undefined when the comment has no markers in this body. `getRanges()` gives the range a
|
|
78
|
+
* paragraph at a time, as this method did before.
|
|
79
|
+
*/
|
|
80
|
+
getRange(): Range | undefined;
|
|
81
|
+
/** Where a range marker stands: its paragraph and offset, a block-level one's the next or the previous paragraph's edge. */
|
|
82
|
+
private anchor;
|
|
83
|
+
/**
|
|
84
|
+
* The commented range a paragraph at a time: a `Range` per paragraph the comment touches (extension; what
|
|
85
|
+
* `getRange()` returned until CR-014 phase 1). Empty when the comment has no markers in this body.
|
|
86
|
+
*/
|
|
87
|
+
getRanges(): Range[];
|
|
71
88
|
/** This comment and, depth first, its replies. */
|
|
72
89
|
private thread;
|
|
73
90
|
private removeSelf;
|
|
@@ -108,6 +125,7 @@ export declare function commentsOf(scope: Body | Paragraph | Range): Promise<Com
|
|
|
108
125
|
* Comments whose anchored text went with a rejected insertion or an accepted deletion (check 32;
|
|
109
126
|
* `TrackedChange`'s `removeRevision`) had their markers removed then; their entries go here, with
|
|
110
127
|
* their replies, when the comments are next read or the package is saved (`WordprocessingMLPackage.saveTo`).
|
|
128
|
+
* With the last comment, the comment parts go too (`flushPendingRemovals`).
|
|
111
129
|
*/
|
|
112
130
|
export declare function flushPendingCommentRemovals(body: Body): Promise<void>;
|
|
113
131
|
export type { CommentParts, Author } from './comments.mjs';
|
|
@@ -2,13 +2,16 @@ import * as el from '@docx4j/generated-objects-ts/el/org_docx4j_wml';
|
|
|
2
2
|
import * as wmlFactory from '@docx4j/generated-objects-ts/factory/org_docx4j_wml';
|
|
3
3
|
import * as w15Factory from '@docx4j/generated-objects-ts/factory/org_docx4j_w15';
|
|
4
4
|
import * as w16cidFactory from '@docx4j/generated-objects-ts/factory/org_docx4j_w16cid';
|
|
5
|
-
import {
|
|
5
|
+
import { applyRunOptions, linkParents } from '@docx4j/generated-objects-ts/builders/wml';
|
|
6
|
+
import { oneParagraphRun } from './officeText.mjs';
|
|
6
7
|
import { Docx4JException } from '../../opc/exceptions.mjs';
|
|
7
8
|
import { Body } from './Body.mjs';
|
|
8
9
|
import { Paragraph } from './Paragraph.mjs';
|
|
9
10
|
import { Range } from './Range.mjs';
|
|
10
|
-
import { runOf, paragraphOf, typeNameOf } from './tree.mjs';
|
|
11
|
+
import { runOf, paragraphOf, typeNameOf, selectedBranchOf, BRANCH_TYPES } from './tree.mjs';
|
|
12
|
+
import { storyLayout } from './story.mjs';
|
|
11
13
|
import { revisionDateOf, wordCalendarOf, copyRPr } from './tracking.mjs';
|
|
14
|
+
import { relationshipIdsIn, queueRelationshipRemovals } from './relationships.mjs';
|
|
12
15
|
import { COMMENT_REFERENCE_STYLE, COMMENT_TEXT_STYLE, commentExOf, commentIdsOf, commentPartsAccess, commentParaId, initialsOf, isDone, markersOf, markersOfParagraph, nextCommentId, paraIdTaken, randomHexId, removeMarkers, setCommentApi, } from './comments.mjs';
|
|
13
16
|
/**
|
|
14
17
|
* A subset of Office JS `Word.Comment` over a `w:comment` and the markers that anchor it. A view:
|
|
@@ -77,11 +80,13 @@ export class Comment {
|
|
|
77
80
|
}
|
|
78
81
|
/** The comment's text, a paragraph per line; setting it replaces the paragraphs. */
|
|
79
82
|
get content() {
|
|
83
|
+
// Office JS's comment.content: its body's text, the paragraphs a mark \r apart (check 51)
|
|
80
84
|
return this.commentBody.text;
|
|
81
85
|
}
|
|
82
86
|
set content(text) {
|
|
83
87
|
const paraId = commentParaId(this.element);
|
|
84
|
-
|
|
88
|
+
// a paragraph per line, \r (as the getter gives it) or \n
|
|
89
|
+
const paragraphs = text.split(/\r\n|\r|\n/).map((line, i) => commentParagraph(line, i === 0));
|
|
85
90
|
if (paraId)
|
|
86
91
|
paragraphs[0].value.paraId = paraId;
|
|
87
92
|
this.element.content = paragraphs;
|
|
@@ -135,6 +140,14 @@ export class Comment {
|
|
|
135
140
|
/** Removes the comment and its replies: the markers, the reference runs and every side-part entry. */
|
|
136
141
|
async delete() {
|
|
137
142
|
await this.parts.ensureAll();
|
|
143
|
+
this.removeThread();
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* @internal `delete()` once the side parts it touches are loaded: public so that a resolution's
|
|
147
|
+
* removals (`flushPendingRemovals`), which load only the parts the document has, take a comment away
|
|
148
|
+
* without creating any (CR-002 section 54).
|
|
149
|
+
*/
|
|
150
|
+
removeThread() {
|
|
138
151
|
for (const comment of this.thread())
|
|
139
152
|
comment.removeSelf();
|
|
140
153
|
if (this.parentComment) {
|
|
@@ -145,12 +158,57 @@ export class Comment {
|
|
|
145
158
|
}
|
|
146
159
|
}
|
|
147
160
|
/**
|
|
148
|
-
* The commented range:
|
|
149
|
-
*
|
|
161
|
+
* The commented range: one `Range` from the comment's start to its end, across paragraphs where the comment
|
|
162
|
+
* spans them, as Office JS's `Comment.getRange()` (CR-014 phase 1, D2; check 52: a comment from one paragraph
|
|
163
|
+
* into the next reads `BODY1B\rLIST1A`). A start marker between blocks (Word writes one before a control's
|
|
164
|
+
* first paragraph) starts the range at the next paragraph, and an end marker between blocks ends it at the
|
|
165
|
+
* previous one's end. Undefined when the comment has no markers in this body. `getRanges()` gives the range a
|
|
166
|
+
* paragraph at a time, as this method did before.
|
|
150
167
|
*/
|
|
151
168
|
getRange() {
|
|
169
|
+
const markers = markersOf(this.body.container, (p) => this.body.hiddenRuns(p)).filter((m) => m.id === this.id);
|
|
170
|
+
const start = markers.find((m) => m.kind === 'start');
|
|
171
|
+
const end = [...markers].reverse().find((m) => m.kind === 'end');
|
|
172
|
+
const from = start && this.anchor(start, 'start');
|
|
173
|
+
const to = end && this.anchor(end, 'end');
|
|
174
|
+
if (!from || !to)
|
|
175
|
+
return this.getRanges()[0];
|
|
176
|
+
const paragraphs = this.body.paragraphs;
|
|
177
|
+
const a = paragraphs.findIndex((p) => p.element === from.paragraph.element);
|
|
178
|
+
const b = paragraphs.findIndex((p) => p.element === to.paragraph.element);
|
|
179
|
+
if (a < 0 || b < 0 || b < a || (a === b && to.offset < from.offset))
|
|
180
|
+
return this.getRanges()[0];
|
|
181
|
+
return a === b ? new Range(from.paragraph, from.offset, to.offset)
|
|
182
|
+
: new Range(from.paragraph, from.offset, to.offset, false, false, to.paragraph);
|
|
183
|
+
}
|
|
184
|
+
/** Where a range marker stands: its paragraph and offset, a block-level one's the next or the previous paragraph's edge. */
|
|
185
|
+
anchor(marker, side) {
|
|
186
|
+
var _a;
|
|
187
|
+
if (marker.paragraph && marker.paragraphContainer) {
|
|
188
|
+
const paragraph = new Paragraph(marker.paragraph, marker.paragraphContainer, this.body);
|
|
189
|
+
return { paragraph, offset: (_a = marker.offset) !== null && _a !== void 0 ? _a : (side === 'start' ? 0 : paragraph.text.length) };
|
|
190
|
+
}
|
|
191
|
+
const at = marker.owner.indexOf(marker.item);
|
|
192
|
+
if (at < 0)
|
|
193
|
+
return undefined;
|
|
194
|
+
const blocks = side === 'start' ? marker.owner.slice(at + 1) : marker.owner.slice(0, at).reverse();
|
|
195
|
+
for (const block of blocks) {
|
|
196
|
+
const found = storyLayout([block], () => '').paragraphs;
|
|
197
|
+
const sp = side === 'start' ? found[0] : found[found.length - 1];
|
|
198
|
+
if (!sp)
|
|
199
|
+
continue;
|
|
200
|
+
const paragraph = new Paragraph(sp.element, sp.container, this.body);
|
|
201
|
+
return { paragraph, offset: side === 'start' ? 0 : paragraph.text.length };
|
|
202
|
+
}
|
|
203
|
+
return undefined;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* The commented range a paragraph at a time: a `Range` per paragraph the comment touches (extension; what
|
|
207
|
+
* `getRange()` returned until CR-014 phase 1). Empty when the comment has no markers in this body.
|
|
208
|
+
*/
|
|
209
|
+
getRanges() {
|
|
152
210
|
var _a, _b, _c, _d;
|
|
153
|
-
const markers = markersOf(this.body.container).filter((m) => m.id === this.id && m.paragraph !== undefined);
|
|
211
|
+
const markers = markersOf(this.body.container, (p) => this.body.hiddenRuns(p)).filter((m) => m.id === this.id && m.paragraph !== undefined);
|
|
154
212
|
if (markers.length === 0)
|
|
155
213
|
return [];
|
|
156
214
|
const paragraphs = this.body.paragraphs;
|
|
@@ -191,6 +249,12 @@ export class Comment {
|
|
|
191
249
|
if (i >= 0)
|
|
192
250
|
comments.splice(i, 1);
|
|
193
251
|
}
|
|
252
|
+
// what the comment's own content related to - a picture's image - goes on save when nothing else
|
|
253
|
+
// uses it, as for a picture deleted outright (CR-002 section 50; docx4j's Removals)
|
|
254
|
+
const released = new Set();
|
|
255
|
+
relationshipIdsIn(this.element.content, released);
|
|
256
|
+
const pkg = this.body.package_;
|
|
257
|
+
queueRelationshipRemovals(pkg === null || pkg === void 0 ? void 0 : pkg.pendingRelationshipRemovals, this.parts.commentsPart, released);
|
|
194
258
|
const paraId = this.paraId;
|
|
195
259
|
if (paraId === undefined)
|
|
196
260
|
return;
|
|
@@ -285,11 +349,14 @@ function nestedIndex(owner, index) {
|
|
|
285
349
|
}
|
|
286
350
|
/** A paragraph of a comment: the `CommentText` style, opened by the annotation reference run. */
|
|
287
351
|
function commentParagraph(text, first) {
|
|
352
|
+
var _a;
|
|
288
353
|
const runs = [];
|
|
289
354
|
if (first)
|
|
290
355
|
runs.push(annotationRefRun());
|
|
291
|
-
|
|
292
|
-
|
|
356
|
+
// its line's characters as they read (CR-002 section 60 D1, E3); a line break is a paragraph of its own (D5)
|
|
357
|
+
const run = oneParagraphRun(text);
|
|
358
|
+
if ((_a = run.value.content) === null || _a === void 0 ? void 0 : _a.length)
|
|
359
|
+
runs.push(run);
|
|
293
360
|
return paragraphOf(runs, { TYPE_NAME: 'org_docx4j_wml.PPr', pStyle: { val: COMMENT_TEXT_STYLE } });
|
|
294
361
|
}
|
|
295
362
|
function insertAt(owner, index, items, parent) {
|
|
@@ -300,6 +367,18 @@ function insertAt(owner, index, items, parent) {
|
|
|
300
367
|
function parentOf(element) {
|
|
301
368
|
return element.value.PARENT;
|
|
302
369
|
}
|
|
370
|
+
/** The innermost branch of a kept `mc:AlternateContent` no reader takes that holds a value, or undefined. */
|
|
371
|
+
function unreadBranchOf(value) {
|
|
372
|
+
for (let o = value.PARENT, guard = 0; o && guard < 256; o = o.PARENT, guard++) {
|
|
373
|
+
const tn = o.TYPE_NAME;
|
|
374
|
+
if (tn === undefined || !BRANCH_TYPES.has(tn))
|
|
375
|
+
continue;
|
|
376
|
+
const ac = o.PARENT;
|
|
377
|
+
if (ac && selectedBranchOf(ac) !== o.any)
|
|
378
|
+
return o;
|
|
379
|
+
}
|
|
380
|
+
return undefined;
|
|
381
|
+
}
|
|
303
382
|
/**
|
|
304
383
|
* Where a marker for this segment's run goes when it is not put inside the revision the run sits
|
|
305
384
|
* in (`placeAround`): beside the run, but outside the `w:ins` or `w:del`, so that a comment made
|
|
@@ -316,10 +395,17 @@ function markerSite(seg, fallback, after) {
|
|
|
316
395
|
function placeAround(range, id) {
|
|
317
396
|
var _a;
|
|
318
397
|
var _b;
|
|
398
|
+
if (range.spansParagraphs) {
|
|
399
|
+
placeAcross(range, id);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
319
402
|
const paragraph = range.paragraph;
|
|
320
|
-
|
|
403
|
+
// a run holding the span holds nothing else, a tab or a break beside it moved out too, as `font` splits (until
|
|
404
|
+
// CR-014 phase 3 only the w:t were split, and a marker went beside the whole run, widening the anchor)
|
|
321
405
|
if (range.end > range.start)
|
|
322
|
-
paragraph.
|
|
406
|
+
paragraph.splitRunsAround(range.start, range.end);
|
|
407
|
+
else
|
|
408
|
+
paragraph.splitAt(range.start);
|
|
323
409
|
const covered = range.end > range.start ? paragraph.segments().filter((s) => s.end > range.start && s.start < range.end) : [];
|
|
324
410
|
const start = el.commentRangeStart(wmlFactory.createCommentRangeStart({ id }));
|
|
325
411
|
const end = el.commentRangeEnd(wmlFactory.createCommentRangeEnd({ id }));
|
|
@@ -362,16 +448,90 @@ function placeAround(range, id) {
|
|
|
362
448
|
insertAt(before.owner, before.index, [start], before.parent);
|
|
363
449
|
}
|
|
364
450
|
}
|
|
451
|
+
/**
|
|
452
|
+
* The markers of a comment over a range across paragraphs, as Word writes them (check 52, cases 79 to 85; CR-014
|
|
453
|
+
* phase 3): the start before the range's first character, in its first paragraph, and the end and the reference
|
|
454
|
+
* run after its last character, in its last paragraph, before a mark the range holds. A table between, or a cell
|
|
455
|
+
* either end is in, stays as it is: the markers stand in the paragraphs. On a block control's content range Word
|
|
456
|
+
* put the start before the control's first paragraph, in `w:sdtContent` (case 82); here it is inside that
|
|
457
|
+
* paragraph, which reads the same (CR-014 section 9.2). An insertion at either end is treated as `placeAround`
|
|
458
|
+
* treats one: the start inside it, before the first commented run; the end after the last, the rest of the
|
|
459
|
+
* insertion split off.
|
|
460
|
+
*/
|
|
461
|
+
function placeAcross(range, id) {
|
|
462
|
+
var _a, _b, _c, _d, _e;
|
|
463
|
+
var _f, _g;
|
|
464
|
+
const first = range.paragraph;
|
|
465
|
+
const last = range.endParagraph;
|
|
466
|
+
const start = el.commentRangeStart(wmlFactory.createCommentRangeStart({ id }));
|
|
467
|
+
const end = el.commentRangeEnd(wmlFactory.createCommentRangeEnd({ id }));
|
|
468
|
+
const reference = referenceRun(id);
|
|
469
|
+
// the end first; the two are in different paragraphs, so neither's offsets move with the other's markers. The
|
|
470
|
+
// runs are split as `font` splits them, so a marker never goes beside a run holding text outside the range
|
|
471
|
+
if (range.end > 0)
|
|
472
|
+
last.splitRunsAround(0, range.end);
|
|
473
|
+
const before = last.segments().filter((s) => s.start < range.end);
|
|
474
|
+
const lastSeg = before[before.length - 1];
|
|
475
|
+
if (((_a = lastSeg === null || lastSeg === void 0 ? void 0 : lastSeg.revision) === null || _a === void 0 ? void 0 : _a.kind) === 'ins') {
|
|
476
|
+
last.splitHolderAround(lastSeg.revision, lastSeg.runIndex + 1, [end, reference], () => last.nextAnnotationId());
|
|
477
|
+
}
|
|
478
|
+
else if (lastSeg) {
|
|
479
|
+
const site = markerSite(lastSeg, last.p, true);
|
|
480
|
+
insertAt(site.owner, site.index, [end, reference], site.parent);
|
|
481
|
+
}
|
|
482
|
+
else {
|
|
483
|
+
// nothing of the last paragraph in the range: the end at its start
|
|
484
|
+
const next = last.segments()[0];
|
|
485
|
+
const site = next ? markerSite(next, last.p, false) : { owner: ((_b = (_f = last.p).content) !== null && _b !== void 0 ? _b : (_f.content = [])), index: 0, parent: last.p };
|
|
486
|
+
insertAt(site.owner, site.index, [end, reference], site.parent);
|
|
487
|
+
}
|
|
488
|
+
if (range.start < first.text.length)
|
|
489
|
+
first.splitRunsAround(range.start, first.text.length);
|
|
490
|
+
const segments = first.segments();
|
|
491
|
+
const firstSeg = segments.find((s) => s.end > range.start);
|
|
492
|
+
if (((_c = firstSeg === null || firstSeg === void 0 ? void 0 : firstSeg.revision) === null || _c === void 0 ? void 0 : _c.kind) === 'ins')
|
|
493
|
+
insertAt(firstSeg.runOwner, firstSeg.runIndex, [start], firstSeg.revision.value);
|
|
494
|
+
else if (firstSeg) {
|
|
495
|
+
const site = markerSite(firstSeg, first.p, false);
|
|
496
|
+
insertAt(site.owner, site.index, [start], site.parent);
|
|
497
|
+
}
|
|
498
|
+
else {
|
|
499
|
+
// nothing of the first paragraph in the range: the start at its end
|
|
500
|
+
const previous = segments[segments.length - 1];
|
|
501
|
+
const site = previous ? markerSite(previous, first.p, true) : { owner: ((_d = (_g = first.p).content) !== null && _d !== void 0 ? _d : (_g.content = [])), index: ((_e = first.p.content) !== null && _e !== void 0 ? _e : []).length, parent: first.p };
|
|
502
|
+
insertAt(site.owner, site.index, [start], site.parent);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
365
505
|
/** Writes the markers of a reply next to its parent's, as Word nests them. */
|
|
366
506
|
function placeAfter(body, parentId, id) {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
const
|
|
371
|
-
|
|
507
|
+
var _a;
|
|
508
|
+
// the parent's markers in every branch of a kept mc:AlternateContent, each branch no reader takes
|
|
509
|
+
// apart, so that the reply is anchored in each as its parent is (CR-013 phase 3)
|
|
510
|
+
const groups = new Map();
|
|
511
|
+
for (const marker of markersOf(body.container, undefined, 'every')) {
|
|
512
|
+
if (marker.id !== parentId)
|
|
513
|
+
continue;
|
|
514
|
+
const key = unreadBranchOf(marker.item.value);
|
|
515
|
+
let group = groups.get(key);
|
|
516
|
+
if (!group)
|
|
517
|
+
groups.set(key, group = []);
|
|
518
|
+
group.push(marker);
|
|
519
|
+
}
|
|
520
|
+
const read = (_a = groups.get(undefined)) !== null && _a !== void 0 ? _a : [];
|
|
521
|
+
if (!read.some((m) => (m.kind === 'reference' && m.run && m.runOwner) || m.kind === 'end')) {
|
|
372
522
|
// refused before anything is written, so that no marker is left naming a comment never made
|
|
373
523
|
throw new Docx4JException(`Comment ${parentId} has no markers in this body; cannot anchor a reply`);
|
|
374
524
|
}
|
|
525
|
+
for (const markers of groups.values())
|
|
526
|
+
placeAfterIn(markers, id);
|
|
527
|
+
}
|
|
528
|
+
/** A reply's markers after its parent's, in one branch's markers (or those outside any no reader takes). */
|
|
529
|
+
function placeAfterIn(markers, id) {
|
|
530
|
+
const start = markers.find((m) => m.kind === 'start');
|
|
531
|
+
const end = [...markers].reverse().find((m) => m.kind === 'end');
|
|
532
|
+
const reference = [...markers].reverse().find((m) => m.kind === 'reference');
|
|
533
|
+
if (!((reference === null || reference === void 0 ? void 0 : reference.run) && reference.runOwner) && !end)
|
|
534
|
+
return;
|
|
375
535
|
if (start)
|
|
376
536
|
insertAt(start.owner, start.owner.indexOf(start.item) + 1, [el.commentRangeStart(wmlFactory.createCommentRangeStart({ id }))], parentOf(start.item));
|
|
377
537
|
if (end)
|
|
@@ -506,8 +666,9 @@ function commentId(parts, body, options) {
|
|
|
506
666
|
}
|
|
507
667
|
/** The paragraphs of a comment's content: a string splits on newlines, elements are taken as they are. */
|
|
508
668
|
function paragraphsOfContent(content) {
|
|
669
|
+
// a paragraph per line, at \r, \n or \r\n, as Word's comments take them (CR-002 section 60 D5, check 55)
|
|
509
670
|
if (typeof content === 'string')
|
|
510
|
-
return content.split(
|
|
671
|
+
return content.split(/\r\n|\r|\n/).map((line, i) => commentParagraph(line, i === 0));
|
|
511
672
|
const paragraphs = [...content];
|
|
512
673
|
if (paragraphs.length === 0)
|
|
513
674
|
throw new Docx4JException('A comment needs at least one paragraph');
|
|
@@ -542,6 +703,7 @@ export async function commentsOf(scope) {
|
|
|
542
703
|
* Comments whose anchored text went with a rejected insertion or an accepted deletion (check 32;
|
|
543
704
|
* `TrackedChange`'s `removeRevision`) had their markers removed then; their entries go here, with
|
|
544
705
|
* their replies, when the comments are next read or the package is saved (`WordprocessingMLPackage.saveTo`).
|
|
706
|
+
* With the last comment, the comment parts go too (`flushPendingRemovals`).
|
|
545
707
|
*/
|
|
546
708
|
export async function flushPendingCommentRemovals(body) {
|
|
547
709
|
var _a;
|
|
@@ -555,18 +717,39 @@ export async function flushPendingCommentRemovals(body) {
|
|
|
555
717
|
}
|
|
556
718
|
await flushPendingRemovals(body, parts);
|
|
557
719
|
}
|
|
720
|
+
/**
|
|
721
|
+
* The entries of the comments a resolution took away, replies included. The side parts the document
|
|
722
|
+
* has are loaded for it and none is created: before section 54 a removal created the commentsExtended,
|
|
723
|
+
* commentsIds and people parts a document lacked, as `delete()` does.
|
|
724
|
+
*
|
|
725
|
+
* With the last comment a resolution takes away, the comment parts go, as Word 365 removed them
|
|
726
|
+
* (docx4j CR-043 section 15; docx4j-python's artefact 8 rejected, docx4j's U22, core-ts check 32): the
|
|
727
|
+
* comments part and its commentsExtended, commentsIds and commentsExtensible parts, with their
|
|
728
|
+
* relationships; and the people part where no tracked change is left to name an author (U22: Word kept
|
|
729
|
+
* it while a deletion was still tracked). docx4j decides when its resolution ends; this, when the
|
|
730
|
+
* entries go, so tracked changes made or resolved in between count.
|
|
731
|
+
*/
|
|
558
732
|
async function flushPendingRemovals(body, parts) {
|
|
733
|
+
var _a;
|
|
559
734
|
const pkg = body.package_;
|
|
560
735
|
const pending = pkg === null || pkg === void 0 ? void 0 : pkg.pendingCommentRemovals;
|
|
561
736
|
if (!(pending === null || pending === void 0 ? void 0 : pending.size))
|
|
562
737
|
return;
|
|
738
|
+
await parts.loadExisting();
|
|
563
739
|
const views = viewsOf(parts, body);
|
|
740
|
+
let removed = false;
|
|
564
741
|
for (const id of [...pending]) {
|
|
565
742
|
const view = views.get(id);
|
|
566
|
-
if (view)
|
|
567
|
-
|
|
743
|
+
if (view) {
|
|
744
|
+
view.removeThread();
|
|
745
|
+
removed = true;
|
|
746
|
+
}
|
|
568
747
|
pending.delete(id);
|
|
569
748
|
}
|
|
749
|
+
if (!removed || ((_a = parts.comments.comment) !== null && _a !== void 0 ? _a : []).length > 0)
|
|
750
|
+
return;
|
|
751
|
+
const people = parts.people !== undefined && (pkg === null || pkg === void 0 ? void 0 : pkg.getAllTrackedChanges) !== undefined && (await pkg.getAllTrackedChanges()).length === 0;
|
|
752
|
+
parts.drop(people);
|
|
570
753
|
}
|
|
571
754
|
/** A `Comment` view per entry in the parts, replies linked to their parents. */
|
|
572
755
|
function viewsOf(parts, body) {
|
|
@@ -595,7 +778,7 @@ function idsInRange(range) {
|
|
|
595
778
|
var _a;
|
|
596
779
|
const spans = new Map();
|
|
597
780
|
const order = [];
|
|
598
|
-
for (const marker of markersOfParagraph(range.paragraph.element, range.paragraph.container)) {
|
|
781
|
+
for (const marker of markersOfParagraph(range.paragraph.element, range.paragraph.container, range.paragraph.hiddenRuns())) {
|
|
599
782
|
const at = (_a = marker.offset) !== null && _a !== void 0 ? _a : 0;
|
|
600
783
|
const span = spans.get(marker.id);
|
|
601
784
|
if (span) {
|