@stll/folio-core 0.15.1 → 0.15.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/dist/docx/commentParser.js +30 -2
- package/dist/docx/drawingIdNormalization.d.ts +5 -0
- package/dist/docx/drawingIdNormalization.js +35 -0
- package/dist/docx/drawingUtils.d.ts +1 -1
- package/dist/docx/drawingUtils.js +111 -27
- package/dist/docx/headerFooterVerbatim.d.ts +2 -1
- package/dist/docx/headerFooterVerbatim.js +6 -1
- package/dist/docx/paragraphParser.js +5 -2
- package/dist/docx/paragraphTraversal.d.ts +5 -3
- package/dist/docx/paragraphTraversal.js +20 -13
- package/dist/docx/parser.js +11 -1
- package/dist/docx/parserEnums.d.ts +4 -1
- package/dist/docx/parserEnums.js +5 -2
- package/dist/docx/runConsolidator.js +0 -1
- package/dist/docx/runParser.js +17 -1
- package/dist/docx/serializer/commentSerializer.js +12 -7
- package/dist/docx/serializer/runSerializer.js +16 -10
- package/dist/docx/serializer/sectionPropertiesSerializer.js +3 -2
- package/dist/docx/shapeParser.js +5 -113
- package/dist/docx/tableParser.js +8 -6
- package/dist/docx/textBoxParser.js +1 -1
- package/dist/model.d.ts +3 -3
- package/dist/model.js +2 -2
- package/dist/prosemirror/attrs/index.d.ts +4 -2
- package/dist/prosemirror/attrs/index.js +17 -2
- package/dist/prosemirror/conversion/fromProseDoc.js +10 -6
- package/dist/prosemirror/conversion/toProseDoc.js +1 -1
- package/dist/prosemirror/extensions/nodes/TabExtension.js +32 -9
- package/dist/prosemirror/schema/index.d.ts +2 -2
- package/dist/prosemirror/schema/nodes.d.ts +4 -1
- package/dist/prosemirror/validation.js +5 -3
- package/dist/types/content.d.ts +2 -2
- package/dist/types/documentEnumValues.d.ts +4 -1
- package/dist/types/documentEnumValues.js +14 -1
- package/dist/types/index.d.ts +2 -1
- package/package.json +2 -2
|
@@ -1,6 +1,26 @@
|
|
|
1
|
-
import { findChild, getAttribute, getChildElements, parseXml } from "./xmlParser.js";
|
|
1
|
+
import { findChild, getAttribute, getChildElements, getLocalName, parseXml } from "./xmlParser.js";
|
|
2
|
+
import { parseRunProperties } from "./runParser.js";
|
|
2
3
|
import { parseParagraph } from "./paragraphParser.js";
|
|
3
4
|
//#region src/docx/commentParser.ts
|
|
5
|
+
const DEFAULT_ANNOTATION_REFERENCE_STYLE_ID = "CommentReference";
|
|
6
|
+
const normalizeAnnotationReferenceFormatting = (formatting) => {
|
|
7
|
+
if (formatting?.styleId === DEFAULT_ANNOTATION_REFERENCE_STYLE_ID && Object.keys(formatting).length === 1) return;
|
|
8
|
+
return formatting;
|
|
9
|
+
};
|
|
10
|
+
const normalizeFirstCommentParagraph = (paragraphElement, paragraph, theme) => {
|
|
11
|
+
const firstContentElement = getChildElements(paragraphElement).find((element) => getLocalName(element.name) !== "pPr");
|
|
12
|
+
if (!firstContentElement || getLocalName(firstContentElement.name) !== "r" || !findChild(firstContentElement, "w", "annotationRef")) return { paragraph };
|
|
13
|
+
const runProperties = findChild(firstContentElement, "w", "rPr");
|
|
14
|
+
const annotationReferenceFormatting = normalizeAnnotationReferenceFormatting(runProperties ? parseRunProperties(runProperties, theme) : void 0);
|
|
15
|
+
const firstParsedContent = paragraph.content.at(0);
|
|
16
|
+
return {
|
|
17
|
+
paragraph: firstParsedContent?.type === "run" && firstParsedContent.content.length === 0 ? {
|
|
18
|
+
...paragraph,
|
|
19
|
+
content: paragraph.content.slice(1)
|
|
20
|
+
} : paragraph,
|
|
21
|
+
...annotationReferenceFormatting !== void 0 ? { annotationReferenceFormatting } : {}
|
|
22
|
+
};
|
|
23
|
+
};
|
|
4
24
|
/**
|
|
5
25
|
* Build a lookup from paraId → dateUtc from commentsExtensible.xml
|
|
6
26
|
*
|
|
@@ -91,9 +111,16 @@ function parseComments(commentsXml, styles, theme, rels, media, commentsExtensib
|
|
|
91
111
|
const date = (paraId ? dateUtcByParaId.get(paraId) : void 0) ?? localDate;
|
|
92
112
|
const done = (paraId ? extendedByParaId.get(paraId) : void 0)?.done;
|
|
93
113
|
const paragraphs = [];
|
|
114
|
+
let annotationReferenceFormatting;
|
|
94
115
|
for (const contentChild of getChildElements(child)) if ((contentChild.name?.replace(/^.*:/u, "") ?? "") === "p") {
|
|
95
116
|
const paragraph = parseParagraph(contentChild, styles, theme, null, rels, media);
|
|
96
|
-
paragraphs.
|
|
117
|
+
if (paragraphs.length > 0) {
|
|
118
|
+
paragraphs.push(paragraph);
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const normalized = normalizeFirstCommentParagraph(contentChild, paragraph, theme);
|
|
122
|
+
annotationReferenceFormatting = normalized.annotationReferenceFormatting;
|
|
123
|
+
paragraphs.push(normalized.paragraph);
|
|
97
124
|
}
|
|
98
125
|
const commentIndex = comments.length;
|
|
99
126
|
if (paraId) {
|
|
@@ -106,6 +133,7 @@ function parseComments(commentsXml, styles, theme, rels, media, commentsExtensib
|
|
|
106
133
|
...initials !== void 0 ? { initials } : {},
|
|
107
134
|
...date !== void 0 ? { date } : {},
|
|
108
135
|
...done !== void 0 ? { done } : {},
|
|
136
|
+
...annotationReferenceFormatting !== void 0 ? { annotationReferenceFormatting } : {},
|
|
109
137
|
content: paragraphs
|
|
110
138
|
});
|
|
111
139
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { visitDocxParagraphs, visitParagraphRuns } from "./paragraphTraversal.js";
|
|
2
|
+
//#region src/docx/drawingIdNormalization.ts
|
|
3
|
+
const GENERATED_DRAWING_ID_START = 1e5;
|
|
4
|
+
const needsGeneratedId = ({ id }) => id === void 0 || id === "" || id === "0";
|
|
5
|
+
const normalizeDrawingIds = (surfaces) => {
|
|
6
|
+
const entries = [];
|
|
7
|
+
visitDocxParagraphs(surfaces, (paragraph) => {
|
|
8
|
+
visitParagraphRuns(paragraph, (run) => {
|
|
9
|
+
for (const content of run.content) {
|
|
10
|
+
if (content.type === "shape") {
|
|
11
|
+
entries.push({
|
|
12
|
+
drawing: content.shape,
|
|
13
|
+
generateWhenMissing: true
|
|
14
|
+
});
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (content.type === "drawing") entries.push({
|
|
18
|
+
drawing: content.image,
|
|
19
|
+
generateWhenMissing: content.rawXml === void 0
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
const usedIds = new Set(entries.flatMap(({ drawing }) => needsGeneratedId(drawing) ? [] : [drawing.id]));
|
|
25
|
+
let nextId = GENERATED_DRAWING_ID_START;
|
|
26
|
+
for (const { drawing, generateWhenMissing } of entries) {
|
|
27
|
+
if (!generateWhenMissing || !needsGeneratedId(drawing)) continue;
|
|
28
|
+
while (usedIds.has(String(nextId))) nextId += 1;
|
|
29
|
+
drawing.id = String(nextId);
|
|
30
|
+
usedIds.add(drawing.id);
|
|
31
|
+
nextId += 1;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
//#endregion
|
|
35
|
+
export { normalizeDrawingIds };
|
|
@@ -48,7 +48,7 @@ declare function parsePositionV(posV: XmlElement | null): document_d_exports.Ima
|
|
|
48
48
|
/**
|
|
49
49
|
* Parse position for anchored drawings (combines positionH + positionV).
|
|
50
50
|
*/
|
|
51
|
-
declare function parseAnchorPosition(anchor: XmlElement): document_d_exports.ImagePosition
|
|
51
|
+
declare function parseAnchorPosition(anchor: XmlElement): document_d_exports.ImagePosition;
|
|
52
52
|
/** Known wrap element names */
|
|
53
53
|
declare const WRAP_ELEMENT_NAMES: string[];
|
|
54
54
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ImageHorizontalAlignmentSchema, ImageHorizontalRelativeToSchema, ImageVerticalAlignmentSchema, ImageVerticalRelativeToSchema, ImageWrapTextSchema, ShapeOutlineStyleSchema, narrowEnum } from "./parserEnums.js";
|
|
2
|
-
import { findByFullName, getAttribute, getChildElements, getTextContent, parseNumericAttribute } from "./xmlParser.js";
|
|
2
|
+
import { elementToXml, findByFullName, findChildByLocalName, findChildrenByLocalName, getAttribute, getChildElements, getTextContent, parseNumericAttribute } from "./xmlParser.js";
|
|
3
3
|
//#region src/docx/drawingUtils.ts
|
|
4
4
|
/**
|
|
5
5
|
* Map OOXML scheme names to standard theme color slots.
|
|
@@ -119,9 +119,8 @@ function parseColorElement(element) {
|
|
|
119
119
|
*/
|
|
120
120
|
function parseFill(spPr) {
|
|
121
121
|
if (!spPr) return;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const solidFill = children.find((el) => el.name === "a:solidFill");
|
|
122
|
+
if (findChildByLocalName(spPr, "noFill")) return { type: "none" };
|
|
123
|
+
const solidFill = findChildByLocalName(spPr, "solidFill");
|
|
125
124
|
if (solidFill) {
|
|
126
125
|
const color = parseColorElement(solidFill);
|
|
127
126
|
return color !== void 0 ? {
|
|
@@ -129,31 +128,105 @@ function parseFill(spPr) {
|
|
|
129
128
|
color
|
|
130
129
|
} : { type: "solid" };
|
|
131
130
|
}
|
|
132
|
-
|
|
131
|
+
const gradientFill = findChildByLocalName(spPr, "gradFill");
|
|
132
|
+
if (gradientFill) return parseGradientFill(gradientFill);
|
|
133
|
+
}
|
|
134
|
+
function parseGradientFill(gradientFill) {
|
|
135
|
+
let type = "linear";
|
|
136
|
+
let angle;
|
|
137
|
+
const linear = findChildByLocalName(gradientFill, "lin");
|
|
138
|
+
if (linear) {
|
|
139
|
+
const authoredAngle = getAttribute(linear, null, "ang");
|
|
140
|
+
if (authoredAngle) {
|
|
141
|
+
const parsedAngle = Number.parseInt(authoredAngle, 10);
|
|
142
|
+
angle = Number.isNaN(parsedAngle) ? void 0 : parsedAngle / 6e4;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const path = findChildByLocalName(gradientFill, "path");
|
|
146
|
+
if (path) {
|
|
147
|
+
const pathType = getAttribute(path, null, "path");
|
|
148
|
+
if (pathType === "circle") type = "radial";
|
|
149
|
+
else if (pathType === "rect") type = "rectangular";
|
|
150
|
+
else type = "path";
|
|
151
|
+
}
|
|
152
|
+
const stops = [];
|
|
153
|
+
const stopList = findChildByLocalName(gradientFill, "gsLst");
|
|
154
|
+
if (stopList) for (const stop of findChildrenByLocalName(stopList, "gs")) {
|
|
155
|
+
const authoredPosition = getAttribute(stop, null, "pos");
|
|
156
|
+
const parsedPosition = authoredPosition ? Number.parseInt(authoredPosition, 10) : 0;
|
|
157
|
+
const color = parseColorElement(stop);
|
|
158
|
+
if (color) stops.push({
|
|
159
|
+
position: Number.isNaN(parsedPosition) ? 0 : parsedPosition,
|
|
160
|
+
color
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
type: "gradient",
|
|
165
|
+
rawXml: elementToXml(gradientFill),
|
|
166
|
+
gradient: {
|
|
167
|
+
type,
|
|
168
|
+
...angle !== void 0 ? { angle } : {},
|
|
169
|
+
stops
|
|
170
|
+
}
|
|
171
|
+
};
|
|
133
172
|
}
|
|
134
173
|
/**
|
|
135
174
|
* Parse outline from shape properties (a:ln).
|
|
136
175
|
*/
|
|
137
176
|
function parseOutline(spPr) {
|
|
138
|
-
const ln = spPr ?
|
|
177
|
+
const ln = spPr ? findChildByLocalName(spPr, "ln") : null;
|
|
139
178
|
if (!ln) return;
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const outline = {};
|
|
179
|
+
if (findChildByLocalName(ln, "noFill")) return;
|
|
180
|
+
const outline = { rawXml: elementToXml(ln) };
|
|
143
181
|
const w = getAttribute(ln, null, "w");
|
|
144
|
-
if (w)
|
|
145
|
-
|
|
182
|
+
if (w) {
|
|
183
|
+
const parsed = Number.parseInt(w, 10);
|
|
184
|
+
if (!Number.isNaN(parsed)) outline.width = parsed;
|
|
185
|
+
}
|
|
186
|
+
const cap = getAttribute(ln, null, "cap");
|
|
187
|
+
if (cap === "flat") outline.cap = "flat";
|
|
188
|
+
else if (cap === "rnd") outline.cap = "round";
|
|
189
|
+
else if (cap === "sq") outline.cap = "square";
|
|
190
|
+
if (findChildByLocalName(ln, "bevel")) outline.join = "bevel";
|
|
191
|
+
else if (findChildByLocalName(ln, "round")) outline.join = "round";
|
|
192
|
+
else if (findChildByLocalName(ln, "miter")) outline.join = "miter";
|
|
193
|
+
const solidFill = findChildByLocalName(ln, "solidFill");
|
|
146
194
|
if (solidFill) {
|
|
147
195
|
const color = parseColorElement(solidFill);
|
|
148
196
|
if (color !== void 0) outline.color = color;
|
|
149
197
|
}
|
|
150
|
-
const prstDash =
|
|
198
|
+
const prstDash = findChildByLocalName(ln, "prstDash");
|
|
151
199
|
if (prstDash) {
|
|
152
200
|
const val = narrowEnum(getAttribute(prstDash, null, "val"), ShapeOutlineStyleSchema);
|
|
153
201
|
if (val) outline.style = val;
|
|
154
202
|
}
|
|
203
|
+
const headEnd = findChildByLocalName(ln, "headEnd");
|
|
204
|
+
if (headEnd) outline.headEnd = parseLineEnd(headEnd);
|
|
205
|
+
const tailEnd = findChildByLocalName(ln, "tailEnd");
|
|
206
|
+
if (tailEnd) outline.tailEnd = parseLineEnd(tailEnd);
|
|
155
207
|
return outline;
|
|
156
208
|
}
|
|
209
|
+
const LINE_END_TYPES = [
|
|
210
|
+
"none",
|
|
211
|
+
"triangle",
|
|
212
|
+
"stealth",
|
|
213
|
+
"diamond",
|
|
214
|
+
"oval",
|
|
215
|
+
"arrow"
|
|
216
|
+
];
|
|
217
|
+
function parseLineEnd(element) {
|
|
218
|
+
const authoredType = getAttribute(element, null, "type");
|
|
219
|
+
const type = LINE_END_TYPES.find((allowed) => allowed === authoredType) ?? "none";
|
|
220
|
+
const authoredWidth = getAttribute(element, null, "w");
|
|
221
|
+
const authoredLength = getAttribute(element, null, "len");
|
|
222
|
+
const width = authoredWidth === "sm" || authoredWidth === "med" || authoredWidth === "lg" ? authoredWidth : void 0;
|
|
223
|
+
const length = authoredLength === "sm" || authoredLength === "med" || authoredLength === "lg" ? authoredLength : void 0;
|
|
224
|
+
return {
|
|
225
|
+
type,
|
|
226
|
+
...width !== void 0 ? { width } : {},
|
|
227
|
+
...length !== void 0 ? { length } : {}
|
|
228
|
+
};
|
|
229
|
+
}
|
|
157
230
|
/**
|
|
158
231
|
* Parse horizontal position from wp:positionH element.
|
|
159
232
|
*/
|
|
@@ -162,11 +235,11 @@ function parsePositionH(posH) {
|
|
|
162
235
|
const relativeTo = narrowEnum(getAttribute(posH, null, "relativeFrom"), ImageHorizontalRelativeToSchema) ?? "column";
|
|
163
236
|
const alignEl = findByFullName(posH, "wp:align");
|
|
164
237
|
if (alignEl) {
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
238
|
+
const alignment = narrowEnum(getTextContent(alignEl), ImageHorizontalAlignmentSchema);
|
|
239
|
+
if (alignment) return {
|
|
240
|
+
relativeTo,
|
|
241
|
+
alignment
|
|
242
|
+
};
|
|
170
243
|
}
|
|
171
244
|
const posOffsetEl = findByFullName(posH, "wp:posOffset");
|
|
172
245
|
if (posOffsetEl) {
|
|
@@ -177,7 +250,10 @@ function parsePositionH(posH) {
|
|
|
177
250
|
posOffset: Number.isNaN(posOffset) ? 0 : posOffset
|
|
178
251
|
};
|
|
179
252
|
}
|
|
180
|
-
return {
|
|
253
|
+
return {
|
|
254
|
+
relativeTo,
|
|
255
|
+
posOffset: 0
|
|
256
|
+
};
|
|
181
257
|
}
|
|
182
258
|
/**
|
|
183
259
|
* Parse vertical position from wp:positionV element.
|
|
@@ -187,11 +263,11 @@ function parsePositionV(posV) {
|
|
|
187
263
|
const relativeTo = narrowEnum(getAttribute(posV, null, "relativeFrom"), ImageVerticalRelativeToSchema) ?? "paragraph";
|
|
188
264
|
const alignEl = findByFullName(posV, "wp:align");
|
|
189
265
|
if (alignEl) {
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
266
|
+
const alignment = narrowEnum(getTextContent(alignEl), ImageVerticalAlignmentSchema);
|
|
267
|
+
if (alignment) return {
|
|
268
|
+
relativeTo,
|
|
269
|
+
alignment
|
|
270
|
+
};
|
|
195
271
|
}
|
|
196
272
|
const posOffsetEl = findByFullName(posV, "wp:posOffset");
|
|
197
273
|
if (posOffsetEl) {
|
|
@@ -202,7 +278,10 @@ function parsePositionV(posV) {
|
|
|
202
278
|
posOffset: Number.isNaN(posOffset) ? 0 : posOffset
|
|
203
279
|
};
|
|
204
280
|
}
|
|
205
|
-
return {
|
|
281
|
+
return {
|
|
282
|
+
relativeTo,
|
|
283
|
+
posOffset: 0
|
|
284
|
+
};
|
|
206
285
|
}
|
|
207
286
|
/**
|
|
208
287
|
* Parse position for anchored drawings (combines positionH + positionV).
|
|
@@ -210,10 +289,15 @@ function parsePositionV(posV) {
|
|
|
210
289
|
function parseAnchorPosition(anchor) {
|
|
211
290
|
const positionH = findByFullName(anchor, "wp:positionH");
|
|
212
291
|
const positionV = findByFullName(anchor, "wp:positionV");
|
|
213
|
-
if (!positionH && !positionV) return;
|
|
214
292
|
return {
|
|
215
|
-
horizontal: parsePositionH(positionH) ?? {
|
|
216
|
-
|
|
293
|
+
horizontal: parsePositionH(positionH) ?? {
|
|
294
|
+
relativeTo: "column",
|
|
295
|
+
posOffset: 0
|
|
296
|
+
},
|
|
297
|
+
vertical: parsePositionV(positionV) ?? {
|
|
298
|
+
relativeTo: "paragraph",
|
|
299
|
+
posOffset: 0
|
|
300
|
+
}
|
|
217
301
|
};
|
|
218
302
|
}
|
|
219
303
|
/** Known wrap element names */
|
|
@@ -14,6 +14,7 @@ type HeaderFooterWithVerbatim = document_d_exports.HeaderFooter & {
|
|
|
14
14
|
declare const getHeaderFooterVerbatimXml: (hf: document_d_exports.HeaderFooter) => string | undefined;
|
|
15
15
|
declare const canReplayHeaderFooterVerbatim: (hf: document_d_exports.HeaderFooter) => boolean;
|
|
16
16
|
declare const assignHeaderFooterVerbatimXml: (hf: document_d_exports.HeaderFooter, xml: string) => void;
|
|
17
|
+
declare const refreshHeaderFooterVerbatimFingerprint: (hf: document_d_exports.HeaderFooter) => void;
|
|
17
18
|
declare const clearHeaderFooterVerbatimXml: (hf: document_d_exports.HeaderFooter) => void;
|
|
18
19
|
//#endregion
|
|
19
|
-
export { HeaderFooterWithVerbatim, assignHeaderFooterVerbatimXml, canReplayHeaderFooterVerbatim, clearHeaderFooterVerbatimXml, getHeaderFooterVerbatimXml };
|
|
20
|
+
export { HeaderFooterWithVerbatim, assignHeaderFooterVerbatimXml, canReplayHeaderFooterVerbatim, clearHeaderFooterVerbatimXml, getHeaderFooterVerbatimXml, refreshHeaderFooterVerbatimFingerprint };
|
|
@@ -16,10 +16,15 @@ const assignHeaderFooterVerbatimXml = (hf, xml) => {
|
|
|
16
16
|
ext.verbatimXml = xml;
|
|
17
17
|
ext.verbatimFingerprint = headerFooterSerializationFingerprint(hf);
|
|
18
18
|
};
|
|
19
|
+
const refreshHeaderFooterVerbatimFingerprint = (hf) => {
|
|
20
|
+
const ext = hf;
|
|
21
|
+
if (!ext.verbatimXml) return;
|
|
22
|
+
ext.verbatimFingerprint = headerFooterSerializationFingerprint(hf);
|
|
23
|
+
};
|
|
19
24
|
const clearHeaderFooterVerbatimXml = (hf) => {
|
|
20
25
|
const ext = hf;
|
|
21
26
|
delete ext.verbatimXml;
|
|
22
27
|
delete ext.verbatimFingerprint;
|
|
23
28
|
};
|
|
24
29
|
//#endregion
|
|
25
|
-
export { assignHeaderFooterVerbatimXml, canReplayHeaderFooterVerbatim, clearHeaderFooterVerbatimXml, getHeaderFooterVerbatimXml };
|
|
30
|
+
export { assignHeaderFooterVerbatimXml, canReplayHeaderFooterVerbatim, clearHeaderFooterVerbatimXml, getHeaderFooterVerbatimXml, refreshHeaderFooterVerbatimFingerprint };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BorderStyleSchema, FrameWrapSchema, FrameXAlignSchema, FrameYAlignSchema, LineSpacingRuleSchema, ParagraphAlignmentSchema, ShadingPatternSchema, TabLeaderSchema, TabStopAlignmentSchema, ThemeColorSlotSchema, narrowEnum } from "./parserEnums.js";
|
|
2
|
-
import { elementToXml, findChild, findChildren, getAttribute, getChildElements, getLocalName, mergeXmlnsDeclarations, parseBooleanElement, parseNumberingLevelAttribute, parseNumericAttribute } from "./xmlParser.js";
|
|
2
|
+
import { elementToXml, findChild, findChildren, getAttribute, getChildElements, getLocalName, matchesName, mergeXmlnsDeclarations, parseBooleanElement, parseNumberingLevelAttribute, parseNumericAttribute } from "./xmlParser.js";
|
|
3
3
|
import { parseRun, parseRunProperties } from "./runParser.js";
|
|
4
4
|
import { parseFieldType } from "./fieldParser.js";
|
|
5
5
|
import { isValidHexId } from "../utils/hexId.js";
|
|
@@ -684,6 +684,9 @@ function parseSimpleField(node, styles, theme, rels, media, rootXmlns = {}) {
|
|
|
684
684
|
}
|
|
685
685
|
return field;
|
|
686
686
|
}
|
|
687
|
+
function hasRunPayloadElement(runElement) {
|
|
688
|
+
return getChildElements(runElement).some((child) => !matchesName(child, "w", "rPr"));
|
|
689
|
+
}
|
|
687
690
|
/**
|
|
688
691
|
* Parse all content within a paragraph
|
|
689
692
|
*
|
|
@@ -789,7 +792,7 @@ function parseParagraphContents(paraElement, styles, theme, _numbering, rels, me
|
|
|
789
792
|
type: "commentReference",
|
|
790
793
|
id: commentReferenceId
|
|
791
794
|
});
|
|
792
|
-
} else contents.push(run);
|
|
795
|
+
} else if (run.content.length > 0 || hasRunPayloadElement(runElement)) contents.push(run);
|
|
793
796
|
break;
|
|
794
797
|
}
|
|
795
798
|
case "hyperlink":
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { document_d_exports } from "../types/document.js";
|
|
2
2
|
//#region src/docx/paragraphTraversal.d.ts
|
|
3
|
-
type
|
|
3
|
+
type DocxParagraphSurfaces = {
|
|
4
4
|
documentBody: document_d_exports.DocumentBody;
|
|
5
5
|
headers?: Map<string, document_d_exports.HeaderFooter> | undefined;
|
|
6
6
|
footers?: Map<string, document_d_exports.HeaderFooter> | undefined;
|
|
7
7
|
footnotes?: readonly document_d_exports.Footnote[] | undefined;
|
|
8
8
|
endnotes?: readonly document_d_exports.Endnote[] | undefined;
|
|
9
9
|
};
|
|
10
|
-
|
|
10
|
+
/** Visit every run directly owned by a paragraph's inline-content tree. */
|
|
11
|
+
declare const visitParagraphRuns: (paragraph: document_d_exports.Paragraph, visit: (run: document_d_exports.Run) => void) => void;
|
|
12
|
+
declare const visitDocxParagraphs: ({ documentBody, headers, footers, footnotes, endnotes }: DocxParagraphSurfaces, visit: (paragraph: document_d_exports.Paragraph) => void) => void;
|
|
11
13
|
//#endregion
|
|
12
|
-
export { visitDocxParagraphs };
|
|
14
|
+
export { DocxParagraphSurfaces, visitDocxParagraphs, visitParagraphRuns };
|
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
//#region src/docx/paragraphTraversal.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const visitParagraph = (paragraph) => {
|
|
5
|
-
if (seenParagraphs.has(paragraph)) return;
|
|
6
|
-
seenParagraphs.add(paragraph);
|
|
7
|
-
visit(paragraph);
|
|
8
|
-
for (const content of paragraph.content) visitParagraphContent(content);
|
|
9
|
-
};
|
|
2
|
+
/** Visit every run directly owned by a paragraph's inline-content tree. */
|
|
3
|
+
const visitParagraphRuns = (paragraph, visit) => {
|
|
10
4
|
const visitRun = (run) => {
|
|
11
|
-
|
|
12
|
-
if (content.type !== "shape" || !content.shape.textBody) continue;
|
|
13
|
-
for (const block of content.shape.textBody.content) visitBlock(block);
|
|
14
|
-
}
|
|
5
|
+
visit(run);
|
|
15
6
|
};
|
|
16
7
|
const visitHyperlink = (hyperlink) => {
|
|
17
8
|
for (const child of hyperlink.children) if (child.type === "run") visitRun(child);
|
|
@@ -47,6 +38,22 @@ const visitDocxParagraphs = ({ documentBody, headers, footers, footnotes, endnot
|
|
|
47
38
|
for (const run of content.fieldResult) visitRun(run);
|
|
48
39
|
}
|
|
49
40
|
};
|
|
41
|
+
for (const content of paragraph.content) visitParagraphContent(content);
|
|
42
|
+
};
|
|
43
|
+
const visitDocxParagraphs = ({ documentBody, headers, footers, footnotes, endnotes }, visit) => {
|
|
44
|
+
const seenParagraphs = /* @__PURE__ */ new WeakSet();
|
|
45
|
+
const visitParagraph = (paragraph) => {
|
|
46
|
+
if (seenParagraphs.has(paragraph)) return;
|
|
47
|
+
seenParagraphs.add(paragraph);
|
|
48
|
+
visit(paragraph);
|
|
49
|
+
visitParagraphRuns(paragraph, visitRun);
|
|
50
|
+
};
|
|
51
|
+
const visitRun = (run) => {
|
|
52
|
+
for (const content of run.content) {
|
|
53
|
+
if (content.type !== "shape" || !content.shape.textBody) continue;
|
|
54
|
+
for (const block of content.shape.textBody.content) visitBlock(block);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
50
57
|
const visitTable = (table) => {
|
|
51
58
|
for (const row of table.rows) for (const cell of row.cells) visitBlocks(cell.content);
|
|
52
59
|
};
|
|
@@ -73,4 +80,4 @@ const visitDocxParagraphs = ({ documentBody, headers, footers, footnotes, endnot
|
|
|
73
80
|
for (const comment of documentBody.comments ?? []) for (const paragraph of comment.content) visitParagraph(paragraph);
|
|
74
81
|
};
|
|
75
82
|
//#endregion
|
|
76
|
-
export { visitDocxParagraphs };
|
|
83
|
+
export { visitDocxParagraphs, visitParagraphRuns };
|
package/dist/docx/parser.js
CHANGED
|
@@ -9,8 +9,9 @@ import { normalizeCommentReferences } from "./commentReferenceNormalization.js";
|
|
|
9
9
|
import { detectDocxConformanceClass } from "./conformance.js";
|
|
10
10
|
import { parseCoreProperties } from "./corePropertiesParser.js";
|
|
11
11
|
import { extractAllTemplateVariables, parseDocumentBody } from "./documentParser.js";
|
|
12
|
+
import { normalizeDrawingIds } from "./drawingIdNormalization.js";
|
|
12
13
|
import { parseEndnotes, parseFootnotes } from "./footnoteParser.js";
|
|
13
|
-
import { assignHeaderFooterVerbatimXml } from "./headerFooterVerbatim.js";
|
|
14
|
+
import { assignHeaderFooterVerbatimXml, refreshHeaderFooterVerbatimFingerprint } from "./headerFooterVerbatim.js";
|
|
14
15
|
import { parseFooter, parseHeader } from "./headerFooterParser.js";
|
|
15
16
|
import { normalizeHeaderFooterReferences } from "./headerFooterReferenceNormalization.js";
|
|
16
17
|
import { DocxModelValidationError, formatDocumentModelIssues, validateFolioDocumentModel } from "./modelValidation.js";
|
|
@@ -123,6 +124,15 @@ async function parseDocx(input, options = {}) {
|
|
|
123
124
|
onProgress("Parsing comments...", 75);
|
|
124
125
|
const comments = timeStage("comments", () => parseComments(raw.commentsXml, styles, theme, rels, media, raw.commentsExtensibleXml, raw.commentsExtendedXml));
|
|
125
126
|
if (comments.length > 0) documentBody.comments = comments;
|
|
127
|
+
normalizeDrawingIds({
|
|
128
|
+
documentBody,
|
|
129
|
+
...headers !== void 0 ? { headers } : {},
|
|
130
|
+
...footers !== void 0 ? { footers } : {},
|
|
131
|
+
...footnotes !== void 0 ? { footnotes } : {},
|
|
132
|
+
...endnotes !== void 0 ? { endnotes } : {}
|
|
133
|
+
});
|
|
134
|
+
for (const header of headers?.values() ?? []) refreshHeaderFooterVerbatimFingerprint(header);
|
|
135
|
+
for (const footer of footers?.values() ?? []) refreshHeaderFooterVerbatimFingerprint(footer);
|
|
126
136
|
normalizeRenderedPageBreakHints({
|
|
127
137
|
documentBody,
|
|
128
138
|
...headers !== void 0 ? { headers } : {},
|
|
@@ -19,6 +19,9 @@ declare const ParagraphAlignmentSchema: v.PicklistSchema<readonly ["left", "cent
|
|
|
19
19
|
declare const LineSpacingRuleSchema: v.PicklistSchema<readonly ["auto", "exact", "atLeast"], undefined>;
|
|
20
20
|
declare const TabStopAlignmentSchema: v.PicklistSchema<readonly ["left", "center", "right", "decimal", "bar", "clear", "num"], undefined>;
|
|
21
21
|
declare const TabLeaderSchema: v.PicklistSchema<readonly ["none", "dot", "hyphen", "underscore", "heavy", "middleDot"], undefined>;
|
|
22
|
+
declare const PositionalTabRelativeToSchema: v.PicklistSchema<readonly ["margin", "indent"], undefined>;
|
|
23
|
+
declare const PositionalTabAlignmentSchema: v.PicklistSchema<readonly ["left", "center", "right"], undefined>;
|
|
24
|
+
declare const PositionalTabLeaderSchema: v.PicklistSchema<readonly ["none", "dot", "hyphen", "underscore", "middleDot"], undefined>;
|
|
22
25
|
declare const FrameXAlignSchema: v.PicklistSchema<readonly ["left", "center", "right", "inside", "outside"], undefined>;
|
|
23
26
|
declare const FrameYAlignSchema: v.PicklistSchema<readonly ["top", "center", "bottom", "inside", "outside", "inline"], undefined>;
|
|
24
27
|
declare const FrameWrapSchema: v.PicklistSchema<readonly ["around", "auto", "none", "notBeside", "through", "tight"], undefined>;
|
|
@@ -42,4 +45,4 @@ declare const ShapeTypeSchema: v.PicklistSchema<readonly ["rect", "roundRect", "
|
|
|
42
45
|
declare const NumberFormatSchema: v.PicklistSchema<readonly ["decimal", "upperRoman", "lowerRoman", "upperLetter", "lowerLetter", "ordinal", "cardinalText", "ordinalText", "hex", "chicago", "ideographDigital", "japaneseCounting", "aiueo", "iroha", "decimalFullWidth", "decimalHalfWidth", "japaneseLegal", "japaneseDigitalTenThousand", "decimalEnclosedCircle", "decimalFullWidth2", "aiueoFullWidth", "irohaFullWidth", "decimalZero", "decimalZero3", "decimalZero4", "decimalZero5", "bullet", "ganada", "chosung", "decimalEnclosedFullstop", "decimalEnclosedParen", "decimalEnclosedCircleChinese", "ideographEnclosedCircle", "ideographTraditional", "ideographZodiac", "ideographZodiacTraditional", "taiwaneseCounting", "ideographLegalTraditional", "taiwaneseCountingThousand", "taiwaneseDigital", "chineseCounting", "chineseLegalSimplified", "chineseCountingThousand", "koreanDigital", "koreanCounting", "koreanLegal", "koreanDigital2", "vietnameseCounting", "russianLower", "russianUpper", "none", "numberInDash", "hebrew1", "hebrew2", "arabicAlpha", "arabicAbjad", "hindiVowels", "hindiConsonants", "hindiNumbers", "hindiCounting", "thaiLetters", "thaiNumbers", "thaiCounting"], undefined>;
|
|
43
46
|
declare const LevelSuffixSchema: v.PicklistSchema<readonly ["tab", "space", "nothing"], undefined>;
|
|
44
47
|
//#endregion
|
|
45
|
-
export { BorderStyleSchema, ConditionalStyleTypeSchema, EmphasisMarkSchema, FieldTypeSchema, FloatingTableXSpecSchema, FloatingTableYSpecSchema, FontHintSchema, FontThemeSchema, FrameWrapSchema, FrameXAlignSchema, FrameYAlignSchema, HighlightColorSchema, ImageHorizontalAlignmentSchema, ImageHorizontalRelativeToSchema, ImageVerticalAlignmentSchema, ImageVerticalRelativeToSchema, ImageWrapTextSchema, LevelSuffixSchema, LineSpacingRuleSchema, NumberFormatSchema, ParagraphAlignmentSchema, SdtLockSchema, ShadingPatternSchema, ShapeOutlineStyleSchema, ShapeTypeSchema, StyleTypeSchema, TabLeaderSchema, TabStopAlignmentSchema, TableCellTextDirectionSchema, TableRowHeightRuleSchema, TableWidthTypeSchema, TextEffectSchema, ThemeColorSlotSchema, UnderlineStyleSchema, narrowEnum };
|
|
48
|
+
export { BorderStyleSchema, ConditionalStyleTypeSchema, EmphasisMarkSchema, FieldTypeSchema, FloatingTableXSpecSchema, FloatingTableYSpecSchema, FontHintSchema, FontThemeSchema, FrameWrapSchema, FrameXAlignSchema, FrameYAlignSchema, HighlightColorSchema, ImageHorizontalAlignmentSchema, ImageHorizontalRelativeToSchema, ImageVerticalAlignmentSchema, ImageVerticalRelativeToSchema, ImageWrapTextSchema, LevelSuffixSchema, LineSpacingRuleSchema, NumberFormatSchema, ParagraphAlignmentSchema, PositionalTabAlignmentSchema, PositionalTabLeaderSchema, PositionalTabRelativeToSchema, SdtLockSchema, ShadingPatternSchema, ShapeOutlineStyleSchema, ShapeTypeSchema, StyleTypeSchema, TabLeaderSchema, TabStopAlignmentSchema, TableCellTextDirectionSchema, TableRowHeightRuleSchema, TableWidthTypeSchema, TextEffectSchema, ThemeColorSlotSchema, UnderlineStyleSchema, narrowEnum };
|
package/dist/docx/parserEnums.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, NUMBER_FORMAT_VALUES, PARAGRAPH_ALIGNMENT_VALUES, SDT_LOCK_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES } from "../types/documentEnumValues.js";
|
|
1
|
+
import { BORDER_STYLE_VALUES, CONDITIONAL_STYLE_TYPE_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FLOATING_TABLE_X_SPEC_VALUES, FLOATING_TABLE_Y_SPEC_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, FRAME_WRAP_VALUES, FRAME_X_ALIGN_VALUES, FRAME_Y_ALIGN_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, LEVEL_SUFFIX_VALUES, LINE_SPACING_RULE_VALUES, NUMBER_FORMAT_VALUES, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SHADING_PATTERN_VALUES, SHAPE_OUTLINE_STYLE_VALUES, SHAPE_TYPE_VALUES, STYLE_TYPE_VALUES, TABLE_CELL_TEXT_DIRECTION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_EFFECT_VALUES, THEME_COLOR_SLOT_VALUES, UNDERLINE_STYLE_VALUES } from "../types/documentEnumValues.js";
|
|
2
2
|
import * as v from "valibot";
|
|
3
3
|
//#region src/docx/parserEnums.ts
|
|
4
4
|
/**
|
|
@@ -45,6 +45,9 @@ const ParagraphAlignmentSchema = v.picklist(PARAGRAPH_ALIGNMENT_VALUES);
|
|
|
45
45
|
const LineSpacingRuleSchema = v.picklist(LINE_SPACING_RULE_VALUES);
|
|
46
46
|
const TabStopAlignmentSchema = v.picklist(TAB_STOP_ALIGNMENT_VALUES);
|
|
47
47
|
const TabLeaderSchema = v.picklist(TAB_LEADER_VALUES);
|
|
48
|
+
const PositionalTabRelativeToSchema = v.picklist(POSITIONAL_TAB_RELATIVE_TO_VALUES);
|
|
49
|
+
const PositionalTabAlignmentSchema = v.picklist(POSITIONAL_TAB_ALIGNMENT_VALUES);
|
|
50
|
+
const PositionalTabLeaderSchema = v.picklist(POSITIONAL_TAB_LEADER_VALUES);
|
|
48
51
|
const FrameXAlignSchema = v.picklist(FRAME_X_ALIGN_VALUES);
|
|
49
52
|
const FrameYAlignSchema = v.picklist(FRAME_Y_ALIGN_VALUES);
|
|
50
53
|
const FrameWrapSchema = v.picklist(FRAME_WRAP_VALUES);
|
|
@@ -68,4 +71,4 @@ const ShapeTypeSchema = v.picklist(SHAPE_TYPE_VALUES);
|
|
|
68
71
|
const NumberFormatSchema = v.picklist(NUMBER_FORMAT_VALUES);
|
|
69
72
|
const LevelSuffixSchema = v.picklist(LEVEL_SUFFIX_VALUES);
|
|
70
73
|
//#endregion
|
|
71
|
-
export { BorderStyleSchema, ConditionalStyleTypeSchema, EmphasisMarkSchema, FieldTypeSchema, FloatingTableXSpecSchema, FloatingTableYSpecSchema, FontHintSchema, FontThemeSchema, FrameWrapSchema, FrameXAlignSchema, FrameYAlignSchema, HighlightColorSchema, ImageHorizontalAlignmentSchema, ImageHorizontalRelativeToSchema, ImageVerticalAlignmentSchema, ImageVerticalRelativeToSchema, ImageWrapTextSchema, LevelSuffixSchema, LineSpacingRuleSchema, NumberFormatSchema, ParagraphAlignmentSchema, SdtLockSchema, ShadingPatternSchema, ShapeOutlineStyleSchema, ShapeTypeSchema, StyleTypeSchema, TabLeaderSchema, TabStopAlignmentSchema, TableCellTextDirectionSchema, TableRowHeightRuleSchema, TableWidthTypeSchema, TextEffectSchema, ThemeColorSlotSchema, UnderlineStyleSchema, narrowEnum };
|
|
74
|
+
export { BorderStyleSchema, ConditionalStyleTypeSchema, EmphasisMarkSchema, FieldTypeSchema, FloatingTableXSpecSchema, FloatingTableYSpecSchema, FontHintSchema, FontThemeSchema, FrameWrapSchema, FrameXAlignSchema, FrameYAlignSchema, HighlightColorSchema, ImageHorizontalAlignmentSchema, ImageHorizontalRelativeToSchema, ImageVerticalAlignmentSchema, ImageVerticalRelativeToSchema, ImageWrapTextSchema, LevelSuffixSchema, LineSpacingRuleSchema, NumberFormatSchema, ParagraphAlignmentSchema, PositionalTabAlignmentSchema, PositionalTabLeaderSchema, PositionalTabRelativeToSchema, SdtLockSchema, ShadingPatternSchema, ShapeOutlineStyleSchema, ShapeTypeSchema, StyleTypeSchema, TabLeaderSchema, TabStopAlignmentSchema, TableCellTextDirectionSchema, TableRowHeightRuleSchema, TableWidthTypeSchema, TextEffectSchema, ThemeColorSlotSchema, UnderlineStyleSchema, narrowEnum };
|
package/dist/docx/runParser.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EmphasisMarkSchema, FontHintSchema, FontThemeSchema, HighlightColorSchema, ShadingPatternSchema, TextEffectSchema, ThemeColorSlotSchema, UnderlineStyleSchema, narrowEnum } from "./parserEnums.js";
|
|
1
|
+
import { EmphasisMarkSchema, FontHintSchema, FontThemeSchema, HighlightColorSchema, PositionalTabAlignmentSchema, PositionalTabLeaderSchema, PositionalTabRelativeToSchema, ShadingPatternSchema, TextEffectSchema, ThemeColorSlotSchema, UnderlineStyleSchema, narrowEnum } from "./parserEnums.js";
|
|
2
2
|
import { cloneWithXmlnsDeclarations, elementToXml, findAllDeep, findChild, findChildren, getAttribute, getChildElements, getLocalName, getTextContent, mergeXmlnsDeclarations, parseBooleanElement, parseNumericAttribute } from "./xmlParser.js";
|
|
3
3
|
import { isTextBoxDrawing } from "./textBoxParser.js";
|
|
4
4
|
import { parseImage } from "./imageParser.js";
|
|
@@ -386,6 +386,19 @@ function parseTextContent(element) {
|
|
|
386
386
|
function parseTabContent() {
|
|
387
387
|
return { type: "tab" };
|
|
388
388
|
}
|
|
389
|
+
function parsePositionalTabContent(element) {
|
|
390
|
+
const positional = {};
|
|
391
|
+
const relativeTo = narrowEnum(getAttribute(element, "w", "relativeTo"), PositionalTabRelativeToSchema);
|
|
392
|
+
const alignment = narrowEnum(getAttribute(element, "w", "alignment"), PositionalTabAlignmentSchema);
|
|
393
|
+
const leader = narrowEnum(getAttribute(element, "w", "leader"), PositionalTabLeaderSchema);
|
|
394
|
+
if (relativeTo !== void 0) positional.relativeTo = relativeTo;
|
|
395
|
+
if (alignment !== void 0) positional.alignment = alignment;
|
|
396
|
+
if (leader !== void 0) positional.leader = leader;
|
|
397
|
+
return {
|
|
398
|
+
type: "tab",
|
|
399
|
+
positional
|
|
400
|
+
};
|
|
401
|
+
}
|
|
389
402
|
/**
|
|
390
403
|
* Parse break element (w:br)
|
|
391
404
|
*/
|
|
@@ -516,6 +529,9 @@ function parseRunContents(runElement, rels, media, rootXmlns = {}) {
|
|
|
516
529
|
case "tab":
|
|
517
530
|
contents.push(parseTabContent());
|
|
518
531
|
break;
|
|
532
|
+
case "ptab":
|
|
533
|
+
contents.push(parsePositionalTabContent(child));
|
|
534
|
+
break;
|
|
519
535
|
case "br":
|
|
520
536
|
contents.push(parseBreakContent(child));
|
|
521
537
|
break;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { deterministicHexId } from "../../utils/hexId.js";
|
|
2
2
|
import { escapeXml } from "./xmlUtils.js";
|
|
3
|
+
import { serializeTextFormatting } from "./runSerializer.js";
|
|
3
4
|
import { serializeParagraph } from "./paragraphSerializer.js";
|
|
4
5
|
//#region src/docx/serializer/commentSerializer.ts
|
|
5
6
|
/**
|
|
@@ -7,27 +8,31 @@ import { serializeParagraph } from "./paragraphSerializer.js";
|
|
|
7
8
|
*
|
|
8
9
|
* Serializes Comment[] to OOXML comments.xml format.
|
|
9
10
|
*/
|
|
10
|
-
const
|
|
11
|
+
const DEFAULT_ANNOTATION_REFERENCE_PROPERTIES = "<w:rPr><w:rStyle w:val=\"CommentReference\"/></w:rPr>";
|
|
11
12
|
const PARAGRAPH_PROPERTIES_END = "</w:pPr>";
|
|
13
|
+
const serializeAnnotationReference = (formatting) => {
|
|
14
|
+
return `<w:r>${formatting ? serializeTextFormatting(formatting) : DEFAULT_ANNOTATION_REFERENCE_PROPERTIES}<w:annotationRef/></w:r>`;
|
|
15
|
+
};
|
|
12
16
|
/** Serialize a paragraph, prepending an annotationRef run (required by Word in first paragraph of a comment) */
|
|
13
|
-
function serializeParagraphWithAnnotationRef(paragraph) {
|
|
17
|
+
function serializeParagraphWithAnnotationRef(paragraph, formatting) {
|
|
14
18
|
const xml = serializeParagraph(paragraph);
|
|
19
|
+
const annotationReference = serializeAnnotationReference(formatting);
|
|
15
20
|
const propertiesEnd = xml.indexOf(PARAGRAPH_PROPERTIES_END);
|
|
16
21
|
if (propertiesEnd !== -1) {
|
|
17
22
|
const contentStart = propertiesEnd + 8;
|
|
18
|
-
return `${xml.slice(0, contentStart)}${
|
|
23
|
+
return `${xml.slice(0, contentStart)}${annotationReference}${xml.slice(contentStart)}`;
|
|
19
24
|
}
|
|
20
|
-
return xml.replace(/^<w:p(?=[\s>])[^>]*>/u, (openingTag) => `${openingTag}${
|
|
25
|
+
return xml.replace(/^<w:p(?=[\s>])[^>]*>/u, (openingTag) => `${openingTag}${annotationReference}`);
|
|
21
26
|
}
|
|
22
27
|
function serializeComment(comment) {
|
|
23
28
|
const attrs = [`w:id="${comment.id}"`, `w:author="${escapeXml(comment.author)}"`];
|
|
24
|
-
if (comment.initials) attrs.push(`w:initials="${escapeXml(comment.initials)}"`);
|
|
29
|
+
if (comment.initials !== void 0) attrs.push(`w:initials="${escapeXml(comment.initials)}"`);
|
|
25
30
|
if (comment.date) attrs.push(`w:date="${escapeXml(comment.date)}"`);
|
|
26
31
|
let xml = `<w:comment ${attrs.join(" ")}>`;
|
|
27
32
|
if (comment.content.length > 0) {
|
|
28
|
-
xml += serializeParagraphWithAnnotationRef(comment.content[0]);
|
|
33
|
+
xml += serializeParagraphWithAnnotationRef(comment.content[0], comment.annotationReferenceFormatting);
|
|
29
34
|
for (let i = 1; i < comment.content.length; i++) xml += serializeParagraph(comment.content[i]);
|
|
30
|
-
} else xml +=
|
|
35
|
+
} else xml += `<w:p>${serializeAnnotationReference(comment.annotationReferenceFormatting)}</w:p>`;
|
|
31
36
|
xml += "</w:comment>";
|
|
32
37
|
return xml;
|
|
33
38
|
}
|