@gct-paas/word 0.1.34 → 0.1.35
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.
|
@@ -79,6 +79,11 @@ export declare class DataManager {
|
|
|
79
79
|
private get2DByCoords;
|
|
80
80
|
private set2DByCoords;
|
|
81
81
|
private cleanupCrossByAxisUid;
|
|
82
|
+
/**
|
|
83
|
+
* 复制轴行插入时:若 uid 与已有行重复,换新 uid 并复制关联交叉区行。
|
|
84
|
+
*/
|
|
85
|
+
private duplicateCrossRowsByAxisUid;
|
|
86
|
+
private prepareAxisRowForInsert;
|
|
82
87
|
/**
|
|
83
88
|
* 将一个部分值对象合进整体
|
|
84
89
|
*/
|
|
@@ -46,6 +46,8 @@ export declare class Wtc extends ModelGroup {
|
|
|
46
46
|
/** 是否是合并起始单元格 */
|
|
47
47
|
get isMergeStart(): boolean;
|
|
48
48
|
get contents(): Wp[];
|
|
49
|
+
/** 单元格垂直对齐(w:tcPr/w:vAlign) */
|
|
50
|
+
get vAlign(): 'top' | 'center' | 'bottom' | undefined;
|
|
49
51
|
get firstContent(): Wp | undefined;
|
|
50
52
|
get lastContent(): Wp | undefined;
|
|
51
53
|
get cellMergeInfo(): {
|
|
@@ -18,6 +18,8 @@ export declare class Paragraph extends LayoutGroup<LayoutNode> {
|
|
|
18
18
|
component: "paragraph";
|
|
19
19
|
parent: ParagraphParent;
|
|
20
20
|
baseline: number;
|
|
21
|
+
/** 上次 layout 应用的水平对齐偏移,避免重复 layout 时累加 */
|
|
22
|
+
private _alignmentOffset;
|
|
21
23
|
splitFillEvent: EventUtil;
|
|
22
24
|
constructor(options: ParagraphOptions);
|
|
23
25
|
/**
|
package/dist/index.es.js
CHANGED
|
@@ -22204,7 +22204,7 @@ class WpPr extends ModelNode {
|
|
|
22204
22204
|
while (node.parent) {
|
|
22205
22205
|
node = node.parent;
|
|
22206
22206
|
}
|
|
22207
|
-
this._cachedWStyles = node.styles;
|
|
22207
|
+
this._cachedWStyles = node.styles ?? node.root?.styles;
|
|
22208
22208
|
return this._cachedWStyles;
|
|
22209
22209
|
}
|
|
22210
22210
|
/**
|
|
@@ -22433,6 +22433,13 @@ class Wp extends ModelGroup {
|
|
|
22433
22433
|
constructor(options) {
|
|
22434
22434
|
super(options);
|
|
22435
22435
|
this.pPr = options.pPr;
|
|
22436
|
+
this.bindPPrParent();
|
|
22437
|
+
}
|
|
22438
|
+
/** 将 pPr 挂到段落节点,供样式解析沿 parent 链查找 styles */
|
|
22439
|
+
bindPPrParent() {
|
|
22440
|
+
if (this.pPr) {
|
|
22441
|
+
this.pPr.parent = this;
|
|
22442
|
+
}
|
|
22436
22443
|
}
|
|
22437
22444
|
get styleId() {
|
|
22438
22445
|
return this.pPr?.styleId;
|
|
@@ -22492,6 +22499,7 @@ class Wp extends ModelGroup {
|
|
|
22492
22499
|
wp.runs.forEach((run) => {
|
|
22493
22500
|
run.parent = wp;
|
|
22494
22501
|
});
|
|
22502
|
+
wp.bindPPrParent();
|
|
22495
22503
|
return wp;
|
|
22496
22504
|
}
|
|
22497
22505
|
toXmlJson() {
|
|
@@ -22560,6 +22568,7 @@ class Wp extends ModelGroup {
|
|
|
22560
22568
|
ensurePPr() {
|
|
22561
22569
|
if (!this.pPr) {
|
|
22562
22570
|
this.pPr = new WpPr({ elements: [] });
|
|
22571
|
+
this.bindPPrParent();
|
|
22563
22572
|
}
|
|
22564
22573
|
return this.pPr;
|
|
22565
22574
|
}
|
|
@@ -22695,6 +22704,15 @@ class Wtc extends ModelGroup {
|
|
|
22695
22704
|
get contents() {
|
|
22696
22705
|
return this.children.filter((child) => child instanceof Wp);
|
|
22697
22706
|
}
|
|
22707
|
+
/** 单元格垂直对齐(w:tcPr/w:vAlign) */
|
|
22708
|
+
get vAlign() {
|
|
22709
|
+
const elem = this.tcPrRaw ? pickElement(this.tcPrRaw, "w:vAlign") : void 0;
|
|
22710
|
+
const val = elem?.["@attrs"]?.["w:val"];
|
|
22711
|
+
if (val === "center" || val === "bottom" || val === "top") {
|
|
22712
|
+
return val;
|
|
22713
|
+
}
|
|
22714
|
+
return void 0;
|
|
22715
|
+
}
|
|
22698
22716
|
get firstContent() {
|
|
22699
22717
|
return this.contents[0];
|
|
22700
22718
|
}
|
|
@@ -26036,6 +26054,101 @@ class Wdocument extends ModelGroup {
|
|
|
26036
26054
|
return result;
|
|
26037
26055
|
}
|
|
26038
26056
|
}
|
|
26057
|
+
class ParagraphStyleResolver {
|
|
26058
|
+
/**
|
|
26059
|
+
* 计算段落的有效样式
|
|
26060
|
+
* 优先级:直接属性 > 样式定义 > 文档默认
|
|
26061
|
+
*
|
|
26062
|
+
* @param wpPr - 段落属性节点
|
|
26063
|
+
* @returns 计算后的有效样式
|
|
26064
|
+
*
|
|
26065
|
+
* @example
|
|
26066
|
+
* const style = ParagraphStyleResolver.resolve(wpPr);
|
|
26067
|
+
* console.log(style.alignment); // 可能来自直接属性或样式定义
|
|
26068
|
+
*/
|
|
26069
|
+
static resolve(wpPr) {
|
|
26070
|
+
const directStyle = wpPr.directStyle;
|
|
26071
|
+
if (!wpPr.styleId || !wpPr.wStyles) {
|
|
26072
|
+
return directStyle;
|
|
26073
|
+
}
|
|
26074
|
+
const styleDefinition = wpPr.wStyles.resolveStyleDef(wpPr.styleId);
|
|
26075
|
+
if (!styleDefinition) {
|
|
26076
|
+
return directStyle;
|
|
26077
|
+
}
|
|
26078
|
+
const inheritedStyle = this.convertPPrToStyle(styleDefinition.pPr);
|
|
26079
|
+
return this.mergeStyles(inheritedStyle, directStyle);
|
|
26080
|
+
}
|
|
26081
|
+
/**
|
|
26082
|
+
* 从 WparagraphProperties 转换为 ParagraphStyle
|
|
26083
|
+
*
|
|
26084
|
+
* WparagraphProperties 是样式体系内部使用的数值化表示
|
|
26085
|
+
* ParagraphStyle 是对外的字符串化 API 表示
|
|
26086
|
+
*
|
|
26087
|
+
* @param pPr - 段落属性对象(可能为 undefined)
|
|
26088
|
+
* @returns 转换后的段落样式
|
|
26089
|
+
*/
|
|
26090
|
+
static convertPPrToStyle(pPr) {
|
|
26091
|
+
if (!pPr) {
|
|
26092
|
+
return {};
|
|
26093
|
+
}
|
|
26094
|
+
const style = {};
|
|
26095
|
+
if (pPr.alignment) {
|
|
26096
|
+
style.alignment = pPr.alignment;
|
|
26097
|
+
}
|
|
26098
|
+
if (pPr.indent && Object.keys(pPr.indent).length > 0) {
|
|
26099
|
+
style.indent = {
|
|
26100
|
+
left: pPr.indent.left?.toString(),
|
|
26101
|
+
right: pPr.indent.right?.toString(),
|
|
26102
|
+
firstLine: pPr.indent.firstLine?.toString()
|
|
26103
|
+
};
|
|
26104
|
+
}
|
|
26105
|
+
if (pPr.spacing && Object.keys(pPr.spacing).length > 0) {
|
|
26106
|
+
style.spacing = {
|
|
26107
|
+
before: pPr.spacing.before?.toString(),
|
|
26108
|
+
after: pPr.spacing.after?.toString(),
|
|
26109
|
+
line: pPr.spacing.line?.toString(),
|
|
26110
|
+
beforeAutospacing: pPr.spacing.beforeAutospacing,
|
|
26111
|
+
afterAutospacing: pPr.spacing.afterAutospacing
|
|
26112
|
+
};
|
|
26113
|
+
}
|
|
26114
|
+
return style;
|
|
26115
|
+
}
|
|
26116
|
+
/**
|
|
26117
|
+
* 深度合并两个样式对象
|
|
26118
|
+
* 后来的值优先覆盖前面的值(override > base)
|
|
26119
|
+
*
|
|
26120
|
+
* @param base - 基础样式(如样式定义)
|
|
26121
|
+
* @param override - 覆盖样式(如直接属性)
|
|
26122
|
+
* @returns 合并后的样式
|
|
26123
|
+
*/
|
|
26124
|
+
static mergeStyles(base, override) {
|
|
26125
|
+
const result = {};
|
|
26126
|
+
result.alignment = override.alignment ?? base.alignment;
|
|
26127
|
+
if (base.indent || override.indent) {
|
|
26128
|
+
result.indent = {
|
|
26129
|
+
left: override.indent?.left ?? base.indent?.left,
|
|
26130
|
+
right: override.indent?.right ?? base.indent?.right,
|
|
26131
|
+
firstLine: override.indent?.firstLine ?? base.indent?.firstLine
|
|
26132
|
+
};
|
|
26133
|
+
}
|
|
26134
|
+
if (base.spacing || override.spacing) {
|
|
26135
|
+
result.spacing = {
|
|
26136
|
+
before: override.spacing?.before ?? base.spacing?.before,
|
|
26137
|
+
after: override.spacing?.after ?? base.spacing?.after,
|
|
26138
|
+
line: override.spacing?.line ?? base.spacing?.line,
|
|
26139
|
+
beforeAutospacing: override.spacing?.beforeAutospacing ?? base.spacing?.beforeAutospacing,
|
|
26140
|
+
afterAutospacing: override.spacing?.afterAutospacing ?? base.spacing?.afterAutospacing
|
|
26141
|
+
};
|
|
26142
|
+
}
|
|
26143
|
+
if (base.lang || override.lang) {
|
|
26144
|
+
result.lang = {
|
|
26145
|
+
val: override.lang?.val ?? base.lang?.val,
|
|
26146
|
+
eastAsia: override.lang?.eastAsia ?? base.lang?.eastAsia
|
|
26147
|
+
};
|
|
26148
|
+
}
|
|
26149
|
+
return result;
|
|
26150
|
+
}
|
|
26151
|
+
}
|
|
26039
26152
|
class TextStyleResolver {
|
|
26040
26153
|
/**
|
|
26041
26154
|
* 计算字符的有效样式
|
|
@@ -40251,6 +40364,8 @@ class Paragraph extends LayoutGroup {
|
|
|
40251
40364
|
component = BuiltinComponentTypeConst.Paragraph;
|
|
40252
40365
|
baseline = 0;
|
|
40253
40366
|
// 基线位置,默认为 0,表示与段落顶部对齐
|
|
40367
|
+
/** 上次 layout 应用的水平对齐偏移,避免重复 layout 时累加 */
|
|
40368
|
+
_alignmentOffset = 0;
|
|
40254
40369
|
splitFillEvent = new EventUtil();
|
|
40255
40370
|
// backgroundColor?: string = 'rgba(0,0,0,0.06)';
|
|
40256
40371
|
// borderTop?: Border = {
|
|
@@ -40317,15 +40432,19 @@ class Paragraph extends LayoutGroup {
|
|
|
40317
40432
|
}
|
|
40318
40433
|
applyStyle() {
|
|
40319
40434
|
const wp = this.doc.layoutMapper.getModelNodeById(this.modelRef.id);
|
|
40320
|
-
const style = wp?.pPr
|
|
40435
|
+
const style = wp?.pPr ? ParagraphStyleResolver.resolve(wp.pPr) : {};
|
|
40321
40436
|
let offset2 = 0;
|
|
40322
40437
|
if (style.alignment === "center") {
|
|
40323
40438
|
offset2 = (this.width - this.getContextWidth()) / 2;
|
|
40324
40439
|
} else if (style.alignment === "right") {
|
|
40325
40440
|
offset2 = this.width - this.getContextWidth();
|
|
40326
40441
|
}
|
|
40442
|
+
offset2 = Math.max(offset2, 0);
|
|
40443
|
+
const delta = offset2 - this._alignmentOffset;
|
|
40444
|
+
this._alignmentOffset = offset2;
|
|
40445
|
+
if (delta === 0) return;
|
|
40327
40446
|
this.forEachChild((child) => {
|
|
40328
|
-
child.x +=
|
|
40447
|
+
child.x += delta;
|
|
40329
40448
|
});
|
|
40330
40449
|
}
|
|
40331
40450
|
/**
|
|
@@ -42310,8 +42429,18 @@ class TableCell extends LayoutGroup {
|
|
|
42310
42429
|
layout(x2, y2) {
|
|
42311
42430
|
this.layoutX = x2;
|
|
42312
42431
|
this.layoutY = y2;
|
|
42432
|
+
const contentHeight = this.getContentHeight();
|
|
42433
|
+
const innerHeight = this.height - this.pt - this.pb;
|
|
42434
|
+
let contentOffsetY = 0;
|
|
42435
|
+
const wtc = this.modelRef ? this.doc.layoutMapper.getModelNodeById(this.modelRef.id) : void 0;
|
|
42436
|
+
const vAlign = wtc?.vAlign;
|
|
42437
|
+
if (vAlign === "center") {
|
|
42438
|
+
contentOffsetY = Math.max(0, (innerHeight - contentHeight) / 2);
|
|
42439
|
+
} else if (vAlign === "bottom") {
|
|
42440
|
+
contentOffsetY = Math.max(0, innerHeight - contentHeight);
|
|
42441
|
+
}
|
|
42313
42442
|
this.forEachChild((child) => {
|
|
42314
|
-
child.layout(this.layoutX + this.pl, this.layoutY + this.pt + child.y);
|
|
42443
|
+
child.layout(this.layoutX + this.pl, this.layoutY + this.pt + contentOffsetY + child.y);
|
|
42315
42444
|
});
|
|
42316
42445
|
}
|
|
42317
42446
|
}
|
|
@@ -46160,6 +46289,39 @@ class DataManager {
|
|
|
46160
46289
|
this.emit(path2, next, oldValue);
|
|
46161
46290
|
});
|
|
46162
46291
|
}
|
|
46292
|
+
/**
|
|
46293
|
+
* 复制轴行插入时:若 uid 与已有行重复,换新 uid 并复制关联交叉区行。
|
|
46294
|
+
*/
|
|
46295
|
+
duplicateCrossRowsByAxisUid(crossKeys, axis, oldUid, newUid) {
|
|
46296
|
+
const uidField = axis === "y" ? "__gw_y_uid" : "__gw_x_uid";
|
|
46297
|
+
for (const crossKey of crossKeys) {
|
|
46298
|
+
const path2 = `$.${crossKey}`;
|
|
46299
|
+
const rows = this.getByPath(this.rawData, path2);
|
|
46300
|
+
if (!Array.isArray(rows)) continue;
|
|
46301
|
+
const matched = rows.filter((item) => item?.[uidField] === oldUid);
|
|
46302
|
+
if (matched.length === 0) continue;
|
|
46303
|
+
const oldValue = this.deepClone(rows);
|
|
46304
|
+
const copies = matched.map((item) => {
|
|
46305
|
+
const copy = this.deepClone(item);
|
|
46306
|
+
copy[uidField] = newUid;
|
|
46307
|
+
return copy;
|
|
46308
|
+
});
|
|
46309
|
+
const next = [...rows, ...copies];
|
|
46310
|
+
this.setByPath(this.rawData, path2, next);
|
|
46311
|
+
this.emit(path2, next, oldValue);
|
|
46312
|
+
}
|
|
46313
|
+
}
|
|
46314
|
+
prepareAxisRowForInsert(arr, axisInfo, value) {
|
|
46315
|
+
const cloned = this.deepClone(value);
|
|
46316
|
+
const uidField = axisInfo.axis === "y" ? "__gw_y_uid" : "__gw_x_uid";
|
|
46317
|
+
const oldUid = cloned?.[uidField];
|
|
46318
|
+
if (oldUid && arr.some((row) => row?.[uidField] === oldUid)) {
|
|
46319
|
+
const newUid = `${axisInfo.axis}_${uuid()}`;
|
|
46320
|
+
cloned[uidField] = newUid;
|
|
46321
|
+
this.duplicateCrossRowsByAxisUid(axisInfo.crossKeys, axisInfo.axis, oldUid, newUid);
|
|
46322
|
+
}
|
|
46323
|
+
return cloned;
|
|
46324
|
+
}
|
|
46163
46325
|
/**
|
|
46164
46326
|
* 将一个部分值对象合进整体
|
|
46165
46327
|
*/
|
|
@@ -46229,7 +46391,7 @@ class DataManager {
|
|
|
46229
46391
|
const tableKey = path2.replace(/^\$\./, "").replace(/\[(n|\d+)\]/g, "");
|
|
46230
46392
|
const axisInfo = this.resolveAxisByTableKey(tableKey);
|
|
46231
46393
|
values.forEach((value) => {
|
|
46232
|
-
const cloned = this.deepClone(value);
|
|
46394
|
+
const cloned = axisInfo ? this.prepareAxisRowForInsert(arr, axisInfo, value) : this.deepClone(value);
|
|
46233
46395
|
arr.push(cloned);
|
|
46234
46396
|
if (axisInfo) {
|
|
46235
46397
|
const index2 = arr.length - 1;
|
|
@@ -46290,10 +46452,12 @@ class DataManager {
|
|
|
46290
46452
|
throw new Error(`Index ${index2} out of bounds for array of length ${arr.length}`);
|
|
46291
46453
|
}
|
|
46292
46454
|
const oldValue = [...arr];
|
|
46293
|
-
const clonedValues = values.map((value) => this.deepClone(value));
|
|
46294
|
-
arr.splice(index2, 0, ...clonedValues);
|
|
46295
46455
|
const tableKey = path2.replace(/^\$\./, "").replace(/\[(n|\d+)\]/g, "");
|
|
46296
46456
|
const axisInfo = this.resolveAxisByTableKey(tableKey);
|
|
46457
|
+
const clonedValues = values.map(
|
|
46458
|
+
(value) => axisInfo ? this.prepareAxisRowForInsert(arr, axisInfo, value) : this.deepClone(value)
|
|
46459
|
+
);
|
|
46460
|
+
arr.splice(index2, 0, ...clonedValues);
|
|
46297
46461
|
if (axisInfo) {
|
|
46298
46462
|
for (let i = index2; i < arr.length; i++) {
|
|
46299
46463
|
this.ensureAxisRowAndUid(tableKey, i, axisInfo.axis);
|
|
@@ -46344,6 +46508,7 @@ class DataManager {
|
|
|
46344
46508
|
const data = this.deepClone(this.rawData);
|
|
46345
46509
|
for (let path2 of this.defaults.keys()) {
|
|
46346
46510
|
if (this.defaults.get(path2) === void 0) continue;
|
|
46511
|
+
if (path2.includes("[n")) continue;
|
|
46347
46512
|
const value = this.getByPath(data, path2);
|
|
46348
46513
|
if (value !== void 0) continue;
|
|
46349
46514
|
this.setByPath(data, path2, this.getDefault(path2));
|