@portone/docx-editor 0.2.1 → 0.3.0
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/CHANGELOG.md +109 -0
- package/CONTRIBUTING.md +5 -1
- package/dist/DocxEditor.d.ts +6 -0
- package/dist/DocxEditor.js +12 -29
- package/dist/core.d.ts +23 -8
- package/dist/core.js +9 -4
- package/dist/docx/cloning.d.ts +38 -0
- package/dist/docx/cloning.js +74 -0
- package/dist/docx/commentOnlyChange.d.ts +12 -7
- package/dist/docx/commentOnlyChange.js +9 -156
- package/dist/docx/comments/constants.d.ts +0 -1
- package/dist/docx/comments/constants.js +0 -2
- package/dist/docx/comments/grammar.d.ts +10 -4
- package/dist/docx/comments/grammar.js +12 -2
- package/dist/docx/comments/{verifying.d.ts → parts.d.ts} +26 -18
- package/dist/docx/comments/parts.js +279 -0
- package/dist/docx/comments/people.d.ts +11 -2
- package/dist/docx/comments/people.js +16 -92
- package/dist/docx/comments/policy.d.ts +7 -0
- package/dist/docx/comments/policy.js +43 -0
- package/dist/docx/comments/reading.js +8 -10
- package/dist/docx/comments/writing.d.ts +19 -7
- package/dist/docx/comments/writing.js +52 -111
- package/dist/docx/documentSettings.d.ts +7 -0
- package/dist/docx/documentSettings.js +10 -2
- package/dist/docx/exportDocx.d.ts +40 -5
- package/dist/docx/exportDocx.js +69 -71
- package/dist/docx/exportRefs.d.ts +5 -2
- package/dist/docx/exportRefs.js +3 -1
- package/dist/docx/fidelity.d.ts +43 -0
- package/dist/docx/fidelity.js +64 -0
- package/dist/docx/formatting/attrs.d.ts +27 -0
- package/dist/docx/formatting/attrs.js +31 -0
- package/dist/docx/formatting/context.d.ts +31 -0
- package/dist/docx/formatting/context.js +42 -0
- package/dist/docx/formatting/direct.d.ts +6 -5
- package/dist/docx/formatting/direct.js +52 -78
- package/dist/docx/formatting/resolve.d.ts +45 -0
- package/dist/docx/formatting/resolve.js +140 -0
- package/dist/docx/formatting/runProperties.d.ts +93 -0
- package/dist/docx/formatting/runProperties.js +316 -0
- package/dist/docx/formatting/styles.js +3 -3
- package/dist/docx/formatting/tabStops.js +7 -22
- package/dist/docx/formatting.d.ts +4 -1
- package/dist/docx/formatting.js +4 -1
- package/dist/docx/headersFooters.js +6 -13
- package/dist/docx/identities.d.ts +67 -0
- package/dist/docx/identities.js +174 -0
- package/dist/docx/importDocx.d.ts +12 -1
- package/dist/docx/importDocx.js +72 -79
- package/dist/docx/importParagraph.d.ts +1 -1
- package/dist/docx/importParagraph.js +4 -3
- package/dist/docx/importTable.d.ts +1 -1
- package/dist/docx/importTable.js +17 -1
- package/dist/docx/invariants.d.ts +33 -0
- package/dist/docx/invariants.js +256 -0
- package/dist/docx/media.d.ts +6 -4
- package/dist/docx/media.js +6 -37
- package/dist/docx/newLists.d.ts +20 -0
- package/dist/docx/newLists.js +36 -0
- package/dist/docx/notes.js +3 -7
- package/dist/docx/numberingPlanner.d.ts +8 -0
- package/dist/docx/numberingPlanner.js +19 -0
- package/dist/docx/packageParts.d.ts +42 -0
- package/dist/docx/packageParts.js +135 -0
- package/dist/docx/pageGeometry.d.ts +2 -0
- package/dist/docx/pageGeometry.js +18 -9
- package/dist/docx/paraProps.d.ts +10 -22
- package/dist/docx/paraProps.js +47 -76
- package/dist/docx/partPlan.d.ts +36 -0
- package/dist/docx/partPlan.js +59 -0
- package/dist/docx/protectionPolicy.d.ts +127 -0
- package/dist/docx/protectionPolicy.js +169 -0
- package/dist/docx/relationships.d.ts +1 -1
- package/dist/docx/relationships.js +8 -13
- package/dist/docx/runProps.d.ts +9 -22
- package/dist/docx/runProps.js +15 -168
- package/dist/docx/scan.js +20 -52
- package/dist/docx/sdt.js +9 -34
- package/dist/docx/sdtProps.d.ts +8 -1
- package/dist/docx/sdtProps.js +10 -0
- package/dist/docx/serializeBlock.d.ts +2 -0
- package/dist/docx/serializeBlock.js +8 -5
- package/dist/docx/serializeTable.js +32 -15
- package/dist/docx/session.d.ts +42 -14
- package/dist/docx/session.js +43 -17
- package/dist/docx/tableFormatting/editing.js +108 -139
- package/dist/docx/tableFormatting/reading.d.ts +16 -6
- package/dist/docx/tableFormatting/reading.js +40 -20
- package/dist/docx/tableTemplate.js +18 -7
- package/dist/download.d.ts +8 -5
- package/dist/download.js +2 -0
- package/dist/editor/clipboard/inlineFormatting.js +19 -30
- package/dist/editor/commands/comments/editing.d.ts +6 -2
- package/dist/editor/commands/comments/editing.js +19 -31
- package/dist/editor/commands/exportQueries.d.ts +15 -0
- package/dist/editor/commands/exportQueries.js +14 -0
- package/dist/editor/commands/fidelityQueries.d.ts +12 -0
- package/dist/editor/commands/fidelityQueries.js +8 -0
- package/dist/editor/commands/formatting/editing.d.ts +2 -2
- package/dist/editor/commands/formatting/editing.js +26 -108
- package/dist/editor/commands/formatting/propertyCommands.d.ts +21 -0
- package/dist/editor/commands/formatting/propertyCommands.js +103 -0
- package/dist/editor/commands/formatting/shared.d.ts +3 -3
- package/dist/editor/commands/formatting/shared.js +5 -2
- package/dist/editor/commands/indentCommands.js +5 -4
- package/dist/editor/commands/index.d.ts +11 -0
- package/dist/editor/commands/index.js +5 -0
- package/dist/editor/commands/linkCommands.js +5 -6
- package/dist/editor/commands/listCommands.js +8 -10
- package/dist/editor/commands/lockCommands.d.ts +7 -1
- package/dist/editor/commands/lockCommands.js +35 -46
- package/dist/editor/commands/paragraphCommands.js +28 -31
- package/dist/editor/commands/spacingCommands.js +1 -1
- package/dist/editor/createEditor.d.ts +17 -29
- package/dist/editor/createEditor.js +58 -58
- package/dist/editor/documentStyles.d.ts +11 -35
- package/dist/editor/documentStyles.js +9 -52
- package/dist/editor/editorDocument.d.ts +56 -0
- package/dist/editor/editorDocument.js +74 -0
- package/dist/editor/externalClipboard.js +16 -45
- package/dist/editor/insertTable.js +4 -3
- package/dist/editor/paragraphEdits.d.ts +11 -18
- package/dist/editor/paragraphEdits.js +7 -16
- package/dist/editor/plugins/displayDerivation.d.ts +47 -0
- package/dist/editor/plugins/displayDerivation.js +78 -0
- package/dist/editor/plugins/imagePaste.js +4 -3
- package/dist/editor/plugins/keymap.js +18 -3
- package/dist/editor/plugins/numberingDecorations.d.ts +5 -11
- package/dist/editor/plugins/numberingDecorations.js +7 -17
- package/dist/editor/plugins/paragraphDisplay.d.ts +7 -0
- package/dist/editor/plugins/paragraphDisplay.js +51 -0
- package/dist/editor/plugins/tabLayout.js +1 -1
- package/dist/editor/plugins/tableDisplay.d.ts +6 -0
- package/dist/editor/plugins/tableDisplay.js +16 -0
- package/dist/index.d.ts +2 -0
- package/dist/model/format.d.ts +30 -8
- package/dist/model/format.js +35 -22
- package/dist/model/tabStops.d.ts +9 -0
- package/dist/model/tabStops.js +18 -0
- package/dist/numbering/listTemplate.js +24 -7
- package/dist/numbering/parseNumbering.d.ts +14 -1
- package/dist/numbering/parseNumbering.js +35 -22
- package/dist/numbering/writeNumbering.d.ts +3 -4
- package/dist/numbering/writeNumbering.js +14 -25
- package/dist/ooxml/childOrder.d.ts +34 -0
- package/dist/ooxml/childOrder.js +496 -0
- package/dist/ooxml/element.d.ts +24 -11
- package/dist/ooxml/element.js +31 -12
- package/dist/ooxml/errors.d.ts +3 -2
- package/dist/ooxml/image.d.ts +4 -0
- package/dist/ooxml/image.js +2 -5
- package/dist/ooxml/partSplice.d.ts +67 -0
- package/dist/ooxml/partSplice.js +169 -0
- package/dist/ooxml/props.d.ts +112 -0
- package/dist/{docx/propsXml.js → ooxml/props.js} +72 -200
- package/dist/ooxml/simpleTypes.d.ts +103 -0
- package/dist/ooxml/simpleTypes.js +182 -0
- package/dist/ooxml/tabStops.js +8 -27
- package/dist/ooxml/tagScan.d.ts +34 -0
- package/dist/ooxml/tagScan.js +108 -0
- package/dist/ooxml/units.d.ts +25 -13
- package/dist/ooxml/units.js +65 -31
- package/dist/ooxml/xml.d.ts +27 -6
- package/dist/ooxml/xml.js +37 -5
- package/dist/page/blockKinds.d.ts +61 -0
- package/dist/page/blockKinds.js +11 -0
- package/dist/page/kinds/index.d.ts +6 -0
- package/dist/page/kinds/index.js +10 -0
- package/dist/page/kinds/paragraphKind.d.ts +10 -0
- package/dist/page/kinds/paragraphKind.js +71 -0
- package/dist/page/kinds/tableKind.d.ts +10 -0
- package/dist/page/kinds/tableKind.js +178 -0
- package/dist/page/measureBlocks.d.ts +3 -14
- package/dist/page/measureBlocks.js +24 -45
- package/dist/page/pageDecorations.d.ts +27 -44
- package/dist/page/pageDecorations.js +70 -152
- package/dist/page/pageLayout.d.ts +2 -19
- package/dist/page/pageLayout.js +36 -6
- package/dist/page/usePageLayout.d.ts +2 -17
- package/dist/page/usePageLayout.js +3 -39
- package/dist/schema/attrRoles.d.ts +25 -18
- package/dist/schema/attrRoles.js +102 -67
- package/dist/schema/displayDerivation.d.ts +82 -0
- package/dist/schema/displayDerivation.js +130 -0
- package/dist/schema/docxSchema.d.ts +3 -0
- package/dist/schema/docxSchema.js +26 -14
- package/dist/schema/editGuard.d.ts +1 -1
- package/dist/schema/guards.d.ts +37 -14
- package/dist/schema/guards.js +29 -3
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.js +2 -0
- package/dist/schema/locks.d.ts +11 -44
- package/dist/schema/locks.js +0 -9
- package/dist/schema/preservedGuards.d.ts +26 -6
- package/dist/schema/preservedGuards.js +31 -1
- package/dist/schema/protection.d.ts +7 -1
- package/dist/schema/protection.js +2 -1
- package/dist/schema/sourceEquality.d.ts +1 -9
- package/dist/schema/sourceEquality.js +1 -27
- package/dist/styles/inlineStyle.js +15 -6
- package/dist/table/cellFormatting.d.ts +8 -1
- package/dist/table/cellFormatting.js +10 -18
- package/dist/table/commands.js +20 -18
- package/dist/table/format.d.ts +3 -0
- package/dist/table/format.js +3 -9
- package/dist/table/gridBorders.d.ts +14 -16
- package/dist/table/gridBorders.js +3 -41
- package/dist/table/merge.d.ts +2 -6
- package/dist/table/merge.js +5 -5
- package/package.json +7 -3
- package/dist/docx/comments/contentTypes.d.ts +0 -7
- package/dist/docx/comments/contentTypes.js +0 -38
- package/dist/docx/comments/verifying.js +0 -206
- package/dist/docx/formatting/effectiveParagraph.d.ts +0 -15
- package/dist/docx/formatting/effectiveParagraph.js +0 -81
- package/dist/docx/propsXml.d.ts +0 -67
- package/dist/docx/uniqueControls.d.ts +0 -14
- package/dist/docx/uniqueControls.js +0 -62
- package/dist/editor/plugins/commentReservations.d.ts +0 -5
- package/dist/editor/plugins/commentReservations.js +0 -26
- package/dist/editor/plugins/styledParagraphs.d.ts +0 -15
- package/dist/editor/plugins/styledParagraphs.js +0 -65
- package/dist/page/tableMeasurements.d.ts +0 -18
- package/dist/page/tableMeasurements.js +0 -119
|
@@ -1,56 +1,27 @@
|
|
|
1
1
|
// src/docx/formatting/direct.ts
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
isUnderlineKind
|
|
3
|
+
RUN_FORMAT_KEYS
|
|
5
4
|
} from "../../model/format.js";
|
|
6
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
ST_DecimalNumber,
|
|
7
|
+
ST_SignedTwipsMeasure,
|
|
8
|
+
ST_TwipsMeasure,
|
|
9
|
+
TWIPS_PER_PT
|
|
10
|
+
} from "../../ooxml/simpleTypes.js";
|
|
7
11
|
import { readTabStopDirectives } from "../../ooxml/tabStops.js";
|
|
8
12
|
import {
|
|
9
13
|
ALIGN_BY_JC,
|
|
10
14
|
borderSide,
|
|
11
15
|
childValue,
|
|
12
|
-
halfPointsToPt,
|
|
13
16
|
isOn,
|
|
14
17
|
round,
|
|
15
18
|
shadingOf,
|
|
16
|
-
toHexColor,
|
|
17
|
-
toNumber,
|
|
18
19
|
twipsToPt,
|
|
19
20
|
wAttr
|
|
20
21
|
} from "../../ooxml/units.js";
|
|
21
22
|
import { childByLocalName } from "../../ooxml/xml.js";
|
|
22
|
-
import { NO_THEME_FONTS
|
|
23
|
-
|
|
24
|
-
superscript: "superscript",
|
|
25
|
-
subscript: "subscript"
|
|
26
|
-
};
|
|
27
|
-
function fontNamesOf(cssNames) {
|
|
28
|
-
if (!cssNames) return [];
|
|
29
|
-
return cssNames.split(",").map((name) => name.trim().replace(/^"|"$/g, "")).filter((name) => name.length > 0);
|
|
30
|
-
}
|
|
31
|
-
var FONT_SLOTS = ["ascii", "eastAsia", "hAnsi", "cs"];
|
|
32
|
-
function slotFontName(rFonts, slot, themeFonts) {
|
|
33
|
-
const written = wAttr(rFonts, slot);
|
|
34
|
-
if (written !== null) return written;
|
|
35
|
-
for (const attr of overridingAttrs("rFonts", slot)) {
|
|
36
|
-
const resolved = themeFontName(themeFonts, wAttr(rFonts, attr));
|
|
37
|
-
if (resolved !== null) return resolved;
|
|
38
|
-
}
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
function fontFamilyOf(rFonts, themeFonts) {
|
|
42
|
-
const names = FONT_SLOTS.map((slot) => slotFontName(rFonts, slot, themeFonts)).filter((name) => name !== null).filter((name) => name.length > 0 && !/["';\\]/.test(name));
|
|
43
|
-
const unique = Array.from(new Set(names));
|
|
44
|
-
return unique.length > 0 ? unique.map((name) => `"${name}"`).join(",") : null;
|
|
45
|
-
}
|
|
46
|
-
function langOf(rPr) {
|
|
47
|
-
const lang = childByLocalName(rPr, "lang");
|
|
48
|
-
if (!lang) return null;
|
|
49
|
-
const eastAsia = wAttr(lang, "eastAsia");
|
|
50
|
-
if (eastAsia !== null && eastAsia.length > 0) return eastAsia;
|
|
51
|
-
const value = wAttr(lang, "val");
|
|
52
|
-
return value !== null && value.length > 0 ? value : null;
|
|
53
|
-
}
|
|
23
|
+
import { NO_THEME_FONTS } from "../theme.js";
|
|
24
|
+
import { RUN_PROPERTIES } from "./runProperties.js";
|
|
54
25
|
function drawnBorder(pBdr, side) {
|
|
55
26
|
const css = borderSide(pBdr, side);
|
|
56
27
|
return css === "none" ? null : css;
|
|
@@ -73,33 +44,39 @@ function readIndent(pPr) {
|
|
|
73
44
|
const ind = childByLocalName(pPr, "ind");
|
|
74
45
|
if (!ind) return {};
|
|
75
46
|
const format = {};
|
|
76
|
-
const start = twipsToPt(
|
|
47
|
+
const start = twipsToPt(
|
|
48
|
+
ST_SignedTwipsMeasure.parse(wAttr(ind, "start") ?? wAttr(ind, "left"))
|
|
49
|
+
);
|
|
77
50
|
if (start !== null) format.indentStartPt = start;
|
|
78
|
-
const end = twipsToPt(
|
|
51
|
+
const end = twipsToPt(
|
|
52
|
+
ST_SignedTwipsMeasure.parse(wAttr(ind, "end") ?? wAttr(ind, "right"))
|
|
53
|
+
);
|
|
79
54
|
if (end !== null) format.indentEndPt = end;
|
|
80
|
-
const hanging = twipsToPt(wAttr(ind, "hanging"));
|
|
81
|
-
const firstLine = twipsToPt(wAttr(ind, "firstLine"));
|
|
55
|
+
const hanging = twipsToPt(ST_TwipsMeasure.parse(wAttr(ind, "hanging")));
|
|
56
|
+
const firstLine = twipsToPt(ST_TwipsMeasure.parse(wAttr(ind, "firstLine")));
|
|
82
57
|
if (hanging !== null) format.textIndentPt = -hanging;
|
|
83
58
|
else if (firstLine !== null) format.textIndentPt = firstLine;
|
|
84
59
|
return format;
|
|
85
60
|
}
|
|
61
|
+
var LINE_UNITS_PER_LINE = 240;
|
|
86
62
|
function readLineSpacing(pPr) {
|
|
87
63
|
const spacing = childByLocalName(pPr, "spacing");
|
|
88
64
|
if (!spacing) return null;
|
|
89
|
-
const line =
|
|
65
|
+
const line = ST_SignedTwipsMeasure.parse(wAttr(spacing, "line"));
|
|
90
66
|
if (line === null) return null;
|
|
91
67
|
const rule = wAttr(spacing, "lineRule");
|
|
92
|
-
|
|
93
|
-
if (rule === "
|
|
94
|
-
return { rule: "
|
|
68
|
+
const pt = round(line / TWIPS_PER_PT);
|
|
69
|
+
if (rule === "exact") return { rule: "exact", pt };
|
|
70
|
+
if (rule === "atLeast") return { rule: "atLeast", pt };
|
|
71
|
+
return { rule: "auto", lines: round(line / LINE_UNITS_PER_LINE) };
|
|
95
72
|
}
|
|
96
73
|
function readSpacing(pPr) {
|
|
97
74
|
const spacing = childByLocalName(pPr, "spacing");
|
|
98
75
|
if (!spacing) return {};
|
|
99
76
|
const format = {};
|
|
100
|
-
const before = twipsToPt(wAttr(spacing, "before"));
|
|
77
|
+
const before = twipsToPt(ST_TwipsMeasure.parse(wAttr(spacing, "before")));
|
|
101
78
|
if (before !== null) format.spaceBeforePt = before;
|
|
102
|
-
const after = twipsToPt(wAttr(spacing, "after"));
|
|
79
|
+
const after = twipsToPt(ST_TwipsMeasure.parse(wAttr(spacing, "after")));
|
|
103
80
|
if (after !== null) format.spaceAfterPt = after;
|
|
104
81
|
const lineSpacing = readLineSpacing(pPr);
|
|
105
82
|
if (lineSpacing) format.lineSpacing = lineSpacing;
|
|
@@ -108,13 +85,13 @@ function readSpacing(pPr) {
|
|
|
108
85
|
function readNumbering(pPr) {
|
|
109
86
|
const numPr = childByLocalName(pPr, "numPr");
|
|
110
87
|
if (!numPr) return {};
|
|
111
|
-
const numId =
|
|
88
|
+
const numId = ST_DecimalNumber.parse(childValue(numPr, "numId"));
|
|
112
89
|
if (numId === 0) return { numbering: null };
|
|
113
90
|
if (numId === null || numId < 0) return {};
|
|
114
91
|
return {
|
|
115
92
|
numbering: {
|
|
116
|
-
numId
|
|
117
|
-
ilvl:
|
|
93
|
+
numId,
|
|
94
|
+
ilvl: ST_DecimalNumber.parse(childValue(numPr, "ilvl")) ?? 0
|
|
118
95
|
}
|
|
119
96
|
};
|
|
120
97
|
}
|
|
@@ -134,34 +111,23 @@ function readParagraphFormat(pPr) {
|
|
|
134
111
|
format.direction = isOn(pPr, "bidi") ? "rtl" : "ltr";
|
|
135
112
|
}
|
|
136
113
|
if (isOn(pPr, "pageBreakBefore")) format.pageBreakBefore = true;
|
|
114
|
+
if (childByLocalName(pPr, "keepNext")) {
|
|
115
|
+
format.keepNext = isOn(pPr, "keepNext");
|
|
116
|
+
}
|
|
137
117
|
const background = shadingOf(pPr);
|
|
138
118
|
if (background) format.background = background;
|
|
139
119
|
return format;
|
|
140
120
|
}
|
|
121
|
+
function readRunProperty(format, key, rPr, themeFonts) {
|
|
122
|
+
const value = RUN_PROPERTIES[key].read(rPr, themeFonts);
|
|
123
|
+
if (value !== void 0) format[key] = value;
|
|
124
|
+
}
|
|
141
125
|
function readRunFormat(rPr, themeFonts = NO_THEME_FONTS) {
|
|
142
126
|
if (!rPr) return null;
|
|
143
127
|
const format = {};
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if (isOn(rPr, "smallCaps")) format.smallCaps = true;
|
|
148
|
-
const underline = childValue(rPr, "u");
|
|
149
|
-
if (isUnderlineKind(underline)) format.underline = underline;
|
|
150
|
-
const fontSizePt = halfPointsToPt(childValue(rPr, "sz"));
|
|
151
|
-
if (fontSizePt !== null) format.fontSizePt = fontSizePt;
|
|
152
|
-
const rFonts = childByLocalName(rPr, "rFonts");
|
|
153
|
-
const fontFamily = rFonts ? fontFamilyOf(rFonts, themeFonts) : null;
|
|
154
|
-
if (fontFamily) format.fontFamily = fontFamily;
|
|
155
|
-
const color = toHexColor(childValue(rPr, "color"));
|
|
156
|
-
if (color) format.color = color;
|
|
157
|
-
const highlight = childValue(rPr, "highlight");
|
|
158
|
-
if (isHighlightName(highlight)) format.highlight = highlight;
|
|
159
|
-
const background = shadingOf(rPr);
|
|
160
|
-
if (background) format.background = background;
|
|
161
|
-
const verticalAlign = VERTICAL_ALIGN_BY_VAL[childValue(rPr, "vertAlign") ?? ""];
|
|
162
|
-
if (verticalAlign) format.verticalAlign = verticalAlign;
|
|
163
|
-
const lang = langOf(rPr);
|
|
164
|
-
if (lang) format.lang = lang;
|
|
128
|
+
for (const key of RUN_FORMAT_KEYS) {
|
|
129
|
+
readRunProperty(format, key, rPr, themeFonts);
|
|
130
|
+
}
|
|
165
131
|
return format;
|
|
166
132
|
}
|
|
167
133
|
var NO_DOCUMENT_DEFAULTS = {
|
|
@@ -177,22 +143,30 @@ function defaultProperties(styles, slot, name) {
|
|
|
177
143
|
function readDefaultParagraphFormat(styles) {
|
|
178
144
|
return readParagraphFormat(defaultProperties(styles, "pPrDefault", "pPr")) ?? {};
|
|
179
145
|
}
|
|
146
|
+
function readRunDefaults(styles, themeFonts = NO_THEME_FONTS) {
|
|
147
|
+
return readRunFormat(defaultProperties(styles, "rPrDefault", "rPr"), themeFonts) ?? {};
|
|
148
|
+
}
|
|
149
|
+
function runStyleIdOf(rPr) {
|
|
150
|
+
const id = rPr ? childValue(rPr, "rStyle") : null;
|
|
151
|
+
return id !== null && id.length > 0 ? id : null;
|
|
152
|
+
}
|
|
180
153
|
function readDocumentDefaults(styles, themeFonts = NO_THEME_FONTS) {
|
|
181
|
-
const
|
|
154
|
+
const run = readRunDefaults(styles, themeFonts);
|
|
182
155
|
const pPr = defaultProperties(styles, "pPrDefault", "pPr");
|
|
183
|
-
const rFonts = rPr ? childByLocalName(rPr, "rFonts") : null;
|
|
184
156
|
return {
|
|
185
|
-
fontSizePt:
|
|
186
|
-
fontFamily:
|
|
157
|
+
fontSizePt: run.fontSizePt ?? null,
|
|
158
|
+
fontFamily: run.fontFamily ?? null,
|
|
187
159
|
lineSpacing: pPr ? readLineSpacing(pPr) : null
|
|
188
160
|
};
|
|
189
161
|
}
|
|
190
162
|
export {
|
|
163
|
+
LINE_UNITS_PER_LINE,
|
|
191
164
|
NO_DOCUMENT_DEFAULTS,
|
|
192
|
-
fontNamesOf,
|
|
193
165
|
readDefaultParagraphFormat,
|
|
194
166
|
readDocumentDefaults,
|
|
195
167
|
readLineSpacing,
|
|
196
168
|
readParagraphFormat,
|
|
197
|
-
|
|
169
|
+
readRunDefaults,
|
|
170
|
+
readRunFormat,
|
|
171
|
+
runStyleIdOf
|
|
198
172
|
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves the §17.7.2 hierarchy for one paragraph and for the runs inside it.
|
|
3
|
+
*
|
|
4
|
+
* The layers are put in order here and nowhere else, so a paragraph's display values are the
|
|
5
|
+
* same whichever path asked for them: opening the document, an edit, a paste, or a paragraph an
|
|
6
|
+
* edit built from nothing.
|
|
7
|
+
*/
|
|
8
|
+
import { type ParagraphFormat, type RunFormat } from "../../model/format";
|
|
9
|
+
import type { TabStop } from "../../model/tabStops";
|
|
10
|
+
import type { TableStyleOverrideType } from "../tableFormatting";
|
|
11
|
+
import type { FormattingContext } from "./context";
|
|
12
|
+
/** Where a paragraph sits when it is inside a table cell. null for body text */
|
|
13
|
+
export interface ParagraphPlacement {
|
|
14
|
+
tableStyleId: string | null;
|
|
15
|
+
/**
|
|
16
|
+
* The conditional formats the cell takes, lowest first. Not read yet: a table style
|
|
17
|
+
* contributes the values it lays down for the whole table alone
|
|
18
|
+
*/
|
|
19
|
+
conditions: readonly TableStyleOverrideType[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The layer of the hierarchy a tab stop came from. Removing an inherited stop means writing a
|
|
23
|
+
* `clear` over it, while a direct one is deleted from the paragraph's own list, which is what a
|
|
24
|
+
* ruler needs to tell apart. The document defaults and a table style count as `style`, since a
|
|
25
|
+
* stop from either is taken away the same way
|
|
26
|
+
*/
|
|
27
|
+
export type TabStopLayer = "numbering" | "style" | "direct" | "implicit";
|
|
28
|
+
export interface LayeredTabStop extends TabStop {
|
|
29
|
+
layer: TabStopLayer;
|
|
30
|
+
}
|
|
31
|
+
export interface ResolvedParagraph {
|
|
32
|
+
/** `format` in `schema`: docDefaults < table style < numbering level < paragraph style < direct */
|
|
33
|
+
format: ParagraphFormat | null;
|
|
34
|
+
/** `styleRun` in `schema`: run defaults < table style rPr < paragraph style rPr. Default font and size stay in CSS variables */
|
|
35
|
+
styleRun: RunFormat | null;
|
|
36
|
+
/** Everything below a run's own formatting, docDefaults included. What a removed run property falls back to */
|
|
37
|
+
inheritedRun: RunFormat;
|
|
38
|
+
/** The stops `format.tabStops` holds, each with the layer that laid it down */
|
|
39
|
+
tabStops: readonly LayeredTabStop[];
|
|
40
|
+
}
|
|
41
|
+
export declare function resolveParagraph(pPr: string | null, context: FormattingContext, placement?: ParagraphPlacement | null): ResolvedParagraph;
|
|
42
|
+
/** `format` on a run mark: paragraph.styleRun < character style < the run's own rPr */
|
|
43
|
+
export declare function resolveRun(rPr: string | null, paragraph: ResolvedParagraph, context: FormattingContext): RunFormat | null;
|
|
44
|
+
/** paragraph.inheritedRun < character style. What a run property taken out of the rPr falls back to */
|
|
45
|
+
export declare function inheritedRunFormat(rPr: string | null, paragraph: ResolvedParagraph, context: FormattingContext): RunFormat;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// src/docx/formatting/resolve.ts
|
|
2
|
+
import {
|
|
3
|
+
toParagraphFormat
|
|
4
|
+
} from "../../model/format.js";
|
|
5
|
+
import {
|
|
6
|
+
levelIndentPt
|
|
7
|
+
} from "../../numbering/parseNumbering.js";
|
|
8
|
+
import { parsePropsXml } from "../../ooxml/props.js";
|
|
9
|
+
import { readParagraphFormat, readRunFormat, runStyleIdOf } from "./direct.js";
|
|
10
|
+
import {
|
|
11
|
+
layerRunFormat,
|
|
12
|
+
paragraphStyleFormat
|
|
13
|
+
} from "./styles.js";
|
|
14
|
+
function directLayer(pPr) {
|
|
15
|
+
return pPr === null ? {} : readParagraphFormat(parsePropsXml(pPr)) ?? {};
|
|
16
|
+
}
|
|
17
|
+
function tableStyleOf(placement, context) {
|
|
18
|
+
const id = placement?.tableStyleId ?? null;
|
|
19
|
+
return id === null ? void 0 : context.styles.get(id);
|
|
20
|
+
}
|
|
21
|
+
function numberingLevelOf(layers, context) {
|
|
22
|
+
const ref = layers.reduce(
|
|
23
|
+
(found, layer) => layer.numbering === void 0 ? found : layer.numbering,
|
|
24
|
+
void 0
|
|
25
|
+
);
|
|
26
|
+
if (!ref) return void 0;
|
|
27
|
+
return context.numbering.lists.get(ref.numId)?.levels.get(ref.ilvl);
|
|
28
|
+
}
|
|
29
|
+
function numberingLayer(level) {
|
|
30
|
+
return level?.tabStops ? { tabStops: level.tabStops } : {};
|
|
31
|
+
}
|
|
32
|
+
function layerValues(base, over) {
|
|
33
|
+
const { tabStops: _stops, ...values } = over;
|
|
34
|
+
return { ...base, ...values };
|
|
35
|
+
}
|
|
36
|
+
function byPosition(left, right) {
|
|
37
|
+
return left.positionPt - right.positionPt;
|
|
38
|
+
}
|
|
39
|
+
function explicitStops(layers) {
|
|
40
|
+
const spoken = /* @__PURE__ */ new Map();
|
|
41
|
+
for (const { values, stops } of layers) {
|
|
42
|
+
for (const stop of values.tabStops ?? []) {
|
|
43
|
+
spoken.set(stop.positionPt, { stop, layer: stops });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return [...spoken.values()].flatMap(
|
|
47
|
+
({ stop, layer }) => stop.align === "clear" ? [] : [{ ...stop, layer }]
|
|
48
|
+
).sort(byPosition);
|
|
49
|
+
}
|
|
50
|
+
function hangingStopPt(values, level) {
|
|
51
|
+
const leading = values.indentStartPt ?? values.indentLeftPt ?? level.startPt;
|
|
52
|
+
const textIndent = values.textIndentPt ?? level.textIndentPt;
|
|
53
|
+
return leading !== null && textIndent !== null && textIndent < 0 ? leading : null;
|
|
54
|
+
}
|
|
55
|
+
function withImplicitStop(stops, positionPt) {
|
|
56
|
+
if (positionPt === null) return stops;
|
|
57
|
+
if (stops.some((stop) => stop.positionPt === positionPt)) return stops;
|
|
58
|
+
const implicit = {
|
|
59
|
+
positionPt,
|
|
60
|
+
align: "start",
|
|
61
|
+
layer: "implicit"
|
|
62
|
+
};
|
|
63
|
+
return [...stops, implicit].sort(byPosition);
|
|
64
|
+
}
|
|
65
|
+
function orNull(values) {
|
|
66
|
+
return Object.keys(values).length === 0 ? null : values;
|
|
67
|
+
}
|
|
68
|
+
function resolveParagraph(pPr, context, placement = null) {
|
|
69
|
+
const tableStyle = tableStyleOf(placement, context);
|
|
70
|
+
const style = paragraphStyleFormat(
|
|
71
|
+
pPr,
|
|
72
|
+
context.styles,
|
|
73
|
+
context.defaultParagraphStyleId
|
|
74
|
+
);
|
|
75
|
+
const direct = directLayer(pPr);
|
|
76
|
+
const explicit = [
|
|
77
|
+
{ values: context.paragraphDefaults, stops: "style" },
|
|
78
|
+
{ values: tableStyle?.paragraph ?? {}, stops: "style" },
|
|
79
|
+
{ values: style?.paragraph ?? {}, stops: "style" },
|
|
80
|
+
{ values: direct, stops: "direct" }
|
|
81
|
+
];
|
|
82
|
+
const level = numberingLevelOf(
|
|
83
|
+
explicit.map((layer) => layer.values),
|
|
84
|
+
context
|
|
85
|
+
);
|
|
86
|
+
const layers = [
|
|
87
|
+
...explicit.slice(0, 2),
|
|
88
|
+
{ values: numberingLayer(level), stops: "numbering" },
|
|
89
|
+
...explicit.slice(2)
|
|
90
|
+
];
|
|
91
|
+
const values = layers.reduce(
|
|
92
|
+
(base, layer) => layerValues(base, layer.values),
|
|
93
|
+
{}
|
|
94
|
+
);
|
|
95
|
+
const stops = explicitStops(layers);
|
|
96
|
+
const tabStops = context.compat.noTabHangInd ? stops : withImplicitStop(
|
|
97
|
+
stops,
|
|
98
|
+
hangingStopPt(values, levelIndentPt(level?.indent ?? null))
|
|
99
|
+
);
|
|
100
|
+
const format = toParagraphFormat(values) ?? {};
|
|
101
|
+
if (tabStops.length > 0) {
|
|
102
|
+
format.tabStops = tabStops.map(({ layer: _layer, ...stop }) => stop);
|
|
103
|
+
}
|
|
104
|
+
const {
|
|
105
|
+
fontSizePt: _size,
|
|
106
|
+
fontFamily: _font,
|
|
107
|
+
...displayDefaults
|
|
108
|
+
} = context.runDefaults;
|
|
109
|
+
const styleRun = {
|
|
110
|
+
...displayDefaults,
|
|
111
|
+
...tableStyle?.run,
|
|
112
|
+
...style?.run
|
|
113
|
+
};
|
|
114
|
+
return {
|
|
115
|
+
format: orNull(format),
|
|
116
|
+
styleRun: orNull(styleRun),
|
|
117
|
+
inheritedRun: { ...context.runDefaults, ...styleRun },
|
|
118
|
+
tabStops
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function characterStyleRun(rPr, context) {
|
|
122
|
+
const id = runStyleIdOf(rPr);
|
|
123
|
+
return id === null ? {} : context.styles.get(id)?.run ?? {};
|
|
124
|
+
}
|
|
125
|
+
function resolveRun(rPr, paragraph, context) {
|
|
126
|
+
const el = rPr === null ? null : parsePropsXml(rPr);
|
|
127
|
+
return layerRunFormat(
|
|
128
|
+
{ ...paragraph.styleRun, ...characterStyleRun(el, context) },
|
|
129
|
+
readRunFormat(el, context.themeFonts)
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
function inheritedRunFormat(rPr, paragraph, context) {
|
|
133
|
+
const el = rPr === null ? null : parsePropsXml(rPr);
|
|
134
|
+
return { ...paragraph.inheritedRun, ...characterStyleRun(el, context) };
|
|
135
|
+
}
|
|
136
|
+
export {
|
|
137
|
+
inheritedRunFormat,
|
|
138
|
+
resolveParagraph,
|
|
139
|
+
resolveRun
|
|
140
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One row per run property: what it reads out of an rPr, what it writes into one, and whether
|
|
3
|
+
* text already carries a value.
|
|
4
|
+
*
|
|
5
|
+
* Reading, writing and comparing used to be three hand-kept copies of the same vocabulary, so a
|
|
6
|
+
* property could be read under one name and written under another. Here each is one row, and the
|
|
7
|
+
* readers and writers below walk the table, so anything else that has to speak for a run
|
|
8
|
+
* property - a tracked change's `w:rPrChange` snapshot, a style's `w:rPr` - asks the same row.
|
|
9
|
+
*
|
|
10
|
+
* The values read are for display only. What goes back into the document is the rPr string, and
|
|
11
|
+
* a write is a list of children swapped into it (`ooxml/props`), never a tree serialized again.
|
|
12
|
+
*/
|
|
13
|
+
import { type RunFormat } from "../../model/format";
|
|
14
|
+
import { type Props } from "../../ooxml/props";
|
|
15
|
+
import { type ThemeFonts } from "../theme";
|
|
16
|
+
/** What text one child of the rPr is to be changed to. A null xml removes that child */
|
|
17
|
+
export type ChildEdit = readonly [name: string, xml: string | null];
|
|
18
|
+
/** What an edit is written against: the rPr as it stands, and everything the layers below the run lay down */
|
|
19
|
+
export interface RunEditContext {
|
|
20
|
+
rPr: Props;
|
|
21
|
+
inherited: RunFormat;
|
|
22
|
+
}
|
|
23
|
+
type Read<K extends keyof RunFormat> = NonNullable<RunFormat[K]>;
|
|
24
|
+
/**
|
|
25
|
+
* The value an edit sets. An off - `false`, an underline of `none` - is not one: it is spelled
|
|
26
|
+
* as null, the withdrawal, and pinned into the rPr only where the layers below would otherwise
|
|
27
|
+
* show through.
|
|
28
|
+
*/
|
|
29
|
+
export type RunSetting<K extends keyof RunFormat> = Exclude<Read<K>, false | "none">;
|
|
30
|
+
/** A run property as it is read and compared. `R` is the value read, `S` the value an edit sets */
|
|
31
|
+
export interface RunProperty<R, S> {
|
|
32
|
+
/**
|
|
33
|
+
* The rPr children the property owns, in the order CT_RPr lays them down. A `w:rPrChange`
|
|
34
|
+
* snapshot of the property is exactly these
|
|
35
|
+
*/
|
|
36
|
+
readonly children: readonly string[];
|
|
37
|
+
read(rPr: Element, themeFonts: ThemeFonts): R | undefined;
|
|
38
|
+
/** Whether the display values switch or paint the property on, which is what a withdrawal has to undo */
|
|
39
|
+
isOn(format: RunFormat): boolean;
|
|
40
|
+
/** Whether the display values already carry the value, so that writing it would change nothing */
|
|
41
|
+
matches(format: RunFormat, value: S): boolean;
|
|
42
|
+
}
|
|
43
|
+
/** A run property an edit may write as well */
|
|
44
|
+
export interface EditableRunProperty<R, S> extends RunProperty<R, S> {
|
|
45
|
+
/** The children that make the run say the value. null for a value the document cannot record */
|
|
46
|
+
write(value: S, context: RunEditContext): ChildEdit[] | null;
|
|
47
|
+
/** The children that take the run's own say away, pinned off where the layers below would otherwise show through */
|
|
48
|
+
off(context: RunEditContext): ChildEdit[];
|
|
49
|
+
}
|
|
50
|
+
/** The properties read for display alone. Nothing writes them, so no edit names them */
|
|
51
|
+
declare const DISPLAY_ONLY_RUN_KEYS: readonly ["lang"];
|
|
52
|
+
type DisplayOnlyRunKey = (typeof DISPLAY_ONLY_RUN_KEYS)[number];
|
|
53
|
+
export type EditableRunKey = Exclude<keyof RunFormat, DisplayOnlyRunKey>;
|
|
54
|
+
/**
|
|
55
|
+
* A job that changes one run property. A null value withdraws the run's own setting: the layers
|
|
56
|
+
* below stand again, except where they would switch or paint the property on, in which case the
|
|
57
|
+
* off is pinned into the run.
|
|
58
|
+
*/
|
|
59
|
+
export type RunEdit<K extends EditableRunKey = EditableRunKey> = {
|
|
60
|
+
[P in K]: {
|
|
61
|
+
key: P;
|
|
62
|
+
value: RunSetting<P> | null;
|
|
63
|
+
};
|
|
64
|
+
}[K];
|
|
65
|
+
/** The settings an rPr built from nothing records */
|
|
66
|
+
export type RunSettings = {
|
|
67
|
+
[K in EditableRunKey]?: RunSetting<K>;
|
|
68
|
+
};
|
|
69
|
+
/** The editable properties, in the order they are read */
|
|
70
|
+
export declare const EDITABLE_RUN_KEYS: readonly EditableRunKey[];
|
|
71
|
+
/**
|
|
72
|
+
* The font names held in a display value.
|
|
73
|
+
* Splits the CSS name list `fontFamilyOf` produced back into individual names.
|
|
74
|
+
*/
|
|
75
|
+
export declare function fontNamesOf(cssNames: string | undefined | null): string[];
|
|
76
|
+
export declare const RUN_PROPERTIES: {
|
|
77
|
+
[K in keyof Required<RunFormat>]: RunProperty<Read<K>, RunSetting<K>>;
|
|
78
|
+
};
|
|
79
|
+
/** Which children of the rPr one job changes and how. null for a value whose meaning cannot be made out */
|
|
80
|
+
export declare function runChildEdits<K extends EditableRunKey>(edit: RunEdit<K>, context: RunEditContext): ChildEdit[] | null;
|
|
81
|
+
/** Whether this text is already in the state the job wants. If it already is, we leave it untouched */
|
|
82
|
+
export declare function matchesRunEdit<K extends EditableRunKey>(format: RunFormat | null, edit: RunEdit<K>): boolean;
|
|
83
|
+
/** The rPr with these children swapped in */
|
|
84
|
+
export declare function withChildEdits(rPr: Props, edits: readonly ChildEdit[]): Props;
|
|
85
|
+
/** Turning formatting on for a run with no formatting creates a minimal rPr from scratch */
|
|
86
|
+
export declare const EMPTY_RUN_PROPS: Props;
|
|
87
|
+
/**
|
|
88
|
+
* A whole rPr recording these settings, built from nothing, and null where they record nothing.
|
|
89
|
+
* A setting the document cannot record is left out, the way an edit refusing it leaves the run
|
|
90
|
+
* as it was.
|
|
91
|
+
*/
|
|
92
|
+
export declare function rPrOf(settings: RunSettings): string | null;
|
|
93
|
+
export {};
|