@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
|
@@ -34,6 +34,8 @@ export declare function findAll(text: string, pattern: RegExp): [number, number]
|
|
|
34
34
|
* section 32 item 1, found by the editor's agreement suite). The clusters are `Intl.Segmenter`'s,
|
|
35
35
|
* computed only for a text with a code unit at or above U+0300, below which every code unit is a
|
|
36
36
|
* cluster of its own, so Latin text pays nothing; a runtime without `Intl.Segmenter` keeps every match.
|
|
37
|
+
* Only the stretches between control characters that a match's ends fall in are segmented, each once
|
|
38
|
+
* (`graphemeBoundaries`), so a search across a long body's paragraphs costs what each paragraph's does.
|
|
37
39
|
*/
|
|
38
40
|
export declare function matchesOf(text: string, pattern: RegExp): RegExpExecArray[];
|
|
39
41
|
/**
|
|
@@ -43,3 +45,75 @@ export declare function matchesOf(text: string, pattern: RegExp): RegExpExecArra
|
|
|
43
45
|
* to nothing, as both languages do.
|
|
44
46
|
*/
|
|
45
47
|
export declare function expandReplacement(replacement: string, match: RegExpExecArray, options?: SearchOptions): string;
|
|
48
|
+
/** What `officeMatches` reads of a paragraph: its segments in Office JS's characters, the objects and hidden items listed. */
|
|
49
|
+
export interface SearchSegment {
|
|
50
|
+
text: string;
|
|
51
|
+
start: number;
|
|
52
|
+
object?: boolean;
|
|
53
|
+
hidden?: boolean;
|
|
54
|
+
item: {
|
|
55
|
+
name: {
|
|
56
|
+
localPart: string;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** One match, as offsets in `Paragraph.text`, with the expression's match over the search's own text. */
|
|
61
|
+
export interface OfficeMatch {
|
|
62
|
+
start: number;
|
|
63
|
+
end: number;
|
|
64
|
+
match: RegExpExecArray;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Every match of a query in a paragraph's text by Office JS's rules (check 48, Word's default view): the
|
|
68
|
+
* text is `Paragraph.text` (hidden text left out, so a query matches across it and never in it), where a
|
|
69
|
+
* picture is a place of no text that a plain query doesn't match across and `^g` matches, and an optional
|
|
70
|
+
* hyphen is passed over unless the query names it (`^-`). A plain query takes Word's Find codes
|
|
71
|
+
* (`FIND_CODES`), and its `-` matches a non-breaking hyphen too. Wildcards read the same text, the codes
|
|
72
|
+
* not translated; a regular expression (`matchRegExp`, this package's extension) reads `Paragraph.text`
|
|
73
|
+
* itself. Only text in [from, to) is read: a range's search.
|
|
74
|
+
*/
|
|
75
|
+
export declare function officeMatches(segments: readonly SearchSegment[], query: string, options?: SearchOptions, from?: number, to?: number): OfficeMatch[];
|
|
76
|
+
/** A paragraph's part in a wildcard search across its marks: its segments, the [from, to) of its text read, its text's length, whether its mark follows. */
|
|
77
|
+
export interface MarkedSegments {
|
|
78
|
+
segments: readonly SearchSegment[];
|
|
79
|
+
from: number;
|
|
80
|
+
to: number;
|
|
81
|
+
length: number;
|
|
82
|
+
mark: boolean;
|
|
83
|
+
}
|
|
84
|
+
/** A hit of a wildcard search across marks: from offset `start` in piece `first` to `end` in piece `last`, which holds its mark where `mark`. */
|
|
85
|
+
export interface MarkedMatch {
|
|
86
|
+
first: number;
|
|
87
|
+
start: number;
|
|
88
|
+
last: number;
|
|
89
|
+
end: number;
|
|
90
|
+
mark: boolean;
|
|
91
|
+
match: RegExpExecArray;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* A wildcard query's hits over consecutive paragraphs, each followed by its mark where `mark` says, as Word's wildcards
|
|
95
|
+
* match a paragraph mark (check 59; CR-002 section 32, K7): `?`, `*` and a class cross one, `^13` is one. The text read
|
|
96
|
+
* in each paragraph is `officeMatches`' for wildcards; the caller gives only paragraphs a hit may span (one cell's, or
|
|
97
|
+
* none's) and only the marks it may hold (a paragraph's own, never a cell's or a row's end).
|
|
98
|
+
*/
|
|
99
|
+
export declare function wildcardMatchesAcross(pieces: readonly MarkedSegments[], query: string, options: SearchOptions): MarkedMatch[];
|
|
100
|
+
/**
|
|
101
|
+
* Refuses a wildcard replacement where a hit holds a paragraph mark (CR-002 section 32, K7): `search` finds it, as
|
|
102
|
+
* Word's does (check 59), but what replacing a mark leaves isn't measured, as for a plain `^p` (`refuseMarkReplacement`).
|
|
103
|
+
*/
|
|
104
|
+
export declare function refuseWildcardMarkReplacement(className: string, hits: readonly {
|
|
105
|
+
spansParagraphs: boolean;
|
|
106
|
+
holdsEndMark: boolean;
|
|
107
|
+
}[]): void;
|
|
108
|
+
/**
|
|
109
|
+
* A plain query split at Word's paragraph mark code, `^p`: its pieces, one more than the marks, each a plain
|
|
110
|
+
* query of its own (`^^` stays an escaped caret); undefined where the query holds no `^p`. What a `Range`'s search
|
|
111
|
+
* across paragraphs matches piece by piece (CR-014 phase 3).
|
|
112
|
+
*/
|
|
113
|
+
export declare function paragraphMarkPieces(query: string): string[] | undefined;
|
|
114
|
+
/**
|
|
115
|
+
* Refuses a replacement whose query holds `^p` (CR-014 phase 3): `search` finds such a hit, but what Office JS's
|
|
116
|
+
* replacement of a paragraph mark leaves isn't measured, and `insertText('Replace')` keeps a last mark (check 52).
|
|
117
|
+
* Until phase 3 such a query matched the two characters `^p`, where Word matches a mark.
|
|
118
|
+
*/
|
|
119
|
+
export declare function refuseMarkReplacement(className: string, find: string, options?: SearchOptions): void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Docx4JException } from '../../opc/exceptions.mjs';
|
|
2
|
+
import { NotSupportedError } from '../../office-js/errors.mjs';
|
|
2
3
|
/** A regular expression for a search text under the options; global so it can iterate matches. */
|
|
3
4
|
export function searchPattern(text, options = {}) {
|
|
4
5
|
if (options.matchRegExp && options.matchWildcards) {
|
|
@@ -19,10 +20,17 @@ export function searchPattern(text, options = {}) {
|
|
|
19
20
|
source = '';
|
|
20
21
|
for (let i = 0; i < text.length; i++) {
|
|
21
22
|
const c = text[i];
|
|
23
|
+
// a code point, a surrogate pair whole, as Word's ? matches an emoji (check 58 case 13; CR-002 section 32, K4);
|
|
24
|
+
// ? and * cross a paragraph's mark where a search reads one (`wildcardMatchesAcross`, check 59, K7)
|
|
22
25
|
if (c === '?')
|
|
23
|
-
source += '
|
|
26
|
+
source += '(?:[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\s\\S])';
|
|
24
27
|
else if (c === '*')
|
|
25
|
-
source += '
|
|
28
|
+
source += '[\\s\\S]*?';
|
|
29
|
+
// ^13, Word's wildcard code for a paragraph mark (check 59)
|
|
30
|
+
else if (c === '^' && text.startsWith('13', i + 1)) {
|
|
31
|
+
source += '\\r';
|
|
32
|
+
i += 2;
|
|
33
|
+
}
|
|
26
34
|
else if (c === '<')
|
|
27
35
|
source += '\\b(?=\\w)';
|
|
28
36
|
else if (c === '>')
|
|
@@ -102,6 +110,8 @@ export function findAll(text, pattern) {
|
|
|
102
110
|
* section 32 item 1, found by the editor's agreement suite). The clusters are `Intl.Segmenter`'s,
|
|
103
111
|
* computed only for a text with a code unit at or above U+0300, below which every code unit is a
|
|
104
112
|
* cluster of its own, so Latin text pays nothing; a runtime without `Intl.Segmenter` keeps every match.
|
|
113
|
+
* Only the stretches between control characters that a match's ends fall in are segmented, each once
|
|
114
|
+
* (`graphemeBoundaries`), so a search across a long body's paragraphs costs what each paragraph's does.
|
|
105
115
|
*/
|
|
106
116
|
export function matchesOf(text, pattern) {
|
|
107
117
|
const out = [];
|
|
@@ -113,20 +123,62 @@ export function matchesOf(text, pattern) {
|
|
|
113
123
|
}
|
|
114
124
|
out.push(m);
|
|
115
125
|
}
|
|
116
|
-
const
|
|
117
|
-
return
|
|
126
|
+
const isBoundary = out.length > 0 ? graphemeBoundaries(text) : undefined;
|
|
127
|
+
return isBoundary === undefined ? out : out.filter((m) => isBoundary(m.index) && isBoundary(m.index + m[0].length));
|
|
118
128
|
}
|
|
119
|
-
/**
|
|
129
|
+
/** A C0 or C1 control character: a grapheme cluster of its own, always a break before and after it but between CR and LF (UAX #29, GB3 to GB5). */
|
|
130
|
+
const isControl = (code) => code < 0x20 || (code >= 0x7F && code < 0xA0);
|
|
131
|
+
/**
|
|
132
|
+
* Whether a grapheme cluster starts at a code-unit offset (the text's end counts); undefined where every unit is its own
|
|
133
|
+
* cluster. A control character always has a break before and after it, and no rule looks back past one, so each stretch
|
|
134
|
+
* between controls (a paragraph's, in a search across marks) is segmented on its own, as it would be within the whole
|
|
135
|
+
* text, and only the stretches asked about, each once. V8's segmenter is quadratic in its input's length: the whole of a
|
|
136
|
+
* 510,000-character body didn't come back in 100 s (the editor's finding, 2026-10-26; CR-002 section 64).
|
|
137
|
+
*/
|
|
120
138
|
function graphemeBoundaries(text) {
|
|
121
139
|
if (!/[\u0300-\uffff]/.test(text))
|
|
122
140
|
return undefined;
|
|
123
141
|
const Segmenter = Intl.Segmenter;
|
|
124
142
|
if (Segmenter === undefined)
|
|
125
143
|
return undefined;
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
144
|
+
const segmenter = new Segmenter(undefined, { granularity: 'grapheme' });
|
|
145
|
+
const controls = [];
|
|
146
|
+
for (let i = 0; i < text.length; i++)
|
|
147
|
+
if (isControl(text.charCodeAt(i)))
|
|
148
|
+
controls.push(i);
|
|
149
|
+
// each stretch's cluster starts, by the stretch's start; undefined where every unit of it is its own cluster
|
|
150
|
+
const stretches = new Map();
|
|
151
|
+
return (at) => {
|
|
152
|
+
if (at <= 0 || at >= text.length)
|
|
153
|
+
return true;
|
|
154
|
+
const before = text.charCodeAt(at - 1);
|
|
155
|
+
const after = text.charCodeAt(at);
|
|
156
|
+
if (isControl(before) || isControl(after))
|
|
157
|
+
return before !== 0x0D || after !== 0x0A;
|
|
158
|
+
// the stretch holding `at`: from just after the last control before it to the first control after it
|
|
159
|
+
let lo = 0;
|
|
160
|
+
let hi = controls.length;
|
|
161
|
+
while (lo < hi) {
|
|
162
|
+
const mid = (lo + hi) >> 1;
|
|
163
|
+
if (controls[mid] < at)
|
|
164
|
+
lo = mid + 1;
|
|
165
|
+
else
|
|
166
|
+
hi = mid;
|
|
167
|
+
}
|
|
168
|
+
const start = lo > 0 ? controls[lo - 1] + 1 : 0;
|
|
169
|
+
if (!stretches.has(start)) {
|
|
170
|
+
const stretch = text.slice(start, lo < controls.length ? controls[lo] : text.length);
|
|
171
|
+
let starts;
|
|
172
|
+
if (/[\u0300-\uffff]/.test(stretch)) {
|
|
173
|
+
starts = new Set();
|
|
174
|
+
for (const segment of segmenter.segment(stretch))
|
|
175
|
+
starts.add(start + segment.index);
|
|
176
|
+
}
|
|
177
|
+
stretches.set(start, starts);
|
|
178
|
+
}
|
|
179
|
+
const starts = stretches.get(start);
|
|
180
|
+
return starts === undefined || starts.has(at);
|
|
181
|
+
};
|
|
130
182
|
}
|
|
131
183
|
/**
|
|
132
184
|
* A replacement with its group references expanded against one match: `$1` to `$9`, `$&` and `$$`
|
|
@@ -143,3 +195,197 @@ export function expandReplacement(replacement, match, options = {}) {
|
|
|
143
195
|
}
|
|
144
196
|
return replacement;
|
|
145
197
|
}
|
|
198
|
+
/** The object replacement character: a picture's place in the text `search` reads, which `^g` matches. */
|
|
199
|
+
const OBJECT = '';
|
|
200
|
+
/**
|
|
201
|
+
* Word's Find codes a plain query may hold (check 48: each matched its character in Office JS's text):
|
|
202
|
+
* `^f` a footnote reference, `^e` an endnote reference, `^l` a line break, `^m` a page break, `^t` a tab,
|
|
203
|
+
* `^~` a non-breaking hyphen, `^-` an optional hyphen, `^g` a picture, `^^` a caret.
|
|
204
|
+
*/
|
|
205
|
+
const FIND_CODES = { f: '\u0002', e: '\u0002', l: '\u000B', m: '\u000C', t: '\t', '~': '\u001E', '-': '\u001F', g: OBJECT, '^': '^' };
|
|
206
|
+
/**
|
|
207
|
+
* Every match of a query in a paragraph's text by Office JS's rules (check 48, Word's default view): the
|
|
208
|
+
* text is `Paragraph.text` (hidden text left out, so a query matches across it and never in it), where a
|
|
209
|
+
* picture is a place of no text that a plain query doesn't match across and `^g` matches, and an optional
|
|
210
|
+
* hyphen is passed over unless the query names it (`^-`). A plain query takes Word's Find codes
|
|
211
|
+
* (`FIND_CODES`), and its `-` matches a non-breaking hyphen too. Wildcards read the same text, the codes
|
|
212
|
+
* not translated; a regular expression (`matchRegExp`, this package's extension) reads `Paragraph.text`
|
|
213
|
+
* itself. Only text in [from, to) is read: a range's search.
|
|
214
|
+
*/
|
|
215
|
+
export function officeMatches(segments, query, options = {}, from = 0, to = Number.POSITIVE_INFINITY) {
|
|
216
|
+
const plain = !options.matchRegExp && !options.matchWildcards;
|
|
217
|
+
const keepSoftHyphens = !plain || /\^-/.test(query.replace(/\^\^/g, ''));
|
|
218
|
+
let pattern;
|
|
219
|
+
let tokens = [];
|
|
220
|
+
if (plain) {
|
|
221
|
+
const translated = plainQuery(query);
|
|
222
|
+
tokens = translated.tokens;
|
|
223
|
+
pattern = patternOf(translated.source, options);
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
pattern = searchPattern(query, options);
|
|
227
|
+
}
|
|
228
|
+
// the usual paragraph: nothing but text, no optional hyphen to pass over, no reference a code must tell
|
|
229
|
+
// apart, so the text searched is Paragraph.text's own [from, to), each offset itself
|
|
230
|
+
if (segments.every((seg) => !seg.object && !seg.hidden) && tokens.every((kind) => kind === undefined)) {
|
|
231
|
+
const whole = segments.map((seg) => seg.text).join('');
|
|
232
|
+
const start = Math.max(0, from);
|
|
233
|
+
const span = whole.substring(start, Math.min(whole.length, to));
|
|
234
|
+
if (keepSoftHyphens || !span.includes('\u001F')) {
|
|
235
|
+
return matchesOf(span, pattern).map((match) => ({ start: start + match.index, end: start + match.index + match[0].length, match }));
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
let text = '';
|
|
239
|
+
const starts = [];
|
|
240
|
+
const ends = [];
|
|
241
|
+
const notes = [];
|
|
242
|
+
for (const seg of segments) {
|
|
243
|
+
if (seg.hidden)
|
|
244
|
+
continue;
|
|
245
|
+
if (seg.object) {
|
|
246
|
+
if (!options.matchRegExp && from < seg.start && seg.start < to) {
|
|
247
|
+
text += OBJECT;
|
|
248
|
+
starts.push(seg.start);
|
|
249
|
+
ends.push(seg.start);
|
|
250
|
+
notes.push(undefined);
|
|
251
|
+
}
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
for (let i = 0; i < seg.text.length; i++) {
|
|
255
|
+
const at = seg.start + i;
|
|
256
|
+
if (at < from || at >= to)
|
|
257
|
+
continue;
|
|
258
|
+
const c = seg.text[i];
|
|
259
|
+
if (c === '\u001F' && !keepSoftHyphens)
|
|
260
|
+
continue;
|
|
261
|
+
text += c;
|
|
262
|
+
starts.push(at);
|
|
263
|
+
ends.push(at + 1);
|
|
264
|
+
notes.push(c === '\u0002' ? seg.item.name.localPart : undefined);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
const out = [];
|
|
268
|
+
for (const match of matchesOf(text, pattern)) {
|
|
269
|
+
const a = match.index;
|
|
270
|
+
const b = a + match[0].length;
|
|
271
|
+
// ^f and ^e both read U+0002: each matches only its own kind of reference
|
|
272
|
+
if (tokens.some((kind, i) => { var _a; return kind !== undefined && !((_a = notes[a + i]) !== null && _a !== void 0 ? _a : '').startsWith(kind); }))
|
|
273
|
+
continue;
|
|
274
|
+
out.push({ start: starts[a], end: ends[b - 1], match });
|
|
275
|
+
}
|
|
276
|
+
return out;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* A wildcard query's hits over consecutive paragraphs, each followed by its mark where `mark` says, as Word's wildcards
|
|
280
|
+
* match a paragraph mark (check 59; CR-002 section 32, K7): `?`, `*` and a class cross one, `^13` is one. The text read
|
|
281
|
+
* in each paragraph is `officeMatches`' for wildcards; the caller gives only paragraphs a hit may span (one cell's, or
|
|
282
|
+
* none's) and only the marks it may hold (a paragraph's own, never a cell's or a row's end).
|
|
283
|
+
*/
|
|
284
|
+
export function wildcardMatchesAcross(pieces, query, options) {
|
|
285
|
+
const pattern = searchPattern(query, { ...options, matchWildcards: true });
|
|
286
|
+
let text = '';
|
|
287
|
+
const starts = [];
|
|
288
|
+
const ends = [];
|
|
289
|
+
const marks = [];
|
|
290
|
+
const put = (c, k, start, end, mark) => { text += c; starts.push([k, start]); ends.push([k, end]); marks.push(mark); };
|
|
291
|
+
pieces.forEach((piece, k) => {
|
|
292
|
+
for (const seg of piece.segments) {
|
|
293
|
+
if (seg.hidden)
|
|
294
|
+
continue;
|
|
295
|
+
if (seg.object) {
|
|
296
|
+
if (piece.from < seg.start && seg.start < piece.to)
|
|
297
|
+
put(OBJECT, k, seg.start, seg.start, false);
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
for (let i = 0; i < seg.text.length; i++) {
|
|
301
|
+
const at = seg.start + i;
|
|
302
|
+
if (at >= piece.from && at < piece.to)
|
|
303
|
+
put(seg.text[i], k, at, at + 1, false);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
if (piece.mark)
|
|
307
|
+
put('\r', k, piece.length, piece.length, true);
|
|
308
|
+
});
|
|
309
|
+
return matchesOf(text, pattern).map((match) => {
|
|
310
|
+
const a = match.index;
|
|
311
|
+
const b = a + match[0].length;
|
|
312
|
+
return { first: starts[a][0], start: starts[a][1], last: ends[b - 1][0], end: ends[b - 1][1], mark: marks[b - 1], match };
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Refuses a wildcard replacement where a hit holds a paragraph mark (CR-002 section 32, K7): `search` finds it, as
|
|
317
|
+
* Word's does (check 59), but what replacing a mark leaves isn't measured, as for a plain `^p` (`refuseMarkReplacement`).
|
|
318
|
+
*/
|
|
319
|
+
export function refuseWildcardMarkReplacement(className, hits) {
|
|
320
|
+
if (!hits.some((hit) => hit.spansParagraphs || hit.holdsEndMark))
|
|
321
|
+
return;
|
|
322
|
+
throw new NotSupportedError(className, 'replaceText', "a hit holds a paragraph mark, which Word's wildcards match (check 59), and what replacing "
|
|
323
|
+
+ 'one does isn\'t measured (CR-002 section 32); search for the hits and edit their ranges');
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* A plain query split at Word's paragraph mark code, `^p`: its pieces, one more than the marks, each a plain
|
|
327
|
+
* query of its own (`^^` stays an escaped caret); undefined where the query holds no `^p`. What a `Range`'s search
|
|
328
|
+
* across paragraphs matches piece by piece (CR-014 phase 3).
|
|
329
|
+
*/
|
|
330
|
+
export function paragraphMarkPieces(query) {
|
|
331
|
+
const pieces = [];
|
|
332
|
+
let piece = '';
|
|
333
|
+
for (let i = 0; i < query.length; i++) {
|
|
334
|
+
const c = query[i];
|
|
335
|
+
if (c === '^' && query[i + 1] === 'p') {
|
|
336
|
+
pieces.push(piece);
|
|
337
|
+
piece = '';
|
|
338
|
+
i++;
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
if (c === '^' && i + 1 < query.length) {
|
|
342
|
+
piece += c + query[i + 1];
|
|
343
|
+
i++;
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
piece += c;
|
|
347
|
+
}
|
|
348
|
+
if (pieces.length === 0)
|
|
349
|
+
return undefined;
|
|
350
|
+
pieces.push(piece);
|
|
351
|
+
return pieces;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Refuses a replacement whose query holds `^p` (CR-014 phase 3): `search` finds such a hit, but what Office JS's
|
|
355
|
+
* replacement of a paragraph mark leaves isn't measured, and `insertText('Replace')` keeps a last mark (check 52).
|
|
356
|
+
* Until phase 3 such a query matched the two characters `^p`, where Word matches a mark.
|
|
357
|
+
*/
|
|
358
|
+
export function refuseMarkReplacement(className, find, options) {
|
|
359
|
+
if ((options === null || options === void 0 ? void 0 : options.matchWildcards) || (options === null || options === void 0 ? void 0 : options.matchRegExp) || !paragraphMarkPieces(find))
|
|
360
|
+
return;
|
|
361
|
+
throw new NotSupportedError(className, 'replaceText', "the query holds ^p, Word's paragraph mark, and what replacing one does isn't "
|
|
362
|
+
+ "measured (CR-014 phase 3); search for the hits and edit their ranges");
|
|
363
|
+
}
|
|
364
|
+
/** A plain query as an expression over `officeMatches`' text, and which of its characters are `^f` or `^e`. */
|
|
365
|
+
function plainQuery(query) {
|
|
366
|
+
let source = '';
|
|
367
|
+
const tokens = [];
|
|
368
|
+
for (let i = 0; i < query.length; i++) {
|
|
369
|
+
const c = query[i];
|
|
370
|
+
const code = c === '^' ? query[i + 1] : undefined;
|
|
371
|
+
if (code !== undefined && FIND_CODES[code] !== undefined) {
|
|
372
|
+
source += escapeRegExp(FIND_CODES[code]);
|
|
373
|
+
tokens.push(code === 'f' ? 'footnote' : code === 'e' ? 'endnote' : undefined);
|
|
374
|
+
i++;
|
|
375
|
+
}
|
|
376
|
+
else if (c === '-') {
|
|
377
|
+
source += '[-\\u001E]'; // a non-breaking hyphen is a hyphen to a plain query
|
|
378
|
+
tokens.push(undefined);
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
source += escapeRegExp(c);
|
|
382
|
+
tokens.push(undefined);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return { source, tokens };
|
|
386
|
+
}
|
|
387
|
+
/** `searchPattern`'s flags and whole-word guard over a source already written as an expression. */
|
|
388
|
+
function patternOf(source, options) {
|
|
389
|
+
const guarded = options.matchWholeWord ? `(?<![\\w])${source}(?![\\w])` : source;
|
|
390
|
+
return new RegExp(guarded, options.matchCase ? 'g' : 'gi');
|
|
391
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import type * as wml from '@docx4j/generated-objects-ts/modules/org_docx4j_wml';
|
|
2
|
+
import { type RunOptions } from '@docx4j/generated-objects-ts/builders/wml';
|
|
3
|
+
import { type Element } from './tree.mjs';
|
|
4
|
+
import type { Paragraph } from './Paragraph.mjs';
|
|
5
|
+
/** What a write needs of the `Range` it writes: its two ends, and whether it holds its last paragraph's mark. */
|
|
6
|
+
export interface Span {
|
|
7
|
+
readonly paragraph: Paragraph;
|
|
8
|
+
readonly endParagraph: Paragraph;
|
|
9
|
+
readonly start: number;
|
|
10
|
+
readonly end: number;
|
|
11
|
+
readonly whole: boolean;
|
|
12
|
+
/** The range holds its last paragraph's mark (a 'Whole' range), or a table's end in its place. */
|
|
13
|
+
readonly holdsEndMark: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Where a range's two ends stand in the innermost list of blocks holding both: the block holding the start and
|
|
17
|
+
* the block holding the end, each the end's paragraph itself, or a table or content control the range holds
|
|
18
|
+
* whole (a table's 'Whole' range, a body's that starts with a table).
|
|
19
|
+
*/
|
|
20
|
+
export interface Extent {
|
|
21
|
+
list: Element[];
|
|
22
|
+
first: number;
|
|
23
|
+
last: number;
|
|
24
|
+
/** The start's paragraph, where it is the first block itself (or in `headInside`); else that block goes whole. */
|
|
25
|
+
head?: Paragraph;
|
|
26
|
+
/** The end's paragraph, where it is the last block itself (or in `tailInside`); else that block goes whole. */
|
|
27
|
+
tail?: Paragraph;
|
|
28
|
+
/** Where the range starts inside a block content control at `first`: the control's list holding `head` (check 54 case 20). */
|
|
29
|
+
headInside?: Element[];
|
|
30
|
+
/** Where the range ends inside a block content control at `last`: the control's list holding `tail` (check 54 case 18). */
|
|
31
|
+
tailInside?: Element[];
|
|
32
|
+
}
|
|
33
|
+
/** Where a deletion closed up: the paragraph, and the offset in it a replacement's text goes at. */
|
|
34
|
+
export interface Landing {
|
|
35
|
+
paragraph: Paragraph;
|
|
36
|
+
offset: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The extent of a range, refusing one that starts or ends inside a block it doesn't hold whole. Inside a table
|
|
40
|
+
* that is Word's own refusal (check 52: `delete()` and `Replace` on a range from a cell to a paragraph after the
|
|
41
|
+
* table, or from a paragraph into a cell, threw `GeneralException` and changed nothing, tracked or not; D3).
|
|
42
|
+
* Inside a block content control, `crossControls` lets a range end in the control's own paragraphs, one level
|
|
43
|
+
* down, as `delete()` takes one (check 54 cases 18 to 20); anything else there is `NotSupportedError`.
|
|
44
|
+
*/
|
|
45
|
+
export declare function extentOf(span: Span, member: string, crossControls?: boolean): Extent;
|
|
46
|
+
/**
|
|
47
|
+
* Deletes a range across paragraphs, or one holding its last paragraph's mark, as Word does (check 52, cases 3 to
|
|
48
|
+
* 28; check 54, cases 5 to 20): the start's paragraph loses its text from the start, every block between goes whole
|
|
49
|
+
* (a table too), the end's paragraph loses its text to the end, and the two join in the end paragraph's properties,
|
|
50
|
+
* each run keeping its own formatting. A mark the range holds goes (`dropMark`): its paragraph joins the paragraph
|
|
51
|
+
* after it, in that one's properties (W1, W2; after a whole table the range took, case 5), or, with no paragraph
|
|
52
|
+
* after it, goes itself where its text went with the range (before a table, at a control's end: cases 8 and 12),
|
|
53
|
+
* a cell's last paragraph and a story's last kept (case 10). `keepLastMark` is `Replace`'s, which keeps it.
|
|
54
|
+
*
|
|
55
|
+
* A range ending (or starting) in a block content control's own paragraph, the other end outside it, joins
|
|
56
|
+
* nothing across the control's edge: the texts go, and the start's paragraph takes the end's paragraph properties
|
|
57
|
+
* (cases 18 to 20). A comment whose reference goes with the range goes too (case 27).
|
|
58
|
+
*
|
|
59
|
+
* Tracked, nothing is joined: the text is a `w:del`, every mark in the range is marked deleted but a last one the
|
|
60
|
+
* range doesn't hold, or that can't go (a cell's last), and a table's rows and its cells' marks are deleted, with no
|
|
61
|
+
* `w:pPrChange` (Word's markup in its save after check 52's run). Accepting gives the untracked answer.
|
|
62
|
+
*/
|
|
63
|
+
export declare function deleteSpan(span: Span, extent: Extent, keepLastMark: boolean): Landing | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Refuses, before anything changes, a tracked deletion of a range holding a whole `w:altChunk` or kept
|
|
66
|
+
* `mc:AlternateContent`: neither has a deleted form, and Accept All would leave it where the untracked deletion
|
|
67
|
+
* takes it, the paragraphs either side unjoined. A content control or custom XML element held whole is deleted as
|
|
68
|
+
* Word deletes one (check 54 cases 15 and 17: `markHolderDeleted`).
|
|
69
|
+
*/
|
|
70
|
+
export declare function assertTrackable(extent: Extent, member: string): void;
|
|
71
|
+
/** The first replaced character's run properties and where it stood, read before anything is deleted. */
|
|
72
|
+
export interface FirstCharacter {
|
|
73
|
+
rPr: wml.RPr | undefined;
|
|
74
|
+
pPr: wml.PPr | undefined;
|
|
75
|
+
p: wml.P;
|
|
76
|
+
}
|
|
77
|
+
/** The character at a range's start: its run's properties, or its paragraph's mark's where the range starts at the mark. */
|
|
78
|
+
export declare function firstCharacterOf(span: Span): FirstCharacter;
|
|
79
|
+
/**
|
|
80
|
+
* The run properties that give text in `into` the look the first replaced character had (check 52, cases 29 to
|
|
81
|
+
* 38): its run's own properties, and each property its paragraph's style gave it that `into`'s doesn't, written
|
|
82
|
+
* direct - a heading's font, size, colour and bold in a body paragraph (case 29), and a body paragraph's
|
|
83
|
+
* `w:b w:val="0"` and automatic colour in a heading (case 30). A property no style sets anywhere and `into`'s does
|
|
84
|
+
* is written as its neutral value where it has one (`NEUTRAL`).
|
|
85
|
+
*/
|
|
86
|
+
export declare function lookOf(first: FirstCharacter, into: Paragraph): wml.RPr | undefined;
|
|
87
|
+
/** The text of an untracked `Replace`, put where the deletion closed up, in the first replaced character's look. */
|
|
88
|
+
export declare function placeReplacement(landing: Landing, first: FirstCharacter, text: string): {
|
|
89
|
+
first: Paragraph;
|
|
90
|
+
last: Paragraph;
|
|
91
|
+
start: number;
|
|
92
|
+
end: number;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* A paragraph of `text` put at `offset` in `p`, as Word puts one where a range across paragraphs starts
|
|
96
|
+
* ('Before') or ends ('After') (check 52, cases 57 to 70): at the paragraph's start it goes before it and at its
|
|
97
|
+
* end after it, in its properties (`Paragraph.insertParagraph`); inside it `p` is split there (`splitParagraph`)
|
|
98
|
+
* and the new paragraph goes between the halves, its mark and its text in the formatting of the run before the
|
|
99
|
+
* split (case 63's italic). Tracked, the new paragraph and the first half's mark are inserted (cases 69 and 70).
|
|
100
|
+
* Returns the new paragraph, and the first half where `p` was split.
|
|
101
|
+
*/
|
|
102
|
+
export declare function insertParagraphAt(p: Paragraph, offset: number, text: string): {
|
|
103
|
+
inserted: Paragraph;
|
|
104
|
+
firstHalf?: Paragraph;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Paragraph breaks put into `p` at `offsets` (ascending, in its text), as Word's insertText writes a line feed or
|
|
108
|
+
* carriage return (CR-002 section 60 E1, check 55): at a split (`splitParagraph`), in the formatting of the run before
|
|
109
|
+
* it; at the paragraph's end an empty paragraph after it, at its start one before it, in its properties. Tracked, each
|
|
110
|
+
* new mark is inserted. Returns the first paragraph and the last, which holds what followed the last break.
|
|
111
|
+
*/
|
|
112
|
+
export declare function breakParagraphAt(p: Paragraph, offsets: readonly number[]): {
|
|
113
|
+
first: Paragraph;
|
|
114
|
+
last: Paragraph;
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Splits `p` at `offset`, inside its text: what is before it becomes a new paragraph in front of `p`, in a copy of
|
|
118
|
+
* its properties with a mark of its own in `rPr`'s formatting, and `p` keeps the rest with its own mark, its
|
|
119
|
+
* section break and its identity, as Word keeps them (check 52 cases 57 and 63). A link, a revision or a smart tag
|
|
120
|
+
* the offset is inside is split into two of the same; a complex field's result is split, the field running across the
|
|
121
|
+
* two, and a `w:fldSimple` is made a complex field first, as Word makes it (check 57, CR-002 section 62.2 D1); a content
|
|
122
|
+
* control or a kept `mc:AlternateContent` there is refused, since its two halves would be two of it. Tracked, the new
|
|
123
|
+
* mark is inserted, as Word marks the first half's (cases 69 and 70). Returns the first half.
|
|
124
|
+
*/
|
|
125
|
+
export declare function splitParagraph(p: Paragraph, offset: number, rPr: wml.RPr | undefined): Paragraph;
|
|
126
|
+
/**
|
|
127
|
+
* Word's form of a table put after the paragraph a table cell ends with (check 52, cases 86 and 87; CR-002 section 55.6):
|
|
128
|
+
* that paragraph is split at its end, as a paragraph break there splits it (`splitAtEnd`), the table between the halves,
|
|
129
|
+
* so the cell's mark stays last. The paragraph keeps its text and becomes the first half, whose new mark takes the
|
|
130
|
+
* formatting of the text before it and, tracked, is the inserted one; its properties as they were go after the table, in
|
|
131
|
+
* an empty paragraph, unmarked. The paragraph keeps its text, not its mark, so that a view of it (a `Range`) still holds it.
|
|
132
|
+
*/
|
|
133
|
+
export declare function keepCellMarkLast(p: Paragraph, cellContent: Element[]): void;
|
|
134
|
+
/** The run holders a paragraph split may cut in two: each half is a whole one of the same. */
|
|
135
|
+
export declare const SPLITTABLE: Set<string>;
|
|
136
|
+
/** The run holders a paragraph break may be made inside: those it cuts in two, and a `w:fldSimple`, made a complex field first (D1). */
|
|
137
|
+
export declare const BREAKABLE: ReadonlySet<string>;
|
|
138
|
+
/**
|
|
139
|
+
* Every `w:fldSimple` a run is inside, below the paragraph, made a complex field, the innermost first: what Word does
|
|
140
|
+
* before a paragraph break inside a simple field's result (check 57 cases 2 and 4, CR-002 section 62.2 D1). The caller
|
|
141
|
+
* has checked that every other holder there can be cut in two.
|
|
142
|
+
*/
|
|
143
|
+
export declare function unfoldSimpleFieldsAround(run: object, p: object): void;
|
|
144
|
+
/** A piece of a range in one paragraph: its runs, and whether the range holds the paragraph's mark. */
|
|
145
|
+
export interface FontPiece {
|
|
146
|
+
paragraph: Paragraph;
|
|
147
|
+
start: number;
|
|
148
|
+
end: number;
|
|
149
|
+
runs: () => Element<wml.R>[];
|
|
150
|
+
holdsMark: boolean;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* A `font` write over a range across paragraphs (check 52, cases 49 to 56): every run in the range, a table's
|
|
154
|
+
* cells' too, split at the range's ends, and each mark the range holds, as Word formats them. A property goes only
|
|
155
|
+
* where a run or mark doesn't read the value already (`reads`): Word wrote `w:b` on none of a heading's runs, bold
|
|
156
|
+
* through its style, and tracked no change there; nor `w:sz` on a heading's 14-point runs (check 54). Tracked, each
|
|
157
|
+
* run and mark changed has its `w:rPrChange` (case 56: the body paragraph's mark's).
|
|
158
|
+
*/
|
|
159
|
+
export declare function formatSpan(pieces: FontPiece[], opts: RunOptions): void;
|