@docx4j/core-ts 0.5.0 → 0.7.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 +92 -4
- package/dist/html/convert.mjs +2 -1
- 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 +145 -23
- package/dist/model/content/Body.mjs +507 -150
- package/dist/model/content/Comment.d.mts +23 -5
- package/dist/model/content/Comment.mjs +207 -26
- package/dist/model/content/ContentControl.d.mts +198 -19
- package/dist/model/content/ContentControl.mjs +672 -99
- package/dist/model/content/Font.d.mts +70 -17
- package/dist/model/content/Font.mjs +119 -36
- package/dist/model/content/InlinePicture.d.mts +11 -0
- package/dist/model/content/InlinePicture.mjs +21 -1
- package/dist/model/content/List.d.mts +6 -3
- package/dist/model/content/List.mjs +18 -8
- package/dist/model/content/Paragraph.d.mts +200 -14
- package/dist/model/content/Paragraph.mjs +898 -82
- package/dist/model/content/Range.d.mts +227 -12
- package/dist/model/content/Range.mjs +785 -59
- 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 +135 -49
- package/dist/model/content/TrackedChange.d.mts +174 -15
- package/dist/model/content/TrackedChange.mjs +734 -170
- 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 +10 -3
- package/dist/model/content/index.mjs +10 -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/ooxml.mjs +12 -1
- package/dist/model/content/outline.d.mts +5 -0
- package/dist/model/content/outline.mjs +13 -0
- package/dist/model/content/paraIds.d.mts +5 -0
- package/dist/model/content/paraIds.mjs +54 -0
- package/dist/model/content/placeholders.d.mts +110 -0
- package/dist/model/content/placeholders.mjs +253 -0
- package/dist/model/content/search.d.mts +74 -0
- package/dist/model/content/search.mjs +255 -9
- package/dist/model/content/spanEdits.d.mts +159 -0
- package/dist/model/content/spanEdits.mjs +728 -0
- package/dist/model/content/story.d.mts +47 -0
- package/dist/model/content/story.mjs +95 -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 +102 -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 +63 -6
- package/dist/model/content/tracking.mjs +242 -22
- package/dist/model/content/tree.d.mts +172 -24
- package/dist/model/content/tree.mjs +328 -54
- package/dist/model/content/wordRange.d.mts +48 -0
- package/dist/model/content/wordRange.mjs +97 -0
- package/dist/model/customxml/CustomXmlPartCollection.d.mts +30 -1
- package/dist/model/customxml/CustomXmlPartCollection.mjs +81 -12
- package/dist/model/customxml/XmlMapping.d.mts +32 -8
- package/dist/model/customxml/XmlMapping.mjs +64 -10
- package/dist/model/customxml/bindings.d.mts +33 -4
- package/dist/model/customxml/bindings.mjs +171 -45
- package/dist/model/customxml/index.d.mts +1 -0
- package/dist/model/customxml/index.mjs +1 -0
- package/dist/model/customxml/kinds.d.mts +8 -3
- package/dist/model/customxml/kinds.mjs +26 -5
- package/dist/model/customxml/opendope.d.mts +4 -1
- package/dist/model/customxml/opendope.mjs +9 -6
- package/dist/model/customxml/picturePlaceholder.d.mts +17 -0
- package/dist/model/customxml/picturePlaceholder.mjs +32 -0
- package/dist/model/customxml/pictures.d.mts +4 -3
- package/dist/model/customxml/pictures.mjs +22 -8
- package/dist/model/customxml/storeItems.d.mts +57 -0
- package/dist/model/customxml/storeItems.mjs +122 -0
- package/dist/model/customxml/xhtml.mjs +23 -22
- package/dist/model/dateZone.d.mts +25 -0
- package/dist/model/dateZone.mjs +57 -0
- package/dist/model/index.d.mts +3 -0
- package/dist/model/index.mjs +5 -0
- package/dist/model/listnumbering/Emulator.d.mts +37 -5
- package/dist/model/listnumbering/Emulator.mjs +63 -9
- package/dist/model/properties/PropertyResolver.d.mts +74 -2
- package/dist/model/properties/PropertyResolver.mjs +133 -5
- package/dist/model/properties/catalogue.d.mts +19 -5
- package/dist/model/properties/catalogue.mjs +41 -15
- package/dist/model/properties/index.d.mts +1 -1
- package/dist/model/properties/log.d.mts +1 -1
- package/dist/model/properties/log.mjs +5 -5
- package/dist/model/properties/styleUtil.d.mts +3 -1
- package/dist/model/properties/styleUtil.mjs +20 -24
- package/dist/model/properties/table.mjs +4 -2
- package/dist/model/text/CaseMapping.d.mts +38 -0
- package/dist/model/text/CaseMapping.mjs +86 -0
- package/dist/model/text/Extractor.d.mts +349 -0
- package/dist/model/text/Extractor.mjs +2406 -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 +542 -0
- package/dist/model/text/TextContext.d.mts +256 -0
- package/dist/model/text/TextContext.mjs +600 -0
- package/dist/model/text/TextOptions.d.mts +233 -0
- package/dist/model/text/TextOptions.mjs +419 -0
- package/dist/model/text/TextResult.d.mts +621 -0
- package/dist/model/text/TextResult.mjs +629 -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 +936 -0
- package/dist/model/text/caseMapping.generated.d.mts +7 -0
- package/dist/model/text/caseMapping.generated.mjs +214 -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 +8 -0
- package/dist/model/text/index.mjs +9 -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/model/wordIntegers.d.mts +29 -0
- package/dist/model/wordIntegers.mjs +78 -0
- package/dist/office-js/document.mjs +15 -1
- 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 +29 -12
- package/dist/opc/DirectoryPartStore.d.mts +6 -2
- package/dist/opc/DirectoryPartStore.mjs +11 -4
- package/dist/opc/FlatOpcPartStore.d.mts +4 -2
- package/dist/opc/FlatOpcPartStore.mjs +11 -8
- package/dist/opc/Load.d.mts +32 -0
- package/dist/opc/Load.mjs +115 -5
- package/dist/opc/PartStore.d.mts +34 -1
- package/dist/opc/PartStore.mjs +71 -8
- package/dist/opc/Save.d.mts +32 -0
- package/dist/opc/Save.mjs +110 -4
- package/dist/opc/ZipPartStore.d.mts +4 -2
- package/dist/opc/ZipPartStore.mjs +12 -7
- package/dist/opc/exceptions.d.mts +140 -0
- package/dist/opc/exceptions.mjs +108 -0
- package/dist/opc/index.d.mts +8 -5
- package/dist/opc/index.mjs +5 -3
- package/dist/opc/mce/preprocessor.d.mts +141 -5
- package/dist/opc/mce/preprocessor.mjs +119 -18
- package/dist/opc/mce/understood.d.mts +3 -11
- package/dist/opc/mce/understood.mjs +27 -23
- package/dist/opc/repair/breaks.d.mts +23 -0
- package/dist/opc/repair/breaks.mjs +288 -0
- package/dist/opc/repair/hosts.d.mts +12 -0
- package/dist/opc/repair/hosts.mjs +33 -0
- package/dist/opc/repair/mainRoot.d.mts +19 -0
- package/dist/opc/repair/mainRoot.mjs +168 -0
- package/dist/opc/repair/unknownElements.d.mts +8 -0
- package/dist/opc/repair/unknownElements.mjs +180 -0
- package/dist/opc/repair/wmlNames.generated.d.mts +2 -0
- package/dist/opc/repair/wmlNames.generated.mjs +80 -0
- package/dist/opc/skipped.d.mts +50 -0
- package/dist/opc/skipped.mjs +140 -0
- package/dist/packages/OpcPackage.d.mts +110 -4
- package/dist/packages/OpcPackage.mjs +123 -7
- package/dist/packages/WordprocessingMLPackage.d.mts +45 -8
- package/dist/packages/WordprocessingMLPackage.mjs +158 -21
- package/dist/packages/index.d.mts +1 -1
- package/dist/parts/DefaultXmlPart.mjs +2 -2
- package/dist/parts/Part.d.mts +14 -2
- package/dist/parts/RelationshipsPart.d.mts +15 -0
- package/dist/parts/RelationshipsPart.mjs +66 -1
- package/dist/parts/XmlPart.d.mts +63 -32
- package/dist/parts/XmlPart.mjs +240 -96
- package/dist/parts/wml/comments.mjs +30 -0
- package/dist/parts/wml/index.d.mts +12 -1
- package/dist/parts/wml/index.mjs +37 -1
- package/dist/xml/dom.d.mts +7 -0
- package/dist/xml/dom.mjs +18 -0
- package/package.json +2 -2
|
@@ -36,8 +36,8 @@ export declare class Comment {
|
|
|
36
36
|
/**
|
|
37
37
|
* When the comment was made, as Word means it (CR-002 section 29, the revision dates' rule): its
|
|
38
38
|
* `w16cex:dateUtc` when the document has one for it, which is UTC; else `w:date`, which Word writes
|
|
39
|
-
* on the author's local wall clock whatever its `Z` says, read as local time
|
|
40
|
-
* comment carries neither.
|
|
39
|
+
* on the author's local wall clock whatever its `Z` says, read as local time in the package's
|
|
40
|
+
* `dateTimeZone` (CR-018), else the runtime's. Undefined when the comment carries neither.
|
|
41
41
|
*/
|
|
42
42
|
get creationDate(): Date | undefined;
|
|
43
43
|
/** The comment's paragraphs as a `Body` (extension: the same content API as the document's). */
|
|
@@ -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,15 @@ 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 {
|
|
11
|
+
import { runOf, paragraphOf, typeNameOf, selectedBranchOf, BRANCH_TYPES } from './tree.mjs';
|
|
12
|
+
import { storyLayout } from './story.mjs';
|
|
13
|
+
import { revisionDateOf, wordCalendarOf, nowToTheMinute, copyRPr } from './tracking.mjs';
|
|
12
14
|
import { relationshipIdsIn, queueRelationshipRemovals } from './relationships.mjs';
|
|
13
15
|
import { COMMENT_REFERENCE_STYLE, COMMENT_TEXT_STYLE, commentExOf, commentIdsOf, commentPartsAccess, commentParaId, initialsOf, isDone, markersOf, markersOfParagraph, nextCommentId, paraIdTaken, randomHexId, removeMarkers, setCommentApi, } from './comments.mjs';
|
|
14
16
|
/**
|
|
@@ -54,8 +56,8 @@ export class Comment {
|
|
|
54
56
|
/**
|
|
55
57
|
* When the comment was made, as Word means it (CR-002 section 29, the revision dates' rule): its
|
|
56
58
|
* `w16cex:dateUtc` when the document has one for it, which is UTC; else `w:date`, which Word writes
|
|
57
|
-
* on the author's local wall clock whatever its `Z` says, read as local time
|
|
58
|
-
* comment carries neither.
|
|
59
|
+
* on the author's local wall clock whatever its `Z` says, read as local time in the package's
|
|
60
|
+
* `dateTimeZone` (CR-018), else the runtime's. Undefined when the comment carries neither.
|
|
59
61
|
*/
|
|
60
62
|
get creationDate() {
|
|
61
63
|
var _a;
|
|
@@ -65,7 +67,7 @@ export class Comment {
|
|
|
65
67
|
if (utc)
|
|
66
68
|
return utc;
|
|
67
69
|
}
|
|
68
|
-
return revisionDateOf({ date: this.element.date });
|
|
70
|
+
return revisionDateOf({ date: this.element.date }, zoneOf(this.body.package_));
|
|
69
71
|
}
|
|
70
72
|
/** The comment's paragraphs as a `Body` (extension: the same content API as the document's). */
|
|
71
73
|
get commentBody() {
|
|
@@ -78,11 +80,13 @@ export class Comment {
|
|
|
78
80
|
}
|
|
79
81
|
/** The comment's text, a paragraph per line; setting it replaces the paragraphs. */
|
|
80
82
|
get content() {
|
|
83
|
+
// Office JS's comment.content: its body's text, the paragraphs a mark \r apart (check 51)
|
|
81
84
|
return this.commentBody.text;
|
|
82
85
|
}
|
|
83
86
|
set content(text) {
|
|
84
87
|
const paraId = commentParaId(this.element);
|
|
85
|
-
|
|
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));
|
|
86
90
|
if (paraId)
|
|
87
91
|
paragraphs[0].value.paraId = paraId;
|
|
88
92
|
this.element.content = paragraphs;
|
|
@@ -136,6 +140,14 @@ export class Comment {
|
|
|
136
140
|
/** Removes the comment and its replies: the markers, the reference runs and every side-part entry. */
|
|
137
141
|
async delete() {
|
|
138
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() {
|
|
139
151
|
for (const comment of this.thread())
|
|
140
152
|
comment.removeSelf();
|
|
141
153
|
if (this.parentComment) {
|
|
@@ -146,12 +158,57 @@ export class Comment {
|
|
|
146
158
|
}
|
|
147
159
|
}
|
|
148
160
|
/**
|
|
149
|
-
* The commented range:
|
|
150
|
-
*
|
|
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.
|
|
151
167
|
*/
|
|
152
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() {
|
|
153
210
|
var _a, _b, _c, _d;
|
|
154
|
-
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);
|
|
155
212
|
if (markers.length === 0)
|
|
156
213
|
return [];
|
|
157
214
|
const paragraphs = this.body.paragraphs;
|
|
@@ -292,11 +349,14 @@ function nestedIndex(owner, index) {
|
|
|
292
349
|
}
|
|
293
350
|
/** A paragraph of a comment: the `CommentText` style, opened by the annotation reference run. */
|
|
294
351
|
function commentParagraph(text, first) {
|
|
352
|
+
var _a;
|
|
295
353
|
const runs = [];
|
|
296
354
|
if (first)
|
|
297
355
|
runs.push(annotationRefRun());
|
|
298
|
-
|
|
299
|
-
|
|
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);
|
|
300
360
|
return paragraphOf(runs, { TYPE_NAME: 'org_docx4j_wml.PPr', pStyle: { val: COMMENT_TEXT_STYLE } });
|
|
301
361
|
}
|
|
302
362
|
function insertAt(owner, index, items, parent) {
|
|
@@ -307,6 +367,18 @@ function insertAt(owner, index, items, parent) {
|
|
|
307
367
|
function parentOf(element) {
|
|
308
368
|
return element.value.PARENT;
|
|
309
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
|
+
}
|
|
310
382
|
/**
|
|
311
383
|
* Where a marker for this segment's run goes when it is not put inside the revision the run sits
|
|
312
384
|
* in (`placeAround`): beside the run, but outside the `w:ins` or `w:del`, so that a comment made
|
|
@@ -323,10 +395,17 @@ function markerSite(seg, fallback, after) {
|
|
|
323
395
|
function placeAround(range, id) {
|
|
324
396
|
var _a;
|
|
325
397
|
var _b;
|
|
398
|
+
if (range.spansParagraphs) {
|
|
399
|
+
placeAcross(range, id);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
326
402
|
const paragraph = range.paragraph;
|
|
327
|
-
|
|
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)
|
|
328
405
|
if (range.end > range.start)
|
|
329
|
-
paragraph.
|
|
406
|
+
paragraph.splitRunsAround(range.start, range.end);
|
|
407
|
+
else
|
|
408
|
+
paragraph.splitAt(range.start);
|
|
330
409
|
const covered = range.end > range.start ? paragraph.segments().filter((s) => s.end > range.start && s.start < range.end) : [];
|
|
331
410
|
const start = el.commentRangeStart(wmlFactory.createCommentRangeStart({ id }));
|
|
332
411
|
const end = el.commentRangeEnd(wmlFactory.createCommentRangeEnd({ id }));
|
|
@@ -369,16 +448,90 @@ function placeAround(range, id) {
|
|
|
369
448
|
insertAt(before.owner, before.index, [start], before.parent);
|
|
370
449
|
}
|
|
371
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
|
+
}
|
|
372
505
|
/** Writes the markers of a reply next to its parent's, as Word nests them. */
|
|
373
506
|
function placeAfter(body, parentId, id) {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
const
|
|
378
|
-
|
|
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')) {
|
|
379
522
|
// refused before anything is written, so that no marker is left naming a comment never made
|
|
380
523
|
throw new Docx4JException(`Comment ${parentId} has no markers in this body; cannot anchor a reply`);
|
|
381
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;
|
|
382
535
|
if (start)
|
|
383
536
|
insertAt(start.owner, start.owner.indexOf(start.item) + 1, [el.commentRangeStart(wmlFactory.createCommentRangeStart({ id }))], parentOf(start.item));
|
|
384
537
|
if (end)
|
|
@@ -398,13 +551,14 @@ function addComment(parts, body, id, paragraphs, parent, options) {
|
|
|
398
551
|
var _a, _b, _c, _d, _e, _f;
|
|
399
552
|
var _g, _h;
|
|
400
553
|
const author = (_a = options === null || options === void 0 ? void 0 : options.author) !== null && _a !== void 0 ? _a : parts.author;
|
|
401
|
-
// one instant for w:date (the local wall clock, as Word writes it) and w16cex:dateUtc (UTC)
|
|
402
|
-
|
|
554
|
+
// one instant for w:date (the local wall clock in the package's zone, as Word writes it) and w16cex:dateUtc (UTC);
|
|
555
|
+
// a new comment is stamped to the minute, as a revision is and as Word stamps (CR-018, the date rule's point 5)
|
|
556
|
+
const made = (_b = options === null || options === void 0 ? void 0 : options.date) !== null && _b !== void 0 ? _b : nowToTheMinute();
|
|
403
557
|
const paraId = randomHexId((candidate) => paraIdTaken(parts, body.container, candidate));
|
|
404
558
|
paragraphs[0].value.paraId = paraId;
|
|
405
559
|
const comment = wmlFactory.createCommentsComment({
|
|
406
560
|
id, author: author.name, initials: (_c = options === null || options === void 0 ? void 0 : options.initials) !== null && _c !== void 0 ? _c : initialsOf(author),
|
|
407
|
-
date: wordCalendarOf(made),
|
|
561
|
+
date: wordCalendarOf(made, zoneOf(body.package_)),
|
|
408
562
|
content: paragraphs,
|
|
409
563
|
});
|
|
410
564
|
const comments = ((_d = (_g = parts.comments).comment) !== null && _d !== void 0 ? _d : (_g.comment = []));
|
|
@@ -513,8 +667,9 @@ function commentId(parts, body, options) {
|
|
|
513
667
|
}
|
|
514
668
|
/** The paragraphs of a comment's content: a string splits on newlines, elements are taken as they are. */
|
|
515
669
|
function paragraphsOfContent(content) {
|
|
670
|
+
// a paragraph per line, at \r, \n or \r\n, as Word's comments take them (CR-002 section 60 D5, check 55)
|
|
516
671
|
if (typeof content === 'string')
|
|
517
|
-
return content.split(
|
|
672
|
+
return content.split(/\r\n|\r|\n/).map((line, i) => commentParagraph(line, i === 0));
|
|
518
673
|
const paragraphs = [...content];
|
|
519
674
|
if (paragraphs.length === 0)
|
|
520
675
|
throw new Docx4JException('A comment needs at least one paragraph');
|
|
@@ -549,6 +704,7 @@ export async function commentsOf(scope) {
|
|
|
549
704
|
* Comments whose anchored text went with a rejected insertion or an accepted deletion (check 32;
|
|
550
705
|
* `TrackedChange`'s `removeRevision`) had their markers removed then; their entries go here, with
|
|
551
706
|
* their replies, when the comments are next read or the package is saved (`WordprocessingMLPackage.saveTo`).
|
|
707
|
+
* With the last comment, the comment parts go too (`flushPendingRemovals`).
|
|
552
708
|
*/
|
|
553
709
|
export async function flushPendingCommentRemovals(body) {
|
|
554
710
|
var _a;
|
|
@@ -562,18 +718,39 @@ export async function flushPendingCommentRemovals(body) {
|
|
|
562
718
|
}
|
|
563
719
|
await flushPendingRemovals(body, parts);
|
|
564
720
|
}
|
|
721
|
+
/**
|
|
722
|
+
* The entries of the comments a resolution took away, replies included. The side parts the document
|
|
723
|
+
* has are loaded for it and none is created: before section 54 a removal created the commentsExtended,
|
|
724
|
+
* commentsIds and people parts a document lacked, as `delete()` does.
|
|
725
|
+
*
|
|
726
|
+
* With the last comment a resolution takes away, the comment parts go, as Word 365 removed them
|
|
727
|
+
* (docx4j CR-043 section 15; docx4j-python's artefact 8 rejected, docx4j's U22, core-ts check 32): the
|
|
728
|
+
* comments part and its commentsExtended, commentsIds and commentsExtensible parts, with their
|
|
729
|
+
* relationships; and the people part where no tracked change is left to name an author (U22: Word kept
|
|
730
|
+
* it while a deletion was still tracked). docx4j decides when its resolution ends; this, when the
|
|
731
|
+
* entries go, so tracked changes made or resolved in between count.
|
|
732
|
+
*/
|
|
565
733
|
async function flushPendingRemovals(body, parts) {
|
|
734
|
+
var _a;
|
|
566
735
|
const pkg = body.package_;
|
|
567
736
|
const pending = pkg === null || pkg === void 0 ? void 0 : pkg.pendingCommentRemovals;
|
|
568
737
|
if (!(pending === null || pending === void 0 ? void 0 : pending.size))
|
|
569
738
|
return;
|
|
739
|
+
await parts.loadExisting();
|
|
570
740
|
const views = viewsOf(parts, body);
|
|
741
|
+
let removed = false;
|
|
571
742
|
for (const id of [...pending]) {
|
|
572
743
|
const view = views.get(id);
|
|
573
|
-
if (view)
|
|
574
|
-
|
|
744
|
+
if (view) {
|
|
745
|
+
view.removeThread();
|
|
746
|
+
removed = true;
|
|
747
|
+
}
|
|
575
748
|
pending.delete(id);
|
|
576
749
|
}
|
|
750
|
+
if (!removed || ((_a = parts.comments.comment) !== null && _a !== void 0 ? _a : []).length > 0)
|
|
751
|
+
return;
|
|
752
|
+
const people = parts.people !== undefined && (pkg === null || pkg === void 0 ? void 0 : pkg.getAllTrackedChanges) !== undefined && (await pkg.getAllTrackedChanges()).length === 0;
|
|
753
|
+
parts.drop(people);
|
|
577
754
|
}
|
|
578
755
|
/** A `Comment` view per entry in the parts, replies linked to their parents. */
|
|
579
756
|
function viewsOf(parts, body) {
|
|
@@ -602,7 +779,7 @@ function idsInRange(range) {
|
|
|
602
779
|
var _a;
|
|
603
780
|
const spans = new Map();
|
|
604
781
|
const order = [];
|
|
605
|
-
for (const marker of markersOfParagraph(range.paragraph.element, range.paragraph.container)) {
|
|
782
|
+
for (const marker of markersOfParagraph(range.paragraph.element, range.paragraph.container, range.paragraph.hiddenRuns())) {
|
|
606
783
|
const at = (_a = marker.offset) !== null && _a !== void 0 ? _a : 0;
|
|
607
784
|
const span = spans.get(marker.id);
|
|
608
785
|
if (span) {
|
|
@@ -621,3 +798,7 @@ function unique(ids) {
|
|
|
621
798
|
return ids.filter((id) => (seen.has(id) ? false : (seen.add(id), true)));
|
|
622
799
|
}
|
|
623
800
|
setCommentApi({ commentsOf, insertComment });
|
|
801
|
+
/** The package's `dateTimeZone` (CR-018), read duck-typed since the package module cannot be imported here. */
|
|
802
|
+
function zoneOf(pkg) {
|
|
803
|
+
return pkg === null || pkg === void 0 ? void 0 : pkg.dateTimeZone;
|
|
804
|
+
}
|