@stll/folio-core 0.27.1 → 0.28.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/docx/server/extractDocxText.js +108 -33
- package/dist/docx/server/materializeYjsDocx.d.ts +31 -0
- package/dist/docx/server/materializeYjsDocx.js +61 -0
- package/dist/docx/styleParser.js +15 -14
- package/dist/layout-bridge/convert/toFlowBlocks.js +74 -23
- package/dist/layout-engine/footnoteColumnReflow.d.ts +15 -0
- package/dist/layout-engine/footnoteColumnReflow.js +74 -0
- package/dist/layout-engine/index.d.ts +3 -5
- package/dist/layout-engine/index.js +36 -15
- package/dist/layout-engine/measure/cache.d.ts +1 -1
- package/dist/layout-engine/measure/cache.js +11 -2
- package/dist/layout-engine/measure/listMarkerWidth.d.ts +3 -1
- package/dist/layout-engine/measure/listMarkerWidth.js +6 -4
- package/dist/layout-engine/paginator.d.ts +6 -0
- package/dist/layout-engine/paginator.js +30 -11
- package/dist/layout-engine/types.d.ts +11 -6
- package/dist/prosemirror/attrs/index.js +3 -2
- package/dist/prosemirror/commands/formatPainter.js +45 -1
- package/dist/prosemirror/conversion/fromProseDoc.d.ts +4 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +59 -44
- package/dist/prosemirror/conversion/toProseDoc.d.ts +4 -1
- package/dist/prosemirror/conversion/toProseDoc.js +156 -33
- package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.js +22 -22
- package/dist/prosemirror/schema/marks.d.ts +3 -1
- package/dist/prosemirror/styles/styleResolver.d.ts +0 -1
- package/dist/prosemirror/styles/styleResolver.js +22 -29
- package/dist/prosemirror/styles/styleToggleCascade.d.ts +37 -0
- package/dist/prosemirror/styles/styleToggleCascade.js +52 -0
- package/dist/server.d.ts +2 -1
- package/dist/server.js +2 -1
- package/dist/utils/textFormattingMerge.d.ts +9 -1
- package/dist/utils/textFormattingMerge.js +32 -1
- package/package.json +2 -2
|
@@ -8,6 +8,7 @@ import { applyRunFormattingOverrideAttrs } from "../extensions/marks/RunFormatti
|
|
|
8
8
|
import { directionToBidi } from "../paragraphDirection.js";
|
|
9
9
|
import { RUN_FORMATTING_MARK_NAMES } from "../runFormattingMarkNames.js";
|
|
10
10
|
import { parseShapeGeometryAdjustments } from "../shapeGeometryAdjustments.js";
|
|
11
|
+
import { cascadeStyleTextFormatting } from "../styles/styleToggleCascade.js";
|
|
11
12
|
import { expectTextBoxAnchorAttrs } from "../textBoxAnchorAttrs.js";
|
|
12
13
|
import { assertValidProseMirrorDocument } from "../validation.js";
|
|
13
14
|
import { runShadingAttrsToShading } from "./runShadingMark.js";
|
|
@@ -647,6 +648,7 @@ function paragraphAttrsToFormatting(attrs) {
|
|
|
647
648
|
*/
|
|
648
649
|
function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, textBoxAnchorMarkers, skipLeadingRenderedPageBreak = false) {
|
|
649
650
|
const content = [];
|
|
651
|
+
const inheritedFormatting = paragraph.type.name === "paragraph" ? expectParagraphAttrs(paragraph).defaultTextFormatting ?? void 0 : void 0;
|
|
650
652
|
const sortedEmptyHyperlinks = (emptyHyperlinks ?? []).map((attrs, order) => ({
|
|
651
653
|
attrs,
|
|
652
654
|
order
|
|
@@ -763,7 +765,12 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
|
|
|
763
765
|
const changeMark = insertionMark ?? deletionMark;
|
|
764
766
|
if (!changeMark) return;
|
|
765
767
|
const changeAttrs = expectTrackedChangeMarkAttrs(changeMark);
|
|
766
|
-
const
|
|
768
|
+
const otherMarks = node.marks.filter((m) => m.type.name !== "insertion" && m.type.name !== "deletion");
|
|
769
|
+
const run = createTrackedChangeRun({
|
|
770
|
+
inheritedFormatting,
|
|
771
|
+
marks: otherMarks,
|
|
772
|
+
node
|
|
773
|
+
});
|
|
767
774
|
if (!run) return;
|
|
768
775
|
const trackedContent = linkMark ? {
|
|
769
776
|
...createHyperlink(linkMark),
|
|
@@ -809,7 +816,11 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
|
|
|
809
816
|
currentHyperlink = createHyperlink(linkMark);
|
|
810
817
|
currentHyperlinkKey = linkKey;
|
|
811
818
|
}
|
|
812
|
-
addNodeToHyperlink(
|
|
819
|
+
addNodeToHyperlink({
|
|
820
|
+
hyperlink: currentHyperlink,
|
|
821
|
+
inheritedFormatting,
|
|
822
|
+
node
|
|
823
|
+
});
|
|
813
824
|
return;
|
|
814
825
|
}
|
|
815
826
|
if (currentHyperlink) flushCurrentInline();
|
|
@@ -818,7 +829,11 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
|
|
|
818
829
|
if (currentRun && currentMarksKey === marksKey) appendTextToRun(currentRun, node.text || "");
|
|
819
830
|
else {
|
|
820
831
|
if (currentRun) content.push(currentRun);
|
|
821
|
-
currentRun = createRunFromText(
|
|
832
|
+
currentRun = createRunFromText({
|
|
833
|
+
inheritedFormatting,
|
|
834
|
+
marks: node.marks,
|
|
835
|
+
text: node.text || ""
|
|
836
|
+
});
|
|
822
837
|
currentMarksKey = marksKey;
|
|
823
838
|
}
|
|
824
839
|
} else if (node.type.name === "symbol") {
|
|
@@ -880,11 +895,11 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, te
|
|
|
880
895
|
});
|
|
881
896
|
return content;
|
|
882
897
|
}
|
|
883
|
-
function createTrackedChangeRun(
|
|
898
|
+
function createTrackedChangeRun({ inheritedFormatting, marks, node }) {
|
|
884
899
|
const noteRefMark = marks.find((mark) => mark.type.name === "footnoteRef");
|
|
885
900
|
if (noteRefMark) return createNoteReferenceRun(noteRefMark, marks);
|
|
886
901
|
if (node.isText) {
|
|
887
|
-
const formatting = marksToTextFormatting(marks);
|
|
902
|
+
const formatting = marksToTextFormatting(marks, { inheritedFormatting });
|
|
888
903
|
const run = {
|
|
889
904
|
type: "run",
|
|
890
905
|
content: node.text ? [{
|
|
@@ -989,10 +1004,7 @@ function createHyperlink(linkMark) {
|
|
|
989
1004
|
if (attrs.rId) hyperlink.rId = attrs.rId;
|
|
990
1005
|
return hyperlink;
|
|
991
1006
|
}
|
|
992
|
-
|
|
993
|
-
* Add a node to a hyperlink
|
|
994
|
-
*/
|
|
995
|
-
function addNodeToHyperlink(hyperlink, node) {
|
|
1007
|
+
function addNodeToHyperlink({ hyperlink, inheritedFormatting, node }) {
|
|
996
1008
|
const noteRefMark = node.marks.find((m) => m.type.name === "footnoteRef");
|
|
997
1009
|
if (noteRefMark) {
|
|
998
1010
|
hyperlink.children.push(createNoteReferenceRun(noteRefMark, node.marks));
|
|
@@ -1000,7 +1012,11 @@ function addNodeToHyperlink(hyperlink, node) {
|
|
|
1000
1012
|
}
|
|
1001
1013
|
const nonLinkMarks = node.marks.filter((m) => m.type.name !== "hyperlink");
|
|
1002
1014
|
if (node.isText && node.text) {
|
|
1003
|
-
const run = createRunFromText(
|
|
1015
|
+
const run = createRunFromText({
|
|
1016
|
+
inheritedFormatting,
|
|
1017
|
+
marks: nonLinkMarks,
|
|
1018
|
+
text: node.text
|
|
1019
|
+
});
|
|
1004
1020
|
hyperlink.children.push(run);
|
|
1005
1021
|
return;
|
|
1006
1022
|
}
|
|
@@ -1044,11 +1060,8 @@ function createNoteReferenceRun(noteRefMark, marks) {
|
|
|
1044
1060
|
if (vertAlign) run.formatting = { vertAlign };
|
|
1045
1061
|
return run;
|
|
1046
1062
|
}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
*/
|
|
1050
|
-
function createRunFromText(text, marks) {
|
|
1051
|
-
const formatting = getRunFormattingFromMarks(marks);
|
|
1063
|
+
function createRunFromText({ inheritedFormatting, marks, text }) {
|
|
1064
|
+
const formatting = getRunFormattingFromMarks(marks, { inheritedFormatting });
|
|
1052
1065
|
const run = {
|
|
1053
1066
|
type: "run",
|
|
1054
1067
|
content: [{
|
|
@@ -1082,9 +1095,9 @@ function restoreRunPropertyChanges(run, marks) {
|
|
|
1082
1095
|
if (changes.length === 0) return;
|
|
1083
1096
|
run.propertyChanges = [...changes];
|
|
1084
1097
|
}
|
|
1085
|
-
function getRunFormattingFromMarks(marks) {
|
|
1098
|
+
function getRunFormattingFromMarks(marks, options) {
|
|
1086
1099
|
if (!marks || marks.length === 0) return;
|
|
1087
|
-
const formatting = marksToTextFormatting(marks);
|
|
1100
|
+
const formatting = marksToTextFormatting(marks, options);
|
|
1088
1101
|
return Object.keys(formatting).length > 0 ? formatting : void 0;
|
|
1089
1102
|
}
|
|
1090
1103
|
/**
|
|
@@ -1354,11 +1367,9 @@ function createShapeRun(node) {
|
|
|
1354
1367
|
}]
|
|
1355
1368
|
};
|
|
1356
1369
|
}
|
|
1357
|
-
|
|
1358
|
-
* Convert ProseMirror marks to TextFormatting
|
|
1359
|
-
*/
|
|
1360
|
-
function marksToTextFormatting(marks) {
|
|
1370
|
+
function marksToTextFormatting(marks, options) {
|
|
1361
1371
|
const formatting = {};
|
|
1372
|
+
let directOverrideFormatting;
|
|
1362
1373
|
let characterStyleRPr;
|
|
1363
1374
|
let runFormattingOverrideMark;
|
|
1364
1375
|
for (const mark of marks) switch (mark.type.name) {
|
|
@@ -1483,8 +1494,18 @@ function marksToTextFormatting(marks) {
|
|
|
1483
1494
|
}
|
|
1484
1495
|
default: break;
|
|
1485
1496
|
}
|
|
1486
|
-
if (runFormattingOverrideMark)
|
|
1487
|
-
|
|
1497
|
+
if (runFormattingOverrideMark) {
|
|
1498
|
+
const overrideAttrs = expectRunFormattingOverrideMarkAttrs(runFormattingOverrideMark);
|
|
1499
|
+
applyRunFormattingOverrideAttrs(formatting, overrideAttrs);
|
|
1500
|
+
directOverrideFormatting = {};
|
|
1501
|
+
applyRunFormattingOverrideAttrs(directOverrideFormatting, overrideAttrs);
|
|
1502
|
+
}
|
|
1503
|
+
if (characterStyleRPr) return subtractCharacterStyleFormatting({
|
|
1504
|
+
directOverrideFormatting,
|
|
1505
|
+
formatting,
|
|
1506
|
+
inheritedFormatting: options?.inheritedFormatting,
|
|
1507
|
+
styleRPr: characterStyleRPr
|
|
1508
|
+
});
|
|
1488
1509
|
return formatting;
|
|
1489
1510
|
}
|
|
1490
1511
|
/**
|
|
@@ -1509,35 +1530,29 @@ const NEGATABLE_STYLE_KEYS = [
|
|
|
1509
1530
|
["outline", null],
|
|
1510
1531
|
["rtl", null]
|
|
1511
1532
|
];
|
|
1512
|
-
|
|
1513
|
-
* Drop run formatting values that the run's character style already provides
|
|
1514
|
-
* (the `w:rStyle` reference re-imposes them on load), so a styled run
|
|
1515
|
-
* serializes back to a style reference instead of baked direct formatting.
|
|
1516
|
-
*
|
|
1517
|
-
* `styleRPr` is the load-time snapshot from the characterStyle mark, captured
|
|
1518
|
-
* in the same normal form this module produces from marks, so value equality
|
|
1519
|
-
* is a faithful "came from the style and is unchanged" check. Values that
|
|
1520
|
-
* differ (user edits, direct overrides from the source document) stay as
|
|
1521
|
-
* direct formatting, which wins over the style per the OOXML cascade.
|
|
1522
|
-
*
|
|
1523
|
-
* When the user *removes* a boolean property the style supplied (e.g. toggling
|
|
1524
|
-
* off bold on text whose `w:rStyle` is bold), that key is no longer present in
|
|
1525
|
-
* `formatting`, so the subtraction loop above never sees it. Without a counter,
|
|
1526
|
-
* the run keeps the style reference and Word re-applies the removed formatting
|
|
1527
|
-
* on load. The second pass emits an explicit negative override (`false`) for
|
|
1528
|
-
* each negatable boolean the style set to `true` but the run no longer carries.
|
|
1529
|
-
*/
|
|
1530
|
-
function subtractCharacterStyleFormatting(formatting, styleRPr) {
|
|
1533
|
+
function subtractCharacterStyleFormatting({ directOverrideFormatting, formatting, inheritedFormatting, styleRPr }) {
|
|
1531
1534
|
const result = {};
|
|
1535
|
+
const effectiveStyleFormatting = cascadeStyleTextFormatting([{
|
|
1536
|
+
formatting: inheritedFormatting,
|
|
1537
|
+
type: "direct"
|
|
1538
|
+
}, {
|
|
1539
|
+
formatting: styleRPr,
|
|
1540
|
+
type: "style"
|
|
1541
|
+
}]).formatting;
|
|
1532
1542
|
for (const key of Object.keys(formatting)) {
|
|
1533
1543
|
const value = formatting[key];
|
|
1534
1544
|
if (value === void 0) continue;
|
|
1535
|
-
|
|
1545
|
+
if (directOverrideFormatting?.[key] !== void 0) {
|
|
1546
|
+
result[key] = value;
|
|
1547
|
+
continue;
|
|
1548
|
+
}
|
|
1549
|
+
const styleValue = key === "styleId" ? void 0 : effectiveStyleFormatting?.[key];
|
|
1550
|
+
if ((key === "boldCs" || key === "italicCs") && styleValue === false && value === true) continue;
|
|
1536
1551
|
if (styleValue !== void 0 && JSON.stringify(value) === JSON.stringify(styleValue)) continue;
|
|
1537
1552
|
result[key] = value;
|
|
1538
1553
|
}
|
|
1539
1554
|
for (const [key, csKey] of NEGATABLE_STYLE_KEYS) {
|
|
1540
|
-
if (
|
|
1555
|
+
if (effectiveStyleFormatting?.[key] !== true || formatting[key] !== void 0) continue;
|
|
1541
1556
|
result[key] = false;
|
|
1542
1557
|
if (csKey !== null) result[csKey] = false;
|
|
1543
1558
|
}
|
|
@@ -22,7 +22,10 @@ declare function standaloneTableCellToProseMirror(cell: document_d_exports.Table
|
|
|
22
22
|
/**
|
|
23
23
|
* Convert TextFormatting to ProseMirror marks
|
|
24
24
|
*/
|
|
25
|
-
|
|
25
|
+
type TextFormattingToMarksOptions = {
|
|
26
|
+
overrideFormatting: document_d_exports.TextFormatting | undefined;
|
|
27
|
+
};
|
|
28
|
+
declare function textFormattingToMarks(formatting: document_d_exports.TextFormatting | undefined, options?: TextFormattingToMarksOptions): ReturnType<typeof schema.mark>[];
|
|
26
29
|
/**
|
|
27
30
|
* Convert HeaderFooter content (array of Paragraph/Table blocks) to a ProseMirror document.
|
|
28
31
|
* Used for editing headers/footers in their own ProseMirror editor and for
|
|
@@ -8,6 +8,7 @@ import { setAutospacingBaseValue } from "../autospacingBase.js";
|
|
|
8
8
|
import { buildRunFormattingOverrideAttrs } from "../extensions/marks/RunFormattingOverrideExtension.js";
|
|
9
9
|
import { directionFromBidi } from "../paragraphDirection.js";
|
|
10
10
|
import { schema } from "../schema/index.js";
|
|
11
|
+
import { cascadeStyleTextFormatting } from "../styles/styleToggleCascade.js";
|
|
11
12
|
import { assertValidProseMirrorDocument } from "../validation.js";
|
|
12
13
|
import { resolveEffectiveTableCellFormatting } from "./effectiveTableCellFormatting.js";
|
|
13
14
|
import { marksToTextFormatting } from "./fromProseDoc.js";
|
|
@@ -144,22 +145,66 @@ function convertParagraph(paragraph, styleResolver, nextHyperlinkInstanceIndex,
|
|
|
144
145
|
emitInlineNodes([node]);
|
|
145
146
|
};
|
|
146
147
|
let styleRunFormatting;
|
|
148
|
+
let paragraphStyleRunFormatting;
|
|
147
149
|
let paragraphStyleFontFamily;
|
|
148
150
|
if (styleResolver) {
|
|
149
151
|
styleRunFormatting = styleResolver.resolveParagraphStyle(paragraph.formatting?.styleId).runFormatting;
|
|
152
|
+
const paragraphStyle = paragraph.formatting?.styleId ? styleResolver.getStyle(paragraph.formatting.styleId) ?? styleResolver.getDefaultParagraphStyle() : styleResolver.getDefaultParagraphStyle();
|
|
153
|
+
paragraphStyleRunFormatting = paragraphStyle?.type === "paragraph" ? paragraphStyle.rPr : void 0;
|
|
150
154
|
paragraphStyleFontFamily = resolveParagraphStyleFontFamily(paragraph.formatting?.styleId, styleResolver);
|
|
151
155
|
}
|
|
152
156
|
const paragraphRunFormatting = resolveRunFormattingWithoutDefaults(paragraph.formatting?.runProperties, styleResolver);
|
|
153
157
|
let inheritableParagraphRunFormatting;
|
|
154
158
|
if (paragraphRunFormatting && !isTocParagraph) inheritableParagraphRunFormatting = stripParagraphMarkFormattingForBodyRuns(paragraphRunFormatting);
|
|
155
|
-
|
|
159
|
+
const orderedToggleFormatting = cascadeStyleTextFormatting([
|
|
160
|
+
{
|
|
161
|
+
formatting: styleResolver?.getDocDefaults()?.rPr,
|
|
162
|
+
type: "defaults"
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
formatting: extraRunFormatting,
|
|
166
|
+
type: "style"
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
formatting: paragraphStyleRunFormatting,
|
|
170
|
+
type: "style"
|
|
171
|
+
}
|
|
172
|
+
], { ordinaryFormatting: mergeTextFormatting(styleRunFormatting, extraRunFormatting) });
|
|
173
|
+
let baseRunFormatting = orderedToggleFormatting.formatting;
|
|
156
174
|
if (paragraphStyleFontFamily) baseRunFormatting = mergeTextFormatting(baseRunFormatting, { fontFamily: paragraphStyleFontFamily });
|
|
157
175
|
const paragraphMarkPrecedesStyle = paragraph.formatting?.styleId !== void 0;
|
|
158
|
-
const
|
|
176
|
+
const ordinaryDefaultRunFormatting = paragraphMarkPrecedesStyle ? mergeTextFormatting(inheritableParagraphRunFormatting, baseRunFormatting) : mergeTextFormatting(baseRunFormatting, inheritableParagraphRunFormatting);
|
|
177
|
+
const defaultToggleCascade = paragraphMarkPrecedesStyle ? cascadeStyleTextFormatting([{
|
|
178
|
+
cascade: orderedToggleFormatting,
|
|
179
|
+
type: "carried"
|
|
180
|
+
}], { ordinaryFormatting: ordinaryDefaultRunFormatting }) : cascadeStyleTextFormatting([{
|
|
181
|
+
cascade: orderedToggleFormatting,
|
|
182
|
+
type: "carried"
|
|
183
|
+
}, {
|
|
184
|
+
formatting: inheritableParagraphRunFormatting,
|
|
185
|
+
type: "direct"
|
|
186
|
+
}], { ordinaryFormatting: ordinaryDefaultRunFormatting });
|
|
187
|
+
const defaultRunFormatting = defaultToggleCascade.formatting;
|
|
159
188
|
const getInheritedRunFormatting = (formatting, fieldType) => {
|
|
160
|
-
if (fieldType === "TOC") return
|
|
161
|
-
|
|
162
|
-
|
|
189
|
+
if (fieldType === "TOC") return {
|
|
190
|
+
formatting: hasDirectRunFormatting(formatting) ? suppressParagraphMarkFormatting(baseRunFormatting, void 0, formatting) : baseRunFormatting,
|
|
191
|
+
toggleCascade: orderedToggleFormatting
|
|
192
|
+
};
|
|
193
|
+
if (!(hasDirectRunFormatting(formatting) || formatting?.styleId !== void 0)) return {
|
|
194
|
+
formatting: defaultRunFormatting,
|
|
195
|
+
toggleCascade: defaultToggleCascade
|
|
196
|
+
};
|
|
197
|
+
const suppressedFormatting = suppressParagraphMarkFormatting(baseRunFormatting, inheritableParagraphRunFormatting, formatting, paragraphMarkPrecedesStyle);
|
|
198
|
+
const paragraphMarkOverrides = getParagraphMarkSuppressionOverrides({
|
|
199
|
+
directFormatting: formatting,
|
|
200
|
+
paragraphMarkFormatting: inheritableParagraphRunFormatting,
|
|
201
|
+
suppressedFormatting
|
|
202
|
+
});
|
|
203
|
+
return {
|
|
204
|
+
formatting: suppressedFormatting,
|
|
205
|
+
...paragraphMarkOverrides ? { paragraphMarkOverrides } : {},
|
|
206
|
+
toggleCascade: orderedToggleFormatting
|
|
207
|
+
};
|
|
163
208
|
};
|
|
164
209
|
const emitTrackedChange = (change, markType, moveKind) => {
|
|
165
210
|
emitInlineNodes(convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, getInheritedRunFormatting, styleResolver, moveKind, textBoxAnchors));
|
|
@@ -499,27 +544,37 @@ function stripParagraphMarkFormattingForBodyRuns(formatting) {
|
|
|
499
544
|
const { fontFamily: _fontFamily, ...bodyRunFormatting } = paragraphMarkFormatting;
|
|
500
545
|
return Object.keys(bodyRunFormatting).length > 0 ? bodyRunFormatting : void 0;
|
|
501
546
|
}
|
|
547
|
+
const PARAGRAPH_MARK_BOOLEAN_KEYS = [
|
|
548
|
+
"bold",
|
|
549
|
+
"italic",
|
|
550
|
+
"strike",
|
|
551
|
+
"doubleStrike",
|
|
552
|
+
"allCaps",
|
|
553
|
+
"smallCaps",
|
|
554
|
+
"hidden",
|
|
555
|
+
"emboss",
|
|
556
|
+
"imprint",
|
|
557
|
+
"shadow",
|
|
558
|
+
"outline",
|
|
559
|
+
"rtl"
|
|
560
|
+
];
|
|
502
561
|
function suppressParagraphMarkFormatting(base, paragraphMark, direct, paragraphMarkPrecedesStyle = false) {
|
|
503
562
|
if (!paragraphMark) return base;
|
|
504
563
|
const result = (paragraphMarkPrecedesStyle ? mergeTextFormatting(paragraphMark, base) : mergeTextFormatting(base, paragraphMark)) ?? {};
|
|
505
|
-
suppressBooleanParagraphMark(result, base, paragraphMark, direct,
|
|
506
|
-
suppressBooleanParagraphMark(result, base, paragraphMark, direct, "italic");
|
|
507
|
-
suppressBooleanParagraphMark(result, base, paragraphMark, direct, "strike");
|
|
508
|
-
suppressBooleanParagraphMark(result, base, paragraphMark, direct, "doubleStrike");
|
|
509
|
-
suppressBooleanParagraphMark(result, base, paragraphMark, direct, "allCaps");
|
|
510
|
-
suppressBooleanParagraphMark(result, base, paragraphMark, direct, "smallCaps");
|
|
511
|
-
suppressBooleanParagraphMark(result, base, paragraphMark, direct, "hidden");
|
|
512
|
-
suppressBooleanParagraphMark(result, base, paragraphMark, direct, "emboss");
|
|
513
|
-
suppressBooleanParagraphMark(result, base, paragraphMark, direct, "imprint");
|
|
514
|
-
suppressBooleanParagraphMark(result, base, paragraphMark, direct, "shadow");
|
|
515
|
-
suppressBooleanParagraphMark(result, base, paragraphMark, direct, "outline");
|
|
516
|
-
suppressBooleanParagraphMark(result, base, paragraphMark, direct, "rtl");
|
|
564
|
+
for (const key of PARAGRAPH_MARK_BOOLEAN_KEYS) suppressBooleanParagraphMark(result, base, paragraphMark, direct, key);
|
|
517
565
|
if (paragraphMark.fontSize !== void 0 && direct?.fontSize === void 0 && base?.fontSize !== void 0) result.fontSize = base.fontSize;
|
|
518
566
|
if (paragraphMark.fontSizeCs !== void 0 && direct?.fontSizeCs === void 0 && base?.fontSizeCs !== void 0) result.fontSizeCs = base.fontSizeCs;
|
|
519
567
|
if (paragraphMark.underline !== void 0 && direct?.underline === void 0) result.underline = { style: "none" };
|
|
520
568
|
if (paragraphMark.spacing !== void 0 && direct?.spacing === void 0) result.spacing = 0;
|
|
521
569
|
return Object.keys(result).length > 0 ? result : void 0;
|
|
522
570
|
}
|
|
571
|
+
function getParagraphMarkSuppressionOverrides({ directFormatting, paragraphMarkFormatting, suppressedFormatting }) {
|
|
572
|
+
if (!paragraphMarkFormatting) return;
|
|
573
|
+
const overrides = {};
|
|
574
|
+
for (const key of PARAGRAPH_MARK_BOOLEAN_KEYS) if (paragraphMarkFormatting[key] !== void 0 && directFormatting?.[key] === void 0 && suppressedFormatting?.[key] === false) overrides[key] = false;
|
|
575
|
+
if (paragraphMarkFormatting.underline !== void 0 && directFormatting?.underline === void 0 && suppressedFormatting?.underline?.style === "none") overrides.underline = { style: "none" };
|
|
576
|
+
return Object.keys(overrides).length > 0 ? overrides : void 0;
|
|
577
|
+
}
|
|
523
578
|
function suppressBooleanParagraphMark(result, base, paragraphMark, direct, key) {
|
|
524
579
|
if (paragraphMark[key] === void 0 || direct?.[key] !== void 0) return;
|
|
525
580
|
result[key] = base?.[key] ?? false;
|
|
@@ -536,15 +591,45 @@ function resolveTextFormatting(formatting, styleResolver) {
|
|
|
536
591
|
*/
|
|
537
592
|
function resolveRunFormattingWithoutDefaults(formatting, styleResolver) {
|
|
538
593
|
if (!formatting || !styleResolver) return formatting;
|
|
539
|
-
return
|
|
594
|
+
return cascadeStyleTextFormatting([{
|
|
595
|
+
formatting: formatting.styleId ? styleResolver.getRunStyleOwnProperties(formatting.styleId) : void 0,
|
|
596
|
+
type: "style"
|
|
597
|
+
}, {
|
|
598
|
+
formatting,
|
|
599
|
+
type: "direct"
|
|
600
|
+
}]).formatting;
|
|
540
601
|
}
|
|
541
602
|
function resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver, options = {}) {
|
|
542
603
|
const style = styleId ? styleResolver.getStyle(styleId) ?? styleResolver.getDefaultParagraphStyle() : styleResolver.getDefaultParagraphStyle();
|
|
543
604
|
const paragraphStyleRpr = style?.type === "paragraph" ? style.rPr : void 0;
|
|
544
605
|
const rawParagraphMarkRpr = options.includeParagraphMarkRunProperties === false ? void 0 : formatting?.runProperties;
|
|
545
606
|
const paragraphRunProperties = rawParagraphMarkRpr ? stripParagraphMarkOnlyFormatting(resolveRunFormattingWithoutDefaults(rawParagraphMarkRpr, styleResolver) ?? {}) : void 0;
|
|
546
|
-
const
|
|
547
|
-
|
|
607
|
+
const orderedBodyToggleFormatting = cascadeStyleTextFormatting([
|
|
608
|
+
{
|
|
609
|
+
formatting: styleResolver.getDocDefaults()?.rPr,
|
|
610
|
+
type: "defaults"
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
formatting: paragraphStyleRpr,
|
|
614
|
+
type: "style"
|
|
615
|
+
},
|
|
616
|
+
{
|
|
617
|
+
formatting: styleResolver.getDefaultCharacterStyle()?.rPr,
|
|
618
|
+
type: "style"
|
|
619
|
+
}
|
|
620
|
+
], { ordinaryFormatting: mergeTextFormatting(mergeTextFormatting(styleResolver.getDocDefaults()?.rPr, styleResolver.getDefaultCharacterStyle()?.rPr), paragraphStyleRpr) });
|
|
621
|
+
const bodyRunDefaults = orderedBodyToggleFormatting.formatting;
|
|
622
|
+
if (styleId !== void 0) return cascadeStyleTextFormatting([{
|
|
623
|
+
cascade: orderedBodyToggleFormatting,
|
|
624
|
+
type: "carried"
|
|
625
|
+
}], { ordinaryFormatting: mergeTextFormatting(paragraphRunProperties, bodyRunDefaults) }).formatting;
|
|
626
|
+
return cascadeStyleTextFormatting([{
|
|
627
|
+
cascade: orderedBodyToggleFormatting,
|
|
628
|
+
type: "carried"
|
|
629
|
+
}, {
|
|
630
|
+
formatting: paragraphRunProperties,
|
|
631
|
+
type: "direct"
|
|
632
|
+
}], { ordinaryFormatting: mergeTextFormatting(bodyRunDefaults, paragraphRunProperties) }).formatting;
|
|
548
633
|
}
|
|
549
634
|
function calculateRowSpans(table) {
|
|
550
635
|
const result = /* @__PURE__ */ new Map();
|
|
@@ -1012,11 +1097,11 @@ function convertInlineSdt(sdt, nextHyperlinkInstanceIndex, getInheritedRunFormat
|
|
|
1012
1097
|
* Convert a Run to ProseMirror text nodes with marks
|
|
1013
1098
|
*
|
|
1014
1099
|
* @param run - The run to convert
|
|
1015
|
-
* @param
|
|
1100
|
+
* @param resolvedStyleFormatting - Paragraph formatting and its explicit style-toggle state
|
|
1016
1101
|
*/
|
|
1017
|
-
function convertRun(run,
|
|
1102
|
+
function convertRun(run, resolvedStyleFormatting, styleResolver, textBoxAnchors) {
|
|
1018
1103
|
const nodes = [];
|
|
1019
|
-
const { marks, mergedFormatting } = buildRunMarks(run.formatting,
|
|
1104
|
+
const { marks, mergedFormatting } = buildRunMarks(run.formatting, resolvedStyleFormatting, styleResolver);
|
|
1020
1105
|
if (run.propertyChanges && run.propertyChanges.length > 0) marks.push(schema.mark("runPropertyChange", { changes: [...run.propertyChanges] }));
|
|
1021
1106
|
for (const content of run.content) {
|
|
1022
1107
|
const contentNodes = convertRunContent(content, marks, mergedFormatting, textBoxAnchors);
|
|
@@ -1024,13 +1109,34 @@ function convertRun(run, styleFormatting, styleResolver, textBoxAnchors) {
|
|
|
1024
1109
|
}
|
|
1025
1110
|
return nodes;
|
|
1026
1111
|
}
|
|
1027
|
-
function buildRunMarks(runFormatting,
|
|
1112
|
+
function buildRunMarks(runFormatting, inherited, styleResolver) {
|
|
1028
1113
|
const styleId = runFormatting?.styleId;
|
|
1029
|
-
const
|
|
1030
|
-
|
|
1031
|
-
|
|
1114
|
+
const characterStyleFormatting = styleId ? styleResolver?.getRunStyleOwnProperties(styleId) : styleResolver?.getDefaultCharacterStyle()?.rPr;
|
|
1115
|
+
let ordinaryRunStyleFormatting = inherited.formatting ? { ...inherited.formatting } : {};
|
|
1116
|
+
if (styleId) ordinaryRunStyleFormatting = mergeTextFormatting(inherited.formatting, characterStyleFormatting) ?? {};
|
|
1117
|
+
const cascadedStyleFormatting = cascadeStyleTextFormatting([{
|
|
1118
|
+
cascade: inherited.toggleCascade,
|
|
1119
|
+
type: "carried"
|
|
1120
|
+
}, {
|
|
1121
|
+
formatting: characterStyleFormatting,
|
|
1122
|
+
type: "style"
|
|
1123
|
+
}], { ordinaryFormatting: ordinaryRunStyleFormatting });
|
|
1124
|
+
const runStyleFormatting = cascadedStyleFormatting.formatting;
|
|
1125
|
+
const mergedFormatting = cascadeStyleTextFormatting([{
|
|
1126
|
+
cascade: cascadedStyleFormatting,
|
|
1127
|
+
type: "carried"
|
|
1128
|
+
}, {
|
|
1129
|
+
formatting: runFormatting,
|
|
1130
|
+
type: "direct"
|
|
1131
|
+
}], { ordinaryFormatting: mergeTextFormatting(runStyleFormatting, runFormatting) }).formatting;
|
|
1132
|
+
const marks = textFormattingToMarks(mergedFormatting, { overrideFormatting: getRunFormattingOverrides({
|
|
1133
|
+
directFormatting: runFormatting,
|
|
1134
|
+
effectiveStyleFormatting: runStyleFormatting,
|
|
1135
|
+
hasCharacterStyle: styleId !== void 0,
|
|
1136
|
+
paragraphMarkOverrides: inherited.paragraphMarkOverrides
|
|
1137
|
+
}) });
|
|
1032
1138
|
if (styleId) {
|
|
1033
|
-
const styleRPr =
|
|
1139
|
+
const styleRPr = characterStyleFormatting ? marksToTextFormatting(textFormattingToMarks(characterStyleFormatting)) : void 0;
|
|
1034
1140
|
marks.push(schema.mark("characterStyle", {
|
|
1035
1141
|
styleId,
|
|
1036
1142
|
_styleRPr: styleRPr && Object.keys(styleRPr).length > 0 ? styleRPr : null
|
|
@@ -1041,6 +1147,26 @@ function buildRunMarks(runFormatting, inheritedFormatting, styleResolver) {
|
|
|
1041
1147
|
mergedFormatting
|
|
1042
1148
|
};
|
|
1043
1149
|
}
|
|
1150
|
+
const ORDINARY_STYLE_TOGGLE_KEYS = [
|
|
1151
|
+
"bold",
|
|
1152
|
+
"italic",
|
|
1153
|
+
"strike",
|
|
1154
|
+
"allCaps",
|
|
1155
|
+
"smallCaps",
|
|
1156
|
+
"hidden",
|
|
1157
|
+
"emboss",
|
|
1158
|
+
"imprint",
|
|
1159
|
+
"shadow",
|
|
1160
|
+
"outline"
|
|
1161
|
+
];
|
|
1162
|
+
function getRunFormattingOverrides({ directFormatting, effectiveStyleFormatting, hasCharacterStyle, paragraphMarkOverrides }) {
|
|
1163
|
+
const overrides = mergeTextFormatting(paragraphMarkOverrides, directFormatting);
|
|
1164
|
+
if (!overrides || !directFormatting) return overrides;
|
|
1165
|
+
for (const key of ORDINARY_STYLE_TOGGLE_KEYS) if (directFormatting[key] === true && (!hasCharacterStyle || effectiveStyleFormatting?.[key] !== true)) Reflect.deleteProperty(overrides, key);
|
|
1166
|
+
if (directFormatting.boldCs === true && directFormatting.boldCs === directFormatting.bold && (!hasCharacterStyle || effectiveStyleFormatting?.boldCs === void 0)) Reflect.deleteProperty(overrides, "boldCs");
|
|
1167
|
+
if (directFormatting.italicCs === true && directFormatting.italicCs === directFormatting.italic && (!hasCharacterStyle || effectiveStyleFormatting?.italicCs === void 0)) Reflect.deleteProperty(overrides, "italicCs");
|
|
1168
|
+
return overrides;
|
|
1169
|
+
}
|
|
1044
1170
|
/**
|
|
1045
1171
|
* Convert RunContent to ProseMirror nodes
|
|
1046
1172
|
*/
|
|
@@ -1220,13 +1346,10 @@ function convertHyperlink(hyperlink, { getInheritedRunFormatting, styleResolver,
|
|
|
1220
1346
|
}
|
|
1221
1347
|
return nodes;
|
|
1222
1348
|
}
|
|
1223
|
-
|
|
1224
|
-
* Convert TextFormatting to ProseMirror marks
|
|
1225
|
-
*/
|
|
1226
|
-
function textFormattingToMarks(formatting) {
|
|
1349
|
+
function textFormattingToMarks(formatting, options) {
|
|
1227
1350
|
if (!formatting) return [];
|
|
1228
1351
|
const marks = [];
|
|
1229
|
-
const overrideAttrs = buildRunFormattingOverrideAttrs(formatting);
|
|
1352
|
+
const overrideAttrs = buildRunFormattingOverrideAttrs(options ? options.overrideFormatting : formatting);
|
|
1230
1353
|
if (overrideAttrs) marks.push(schema.mark("runFormattingOverride", overrideAttrs));
|
|
1231
1354
|
if (formatting.bold) marks.push(schema.mark("bold"));
|
|
1232
1355
|
if (formatting.italic) marks.push(schema.mark("italic"));
|
|
@@ -4,38 +4,38 @@ import { createMarkExtension } from "../create.js";
|
|
|
4
4
|
function buildRunFormattingOverrideAttrs(formatting) {
|
|
5
5
|
if (!formatting) return;
|
|
6
6
|
const attrs = {};
|
|
7
|
-
if (formatting.bold
|
|
8
|
-
if (formatting.italic
|
|
7
|
+
if (formatting.bold !== void 0) attrs.bold = formatting.bold;
|
|
8
|
+
if (formatting.italic !== void 0) attrs.italic = formatting.italic;
|
|
9
9
|
if (formatting.underline?.style === "none") attrs.underline = "none";
|
|
10
|
-
if (formatting.strike
|
|
10
|
+
if (formatting.strike !== void 0) attrs.strike = formatting.strike;
|
|
11
11
|
if (formatting.doubleStrike === false) attrs.doubleStrike = false;
|
|
12
|
-
if (formatting.allCaps
|
|
13
|
-
if (formatting.smallCaps
|
|
14
|
-
if (formatting.hidden
|
|
15
|
-
if (formatting.emboss
|
|
16
|
-
if (formatting.imprint
|
|
17
|
-
if (formatting.shadow
|
|
18
|
-
if (formatting.outline
|
|
12
|
+
if (formatting.allCaps !== void 0) attrs.allCaps = formatting.allCaps;
|
|
13
|
+
if (formatting.smallCaps !== void 0) attrs.smallCaps = formatting.smallCaps;
|
|
14
|
+
if (formatting.hidden !== void 0) attrs.hidden = formatting.hidden;
|
|
15
|
+
if (formatting.emboss !== void 0) attrs.emboss = formatting.emboss;
|
|
16
|
+
if (formatting.imprint !== void 0) attrs.imprint = formatting.imprint;
|
|
17
|
+
if (formatting.shadow !== void 0) attrs.shadow = formatting.shadow;
|
|
18
|
+
if (formatting.outline !== void 0) attrs.outline = formatting.outline;
|
|
19
19
|
if (formatting.rtl === false) attrs.rtl = false;
|
|
20
|
-
if (formatting.boldCs !== void 0
|
|
21
|
-
if (formatting.italicCs !== void 0
|
|
20
|
+
if (formatting.boldCs !== void 0) attrs.boldCs = formatting.boldCs;
|
|
21
|
+
if (formatting.italicCs !== void 0) attrs.italicCs = formatting.italicCs;
|
|
22
22
|
if (formatting.fontSizeCs !== void 0 && formatting.fontSizeCs !== formatting.fontSize) attrs.fontSizeCs = formatting.fontSizeCs;
|
|
23
23
|
if (formatting.cs !== void 0) attrs.cs = formatting.cs;
|
|
24
24
|
return Object.keys(attrs).length > 0 ? attrs : void 0;
|
|
25
25
|
}
|
|
26
26
|
function applyRunFormattingOverrideAttrs(formatting, attrs) {
|
|
27
|
-
if (attrs.bold
|
|
28
|
-
if (attrs.italic
|
|
27
|
+
if (attrs.bold !== void 0) formatting.bold = attrs.bold;
|
|
28
|
+
if (attrs.italic !== void 0) formatting.italic = attrs.italic;
|
|
29
29
|
if (attrs.underline === "none") formatting.underline = { style: "none" };
|
|
30
|
-
if (attrs.strike
|
|
30
|
+
if (attrs.strike !== void 0) formatting.strike = attrs.strike;
|
|
31
31
|
if (attrs.doubleStrike === false) formatting.doubleStrike = false;
|
|
32
|
-
if (attrs.allCaps
|
|
33
|
-
if (attrs.smallCaps
|
|
34
|
-
if (attrs.hidden
|
|
35
|
-
if (attrs.emboss
|
|
36
|
-
if (attrs.imprint
|
|
37
|
-
if (attrs.shadow
|
|
38
|
-
if (attrs.outline
|
|
32
|
+
if (attrs.allCaps !== void 0) formatting.allCaps = attrs.allCaps;
|
|
33
|
+
if (attrs.smallCaps !== void 0) formatting.smallCaps = attrs.smallCaps;
|
|
34
|
+
if (attrs.hidden !== void 0) formatting.hidden = attrs.hidden;
|
|
35
|
+
if (attrs.emboss !== void 0) formatting.emboss = attrs.emboss;
|
|
36
|
+
if (attrs.imprint !== void 0) formatting.imprint = attrs.imprint;
|
|
37
|
+
if (attrs.shadow !== void 0) formatting.shadow = attrs.shadow;
|
|
38
|
+
if (attrs.outline !== void 0) formatting.outline = attrs.outline;
|
|
39
39
|
if (attrs.rtl === false) formatting.rtl = false;
|
|
40
40
|
if (attrs.boldCs !== void 0) formatting.boldCs = attrs.boldCs;
|
|
41
41
|
if (attrs.italicCs !== void 0) formatting.italicCs = attrs.italicCs;
|
|
@@ -121,7 +121,9 @@ type RunPropertyChangeMarkAttrs = {
|
|
|
121
121
|
provenance: TrackedChangeProvenance;
|
|
122
122
|
suggestionId?: string;
|
|
123
123
|
};
|
|
124
|
-
type RunFormattingOverrideAttrs = { [K in keyof Pick<document_d_exports.TextFormatting, "bold" | "italic" | "strike" | "
|
|
124
|
+
type RunFormattingOverrideAttrs = { [K in keyof Pick<document_d_exports.TextFormatting, "bold" | "italic" | "strike" | "allCaps" | "smallCaps" | "hidden" | "emboss" | "imprint" | "shadow" | "outline">]?: boolean; } & {
|
|
125
|
+
doubleStrike?: false;
|
|
126
|
+
rtl?: false;
|
|
125
127
|
/** Independent complex-script weight (`w:bCs`). */
|
|
126
128
|
boldCs?: boolean;
|
|
127
129
|
/** Force complex-script formatting for the full run (`w:cs`). */
|