reamkit 1.16.0 → 1.17.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/dist/esm/core/bidi/segments.js +1 -2
- package/dist/esm/core/converter/project.js +5 -1
- package/dist/esm/core/document-model/index.d.ts +1 -1
- package/dist/esm/core/document-model/types.d.ts +473 -7
- package/dist/esm/core/drawingml/chart-geometry.d.ts +8 -12
- package/dist/esm/core/drawingml/chart-geometry.js +58 -9
- package/dist/esm/core/drawingml/chart-parser.js +44 -5
- package/dist/esm/core/drawingml/colors.d.ts +1 -1
- package/dist/esm/core/drawingml/colors.js +27 -1
- package/dist/esm/core/drawingml/preset-geometry.js +233 -0
- package/dist/esm/core/drawingml/shape-render.d.ts +12 -0
- package/dist/esm/core/drawingml/shape-render.js +116 -3
- package/dist/esm/core/drawingml/theme-parser.d.ts +10 -0
- package/dist/esm/core/drawingml/theme-parser.js +19 -1
- package/dist/esm/core/font/measure.d.ts +5 -0
- package/dist/esm/core/font/measure.js +21 -1
- package/dist/esm/core/images.d.ts +2 -2
- package/dist/esm/core/images.js +181 -0
- package/dist/esm/core/ir/flow.d.ts +23 -1
- package/dist/esm/core/numbering/apply.d.ts +5 -3
- package/dist/esm/core/numbering/apply.js +42 -11
- package/dist/esm/core/numbering/index.js +2 -0
- package/dist/esm/core/numbering/state.d.ts +13 -1
- package/dist/esm/core/numbering/state.js +256 -15
- package/dist/esm/core/po-helpers.js +16 -1
- package/dist/esm/core/style-cascade/resolver.js +66 -11
- package/dist/esm/core/style-cascade/table.js +35 -11
- package/dist/esm/core/style-cascade/types.d.ts +42 -1
- package/dist/esm/core/style-cascade/types.js +4 -0
- package/dist/esm/core/vector.d.ts +17 -0
- package/dist/esm/excel/print-model.js +1 -1
- package/dist/esm/excel/sheet-to-flow.js +10 -8
- package/dist/esm/excel/worksheet-parser.js +1 -1
- package/dist/esm/html/html-writer.js +18 -4
- package/dist/esm/layout/page-doc.d.ts +62 -2
- package/dist/esm/layout/styled-layout.d.ts +44 -2
- package/dist/esm/layout/styled-layout.js +1870 -228
- package/dist/esm/pdf/shading.js +76 -6
- package/dist/esm/pdf/styled-page-emitter.js +217 -43
- package/dist/esm/pdf/vector-graphics.d.ts +28 -1
- package/dist/esm/pdf/vector-graphics.js +94 -11
- package/dist/esm/pptx/pptx-reader.js +1 -0
- package/dist/esm/pptx/slide-parser.d.ts +21 -4
- package/dist/esm/pptx/slide-parser.js +86 -23
- package/dist/esm/svg/svg-writer.js +1 -1
- package/dist/esm/word/document-parser.d.ts +96 -7
- package/dist/esm/word/document-parser.js +537 -116
- package/dist/esm/word/docx-reader.js +135 -43
- package/dist/esm/word/docx-writer.js +6 -1
- package/dist/esm/word/drawing-parser.d.ts +53 -5
- package/dist/esm/word/drawing-parser.js +1540 -54
- package/dist/esm/word/index.d.ts +4 -4
- package/dist/esm/word/numbering-parser.d.ts +2 -1
- package/dist/esm/word/numbering-parser.js +107 -21
- package/dist/esm/word/paragraph-properties.d.ts +11 -1
- package/dist/esm/word/paragraph-properties.js +219 -10
- package/dist/esm/word/run-properties.js +45 -1
- package/dist/esm/word/settings-parser.d.ts +24 -0
- package/dist/esm/word/settings-parser.js +31 -5
- package/dist/esm/word/shading.d.ts +11 -0
- package/dist/esm/word/shading.js +64 -0
- package/dist/esm/word/styles-parser.js +8 -2
- package/dist/esm/word/table-parser.d.ts +9 -1
- package/dist/esm/word/table-parser.js +182 -30
- package/package.json +1 -1
|
@@ -1,11 +1,37 @@
|
|
|
1
1
|
//#region src/core/numbering/state.ts
|
|
2
2
|
/**
|
|
3
|
+
* §17.9.27 — the levels an INSTANCE actually numbers by: its abstract
|
|
4
|
+
* definition's, with any `w:lvlOverride/w:lvl` shadowing them. Cached per
|
|
5
|
+
* instance, since every list paragraph asks for it.
|
|
6
|
+
*
|
|
7
|
+
* @param numbering The parsed numbering definitions.
|
|
8
|
+
* @param instance The `w:num` the paragraph refers to.
|
|
9
|
+
* @returns The effective abstract numbering, or `undefined` when the instance
|
|
10
|
+
* names one that is not there.
|
|
11
|
+
*/
|
|
12
|
+
function effectiveAbstract(numbering, instance) {
|
|
13
|
+
const base = numbering.abstractNums.get(instance.abstractNumId);
|
|
14
|
+
if (!base || !instance.levelOverrides || instance.levelOverrides.size === 0) return base;
|
|
15
|
+
const hit = effectiveCache.get(instance);
|
|
16
|
+
if (hit) return hit;
|
|
17
|
+
const levels = new Map(base.levels);
|
|
18
|
+
for (const [ilvl, lvl] of instance.levelOverrides) levels.set(ilvl, lvl);
|
|
19
|
+
const merged = {
|
|
20
|
+
id: base.id,
|
|
21
|
+
levels
|
|
22
|
+
};
|
|
23
|
+
effectiveCache.set(instance, merged);
|
|
24
|
+
return merged;
|
|
25
|
+
}
|
|
26
|
+
var effectiveCache = /* @__PURE__ */ new WeakMap();
|
|
27
|
+
/**
|
|
3
28
|
* Mutable list-counter state for one numbering scope (e.g. a body or a single
|
|
4
29
|
* header/footer band). Tracks a counter per list per level and advances them as
|
|
5
30
|
* paragraphs are visited in order.
|
|
6
31
|
*/
|
|
7
32
|
var NumberingState = class {
|
|
8
33
|
counters = /* @__PURE__ */ new Map();
|
|
34
|
+
restarted = /* @__PURE__ */ new Set();
|
|
9
35
|
/**
|
|
10
36
|
* Advance the counter for `ref` (resetting deeper levels) and format its
|
|
11
37
|
* marker text. The first hit at a level seeds it from the level's `start`;
|
|
@@ -19,19 +45,27 @@ var NumberingState = class {
|
|
|
19
45
|
resolveMarker(numbering, ref) {
|
|
20
46
|
const instance = numbering.numInstances.get(ref.numId);
|
|
21
47
|
if (!instance) return null;
|
|
22
|
-
const abstractNum = numbering
|
|
48
|
+
const abstractNum = effectiveAbstract(numbering, instance);
|
|
23
49
|
if (!abstractNum) return null;
|
|
24
50
|
const level = abstractNum.levels.get(ref.ilvl);
|
|
25
51
|
if (!level) return null;
|
|
26
|
-
let arr = this.counters.get(
|
|
52
|
+
let arr = this.counters.get(instance.abstractNumId);
|
|
27
53
|
if (!arr) {
|
|
28
|
-
arr = new Array(9).fill(0);
|
|
29
|
-
this.counters.set(
|
|
54
|
+
arr = new Array(9).fill(void 0);
|
|
55
|
+
this.counters.set(instance.abstractNumId, arr);
|
|
56
|
+
}
|
|
57
|
+
for (let k = ref.ilvl + 1; k < arr.length; k++) arr[k] = void 0;
|
|
58
|
+
const startAt = (i, fallback) => instance.startOverrides?.get(i) ?? fallback ?? 0;
|
|
59
|
+
const restartKey = `${ref.numId}:${String(ref.ilvl)}`;
|
|
60
|
+
const override = instance.startOverrides?.get(ref.ilvl);
|
|
61
|
+
if (override !== void 0 && !this.restarted.has(restartKey)) {
|
|
62
|
+
this.restarted.add(restartKey);
|
|
63
|
+
arr[ref.ilvl] = override;
|
|
64
|
+
} else {
|
|
65
|
+
const current = arr[ref.ilvl];
|
|
66
|
+
arr[ref.ilvl] = current === void 0 ? startAt(ref.ilvl, level.start) : current + 1;
|
|
30
67
|
}
|
|
31
|
-
|
|
32
|
-
if (arr[ref.ilvl] === 0) arr[ref.ilvl] = level.start;
|
|
33
|
-
else arr[ref.ilvl] += 1;
|
|
34
|
-
return formatLevelMarker(abstractNum, level, arr);
|
|
68
|
+
return formatLevelMarker(abstractNum, level, arr.map((n, i) => n ?? startAt(i, abstractNum.levels.get(i)?.start)));
|
|
35
69
|
}
|
|
36
70
|
};
|
|
37
71
|
function formatLevelMarker(abstractNum, currentLevel, counters) {
|
|
@@ -40,20 +74,227 @@ function formatLevelMarker(abstractNum, currentLevel, counters) {
|
|
|
40
74
|
const lvlIdx = Number(n) - 1;
|
|
41
75
|
const level = abstractNum.levels.get(lvlIdx);
|
|
42
76
|
const counter = counters[lvlIdx] ?? 0;
|
|
43
|
-
return formatCounter(level?.format ?? "decimal", counter);
|
|
77
|
+
return formatCounter(currentLevel.isLegal === true && lvlIdx !== currentLevel.ilvl ? "decimal" : level?.format ?? "decimal", counter);
|
|
44
78
|
});
|
|
45
79
|
}
|
|
46
80
|
function formatCounter(format, n) {
|
|
47
|
-
if (n
|
|
81
|
+
if (n < 0) return "";
|
|
48
82
|
switch (format) {
|
|
49
83
|
case "decimal": return String(n);
|
|
50
|
-
case "
|
|
51
|
-
case "
|
|
52
|
-
case "
|
|
53
|
-
case "
|
|
84
|
+
case "decimalZero": return n < 10 ? `0${String(n)}` : String(n);
|
|
85
|
+
case "decimalFullWidth": return digitByDigit(n, FULL_WIDTH_DIGITS);
|
|
86
|
+
case "ordinal": return `${String(n)}${ordinalSuffix(n)}`;
|
|
87
|
+
case "lowerLetter": return n === 0 ? "" : toLetters(n).toLowerCase();
|
|
88
|
+
case "upperLetter": return n === 0 ? "" : toLetters(n);
|
|
89
|
+
case "lowerRoman": return n === 0 ? "" : toRoman(n).toLowerCase();
|
|
90
|
+
case "upperRoman": return n === 0 ? "" : toRoman(n);
|
|
91
|
+
case "ideographTraditional": return n === 0 ? "" : n <= HEAVENLY_STEMS.length ? HEAVENLY_STEMS[n - 1] : String(n);
|
|
92
|
+
case "ideographZodiac": return n === 0 ? "" : n <= EARTHLY_BRANCHES.length ? EARTHLY_BRANCHES[n - 1] : String(n);
|
|
93
|
+
case "ideographDigital":
|
|
94
|
+
case "koreanDigital2": return digitByDigit(n, IDEOGRAPH_DIGITS);
|
|
95
|
+
case "ideographLegalTraditional": return counting(n, LEGAL_DIGITS, LEGAL_UNITS, false);
|
|
96
|
+
case "chineseCounting":
|
|
97
|
+
case "chineseCountingThousand":
|
|
98
|
+
case "japaneseCounting":
|
|
99
|
+
case "koreanCounting":
|
|
100
|
+
case "taiwaneseCounting":
|
|
101
|
+
case "taiwaneseCountingThousand": return counting(n, IDEOGRAPH_DIGITS, COUNTING_UNITS, true);
|
|
102
|
+
case "hebrew1": return n === 0 ? "" : toHebrewNumeral(n);
|
|
103
|
+
case "hebrew2": return n === 0 ? "" : HEBREW_ALPHABET[(n - 1) % HEBREW_ALPHABET.length];
|
|
104
|
+
case "decimalEnclosedCircle": return n >= 1 && n <= 20 ? String.fromCodePoint(9311 + n) : String(n);
|
|
105
|
+
case "chicago":
|
|
106
|
+
if (n < 1) return "";
|
|
107
|
+
return CHICAGO_MARKS[(n - 1) % CHICAGO_MARKS.length].repeat(Math.floor((n - 1) / CHICAGO_MARKS.length) + 1);
|
|
54
108
|
default: return "";
|
|
55
109
|
}
|
|
56
110
|
}
|
|
111
|
+
var HEBREW_ONES = [
|
|
112
|
+
"",
|
|
113
|
+
"א",
|
|
114
|
+
"ב",
|
|
115
|
+
"ג",
|
|
116
|
+
"ד",
|
|
117
|
+
"ה",
|
|
118
|
+
"ו",
|
|
119
|
+
"ז",
|
|
120
|
+
"ח",
|
|
121
|
+
"ט"
|
|
122
|
+
];
|
|
123
|
+
var HEBREW_TENS = [
|
|
124
|
+
"",
|
|
125
|
+
"י",
|
|
126
|
+
"כ",
|
|
127
|
+
"ל",
|
|
128
|
+
"מ",
|
|
129
|
+
"נ",
|
|
130
|
+
"ס",
|
|
131
|
+
"ע",
|
|
132
|
+
"פ",
|
|
133
|
+
"צ"
|
|
134
|
+
];
|
|
135
|
+
var HEBREW_HUNDREDS = [
|
|
136
|
+
"",
|
|
137
|
+
"ק",
|
|
138
|
+
"ר",
|
|
139
|
+
"ש",
|
|
140
|
+
"ת"
|
|
141
|
+
];
|
|
142
|
+
var HEBREW_ALPHABET = [
|
|
143
|
+
"א",
|
|
144
|
+
"ב",
|
|
145
|
+
"ג",
|
|
146
|
+
"ד",
|
|
147
|
+
"ה",
|
|
148
|
+
"ו",
|
|
149
|
+
"ז",
|
|
150
|
+
"ח",
|
|
151
|
+
"ט",
|
|
152
|
+
"י",
|
|
153
|
+
"כ",
|
|
154
|
+
"ל",
|
|
155
|
+
"מ",
|
|
156
|
+
"נ",
|
|
157
|
+
"ס",
|
|
158
|
+
"ע",
|
|
159
|
+
"פ",
|
|
160
|
+
"צ",
|
|
161
|
+
"ק",
|
|
162
|
+
"ר",
|
|
163
|
+
"ש",
|
|
164
|
+
"ת"
|
|
165
|
+
];
|
|
166
|
+
function toHebrewNumeral(n) {
|
|
167
|
+
let rest = n;
|
|
168
|
+
let out = "";
|
|
169
|
+
while (rest >= 400) {
|
|
170
|
+
out += "ת";
|
|
171
|
+
rest -= 400;
|
|
172
|
+
}
|
|
173
|
+
out += HEBREW_HUNDREDS[Math.floor(rest / 100)] ?? "";
|
|
174
|
+
rest %= 100;
|
|
175
|
+
if (rest === 15 || rest === 16) out += rest === 15 ? "טו" : "טז";
|
|
176
|
+
else {
|
|
177
|
+
out += HEBREW_TENS[Math.floor(rest / 10)] ?? "";
|
|
178
|
+
out += HEBREW_ONES[rest % 10] ?? "";
|
|
179
|
+
}
|
|
180
|
+
return out;
|
|
181
|
+
}
|
|
182
|
+
var CHICAGO_MARKS = [
|
|
183
|
+
"*",
|
|
184
|
+
"†",
|
|
185
|
+
"‡",
|
|
186
|
+
"§"
|
|
187
|
+
];
|
|
188
|
+
var IDEOGRAPH_DIGITS = [
|
|
189
|
+
"零",
|
|
190
|
+
"一",
|
|
191
|
+
"二",
|
|
192
|
+
"三",
|
|
193
|
+
"四",
|
|
194
|
+
"五",
|
|
195
|
+
"六",
|
|
196
|
+
"七",
|
|
197
|
+
"八",
|
|
198
|
+
"九"
|
|
199
|
+
];
|
|
200
|
+
var COUNTING_UNITS = [
|
|
201
|
+
"",
|
|
202
|
+
"十",
|
|
203
|
+
"百",
|
|
204
|
+
"千"
|
|
205
|
+
];
|
|
206
|
+
var LEGAL_DIGITS = [
|
|
207
|
+
"零",
|
|
208
|
+
"壹",
|
|
209
|
+
"貳",
|
|
210
|
+
"參",
|
|
211
|
+
"肆",
|
|
212
|
+
"伍",
|
|
213
|
+
"陸",
|
|
214
|
+
"柒",
|
|
215
|
+
"捌",
|
|
216
|
+
"玖"
|
|
217
|
+
];
|
|
218
|
+
var LEGAL_UNITS = [
|
|
219
|
+
"",
|
|
220
|
+
"拾",
|
|
221
|
+
"佰",
|
|
222
|
+
"仟"
|
|
223
|
+
];
|
|
224
|
+
var HEAVENLY_STEMS = [
|
|
225
|
+
"甲",
|
|
226
|
+
"乙",
|
|
227
|
+
"丙",
|
|
228
|
+
"丁",
|
|
229
|
+
"戊",
|
|
230
|
+
"己",
|
|
231
|
+
"庚",
|
|
232
|
+
"辛",
|
|
233
|
+
"壬",
|
|
234
|
+
"癸"
|
|
235
|
+
];
|
|
236
|
+
var EARTHLY_BRANCHES = [
|
|
237
|
+
"子",
|
|
238
|
+
"丑",
|
|
239
|
+
"寅",
|
|
240
|
+
"卯",
|
|
241
|
+
"辰",
|
|
242
|
+
"巳",
|
|
243
|
+
"午",
|
|
244
|
+
"未",
|
|
245
|
+
"申",
|
|
246
|
+
"酉",
|
|
247
|
+
"戌",
|
|
248
|
+
"亥"
|
|
249
|
+
];
|
|
250
|
+
var FULL_WIDTH_DIGITS = [
|
|
251
|
+
"0",
|
|
252
|
+
"1",
|
|
253
|
+
"2",
|
|
254
|
+
"3",
|
|
255
|
+
"4",
|
|
256
|
+
"5",
|
|
257
|
+
"6",
|
|
258
|
+
"7",
|
|
259
|
+
"8",
|
|
260
|
+
"9"
|
|
261
|
+
];
|
|
262
|
+
/** Each decimal digit as its own glyph — no units, no elision (10 → 一零). */
|
|
263
|
+
function digitByDigit(n, digits) {
|
|
264
|
+
return String(n).split("").map((d) => digits[Number(d)] ?? d).join("");
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* The counting systems: digits carrying place units (十百千). `elideTen` drops
|
|
268
|
+
* the leading 一 of the tens place, which is what the plain counting systems do
|
|
269
|
+
* (11 → 十一) and the formal one does not (11 → 壹拾壹). Above the units the
|
|
270
|
+
* table covers, plain digits — a list marker never gets that far.
|
|
271
|
+
*/
|
|
272
|
+
function counting(n, digits, units, elideTen) {
|
|
273
|
+
if (n >= 10 ** units.length) return String(n);
|
|
274
|
+
const ds = String(n).split("").map(Number);
|
|
275
|
+
let out = "";
|
|
276
|
+
ds.forEach((d, i) => {
|
|
277
|
+
const place = ds.length - 1 - i;
|
|
278
|
+
if (d === 0) {
|
|
279
|
+
if (out.length > 0 && !out.endsWith(digits[0]) && ds.slice(i).some((x) => x > 0)) out += digits[0];
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const head = elideTen && d === 1 && place === 1 && i === 0 ? "" : digits[d];
|
|
283
|
+
out += head + units[place];
|
|
284
|
+
});
|
|
285
|
+
return out;
|
|
286
|
+
}
|
|
287
|
+
/** `1st`, `2nd`, `3rd`, `4th` — the English ordinal suffixes (§17.18.59). */
|
|
288
|
+
function ordinalSuffix(n) {
|
|
289
|
+
const two = n % 100;
|
|
290
|
+
if (two >= 11 && two <= 13) return "th";
|
|
291
|
+
switch (n % 10) {
|
|
292
|
+
case 1: return "st";
|
|
293
|
+
case 2: return "nd";
|
|
294
|
+
case 3: return "rd";
|
|
295
|
+
default: return "th";
|
|
296
|
+
}
|
|
297
|
+
}
|
|
57
298
|
function toLetters(n) {
|
|
58
299
|
let s = "";
|
|
59
300
|
let v = n;
|
|
@@ -95,4 +336,4 @@ function normalizeBullet(lvlText) {
|
|
|
95
336
|
return lvlText;
|
|
96
337
|
}
|
|
97
338
|
//#endregion
|
|
98
|
-
export { NumberingState };
|
|
339
|
+
export { NumberingState, effectiveAbstract, formatLevelMarker };
|
|
@@ -65,7 +65,22 @@ function poIntAttr(node, name) {
|
|
|
65
65
|
const v = poAttr(node, name);
|
|
66
66
|
if (v === void 0) return void 0;
|
|
67
67
|
const n = Number(v);
|
|
68
|
-
|
|
68
|
+
if (Number.isFinite(n)) return n;
|
|
69
|
+
return universalMeasureTwips(v);
|
|
70
|
+
}
|
|
71
|
+
var MEASURE_TWIPS = new Map([
|
|
72
|
+
["pt", 20],
|
|
73
|
+
["pc", 240],
|
|
74
|
+
["pi", 240],
|
|
75
|
+
["in", 1440],
|
|
76
|
+
["cm", 1440 / 2.54],
|
|
77
|
+
["mm", 144 / 2.54]
|
|
78
|
+
]);
|
|
79
|
+
function universalMeasureTwips(raw) {
|
|
80
|
+
const m = /^\s*(-?[0-9]+(?:\.[0-9]+)?)(pt|pc|pi|in|cm|mm)\s*$/iu.exec(raw);
|
|
81
|
+
if (!m) return void 0;
|
|
82
|
+
const per = MEASURE_TWIPS.get(m[2].toLowerCase());
|
|
83
|
+
return per === void 0 ? void 0 : Number(m[1]) * per;
|
|
69
84
|
}
|
|
70
85
|
/** Shorthand for the `val` attribute (`@w:val`/…). */
|
|
71
86
|
function poVal(node) {
|
|
@@ -38,8 +38,10 @@ function resolveRunProperties(runDirect, paragraphDirect, sheet) {
|
|
|
38
38
|
}
|
|
39
39
|
function computeRunProperties(runDirect, paragraphDirect, sheet) {
|
|
40
40
|
let acc = mergeRun(DEFAULT_RESOLVED_RUN, sheet.defaultRunProperties);
|
|
41
|
-
if (paragraphDirect.
|
|
42
|
-
|
|
41
|
+
if (paragraphDirect.inheritedRun) acc = mergeRun(acc, paragraphDirect.inheritedRun);
|
|
42
|
+
const styleId = paragraphDirect.styleId ?? defaultParagraphStyleId(sheet);
|
|
43
|
+
if (styleId) {
|
|
44
|
+
const chain = resolveStyleChain(styleId, sheet);
|
|
43
45
|
acc = mergeRun(acc, chain.rPr);
|
|
44
46
|
}
|
|
45
47
|
if (runDirect.styleId) {
|
|
@@ -71,12 +73,27 @@ function resolveParagraphProperties(paragraphDirect, sheet) {
|
|
|
71
73
|
}
|
|
72
74
|
function computeParagraphProperties(paragraphDirect, sheet) {
|
|
73
75
|
let acc = mergePar(DEFAULT_RESOLVED_PARAGRAPH, sheet.defaultParagraphProperties);
|
|
74
|
-
if (paragraphDirect.
|
|
75
|
-
|
|
76
|
+
if (paragraphDirect.tableStyle ?? paragraphDirect.inheritedRun) acc = mergePar(acc, {
|
|
77
|
+
...paragraphDirect.tableStyle,
|
|
78
|
+
...paragraphDirect.inheritedRun ? { runProperties: paragraphDirect.inheritedRun } : {}
|
|
79
|
+
});
|
|
80
|
+
const styleId = paragraphDirect.styleId ?? defaultParagraphStyleId(sheet);
|
|
81
|
+
if (styleId) {
|
|
82
|
+
const chain = resolveStyleChain(styleId, sheet);
|
|
76
83
|
acc = mergePar(acc, chain.pPr);
|
|
77
84
|
}
|
|
78
85
|
return mergePar(acc, paragraphDirect);
|
|
79
86
|
}
|
|
87
|
+
/** The id of the `w:default="1"` paragraph style, cached per sheet. */
|
|
88
|
+
var defaultParagraphStyleCache = /* @__PURE__ */ new WeakMap();
|
|
89
|
+
function defaultParagraphStyleId(sheet) {
|
|
90
|
+
const hit = defaultParagraphStyleCache.get(sheet);
|
|
91
|
+
if (hit !== void 0) return hit ?? void 0;
|
|
92
|
+
let found = null;
|
|
93
|
+
for (const style of sheet.styles.values()) if (style.type === "paragraph" && style.isDefault) found = style.id;
|
|
94
|
+
defaultParagraphStyleCache.set(sheet, found);
|
|
95
|
+
return found ?? void 0;
|
|
96
|
+
}
|
|
80
97
|
function resolveStyleChain(styleId, sheet) {
|
|
81
98
|
const chain = [];
|
|
82
99
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -108,40 +125,72 @@ function mergeRun(base, override) {
|
|
|
108
125
|
bold: override.bold ?? base.bold,
|
|
109
126
|
italic: override.italic ?? base.italic,
|
|
110
127
|
underline: override.underline ?? base.underline,
|
|
128
|
+
...override.underlineColorHex ?? base.underlineColorHex ? { underlineColorHex: override.underlineColorHex ?? base.underlineColorHex } : {},
|
|
111
129
|
strike: override.strike ?? base.strike,
|
|
130
|
+
caps: override.caps ?? base.caps,
|
|
131
|
+
smallCaps: override.smallCaps ?? base.smallCaps,
|
|
112
132
|
fontSizePt: override.fontSizePt ?? base.fontSizePt,
|
|
113
133
|
colorHex: override.colorHex ?? base.colorHex,
|
|
114
134
|
fontFamily: override.fontFamily ?? base.fontFamily,
|
|
115
135
|
verticalAlign: override.verticalAlign ?? base.verticalAlign,
|
|
116
136
|
rtl: override.rtl ?? base.rtl,
|
|
117
|
-
...lang !== void 0 ? { lang } : {}
|
|
137
|
+
...lang !== void 0 ? { lang } : {},
|
|
138
|
+
...(override.shadingColorHex ?? base.shadingColorHex) !== void 0 ? { shadingColorHex: override.shadingColorHex ?? base.shadingColorHex } : {},
|
|
139
|
+
...(override.letterSpacingPt ?? base.letterSpacingPt) !== void 0 ? { letterSpacingPt: override.letterSpacingPt ?? base.letterSpacingPt } : {}
|
|
118
140
|
};
|
|
119
141
|
}
|
|
120
142
|
function mergePar(base, override) {
|
|
121
143
|
const outlineLevel = override.outlineLevel ?? base.outlineLevel;
|
|
122
144
|
const styleId = override.styleId ?? base.styleId;
|
|
123
|
-
const numbering = override.numbering ?? base.numbering
|
|
145
|
+
const numbering = override.numbering ?? (override.numberingLevel !== void 0 && base.numbering !== void 0 ? {
|
|
146
|
+
...base.numbering,
|
|
147
|
+
ilvl: override.numberingLevel
|
|
148
|
+
} : base.numbering);
|
|
149
|
+
const runProperties = override.runProperties ?? base.runProperties;
|
|
150
|
+
const frame = override.frame ?? base.frame;
|
|
151
|
+
const sectionBreak = override.sectionBreak ?? base.sectionBreak;
|
|
152
|
+
const textDirection = override.textDirection ?? base.textDirection;
|
|
153
|
+
const snapToGrid = override.snapToGrid ?? base.snapToGrid;
|
|
124
154
|
return {
|
|
125
155
|
alignment: override.alignment ?? base.alignment,
|
|
126
|
-
spacingBefore: override.spacingBefore ?? base.spacingBefore,
|
|
127
|
-
spacingAfter: override.spacingAfter ?? base.spacingAfter,
|
|
156
|
+
spacingBefore: override.spacingBeforeAuto ?? override.spacingBefore ?? base.spacingBefore,
|
|
157
|
+
spacingAfter: override.spacingAfterAuto ?? override.spacingAfter ?? base.spacingAfter,
|
|
128
158
|
spacingLine: override.spacingLine ?? base.spacingLine,
|
|
129
159
|
spacingLineRule: override.spacingLineRule ?? base.spacingLineRule,
|
|
130
160
|
indentLeft: override.indentLeft ?? base.indentLeft,
|
|
131
161
|
indentRight: override.indentRight ?? base.indentRight,
|
|
132
162
|
indentFirstLine: override.indentFirstLine ?? base.indentFirstLine,
|
|
133
163
|
pageBreakBefore: override.pageBreakBefore ?? base.pageBreakBefore,
|
|
164
|
+
contextualSpacing: override.contextualSpacing ?? base.contextualSpacing,
|
|
165
|
+
tabs: override.tabs ?? base.tabs,
|
|
134
166
|
bidi: override.bidi ?? base.bidi,
|
|
167
|
+
...override.borders ?? base.borders ? { borders: override.borders ?? base.borders } : {},
|
|
168
|
+
...override.shading ?? base.shading ? { shading: override.shading ?? base.shading } : {},
|
|
135
169
|
...outlineLevel !== void 0 ? { outlineLevel } : {},
|
|
136
170
|
...styleId !== void 0 ? { styleId } : {},
|
|
137
|
-
...numbering !== void 0 ? { numbering } : {}
|
|
171
|
+
...numbering !== void 0 ? { numbering } : {},
|
|
172
|
+
...runProperties !== void 0 ? { runProperties } : {},
|
|
173
|
+
...frame !== void 0 ? { frame } : {},
|
|
174
|
+
...sectionBreak !== void 0 ? { sectionBreak } : {},
|
|
175
|
+
...textDirection !== void 0 ? { textDirection } : {},
|
|
176
|
+
...snapToGrid !== void 0 ? { snapToGrid } : {}
|
|
138
177
|
};
|
|
139
178
|
}
|
|
140
179
|
function mergeRunPartial(base, override) {
|
|
141
180
|
return copyDefined(base, override);
|
|
142
181
|
}
|
|
143
182
|
function mergeParPartial(base, override) {
|
|
144
|
-
|
|
183
|
+
const out = copyDefined(base, override);
|
|
184
|
+
if (override.numbering === void 0 && override.numberingLevel !== void 0) {
|
|
185
|
+
if (base.numbering !== void 0) return {
|
|
186
|
+
...out,
|
|
187
|
+
numbering: {
|
|
188
|
+
...base.numbering,
|
|
189
|
+
ilvl: override.numberingLevel
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
return out;
|
|
145
194
|
}
|
|
146
195
|
function copyDefined(base, override) {
|
|
147
196
|
const out = { ...base };
|
|
@@ -188,7 +237,13 @@ function resolveBodyStyles(body, sheet) {
|
|
|
188
237
|
const visit = (el) => {
|
|
189
238
|
if (el.kind === "paragraph") visitParagraph(el.paragraph);
|
|
190
239
|
else if (el.kind === "table") for (const row of el.table.rows) for (const cell of row.cells) for (const child of cell.content) visit(child);
|
|
191
|
-
else if (el.kind === "shape"
|
|
240
|
+
else if (el.kind === "shape") {
|
|
241
|
+
const shapeText = (sh) => {
|
|
242
|
+
for (const child of sh.text?.content ?? []) visit(child);
|
|
243
|
+
for (const member of sh.children ?? []) shapeText(member.shape);
|
|
244
|
+
};
|
|
245
|
+
shapeText(el.shape);
|
|
246
|
+
}
|
|
192
247
|
};
|
|
193
248
|
for (const el of body) visit(el);
|
|
194
249
|
return body;
|
|
@@ -22,8 +22,10 @@ function applyTableStyle(table, sheet) {
|
|
|
22
22
|
const folded = foldTableStyleChain(styleId, sheet);
|
|
23
23
|
if (!folded) return;
|
|
24
24
|
const tp = table.properties;
|
|
25
|
+
const directBorders = tp.borders;
|
|
25
26
|
if (!tp.borders && folded.base.borders) tp.borders = folded.base.borders;
|
|
26
27
|
if (!tp.defaultCellMargins && folded.base.cellMargins) tp.defaultCellMargins = folded.base.cellMargins;
|
|
28
|
+
if (tp.indentPt === void 0 && folded.base.indentPt !== void 0) tp.indentPt = folded.base.indentPt;
|
|
27
29
|
const look = table.properties.look ?? {};
|
|
28
30
|
const rows = table.rows;
|
|
29
31
|
const colCount = Math.max(table.grid.length, ...rows.map((r) => r.cells.reduce((s, c) => s + (c.properties.colSpan ?? 1), 0)));
|
|
@@ -33,8 +35,8 @@ function applyTableStyle(table, sheet) {
|
|
|
33
35
|
for (const cell of row.cells) {
|
|
34
36
|
const span = cell.properties.colSpan ?? 1;
|
|
35
37
|
const layer = cellLayer(folded, look, {
|
|
36
|
-
firstRow: r === 0,
|
|
37
|
-
lastRow: r === rows.length - 1,
|
|
38
|
+
firstRow: r === 0 || row.properties.conditional?.firstRow === true,
|
|
39
|
+
lastRow: r === rows.length - 1 || row.properties.conditional?.lastRow === true,
|
|
38
40
|
firstCol: colStart === 0,
|
|
39
41
|
lastCol: colStart + span >= colCount,
|
|
40
42
|
rowBand: bandIndex(r, look.firstRow === true, folded.rowBandSize),
|
|
@@ -42,20 +44,34 @@ function applyTableStyle(table, sheet) {
|
|
|
42
44
|
noHBand: look.noHBand === true,
|
|
43
45
|
noVBand: look.noVBand === true
|
|
44
46
|
});
|
|
47
|
+
const pos = {
|
|
48
|
+
firstRow: r === 0 || row.properties.conditional?.firstRow === true,
|
|
49
|
+
lastRow: r === rows.length - 1 || row.properties.conditional?.lastRow === true,
|
|
50
|
+
firstCol: colStart === 0,
|
|
51
|
+
lastCol: colStart + span >= colCount
|
|
52
|
+
};
|
|
45
53
|
colStart += span;
|
|
46
54
|
if (!layer) continue;
|
|
47
|
-
applyLayerToCell(cell, layer);
|
|
55
|
+
applyLayerToCell(cell, layer, directBorders, pos);
|
|
48
56
|
}
|
|
49
57
|
}
|
|
50
58
|
}
|
|
51
|
-
function applyLayerToCell(tableCell, layer) {
|
|
59
|
+
function applyLayerToCell(tableCell, layer, directBorders, pos) {
|
|
52
60
|
const cell = tableCell;
|
|
53
61
|
if (layer.shading && !cell.properties.shading) cell.properties.shading = layer.shading;
|
|
54
62
|
if (layer.cellMargins && !cell.properties.margins) cell.properties.margins = layer.cellMargins;
|
|
55
63
|
if (layer.borders) {
|
|
56
64
|
const own = cell.properties.borders ?? {};
|
|
65
|
+
const fromStyle = { ...layer.borders };
|
|
66
|
+
if (directBorders) {
|
|
67
|
+
const stated = (side, outer) => (outer ? directBorders[side] : directBorders[side === "top" || side === "bottom" ? "insideH" : "insideV"]) !== void 0;
|
|
68
|
+
if (stated("top", pos.firstRow)) delete fromStyle.top;
|
|
69
|
+
if (stated("bottom", pos.lastRow)) delete fromStyle.bottom;
|
|
70
|
+
if (stated("left", pos.firstCol)) delete fromStyle.left;
|
|
71
|
+
if (stated("right", pos.lastCol)) delete fromStyle.right;
|
|
72
|
+
}
|
|
57
73
|
const merged = {
|
|
58
|
-
...
|
|
74
|
+
...fromStyle,
|
|
59
75
|
...definedOnly(own)
|
|
60
76
|
};
|
|
61
77
|
cell.properties.borders = merged;
|
|
@@ -64,12 +80,18 @@ function applyLayerToCell(tableCell, layer) {
|
|
|
64
80
|
if (el.kind !== "paragraph") continue;
|
|
65
81
|
const p = el.paragraph;
|
|
66
82
|
if (layer.paragraphProperties) p.properties = {
|
|
67
|
-
...
|
|
68
|
-
|
|
83
|
+
...p.properties,
|
|
84
|
+
tableStyle: {
|
|
85
|
+
...p.properties.tableStyle,
|
|
86
|
+
...layer.paragraphProperties
|
|
87
|
+
}
|
|
69
88
|
};
|
|
70
|
-
if (layer.runProperties)
|
|
71
|
-
...
|
|
72
|
-
|
|
89
|
+
if (layer.runProperties) p.properties = {
|
|
90
|
+
...p.properties,
|
|
91
|
+
inheritedRun: {
|
|
92
|
+
...p.properties.inheritedRun,
|
|
93
|
+
...layer.runProperties
|
|
94
|
+
}
|
|
73
95
|
};
|
|
74
96
|
}
|
|
75
97
|
}
|
|
@@ -79,7 +101,8 @@ function bandIndex(index, skipFirst, bandSize) {
|
|
|
79
101
|
return Math.floor(adjusted / Math.max(1, bandSize));
|
|
80
102
|
}
|
|
81
103
|
function cellLayer(folded, look, pos) {
|
|
82
|
-
const
|
|
104
|
+
const { borders: _tableWide, ...withoutBorders } = folded.base;
|
|
105
|
+
const layers = [withoutBorders];
|
|
83
106
|
const cond = (t) => folded.conditions.get(t);
|
|
84
107
|
if (!pos.noVBand && pos.colBand >= 0) layers.push(pos.colBand % 2 === 0 ? cond("band1Vert") : cond("band2Vert"));
|
|
85
108
|
if (!pos.noHBand && pos.rowBand >= 0) layers.push(pos.rowBand % 2 === 0 ? cond("band1Horz") : cond("band2Horz"));
|
|
@@ -145,6 +168,7 @@ function mergeLayer(base, override) {
|
|
|
145
168
|
...base.cellMargins,
|
|
146
169
|
...definedOnly(override.cellMargins ?? {})
|
|
147
170
|
} } : {},
|
|
171
|
+
...(override.indentPt ?? base.indentPt) !== void 0 ? { indentPt: override.indentPt ?? base.indentPt } : {},
|
|
148
172
|
...override.shading ?? base.shading ? { shading: override.shading ?? base.shading } : {},
|
|
149
173
|
...override.runProperties ?? base.runProperties ? { runProperties: {
|
|
150
174
|
...base.runProperties,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Alignment, FontFamilyMap, NumberingReference, UnderlineStyle, VerticalAlign } from '../document-model/index.js';
|
|
1
|
+
import { Alignment, CellBorders, CellShading, FontFamilyMap, FrameProperties, NumberingReference, RunProperties, TabStop, UnderlineStyle, VerticalAlign } from '../document-model/index.js';
|
|
2
2
|
import { Pt } from '../ir/index.js';
|
|
3
3
|
/**
|
|
4
4
|
* A run's fully-resolved properties: every field required because the cascade
|
|
@@ -9,7 +9,13 @@ export interface ResolvedRunProperties {
|
|
|
9
9
|
readonly bold: boolean;
|
|
10
10
|
readonly italic: boolean;
|
|
11
11
|
readonly underline: UnderlineStyle;
|
|
12
|
+
/** §17.3.2.40 `w:u @w:color` — the underline's own colour; absent means the text's. */
|
|
13
|
+
readonly underlineColorHex?: string;
|
|
12
14
|
readonly strike: boolean;
|
|
15
|
+
/** §17.3.2.5 `w:caps` — displayed in capitals. */
|
|
16
|
+
readonly caps: boolean;
|
|
17
|
+
/** §17.3.2.33 `w:smallCaps` — displayed in capitals, the lower case smaller. */
|
|
18
|
+
readonly smallCaps: boolean;
|
|
13
19
|
readonly fontSizePt: Pt;
|
|
14
20
|
readonly colorHex: string;
|
|
15
21
|
readonly fontFamily: FontFamilyMap;
|
|
@@ -20,6 +26,10 @@ export interface ResolvedRunProperties {
|
|
|
20
26
|
* specifies one; consumed by the tagged-PDF per-element `/Lang`, never layout.
|
|
21
27
|
*/
|
|
22
28
|
readonly lang?: string;
|
|
29
|
+
/** §17.3.2.32 — the background painted behind the run's glyphs. */
|
|
30
|
+
readonly shadingColorHex?: string;
|
|
31
|
+
/** §17.3.2.35 — extra space between the run's characters, in points. */
|
|
32
|
+
readonly letterSpacingPt?: Pt;
|
|
23
33
|
}
|
|
24
34
|
/**
|
|
25
35
|
* A paragraph's fully-resolved properties: every field required, the cascade
|
|
@@ -35,6 +45,14 @@ export interface ResolvedParagraphProperties {
|
|
|
35
45
|
readonly indentRight: Pt;
|
|
36
46
|
readonly indentFirstLine: Pt;
|
|
37
47
|
readonly pageBreakBefore: boolean;
|
|
48
|
+
/** §17.3.1.9 — drop the space between this paragraph and a same-styled neighbour. */
|
|
49
|
+
readonly contextualSpacing: boolean;
|
|
50
|
+
/** §17.3.1.37 — the paragraph's tab stops, in ascending position order. */
|
|
51
|
+
readonly tabs: ReadonlyArray<TabStop>;
|
|
52
|
+
/** §17.3.1.24 `w:pBdr` — rules drawn around the paragraph. */
|
|
53
|
+
readonly borders?: CellBorders;
|
|
54
|
+
/** §17.3.1.31 `w:pPr/w:shd` — the paragraph's own background fill. */
|
|
55
|
+
readonly shading?: CellShading;
|
|
38
56
|
readonly bidi: boolean;
|
|
39
57
|
/**
|
|
40
58
|
* ECMA-376 §17.3.1.20 — resolved outline level (0–8). Undefined = body text.
|
|
@@ -46,11 +64,34 @@ export interface ResolvedParagraphProperties {
|
|
|
46
64
|
* detection when a style lacks an explicit outline level.
|
|
47
65
|
*/
|
|
48
66
|
readonly styleId?: string;
|
|
67
|
+
/**
|
|
68
|
+
* §17.3.1.29 `w:pPr/w:rPr` — the formatting of the paragraph MARK. An empty
|
|
69
|
+
* paragraph is as tall as its mark, so dropping this on resolution collapsed
|
|
70
|
+
* a 36pt empty cell to a line of body text (conditionalstyles-tbllook.docx).
|
|
71
|
+
*/
|
|
72
|
+
readonly runProperties?: RunProperties;
|
|
73
|
+
/** §17.3.1.11 — the paragraph floats as a text frame. */
|
|
74
|
+
readonly frame?: FrameProperties;
|
|
75
|
+
/** §17.3.1.41 — which way the paragraph's lines run (`lrTb` is not recorded). */
|
|
76
|
+
readonly textDirection?: 'btLr' | 'tbRl';
|
|
77
|
+
/** §17.3.1.32 — whether these lines stand on the section's grid. Absent ⇒ they do. */
|
|
78
|
+
readonly snapToGrid?: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* §17.6.17 — the paragraph mark carries the section break, so a paragraph
|
|
81
|
+
* with no content of its own prints nothing at all.
|
|
82
|
+
*/
|
|
83
|
+
readonly sectionBreak?: boolean;
|
|
49
84
|
/**
|
|
50
85
|
* §17.9 list reference, carried through for tagged-PDF list structure
|
|
51
86
|
* (L/LI nesting) — markers themselves are materialized by `applyNumbering`.
|
|
52
87
|
*/
|
|
53
88
|
readonly numbering?: NumberingReference;
|
|
89
|
+
/**
|
|
90
|
+
* §17.6.5 — the line pitch of the section's document grid, in points. Not a
|
|
91
|
+
* property of the paragraph at all: the section it falls in owns it, and the
|
|
92
|
+
* layout stamps it here so a line knows the grid it stands on.
|
|
93
|
+
*/
|
|
94
|
+
readonly gridLinePitchPt?: Pt;
|
|
54
95
|
}
|
|
55
96
|
/** Word's empty-document run defaults (used when `docDefaults` is absent). */
|
|
56
97
|
export declare const DEFAULT_RESOLVED_RUN: ResolvedRunProperties;
|
|
@@ -6,6 +6,8 @@ var DEFAULT_RESOLVED_RUN = {
|
|
|
6
6
|
italic: false,
|
|
7
7
|
underline: "none",
|
|
8
8
|
strike: false,
|
|
9
|
+
caps: false,
|
|
10
|
+
smallCaps: false,
|
|
9
11
|
fontSizePt: halfPtToPt(22),
|
|
10
12
|
colorHex: "000000",
|
|
11
13
|
fontFamily: {},
|
|
@@ -23,6 +25,8 @@ var DEFAULT_RESOLVED_PARAGRAPH = {
|
|
|
23
25
|
indentRight: twipsToPt(0),
|
|
24
26
|
indentFirstLine: twipsToPt(0),
|
|
25
27
|
pageBreakBefore: false,
|
|
28
|
+
contextualSpacing: false,
|
|
29
|
+
tabs: [],
|
|
26
30
|
bidi: false
|
|
27
31
|
};
|
|
28
32
|
//#endregion
|