@portone/docx-editor 0.2.1 → 0.4.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 (253) hide show
  1. package/CHANGELOG.md +155 -0
  2. package/CONTRIBUTING.md +5 -1
  3. package/dist/DocxEditor.d.ts +6 -0
  4. package/dist/DocxEditor.js +13 -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 +59 -112
  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 +88 -74
  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 +45 -0
  33. package/dist/docx/formatting/attrs.js +86 -0
  34. package/dist/docx/formatting/context.d.ts +39 -0
  35. package/dist/docx/formatting/context.js +60 -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 +51 -0
  39. package/dist/docx/formatting/resolve.js +160 -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.d.ts +25 -2
  43. package/dist/docx/formatting/styles.js +87 -6
  44. package/dist/docx/formatting/tabStops.js +7 -22
  45. package/dist/docx/formatting.d.ts +4 -1
  46. package/dist/docx/formatting.js +4 -1
  47. package/dist/docx/headersFooters.js +6 -13
  48. package/dist/docx/hyperlink.d.ts +14 -4
  49. package/dist/docx/hyperlink.js +4 -1
  50. package/dist/docx/identities.d.ts +67 -0
  51. package/dist/docx/identities.js +174 -0
  52. package/dist/docx/importDocx.d.ts +12 -1
  53. package/dist/docx/importDocx.js +90 -88
  54. package/dist/docx/importParagraph.d.ts +1 -1
  55. package/dist/docx/importParagraph.js +4 -3
  56. package/dist/docx/importTable.d.ts +2 -2
  57. package/dist/docx/importTable.js +69 -56
  58. package/dist/docx/invariants.d.ts +33 -0
  59. package/dist/docx/invariants.js +269 -0
  60. package/dist/docx/media.d.ts +6 -4
  61. package/dist/docx/media.js +6 -37
  62. package/dist/docx/newLists.d.ts +50 -0
  63. package/dist/docx/newLists.js +59 -0
  64. package/dist/docx/notes.js +3 -7
  65. package/dist/docx/numberingPlanner.d.ts +11 -0
  66. package/dist/docx/numberingPlanner.js +50 -0
  67. package/dist/docx/packageParts.d.ts +42 -0
  68. package/dist/docx/packageParts.js +135 -0
  69. package/dist/docx/pageGeometry.d.ts +2 -0
  70. package/dist/docx/pageGeometry.js +18 -9
  71. package/dist/docx/paraProps.d.ts +10 -22
  72. package/dist/docx/paraProps.js +47 -76
  73. package/dist/docx/partPlan.d.ts +36 -0
  74. package/dist/docx/partPlan.js +59 -0
  75. package/dist/docx/protectionPolicy.d.ts +127 -0
  76. package/dist/docx/protectionPolicy.js +169 -0
  77. package/dist/docx/relationships.d.ts +1 -1
  78. package/dist/docx/relationships.js +8 -13
  79. package/dist/docx/runProps.d.ts +9 -22
  80. package/dist/docx/runProps.js +15 -168
  81. package/dist/docx/scan.js +20 -52
  82. package/dist/docx/sdt.js +9 -34
  83. package/dist/docx/sdtProps.d.ts +8 -1
  84. package/dist/docx/sdtProps.js +10 -0
  85. package/dist/docx/serializeBlock.d.ts +2 -0
  86. package/dist/docx/serializeBlock.js +8 -5
  87. package/dist/docx/serializeTable.js +32 -15
  88. package/dist/docx/session.d.ts +42 -14
  89. package/dist/docx/session.js +53 -17
  90. package/dist/docx/tableFormatting/conditions.d.ts +76 -0
  91. package/dist/docx/tableFormatting/conditions.js +196 -0
  92. package/dist/docx/tableFormatting/editing.d.ts +7 -3
  93. package/dist/docx/tableFormatting/editing.js +111 -143
  94. package/dist/docx/tableFormatting/reading.d.ts +63 -23
  95. package/dist/docx/tableFormatting/reading.js +132 -38
  96. package/dist/docx/tableFormatting.d.ts +1 -0
  97. package/dist/docx/tableFormatting.js +1 -0
  98. package/dist/docx/tableTemplate.js +30 -19
  99. package/dist/download.d.ts +8 -5
  100. package/dist/download.js +2 -0
  101. package/dist/editor/clipboard/inlineFormatting.js +19 -30
  102. package/dist/editor/commands/comments/editing.d.ts +6 -2
  103. package/dist/editor/commands/comments/editing.js +19 -31
  104. package/dist/editor/commands/exportQueries.d.ts +15 -0
  105. package/dist/editor/commands/exportQueries.js +14 -0
  106. package/dist/editor/commands/fidelityQueries.d.ts +12 -0
  107. package/dist/editor/commands/fidelityQueries.js +8 -0
  108. package/dist/editor/commands/formatting/editing.d.ts +2 -2
  109. package/dist/editor/commands/formatting/editing.js +26 -108
  110. package/dist/editor/commands/formatting/propertyCommands.d.ts +21 -0
  111. package/dist/editor/commands/formatting/propertyCommands.js +108 -0
  112. package/dist/editor/commands/formatting/shared.d.ts +3 -3
  113. package/dist/editor/commands/formatting/shared.js +5 -2
  114. package/dist/editor/commands/indentCommands.js +5 -4
  115. package/dist/editor/commands/index.d.ts +11 -0
  116. package/dist/editor/commands/index.js +5 -0
  117. package/dist/editor/commands/linkCommands.js +5 -6
  118. package/dist/editor/commands/listCommands.d.ts +6 -3
  119. package/dist/editor/commands/listCommands.js +73 -30
  120. package/dist/editor/commands/lockCommands.d.ts +7 -1
  121. package/dist/editor/commands/lockCommands.js +35 -46
  122. package/dist/editor/commands/paragraphCommands.js +33 -31
  123. package/dist/editor/commands/spacingCommands.js +1 -1
  124. package/dist/editor/createEditor.d.ts +17 -29
  125. package/dist/editor/createEditor.js +58 -58
  126. package/dist/editor/documentStyles.d.ts +11 -35
  127. package/dist/editor/documentStyles.js +9 -52
  128. package/dist/editor/editorDocument.d.ts +57 -0
  129. package/dist/editor/editorDocument.js +86 -0
  130. package/dist/editor/externalClipboard.d.ts +13 -2
  131. package/dist/editor/externalClipboard.js +76 -75
  132. package/dist/editor/insertTable.js +4 -3
  133. package/dist/editor/paragraphEdits.d.ts +27 -19
  134. package/dist/editor/paragraphEdits.js +18 -19
  135. package/dist/editor/paragraphPlacement.d.ts +11 -0
  136. package/dist/editor/paragraphPlacement.js +18 -0
  137. package/dist/editor/plugins/displayDerivation.d.ts +47 -0
  138. package/dist/editor/plugins/displayDerivation.js +78 -0
  139. package/dist/editor/plugins/imagePaste.js +11 -7
  140. package/dist/editor/plugins/keymap.js +18 -3
  141. package/dist/editor/plugins/numberingDecorations.d.ts +14 -14
  142. package/dist/editor/plugins/numberingDecorations.js +50 -19
  143. package/dist/editor/plugins/paragraphDisplay.d.ts +7 -0
  144. package/dist/editor/plugins/paragraphDisplay.js +57 -0
  145. package/dist/editor/plugins/tabLayout.js +1 -1
  146. package/dist/editor/plugins/tableDisplay.d.ts +6 -0
  147. package/dist/editor/plugins/tableDisplay.js +30 -0
  148. package/dist/index.d.ts +2 -0
  149. package/dist/model/format.d.ts +80 -8
  150. package/dist/model/format.js +100 -22
  151. package/dist/model/tabStops.d.ts +9 -0
  152. package/dist/model/tabStops.js +18 -0
  153. package/dist/numbering/listRegistry.d.ts +37 -0
  154. package/dist/numbering/listRegistry.js +112 -0
  155. package/dist/numbering/listTemplate.d.ts +26 -17
  156. package/dist/numbering/listTemplate.js +88 -25
  157. package/dist/numbering/markers.d.ts +15 -6
  158. package/dist/numbering/markers.js +26 -59
  159. package/dist/numbering/parseNumbering.d.ts +84 -6
  160. package/dist/numbering/parseNumbering.js +131 -44
  161. package/dist/numbering/spellers.d.ts +15 -0
  162. package/dist/numbering/spellers.js +96 -0
  163. package/dist/numbering/writeNumbering.d.ts +8 -7
  164. package/dist/numbering/writeNumbering.js +28 -39
  165. package/dist/ooxml/childOrder.d.ts +34 -0
  166. package/dist/ooxml/childOrder.js +496 -0
  167. package/dist/ooxml/conformance.d.ts +28 -0
  168. package/dist/ooxml/conformance.js +20 -0
  169. package/dist/ooxml/element.d.ts +24 -11
  170. package/dist/ooxml/element.js +31 -12
  171. package/dist/ooxml/errors.d.ts +6 -5
  172. package/dist/ooxml/image.d.ts +4 -0
  173. package/dist/ooxml/image.js +2 -5
  174. package/dist/ooxml/names.d.ts +9 -0
  175. package/dist/ooxml/names.js +8 -1
  176. package/dist/ooxml/partSplice.d.ts +67 -0
  177. package/dist/ooxml/partSplice.js +176 -0
  178. package/dist/ooxml/props.d.ts +112 -0
  179. package/dist/{docx/propsXml.js → ooxml/props.js} +72 -200
  180. package/dist/ooxml/simpleTypes.d.ts +103 -0
  181. package/dist/ooxml/simpleTypes.js +182 -0
  182. package/dist/ooxml/tabStops.js +8 -27
  183. package/dist/ooxml/tagScan.d.ts +34 -0
  184. package/dist/ooxml/tagScan.js +108 -0
  185. package/dist/ooxml/units.d.ts +25 -13
  186. package/dist/ooxml/units.js +65 -31
  187. package/dist/ooxml/xml.d.ts +35 -15
  188. package/dist/ooxml/xml.js +43 -11
  189. package/dist/page/PageGuides.d.ts +1 -1
  190. package/dist/page/PageGuides.js +0 -13
  191. package/dist/page/blockKinds.d.ts +61 -0
  192. package/dist/page/blockKinds.js +11 -0
  193. package/dist/page/kinds/index.d.ts +6 -0
  194. package/dist/page/kinds/index.js +10 -0
  195. package/dist/page/kinds/paragraphKind.d.ts +10 -0
  196. package/dist/page/kinds/paragraphKind.js +71 -0
  197. package/dist/page/kinds/tableKind.d.ts +10 -0
  198. package/dist/page/kinds/tableKind.js +178 -0
  199. package/dist/page/measureBlocks.d.ts +3 -14
  200. package/dist/page/measureBlocks.js +24 -45
  201. package/dist/page/pageDecorations.d.ts +27 -44
  202. package/dist/page/pageDecorations.js +70 -152
  203. package/dist/page/pageLayout.d.ts +2 -29
  204. package/dist/page/pageLayout.js +39 -16
  205. package/dist/page/usePageLayout.d.ts +2 -24
  206. package/dist/page/usePageLayout.js +5 -48
  207. package/dist/schema/attrRoles.d.ts +25 -18
  208. package/dist/schema/attrRoles.js +110 -68
  209. package/dist/schema/displayDerivation.d.ts +82 -0
  210. package/dist/schema/displayDerivation.js +130 -0
  211. package/dist/schema/docxSchema.d.ts +3 -0
  212. package/dist/schema/docxSchema.js +58 -17
  213. package/dist/schema/editGuard.d.ts +1 -1
  214. package/dist/schema/guards.d.ts +37 -14
  215. package/dist/schema/guards.js +29 -3
  216. package/dist/schema/index.d.ts +2 -0
  217. package/dist/schema/index.js +2 -0
  218. package/dist/schema/locks.d.ts +11 -44
  219. package/dist/schema/locks.js +0 -9
  220. package/dist/schema/preservedGuards.d.ts +26 -6
  221. package/dist/schema/preservedGuards.js +31 -1
  222. package/dist/schema/protection.d.ts +7 -1
  223. package/dist/schema/protection.js +2 -1
  224. package/dist/schema/sourceEquality.d.ts +1 -9
  225. package/dist/schema/sourceEquality.js +1 -27
  226. package/dist/styles/classNames.d.ts +13 -2
  227. package/dist/styles/classNames.js +13 -2
  228. package/dist/styles/inlineStyle.js +15 -6
  229. package/dist/styles.css +16 -18
  230. package/dist/table/cellFormatting.d.ts +8 -1
  231. package/dist/table/cellFormatting.js +11 -20
  232. package/dist/table/commands.js +20 -18
  233. package/dist/table/format.d.ts +3 -0
  234. package/dist/table/format.js +3 -9
  235. package/dist/table/gridBorders.d.ts +24 -30
  236. package/dist/table/gridBorders.js +35 -59
  237. package/dist/table/merge.d.ts +2 -6
  238. package/dist/table/merge.js +5 -5
  239. package/package.json +7 -3
  240. package/dist/docx/comments/contentTypes.d.ts +0 -7
  241. package/dist/docx/comments/contentTypes.js +0 -38
  242. package/dist/docx/comments/verifying.js +0 -206
  243. package/dist/docx/formatting/effectiveParagraph.d.ts +0 -15
  244. package/dist/docx/formatting/effectiveParagraph.js +0 -81
  245. package/dist/docx/propsXml.d.ts +0 -67
  246. package/dist/docx/uniqueControls.d.ts +0 -14
  247. package/dist/docx/uniqueControls.js +0 -62
  248. package/dist/editor/plugins/commentReservations.d.ts +0 -5
  249. package/dist/editor/plugins/commentReservations.js +0 -26
  250. package/dist/editor/plugins/styledParagraphs.d.ts +0 -15
  251. package/dist/editor/plugins/styledParagraphs.js +0 -65
  252. package/dist/page/tableMeasurements.d.ts +0 -18
  253. 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
+ };
@@ -1,9 +1,16 @@
1
1
  /** Reads and layers styles.xml values used by the display model. */
2
- import { type CellMargins, type InsideBorders, type ParagraphFormat, type RunFormat, type TableFormat } from "../../model/format";
2
+ import { type BandSizes, type CellMargins, type InsideBorders, type ParagraphFormat, type RunFormat, type TableFormat, type TableStyleOverrideType } from "../../model/format";
3
+ import type { NumberingStyleLinks } from "../../numbering/parseNumbering";
4
+ import { type ConditionalTableFormat } from "../tableFormatting";
3
5
  import { type ThemeFonts } from "../theme";
4
6
  import { type ParagraphFormatLayer } from "./tabStops";
7
+ /** The kind of object a style dresses (`w:style/@w:type`, ST_StyleType) */
8
+ export type StyleType = "paragraph" | "character" | "table" | "numbering";
9
+ /** What a table style dresses each part of a table with, by the part it covers */
10
+ export type TableStyleConditionFormats = Readonly<Partial<Record<TableStyleOverrideType, ConditionalTableFormat>>>;
5
11
  /** The display values one style passes down to paragraphs, to text, and to tables */
6
12
  export interface StyleFormat {
13
+ type: StyleType;
7
14
  paragraph: ParagraphFormatLayer;
8
15
  run: RunFormat;
9
16
  table: TableFormat;
@@ -11,6 +18,14 @@ export interface StyleFormat {
11
18
  tableInside: InsideBorders;
12
19
  /** The cell margins the style laid down. A side it says nothing about is null */
13
20
  tableCellMargins: CellMargins;
21
+ /** How many rows and columns one band of this table style is made of */
22
+ tableBands: BandSizes;
23
+ /**
24
+ * The conditional formats it wrote (`w:tblStylePr`). Each part is layered down the `basedOn`
25
+ * chain on its own, so a style that redresses the header row alone leaves the parts the styles
26
+ * it is based on dressed standing.
27
+ */
28
+ tableConditions: TableStyleConditionFormats;
14
29
  }
15
30
  /** A table looked up by style name. The `basedOn` chain has already been layered into the values */
16
31
  export type StyleTable = ReadonlyMap<string, StyleFormat>;
@@ -19,10 +34,18 @@ export declare const NO_STYLES: StyleTable;
19
34
  * Reads the style chain from styles.xml into effective values for display.
20
35
  *
21
36
  * A style name is unique across all kinds (paragraph, character, table), so we take them in
22
- * without telling the kinds apart.
37
+ * without telling the kinds apart, and each one remembers the kind it is.
23
38
  * The names a paragraph points at are only ever paragraph styles, so the other kinds are never looked up.
24
39
  */
25
40
  export declare function readStyles(styles: Document, themeFonts?: ThemeFonts): StyleTable;
41
+ /**
42
+ * The list each numbering style names.
43
+ *
44
+ * A numbering style carries its list in the `w:numPr` of its paragraph properties, and that is the
45
+ * only way a numbering definition deferring to a style (`w:numStyleLink`) finds the levels it
46
+ * draws. A style naming no list, or naming the empty list `w:numId` 0, links to nothing.
47
+ */
48
+ export declare function numberingStyleLinks(styles: StyleTable): NumberingStyleLinks;
26
49
  /**
27
50
  * The default table style, which for most documents is where a plain table gets its cell margins
28
51
  * and its lines from
@@ -1,18 +1,25 @@
1
1
  // src/docx/formatting/styles.ts
2
2
  import {
3
+ TABLE_STYLE_CONDITIONS,
3
4
  toParagraphFormat,
4
5
  toRunFormat,
5
6
  toTableFormat
6
7
  } from "../../model/format.js";
8
+ import { parsePropsXml } from "../../ooxml/props.js";
9
+ import { ST_OnOff } from "../../ooxml/simpleTypes.js";
7
10
  import { childValue, isOn, wAttr } from "../../ooxml/units.js";
8
11
  import { childByLocalName, elementChildren } from "../../ooxml/xml.js";
9
- import { parsePropsXml } from "../propsXml.js";
10
12
  import {
13
+ layerBandSizes,
11
14
  layerCellMargins,
15
+ layerCellStyleFormat,
12
16
  layerInsideBorders,
17
+ NO_BAND_SIZES,
13
18
  NO_CELL_MARGINS,
14
19
  NO_INSIDE_BORDERS,
20
+ readBandSizes,
15
21
  readCellMarginsOf,
22
+ readCellStyleFormat,
16
23
  readInsideBorders,
17
24
  readTableFormat
18
25
  } from "../tableFormatting.js";
@@ -34,23 +41,51 @@ function styleChain(id, sources) {
34
41
  return chain;
35
42
  }
36
43
  var EMPTY_STYLE_FORMAT = {
44
+ type: "paragraph",
37
45
  paragraph: {},
38
46
  run: {},
39
47
  table: {},
40
48
  tableInside: NO_INSIDE_BORDERS,
41
- tableCellMargins: NO_CELL_MARGINS
49
+ tableCellMargins: NO_CELL_MARGINS,
50
+ tableBands: NO_BAND_SIZES,
51
+ tableConditions: {}
42
52
  };
53
+ function conditionOf(el) {
54
+ const type = wAttr(el, "type");
55
+ return TABLE_STYLE_CONDITIONS.find((known) => known === type) ?? null;
56
+ }
57
+ function readConditionalFormat(el, themeFonts) {
58
+ const tblPr = childByLocalName(el, "tblPr");
59
+ return {
60
+ paragraph: readParagraphFormat(childByLocalName(el, "pPr")) ?? {},
61
+ run: readRunFormat(childByLocalName(el, "rPr"), themeFonts) ?? {},
62
+ table: readTableFormat(tblPr) ?? {},
63
+ cell: readCellStyleFormat(childByLocalName(el, "tcPr"), tblPr)
64
+ };
65
+ }
66
+ function readConditions(source, themeFonts) {
67
+ const conditions = {};
68
+ for (const el of source.tblStylePr) {
69
+ const type = conditionOf(el);
70
+ if (type !== null) conditions[type] = readConditionalFormat(el, themeFonts);
71
+ }
72
+ return conditions;
73
+ }
43
74
  function readStyleFormat(source, themeFonts) {
44
75
  return {
76
+ type: source.type,
45
77
  paragraph: readParagraphFormat(source.pPr) ?? {},
46
78
  run: readRunFormat(source.rPr, themeFonts) ?? {},
47
79
  table: readTableFormat(source.tblPr) ?? {},
48
80
  tableInside: readInsideBorders(source.tblPr),
49
- tableCellMargins: readCellMarginsOf(source.tblPr, "tblCellMar")
81
+ tableCellMargins: readCellMarginsOf(source.tblPr, "tblCellMar"),
82
+ tableBands: readBandSizes(source.tblPr),
83
+ tableConditions: readConditions(source, themeFonts)
50
84
  };
51
85
  }
52
86
  function layerStyleFormat(base, over) {
53
87
  return {
88
+ type: over.type,
54
89
  paragraph: layerParagraphValues(base.paragraph, over.paragraph),
55
90
  run: { ...base.run, ...over.run },
56
91
  table: { ...base.table, ...over.table },
@@ -58,12 +93,45 @@ function layerStyleFormat(base, over) {
58
93
  tableCellMargins: layerCellMargins(
59
94
  base.tableCellMargins,
60
95
  over.tableCellMargins
96
+ ),
97
+ tableBands: layerBandSizes(base.tableBands, over.tableBands),
98
+ tableConditions: layerConditions(
99
+ base.tableConditions,
100
+ over.tableConditions
61
101
  )
62
102
  };
63
103
  }
104
+ function layerConditionalFormat(base, over) {
105
+ return {
106
+ paragraph: layerParagraphValues(base.paragraph, over.paragraph),
107
+ run: { ...base.run, ...over.run },
108
+ table: { ...base.table, ...over.table },
109
+ cell: layerCellStyleFormat(base.cell, over.cell)
110
+ };
111
+ }
112
+ function layerConditions(base, over) {
113
+ const conditions = {};
114
+ for (const type of TABLE_STYLE_CONDITIONS) {
115
+ const under = base[type];
116
+ const above = over[type];
117
+ const format = under && above ? layerConditionalFormat(under, above) : above ?? under;
118
+ if (format) conditions[type] = format;
119
+ }
120
+ return conditions;
121
+ }
64
122
  function foldChain(chain, themeFonts) {
65
123
  return chain.map((source) => readStyleFormat(source, themeFonts)).reduce(layerStyleFormat, EMPTY_STYLE_FORMAT);
66
124
  }
125
+ var STYLE_TYPES = [
126
+ "paragraph",
127
+ "character",
128
+ "table",
129
+ "numbering"
130
+ ];
131
+ function styleTypeOf(el) {
132
+ const type = wAttr(el, "type");
133
+ return STYLE_TYPES.find((known) => known === type) ?? "paragraph";
134
+ }
67
135
  function readStyles(styles, themeFonts = NO_THEME_FONTS) {
68
136
  const sources = /* @__PURE__ */ new Map();
69
137
  for (const el of elementChildren(styles.documentElement)) {
@@ -71,10 +139,14 @@ function readStyles(styles, themeFonts = NO_THEME_FONTS) {
71
139
  const id = wAttr(el, "styleId");
72
140
  if (id === null || id.length === 0) continue;
73
141
  sources.set(id, {
142
+ type: styleTypeOf(el),
74
143
  basedOn: childValue(el, "basedOn"),
75
144
  pPr: childByLocalName(el, "pPr"),
76
145
  rPr: childByLocalName(el, "rPr"),
77
- tblPr: childByLocalName(el, "tblPr")
146
+ tblPr: childByLocalName(el, "tblPr"),
147
+ tblStylePr: elementChildren(el).filter(
148
+ (child) => child.localName === "tblStylePr"
149
+ )
78
150
  });
79
151
  }
80
152
  const table = /* @__PURE__ */ new Map();
@@ -83,9 +155,17 @@ function readStyles(styles, themeFonts = NO_THEME_FONTS) {
83
155
  }
84
156
  return table;
85
157
  }
158
+ function numberingStyleLinks(styles) {
159
+ const links = /* @__PURE__ */ new Map();
160
+ for (const [id, format] of styles) {
161
+ if (format.type !== "numbering") continue;
162
+ const numId = format.paragraph.numbering?.numId;
163
+ if (numId !== void 0) links.set(id, numId);
164
+ }
165
+ return links;
166
+ }
86
167
  function isDefaultStyle(el) {
87
- const value = wAttr(el, "default");
88
- return value === "1" || value === "true";
168
+ return ST_OnOff.parse(wAttr(el, "default")) === true;
89
169
  }
90
170
  function defaultStyleIdOf(styles, type) {
91
171
  let found = null;
@@ -158,6 +238,7 @@ export {
158
238
  layerParagraphFormat,
159
239
  layerRunFormat,
160
240
  layerTableFormat,
241
+ numberingStyleLinks,
161
242
  paragraphStyleFormat,
162
243
  readParagraphStyles,
163
244
  readStyles,
@@ -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),