@stll/folio-core 0.47.1 → 0.47.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/notePropertiesParser.js +10 -2
- package/dist/docx/numberingParser.d.ts +2 -10
- package/dist/docx/numberingParser.js +6 -14
- package/dist/docx/runParser.js +10 -4
- package/dist/docx/serializer/numberingSerializer.js +2 -3
- package/dist/docx/serializer/runSerializer.js +5 -2
- package/dist/docx/serializer/sectionPropertiesSerializer.js +10 -2
- package/dist/docx/serializer/tableSerializer.js +2 -1
- package/dist/docx/tableParser.js +3 -1
- package/dist/prosemirror/attrs/index.js +20 -0
- package/dist/prosemirror/conversion/fromProseDoc.js +31 -15
- package/dist/prosemirror/conversion/toProseDoc.js +13 -3
- package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +2 -1
- package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +7 -3
- package/dist/prosemirror/extensions/nodes/HardBreakExtension.js +5 -1
- package/dist/prosemirror/extensions/nodes/TableExtension.js +40 -1
- package/dist/prosemirror/runFormattingInlineCarriers.js +18 -1
- package/dist/prosemirror/schema/marks.d.ts +4 -0
- package/dist/prosemirror/schema/nodes.d.ts +11 -0
- package/dist/utils/tableOperations.d.ts +1 -1
- package/package.json +2 -2
|
@@ -52,7 +52,11 @@ function parseFootnoteProperties(element) {
|
|
|
52
52
|
const numFmtEl = findChild(element, "w", "numFmt");
|
|
53
53
|
if (numFmtEl) {
|
|
54
54
|
const numFmt = parseNumberFormat(getAttribute(numFmtEl, "w", "val"));
|
|
55
|
-
if (numFmt !== void 0)
|
|
55
|
+
if (numFmt !== void 0) {
|
|
56
|
+
props.numFmt = numFmt;
|
|
57
|
+
const format = getAttribute(numFmtEl, "w", "format");
|
|
58
|
+
if (format !== null) props.numFmtFormat = format;
|
|
59
|
+
}
|
|
56
60
|
}
|
|
57
61
|
const numStartEl = findChild(element, "w", "numStart");
|
|
58
62
|
if (numStartEl) {
|
|
@@ -81,7 +85,11 @@ function parseEndnoteProperties(element) {
|
|
|
81
85
|
const numFmtEl = findChild(element, "w", "numFmt");
|
|
82
86
|
if (numFmtEl) {
|
|
83
87
|
const numFmt = parseNumberFormat(getAttribute(numFmtEl, "w", "val"));
|
|
84
|
-
if (numFmt !== void 0)
|
|
88
|
+
if (numFmt !== void 0) {
|
|
89
|
+
props.numFmt = numFmt;
|
|
90
|
+
const format = getAttribute(numFmtEl, "w", "format");
|
|
91
|
+
if (format !== null) props.numFmtFormat = format;
|
|
92
|
+
}
|
|
85
93
|
}
|
|
86
94
|
const numStartEl = findChild(element, "w", "numStart");
|
|
87
95
|
if (numStartEl) {
|
|
@@ -24,7 +24,7 @@ type NumberingMap = {
|
|
|
24
24
|
* @returns NumberingMap with definitions and helper functions
|
|
25
25
|
*/
|
|
26
26
|
declare function parseNumbering(numberingXml: string | null): NumberingMap;
|
|
27
|
-
/** A `w:numFmt` as the model holds it:
|
|
27
|
+
/** A `w:numFmt` as the model holds it: its token and authored format metadata. */
|
|
28
28
|
type ResolvedNumFmt = Pick<document_d_exports.ListLevel, "numFmt" | "numFmtFormat">;
|
|
29
29
|
/**
|
|
30
30
|
* The width a `custom` format's zero-padded first token counts to, or
|
|
@@ -35,14 +35,6 @@ type ResolvedNumFmt = Pick<document_d_exports.ListLevel, "numFmt" | "numFmtForma
|
|
|
35
35
|
* way; the width is the digit count of the first token, clamped to five.
|
|
36
36
|
*/
|
|
37
37
|
declare const customNumberFormatPadWidth: (format: string | undefined) => number | undefined;
|
|
38
|
-
/**
|
|
39
|
-
* The `@w:format` a level's `w:numFmt` writes, which only `custom` carries.
|
|
40
|
-
*
|
|
41
|
-
* `custom` is the reserved member that defers to another attribute, so the
|
|
42
|
-
* comparison lives here, in the module the reserved-value registry names as
|
|
43
|
-
* its owner, rather than in the serializer that needs the answer.
|
|
44
|
-
*/
|
|
45
|
-
declare const customNumberFormatOf: (level: ResolvedNumFmt) => string | undefined;
|
|
46
38
|
/** What the marker renderer counts a level in; `custom` decides by pad width. */
|
|
47
39
|
declare const counterFormatOf: (level: ResolvedNumFmt) => document_d_exports.CounterFormat;
|
|
48
40
|
/** {@link MARKER_ALIGNMENT} for a level that may not state a justification. */
|
|
@@ -92,4 +84,4 @@ declare function isBulletLevel(level: document_d_exports.ListLevel): boolean;
|
|
|
92
84
|
/** Whether a numbering level reserves horizontal space for a visible marker. */
|
|
93
85
|
declare const numberingLevelHasMarkerSlot: (level: Pick<document_d_exports.ListLevel, "numFmt">) => boolean;
|
|
94
86
|
//#endregion
|
|
95
|
-
export { NumberingMap, computeListRendering, counterFormatOf, createNumberingMap,
|
|
87
|
+
export { NumberingMap, computeListRendering, counterFormatOf, createNumberingMap, customNumberFormatPadWidth, formatOoxmlCounter as formatNumber, getBulletCharacter, getCachedNumberingMap, isBulletLevel, markerAlignmentForLevel, markerFormattingFromLevel, numberingLevelHasMarkerSlot, padDecimal, parseNumbering, renderListMarker };
|
|
@@ -248,16 +248,16 @@ function parseListLevel(element) {
|
|
|
248
248
|
* Resolve a `<w:numFmt>` element, or null when it is absent or carries a token
|
|
249
249
|
* outside `ST_NumberFormat` (an mc:Fallback can then supply the rendering).
|
|
250
250
|
*
|
|
251
|
-
*
|
|
252
|
-
* decoded here into a synthetic `decimalZero{3,4,5}` the
|
|
253
|
-
* declare, which the serializer wrote back as a `w:val`
|
|
254
|
-
* The pad
|
|
251
|
+
* `@w:format` stays beside every admitted token exactly as authored. `custom`
|
|
252
|
+
* used to be decoded here into a synthetic `decimalZero{3,4,5}` the
|
|
253
|
+
* enumeration does not declare, which the serializer wrote back as a `w:val`
|
|
254
|
+
* no consumer can read. The pad-width interpretation belongs to the renderer,
|
|
255
|
+
* not to the model; preservation belongs to every schema-valid `CT_NumFmt`.
|
|
255
256
|
*/
|
|
256
257
|
function resolveNumFmt(numFmtEl) {
|
|
257
258
|
if (!numFmtEl) return null;
|
|
258
259
|
const numFmt = narrowEnum(getAttribute(numFmtEl, "w", "val"), NumberFormatSchema);
|
|
259
260
|
if (numFmt === void 0) return null;
|
|
260
|
-
if (numFmt !== "custom") return { numFmt };
|
|
261
261
|
const format = getAttribute(numFmtEl, "w", "format");
|
|
262
262
|
return format === null ? { numFmt } : {
|
|
263
263
|
numFmt,
|
|
@@ -293,14 +293,6 @@ const customNumberFormatPadWidth = (format) => {
|
|
|
293
293
|
if (!/^0+1$/u.test(firstToken)) return;
|
|
294
294
|
return Math.min(firstToken.length, 5);
|
|
295
295
|
};
|
|
296
|
-
/**
|
|
297
|
-
* The `@w:format` a level's `w:numFmt` writes, which only `custom` carries.
|
|
298
|
-
*
|
|
299
|
-
* `custom` is the reserved member that defers to another attribute, so the
|
|
300
|
-
* comparison lives here, in the module the reserved-value registry names as
|
|
301
|
-
* its owner, rather than in the serializer that needs the answer.
|
|
302
|
-
*/
|
|
303
|
-
const customNumberFormatOf = (level) => level.numFmt === "custom" ? level.numFmtFormat : void 0;
|
|
304
296
|
/** What the marker renderer counts a level in; `custom` decides by pad width. */
|
|
305
297
|
const counterFormatOf = (level) => {
|
|
306
298
|
if (level.numFmt !== "custom") return level.numFmt;
|
|
@@ -511,4 +503,4 @@ function isBulletLevel(level) {
|
|
|
511
503
|
/** Whether a numbering level reserves horizontal space for a visible marker. */
|
|
512
504
|
const numberingLevelHasMarkerSlot = (level) => level.numFmt !== "none";
|
|
513
505
|
//#endregion
|
|
514
|
-
export { computeListRendering, counterFormatOf, createNumberingMap,
|
|
506
|
+
export { computeListRendering, counterFormatOf, createNumberingMap, customNumberFormatPadWidth, formatOoxmlCounter as formatNumber, getBulletCharacter, getCachedNumberingMap, isBulletLevel, markerAlignmentForLevel, markerFormattingFromLevel, numberingLevelHasMarkerSlot, padDecimal, parseNumbering, renderListMarker };
|
package/dist/docx/runParser.js
CHANGED
|
@@ -16,7 +16,7 @@ import { resolveThemeFontRef } from "./themeParser.js";
|
|
|
16
16
|
import { parsePropertyChangeInfo } from "./trackedChangeInfo.js";
|
|
17
17
|
import { captureVerbatimXml } from "./verbatimCapture.js";
|
|
18
18
|
import { parseVmlImageContent, shouldPreserveRawVmlPict } from "./vmlImageParser.js";
|
|
19
|
-
import { WORDPROCESSINGML_NAMESPACE_URIS, cloneWithXmlnsDeclarations, findAllDeep, findChild, findChildren, getAttribute, getChildElements, getLocalName, getNamespaceUri, getTextContent, mergeXmlnsDeclarations, parseBooleanElement, parseNumericAttribute, selectAlternateContentBranch } from "./xmlParser.js";
|
|
19
|
+
import { WORDPROCESSINGML_NAMESPACE_URIS, cloneWithXmlnsDeclarations, findAllDeep, findChild, findChildren, getAttribute, getChildElements, getLocalName, getNamespaceUri, getTextContent, mergeXmlnsDeclarations, parseBooleanElement, parseNumericAttribute, parseOnOffAttribute, selectAlternateContentBranch } from "./xmlParser.js";
|
|
20
20
|
import { DRAWING_RAW_XML_MODES } from "@stll/docx-core/model";
|
|
21
21
|
//#region src/docx/runParser.ts
|
|
22
22
|
/**
|
|
@@ -486,19 +486,25 @@ function parseSymbolContent(element) {
|
|
|
486
486
|
* Parse footnote reference (w:footnoteReference)
|
|
487
487
|
*/
|
|
488
488
|
function parseFootnoteReference(element) {
|
|
489
|
-
|
|
489
|
+
const reference = {
|
|
490
490
|
type: "footnoteRef",
|
|
491
491
|
id: parseNumericAttribute(element, "w", "id") ?? 0
|
|
492
492
|
};
|
|
493
|
+
const customMarkFollows = parseOnOffAttribute(element, "w", "customMarkFollows");
|
|
494
|
+
if (customMarkFollows !== void 0) reference.customMarkFollows = customMarkFollows;
|
|
495
|
+
return reference;
|
|
493
496
|
}
|
|
494
497
|
/**
|
|
495
498
|
* Parse endnote reference (w:endnoteReference)
|
|
496
499
|
*/
|
|
497
500
|
function parseEndnoteReference(element) {
|
|
498
|
-
|
|
501
|
+
const reference = {
|
|
499
502
|
type: "endnoteRef",
|
|
500
503
|
id: parseNumericAttribute(element, "w", "id") ?? 0
|
|
501
504
|
};
|
|
505
|
+
const customMarkFollows = parseOnOffAttribute(element, "w", "customMarkFollows");
|
|
506
|
+
if (customMarkFollows !== void 0) reference.customMarkFollows = customMarkFollows;
|
|
507
|
+
return reference;
|
|
502
508
|
}
|
|
503
509
|
/**
|
|
504
510
|
* Parse field character (w:fldChar)
|
|
@@ -670,7 +676,7 @@ function parseRunContents(runElement, rels, media, rootXmlns = {}) {
|
|
|
670
676
|
case "cr":
|
|
671
677
|
contents.push({
|
|
672
678
|
type: "break",
|
|
673
|
-
|
|
679
|
+
sourceElement: "cr"
|
|
674
680
|
});
|
|
675
681
|
break;
|
|
676
682
|
case "AlternateContent": {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { serializeParagraphPropertySet } from "../../internal/paragraphFormattingSerialization.js";
|
|
2
2
|
import { serializePreservedAttributes } from "../attributeRemainder.js";
|
|
3
|
-
import { customNumberFormatOf } from "../numberingParser.js";
|
|
4
3
|
import { serializePartElement } from "./partNamespaces.js";
|
|
5
4
|
import { serializeTextFormatting } from "./textFormattingSerializer.js";
|
|
6
5
|
import { intAttr } from "./xmlUtils.js";
|
|
@@ -9,8 +8,8 @@ import { serializeSequenceChildren } from "@stll/docx-core/schema";
|
|
|
9
8
|
//#region src/docx/serializer/numberingSerializer.ts
|
|
10
9
|
/** Serialize one `w:lvl`. */
|
|
11
10
|
function serializeLevel(level) {
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
let numFmtFormat = "";
|
|
12
|
+
if (level.numFmtFormat !== void 0) numFmtFormat = ` w:format="${escapeXmlAttribute(level.numFmtFormat)}"`;
|
|
14
13
|
const pPr = level.pPr === void 0 ? "" : serializeParagraphPropertySet({ formatting: level.pPr }) || "<w:pPr/>";
|
|
15
14
|
const rPr = level.rPr === void 0 ? "" : serializeTextFormatting(level.rPr) || "<w:rPr/>";
|
|
16
15
|
const lvlTextAttrs = [`w:val="${escapeXmlAttribute(level.lvlText)}"`];
|
|
@@ -76,6 +76,7 @@ function serializeTabContent(content) {
|
|
|
76
76
|
* Serialize break content (w:br)
|
|
77
77
|
*/
|
|
78
78
|
function serializeBreakContent(content) {
|
|
79
|
+
if (content.sourceElement === "cr") return "<w:cr/>";
|
|
79
80
|
const attrs = [];
|
|
80
81
|
if (content.breakType === "page") attrs.push("w:type=\"page\"");
|
|
81
82
|
else if (content.breakType === "column") attrs.push("w:type=\"column\"");
|
|
@@ -94,8 +95,10 @@ function serializeSymbolContent(content) {
|
|
|
94
95
|
* Serialize footnote/endnote reference
|
|
95
96
|
*/
|
|
96
97
|
function serializeNoteReference(content) {
|
|
97
|
-
|
|
98
|
-
|
|
98
|
+
let customMarkFollows = "";
|
|
99
|
+
if (content.customMarkFollows !== void 0) customMarkFollows = ` w:customMarkFollows="${content.customMarkFollows ? "1" : "0"}"`;
|
|
100
|
+
if (content.type === "footnoteRef") return `<w:footnoteReference w:id="${content.id}"${customMarkFollows}/>`;
|
|
101
|
+
return `<w:endnoteReference w:id="${content.id}"${customMarkFollows}/>`;
|
|
99
102
|
}
|
|
100
103
|
/**
|
|
101
104
|
* Serialize field character (w:fldChar)
|
|
@@ -13,7 +13,11 @@ function serializeFootnoteProperties(props) {
|
|
|
13
13
|
if (!props) return "";
|
|
14
14
|
const parts = [];
|
|
15
15
|
if (props.position) parts.push(`<w:pos w:val="${props.position}"/>`);
|
|
16
|
-
if (props.numFmt)
|
|
16
|
+
if (props.numFmt) {
|
|
17
|
+
let format = "";
|
|
18
|
+
if (props.numFmtFormat !== void 0) format = ` w:format="${escapeXmlAttribute(props.numFmtFormat)}"`;
|
|
19
|
+
parts.push(`<w:numFmt w:val="${props.numFmt}"${format}/>`);
|
|
20
|
+
}
|
|
17
21
|
if (props.numStart !== void 0) parts.push(`<w:numStart w:val="${intAttr(props.numStart)}"/>`);
|
|
18
22
|
if (props.numRestart) parts.push(`<w:numRestart w:val="${props.numRestart}"/>`);
|
|
19
23
|
return parts.length > 0 ? `<w:footnotePr>${parts.join("")}</w:footnotePr>` : "";
|
|
@@ -25,7 +29,11 @@ function serializeEndnoteProperties(props) {
|
|
|
25
29
|
if (!props) return "";
|
|
26
30
|
const parts = [];
|
|
27
31
|
if (props.position) parts.push(`<w:pos w:val="${props.position}"/>`);
|
|
28
|
-
if (props.numFmt)
|
|
32
|
+
if (props.numFmt) {
|
|
33
|
+
let format = "";
|
|
34
|
+
if (props.numFmtFormat !== void 0) format = ` w:format="${escapeXmlAttribute(props.numFmtFormat)}"`;
|
|
35
|
+
parts.push(`<w:numFmt w:val="${props.numFmt}"${format}/>`);
|
|
36
|
+
}
|
|
29
37
|
if (props.numStart !== void 0) parts.push(`<w:numStart w:val="${intAttr(props.numStart)}"/>`);
|
|
30
38
|
if (props.numRestart) parts.push(`<w:numRestart w:val="${props.numRestart}"/>`);
|
|
31
39
|
return parts.length > 0 ? `<w:endnotePr>${parts.join("")}</w:endnotePr>` : "";
|
|
@@ -529,10 +529,11 @@ function serializeCellContent(content, serializeParagraph) {
|
|
|
529
529
|
*/
|
|
530
530
|
function serializeTableCell(cell, serializeParagraph) {
|
|
531
531
|
const parts = [];
|
|
532
|
+
const id = cell.id === void 0 ? "" : ` w:id="${escapeXmlAttribute(cell.id)}"`;
|
|
532
533
|
const tcPrXml = serializeTableCellFormatting(cell.formatting, cell.propertyChanges, cell.structuralChange);
|
|
533
534
|
if (tcPrXml) parts.push(tcPrXml);
|
|
534
535
|
parts.push(serializeCellContent(cell.content, serializeParagraph));
|
|
535
|
-
return `<w:tc>${parts.join("")}</w:tc>`;
|
|
536
|
+
return `<w:tc${id}>${parts.join("")}</w:tc>`;
|
|
536
537
|
}
|
|
537
538
|
/**
|
|
538
539
|
* A container's verbatim sink and its bookmark markers, as one positioned list.
|
package/dist/docx/tableParser.js
CHANGED
|
@@ -12,7 +12,7 @@ import { TABLE_LOOK_FLAGS } from "./tableLook.js";
|
|
|
12
12
|
import { parsePropertyChangeInfo, parseTrackedChangeInfo } from "./trackedChangeInfo.js";
|
|
13
13
|
import { percentageSpelling, transitionalSlotEncoding } from "./transitionalSpelling.js";
|
|
14
14
|
import { captureVerbatimXml } from "./verbatimCapture.js";
|
|
15
|
-
import { cloneElement, findChild, findChildren, findWordprocessingChild, getAttribute, getLocalName, mergeXmlnsDeclarations, parseBooleanElement, parseNumericAttribute, parseOnOffAttribute, parseTableMeasurementValue, selectAlternateContentBranch } from "./xmlParser.js";
|
|
15
|
+
import { WORDPROCESSINGML_NAMESPACE_URIS, cloneElement, findChild, findChildren, findWordprocessingChild, getAttribute, getAttributeByNamespaceUri, getLocalName, mergeXmlnsDeclarations, parseBooleanElement, parseNumericAttribute, parseOnOffAttribute, parseTableMeasurementValue, selectAlternateContentBranch } from "./xmlParser.js";
|
|
16
16
|
//#region src/docx/tableParser.ts
|
|
17
17
|
/**
|
|
18
18
|
* Sanity cap on `w:gridSpan` (and the derived table column count). Word's
|
|
@@ -858,6 +858,8 @@ function parseTableCell(tcElement, styles, theme, numbering, rels, media, option
|
|
|
858
858
|
type: "tableCell",
|
|
859
859
|
content: []
|
|
860
860
|
};
|
|
861
|
+
const id = getAttributeByNamespaceUri(tcElement, WORDPROCESSINGML_NAMESPACE_URIS, "id");
|
|
862
|
+
if (id !== null) cell.id = id;
|
|
861
863
|
const tcPrElement = findChild(tcElement, "w", "tcPr");
|
|
862
864
|
const formatting = parseTableCellProperties(tcPrElement);
|
|
863
865
|
if (formatting) cell.formatting = formatting;
|
|
@@ -89,6 +89,7 @@ const TEXT_BOX_TRACKED_CHANGE_TYPES = [
|
|
|
89
89
|
"moveTo"
|
|
90
90
|
];
|
|
91
91
|
const HARD_BREAK_TYPES = ["column", "textWrapping"];
|
|
92
|
+
const HARD_BREAK_SOURCE_ELEMENTS = ["br", "cr"];
|
|
92
93
|
const PAGE_BREAK_CLEAR_VALUES = [
|
|
93
94
|
"none",
|
|
94
95
|
"left",
|
|
@@ -269,8 +270,19 @@ const readHardBreakAttrs = (node) => {
|
|
|
269
270
|
const attrs = attrsRecord(node.attrs);
|
|
270
271
|
const issues = [];
|
|
271
272
|
expectNodeType(node, "hardBreak", issues);
|
|
273
|
+
optionalOneOf(attrs, "sourceElement", "hardBreak.attrs.sourceElement", issues, HARD_BREAK_SOURCE_ELEMENTS);
|
|
272
274
|
optionalOneOf(attrs, "breakType", "hardBreak.attrs.breakType", issues, HARD_BREAK_TYPES);
|
|
273
275
|
optionalOneOf(attrs, "clear", "hardBreak.attrs.clear", issues, PAGE_BREAK_CLEAR_VALUES);
|
|
276
|
+
if (attrs["sourceElement"] === "cr") {
|
|
277
|
+
if (attrs["breakType"] !== void 0 && attrs["breakType"] !== null) issues.push({
|
|
278
|
+
path: "hardBreak.attrs.breakType",
|
|
279
|
+
message: "Not allowed on a carriage-return element."
|
|
280
|
+
});
|
|
281
|
+
if (attrs["clear"] !== void 0 && attrs["clear"] !== null) issues.push({
|
|
282
|
+
path: "hardBreak.attrs.clear",
|
|
283
|
+
message: "Not allowed on a carriage-return element."
|
|
284
|
+
});
|
|
285
|
+
}
|
|
274
286
|
return attrsResult(attrs, issues);
|
|
275
287
|
};
|
|
276
288
|
const expectHardBreakAttrs = (node) => expectCachedNodeAttrs(node, hardBreakAttrsCache, readHardBreakAttrs, "hard break attrs");
|
|
@@ -386,6 +398,7 @@ const readTableCellAttrs = (node) => {
|
|
|
386
398
|
const attrs = attrsRecord(node.attrs);
|
|
387
399
|
const issues = [];
|
|
388
400
|
expectNodeTypeOneOf(node, ["tableCell", "tableHeader"], issues);
|
|
401
|
+
optionalString(attrs, "_docxCellId", "tableCell.attrs._docxCellId", issues);
|
|
389
402
|
requiredNumber(attrs, "colspan", "tableCell.attrs.colspan", issues);
|
|
390
403
|
requiredNumber(attrs, "rowspan", "tableCell.attrs.rowspan", issues);
|
|
391
404
|
optionalOneOf(attrs, "_omittedGridSlot", "tableCell.attrs._omittedGridSlot", issues, OMITTED_GRID_SLOT_VALUES);
|
|
@@ -767,6 +780,7 @@ const readFootnoteRefMarkAttrs = (mark) => {
|
|
|
767
780
|
requiredStringOrNumber(attrs, "id", "footnoteRef.attrs.id", issues);
|
|
768
781
|
optionalOneOf(attrs, "noteType", "footnoteRef.attrs.noteType", issues, NOTE_TYPES);
|
|
769
782
|
optionalOneOf(attrs, "vertAlign", "footnoteRef.attrs.vertAlign", issues, NOTE_REF_VERT_ALIGNS);
|
|
783
|
+
optionalBoolean(attrs, "customMarkFollows", "footnoteRef.attrs.customMarkFollows", issues);
|
|
770
784
|
return attrsResult(attrs, issues);
|
|
771
785
|
};
|
|
772
786
|
const expectFootnoteRefMarkAttrs = (mark) => expectCachedMarkAttrs(mark, footnoteRefAttrsCache, readFootnoteRefMarkAttrs, "footnote reference attrs");
|
|
@@ -1018,6 +1032,9 @@ const readHyperlinkMarkAttrs = (mark) => {
|
|
|
1018
1032
|
requiredString(attrs, "href", "hyperlink.attrs.href", issues);
|
|
1019
1033
|
optionalString(attrs, "tooltip", "hyperlink.attrs.tooltip", issues);
|
|
1020
1034
|
optionalString(attrs, "rId", "hyperlink.attrs.rId", issues);
|
|
1035
|
+
optionalString(attrs, "target", "hyperlink.attrs.target", issues);
|
|
1036
|
+
optionalBoolean(attrs, "history", "hyperlink.attrs.history", issues);
|
|
1037
|
+
optionalString(attrs, "docLocation", "hyperlink.attrs.docLocation", issues);
|
|
1021
1038
|
validateNonNegativeInteger(attrs["_docxHyperlinkIndex"], "hyperlink.attrs._docxHyperlinkIndex", issues);
|
|
1022
1039
|
return attrsResult(attrs, issues);
|
|
1023
1040
|
};
|
|
@@ -2612,6 +2629,9 @@ const optionalEmptyHyperlinkArray = (value, issues) => {
|
|
|
2612
2629
|
optionalString(item, "anchor", `${itemPath}.anchor`, issues);
|
|
2613
2630
|
optionalString(item, "tooltip", `${itemPath}.tooltip`, issues);
|
|
2614
2631
|
optionalString(item, "rId", `${itemPath}.rId`, issues);
|
|
2632
|
+
optionalString(item, "target", `${itemPath}.target`, issues);
|
|
2633
|
+
optionalBoolean(item, "history", `${itemPath}.history`, issues);
|
|
2634
|
+
optionalString(item, "docLocation", `${itemPath}.docLocation`, issues);
|
|
2615
2635
|
}
|
|
2616
2636
|
};
|
|
2617
2637
|
//#endregion
|
|
@@ -1643,6 +1643,9 @@ function createEmptyHyperlink(attrs) {
|
|
|
1643
1643
|
if (attrs.anchor !== void 0) hyperlink.anchor = attrs.anchor;
|
|
1644
1644
|
if (attrs.tooltip !== void 0) hyperlink.tooltip = attrs.tooltip;
|
|
1645
1645
|
if (attrs.rId !== void 0) hyperlink.rId = attrs.rId;
|
|
1646
|
+
if (attrs.target !== void 0) hyperlink.target = attrs.target;
|
|
1647
|
+
if (attrs.history !== void 0) hyperlink.history = attrs.history;
|
|
1648
|
+
if (attrs.docLocation !== void 0) hyperlink.docLocation = attrs.docLocation;
|
|
1646
1649
|
return hyperlink;
|
|
1647
1650
|
}
|
|
1648
1651
|
function getCommentMarkIds(marks) {
|
|
@@ -1684,6 +1687,9 @@ function getLinkKey(mark) {
|
|
|
1684
1687
|
attrs.href,
|
|
1685
1688
|
attrs.rId ?? "",
|
|
1686
1689
|
attrs.tooltip ?? "",
|
|
1690
|
+
attrs.target ?? "",
|
|
1691
|
+
attrs.history === void 0 ? "" : String(attrs.history),
|
|
1692
|
+
attrs.docLocation ?? "",
|
|
1687
1693
|
attrs._docxHyperlinkIndex ?? ""
|
|
1688
1694
|
].join("\0");
|
|
1689
1695
|
}
|
|
@@ -1701,21 +1707,24 @@ function getMarksKey(marks) {
|
|
|
1701
1707
|
function createHyperlink(linkMark) {
|
|
1702
1708
|
const attrs = expectHyperlinkMarkAttrs(linkMark);
|
|
1703
1709
|
const href = attrs.href;
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1710
|
+
const metadata = {
|
|
1711
|
+
...attrs.tooltip === void 0 ? {} : { tooltip: attrs.tooltip },
|
|
1712
|
+
...attrs.target === void 0 ? {} : { target: attrs.target },
|
|
1713
|
+
...attrs.history === void 0 ? {} : { history: attrs.history },
|
|
1714
|
+
...attrs.docLocation === void 0 ? {} : { docLocation: attrs.docLocation }
|
|
1715
|
+
};
|
|
1716
|
+
if (href.startsWith("#")) return {
|
|
1717
|
+
type: "hyperlink",
|
|
1718
|
+
anchor: href.slice(1),
|
|
1719
|
+
...metadata,
|
|
1720
|
+
children: []
|
|
1721
|
+
};
|
|
1713
1722
|
const hyperlink = {
|
|
1714
1723
|
type: "hyperlink",
|
|
1715
1724
|
href,
|
|
1725
|
+
...metadata,
|
|
1716
1726
|
children: []
|
|
1717
1727
|
};
|
|
1718
|
-
if (attrs.tooltip) hyperlink.tooltip = attrs.tooltip;
|
|
1719
1728
|
if (attrs.rId) hyperlink.rId = attrs.rId;
|
|
1720
1729
|
return hyperlink;
|
|
1721
1730
|
}
|
|
@@ -1831,12 +1840,14 @@ function getNoteReferenceVertAlign(noteAttrs, marks) {
|
|
|
1831
1840
|
}
|
|
1832
1841
|
function createNoteReferenceRun(noteRefMark, marks, formattingContext) {
|
|
1833
1842
|
const noteAttrs = expectFootnoteRefMarkAttrs(noteRefMark);
|
|
1843
|
+
const noteRef = {
|
|
1844
|
+
type: noteAttrs.noteType === "endnote" ? "endnoteRef" : "footnoteRef",
|
|
1845
|
+
id: typeof noteAttrs.id === "string" ? Number.parseInt(noteAttrs.id, 10) || 0 : noteAttrs.id
|
|
1846
|
+
};
|
|
1847
|
+
if (noteAttrs.customMarkFollows !== void 0) noteRef.customMarkFollows = noteAttrs.customMarkFollows;
|
|
1834
1848
|
const run = {
|
|
1835
1849
|
type: "run",
|
|
1836
|
-
content: [
|
|
1837
|
-
type: noteAttrs.noteType === "endnote" ? "endnoteRef" : "footnoteRef",
|
|
1838
|
-
id: typeof noteAttrs.id === "string" ? Number.parseInt(noteAttrs.id, 10) || 0 : noteAttrs.id
|
|
1839
|
-
}]
|
|
1850
|
+
content: [noteRef]
|
|
1840
1851
|
};
|
|
1841
1852
|
const formatting = getAtomRunFormattingFromMarks(marks, formattingContext);
|
|
1842
1853
|
const vertAlign = getNoteReferenceVertAlign(noteAttrs, marks);
|
|
@@ -2045,8 +2056,12 @@ function createPageBreakCarrierRun({ baseParagraphFormatting, clear, inheritedFo
|
|
|
2045
2056
|
function createBreakRun(attrs, marks, formattingContext) {
|
|
2046
2057
|
const run = {
|
|
2047
2058
|
type: "run",
|
|
2048
|
-
content: [{
|
|
2059
|
+
content: [attrs.sourceElement === "cr" ? {
|
|
2060
|
+
type: "break",
|
|
2061
|
+
sourceElement: "cr"
|
|
2062
|
+
} : {
|
|
2049
2063
|
type: "break",
|
|
2064
|
+
...attrs.sourceElement !== void 0 ? { sourceElement: attrs.sourceElement } : {},
|
|
2050
2065
|
...attrs.breakType !== void 0 ? { breakType: attrs.breakType } : {},
|
|
2051
2066
|
...attrs.clear !== void 0 ? { clear: attrs.clear } : {}
|
|
2052
2067
|
}]
|
|
@@ -3305,6 +3320,7 @@ function convertPMTableCell(node, documentCounts, styleResolver = null) {
|
|
|
3305
3320
|
type: "tableCell",
|
|
3306
3321
|
content
|
|
3307
3322
|
};
|
|
3323
|
+
if (attrs._docxCellId !== void 0) cell.id = attrs._docxCellId;
|
|
3308
3324
|
const cellFormatting = tableCellAttrsToFormatting(attrs);
|
|
3309
3325
|
if (cellFormatting) cell.formatting = cellFormatting;
|
|
3310
3326
|
if (Array.isArray(attrs.tcPrChange) && attrs.tcPrChange.length > 0) cell.propertyChanges = [...attrs.tcPrChange];
|
|
@@ -492,7 +492,10 @@ function convertParagraph(paragraph, styleResolver, context, extraRunFormatting,
|
|
|
492
492
|
...content.href !== void 0 ? { href: content.href } : {},
|
|
493
493
|
...content.anchor !== void 0 ? { anchor: content.anchor } : {},
|
|
494
494
|
...content.tooltip !== void 0 ? { tooltip: content.tooltip } : {},
|
|
495
|
-
...content.rId !== void 0 ? { rId: content.rId } : {}
|
|
495
|
+
...content.rId !== void 0 ? { rId: content.rId } : {},
|
|
496
|
+
...content.target !== void 0 ? { target: content.target } : {},
|
|
497
|
+
...content.history !== void 0 ? { history: content.history } : {},
|
|
498
|
+
...content.docLocation !== void 0 ? { docLocation: content.docLocation } : {}
|
|
496
499
|
});
|
|
497
500
|
break;
|
|
498
501
|
}
|
|
@@ -1325,6 +1328,7 @@ function convertTableCell({ cell, styleResolver, context, isHeader, gridWidthPer
|
|
|
1325
1328
|
colspan: formatting?.gridSpan ?? 1,
|
|
1326
1329
|
rowspan
|
|
1327
1330
|
};
|
|
1331
|
+
if (cell.id !== void 0) attrs._docxCellId = cell.id;
|
|
1328
1332
|
if (effectiveFormatting.width.type === "value") {
|
|
1329
1333
|
attrs.width = effectiveFormatting.width.value;
|
|
1330
1334
|
if (effectiveFormatting.width.widthType) attrs.widthType = effectiveFormatting.width.widthType;
|
|
@@ -2064,6 +2068,7 @@ function convertRunContent(content, marks, formatting, textBoxAnchors, authoredF
|
|
|
2064
2068
|
case "break":
|
|
2065
2069
|
if (content.breakType === "textWrapping" || !content.breakType) {
|
|
2066
2070
|
const attrs = {
|
|
2071
|
+
...content.sourceElement !== void 0 ? { sourceElement: content.sourceElement } : {},
|
|
2067
2072
|
...content.breakType !== void 0 ? { breakType: content.breakType } : {},
|
|
2068
2073
|
...content.clear !== void 0 ? { clear: content.clear } : {}
|
|
2069
2074
|
};
|
|
@@ -2095,7 +2100,8 @@ function convertRunContent(content, marks, formatting, textBoxAnchors, authoredF
|
|
|
2095
2100
|
const footnoteMark = schema.mark("footnoteRef", {
|
|
2096
2101
|
id: content.id.toString(),
|
|
2097
2102
|
noteType: "footnote",
|
|
2098
|
-
vertAlign: noteReferenceVertAlign(formatting?.vertAlign)
|
|
2103
|
+
vertAlign: noteReferenceVertAlign(formatting?.vertAlign),
|
|
2104
|
+
customMarkFollows: content.customMarkFollows
|
|
2099
2105
|
});
|
|
2100
2106
|
return [schema.text(content.id.toString(), [...marks, footnoteMark])];
|
|
2101
2107
|
}
|
|
@@ -2103,7 +2109,8 @@ function convertRunContent(content, marks, formatting, textBoxAnchors, authoredF
|
|
|
2103
2109
|
const endnoteMark = schema.mark("footnoteRef", {
|
|
2104
2110
|
id: content.id.toString(),
|
|
2105
2111
|
noteType: "endnote",
|
|
2106
|
-
vertAlign: noteReferenceVertAlign(formatting?.vertAlign)
|
|
2112
|
+
vertAlign: noteReferenceVertAlign(formatting?.vertAlign),
|
|
2113
|
+
customMarkFollows: content.customMarkFollows
|
|
2107
2114
|
});
|
|
2108
2115
|
return [schema.text(content.id.toString(), [...marks, endnoteMark])];
|
|
2109
2116
|
}
|
|
@@ -2284,6 +2291,9 @@ function convertHyperlink(hyperlink, { getInheritedRunFormatting, styleResolver,
|
|
|
2284
2291
|
href,
|
|
2285
2292
|
tooltip: hyperlink.tooltip,
|
|
2286
2293
|
rId: hyperlink.rId,
|
|
2294
|
+
target: hyperlink.target,
|
|
2295
|
+
history: hyperlink.history,
|
|
2296
|
+
docLocation: hyperlink.docLocation,
|
|
2287
2297
|
_docxHyperlinkIndex: hyperlinkIndex
|
|
2288
2298
|
});
|
|
2289
2299
|
for (const { content: child, stack } of withInlineWrapperStacks(hyperlink.children)) {
|
|
@@ -82,6 +82,9 @@ const HyperlinkExtension = createMarkExtension({
|
|
|
82
82
|
href: {},
|
|
83
83
|
tooltip: { default: null },
|
|
84
84
|
rId: { default: null },
|
|
85
|
+
target: { default: null },
|
|
86
|
+
history: { default: null },
|
|
87
|
+
docLocation: { default: null },
|
|
85
88
|
_docxHyperlinkIndex: { default: null }
|
|
86
89
|
},
|
|
87
90
|
inclusive: false,
|
|
@@ -89,14 +92,15 @@ const HyperlinkExtension = createMarkExtension({
|
|
|
89
92
|
tag: "a[href]",
|
|
90
93
|
getAttrs: (dom) => ({
|
|
91
94
|
href: sanitizeStoredHref(dom.getAttribute("href") ?? void 0),
|
|
92
|
-
tooltip: dom.getAttribute("title") ?? void 0
|
|
95
|
+
tooltip: dom.getAttribute("title") ?? void 0,
|
|
96
|
+
target: dom.getAttribute("target") ?? void 0
|
|
93
97
|
})
|
|
94
98
|
}],
|
|
95
99
|
toDOM(mark) {
|
|
96
|
-
const { href, tooltip } = expectHyperlinkMarkAttrs(mark);
|
|
100
|
+
const { href, target, tooltip } = expectHyperlinkMarkAttrs(mark);
|
|
97
101
|
const domAttrs = {
|
|
98
102
|
href: sanitizeStoredHref(href),
|
|
99
|
-
...anchorTargetAttrs(
|
|
103
|
+
...anchorTargetAttrs(target)
|
|
100
104
|
};
|
|
101
105
|
if (tooltip) domAttrs["title"] = tooltip;
|
|
102
106
|
return [
|
|
@@ -12,6 +12,7 @@ const HardBreakExtension = createNodeExtension({
|
|
|
12
12
|
inline: true,
|
|
13
13
|
group: "inline",
|
|
14
14
|
attrs: {
|
|
15
|
+
sourceElement: { default: null },
|
|
15
16
|
breakType: { default: null },
|
|
16
17
|
clear: { default: null }
|
|
17
18
|
},
|
|
@@ -22,15 +23,18 @@ const HardBreakExtension = createNodeExtension({
|
|
|
22
23
|
if (!(node instanceof HTMLElement)) return null;
|
|
23
24
|
const breakType = node.dataset["docxBreakType"];
|
|
24
25
|
const clear = node.dataset["docxBreakClear"];
|
|
26
|
+
const sourceElement = node.dataset["docxSourceElement"];
|
|
25
27
|
const attrs = {};
|
|
28
|
+
if (sourceElement === "br" || sourceElement === "cr") attrs["sourceElement"] = sourceElement;
|
|
26
29
|
if (breakType === "column" || breakType === "textWrapping") attrs["breakType"] = breakType;
|
|
27
30
|
if (clear === "none" || clear === "left" || clear === "right" || clear === "all") attrs["clear"] = clear;
|
|
28
31
|
return Object.keys(attrs).length > 0 ? attrs : null;
|
|
29
32
|
}
|
|
30
33
|
}],
|
|
31
34
|
toDOM(node) {
|
|
32
|
-
const { breakType, clear } = expectHardBreakAttrs(node);
|
|
35
|
+
const { sourceElement, breakType, clear } = expectHardBreakAttrs(node);
|
|
33
36
|
const attrs = {};
|
|
37
|
+
if (sourceElement !== void 0) attrs["data-docx-source-element"] = sourceElement;
|
|
34
38
|
if (breakType !== void 0) attrs["data-docx-break-type"] = breakType;
|
|
35
39
|
if (clear !== void 0) attrs["data-docx-break-clear"] = clear;
|
|
36
40
|
return Object.keys(attrs).length > 0 ? ["br", attrs] : ["br"];
|
|
@@ -39,6 +39,43 @@ const preserveOmittedGridSlots = (command) => (state, dispatch, view) => {
|
|
|
39
39
|
if (table && hasOmittedGridSlots(table)) return false;
|
|
40
40
|
return command(state, dispatch, view);
|
|
41
41
|
};
|
|
42
|
+
const preserveSourceCellIdentity = (command) => (state, dispatch, view) => {
|
|
43
|
+
if (!command(state, void 0, view)) return false;
|
|
44
|
+
if (!dispatch) return true;
|
|
45
|
+
const rect = selectedRect(state);
|
|
46
|
+
const sourceRelativePosition = rect.map.map.at(rect.top * rect.map.width + rect.left);
|
|
47
|
+
if (sourceRelativePosition === void 0) return panic("The selected table cell is absent from its table map");
|
|
48
|
+
const sourceCell = rect.table.nodeAt(sourceRelativePosition);
|
|
49
|
+
if (!sourceCell) return panic("The selected table cell is absent from its table map");
|
|
50
|
+
const sourceId = expectTableCellAttrs(sourceCell)._docxCellId;
|
|
51
|
+
return command(state, (tr) => {
|
|
52
|
+
if (sourceId === void 0 || sourceId === null) {
|
|
53
|
+
dispatch(tr);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const mappedTablePosition = tr.mapping.map(rect.tableStart - 1, -1);
|
|
57
|
+
const table = tr.doc.nodeAt(mappedTablePosition);
|
|
58
|
+
if (!table) return panic("The split-cell transaction lost its table");
|
|
59
|
+
const tableStart = mappedTablePosition + 1;
|
|
60
|
+
const map = TableMap.get(table);
|
|
61
|
+
const survivingRelativePosition = map.map.at(rect.top * map.width + rect.left);
|
|
62
|
+
if (survivingRelativePosition === void 0) return panic("The surviving table cell is absent from its table map");
|
|
63
|
+
const cleared = /* @__PURE__ */ new Set();
|
|
64
|
+
for (let row = rect.top; row < rect.bottom; row++) for (let column = rect.left; column < rect.right; column++) {
|
|
65
|
+
const relativePosition = map.map.at(row * map.width + column);
|
|
66
|
+
if (relativePosition === void 0) return panic("A split table cell is absent from its table map");
|
|
67
|
+
if (relativePosition === survivingRelativePosition || cleared.has(relativePosition)) continue;
|
|
68
|
+
cleared.add(relativePosition);
|
|
69
|
+
const cell = table.nodeAt(relativePosition);
|
|
70
|
+
if (!cell) return panic("A split table cell is absent from its table map");
|
|
71
|
+
tr.setNodeMarkup(tableStart + relativePosition, null, {
|
|
72
|
+
...cell.attrs,
|
|
73
|
+
_docxCellId: null
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
dispatch(tr);
|
|
77
|
+
}, view);
|
|
78
|
+
};
|
|
42
79
|
const isOneOf = (value, values) => value !== null && value !== void 0 && values.some((allowed) => allowed === value);
|
|
43
80
|
/** Map CSS border-style to OOXML border style. */
|
|
44
81
|
function cssBorderStyleToOoxml(cssStyle) {
|
|
@@ -334,6 +371,7 @@ const tableCellSpec = {
|
|
|
334
371
|
tableRole: "cell",
|
|
335
372
|
isolating: true,
|
|
336
373
|
attrs: {
|
|
374
|
+
_docxCellId: { default: null },
|
|
337
375
|
colspan: { default: 1 },
|
|
338
376
|
rowspan: { default: 1 },
|
|
339
377
|
_omittedGridSlot: { default: null },
|
|
@@ -402,6 +440,7 @@ const tableHeaderSpec = {
|
|
|
402
440
|
tableRole: "header_cell",
|
|
403
441
|
isolating: true,
|
|
404
442
|
attrs: {
|
|
443
|
+
_docxCellId: { default: null },
|
|
405
444
|
colspan: { default: 1 },
|
|
406
445
|
rowspan: { default: 1 },
|
|
407
446
|
_omittedGridSlot: { default: null },
|
|
@@ -2004,7 +2043,7 @@ const TablePluginExtension = createExtension({
|
|
|
2004
2043
|
selectRow: () => selectRow,
|
|
2005
2044
|
selectColumn: () => selectColumn,
|
|
2006
2045
|
mergeCells: () => preserveOmittedGridSlots(mergeCells),
|
|
2007
|
-
splitCell: () => preserveOmittedGridSlots(splitCell),
|
|
2046
|
+
splitCell: () => preserveOmittedGridSlots(preserveSourceCellIdentity(splitCell)),
|
|
2008
2047
|
setCellBorder: (side, spec, clearOthers) => setCellBorder(side, spec, clearOthers),
|
|
2009
2048
|
setTableBorders: (preset, borderSpec) => setTableBorders(preset, borderSpec),
|
|
2010
2049
|
setTableBorderPreset: (preset) => setTableBorderPreset(preset),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { decodeOoxmlSymbolCharacter } from "../utils/ooxmlSymbol.js";
|
|
2
2
|
import { expectFieldAttrs, expectPreservedXmlAttrs, expectSymbolAttrs } from "./attrs/index.js";
|
|
3
|
+
import { PRESERVED_XML_LEVELS } from "./schema/nodes.js";
|
|
3
4
|
import { panic } from "better-result";
|
|
4
5
|
import { Mark } from "prosemirror-model";
|
|
5
6
|
//#region src/prosemirror/runFormattingInlineCarriers.ts
|
|
@@ -31,6 +32,22 @@ const RUN_FORMATTING_INLINE_ATOM_DISPOSITIONS = Object.freeze({
|
|
|
31
32
|
textBoxAnchor: "not-a-run"
|
|
32
33
|
});
|
|
33
34
|
const dispositionsByName = new Map(Object.entries(RUN_FORMATTING_INLINE_ATOM_DISPOSITIONS));
|
|
35
|
+
/**
|
|
36
|
+
* One preserved capture is a `w:r` child and the other is a `w:p` child, and
|
|
37
|
+
* the map above can only name the node type.
|
|
38
|
+
*
|
|
39
|
+
* Only the run-level capture serializes inside a `w:r`, so only it has a
|
|
40
|
+
* `w:rPr` to carry; the save path already branches on the same level. A
|
|
41
|
+
* paragraph-level capture is the markup Word writes BETWEEN runs — `w:proofErr`
|
|
42
|
+
* above all — and treating it as a carrier makes every consumer of this map
|
|
43
|
+
* wrong in the same way: formatting marks put on it are dropped on save, and a
|
|
44
|
+
* comparison is asked to line up the base's proofing annotations with the
|
|
45
|
+
* revised document's own, which no redline can do.
|
|
46
|
+
*/
|
|
47
|
+
const PRESERVED_XML_DISPOSITIONS = {
|
|
48
|
+
[PRESERVED_XML_LEVELS.run]: "preserved-xml-run",
|
|
49
|
+
[PRESERVED_XML_LEVELS.inline]: "not-a-run"
|
|
50
|
+
};
|
|
34
51
|
const CONTROL_CHARACTER_BY_DISPOSITION = Object.freeze({
|
|
35
52
|
"break-run": "\n",
|
|
36
53
|
"field-run": null,
|
|
@@ -73,7 +90,7 @@ const runFormattingInlineAtomDisposition = (node) => {
|
|
|
73
90
|
if (!node.isInline || !node.isAtom) return null;
|
|
74
91
|
const disposition = dispositionsByName.get(node.type.name);
|
|
75
92
|
if (!disposition) return panic(`Inline atom ${JSON.stringify(node.type.name)} has no run-formatting disposition`);
|
|
76
|
-
return disposition;
|
|
93
|
+
return disposition === "preserved-xml-run" ? PRESERVED_XML_DISPOSITIONS[expectPreservedXmlAttrs(node).level] : disposition;
|
|
77
94
|
};
|
|
78
95
|
/** Apply a mark set without changing a carrier's text or serialized ownership. */
|
|
79
96
|
const applyMarksToRunFormattingRepresentation = ({ tr, representation, marks }) => {
|
|
@@ -81,6 +81,7 @@ type FootnoteRefAttrs = {
|
|
|
81
81
|
id: string | number;
|
|
82
82
|
noteType?: "footnote" | "endnote";
|
|
83
83
|
vertAlign?: "baseline" | "superscript";
|
|
84
|
+
customMarkFollows?: document_d_exports.NoteReferenceContent["customMarkFollows"];
|
|
84
85
|
};
|
|
85
86
|
type CommentAttrs = {
|
|
86
87
|
commentId: number;
|
|
@@ -271,6 +272,9 @@ type HyperlinkAttrs = {
|
|
|
271
272
|
href: string;
|
|
272
273
|
tooltip?: string;
|
|
273
274
|
rId?: string;
|
|
275
|
+
target?: document_d_exports.Hyperlink["target"];
|
|
276
|
+
history?: document_d_exports.Hyperlink["history"];
|
|
277
|
+
docLocation?: document_d_exports.Hyperlink["docLocation"];
|
|
274
278
|
_docxHyperlinkIndex?: number;
|
|
275
279
|
};
|
|
276
280
|
//#endregion
|
|
@@ -7,6 +7,12 @@ import { ParagraphNumberingAttr } from "../numberingAttr.js";
|
|
|
7
7
|
import { ParagraphDirection } from "../paragraphDirection.js";
|
|
8
8
|
//#region src/prosemirror/schema/nodes.d.ts
|
|
9
9
|
type HardBreakAttrs = {
|
|
10
|
+
sourceElement: "cr";
|
|
11
|
+
breakType?: never;
|
|
12
|
+
clear?: never;
|
|
13
|
+
} | {
|
|
14
|
+
/** Absent and `br` both serialize as the standard break element. */
|
|
15
|
+
sourceElement?: "br";
|
|
10
16
|
/** Absent means the source `w:br` omitted `w:type`. */
|
|
11
17
|
breakType?: "column" | "textWrapping";
|
|
12
18
|
clear?: "none" | "left" | "right" | "all";
|
|
@@ -216,6 +222,9 @@ type ParagraphAttrs = {
|
|
|
216
222
|
anchor?: document_d_exports.Hyperlink["anchor"];
|
|
217
223
|
tooltip?: document_d_exports.Hyperlink["tooltip"];
|
|
218
224
|
rId?: document_d_exports.Hyperlink["rId"];
|
|
225
|
+
target?: document_d_exports.Hyperlink["target"];
|
|
226
|
+
history?: document_d_exports.Hyperlink["history"];
|
|
227
|
+
docLocation?: document_d_exports.Hyperlink["docLocation"];
|
|
219
228
|
}[];
|
|
220
229
|
/**
|
|
221
230
|
* Run-in heading flag: this paragraph's mark carries
|
|
@@ -1056,6 +1065,8 @@ type SuggestedStructuralMarker = {
|
|
|
1056
1065
|
* Table cell attributes
|
|
1057
1066
|
*/
|
|
1058
1067
|
type TableCellAttrs = {
|
|
1068
|
+
/** Authored OOXML cell identifier. */
|
|
1069
|
+
_docxCellId?: document_d_exports.TableCell["id"];
|
|
1059
1070
|
/** Column span */
|
|
1060
1071
|
colspan: number;
|
|
1061
1072
|
/** Row span */
|
|
@@ -5,7 +5,7 @@ type TablePropertiesCommand = {
|
|
|
5
5
|
widthType?: document_d_exports.TableWidthType | null;
|
|
6
6
|
justification?: document_d_exports.TableAlignment | null;
|
|
7
7
|
};
|
|
8
|
-
declare const TABLE_PROPERTY_JUSTIFICATIONS: readonly
|
|
8
|
+
declare const TABLE_PROPERTY_JUSTIFICATIONS: readonly document_d_exports.TableAlignment[];
|
|
9
9
|
declare const toTablePropertyJustification: (value: string | null | undefined) => NonNullable<TablePropertiesCommand["justification"]>;
|
|
10
10
|
type TableAction = "addRowAbove" | "addRowBelow" | "addColumnLeft" | "addColumnRight" | "deleteRow" | "deleteColumn" | "mergeCells" | "splitCell" | "deleteTable" | "selectTable" | "selectRow" | "selectColumn" | "borderAll" | "borderOutside" | "borderInside" | "borderNone" | "borderTop" | "borderBottom" | "borderLeft" | "borderRight" | {
|
|
11
11
|
type: "cellFillColor";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stll/folio-core",
|
|
3
|
-
"version": "0.47.
|
|
3
|
+
"version": "0.47.2",
|
|
4
4
|
"description": "Headless, framework-neutral core of folio: the OOXML (.docx) parser, document model, ProseMirror integration, and page-layout engine. No React.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"document-model",
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
"perf": "bun scripts/profile-editor.ts"
|
|
129
129
|
},
|
|
130
130
|
"dependencies": {
|
|
131
|
-
"@stll/docx-core": "^0.25.
|
|
131
|
+
"@stll/docx-core": "^0.25.1",
|
|
132
132
|
"@stll/docx-utils": "^0.1.0",
|
|
133
133
|
"@stll/template-conditions": ">=0.4.0 <1.0.0",
|
|
134
134
|
"better-result": "3.0.1",
|