@docx4j/core-ts 0.1.0 → 0.1.2
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/README.md +410 -10
- package/dist/model/content/Body.d.mts +109 -4
- package/dist/model/content/Body.mjs +300 -29
- package/dist/model/content/Comment.d.mts +78 -0
- package/dist/model/content/Comment.mjs +429 -0
- package/dist/model/content/ContentControl.d.mts +173 -0
- package/dist/model/content/ContentControl.mjs +638 -0
- package/dist/model/content/Font.d.mts +48 -8
- package/dist/model/content/Font.mjs +55 -13
- package/dist/model/content/InlinePicture.d.mts +103 -0
- package/dist/model/content/InlinePicture.mjs +361 -0
- package/dist/model/content/List.d.mts +253 -0
- package/dist/model/content/List.mjs +778 -0
- package/dist/model/content/Paragraph.d.mts +213 -16
- package/dist/model/content/Paragraph.mjs +611 -57
- package/dist/model/content/Range.d.mts +48 -4
- package/dist/model/content/Range.mjs +161 -4
- package/dist/model/content/Table.d.mts +130 -0
- package/dist/model/content/Table.mjs +429 -0
- package/dist/model/content/TrackedChange.d.mts +96 -0
- package/dist/model/content/TrackedChange.mjs +352 -0
- package/dist/model/content/comments.d.mts +122 -0
- package/dist/model/content/comments.mjs +248 -0
- package/dist/model/content/index.d.mts +13 -3
- package/dist/model/content/index.mjs +15 -3
- package/dist/model/content/ooxml.d.mts +17 -0
- package/dist/model/content/ooxml.mjs +214 -0
- package/dist/model/content/styles.d.mts +21 -0
- package/dist/model/content/styles.mjs +86 -0
- package/dist/model/content/tracking.d.mts +104 -0
- package/dist/model/content/tracking.mjs +313 -0
- package/dist/model/content/tree.d.mts +56 -9
- package/dist/model/content/tree.mjs +104 -31
- package/dist/model/customxml/CustomXmlPart.d.mts +158 -0
- package/dist/model/customxml/CustomXmlPart.mjs +415 -0
- package/dist/model/customxml/CustomXmlPartCollection.d.mts +68 -0
- package/dist/model/customxml/CustomXmlPartCollection.mjs +183 -0
- package/dist/model/customxml/XmlMapping.d.mts +46 -0
- package/dist/model/customxml/XmlMapping.mjs +98 -0
- package/dist/model/customxml/bindings.d.mts +41 -0
- package/dist/model/customxml/bindings.mjs +230 -0
- package/dist/model/customxml/index.d.mts +7 -0
- package/dist/model/customxml/index.mjs +9 -0
- package/dist/model/customxml/insert.d.mts +20 -0
- package/dist/model/customxml/insert.mjs +22 -0
- package/dist/model/customxml/kinds.d.mts +103 -0
- package/dist/model/customxml/kinds.mjs +267 -0
- package/dist/model/customxml/xpath.d.mts +52 -0
- package/dist/model/customxml/xpath.mjs +205 -0
- package/dist/model/fonts/CJKToEnglish.d.mts +2 -0
- package/dist/model/fonts/CJKToEnglish.mjs +16 -0
- package/dist/model/fonts/FontFallback.d.mts +58 -0
- package/dist/model/fonts/FontFallback.mjs +219 -0
- package/dist/model/fonts/IdentityPlusMapper.d.mts +7 -0
- package/dist/model/fonts/IdentityPlusMapper.mjs +19 -0
- package/dist/model/fonts/LanguageTagToScriptMapping.d.mts +7 -0
- package/dist/model/fonts/LanguageTagToScriptMapping.mjs +67 -0
- package/dist/model/fonts/Mapper.d.mts +190 -0
- package/dist/model/fonts/Mapper.mjs +481 -0
- package/dist/model/fonts/PhysicalFont.d.mts +34 -0
- package/dist/model/fonts/PhysicalFont.mjs +62 -0
- package/dist/model/fonts/RunFontSelector.d.mts +194 -0
- package/dist/model/fonts/RunFontSelector.mjs +441 -0
- package/dist/model/fonts/ThemeFonts.d.mts +17 -0
- package/dist/model/fonts/ThemeFonts.mjs +76 -0
- package/dist/model/fonts/defaultTheme.d.mts +37 -0
- package/dist/model/fonts/defaultTheme.mjs +57 -0
- package/dist/model/fonts/families.generated.d.mts +11 -0
- package/dist/model/fonts/families.generated.mjs +17 -0
- package/dist/model/fonts/fontsInUse.d.mts +39 -0
- package/dist/model/fonts/fontsInUse.mjs +183 -0
- package/dist/model/fonts/index.d.mts +14 -0
- package/dist/model/fonts/index.mjs +29 -0
- package/dist/model/fonts/lookup.d.mts +5 -0
- package/dist/model/fonts/lookup.mjs +12 -0
- package/dist/model/fonts/registry.d.mts +31 -0
- package/dist/model/fonts/registry.mjs +103 -0
- package/dist/model/fonts/scripts.d.mts +2 -0
- package/dist/model/fonts/scripts.mjs +78 -0
- package/dist/model/fonts/substitutions.generated.d.mts +30 -0
- package/dist/model/fonts/substitutions.generated.mjs +12 -0
- package/dist/model/fonts/themes.generated.d.mts +6 -0
- package/dist/model/fonts/themes.generated.mjs +11 -0
- package/dist/model/index.d.mts +5 -0
- package/dist/model/index.mjs +13 -1
- package/dist/model/listnumbering/Emulator.d.mts +187 -0
- package/dist/model/listnumbering/Emulator.mjs +332 -0
- package/dist/model/listnumbering/definitions.d.mts +251 -0
- package/dist/model/listnumbering/definitions.mjs +571 -0
- package/dist/model/listnumbering/formats.d.mts +25 -0
- package/dist/model/listnumbering/formats.mjs +320 -0
- package/dist/model/listnumbering/index.d.mts +4 -0
- package/dist/model/listnumbering/index.mjs +15 -0
- package/dist/model/listnumbering/state.d.mts +97 -0
- package/dist/model/listnumbering/state.mjs +179 -0
- package/dist/model/properties/PropertyResolver.d.mts +216 -0
- package/dist/model/properties/PropertyResolver.mjs +524 -0
- package/dist/model/properties/catalogue.d.mts +179 -0
- package/dist/model/properties/catalogue.mjs +860 -0
- package/dist/model/properties/index.d.mts +4 -0
- package/dist/model/properties/index.mjs +9 -0
- package/dist/model/properties/log.d.mts +7 -0
- package/dist/model/properties/log.mjs +25 -0
- package/dist/model/properties/styleUtil.d.mts +112 -0
- package/dist/model/properties/styleUtil.mjs +359 -0
- package/dist/node/index.d.mts +1 -0
- package/dist/node/index.mjs +12 -0
- package/dist/office-js/document.d.mts +111 -0
- package/dist/office-js/document.mjs +267 -0
- package/dist/office-js/enums.d.mts +187 -0
- package/dist/office-js/enums.mjs +176 -0
- package/dist/office-js/errors.d.mts +29 -0
- package/dist/office-js/errors.mjs +39 -0
- package/dist/office-js/extras.d.mts +5 -0
- package/dist/office-js/extras.mjs +29 -0
- package/dist/office-js/fragment.d.mts +10 -0
- package/dist/office-js/fragment.mjs +23 -0
- package/dist/office-js/index.d.mts +183 -0
- package/dist/office-js/index.mjs +54 -0
- package/dist/office-js/proxy.d.mts +72 -0
- package/dist/office-js/proxy.mjs +279 -0
- package/dist/office-js/run.d.mts +32 -0
- package/dist/office-js/run.mjs +66 -0
- package/dist/office-js/supported.d.mts +7 -0
- package/dist/office-js/supported.generated.d.mts +1 -0
- package/dist/office-js/supported.generated.mjs +235 -0
- package/dist/office-js/supported.mjs +53 -0
- package/dist/office-js/toApiScript.d.mts +25 -0
- package/dist/office-js/toApiScript.mjs +394 -0
- package/dist/opc/ContentTypes.d.mts +11 -0
- package/dist/opc/ContentTypes.mjs +14 -0
- package/dist/opc/DirectoryPartStore.d.mts +47 -0
- package/dist/opc/DirectoryPartStore.mjs +123 -0
- package/dist/opc/exceptions.d.mts +30 -0
- package/dist/opc/exceptions.mjs +38 -0
- package/dist/opc/index.d.mts +1 -1
- package/dist/opc/index.mjs +1 -1
- package/dist/packages/OpcPackage.d.mts +19 -1
- package/dist/packages/OpcPackage.mjs +29 -0
- package/dist/packages/PresentationMLPackage.d.mts +71 -1
- package/dist/packages/PresentationMLPackage.mjs +179 -0
- package/dist/packages/SpreadsheetMLPackage.d.mts +30 -1
- package/dist/packages/SpreadsheetMLPackage.mjs +78 -0
- package/dist/packages/WordprocessingMLPackage.d.mts +124 -2
- package/dist/packages/WordprocessingMLPackage.mjs +309 -2
- package/dist/packages/index.d.mts +1 -1
- package/dist/packages/index.mjs +1 -1
- package/dist/parts/DefaultXmlPart.d.mts +18 -0
- package/dist/parts/DefaultXmlPart.mjs +34 -5
- package/dist/parts/Namespaces.d.mts +18 -0
- package/dist/parts/Namespaces.mjs +20 -0
- package/dist/parts/Part.d.mts +6 -0
- package/dist/parts/Part.mjs +13 -0
- package/dist/parts/PartRegistry.mjs +13 -1
- package/dist/parts/XmlPart.d.mts +33 -0
- package/dist/parts/XmlPart.mjs +105 -2
- package/dist/parts/pml/defaults.d.mts +6 -0
- package/dist/parts/pml/defaults.mjs +53 -0
- package/dist/parts/pml/index.d.mts +66 -3
- package/dist/parts/pml/index.mjs +206 -7
- package/dist/parts/pml/placeholders.d.mts +71 -0
- package/dist/parts/pml/placeholders.mjs +141 -0
- package/dist/parts/sml/index.d.mts +80 -1
- package/dist/parts/sml/index.mjs +154 -1
- package/dist/parts/wml/comments.d.mts +1 -0
- package/dist/parts/wml/comments.mjs +179 -0
- package/dist/parts/wml/defaultNumbering.d.mts +1 -0
- package/dist/parts/wml/defaultNumbering.mjs +216 -0
- package/dist/parts/wml/index.d.mts +121 -0
- package/dist/parts/wml/index.mjs +291 -0
- package/dist/xml/dom.mjs +1 -2
- package/package.json +25 -4
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { log } from '../properties/log.mjs';
|
|
2
|
+
// ---------------------------------------------------------------- the formatters
|
|
3
|
+
/** docx4j `NumberFormatRomanAbstract`: 1 to 3999, nothing outside. */
|
|
4
|
+
const ROMAN = [
|
|
5
|
+
[1000, 'm'], [900, 'cm'], [500, 'd'], [400, 'cd'], [100, 'c'], [90, 'xc'],
|
|
6
|
+
[50, 'l'], [40, 'xl'], [10, 'x'], [9, 'ix'], [5, 'v'], [4, 'iv'], [1, 'i'],
|
|
7
|
+
];
|
|
8
|
+
function romanLower(value) {
|
|
9
|
+
if (value >= 4000 || value < 1)
|
|
10
|
+
throw new RangeError('Numbers must be in range 1-3999');
|
|
11
|
+
let n = value;
|
|
12
|
+
let out = '';
|
|
13
|
+
for (const [number, letters] of ROMAN) {
|
|
14
|
+
while (n >= number) {
|
|
15
|
+
n -= number;
|
|
16
|
+
out += letters;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return out;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* docx4j `NumberFormatAlphabet`: the n-th letter up to the alphabet's length, then that letter
|
|
23
|
+
* repeated - after z comes aa, bb, cc, not ab (ECMA-376 17.18.59, and Word). The Cyrillic,
|
|
24
|
+
* Arabic and Thai sets are the ones Word's labels use, which leave out some letters of each
|
|
25
|
+
* script (Russian has no ё, й, ъ, ы, ь; Thai omits ฃ and ฅ).
|
|
26
|
+
*/
|
|
27
|
+
function alphabet(letters) {
|
|
28
|
+
const glyphs = Array.from(letters);
|
|
29
|
+
return (value) => {
|
|
30
|
+
if (value < 1)
|
|
31
|
+
throw new RangeError(`No letter for ${value}`);
|
|
32
|
+
const size = glyphs.length;
|
|
33
|
+
return glyphs[(value - 1) % size].repeat(Math.floor((value - 1) / size) + 1);
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** docx4j `NumberFormatDigits`: a decimal label in another script's digits. */
|
|
37
|
+
function digits(ten) {
|
|
38
|
+
const glyphs = Array.from(ten);
|
|
39
|
+
if (glyphs.length !== 10)
|
|
40
|
+
throw new Error('ten digits expected');
|
|
41
|
+
return (value) => String(value).replace(/[0-9]/g, (c) => glyphs[c.charCodeAt(0) - 48]);
|
|
42
|
+
}
|
|
43
|
+
/** docx4j `NumberFormatDecimalZero`: 01, 02 ... 09, 10. */
|
|
44
|
+
function decimalZero(value) {
|
|
45
|
+
return value < 10 ? `0${value}` : String(value);
|
|
46
|
+
}
|
|
47
|
+
/** docx4j `NumberFormatOrdinal`: 1st, 2nd, 3rd, 4th, 11th, 21st, 101st, 111th. */
|
|
48
|
+
function ordinal(value) {
|
|
49
|
+
return `${value}${ordinalSuffix(value)}`;
|
|
50
|
+
}
|
|
51
|
+
function ordinalSuffix(n) {
|
|
52
|
+
const abs = Math.abs(n);
|
|
53
|
+
const lastTwo = abs % 100;
|
|
54
|
+
if (lastTwo >= 11 && lastTwo <= 13)
|
|
55
|
+
return 'th';
|
|
56
|
+
switch (abs % 10) {
|
|
57
|
+
case 1: return 'st';
|
|
58
|
+
case 2: return 'nd';
|
|
59
|
+
case 3: return 'rd';
|
|
60
|
+
default: return 'th';
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const ONES = ['Zero', 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine',
|
|
64
|
+
'Ten', 'Eleven', 'Twelve', 'Thirteen', 'Fourteen', 'Fifteen', 'Sixteen', 'Seventeen',
|
|
65
|
+
'Eighteen', 'Nineteen'];
|
|
66
|
+
const TENS = ['', '', 'Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy', 'Eighty', 'Ninety'];
|
|
67
|
+
const SCALES = ['', 'Thousand', 'Million', 'Billion'];
|
|
68
|
+
const ORDINAL_ONES = ['Zeroth', 'First', 'Second', 'Third', 'Fourth', 'Fifth', 'Sixth', 'Seventh',
|
|
69
|
+
'Eighth', 'Ninth', 'Tenth', 'Eleventh', 'Twelfth', 'Thirteenth', 'Fourteenth', 'Fifteenth',
|
|
70
|
+
'Sixteenth', 'Seventeenth', 'Eighteenth', 'Nineteenth'];
|
|
71
|
+
/** docx4j `NumberFormatCardinalText.words`: the cardinal words, every word capitalised. */
|
|
72
|
+
function cardinalWords(value) {
|
|
73
|
+
if (value < 20)
|
|
74
|
+
return ONES[value];
|
|
75
|
+
let n = value;
|
|
76
|
+
const groups = [];
|
|
77
|
+
while (n > 0) {
|
|
78
|
+
groups.push(n % 1000);
|
|
79
|
+
n = Math.floor(n / 1000);
|
|
80
|
+
}
|
|
81
|
+
let out = '';
|
|
82
|
+
for (let i = groups.length - 1; i >= 0; i--) {
|
|
83
|
+
if (groups[i] === 0)
|
|
84
|
+
continue;
|
|
85
|
+
if (out.length > 0)
|
|
86
|
+
out += ' ';
|
|
87
|
+
out += belowThousand(groups[i]);
|
|
88
|
+
if (i > 0)
|
|
89
|
+
out += ` ${SCALES[i]}`;
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
function belowThousand(n) {
|
|
94
|
+
let out = '';
|
|
95
|
+
let rest = n;
|
|
96
|
+
if (rest >= 100) {
|
|
97
|
+
out += `${ONES[Math.floor(rest / 100)]} Hundred`;
|
|
98
|
+
rest %= 100;
|
|
99
|
+
if (rest > 0)
|
|
100
|
+
out += ' ';
|
|
101
|
+
}
|
|
102
|
+
if (rest >= 20) {
|
|
103
|
+
out += TENS[Math.floor(rest / 10)];
|
|
104
|
+
if (rest % 10 > 0)
|
|
105
|
+
out += `-${ONES[rest % 10]}`;
|
|
106
|
+
}
|
|
107
|
+
else if (rest > 0) {
|
|
108
|
+
out += ONES[rest];
|
|
109
|
+
}
|
|
110
|
+
return out;
|
|
111
|
+
}
|
|
112
|
+
/** docx4j `NumberFormatCardinalText`: One, Twenty-One, One Hundred One, One Thousand. */
|
|
113
|
+
function cardinalText(value) {
|
|
114
|
+
if (value < 0)
|
|
115
|
+
throw new RangeError(`No words for ${value}`);
|
|
116
|
+
return cardinalWords(value);
|
|
117
|
+
}
|
|
118
|
+
/** docx4j `NumberFormatOrdinalText`: the cardinal words with the last word made ordinal. */
|
|
119
|
+
function ordinalText(value) {
|
|
120
|
+
if (value < 0)
|
|
121
|
+
throw new RangeError(`No words for ${value}`);
|
|
122
|
+
const cardinal = cardinalWords(value);
|
|
123
|
+
const cut = Math.max(cardinal.lastIndexOf(' '), cardinal.lastIndexOf('-'));
|
|
124
|
+
const head = cut < 0 ? '' : cardinal.slice(0, cut + 1);
|
|
125
|
+
return head + ordinalWord(cardinal.slice(cut + 1));
|
|
126
|
+
}
|
|
127
|
+
function ordinalWord(word) {
|
|
128
|
+
const index = ONES.indexOf(word);
|
|
129
|
+
if (index >= 0)
|
|
130
|
+
return ORDINAL_ONES[index];
|
|
131
|
+
if (word.endsWith('y'))
|
|
132
|
+
return `${word.slice(0, -1)}ieth`; // Twenty -> Twentieth
|
|
133
|
+
return `${word}th`; // Hundred, Thousand, Million
|
|
134
|
+
}
|
|
135
|
+
/** docx4j `NumberFormatChicago`: * † ‡ §, then doubled, then tripled. */
|
|
136
|
+
const CHICAGO_SYMBOLS = ['*', '†', '‡', '§'];
|
|
137
|
+
function chicago(value) {
|
|
138
|
+
if (value < 1)
|
|
139
|
+
throw new RangeError(`No symbol for ${value}`);
|
|
140
|
+
const symbol = CHICAGO_SYMBOLS[(value - 1) % CHICAGO_SYMBOLS.length];
|
|
141
|
+
return symbol.repeat(Math.floor((value - 1) / CHICAGO_SYMBOLS.length) + 1);
|
|
142
|
+
}
|
|
143
|
+
const CIRCLED = ['①', '②', '③', '④', '⑤', '⑥', '⑦', '⑧',
|
|
144
|
+
'⑨', '⑩', '⑪', '⑫', '⑬', '⑭', '⑮', '⑯', '⑰',
|
|
145
|
+
'⑱', '⑲', '⑳'];
|
|
146
|
+
/** docx4j `NumberFormatDecimalEnclosedCircle`: ① to ⑳, and nothing above. */
|
|
147
|
+
function decimalEnclosedCircle(value) {
|
|
148
|
+
if (value <= 0 || value > 20)
|
|
149
|
+
throw new RangeError('Numbers must be in range 1-20');
|
|
150
|
+
return CIRCLED[value - 1];
|
|
151
|
+
}
|
|
152
|
+
const HEBREW_UNITS = ['א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ז', 'ח', 'ט'];
|
|
153
|
+
const HEBREW_TENS = ['י', 'כ', 'ל', 'מ', 'נ', 'ס', 'ע', 'פ', 'צ'];
|
|
154
|
+
const HEBREW_HUNDREDS = ['ק', 'ר', 'ש', 'ת'];
|
|
155
|
+
/** docx4j `NumberFormatHebrew1`: טו and טז for 15 and 16, ת repeated above 400, no gershayim. */
|
|
156
|
+
function hebrew1(value) {
|
|
157
|
+
if (value < 1)
|
|
158
|
+
throw new RangeError(`No Hebrew numeral for ${value}`);
|
|
159
|
+
let out = '';
|
|
160
|
+
let n = value;
|
|
161
|
+
while (n >= 400) {
|
|
162
|
+
out += 'ת';
|
|
163
|
+
n -= 400;
|
|
164
|
+
}
|
|
165
|
+
if (n >= 100) {
|
|
166
|
+
out += HEBREW_HUNDREDS[Math.floor(n / 100) - 1];
|
|
167
|
+
n %= 100;
|
|
168
|
+
}
|
|
169
|
+
if (n === 15)
|
|
170
|
+
return `${out}טו`;
|
|
171
|
+
if (n === 16)
|
|
172
|
+
return `${out}טז`;
|
|
173
|
+
if (n >= 10) {
|
|
174
|
+
out += HEBREW_TENS[Math.floor(n / 10) - 1];
|
|
175
|
+
n %= 10;
|
|
176
|
+
}
|
|
177
|
+
if (n > 0)
|
|
178
|
+
out += HEBREW_UNITS[n - 1];
|
|
179
|
+
return out;
|
|
180
|
+
}
|
|
181
|
+
/** docx4j `NumberFormatChineseAbstract`, with the lower or the legal (upper) characters. */
|
|
182
|
+
function chinese(characters, units, bigUnits) {
|
|
183
|
+
const fourDigit = (num) => {
|
|
184
|
+
let out = '';
|
|
185
|
+
let n = num;
|
|
186
|
+
let unitPosition = 0;
|
|
187
|
+
let lastIsZero = false;
|
|
188
|
+
while (n > 0) {
|
|
189
|
+
const digit = n % 10;
|
|
190
|
+
if (digit !== 0) {
|
|
191
|
+
out = `${characters[digit]}${units[unitPosition]}${out}`;
|
|
192
|
+
lastIsZero = false;
|
|
193
|
+
}
|
|
194
|
+
else if (!lastIsZero) {
|
|
195
|
+
out = `${characters[0]}${out}`;
|
|
196
|
+
lastIsZero = true;
|
|
197
|
+
}
|
|
198
|
+
n = Math.floor(n / 10);
|
|
199
|
+
unitPosition++;
|
|
200
|
+
}
|
|
201
|
+
// remove the trailing 零
|
|
202
|
+
if (out.endsWith(characters[0]))
|
|
203
|
+
out = out.slice(0, -characters[0].length);
|
|
204
|
+
return out;
|
|
205
|
+
};
|
|
206
|
+
return (value) => {
|
|
207
|
+
if (value === 0)
|
|
208
|
+
return characters[0];
|
|
209
|
+
let out = '';
|
|
210
|
+
let n = value;
|
|
211
|
+
let bigUnitPosition = 0;
|
|
212
|
+
let lastIsZero = false;
|
|
213
|
+
while (n > 0) {
|
|
214
|
+
const part = n % 10000;
|
|
215
|
+
if (part !== 0) {
|
|
216
|
+
out = `${fourDigit(part)}${bigUnitPosition > 0 ? bigUnits[bigUnitPosition] : ''}${out}`;
|
|
217
|
+
lastIsZero = false;
|
|
218
|
+
}
|
|
219
|
+
else if (!lastIsZero && out.length > 0) {
|
|
220
|
+
out = `${characters[0]}${out}`;
|
|
221
|
+
lastIsZero = true;
|
|
222
|
+
}
|
|
223
|
+
n = Math.floor(n / 10000);
|
|
224
|
+
bigUnitPosition++;
|
|
225
|
+
}
|
|
226
|
+
return out;
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
const chineseLower = chinese(['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'], ['', '十', '百', '千'], ['', '万', '亿']);
|
|
230
|
+
const chineseUpper = chinese(['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'], ['', '拾', '佰', '仟'], ['', '万', '亿']);
|
|
231
|
+
const decimal = (value) => String(value);
|
|
232
|
+
// ---------------------------------------------------------------- the registry
|
|
233
|
+
/** `w:numFmt` -> its formatter. docx4j `NumberFormatter.REGISTRY`. */
|
|
234
|
+
const REGISTRY = new Map([
|
|
235
|
+
['decimal', decimal],
|
|
236
|
+
['decimalHalfWidth', decimal],
|
|
237
|
+
['none', () => ''],
|
|
238
|
+
// TODO (docx4j's own): revisit; the code elsewhere for bullets overlaps with this numFmt stuff
|
|
239
|
+
['bullet', () => '*'],
|
|
240
|
+
['upperRoman', (v) => romanLower(v).toUpperCase()],
|
|
241
|
+
['lowerRoman', romanLower],
|
|
242
|
+
['lowerLetter', alphabet('abcdefghijklmnopqrstuvwxyz')],
|
|
243
|
+
['upperLetter', alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ')],
|
|
244
|
+
['decimalZero', decimalZero],
|
|
245
|
+
['ordinal', ordinal],
|
|
246
|
+
['cardinalText', cardinalText],
|
|
247
|
+
['ordinalText', ordinalText],
|
|
248
|
+
['hex', (v) => (v >>> 0).toString(16).toUpperCase()],
|
|
249
|
+
['chicago', chicago],
|
|
250
|
+
['numberInDash', (v) => `- ${v} -`],
|
|
251
|
+
['decimalFullWidth', digits('0123456789')],
|
|
252
|
+
['decimalFullWidth2', digits('0123456789')],
|
|
253
|
+
['thaiNumbers', digits('๐๑๒๓๔๕๖๗๘๙')],
|
|
254
|
+
['hindiNumbers', digits('०१२३४५६७८९')],
|
|
255
|
+
['russianLower', alphabet('абвгдежзиклмнопрстуфхцчшщэюя')],
|
|
256
|
+
['russianUpper', alphabet('АБВГДЕЖЗИКЛМНОПРСТУФХЦЧШЩЭЮЯ')],
|
|
257
|
+
['arabicAlpha', alphabet('أبتثجحخدذرزسشصضطظعغفقكلمنهوي')],
|
|
258
|
+
['thaiLetters', alphabet('กขคฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ')],
|
|
259
|
+
['hebrew1', hebrew1],
|
|
260
|
+
// these two are the same in Chinese, no need to be processed separately
|
|
261
|
+
['chineseCounting', chineseLower],
|
|
262
|
+
['chineseCountingThousand', chineseLower],
|
|
263
|
+
// this one means use upper Chinese number characters
|
|
264
|
+
['chineseLegalSimplified', chineseUpper],
|
|
265
|
+
// these two are the same, just to adapt to documents in Chinese
|
|
266
|
+
['decimalEnclosedCircle', decimalEnclosedCircle],
|
|
267
|
+
['decimalEnclosedCircleChinese', decimalEnclosedCircle],
|
|
268
|
+
]);
|
|
269
|
+
/** The formats warned about already: one warning per format, whatever the value or document. */
|
|
270
|
+
const WARNED = new Set();
|
|
271
|
+
/** Adds or replaces the formatter for a `w:numFmt`; `undefined` removes it. docx4j `register`. */
|
|
272
|
+
export function register(numFmt, formatter) {
|
|
273
|
+
if (formatter === undefined)
|
|
274
|
+
REGISTRY.delete(numFmt);
|
|
275
|
+
else
|
|
276
|
+
REGISTRY.set(numFmt, formatter);
|
|
277
|
+
}
|
|
278
|
+
/** The formatter registered for a `w:numFmt`, or undefined. docx4j `NumberFormatter.get`. */
|
|
279
|
+
export function formatterFor(numFmt) {
|
|
280
|
+
return numFmt === undefined ? undefined : REGISTRY.get(numFmt);
|
|
281
|
+
}
|
|
282
|
+
/** Every `w:numFmt` this package can format (a test's, and a caller's, inventory). */
|
|
283
|
+
export function registeredFormats() {
|
|
284
|
+
return [...REGISTRY.keys()];
|
|
285
|
+
}
|
|
286
|
+
/** Forgets which formats have been warned about; a test that asserts on the warning needs it. */
|
|
287
|
+
export function resetWarnings() {
|
|
288
|
+
WARNED.clear();
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* A counter as its label. docx4j `NumberFormatter.getCurrentValueFormatted(numFmt, current, where)`.
|
|
292
|
+
*
|
|
293
|
+
* A `w:numFmt` of undefined is decimal; so is a format with no formatter, and a value the
|
|
294
|
+
* formatter cannot express - with one warning per format naming `where` ("numId 3 ilvl 0") it
|
|
295
|
+
* first happened.
|
|
296
|
+
*/
|
|
297
|
+
export function formatValue(numFmt, value, where) {
|
|
298
|
+
if (numFmt === undefined)
|
|
299
|
+
return String(value);
|
|
300
|
+
const formatter = REGISTRY.get(numFmt);
|
|
301
|
+
if (formatter === undefined) {
|
|
302
|
+
warnOnce(numFmt, `no formatter for numFmt ${numFmt}; decimal labels used`, where);
|
|
303
|
+
return String(value);
|
|
304
|
+
}
|
|
305
|
+
try {
|
|
306
|
+
return formatter(value);
|
|
307
|
+
}
|
|
308
|
+
catch (e) {
|
|
309
|
+
if (!(e instanceof RangeError))
|
|
310
|
+
throw e;
|
|
311
|
+
warnOnce(numFmt, `numFmt ${numFmt} cannot express ${value} (${e.message}); decimal label used`, where);
|
|
312
|
+
return String(value);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function warnOnce(numFmt, message, where) {
|
|
316
|
+
if (WARNED.has(numFmt))
|
|
317
|
+
return;
|
|
318
|
+
WARNED.add(numFmt);
|
|
319
|
+
log.warn(`${message}${where === undefined ? '' : ` (first at ${where})`}; not reported again for this format`);
|
|
320
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { LEVELS, LevelDefinition, AbstractListDefinition, ListDefinition, NumberingDefinitions, type StyleLookup, } from './definitions.mjs';
|
|
2
|
+
export { Counter, NumberingState, NumberingStates, storyKindOf, type PartLike, type StoryKind, } from './state.mjs';
|
|
3
|
+
export { formatValue, formatterFor, register, registeredFormats, resetWarnings, type LabelFormatter, } from './formats.mjs';
|
|
4
|
+
export { Emulator, NumRef, type NumberingResult, type NumberedPackageLike, type NumberingPartLike, } from './Emulator.mjs';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// CR-001 Phase B step 3: list numbering (docx4j `org.docx4j.model.listnumbering`, as CR-014
|
|
2
|
+
// settled it against Word).
|
|
3
|
+
//
|
|
4
|
+
// The split is the one docx4j-python's port uses, so that the two read alike:
|
|
5
|
+
//
|
|
6
|
+
// definitions.mts what a list *is*: `LevelDefinition`, `AbstractListDefinition`,
|
|
7
|
+
// `ListDefinition`, and `NumberingDefinitions` over one `w:numbering`
|
|
8
|
+
// state.mts what it is *up to*: `Counter`, `NumberingState` (one per story of one
|
|
9
|
+
// traversal), `NumberingStates`
|
|
10
|
+
// formats.mts the `w:numFmt` registry, fail-soft to decimal as Word is
|
|
11
|
+
// Emulator.mts the resolution (through `PropertyResolver`) and the counting
|
|
12
|
+
export { LEVELS, LevelDefinition, AbstractListDefinition, ListDefinition, NumberingDefinitions, } from './definitions.mjs';
|
|
13
|
+
export { Counter, NumberingState, NumberingStates, storyKindOf, } from './state.mjs';
|
|
14
|
+
export { formatValue, formatterFor, register, registeredFormats, resetWarnings, } from './formats.mjs';
|
|
15
|
+
export { Emulator, NumRef, } from './Emulator.mjs';
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/** One level's count in one {@link NumberingState}. docx4j `ListLevel.Counter`. */
|
|
2
|
+
export declare class Counter {
|
|
3
|
+
/** The current count. */
|
|
4
|
+
value: number;
|
|
5
|
+
/** The level has been counted in this state; its start value is spent. */
|
|
6
|
+
encounteredAlready: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* A shallower level reset it: it holds its start value, and the next use of the level takes
|
|
9
|
+
* that value rather than incrementing (CR-014 probe P8, measured - a level-2 item straight
|
|
10
|
+
* after a level-0 one reads "2.1.1", where a counter left at start-1 read "2.0.1").
|
|
11
|
+
*/
|
|
12
|
+
resetPending: boolean;
|
|
13
|
+
constructor(value?: number);
|
|
14
|
+
/** One more item at this level. */
|
|
15
|
+
increment(): void;
|
|
16
|
+
/** An independent copy; what {@link NumberingState.copy} is made of. */
|
|
17
|
+
copy(): Counter;
|
|
18
|
+
toString(): string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The counters of one story of one traversal. docx4j `NumberingState`.
|
|
22
|
+
*
|
|
23
|
+
* Not shared: one state belongs to one walk of one story.
|
|
24
|
+
*/
|
|
25
|
+
export declare class NumberingState {
|
|
26
|
+
private readonly byLevel;
|
|
27
|
+
private readonly overridesApplied;
|
|
28
|
+
/**
|
|
29
|
+
* The counter of a level of an abstract list, created at `initial` (the level's start value
|
|
30
|
+
* less one) on first use.
|
|
31
|
+
*/
|
|
32
|
+
counter(abstractNumId: string, ilvl: string, initial: number | undefined): Counter;
|
|
33
|
+
/**
|
|
34
|
+
* Every counter this story stands at, keyed `"<abstractNumId>/<ilvl>"`. docx4j
|
|
35
|
+
* `NumberingState.counters()`, one of the parity accessors it made public in 17.1.1 so that a
|
|
36
|
+
* port can be held to the *counters* and not only to the labels. The live map, as docx4j's
|
|
37
|
+
* unmodifiable view is of the live one: do not hold it across a later `getNumber`.
|
|
38
|
+
*/
|
|
39
|
+
get counters(): ReadonlyMap<string, Counter>;
|
|
40
|
+
/**
|
|
41
|
+
* The `w:num` start overrides spent, keyed `"<numId>/<ilvl>"`. docx4j
|
|
42
|
+
* `NumberingState.startOverridesApplied()`. A `w:num`'s first use at a level is recorded here
|
|
43
|
+
* whether or not it carries a `w:startOverride`, which is docx4j's own behaviour (the flag is
|
|
44
|
+
* set wherever the counter takes a start value), and what its goldens show.
|
|
45
|
+
*/
|
|
46
|
+
get startOverridesApplied(): ReadonlySet<string>;
|
|
47
|
+
/** Whether this `w:num`'s `w:startOverride` has been spent at a level. */
|
|
48
|
+
startOverrideApplied(numId: string, ilvl: string): boolean;
|
|
49
|
+
/** Remember that it has. */
|
|
50
|
+
markStartOverrideApplied(numId: string, ilvl: string): void;
|
|
51
|
+
/** Every list starts again, as at the head of a story. */
|
|
52
|
+
reset(): void;
|
|
53
|
+
/** Nothing has been numbered in this state yet. */
|
|
54
|
+
get isEmpty(): boolean;
|
|
55
|
+
/** An independent copy: what `Emulator.peek` numbers against. */
|
|
56
|
+
copy(): NumberingState;
|
|
57
|
+
toString(): string;
|
|
58
|
+
}
|
|
59
|
+
/** As much of a `Part` as {@link NumberingStates.forPart} reads. */
|
|
60
|
+
export interface PartLike {
|
|
61
|
+
readonly contentType: string;
|
|
62
|
+
}
|
|
63
|
+
/** Which story a part's paragraphs number in. */
|
|
64
|
+
export type StoryKind = 'main' | 'headersFooters' | 'own';
|
|
65
|
+
/**
|
|
66
|
+
* The story a part belongs to, by content type (never by class, so that this module imports no
|
|
67
|
+
* part): every header and footer is one story, the footnotes, endnotes and comments parts each
|
|
68
|
+
* their own, everything else the main story.
|
|
69
|
+
*/
|
|
70
|
+
export declare function storyKindOf(part: PartLike | undefined): StoryKind;
|
|
71
|
+
/**
|
|
72
|
+
* The numbering states of one traversal, one per story. docx4j `NumberingStates`.
|
|
73
|
+
*
|
|
74
|
+
* Word numbers each story from its own counters (CR-014 probe P7, measured 2026-09-12): the body
|
|
75
|
+
* is one story; a section's header and footer share one (header 1 2 3, footer 4 5 6); the
|
|
76
|
+
* footnotes part is one (the second footnote continues the first's count); the endnotes part
|
|
77
|
+
* another; each text box and each comment counts on its own; and the body's count runs past all
|
|
78
|
+
* of them untouched.
|
|
79
|
+
*
|
|
80
|
+
* Only one section was probed, so headers and footers of every section are folded into one story
|
|
81
|
+
* here until a document says otherwise.
|
|
82
|
+
*/
|
|
83
|
+
export declare class NumberingStates {
|
|
84
|
+
private readonly mainState;
|
|
85
|
+
private headersFooters;
|
|
86
|
+
private readonly byPart;
|
|
87
|
+
/** The main document's story. */
|
|
88
|
+
main(): NumberingState;
|
|
89
|
+
/**
|
|
90
|
+
* The story the given part's paragraphs number in: the main document (also for undefined, and
|
|
91
|
+
* for any part not listed in {@link storyKindOf}), the one shared by headers and footers, or
|
|
92
|
+
* the footnotes, endnotes or comments part's own.
|
|
93
|
+
*/
|
|
94
|
+
forPart(part: PartLike | undefined): NumberingState;
|
|
95
|
+
/** A fresh story: a text box's, or a comment's when comments are numbered one by one. */
|
|
96
|
+
newStory(): NumberingState;
|
|
97
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// The counters (docx4j `NumberingState` and `NumberingStates`, CR-014 phase 4).
|
|
2
|
+
//
|
|
3
|
+
// Definitions hold no counters: a traversal owns its states, one per **story**, and passes the
|
|
4
|
+
// right one to the `Emulator`. So two walks of one package do not interleave, a footer's list
|
|
5
|
+
// starts at its own start whenever the footer is read, and `Emulator.peek` can ask what a
|
|
6
|
+
// paragraph's number would be without taking it.
|
|
7
|
+
//
|
|
8
|
+
// Counters are keyed by the **referencing** `w:abstractNum` and the level, which is the sharing
|
|
9
|
+
// rule Word applies: every `w:num` over one abstract definition continues a single sequence
|
|
10
|
+
// (CR-014 probe P1, measured), and a `w:numStyleLink` abstract definition is a list of its own
|
|
11
|
+
// (P2). A `w:num` with a `w:startOverride` for a level resets that shared counter the first
|
|
12
|
+
// time that `w:num` is met at that level, in this story.
|
|
13
|
+
import { ContentTypes } from '../../opc/ContentTypes.mjs';
|
|
14
|
+
/** One level's count in one {@link NumberingState}. docx4j `ListLevel.Counter`. */
|
|
15
|
+
export class Counter {
|
|
16
|
+
constructor(value = 0) {
|
|
17
|
+
/** The level has been counted in this state; its start value is spent. */
|
|
18
|
+
this.encounteredAlready = false;
|
|
19
|
+
/**
|
|
20
|
+
* A shallower level reset it: it holds its start value, and the next use of the level takes
|
|
21
|
+
* that value rather than incrementing (CR-014 probe P8, measured - a level-2 item straight
|
|
22
|
+
* after a level-0 one reads "2.1.1", where a counter left at start-1 read "2.0.1").
|
|
23
|
+
*/
|
|
24
|
+
this.resetPending = false;
|
|
25
|
+
this.value = value;
|
|
26
|
+
}
|
|
27
|
+
/** One more item at this level. */
|
|
28
|
+
increment() {
|
|
29
|
+
this.value += 1;
|
|
30
|
+
}
|
|
31
|
+
/** An independent copy; what {@link NumberingState.copy} is made of. */
|
|
32
|
+
copy() {
|
|
33
|
+
const other = new Counter(this.value);
|
|
34
|
+
other.encounteredAlready = this.encounteredAlready;
|
|
35
|
+
other.resetPending = this.resetPending;
|
|
36
|
+
return other;
|
|
37
|
+
}
|
|
38
|
+
toString() {
|
|
39
|
+
return `${this.value}${this.encounteredAlready ? '' : ' (unused)'}${this.resetPending ? ' (reset)' : ''}`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The counters of one story of one traversal. docx4j `NumberingState`.
|
|
44
|
+
*
|
|
45
|
+
* Not shared: one state belongs to one walk of one story.
|
|
46
|
+
*/
|
|
47
|
+
export class NumberingState {
|
|
48
|
+
constructor() {
|
|
49
|
+
this.byLevel = new Map();
|
|
50
|
+
this.overridesApplied = new Set();
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The counter of a level of an abstract list, created at `initial` (the level's start value
|
|
54
|
+
* less one) on first use.
|
|
55
|
+
*/
|
|
56
|
+
counter(abstractNumId, ilvl, initial) {
|
|
57
|
+
const key = `${abstractNumId}/${ilvl}`;
|
|
58
|
+
let found = this.byLevel.get(key);
|
|
59
|
+
if (found === undefined) {
|
|
60
|
+
found = new Counter(initial !== null && initial !== void 0 ? initial : 0);
|
|
61
|
+
this.byLevel.set(key, found);
|
|
62
|
+
}
|
|
63
|
+
return found;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Every counter this story stands at, keyed `"<abstractNumId>/<ilvl>"`. docx4j
|
|
67
|
+
* `NumberingState.counters()`, one of the parity accessors it made public in 17.1.1 so that a
|
|
68
|
+
* port can be held to the *counters* and not only to the labels. The live map, as docx4j's
|
|
69
|
+
* unmodifiable view is of the live one: do not hold it across a later `getNumber`.
|
|
70
|
+
*/
|
|
71
|
+
get counters() {
|
|
72
|
+
return this.byLevel;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The `w:num` start overrides spent, keyed `"<numId>/<ilvl>"`. docx4j
|
|
76
|
+
* `NumberingState.startOverridesApplied()`. A `w:num`'s first use at a level is recorded here
|
|
77
|
+
* whether or not it carries a `w:startOverride`, which is docx4j's own behaviour (the flag is
|
|
78
|
+
* set wherever the counter takes a start value), and what its goldens show.
|
|
79
|
+
*/
|
|
80
|
+
get startOverridesApplied() {
|
|
81
|
+
return this.overridesApplied;
|
|
82
|
+
}
|
|
83
|
+
/** Whether this `w:num`'s `w:startOverride` has been spent at a level. */
|
|
84
|
+
startOverrideApplied(numId, ilvl) {
|
|
85
|
+
return this.overridesApplied.has(`${numId}/${ilvl}`);
|
|
86
|
+
}
|
|
87
|
+
/** Remember that it has. */
|
|
88
|
+
markStartOverrideApplied(numId, ilvl) {
|
|
89
|
+
this.overridesApplied.add(`${numId}/${ilvl}`);
|
|
90
|
+
}
|
|
91
|
+
/** Every list starts again, as at the head of a story. */
|
|
92
|
+
reset() {
|
|
93
|
+
this.byLevel.clear();
|
|
94
|
+
this.overridesApplied.clear();
|
|
95
|
+
}
|
|
96
|
+
/** Nothing has been numbered in this state yet. */
|
|
97
|
+
get isEmpty() {
|
|
98
|
+
return this.byLevel.size === 0 && this.overridesApplied.size === 0;
|
|
99
|
+
}
|
|
100
|
+
/** An independent copy: what `Emulator.peek` numbers against. */
|
|
101
|
+
copy() {
|
|
102
|
+
const other = new NumberingState();
|
|
103
|
+
for (const [key, counter] of this.byLevel)
|
|
104
|
+
other.byLevel.set(key, counter.copy());
|
|
105
|
+
for (const key of this.overridesApplied)
|
|
106
|
+
other.overridesApplied.add(key);
|
|
107
|
+
return other;
|
|
108
|
+
}
|
|
109
|
+
toString() {
|
|
110
|
+
return `NumberingState(${[...this.byLevel].map(([k, c]) => `${k}=${c}`).join(', ')})`;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The story a part belongs to, by content type (never by class, so that this module imports no
|
|
115
|
+
* part): every header and footer is one story, the footnotes, endnotes and comments parts each
|
|
116
|
+
* their own, everything else the main story.
|
|
117
|
+
*/
|
|
118
|
+
export function storyKindOf(part) {
|
|
119
|
+
switch (part === null || part === void 0 ? void 0 : part.contentType) {
|
|
120
|
+
case ContentTypes.WORDPROCESSINGML_HEADER:
|
|
121
|
+
case ContentTypes.WORDPROCESSINGML_FOOTER:
|
|
122
|
+
return 'headersFooters';
|
|
123
|
+
case ContentTypes.WORDPROCESSINGML_FOOTNOTES:
|
|
124
|
+
case ContentTypes.WORDPROCESSINGML_ENDNOTES:
|
|
125
|
+
case ContentTypes.WORDPROCESSINGML_COMMENTS:
|
|
126
|
+
return 'own';
|
|
127
|
+
default:
|
|
128
|
+
return 'main';
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* The numbering states of one traversal, one per story. docx4j `NumberingStates`.
|
|
133
|
+
*
|
|
134
|
+
* Word numbers each story from its own counters (CR-014 probe P7, measured 2026-09-12): the body
|
|
135
|
+
* is one story; a section's header and footer share one (header 1 2 3, footer 4 5 6); the
|
|
136
|
+
* footnotes part is one (the second footnote continues the first's count); the endnotes part
|
|
137
|
+
* another; each text box and each comment counts on its own; and the body's count runs past all
|
|
138
|
+
* of them untouched.
|
|
139
|
+
*
|
|
140
|
+
* Only one section was probed, so headers and footers of every section are folded into one story
|
|
141
|
+
* here until a document says otherwise.
|
|
142
|
+
*/
|
|
143
|
+
export class NumberingStates {
|
|
144
|
+
constructor() {
|
|
145
|
+
this.mainState = new NumberingState();
|
|
146
|
+
this.byPart = new Map();
|
|
147
|
+
}
|
|
148
|
+
/** The main document's story. */
|
|
149
|
+
main() {
|
|
150
|
+
return this.mainState;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* The story the given part's paragraphs number in: the main document (also for undefined, and
|
|
154
|
+
* for any part not listed in {@link storyKindOf}), the one shared by headers and footers, or
|
|
155
|
+
* the footnotes, endnotes or comments part's own.
|
|
156
|
+
*/
|
|
157
|
+
forPart(part) {
|
|
158
|
+
var _a;
|
|
159
|
+
switch (storyKindOf(part)) {
|
|
160
|
+
case 'headersFooters':
|
|
161
|
+
(_a = this.headersFooters) !== null && _a !== void 0 ? _a : (this.headersFooters = new NumberingState());
|
|
162
|
+
return this.headersFooters;
|
|
163
|
+
case 'own': {
|
|
164
|
+
let found = this.byPart.get(part);
|
|
165
|
+
if (found === undefined) {
|
|
166
|
+
found = new NumberingState();
|
|
167
|
+
this.byPart.set(part, found);
|
|
168
|
+
}
|
|
169
|
+
return found;
|
|
170
|
+
}
|
|
171
|
+
default:
|
|
172
|
+
return this.mainState;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/** A fresh story: a text box's, or a comment's when comments are numbered one by one. */
|
|
176
|
+
newStory() {
|
|
177
|
+
return new NumberingState();
|
|
178
|
+
}
|
|
179
|
+
}
|