@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.
Files changed (225) hide show
  1. package/CHANGELOG.md +109 -0
  2. package/CONTRIBUTING.md +5 -1
  3. package/dist/DocxEditor.d.ts +6 -0
  4. package/dist/DocxEditor.js +12 -29
  5. package/dist/core.d.ts +23 -8
  6. package/dist/core.js +9 -4
  7. package/dist/docx/cloning.d.ts +38 -0
  8. package/dist/docx/cloning.js +74 -0
  9. package/dist/docx/commentOnlyChange.d.ts +12 -7
  10. package/dist/docx/commentOnlyChange.js +9 -156
  11. package/dist/docx/comments/constants.d.ts +0 -1
  12. package/dist/docx/comments/constants.js +0 -2
  13. package/dist/docx/comments/grammar.d.ts +10 -4
  14. package/dist/docx/comments/grammar.js +12 -2
  15. package/dist/docx/comments/{verifying.d.ts → parts.d.ts} +26 -18
  16. package/dist/docx/comments/parts.js +279 -0
  17. package/dist/docx/comments/people.d.ts +11 -2
  18. package/dist/docx/comments/people.js +16 -92
  19. package/dist/docx/comments/policy.d.ts +7 -0
  20. package/dist/docx/comments/policy.js +43 -0
  21. package/dist/docx/comments/reading.js +8 -10
  22. package/dist/docx/comments/writing.d.ts +19 -7
  23. package/dist/docx/comments/writing.js +52 -111
  24. package/dist/docx/documentSettings.d.ts +7 -0
  25. package/dist/docx/documentSettings.js +10 -2
  26. package/dist/docx/exportDocx.d.ts +40 -5
  27. package/dist/docx/exportDocx.js +69 -71
  28. package/dist/docx/exportRefs.d.ts +5 -2
  29. package/dist/docx/exportRefs.js +3 -1
  30. package/dist/docx/fidelity.d.ts +43 -0
  31. package/dist/docx/fidelity.js +64 -0
  32. package/dist/docx/formatting/attrs.d.ts +27 -0
  33. package/dist/docx/formatting/attrs.js +31 -0
  34. package/dist/docx/formatting/context.d.ts +31 -0
  35. package/dist/docx/formatting/context.js +42 -0
  36. package/dist/docx/formatting/direct.d.ts +6 -5
  37. package/dist/docx/formatting/direct.js +52 -78
  38. package/dist/docx/formatting/resolve.d.ts +45 -0
  39. package/dist/docx/formatting/resolve.js +140 -0
  40. package/dist/docx/formatting/runProperties.d.ts +93 -0
  41. package/dist/docx/formatting/runProperties.js +316 -0
  42. package/dist/docx/formatting/styles.js +3 -3
  43. package/dist/docx/formatting/tabStops.js +7 -22
  44. package/dist/docx/formatting.d.ts +4 -1
  45. package/dist/docx/formatting.js +4 -1
  46. package/dist/docx/headersFooters.js +6 -13
  47. package/dist/docx/identities.d.ts +67 -0
  48. package/dist/docx/identities.js +174 -0
  49. package/dist/docx/importDocx.d.ts +12 -1
  50. package/dist/docx/importDocx.js +72 -79
  51. package/dist/docx/importParagraph.d.ts +1 -1
  52. package/dist/docx/importParagraph.js +4 -3
  53. package/dist/docx/importTable.d.ts +1 -1
  54. package/dist/docx/importTable.js +17 -1
  55. package/dist/docx/invariants.d.ts +33 -0
  56. package/dist/docx/invariants.js +256 -0
  57. package/dist/docx/media.d.ts +6 -4
  58. package/dist/docx/media.js +6 -37
  59. package/dist/docx/newLists.d.ts +20 -0
  60. package/dist/docx/newLists.js +36 -0
  61. package/dist/docx/notes.js +3 -7
  62. package/dist/docx/numberingPlanner.d.ts +8 -0
  63. package/dist/docx/numberingPlanner.js +19 -0
  64. package/dist/docx/packageParts.d.ts +42 -0
  65. package/dist/docx/packageParts.js +135 -0
  66. package/dist/docx/pageGeometry.d.ts +2 -0
  67. package/dist/docx/pageGeometry.js +18 -9
  68. package/dist/docx/paraProps.d.ts +10 -22
  69. package/dist/docx/paraProps.js +47 -76
  70. package/dist/docx/partPlan.d.ts +36 -0
  71. package/dist/docx/partPlan.js +59 -0
  72. package/dist/docx/protectionPolicy.d.ts +127 -0
  73. package/dist/docx/protectionPolicy.js +169 -0
  74. package/dist/docx/relationships.d.ts +1 -1
  75. package/dist/docx/relationships.js +8 -13
  76. package/dist/docx/runProps.d.ts +9 -22
  77. package/dist/docx/runProps.js +15 -168
  78. package/dist/docx/scan.js +20 -52
  79. package/dist/docx/sdt.js +9 -34
  80. package/dist/docx/sdtProps.d.ts +8 -1
  81. package/dist/docx/sdtProps.js +10 -0
  82. package/dist/docx/serializeBlock.d.ts +2 -0
  83. package/dist/docx/serializeBlock.js +8 -5
  84. package/dist/docx/serializeTable.js +32 -15
  85. package/dist/docx/session.d.ts +42 -14
  86. package/dist/docx/session.js +43 -17
  87. package/dist/docx/tableFormatting/editing.js +108 -139
  88. package/dist/docx/tableFormatting/reading.d.ts +16 -6
  89. package/dist/docx/tableFormatting/reading.js +40 -20
  90. package/dist/docx/tableTemplate.js +18 -7
  91. package/dist/download.d.ts +8 -5
  92. package/dist/download.js +2 -0
  93. package/dist/editor/clipboard/inlineFormatting.js +19 -30
  94. package/dist/editor/commands/comments/editing.d.ts +6 -2
  95. package/dist/editor/commands/comments/editing.js +19 -31
  96. package/dist/editor/commands/exportQueries.d.ts +15 -0
  97. package/dist/editor/commands/exportQueries.js +14 -0
  98. package/dist/editor/commands/fidelityQueries.d.ts +12 -0
  99. package/dist/editor/commands/fidelityQueries.js +8 -0
  100. package/dist/editor/commands/formatting/editing.d.ts +2 -2
  101. package/dist/editor/commands/formatting/editing.js +26 -108
  102. package/dist/editor/commands/formatting/propertyCommands.d.ts +21 -0
  103. package/dist/editor/commands/formatting/propertyCommands.js +103 -0
  104. package/dist/editor/commands/formatting/shared.d.ts +3 -3
  105. package/dist/editor/commands/formatting/shared.js +5 -2
  106. package/dist/editor/commands/indentCommands.js +5 -4
  107. package/dist/editor/commands/index.d.ts +11 -0
  108. package/dist/editor/commands/index.js +5 -0
  109. package/dist/editor/commands/linkCommands.js +5 -6
  110. package/dist/editor/commands/listCommands.js +8 -10
  111. package/dist/editor/commands/lockCommands.d.ts +7 -1
  112. package/dist/editor/commands/lockCommands.js +35 -46
  113. package/dist/editor/commands/paragraphCommands.js +28 -31
  114. package/dist/editor/commands/spacingCommands.js +1 -1
  115. package/dist/editor/createEditor.d.ts +17 -29
  116. package/dist/editor/createEditor.js +58 -58
  117. package/dist/editor/documentStyles.d.ts +11 -35
  118. package/dist/editor/documentStyles.js +9 -52
  119. package/dist/editor/editorDocument.d.ts +56 -0
  120. package/dist/editor/editorDocument.js +74 -0
  121. package/dist/editor/externalClipboard.js +16 -45
  122. package/dist/editor/insertTable.js +4 -3
  123. package/dist/editor/paragraphEdits.d.ts +11 -18
  124. package/dist/editor/paragraphEdits.js +7 -16
  125. package/dist/editor/plugins/displayDerivation.d.ts +47 -0
  126. package/dist/editor/plugins/displayDerivation.js +78 -0
  127. package/dist/editor/plugins/imagePaste.js +4 -3
  128. package/dist/editor/plugins/keymap.js +18 -3
  129. package/dist/editor/plugins/numberingDecorations.d.ts +5 -11
  130. package/dist/editor/plugins/numberingDecorations.js +7 -17
  131. package/dist/editor/plugins/paragraphDisplay.d.ts +7 -0
  132. package/dist/editor/plugins/paragraphDisplay.js +51 -0
  133. package/dist/editor/plugins/tabLayout.js +1 -1
  134. package/dist/editor/plugins/tableDisplay.d.ts +6 -0
  135. package/dist/editor/plugins/tableDisplay.js +16 -0
  136. package/dist/index.d.ts +2 -0
  137. package/dist/model/format.d.ts +30 -8
  138. package/dist/model/format.js +35 -22
  139. package/dist/model/tabStops.d.ts +9 -0
  140. package/dist/model/tabStops.js +18 -0
  141. package/dist/numbering/listTemplate.js +24 -7
  142. package/dist/numbering/parseNumbering.d.ts +14 -1
  143. package/dist/numbering/parseNumbering.js +35 -22
  144. package/dist/numbering/writeNumbering.d.ts +3 -4
  145. package/dist/numbering/writeNumbering.js +14 -25
  146. package/dist/ooxml/childOrder.d.ts +34 -0
  147. package/dist/ooxml/childOrder.js +496 -0
  148. package/dist/ooxml/element.d.ts +24 -11
  149. package/dist/ooxml/element.js +31 -12
  150. package/dist/ooxml/errors.d.ts +3 -2
  151. package/dist/ooxml/image.d.ts +4 -0
  152. package/dist/ooxml/image.js +2 -5
  153. package/dist/ooxml/partSplice.d.ts +67 -0
  154. package/dist/ooxml/partSplice.js +169 -0
  155. package/dist/ooxml/props.d.ts +112 -0
  156. package/dist/{docx/propsXml.js → ooxml/props.js} +72 -200
  157. package/dist/ooxml/simpleTypes.d.ts +103 -0
  158. package/dist/ooxml/simpleTypes.js +182 -0
  159. package/dist/ooxml/tabStops.js +8 -27
  160. package/dist/ooxml/tagScan.d.ts +34 -0
  161. package/dist/ooxml/tagScan.js +108 -0
  162. package/dist/ooxml/units.d.ts +25 -13
  163. package/dist/ooxml/units.js +65 -31
  164. package/dist/ooxml/xml.d.ts +27 -6
  165. package/dist/ooxml/xml.js +37 -5
  166. package/dist/page/blockKinds.d.ts +61 -0
  167. package/dist/page/blockKinds.js +11 -0
  168. package/dist/page/kinds/index.d.ts +6 -0
  169. package/dist/page/kinds/index.js +10 -0
  170. package/dist/page/kinds/paragraphKind.d.ts +10 -0
  171. package/dist/page/kinds/paragraphKind.js +71 -0
  172. package/dist/page/kinds/tableKind.d.ts +10 -0
  173. package/dist/page/kinds/tableKind.js +178 -0
  174. package/dist/page/measureBlocks.d.ts +3 -14
  175. package/dist/page/measureBlocks.js +24 -45
  176. package/dist/page/pageDecorations.d.ts +27 -44
  177. package/dist/page/pageDecorations.js +70 -152
  178. package/dist/page/pageLayout.d.ts +2 -19
  179. package/dist/page/pageLayout.js +36 -6
  180. package/dist/page/usePageLayout.d.ts +2 -17
  181. package/dist/page/usePageLayout.js +3 -39
  182. package/dist/schema/attrRoles.d.ts +25 -18
  183. package/dist/schema/attrRoles.js +102 -67
  184. package/dist/schema/displayDerivation.d.ts +82 -0
  185. package/dist/schema/displayDerivation.js +130 -0
  186. package/dist/schema/docxSchema.d.ts +3 -0
  187. package/dist/schema/docxSchema.js +26 -14
  188. package/dist/schema/editGuard.d.ts +1 -1
  189. package/dist/schema/guards.d.ts +37 -14
  190. package/dist/schema/guards.js +29 -3
  191. package/dist/schema/index.d.ts +2 -0
  192. package/dist/schema/index.js +2 -0
  193. package/dist/schema/locks.d.ts +11 -44
  194. package/dist/schema/locks.js +0 -9
  195. package/dist/schema/preservedGuards.d.ts +26 -6
  196. package/dist/schema/preservedGuards.js +31 -1
  197. package/dist/schema/protection.d.ts +7 -1
  198. package/dist/schema/protection.js +2 -1
  199. package/dist/schema/sourceEquality.d.ts +1 -9
  200. package/dist/schema/sourceEquality.js +1 -27
  201. package/dist/styles/inlineStyle.js +15 -6
  202. package/dist/table/cellFormatting.d.ts +8 -1
  203. package/dist/table/cellFormatting.js +10 -18
  204. package/dist/table/commands.js +20 -18
  205. package/dist/table/format.d.ts +3 -0
  206. package/dist/table/format.js +3 -9
  207. package/dist/table/gridBorders.d.ts +14 -16
  208. package/dist/table/gridBorders.js +3 -41
  209. package/dist/table/merge.d.ts +2 -6
  210. package/dist/table/merge.js +5 -5
  211. package/package.json +7 -3
  212. package/dist/docx/comments/contentTypes.d.ts +0 -7
  213. package/dist/docx/comments/contentTypes.js +0 -38
  214. package/dist/docx/comments/verifying.js +0 -206
  215. package/dist/docx/formatting/effectiveParagraph.d.ts +0 -15
  216. package/dist/docx/formatting/effectiveParagraph.js +0 -81
  217. package/dist/docx/propsXml.d.ts +0 -67
  218. package/dist/docx/uniqueControls.d.ts +0 -14
  219. package/dist/docx/uniqueControls.js +0 -62
  220. package/dist/editor/plugins/commentReservations.d.ts +0 -5
  221. package/dist/editor/plugins/commentReservations.js +0 -26
  222. package/dist/editor/plugins/styledParagraphs.d.ts +0 -15
  223. package/dist/editor/plugins/styledParagraphs.js +0 -65
  224. package/dist/page/tableMeasurements.d.ts +0 -18
  225. package/dist/page/tableMeasurements.js +0 -119
@@ -0,0 +1,316 @@
1
+ // src/docx/formatting/runProperties.ts
2
+ import {
3
+ isHighlightName,
4
+ isUnderlineKind,
5
+ NO_FILL,
6
+ RUN_FORMAT_KEYS
7
+ } from "../../model/format.js";
8
+ import { elementXml, wAttrValue } from "../../ooxml/element.js";
9
+ import { wName } from "../../ooxml/names.js";
10
+ import { overridingAttrs, setAttr } from "../../ooxml/precedence.js";
11
+ import {
12
+ attrsOf,
13
+ parseProps,
14
+ propsChild,
15
+ renderProps,
16
+ setChild
17
+ } from "../../ooxml/props.js";
18
+ import {
19
+ HALF_POINTS_PER_PT,
20
+ ST_HpsMeasure,
21
+ ST_SignedTwipsMeasure,
22
+ TWIPS_PER_PT
23
+ } from "../../ooxml/simpleTypes.js";
24
+ import {
25
+ childValue,
26
+ halfPointsToPt,
27
+ isOnElement,
28
+ normalizeHex,
29
+ shadingOf,
30
+ toHexColor,
31
+ twipsToPt,
32
+ wAttr
33
+ } from "../../ooxml/units.js";
34
+ import { childByLocalName } from "../../ooxml/xml.js";
35
+ import { isEastAsianFontName } from "../../styles/fontStack.js";
36
+ import { themeFontName } from "../theme.js";
37
+ var DISPLAY_ONLY_RUN_KEYS = ["lang"];
38
+ function isEditableRunKey(key) {
39
+ return !DISPLAY_ONLY_RUN_KEYS.some((display) => display === key);
40
+ }
41
+ var EDITABLE_RUN_KEYS = RUN_FORMAT_KEYS.filter(isEditableRunKey);
42
+ function valXml(name, value) {
43
+ return elementXml(wName(name), value === null ? [] : [[wName("val"), value]]);
44
+ }
45
+ function shadingXml(fill) {
46
+ return elementXml(wName("shd"), [
47
+ [wName("val"), "clear"],
48
+ [wName("color"), "auto"],
49
+ [wName("fill"), fill]
50
+ ]);
51
+ }
52
+ function toggleState(rPr, name) {
53
+ const toggle2 = childByLocalName(rPr, name);
54
+ return toggle2 ? isOnElement(toggle2) : null;
55
+ }
56
+ function fontNamesOf(cssNames) {
57
+ if (!cssNames) return [];
58
+ return cssNames.split(",").map((name) => name.trim().replace(/^"|"$/g, "")).filter((name) => name.length > 0);
59
+ }
60
+ var FONT_SLOTS = ["ascii", "eastAsia", "hAnsi", "cs"];
61
+ function slotFontName(rFonts, slot, themeFonts) {
62
+ const written2 = wAttr(rFonts, slot);
63
+ if (written2 !== null) return written2;
64
+ for (const attr of overridingAttrs("rFonts", slot)) {
65
+ const resolved = themeFontName(themeFonts, wAttr(rFonts, attr));
66
+ if (resolved !== null) return resolved;
67
+ }
68
+ return null;
69
+ }
70
+ function fontFamilyOf(rFonts, themeFonts) {
71
+ const names = FONT_SLOTS.map((slot) => slotFontName(rFonts, slot, themeFonts)).filter((name) => name !== null).filter((name) => name.length > 0 && !/["';\\]/.test(name));
72
+ const unique = Array.from(new Set(names));
73
+ return unique.length > 0 ? unique.map((name) => `"${name}"`).join(",") : null;
74
+ }
75
+ var LATIN_SLOTS = ["ascii", "hAnsi"];
76
+ var EAST_ASIAN_SLOTS = [...LATIN_SLOTS, "eastAsia"];
77
+ function fontSlots(name, hasComplexScript) {
78
+ const slots = isEastAsianFontName(name) ? EAST_ASIAN_SLOTS : LATIN_SLOTS;
79
+ return hasComplexScript ? [...slots, "cs"] : slots;
80
+ }
81
+ function fontName(value) {
82
+ const name = value.trim();
83
+ return name.length > 0 && !/["';<>&]/.test(name) ? name : null;
84
+ }
85
+ function rFontsXml(current, name) {
86
+ const props = current === null ? null : parseProps(current);
87
+ const attrs = props === null ? [] : attrsOf(props);
88
+ if (current !== null && props === null || attrs === null) return null;
89
+ const slots = fontSlots(name, wAttrValue(attrs, "cs") !== null);
90
+ const kept = slots.reduce(
91
+ (rest, slot) => setAttr(rest, "rFonts", slot, null),
92
+ attrs
93
+ );
94
+ return elementXml(wName("rFonts"), [
95
+ ...slots.map((slot) => [wName(slot), name]),
96
+ ...kept
97
+ ]);
98
+ }
99
+ function langOf(rPr) {
100
+ const lang = childByLocalName(rPr, "lang");
101
+ if (!lang) return null;
102
+ const eastAsia = wAttr(lang, "eastAsia");
103
+ if (eastAsia !== null && eastAsia.length > 0) return eastAsia;
104
+ const value = wAttr(lang, "val");
105
+ return value !== null && value.length > 0 ? value : null;
106
+ }
107
+ var VERTICAL_ALIGN_BY_VAL = {
108
+ superscript: "superscript",
109
+ subscript: "subscript"
110
+ };
111
+ function removed(children) {
112
+ return children.map((name) => [name, null]);
113
+ }
114
+ function toggle(key, name, ...twins) {
115
+ const children = [name, ...twins];
116
+ const isOn = (format) => format[key] === true;
117
+ return {
118
+ children,
119
+ read: (rPr) => toggleState(rPr, name) ?? void 0,
120
+ isOn,
121
+ matches: isOn,
122
+ write: () => children.map((child) => [child, valXml(child, null)]),
123
+ off: ({ inherited }) => isOn(inherited) ? children.map((child) => [child, valXml(child, "0")]) : removed(children)
124
+ };
125
+ }
126
+ var UNDERLINE = {
127
+ children: ["u"],
128
+ read: (rPr) => {
129
+ const kind = childValue(rPr, "u");
130
+ return isUnderlineKind(kind) || kind === "none" ? kind : void 0;
131
+ },
132
+ isOn: (format) => format.underline !== void 0 && format.underline !== "none",
133
+ matches: (format, kind) => format.underline === kind,
134
+ write: (kind) => [["u", valXml("u", kind)]],
135
+ off: ({ inherited }) => [
136
+ ["u", UNDERLINE.isOn(inherited) ? valXml("u", "none") : null]
137
+ ]
138
+ };
139
+ var FONT_SIZE = {
140
+ children: ["sz", "szCs"],
141
+ read: (rPr) => halfPointsToPt(ST_HpsMeasure.parse(childValue(rPr, "sz"))) ?? void 0,
142
+ isOn: (format) => format.fontSizePt !== void 0,
143
+ matches: (format, pt) => format.fontSizePt === pt,
144
+ write: (pt) => {
145
+ const half = ST_HpsMeasure.format(pt * HALF_POINTS_PER_PT);
146
+ return half === null ? null : [
147
+ ["sz", valXml("sz", half)],
148
+ ["szCs", valXml("szCs", half)]
149
+ ];
150
+ },
151
+ off: () => removed(FONT_SIZE.children)
152
+ };
153
+ var CHARACTER_SPACING = {
154
+ children: ["spacing"],
155
+ read: (rPr) => twipsToPt(ST_SignedTwipsMeasure.parse(childValue(rPr, "spacing"))) ?? void 0,
156
+ isOn: (format) => format.characterSpacingPt !== void 0,
157
+ matches: (format, pt) => format.characterSpacingPt === pt,
158
+ write: (pt) => {
159
+ const twips = ST_SignedTwipsMeasure.format(Math.round(pt * TWIPS_PER_PT));
160
+ return twips === null ? null : [["spacing", valXml("spacing", twips)]];
161
+ },
162
+ off: () => removed(CHARACTER_SPACING.children)
163
+ };
164
+ var FONT_FAMILY = {
165
+ children: ["rFonts"],
166
+ read: (rPr, themeFonts) => {
167
+ const rFonts = childByLocalName(rPr, "rFonts");
168
+ return rFonts ? fontFamilyOf(rFonts, themeFonts) ?? void 0 : void 0;
169
+ },
170
+ isOn: (format) => fontNamesOf(format.fontFamily).length > 0,
171
+ matches: (format, name) => {
172
+ const names = fontNamesOf(format.fontFamily);
173
+ return names.length === 1 && names[0] === fontName(name);
174
+ },
175
+ write: (name, { rPr }) => {
176
+ const clean = fontName(name);
177
+ if (clean === null) return null;
178
+ const xml = rFontsXml(
179
+ propsChild(rPr.children, "rFonts")?.xml ?? null,
180
+ clean
181
+ );
182
+ return xml === null ? null : [["rFonts", xml]];
183
+ },
184
+ off: () => removed(FONT_FAMILY.children)
185
+ };
186
+ var COLOR = {
187
+ children: ["color"],
188
+ read: (rPr) => toHexColor(childValue(rPr, "color")) ?? void 0,
189
+ isOn: (format) => format.color !== void 0,
190
+ // Colors differing only in capitalization are the same color
191
+ matches: (format, hex) => format.color !== void 0 && normalizeHex(format.color) === normalizeHex(hex),
192
+ write: (hex) => {
193
+ const value = normalizeHex(hex);
194
+ return value === null ? null : [["color", valXml("color", value)]];
195
+ },
196
+ off: ({ inherited }) => [
197
+ ["color", inherited.color === void 0 ? null : valXml("color", "auto")]
198
+ ]
199
+ };
200
+ var HIGHLIGHT = {
201
+ children: ["highlight"],
202
+ read: (rPr) => {
203
+ const name = childValue(rPr, "highlight");
204
+ return isHighlightName(name) ? name : void 0;
205
+ },
206
+ isOn: (format) => format.highlight !== void 0,
207
+ matches: (format, name) => format.highlight === name,
208
+ write: (name) => [["highlight", valXml("highlight", name)]],
209
+ off: ({ inherited }) => [
210
+ [
211
+ "highlight",
212
+ inherited.highlight === void 0 ? null : valXml("highlight", "none")
213
+ ]
214
+ ]
215
+ };
216
+ var BACKGROUND = {
217
+ children: ["highlight", "shd"],
218
+ read: (rPr) => shadingOf(rPr) ?? void 0,
219
+ isOn: (format) => format.highlight !== void 0 || format.background !== void 0 && format.background !== NO_FILL,
220
+ matches: (format, hex) => {
221
+ const fill = normalizeHex(hex);
222
+ return fill !== null && format.highlight === void 0 && format.background !== void 0 && normalizeHex(format.background) === fill;
223
+ },
224
+ write: (hex, context) => {
225
+ const fill = normalizeHex(hex);
226
+ return fill === null ? null : [["shd", shadingXml(fill)], ...HIGHLIGHT.off(context)];
227
+ },
228
+ off: (context) => {
229
+ const painted = context.inherited.background !== void 0 && context.inherited.background !== NO_FILL;
230
+ return [
231
+ ["shd", painted ? shadingXml("auto") : null],
232
+ ...HIGHLIGHT.off(context)
233
+ ];
234
+ }
235
+ };
236
+ var VERTICAL_ALIGN = {
237
+ children: ["vertAlign"],
238
+ read: (rPr) => VERTICAL_ALIGN_BY_VAL[childValue(rPr, "vertAlign") ?? ""],
239
+ isOn: (format) => format.verticalAlign !== void 0,
240
+ matches: (format, align) => format.verticalAlign === align,
241
+ write: (align) => [["vertAlign", valXml("vertAlign", align)]],
242
+ off: ({ inherited }) => [
243
+ [
244
+ "vertAlign",
245
+ inherited.verticalAlign === void 0 ? null : valXml("vertAlign", "baseline")
246
+ ]
247
+ ]
248
+ };
249
+ var LANG = {
250
+ children: ["lang"],
251
+ read: (rPr) => langOf(rPr) ?? void 0,
252
+ isOn: (format) => format.lang !== void 0,
253
+ matches: (format, tag) => format.lang === tag
254
+ };
255
+ var EDITABLE_RUN_PROPERTIES = {
256
+ bold: toggle("bold", "b", "bCs"),
257
+ italic: toggle("italic", "i", "iCs"),
258
+ strike: toggle("strike", "strike"),
259
+ doubleStrike: toggle("doubleStrike", "dstrike"),
260
+ smallCaps: toggle("smallCaps", "smallCaps"),
261
+ caps: toggle("caps", "caps"),
262
+ underline: UNDERLINE,
263
+ fontSizePt: FONT_SIZE,
264
+ characterSpacingPt: CHARACTER_SPACING,
265
+ fontFamily: FONT_FAMILY,
266
+ color: COLOR,
267
+ highlight: HIGHLIGHT,
268
+ background: BACKGROUND,
269
+ verticalAlign: VERTICAL_ALIGN
270
+ };
271
+ var DISPLAY_ONLY_RUN_PROPERTIES = { lang: LANG };
272
+ var RUN_PROPERTIES = { ...EDITABLE_RUN_PROPERTIES, ...DISPLAY_ONLY_RUN_PROPERTIES };
273
+ function runChildEdits(edit, context) {
274
+ const property = EDITABLE_RUN_PROPERTIES[edit.key];
275
+ return edit.value === null ? property.off(context) : property.write(edit.value, context);
276
+ }
277
+ function matchesRunEdit(format, edit) {
278
+ const property = RUN_PROPERTIES[edit.key];
279
+ const values = format ?? {};
280
+ return edit.value === null ? !property.isOn(values) : property.matches(values, edit.value);
281
+ }
282
+ function withChildEdits(rPr, edits) {
283
+ return edits.reduce((kept, [name, xml]) => setChild(kept, name, xml), rPr);
284
+ }
285
+ var EMPTY_RUN_PROPS = {
286
+ tag: wName("rPr"),
287
+ attrs: null,
288
+ children: []
289
+ };
290
+ function written(rPr, key, value) {
291
+ if (value === void 0) return rPr;
292
+ const edits = EDITABLE_RUN_PROPERTIES[key].write(value, {
293
+ rPr,
294
+ inherited: {}
295
+ });
296
+ return edits === null ? rPr : withChildEdits(rPr, edits);
297
+ }
298
+ function rPrOf(settings) {
299
+ const rPr = renderProps(
300
+ EDITABLE_RUN_KEYS.reduce(
301
+ (kept, key) => written(kept, key, settings[key]),
302
+ EMPTY_RUN_PROPS
303
+ )
304
+ );
305
+ return rPr === "" ? null : rPr;
306
+ }
307
+ export {
308
+ EDITABLE_RUN_KEYS,
309
+ EMPTY_RUN_PROPS,
310
+ RUN_PROPERTIES,
311
+ fontNamesOf,
312
+ matchesRunEdit,
313
+ rPrOf,
314
+ runChildEdits,
315
+ withChildEdits
316
+ };
@@ -4,9 +4,10 @@ import {
4
4
  toRunFormat,
5
5
  toTableFormat
6
6
  } from "../../model/format.js";
7
+ import { parsePropsXml } from "../../ooxml/props.js";
8
+ import { ST_OnOff } from "../../ooxml/simpleTypes.js";
7
9
  import { childValue, isOn, wAttr } from "../../ooxml/units.js";
8
10
  import { childByLocalName, elementChildren } from "../../ooxml/xml.js";
9
- import { parsePropsXml } from "../propsXml.js";
10
11
  import {
11
12
  layerCellMargins,
12
13
  layerInsideBorders,
@@ -84,8 +85,7 @@ function readStyles(styles, themeFonts = NO_THEME_FONTS) {
84
85
  return table;
85
86
  }
86
87
  function isDefaultStyle(el) {
87
- const value = wAttr(el, "default");
88
- return value === "1" || value === "true";
88
+ return ST_OnOff.parse(wAttr(el, "default")) === true;
89
89
  }
90
90
  function defaultStyleIdOf(styles, type) {
91
91
  let found = null;
@@ -3,39 +3,24 @@ import { toParagraphFormat } from "../../model/format.js";
3
3
  import {
4
4
  layerTabStopDirectives
5
5
  } from "../../model/tabStops.js";
6
+ import { ST_TabJc, ST_TabTlc } from "../../ooxml/simpleTypes.js";
6
7
  function isRecord(value) {
7
8
  return typeof value === "object" && value !== null && !Array.isArray(value);
8
9
  }
9
- var ALIGNMENTS = /* @__PURE__ */ new Set([
10
- "start",
11
- "center",
12
- "end",
13
- "decimal",
14
- "num",
15
- "bar",
16
- "clear"
17
- ]);
18
- var LEADERS = /* @__PURE__ */ new Set([
19
- "none",
20
- "dot",
21
- "hyphen",
22
- "underscore",
23
- "heavy",
24
- "middleDot"
25
- ]);
26
10
  function toTabStopDirective(value) {
27
- if (!isRecord(value) || typeof value.positionPt !== "number" || !Number.isFinite(value.positionPt) || typeof value.align !== "string" || !ALIGNMENTS.has(value.align)) {
11
+ if (!isRecord(value) || typeof value.positionPt !== "number" || !Number.isFinite(value.positionPt)) {
28
12
  return null;
29
13
  }
30
- if (value.align === "clear") {
14
+ const align = typeof value.align === "string" ? ST_TabJc.parse(value.align) : null;
15
+ if (align === null) return null;
16
+ if (align === "clear") {
31
17
  return { positionPt: value.positionPt, align: "clear" };
32
18
  }
33
- const align = value.align;
34
- const leader = typeof value.leader === "string" && LEADERS.has(value.leader) ? value.leader : void 0;
19
+ const leader = typeof value.leader === "string" ? ST_TabTlc.parse(value.leader) : null;
35
20
  return {
36
21
  positionPt: value.positionPt,
37
22
  align,
38
- ...leader === void 0 ? {} : { leader }
23
+ ...leader === null ? {} : { leader }
39
24
  };
40
25
  }
41
26
  function toParagraphFormatLayer(value) {
@@ -1,4 +1,7 @@
1
+ export * from "./formatting/attrs";
2
+ export * from "./formatting/context";
1
3
  export * from "./formatting/direct";
2
- export * from "./formatting/effectiveParagraph";
4
+ export * from "./formatting/resolve";
5
+ export * from "./formatting/runProperties";
3
6
  export * from "./formatting/styles";
4
7
  export type { ParagraphFormatLayer } from "./formatting/tabStops";
@@ -1,4 +1,7 @@
1
1
  // src/docx/formatting.ts
2
+ export * from "./formatting/attrs.js";
3
+ export * from "./formatting/context.js";
2
4
  export * from "./formatting/direct.js";
3
- export * from "./formatting/effectiveParagraph.js";
5
+ export * from "./formatting/resolve.js";
6
+ export * from "./formatting/runProperties.js";
4
7
  export * from "./formatting/styles.js";
@@ -1,5 +1,5 @@
1
1
  // src/docx/headersFooters.ts
2
- import { ALIGN_BY_JC } from "../ooxml/units.js";
2
+ import { ALIGN_BY_JC, isOnElement } from "../ooxml/units.js";
3
3
  import {
4
4
  attributeByLocalName,
5
5
  decodeUtf8,
@@ -8,6 +8,7 @@ import {
8
8
  R_NS,
9
9
  W_NS
10
10
  } from "../ooxml/xml.js";
11
+ import { relatedPartPath } from "./packageParts.js";
11
12
  import { readRelationships, relsPathOf, resolveTarget } from "./relationships.js";
12
13
  var EMPTY_VARIANTS = {
13
14
  default: null,
@@ -21,11 +22,6 @@ var NO_HEADERS_FOOTERS = {
21
22
  evenAndOdd: false,
22
23
  pageNumberStart: 1
23
24
  };
24
- function isOn(el) {
25
- if (!el) return false;
26
- const value = attributeByLocalName(el, "val")?.toLowerCase();
27
- return value !== "0" && value !== "false" && value !== "off";
28
- }
29
25
  function firstSectPrIn(root) {
30
26
  const namespaced = root.getElementsByTagNameNS(W_NS, "sectPr").item(0);
31
27
  if (namespaced) return namespaced;
@@ -131,15 +127,12 @@ function readContent(bytes) {
131
127
  };
132
128
  }
133
129
  function settingsEvenAndOdd(parts, mainPartPath) {
134
- const relationship = readRelationships(parts, relsPathOf(mainPartPath)).find(
135
- (entry) => entry.type === `${R_NS}/settings` && !entry.external
136
- );
137
- if (!relationship) return false;
138
- const bytes = parts.get(resolveTarget(mainPartPath, relationship.target));
130
+ const path = relatedPartPath(parts, mainPartPath, `${R_NS}/settings`);
131
+ const bytes = path === null ? void 0 : parts.get(path);
139
132
  if (!bytes) return false;
140
133
  const root = parseXml(decodeUtf8(bytes).text).documentElement;
141
134
  const setting = root.getElementsByTagNameNS(W_NS, "evenAndOddHeaders").item(0);
142
- return isOn(setting);
135
+ return isOnElement(setting);
143
136
  }
144
137
  function readVariants(parts, mainPartPath, sectPr, kind) {
145
138
  const relationships = new Map(
@@ -179,7 +172,7 @@ function readHeadersFooters(parts, mainPartPath, body) {
179
172
  return {
180
173
  headers: readVariants(parts, mainPartPath, sectPr, "header"),
181
174
  footers: readVariants(parts, mainPartPath, sectPr, "footer"),
182
- firstPageDifferent: isOn(
175
+ firstPageDifferent: isOnElement(
183
176
  elementChildren(sectPr).find((child) => child.localName === "titlePg") ?? null
184
177
  ),
185
178
  evenAndOdd: settingsEvenAndOdd(parts, mainPartPath),
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Settling, just before export, every name that may be held by one node only.
3
+ *
4
+ * An edit can leave one name standing in two places: splitting a paragraph inside a content
5
+ * control leaves that control in both halves, and dropping a copy of a paragraph carries the
6
+ * original's identifiers along with it. Each name a document must keep unique is one rule here,
7
+ * and the pass walks the blocks once in document order, so the first node to claim a name keeps it
8
+ * and every later claimant gives it up.
9
+ *
10
+ * A document nobody broke apart comes back node for node as it was, which is what keeps an
11
+ * unedited block going out as its original XML.
12
+ *
13
+ * The one walk answers two callers: `withUniqueIdentities` hands the writer the settled document
14
+ * and throws over a block that cannot yield, and `identityProblems` runs the same walk for
15
+ * `docx/invariants` and lists those blocks instead, so what the query reports and what the write
16
+ * refuses cannot come apart.
17
+ */
18
+ import { type Node as PMNode } from "prosemirror-model";
19
+ import { type DocxExportErrorCode } from "../ooxml/errors";
20
+ export interface IdentityRule {
21
+ readonly name: string;
22
+ /**
23
+ * The block to write in place of `block`, with every name it claims that `written` already holds
24
+ * given up, and the names it keeps added to `written`. Returns `block` itself when nothing
25
+ * changes. null means the block cannot yield and the export must refuse. A block's children are
26
+ * not visited here; the walker visits them after this call.
27
+ */
28
+ visit(block: PMNode, written: Set<string>): PMNode | null;
29
+ }
30
+ /**
31
+ * The block a node was opened from, which `docx/exportDocx` writes the original bytes back for.
32
+ * A second node claiming the same block is written from its own attrs instead, and a block that
33
+ * exists only as its original XML has nothing to be written from, so it cannot yield.
34
+ */
35
+ export declare const sourceBlockRule: IdentityRule;
36
+ /**
37
+ * A later paragraph carrying an identifier already written goes out without one, and without its
38
+ * `w14:textId` too, which may not stand without a `w14:paraId` beside it. The walker reaches the
39
+ * paragraphs inside a table, so the rule reads the one block it is handed.
40
+ */
41
+ export declare const paragraphIdRule: IdentityRule;
42
+ /**
43
+ * A content control cannot cross a paragraph, so splitting a paragraph in the middle of one leaves
44
+ * that same control standing in two, and dropping unmarked text into the middle of one breaks it
45
+ * in two within the paragraph. Each piece after the first opens as a copy with a `w:id` of its
46
+ * own (see `docx/sdt` for what a copy must not carry along).
47
+ */
48
+ export declare const controlRule: IdentityRule;
49
+ /**
50
+ * In the order they apply to one block: the source rule first, so that a second claimant of a
51
+ * block is already a rebuilt paragraph by the time the paragraph rule takes its identifier away.
52
+ */
53
+ export declare const IDENTITY_RULES: readonly IdentityRule[];
54
+ /** A block that cannot yield: what the export refuses it with, and where it stands in the document */
55
+ export interface IdentityProblem {
56
+ readonly code: DocxExportErrorCode;
57
+ readonly message: string;
58
+ readonly pos: number;
59
+ }
60
+ /** The document with every later claimant of a name released, in document order */
61
+ export declare function withUniqueIdentities(doc: PMNode, rules?: readonly IdentityRule[]): PMNode;
62
+ /**
63
+ * Every block `withUniqueIdentities` would refuse over, in document order, each where it stands;
64
+ * empty when the pass would go through. The pass is run as the export runs it and its settled
65
+ * document is dropped, so a caller asking ahead of the write reads the same refusal it would throw.
66
+ */
67
+ export declare function identityProblems(doc: PMNode, rules?: readonly IdentityRule[]): readonly IdentityProblem[];