docxmlater 10.0.4 → 10.1.1
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/core/Document.d.ts +22 -0
- package/dist/core/Document.d.ts.map +1 -1
- package/dist/core/Document.js +170 -26
- package/dist/core/Document.js.map +1 -1
- package/dist/core/DocumentParser.d.ts.map +1 -1
- package/dist/core/DocumentParser.js +71 -6
- package/dist/core/DocumentParser.js.map +1 -1
- package/dist/elements/Hyperlink.d.ts +6 -0
- package/dist/elements/Hyperlink.d.ts.map +1 -1
- package/dist/elements/Hyperlink.js +23 -0
- package/dist/elements/Hyperlink.js.map +1 -1
- package/dist/elements/StructuredDocumentTag.d.ts +23 -1
- package/dist/elements/StructuredDocumentTag.d.ts.map +1 -1
- package/dist/elements/StructuredDocumentTag.js +97 -0
- package/dist/elements/StructuredDocumentTag.js.map +1 -1
- package/dist/elements/TableCell.d.ts +5 -0
- package/dist/elements/TableCell.d.ts.map +1 -1
- package/dist/elements/TableCell.js +13 -0
- package/dist/elements/TableCell.js.map +1 -1
- package/dist/elements/TableRow.d.ts +3 -0
- package/dist/elements/TableRow.d.ts.map +1 -1
- package/dist/elements/TableRow.js +10 -0
- package/dist/elements/TableRow.js.map +1 -1
- package/dist/formatting/AbstractNumbering.d.ts +4 -0
- package/dist/formatting/AbstractNumbering.d.ts.map +1 -1
- package/dist/formatting/AbstractNumbering.js +15 -0
- package/dist/formatting/AbstractNumbering.js.map +1 -1
- package/dist/formatting/NumberingInstance.d.ts +6 -0
- package/dist/formatting/NumberingInstance.d.ts.map +1 -1
- package/dist/formatting/NumberingInstance.js +55 -1
- package/dist/formatting/NumberingInstance.js.map +1 -1
- package/dist/formatting/NumberingLevel.d.ts +4 -1
- package/dist/formatting/NumberingLevel.d.ts.map +1 -1
- package/dist/formatting/NumberingLevel.js +17 -0
- package/dist/formatting/NumberingLevel.js.map +1 -1
- package/dist/formatting/Style.d.ts +6 -0
- package/dist/formatting/Style.d.ts.map +1 -1
- package/dist/formatting/Style.js +20 -0
- package/dist/formatting/Style.js.map +1 -1
- package/dist/formatting/StylesManager.d.ts +23 -0
- package/dist/formatting/StylesManager.d.ts.map +1 -1
- package/dist/formatting/StylesManager.js +65 -0
- package/dist/formatting/StylesManager.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/tracking/DocumentTrackingContext.d.ts.map +1 -1
- package/dist/tracking/DocumentTrackingContext.js +30 -7
- package/dist/tracking/DocumentTrackingContext.js.map +1 -1
- package/package.json +1 -1
- package/src/core/Document.ts +287 -31
- package/src/core/DocumentParser.ts +88 -7
- package/src/elements/Hyperlink.ts +47 -0
- package/src/elements/StructuredDocumentTag.ts +230 -1
- package/src/elements/TableCell.ts +36 -1
- package/src/elements/TableRow.ts +24 -1
- package/src/formatting/AbstractNumbering.ts +31 -0
- package/src/formatting/NumberingInstance.ts +88 -1
- package/src/formatting/NumberingLevel.ts +37 -3
- package/src/formatting/Style.ts +46 -0
- package/src/formatting/StylesManager.ts +125 -0
- package/src/index.ts +2 -2
- package/src/tracking/DocumentTrackingContext.ts +38 -7
|
@@ -4352,6 +4352,7 @@ export class DocumentParser {
|
|
|
4352
4352
|
const tooltip = hyperlinkObj["@_w:tooltip"];
|
|
4353
4353
|
const tgtFrame = hyperlinkObj["@_w:tgtFrame"];
|
|
4354
4354
|
const history = hyperlinkObj["@_w:history"];
|
|
4355
|
+
const docLocation = hyperlinkObj["@_w:docLocation"];
|
|
4355
4356
|
|
|
4356
4357
|
// Parse runs inside the hyperlink
|
|
4357
4358
|
const runs = hyperlinkObj["w:r"];
|
|
@@ -4470,6 +4471,7 @@ export class DocumentParser {
|
|
|
4470
4471
|
relationshipId: finalRelationshipId,
|
|
4471
4472
|
tgtFrame,
|
|
4472
4473
|
history,
|
|
4474
|
+
docLocation,
|
|
4473
4475
|
});
|
|
4474
4476
|
|
|
4475
4477
|
// If we successfully parsed a run with tabs/breaks, use it instead of the default run
|
|
@@ -4772,6 +4774,9 @@ export class DocumentParser {
|
|
|
4772
4774
|
if (parseOoxmlBoolean(rPrObj["w:i"])) run.setItalic(true);
|
|
4773
4775
|
if (parseOoxmlBoolean(rPrObj["w:iCs"])) run.setComplexScriptItalic(true);
|
|
4774
4776
|
if (parseOoxmlBoolean(rPrObj["w:strike"])) run.setStrike(true);
|
|
4777
|
+
if (parseOoxmlBoolean(rPrObj["w:dstrike"])) {
|
|
4778
|
+
(run as any).formatting.dstrike = true;
|
|
4779
|
+
}
|
|
4775
4780
|
if (parseOoxmlBoolean(rPrObj["w:smallCaps"])) run.setSmallCaps(true);
|
|
4776
4781
|
if (parseOoxmlBoolean(rPrObj["w:caps"])) run.setAllCaps(true);
|
|
4777
4782
|
|
|
@@ -6094,14 +6099,14 @@ export class DocumentParser {
|
|
|
6094
6099
|
table.setBidiVisual(true);
|
|
6095
6100
|
}
|
|
6096
6101
|
|
|
6097
|
-
// Parse table width
|
|
6102
|
+
// Parse table width — always set when w:tblW is present, including w:w="0" w:type="auto"
|
|
6103
|
+
// (auto-sized tables). Skipping w:w="0" would leave the constructor default (9360/dxa),
|
|
6104
|
+
// causing tblPrChange snapshots to capture wrong "previous" width values.
|
|
6098
6105
|
if (tblPrObj["w:tblW"]) {
|
|
6099
|
-
const width =
|
|
6106
|
+
const width = safeParseInt(tblPrObj["w:tblW"]["@_w:w"], 0);
|
|
6100
6107
|
const widthType = tblPrObj["w:tblW"]["@_w:type"] || "dxa";
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
table.setWidthType(widthType);
|
|
6104
|
-
}
|
|
6108
|
+
table.setWidth(width);
|
|
6109
|
+
table.setWidthType(widthType);
|
|
6105
6110
|
}
|
|
6106
6111
|
|
|
6107
6112
|
// Parse table caption
|
|
@@ -6137,6 +6142,12 @@ export class DocumentParser {
|
|
|
6137
6142
|
}
|
|
6138
6143
|
}
|
|
6139
6144
|
|
|
6145
|
+
// Parse table indentation (w:tblInd) per ECMA-376 Part 1 §17.4.43
|
|
6146
|
+
if (tblPrObj["w:tblInd"]) {
|
|
6147
|
+
const indentVal = safeParseInt(tblPrObj["w:tblInd"]["@_w:w"], 0);
|
|
6148
|
+
table.setIndent(indentVal);
|
|
6149
|
+
}
|
|
6150
|
+
|
|
6140
6151
|
// Parse table cell margins (w:tblCellMar) per ECMA-376 Part 1 §17.4.42
|
|
6141
6152
|
if (tblPrObj["w:tblCellMar"]) {
|
|
6142
6153
|
const cellMar = tblPrObj["w:tblCellMar"];
|
|
@@ -6379,6 +6390,14 @@ export class DocumentParser {
|
|
|
6379
6390
|
}
|
|
6380
6391
|
}
|
|
6381
6392
|
|
|
6393
|
+
// Parse divId (w:divId) per ECMA-376 Part 1 §17.4.9
|
|
6394
|
+
if (trPrObj["w:divId"]) {
|
|
6395
|
+
const val = parseInt(trPrObj["w:divId"]["@_w:val"] || "0", 10);
|
|
6396
|
+
if (val > 0) {
|
|
6397
|
+
row.setDivId(val);
|
|
6398
|
+
}
|
|
6399
|
+
}
|
|
6400
|
+
|
|
6382
6401
|
// Parse table row property change (w:trPrChange) per ECMA-376 Part 1 §17.13.5.38
|
|
6383
6402
|
if (trPrObj["w:trPrChange"]) {
|
|
6384
6403
|
const changeObj = trPrObj["w:trPrChange"];
|
|
@@ -6531,6 +6550,10 @@ export class DocumentParser {
|
|
|
6531
6550
|
borders.left = this.parseBorderElement(bordersObj["w:left"]);
|
|
6532
6551
|
if (bordersObj["w:right"])
|
|
6533
6552
|
borders.right = this.parseBorderElement(bordersObj["w:right"]);
|
|
6553
|
+
if (bordersObj["w:tl2br"])
|
|
6554
|
+
borders.tl2br = this.parseBorderElement(bordersObj["w:tl2br"]);
|
|
6555
|
+
if (bordersObj["w:tr2bl"])
|
|
6556
|
+
borders.tr2bl = this.parseBorderElement(bordersObj["w:tr2bl"]);
|
|
6534
6557
|
|
|
6535
6558
|
if (Object.keys(borders).length > 0) {
|
|
6536
6559
|
cell.setBorders(borders);
|
|
@@ -6605,6 +6628,14 @@ export class DocumentParser {
|
|
|
6605
6628
|
cell.setHideMark(true);
|
|
6606
6629
|
}
|
|
6607
6630
|
|
|
6631
|
+
// Parse headers (w:headers) per ECMA-376 Part 1 §17.4.26
|
|
6632
|
+
if (tcPr["w:headers"]) {
|
|
6633
|
+
const headersVal = tcPr["w:headers"]["@_w:val"];
|
|
6634
|
+
if (headersVal) {
|
|
6635
|
+
cell.setHeaders(headersVal);
|
|
6636
|
+
}
|
|
6637
|
+
}
|
|
6638
|
+
|
|
6608
6639
|
// Parse fit text (w:tcFitText) per ECMA-376 Part 1 §17.4.68
|
|
6609
6640
|
if (tcPr["w:tcFitText"]) {
|
|
6610
6641
|
cell.setFitText(true);
|
|
@@ -7035,6 +7066,46 @@ export class DocumentParser {
|
|
|
7035
7066
|
};
|
|
7036
7067
|
} else if (sdtPr["w:group"]) {
|
|
7037
7068
|
properties.controlType = "group";
|
|
7069
|
+
} else if (sdtPr["w:citation"]) {
|
|
7070
|
+
properties.controlType = "citation";
|
|
7071
|
+
} else if (sdtPr["w:bibliography"]) {
|
|
7072
|
+
properties.controlType = "bibliography";
|
|
7073
|
+
} else if (sdtPr["w:equation"]) {
|
|
7074
|
+
properties.controlType = "equation";
|
|
7075
|
+
} else if (sdtPr["w:docPartList"]) {
|
|
7076
|
+
properties.controlType = "docPartList";
|
|
7077
|
+
const docPartList = sdtPr["w:docPartList"];
|
|
7078
|
+
properties.buildingBlock = {
|
|
7079
|
+
gallery: docPartList?.["w:docPartGallery"]?.["@_w:val"],
|
|
7080
|
+
category: docPartList?.["w:docPartCategory"]?.["@_w:val"],
|
|
7081
|
+
isList: true,
|
|
7082
|
+
};
|
|
7083
|
+
}
|
|
7084
|
+
|
|
7085
|
+
// Parse placeholder (w:placeholder/w:docPart)
|
|
7086
|
+
const placeholderElement = sdtPr["w:placeholder"];
|
|
7087
|
+
if (placeholderElement) {
|
|
7088
|
+
const docPartVal = placeholderElement?.["w:docPart"]?.["@_w:val"];
|
|
7089
|
+
if (docPartVal) {
|
|
7090
|
+
properties.placeholder = { docPart: docPartVal };
|
|
7091
|
+
}
|
|
7092
|
+
}
|
|
7093
|
+
|
|
7094
|
+
// Parse data binding (w:dataBinding)
|
|
7095
|
+
const dataBindingElement = sdtPr["w:dataBinding"];
|
|
7096
|
+
if (dataBindingElement) {
|
|
7097
|
+
properties.dataBinding = {
|
|
7098
|
+
xpath: dataBindingElement["@_w:xpath"] || "",
|
|
7099
|
+
prefixMappings: dataBindingElement["@_w:prefixMappings"],
|
|
7100
|
+
storeItemId: dataBindingElement["@_w:storeItemID"],
|
|
7101
|
+
};
|
|
7102
|
+
}
|
|
7103
|
+
|
|
7104
|
+
// Parse showing placeholder flag (w:showingPlcHdr)
|
|
7105
|
+
const showingPlcHdr = sdtPr["w:showingPlcHdr"];
|
|
7106
|
+
if (showingPlcHdr) {
|
|
7107
|
+
const val = showingPlcHdr["@_w:val"];
|
|
7108
|
+
properties.showingPlcHdr = val === "1" || val === "true" || val === true;
|
|
7038
7109
|
}
|
|
7039
7110
|
}
|
|
7040
7111
|
|
|
@@ -8602,6 +8673,14 @@ export class DocumentParser {
|
|
|
8602
8673
|
const personal =
|
|
8603
8674
|
styleXml.includes("<w:personal/>") || styleXml.includes("<w:personal ");
|
|
8604
8675
|
|
|
8676
|
+
// personalCompose - Style for composing new messages
|
|
8677
|
+
const personalCompose =
|
|
8678
|
+
styleXml.includes("<w:personalCompose/>") || styleXml.includes("<w:personalCompose ");
|
|
8679
|
+
|
|
8680
|
+
// personalReply - Style for replying to messages
|
|
8681
|
+
const personalReply =
|
|
8682
|
+
styleXml.includes("<w:personalReply/>") || styleXml.includes("<w:personalReply ");
|
|
8683
|
+
|
|
8605
8684
|
// autoRedefine - Update style from formatting
|
|
8606
8685
|
const autoRedefine =
|
|
8607
8686
|
styleXml.includes("<w:autoRedefine/>") ||
|
|
@@ -8673,6 +8752,8 @@ export class DocumentParser {
|
|
|
8673
8752
|
unhideWhenUsed: unhideWhenUsed || undefined,
|
|
8674
8753
|
locked: locked || undefined,
|
|
8675
8754
|
personal: personal || undefined,
|
|
8755
|
+
personalCompose: personalCompose || undefined,
|
|
8756
|
+
personalReply: personalReply || undefined,
|
|
8676
8757
|
autoRedefine: autoRedefine || undefined,
|
|
8677
8758
|
uiPriority,
|
|
8678
8759
|
link,
|
|
@@ -10046,7 +10127,7 @@ export class DocumentParser {
|
|
|
10046
10127
|
if (propsObj["w:tcBorders"]) {
|
|
10047
10128
|
const borders: any = {};
|
|
10048
10129
|
const bordersObj = propsObj["w:tcBorders"];
|
|
10049
|
-
for (const side of ['top', 'bottom', 'left', 'right']) {
|
|
10130
|
+
for (const side of ['top', 'bottom', 'left', 'right', 'tl2br', 'tr2bl']) {
|
|
10050
10131
|
if (bordersObj[`w:${side}`]) {
|
|
10051
10132
|
borders[side] = this.parseBorderElement(bordersObj[`w:${side}`]);
|
|
10052
10133
|
}
|
|
@@ -76,6 +76,8 @@ export interface HyperlinkProperties {
|
|
|
76
76
|
tgtFrame?: string;
|
|
77
77
|
/** History tracking attribute */
|
|
78
78
|
history?: string;
|
|
79
|
+
/** Document location for within-document navigation in external files (ECMA-376 §17.16.22) */
|
|
80
|
+
docLocation?: string;
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
/**
|
|
@@ -95,6 +97,8 @@ export class Hyperlink {
|
|
|
95
97
|
private tgtFrame?: string;
|
|
96
98
|
/** History tracking attribute */
|
|
97
99
|
private history?: string;
|
|
100
|
+
/** Document location for within-document navigation in external files */
|
|
101
|
+
private docLocation?: string;
|
|
98
102
|
/** Tracking context for automatic change tracking */
|
|
99
103
|
private trackingContext?: import('../tracking/TrackingContext').TrackingContext;
|
|
100
104
|
/** Parent paragraph reference for automatic tracking */
|
|
@@ -115,6 +119,7 @@ export class Hyperlink {
|
|
|
115
119
|
this.relationshipId = properties.relationshipId;
|
|
116
120
|
this.tgtFrame = properties.tgtFrame;
|
|
117
121
|
this.history = properties.history;
|
|
122
|
+
this.docLocation = properties.docLocation;
|
|
118
123
|
this._isEmpty = properties.isEmpty ?? false;
|
|
119
124
|
|
|
120
125
|
// VALIDATION: Warn about hybrid links (url + anchor)
|
|
@@ -263,6 +268,40 @@ export class Hyperlink {
|
|
|
263
268
|
return this.history;
|
|
264
269
|
}
|
|
265
270
|
|
|
271
|
+
/**
|
|
272
|
+
* Sets the target frame attribute
|
|
273
|
+
* @param tgtFrame Target frame (e.g., "_blank" for new window)
|
|
274
|
+
*/
|
|
275
|
+
setTgtFrame(tgtFrame: string | undefined): this {
|
|
276
|
+
this.tgtFrame = tgtFrame;
|
|
277
|
+
return this;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Sets the history tracking attribute
|
|
282
|
+
* @param history History value (e.g., "1" to add to history)
|
|
283
|
+
*/
|
|
284
|
+
setHistory(history: string | undefined): this {
|
|
285
|
+
this.history = history;
|
|
286
|
+
return this;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Gets the document location attribute (ECMA-376 §17.16.22)
|
|
291
|
+
*/
|
|
292
|
+
getDocLocation(): string | undefined {
|
|
293
|
+
return this.docLocation;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Sets the document location for within-document navigation in external files
|
|
298
|
+
* @param docLocation Location string
|
|
299
|
+
*/
|
|
300
|
+
setDocLocation(docLocation: string | undefined): this {
|
|
301
|
+
this.docLocation = docLocation;
|
|
302
|
+
return this;
|
|
303
|
+
}
|
|
304
|
+
|
|
266
305
|
/**
|
|
267
306
|
* Gets the display text
|
|
268
307
|
*
|
|
@@ -983,6 +1022,9 @@ export class Hyperlink {
|
|
|
983
1022
|
tooltip: this.tooltip,
|
|
984
1023
|
relationshipId: this.relationshipId,
|
|
985
1024
|
formatting: { ...this.formatting },
|
|
1025
|
+
tgtFrame: this.tgtFrame,
|
|
1026
|
+
history: this.history,
|
|
1027
|
+
docLocation: this.docLocation,
|
|
986
1028
|
});
|
|
987
1029
|
|
|
988
1030
|
// Copy the run with its formatting
|
|
@@ -1053,6 +1095,11 @@ export class Hyperlink {
|
|
|
1053
1095
|
attributes["w:history"] = this.history;
|
|
1054
1096
|
}
|
|
1055
1097
|
|
|
1098
|
+
// Document location attribute (ECMA-376 §17.16.22)
|
|
1099
|
+
if (this.docLocation) {
|
|
1100
|
+
attributes["w:docLocation"] = this.docLocation;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1056
1103
|
// Empty/invisible hyperlinks have no children (self-closing element)
|
|
1057
1104
|
if (this._isEmpty) {
|
|
1058
1105
|
return {
|
|
@@ -31,7 +31,11 @@ export type ContentControlType =
|
|
|
31
31
|
| "checkbox"
|
|
32
32
|
| "picture"
|
|
33
33
|
| "buildingBlock"
|
|
34
|
-
| "group"
|
|
34
|
+
| "group"
|
|
35
|
+
| "citation"
|
|
36
|
+
| "bibliography"
|
|
37
|
+
| "docPartList"
|
|
38
|
+
| "equation";
|
|
35
39
|
|
|
36
40
|
/**
|
|
37
41
|
* List item for combo box or dropdown
|
|
@@ -112,6 +116,28 @@ export interface BuildingBlockProperties {
|
|
|
112
116
|
gallery?: string;
|
|
113
117
|
/** Building block category */
|
|
114
118
|
category?: string;
|
|
119
|
+
/** Whether to use docPartList (true) or docPartObj (false, default) */
|
|
120
|
+
isList?: boolean;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Placeholder properties for SDT
|
|
125
|
+
*/
|
|
126
|
+
export interface SDTPlaceholder {
|
|
127
|
+
/** Name of the document part to use as placeholder */
|
|
128
|
+
docPart: string;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Data binding properties for SDT
|
|
133
|
+
*/
|
|
134
|
+
export interface SDTDataBinding {
|
|
135
|
+
/** XPath expression for the data binding */
|
|
136
|
+
xpath: string;
|
|
137
|
+
/** Namespace prefix mappings */
|
|
138
|
+
prefixMappings?: string;
|
|
139
|
+
/** Custom XML data store item ID */
|
|
140
|
+
storeItemId?: string;
|
|
115
141
|
}
|
|
116
142
|
|
|
117
143
|
/**
|
|
@@ -142,6 +168,12 @@ export interface SDTProperties {
|
|
|
142
168
|
checkbox?: CheckboxProperties;
|
|
143
169
|
/** Building block properties */
|
|
144
170
|
buildingBlock?: BuildingBlockProperties;
|
|
171
|
+
/** Placeholder (w:placeholder) */
|
|
172
|
+
placeholder?: SDTPlaceholder;
|
|
173
|
+
/** Data binding (w:dataBinding) */
|
|
174
|
+
dataBinding?: SDTDataBinding;
|
|
175
|
+
/** Whether SDT is currently showing placeholder content */
|
|
176
|
+
showingPlcHdr?: boolean;
|
|
145
177
|
}
|
|
146
178
|
|
|
147
179
|
/**
|
|
@@ -490,6 +522,38 @@ export class StructuredDocumentTag {
|
|
|
490
522
|
);
|
|
491
523
|
}
|
|
492
524
|
|
|
525
|
+
// Add placeholder
|
|
526
|
+
if (this.properties.placeholder) {
|
|
527
|
+
sdtPrChildren.push(
|
|
528
|
+
XMLBuilder.w("placeholder", {}, [
|
|
529
|
+
XMLBuilder.wSelf("docPart", { "w:val": this.properties.placeholder.docPart }),
|
|
530
|
+
])
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// Add showing placeholder flag
|
|
535
|
+
if (this.properties.showingPlcHdr !== undefined) {
|
|
536
|
+
sdtPrChildren.push(
|
|
537
|
+
XMLBuilder.wSelf("showingPlcHdr", {
|
|
538
|
+
"w:val": this.properties.showingPlcHdr ? "true" : "false",
|
|
539
|
+
})
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// Add data binding
|
|
544
|
+
if (this.properties.dataBinding) {
|
|
545
|
+
const dbAttrs: Record<string, string> = {
|
|
546
|
+
"w:xpath": this.properties.dataBinding.xpath,
|
|
547
|
+
};
|
|
548
|
+
if (this.properties.dataBinding.prefixMappings) {
|
|
549
|
+
dbAttrs["w:prefixMappings"] = this.properties.dataBinding.prefixMappings;
|
|
550
|
+
}
|
|
551
|
+
if (this.properties.dataBinding.storeItemId) {
|
|
552
|
+
dbAttrs["w:storeItemID"] = this.properties.dataBinding.storeItemId;
|
|
553
|
+
}
|
|
554
|
+
sdtPrChildren.push(XMLBuilder.wSelf("dataBinding", dbAttrs));
|
|
555
|
+
}
|
|
556
|
+
|
|
493
557
|
// Add control type-specific XML
|
|
494
558
|
if (this.properties.controlType) {
|
|
495
559
|
switch (this.properties.controlType) {
|
|
@@ -643,6 +707,39 @@ export class StructuredDocumentTag {
|
|
|
643
707
|
case "group":
|
|
644
708
|
sdtPrChildren.push(XMLBuilder.wSelf("group", {}));
|
|
645
709
|
break;
|
|
710
|
+
|
|
711
|
+
case "citation":
|
|
712
|
+
sdtPrChildren.push(XMLBuilder.wSelf("citation", {}));
|
|
713
|
+
break;
|
|
714
|
+
|
|
715
|
+
case "bibliography":
|
|
716
|
+
sdtPrChildren.push(XMLBuilder.wSelf("bibliography", {}));
|
|
717
|
+
break;
|
|
718
|
+
|
|
719
|
+
case "equation":
|
|
720
|
+
sdtPrChildren.push(XMLBuilder.wSelf("equation", {}));
|
|
721
|
+
break;
|
|
722
|
+
|
|
723
|
+
case "docPartList":
|
|
724
|
+
if (this.properties.buildingBlock) {
|
|
725
|
+
const dplChildren: XMLElement[] = [];
|
|
726
|
+
if (this.properties.buildingBlock.gallery) {
|
|
727
|
+
dplChildren.push(
|
|
728
|
+
XMLBuilder.wSelf("docPartGallery", {
|
|
729
|
+
"w:val": this.properties.buildingBlock.gallery,
|
|
730
|
+
})
|
|
731
|
+
);
|
|
732
|
+
}
|
|
733
|
+
if (this.properties.buildingBlock.category) {
|
|
734
|
+
dplChildren.push(
|
|
735
|
+
XMLBuilder.wSelf("docPartCategory", {
|
|
736
|
+
"w:val": this.properties.buildingBlock.category,
|
|
737
|
+
})
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
sdtPrChildren.push(XMLBuilder.w("docPartList", {}, dplChildren));
|
|
741
|
+
}
|
|
742
|
+
break;
|
|
646
743
|
}
|
|
647
744
|
}
|
|
648
745
|
|
|
@@ -975,4 +1072,136 @@ export class StructuredDocumentTag {
|
|
|
975
1072
|
const lock = this.properties.lock;
|
|
976
1073
|
return lock !== "contentLocked" && lock !== "sdtContentLocked";
|
|
977
1074
|
}
|
|
1075
|
+
|
|
1076
|
+
/**
|
|
1077
|
+
* Get the placeholder configuration
|
|
1078
|
+
*/
|
|
1079
|
+
getPlaceholder(): SDTPlaceholder | undefined {
|
|
1080
|
+
return this.properties.placeholder;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
/**
|
|
1084
|
+
* Set the placeholder (w:placeholder/w:docPart)
|
|
1085
|
+
* @param docPart - Name of the document part to use as placeholder
|
|
1086
|
+
*/
|
|
1087
|
+
setPlaceholder(docPart: string): this {
|
|
1088
|
+
this.properties.placeholder = { docPart };
|
|
1089
|
+
return this;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
/**
|
|
1093
|
+
* Get the data binding configuration
|
|
1094
|
+
*/
|
|
1095
|
+
getDataBinding(): SDTDataBinding | undefined {
|
|
1096
|
+
return this.properties.dataBinding;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
/**
|
|
1100
|
+
* Set the data binding (w:dataBinding)
|
|
1101
|
+
* @param xpath - XPath expression
|
|
1102
|
+
* @param prefixMappings - Namespace prefix mappings
|
|
1103
|
+
* @param storeItemId - Custom XML data store item ID
|
|
1104
|
+
*/
|
|
1105
|
+
setDataBinding(xpath: string, prefixMappings?: string, storeItemId?: string): this {
|
|
1106
|
+
this.properties.dataBinding = { xpath, prefixMappings, storeItemId };
|
|
1107
|
+
return this;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
/**
|
|
1111
|
+
* Get whether the SDT is currently showing placeholder content
|
|
1112
|
+
*/
|
|
1113
|
+
isShowingPlaceholder(): boolean {
|
|
1114
|
+
return this.properties.showingPlcHdr === true;
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
/**
|
|
1118
|
+
* Set whether the SDT is showing placeholder content
|
|
1119
|
+
* @param val - Whether placeholder is showing
|
|
1120
|
+
*/
|
|
1121
|
+
setShowingPlaceholder(val: boolean): this {
|
|
1122
|
+
this.properties.showingPlcHdr = val;
|
|
1123
|
+
return this;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
/**
|
|
1127
|
+
* Create a citation content control
|
|
1128
|
+
* @param content - Initial content
|
|
1129
|
+
* @param properties - Additional SDT properties
|
|
1130
|
+
*/
|
|
1131
|
+
static createCitation(
|
|
1132
|
+
content: SDTContent[] = [],
|
|
1133
|
+
properties: Partial<SDTProperties> = {}
|
|
1134
|
+
): StructuredDocumentTag {
|
|
1135
|
+
return new StructuredDocumentTag(
|
|
1136
|
+
{
|
|
1137
|
+
id: Date.now() % 1000000000,
|
|
1138
|
+
controlType: "citation",
|
|
1139
|
+
...properties,
|
|
1140
|
+
},
|
|
1141
|
+
content
|
|
1142
|
+
);
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
/**
|
|
1146
|
+
* Create a bibliography content control
|
|
1147
|
+
* @param content - Initial content
|
|
1148
|
+
* @param properties - Additional SDT properties
|
|
1149
|
+
*/
|
|
1150
|
+
static createBibliography(
|
|
1151
|
+
content: SDTContent[] = [],
|
|
1152
|
+
properties: Partial<SDTProperties> = {}
|
|
1153
|
+
): StructuredDocumentTag {
|
|
1154
|
+
return new StructuredDocumentTag(
|
|
1155
|
+
{
|
|
1156
|
+
id: Date.now() % 1000000000,
|
|
1157
|
+
controlType: "bibliography",
|
|
1158
|
+
...properties,
|
|
1159
|
+
},
|
|
1160
|
+
content
|
|
1161
|
+
);
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
/**
|
|
1165
|
+
* Create a document part list content control
|
|
1166
|
+
* Uses w:docPartList instead of w:docPartObj
|
|
1167
|
+
* @param gallery - Building block gallery name
|
|
1168
|
+
* @param category - Building block category
|
|
1169
|
+
* @param content - Initial content
|
|
1170
|
+
* @param properties - Additional SDT properties
|
|
1171
|
+
*/
|
|
1172
|
+
static createDocPartList(
|
|
1173
|
+
gallery: string,
|
|
1174
|
+
category: string,
|
|
1175
|
+
content: SDTContent[] = [],
|
|
1176
|
+
properties: Partial<SDTProperties> = {}
|
|
1177
|
+
): StructuredDocumentTag {
|
|
1178
|
+
return new StructuredDocumentTag(
|
|
1179
|
+
{
|
|
1180
|
+
id: Date.now() % 1000000000,
|
|
1181
|
+
controlType: "docPartList",
|
|
1182
|
+
buildingBlock: { gallery, category, isList: true },
|
|
1183
|
+
...properties,
|
|
1184
|
+
},
|
|
1185
|
+
content
|
|
1186
|
+
);
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
/**
|
|
1190
|
+
* Create an equation content control
|
|
1191
|
+
* @param content - Initial content
|
|
1192
|
+
* @param properties - Additional SDT properties
|
|
1193
|
+
*/
|
|
1194
|
+
static createEquation(
|
|
1195
|
+
content: SDTContent[] = [],
|
|
1196
|
+
properties: Partial<SDTProperties> = {}
|
|
1197
|
+
): StructuredDocumentTag {
|
|
1198
|
+
return new StructuredDocumentTag(
|
|
1199
|
+
{
|
|
1200
|
+
id: Date.now() % 1000000000,
|
|
1201
|
+
controlType: "equation",
|
|
1202
|
+
...properties,
|
|
1203
|
+
},
|
|
1204
|
+
content
|
|
1205
|
+
);
|
|
1206
|
+
}
|
|
978
1207
|
}
|
|
@@ -46,6 +46,10 @@ export interface CellBorders {
|
|
|
46
46
|
bottom?: CellBorder;
|
|
47
47
|
left?: CellBorder;
|
|
48
48
|
right?: CellBorder;
|
|
49
|
+
/** Diagonal border from top-left to bottom-right per ECMA-376 Part 1 §17.4.84 */
|
|
50
|
+
tl2br?: CellBorder;
|
|
51
|
+
/** Diagonal border from top-right to bottom-left per ECMA-376 Part 1 §17.4.85 */
|
|
52
|
+
tr2bl?: CellBorder;
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
/**
|
|
@@ -102,6 +106,8 @@ export interface CellFormatting {
|
|
|
102
106
|
cnfStyle?: string; // Conditional formatting style (14-char binary string)
|
|
103
107
|
vMerge?: VerticalMerge; // Vertical cell merge
|
|
104
108
|
hMerge?: 'restart' | 'continue'; // Legacy horizontal merge (w:hMerge) per ECMA-376 Part 1 §17.4.22
|
|
109
|
+
/** Cell headers attribute for accessibility per ECMA-376 Part 1 §17.4.26 */
|
|
110
|
+
headers?: string;
|
|
105
111
|
}
|
|
106
112
|
|
|
107
113
|
/**
|
|
@@ -947,6 +953,25 @@ export class TableCell {
|
|
|
947
953
|
return this.formatting.hMerge;
|
|
948
954
|
}
|
|
949
955
|
|
|
956
|
+
/**
|
|
957
|
+
* Sets the cell headers attribute for accessibility
|
|
958
|
+
* Links data cells to header cells per ECMA-376 Part 1 §17.4.26
|
|
959
|
+
* @param headers - Space-separated list of header cell IDs
|
|
960
|
+
* @returns This cell for chaining
|
|
961
|
+
*/
|
|
962
|
+
setHeaders(headers: string): this {
|
|
963
|
+
this.formatting.headers = headers;
|
|
964
|
+
return this;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
/**
|
|
968
|
+
* Gets the cell headers attribute
|
|
969
|
+
* @returns Headers string or undefined
|
|
970
|
+
*/
|
|
971
|
+
getHeaders(): string | undefined {
|
|
972
|
+
return this.formatting.headers;
|
|
973
|
+
}
|
|
974
|
+
|
|
950
975
|
/**
|
|
951
976
|
* Gets the cell margins
|
|
952
977
|
* @returns Margins object with top, right, bottom, left or undefined
|
|
@@ -1306,7 +1331,7 @@ export class TableCell {
|
|
|
1306
1331
|
const borderElements: XMLElement[] = [];
|
|
1307
1332
|
const borders = this.formatting.borders;
|
|
1308
1333
|
|
|
1309
|
-
// Ordered per ECMA-376 CT_TcBorders: top, left, bottom, right
|
|
1334
|
+
// Ordered per ECMA-376 CT_TcBorders: top, left, bottom, right, insideH, insideV, tl2br, tr2bl
|
|
1310
1335
|
if (borders.top) {
|
|
1311
1336
|
borderElements.push(XMLBuilder.createBorder("top", borders.top));
|
|
1312
1337
|
}
|
|
@@ -1319,6 +1344,12 @@ export class TableCell {
|
|
|
1319
1344
|
if (borders.right) {
|
|
1320
1345
|
borderElements.push(XMLBuilder.createBorder("right", borders.right));
|
|
1321
1346
|
}
|
|
1347
|
+
if (borders.tl2br) {
|
|
1348
|
+
borderElements.push(XMLBuilder.createBorder("tl2br", borders.tl2br));
|
|
1349
|
+
}
|
|
1350
|
+
if (borders.tr2bl) {
|
|
1351
|
+
borderElements.push(XMLBuilder.createBorder("tr2bl", borders.tr2bl));
|
|
1352
|
+
}
|
|
1322
1353
|
|
|
1323
1354
|
if (borderElements.length > 0) {
|
|
1324
1355
|
tcPrChildren.push(XMLBuilder.w("tcBorders", undefined, borderElements));
|
|
@@ -1409,6 +1440,10 @@ export class TableCell {
|
|
|
1409
1440
|
tcPrChildren.push(XMLBuilder.wSelf("hideMark"));
|
|
1410
1441
|
}
|
|
1411
1442
|
|
|
1443
|
+
// Note: w:headers (cell headers for accessibility) is defined in ECMA-376 Part 1 §17.4.26
|
|
1444
|
+
// but is NOT included in the Transitional schema and fails OOXML validation.
|
|
1445
|
+
// The property is preserved in memory for reading but not generated in XML.
|
|
1446
|
+
|
|
1412
1447
|
// Add cell revision markers (w:cellIns, w:cellDel, w:cellMerge) per ECMA-376 Part 1 §17.13.5.4-5.6
|
|
1413
1448
|
if (this.cellRevision) {
|
|
1414
1449
|
const revType = this.cellRevision.getType();
|
package/src/elements/TableRow.ts
CHANGED
|
@@ -74,6 +74,7 @@ export interface RowFormatting {
|
|
|
74
74
|
cellSpacing?: number; // Row-level cell spacing override in twips
|
|
75
75
|
cellSpacingType?: string; // Cell spacing type (dxa, pct)
|
|
76
76
|
cnfStyle?: string; // Conditional formatting bitmask (per ECMA-376 §17.3.1.8)
|
|
77
|
+
divId?: number; // HTML div association (per ECMA-376 §17.4.9)
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
/**
|
|
@@ -544,6 +545,25 @@ export class TableRow {
|
|
|
544
545
|
return this;
|
|
545
546
|
}
|
|
546
547
|
|
|
548
|
+
/**
|
|
549
|
+
* Sets the HTML div ID for web round-trip
|
|
550
|
+
* Per ECMA-376 Part 1 §17.4.9
|
|
551
|
+
* @param id - Div ID number
|
|
552
|
+
* @returns This row for chaining
|
|
553
|
+
*/
|
|
554
|
+
setDivId(id: number): this {
|
|
555
|
+
this.formatting.divId = id;
|
|
556
|
+
return this;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Gets the HTML div ID
|
|
561
|
+
* @returns Div ID or undefined
|
|
562
|
+
*/
|
|
563
|
+
getDivId(): number | undefined {
|
|
564
|
+
return this.formatting.divId;
|
|
565
|
+
}
|
|
566
|
+
|
|
547
567
|
/**
|
|
548
568
|
* Gets table property exceptions
|
|
549
569
|
* @returns Table property exceptions or undefined
|
|
@@ -735,7 +755,10 @@ export class TableRow {
|
|
|
735
755
|
trPrChildren.push(XMLBuilder.wSelf('cnfStyle', { 'w:val': this.formatting.cnfStyle }));
|
|
736
756
|
}
|
|
737
757
|
|
|
738
|
-
// 2.
|
|
758
|
+
// 2. divId
|
|
759
|
+
if (this.formatting.divId !== undefined) {
|
|
760
|
+
trPrChildren.push(XMLBuilder.wSelf('divId', { 'w:val': this.formatting.divId }));
|
|
761
|
+
}
|
|
739
762
|
|
|
740
763
|
// 3. gridBefore
|
|
741
764
|
if (this.formatting.gridBefore !== undefined) {
|