@portone/docx-editor 0.3.0 → 0.5.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 (217) hide show
  1. package/CHANGELOG.md +205 -0
  2. package/assets/editor.png +0 -0
  3. package/dist/DocxEditor.d.ts +1 -1
  4. package/dist/DocxEditor.js +45 -25
  5. package/dist/core.d.ts +1 -1
  6. package/dist/docx/cloning.js +4 -9
  7. package/dist/docx/commentOnlyChange.d.ts +5 -3
  8. package/dist/docx/comments/grammar.d.ts +27 -10
  9. package/dist/docx/comments/grammar.js +18 -67
  10. package/dist/docx/comments/model.d.ts +5 -6
  11. package/dist/docx/comments/model.js +0 -9
  12. package/dist/docx/comments/parts.d.ts +16 -10
  13. package/dist/docx/comments/parts.js +65 -13
  14. package/dist/docx/comments/people.d.ts +11 -3
  15. package/dist/docx/comments/people.js +20 -6
  16. package/dist/docx/comments/policy.js +7 -1
  17. package/dist/docx/comments/reading.d.ts +4 -2
  18. package/dist/docx/comments/reading.js +1 -14
  19. package/dist/docx/comments/writing.js +78 -35
  20. package/dist/docx/exportDocx.js +30 -18
  21. package/dist/docx/exportRefs.d.ts +8 -3
  22. package/dist/docx/exportRefs.js +2 -1
  23. package/dist/docx/fidelity.js +24 -10
  24. package/dist/docx/fields.d.ts +42 -0
  25. package/dist/docx/fields.js +76 -0
  26. package/dist/docx/formatting/attrs.d.ts +20 -2
  27. package/dist/docx/formatting/attrs.js +57 -2
  28. package/dist/docx/formatting/context.d.ts +10 -2
  29. package/dist/docx/formatting/context.js +23 -5
  30. package/dist/docx/formatting/resolve.d.ts +10 -4
  31. package/dist/docx/formatting/resolve.js +31 -11
  32. package/dist/docx/formatting/styles.d.ts +25 -2
  33. package/dist/docx/formatting/styles.js +84 -3
  34. package/dist/docx/headersFooters.d.ts +89 -20
  35. package/dist/docx/headersFooters.js +163 -172
  36. package/dist/docx/hyperlink.d.ts +14 -4
  37. package/dist/docx/hyperlink.js +4 -1
  38. package/dist/docx/importDocx.d.ts +1 -1
  39. package/dist/docx/importDocx.js +135 -74
  40. package/dist/docx/importParagraph.d.ts +16 -4
  41. package/dist/docx/importParagraph.js +87 -93
  42. package/dist/docx/importPolicy.d.ts +70 -0
  43. package/dist/docx/importPolicy.js +190 -0
  44. package/dist/docx/importPreserved.d.ts +30 -0
  45. package/dist/docx/importPreserved.js +54 -0
  46. package/dist/docx/importTable.d.ts +2 -2
  47. package/dist/docx/importTable.js +107 -66
  48. package/dist/docx/invariants.js +42 -31
  49. package/dist/docx/newLists.d.ts +30 -0
  50. package/dist/docx/newLists.js +24 -1
  51. package/dist/docx/notes.d.ts +6 -1
  52. package/dist/docx/notes.js +6 -16
  53. package/dist/docx/numberingPlanner.d.ts +6 -3
  54. package/dist/docx/numberingPlanner.js +38 -7
  55. package/dist/docx/pageGeometry.d.ts +5 -14
  56. package/dist/docx/pageGeometry.js +0 -12
  57. package/dist/docx/protectionPolicy.d.ts +13 -5
  58. package/dist/docx/protectionPolicy.js +32 -22
  59. package/dist/docx/scan.d.ts +18 -8
  60. package/dist/docx/scan.js +17 -11
  61. package/dist/docx/sections.d.ts +126 -0
  62. package/dist/docx/sections.js +207 -0
  63. package/dist/docx/serializeBlock.d.ts +13 -4
  64. package/dist/docx/serializeBlock.js +16 -18
  65. package/dist/docx/serializeParagraph.d.ts +4 -0
  66. package/dist/docx/serializeParagraph.js +1 -0
  67. package/dist/docx/serializePreserved.d.ts +14 -0
  68. package/dist/docx/serializePreserved.js +24 -0
  69. package/dist/docx/serializeStory.d.ts +17 -0
  70. package/dist/docx/serializeStory.js +17 -0
  71. package/dist/docx/serializeTable.js +10 -13
  72. package/dist/docx/session.d.ts +24 -7
  73. package/dist/docx/session.js +37 -6
  74. package/dist/docx/story.d.ts +140 -0
  75. package/dist/docx/story.js +237 -0
  76. package/dist/docx/storyProjection.js +6 -1
  77. package/dist/docx/tableFormatting/conditions.d.ts +76 -0
  78. package/dist/docx/tableFormatting/conditions.js +196 -0
  79. package/dist/docx/tableFormatting/editing.d.ts +7 -3
  80. package/dist/docx/tableFormatting/editing.js +4 -5
  81. package/dist/docx/tableFormatting/reading.d.ts +49 -19
  82. package/dist/docx/tableFormatting/reading.js +109 -35
  83. package/dist/docx/tableFormatting.d.ts +1 -0
  84. package/dist/docx/tableFormatting.js +1 -0
  85. package/dist/docx/tableTemplate.js +12 -12
  86. package/dist/editor/clipboard/htmlReader.d.ts +30 -0
  87. package/dist/editor/clipboard/htmlReader.js +302 -0
  88. package/dist/editor/clipboard/internalChannel.d.ts +57 -0
  89. package/dist/editor/clipboard/internalChannel.js +58 -0
  90. package/dist/editor/clipboard/normalizers.d.ts +99 -0
  91. package/dist/editor/clipboard/normalizers.js +199 -0
  92. package/dist/editor/clipboard/parser.d.ts +34 -0
  93. package/dist/editor/clipboard/parser.js +58 -0
  94. package/dist/editor/clipboard/plugin.d.ts +21 -0
  95. package/dist/editor/clipboard/plugin.js +320 -0
  96. package/dist/editor/clipboard/readContext.d.ts +24 -0
  97. package/dist/editor/clipboard/readContext.js +19 -0
  98. package/dist/editor/clipboard/readers.d.ts +33 -0
  99. package/dist/editor/clipboard/readers.js +37 -0
  100. package/dist/editor/commands/comments/editing.d.ts +26 -6
  101. package/dist/editor/commands/comments/editing.js +175 -105
  102. package/dist/editor/commands/comments/model.d.ts +34 -17
  103. package/dist/editor/commands/comments/model.js +11 -0
  104. package/dist/editor/commands/comments/reading.d.ts +5 -3
  105. package/dist/editor/commands/comments/reading.js +8 -58
  106. package/dist/editor/commands/formatting/propertyCommands.js +6 -1
  107. package/dist/editor/commands/index.d.ts +2 -2
  108. package/dist/editor/commands/index.js +2 -0
  109. package/dist/editor/commands/listCommands.d.ts +12 -3
  110. package/dist/editor/commands/listCommands.js +76 -30
  111. package/dist/editor/commands/noteQueries.d.ts +22 -5
  112. package/dist/editor/commands/noteQueries.js +34 -6
  113. package/dist/editor/commands/paragraphCommands.js +6 -1
  114. package/dist/editor/createEditor.js +14 -4
  115. package/dist/editor/documentStyles.d.ts +26 -4
  116. package/dist/editor/documentStyles.js +9 -4
  117. package/dist/editor/editorDocument.d.ts +7 -6
  118. package/dist/editor/editorDocument.js +18 -6
  119. package/dist/editor/imageFiles.d.ts +2 -2
  120. package/dist/editor/imageFiles.js +2 -0
  121. package/dist/editor/insertTable.d.ts +1 -1
  122. package/dist/editor/insertTable.js +2 -2
  123. package/dist/editor/paragraphEdits.d.ts +16 -1
  124. package/dist/editor/paragraphEdits.js +13 -5
  125. package/dist/editor/paragraphPlacement.d.ts +11 -0
  126. package/dist/editor/paragraphPlacement.js +18 -0
  127. package/dist/editor/plainText.d.ts +12 -0
  128. package/dist/editor/plainText.js +2 -1
  129. package/dist/editor/plugins/columnResize.js +6 -3
  130. package/dist/editor/plugins/commentComposer.d.ts +28 -0
  131. package/dist/editor/plugins/commentComposer.js +46 -0
  132. package/dist/editor/plugins/commentDecorations.d.ts +29 -2
  133. package/dist/editor/plugins/commentDecorations.js +89 -15
  134. package/dist/editor/plugins/documentProjection.d.ts +31 -0
  135. package/dist/editor/plugins/documentProjection.js +22 -0
  136. package/dist/editor/plugins/imagePaste.js +20 -10
  137. package/dist/editor/plugins/linkPanel.d.ts +7 -3
  138. package/dist/editor/plugins/linkPanel.js +13 -27
  139. package/dist/editor/plugins/numberingDecorations.d.ts +10 -4
  140. package/dist/editor/plugins/numberingDecorations.js +43 -2
  141. package/dist/editor/plugins/panelState.d.ts +67 -0
  142. package/dist/editor/plugins/panelState.js +54 -0
  143. package/dist/editor/plugins/paragraphDisplay.js +9 -3
  144. package/dist/editor/plugins/tableContextMenu.d.ts +1 -1
  145. package/dist/editor/plugins/tableContextMenu.js +30 -47
  146. package/dist/editor/plugins/tableDisplay.js +19 -5
  147. package/dist/editor/plugins/textContextMenu.d.ts +1 -1
  148. package/dist/editor/plugins/textContextMenu.js +30 -47
  149. package/dist/model/format.d.ts +50 -0
  150. package/dist/model/format.js +65 -0
  151. package/dist/numbering/listRegistry.d.ts +37 -0
  152. package/dist/numbering/listRegistry.js +112 -0
  153. package/dist/numbering/listTemplate.d.ts +26 -17
  154. package/dist/numbering/listTemplate.js +66 -20
  155. package/dist/numbering/markers.d.ts +15 -6
  156. package/dist/numbering/markers.js +26 -59
  157. package/dist/numbering/parseNumbering.d.ts +70 -5
  158. package/dist/numbering/parseNumbering.js +100 -26
  159. package/dist/numbering/spellers.d.ts +15 -0
  160. package/dist/numbering/spellers.js +96 -0
  161. package/dist/numbering/writeNumbering.d.ts +5 -3
  162. package/dist/numbering/writeNumbering.js +15 -15
  163. package/dist/ooxml/conformance.d.ts +28 -0
  164. package/dist/ooxml/conformance.js +20 -0
  165. package/dist/ooxml/errors.d.ts +5 -5
  166. package/dist/ooxml/fragment.d.ts +11 -0
  167. package/dist/ooxml/fragment.js +14 -4
  168. package/dist/ooxml/image.d.ts +3 -4
  169. package/dist/ooxml/image.js +50 -5
  170. package/dist/ooxml/names.d.ts +15 -0
  171. package/dist/ooxml/names.js +10 -1
  172. package/dist/ooxml/partSplice.d.ts +1 -1
  173. package/dist/ooxml/partSplice.js +10 -3
  174. package/dist/ooxml/props.d.ts +8 -0
  175. package/dist/ooxml/props.js +14 -4
  176. package/dist/ooxml/rangeMarkers.d.ts +5 -0
  177. package/dist/ooxml/rangeMarkers.js +24 -0
  178. package/dist/ooxml/xml.d.ts +8 -9
  179. package/dist/ooxml/xml.js +6 -6
  180. package/dist/page/PageGuides.d.ts +8 -4
  181. package/dist/page/PageGuides.js +13 -37
  182. package/dist/page/pageLayout.d.ts +62 -13
  183. package/dist/page/pageLayout.js +91 -37
  184. package/dist/page/usePageLayout.d.ts +14 -11
  185. package/dist/page/usePageLayout.js +21 -29
  186. package/dist/schema/attrRoles.js +44 -19
  187. package/dist/schema/docxSchema.d.ts +9 -1
  188. package/dist/schema/docxSchema.js +220 -139
  189. package/dist/schema/editGuard.d.ts +1 -1
  190. package/dist/schema/guards.js +2 -2
  191. package/dist/schema/index.d.ts +1 -0
  192. package/dist/schema/preservedFragments.d.ts +12 -0
  193. package/dist/schema/preservedFragments.js +38 -0
  194. package/dist/schema/preservedGuards.d.ts +9 -7
  195. package/dist/schema/preservedGuards.js +112 -11
  196. package/dist/schema/protection.d.ts +34 -5
  197. package/dist/schema/protection.js +42 -14
  198. package/dist/schema/rendering.js +3 -1
  199. package/dist/schema/stories.d.ts +49 -0
  200. package/dist/schema/stories.js +78 -0
  201. package/dist/styles/classNames.d.ts +16 -7
  202. package/dist/styles/classNames.js +16 -7
  203. package/dist/styles.css +90 -30
  204. package/dist/table/cellFormatting.js +1 -2
  205. package/dist/table/gridBorders.d.ts +11 -15
  206. package/dist/table/gridBorders.js +32 -18
  207. package/dist/table/resize.d.ts +5 -3
  208. package/dist/ui/CommentsPanel.d.ts +1 -3
  209. package/dist/ui/CommentsPanel.js +24 -15
  210. package/dist/ui/NotesPanel.js +2 -2
  211. package/dist/ui/TextMenu.d.ts +1 -3
  212. package/dist/ui/TextMenu.js +10 -6
  213. package/dist/ui/comments/CommentComposer.d.ts +6 -1
  214. package/dist/ui/comments/CommentComposer.js +26 -3
  215. package/package.json +1 -1
  216. package/dist/editor/externalClipboard.d.ts +0 -11
  217. package/dist/editor/externalClipboard.js +0 -456
@@ -1,14 +1,20 @@
1
1
  // src/docx/formatting/context.ts
2
2
  import {
3
- EMPTY_NUMBERING
3
+ EMPTY_NUMBERING,
4
+ parseNumbering
4
5
  } from "../../numbering/parseNumbering.js";
5
6
  import { NO_COMPAT } from "../documentSettings.js";
6
7
  import { NO_THEME_FONTS } from "../theme.js";
7
- import { readDefaultParagraphFormat, readRunDefaults } from "./direct.js";
8
+ import {
9
+ readDefaultParagraphFormat,
10
+ readRunDefaults,
11
+ readRunFormat
12
+ } from "./direct.js";
8
13
  import {
9
14
  defaultParagraphStyleIdOf,
10
15
  defaultTableStyleIdOf,
11
16
  NO_STYLES,
17
+ numberingStyleLinks,
12
18
  readStyles
13
19
  } from "./styles.js";
14
20
  var NO_FORMATTING = {
@@ -21,12 +27,23 @@ var NO_FORMATTING = {
21
27
  themeFonts: NO_THEME_FONTS,
22
28
  compat: NO_COMPAT
23
29
  };
24
- function formattingContextOf(styles, numbering, themeFonts, compat = NO_COMPAT) {
30
+ function numberingOptionsFor(styles, themeFonts) {
31
+ return {
32
+ links: numberingStyleLinks(styles),
33
+ readRun: (rPr) => readRunFormat(rPr, themeFonts)
34
+ };
35
+ }
36
+ function formattingContextOf(styles, numberingXml, themeFonts, compat = NO_COMPAT) {
37
+ const table = styles === null ? NO_STYLES : readStyles(styles, themeFonts);
38
+ const numbering = parseNumbering(
39
+ numberingXml,
40
+ numberingOptionsFor(table, themeFonts)
41
+ );
25
42
  if (styles === null) {
26
43
  return { ...NO_FORMATTING, numbering, themeFonts, compat };
27
44
  }
28
45
  return {
29
- styles: readStyles(styles, themeFonts),
46
+ styles: table,
30
47
  defaultParagraphStyleId: defaultParagraphStyleIdOf(styles),
31
48
  defaultTableStyleId: defaultTableStyleIdOf(styles),
32
49
  paragraphDefaults: readDefaultParagraphFormat(styles),
@@ -38,5 +55,6 @@ function formattingContextOf(styles, numbering, themeFonts, compat = NO_COMPAT)
38
55
  }
39
56
  export {
40
57
  NO_FORMATTING,
41
- formattingContextOf
58
+ formattingContextOf,
59
+ numberingOptionsFor
42
60
  };
@@ -9,13 +9,12 @@ import { type ParagraphFormat, type RunFormat } from "../../model/format";
9
9
  import type { TabStop } from "../../model/tabStops";
10
10
  import type { TableStyleOverrideType } from "../tableFormatting";
11
11
  import type { FormattingContext } from "./context";
12
+ import { type StyleFormat } from "./styles";
12
13
  /** Where a paragraph sits when it is inside a table cell. null for body text */
13
14
  export interface ParagraphPlacement {
15
+ /** What the table's `w:tblStyle` names. null for a table naming none, which wears the default one */
14
16
  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
- */
17
+ /** The parts of the table the cell belongs to, lowest first (`docx/tableFormatting/conditions`) */
19
18
  conditions: readonly TableStyleOverrideType[];
20
19
  }
21
20
  /**
@@ -38,6 +37,13 @@ export interface ResolvedParagraph {
38
37
  /** The stops `format.tabStops` holds, each with the layer that laid it down */
39
38
  tabStops: readonly LayeredTabStop[];
40
39
  }
40
+ /**
41
+ * The table style an object wearing this one is dressed by.
42
+ *
43
+ * A table that points at no style, or at one that is not defined, falls back on the document's
44
+ * default table style, which is what OOXML applies to an object with no style of its own.
45
+ */
46
+ export declare function tableStyleFor(styleId: string | null, context: FormattingContext): StyleFormat | undefined;
41
47
  export declare function resolveParagraph(pPr: string | null, context: FormattingContext, placement?: ParagraphPlacement | null): ResolvedParagraph;
42
48
  /** `format` on a run mark: paragraph.styleRun < character style < the run's own rPr */
43
49
  export declare function resolveRun(rPr: string | null, paragraph: ResolvedParagraph, context: FormattingContext): RunFormat | null;
@@ -2,6 +2,7 @@
2
2
  import {
3
3
  toParagraphFormat
4
4
  } from "../../model/format.js";
5
+ import { listFor } from "../../numbering/listTemplate.js";
5
6
  import {
6
7
  levelIndentPt
7
8
  } from "../../numbering/parseNumbering.js";
@@ -14,9 +15,17 @@ import {
14
15
  function directLayer(pPr) {
15
16
  return pPr === null ? {} : readParagraphFormat(parsePropsXml(pPr)) ?? {};
16
17
  }
17
- function tableStyleOf(placement, context) {
18
- const id = placement?.tableStyleId ?? null;
19
- return id === null ? void 0 : context.styles.get(id);
18
+ function tableStyleFor(styleId, context) {
19
+ const named = styleId === null ? void 0 : context.styles.get(styleId);
20
+ const fallback = context.defaultTableStyleId === null ? void 0 : context.styles.get(context.defaultTableStyleId);
21
+ return named ?? fallback;
22
+ }
23
+ function conditionsOf(style, placement) {
24
+ if (!style || !placement) return [];
25
+ return placement.conditions.flatMap((type) => {
26
+ const format = style.tableConditions[type];
27
+ return format ? [format] : [];
28
+ });
20
29
  }
21
30
  function numberingLevelOf(layers, context) {
22
31
  const ref = layers.reduce(
@@ -24,7 +33,7 @@ function numberingLevelOf(layers, context) {
24
33
  void 0
25
34
  );
26
35
  if (!ref) return void 0;
27
- return context.numbering.lists.get(ref.numId)?.levels.get(ref.ilvl);
36
+ return listFor(context.numbering, ref.numId)?.levels.get(ref.ilvl);
28
37
  }
29
38
  function numberingLayer(level) {
30
39
  return level?.tabStops ? { tabStops: level.tabStops } : {};
@@ -66,16 +75,23 @@ function orNull(values) {
66
75
  return Object.keys(values).length === 0 ? null : values;
67
76
  }
68
77
  function resolveParagraph(pPr, context, placement = null) {
69
- const tableStyle = tableStyleOf(placement, context);
78
+ const tableStyle = placement === null ? void 0 : tableStyleFor(placement.tableStyleId, context);
79
+ const conditions = conditionsOf(tableStyle, placement);
70
80
  const style = paragraphStyleFormat(
71
81
  pPr,
72
82
  context.styles,
73
83
  context.defaultParagraphStyleId
74
84
  );
75
85
  const direct = directLayer(pPr);
86
+ const table = [
87
+ { values: tableStyle?.paragraph ?? {}, stops: "style" },
88
+ ...conditions.map(
89
+ (condition) => ({ values: condition.paragraph, stops: "style" })
90
+ )
91
+ ];
76
92
  const explicit = [
77
93
  { values: context.paragraphDefaults, stops: "style" },
78
- { values: tableStyle?.paragraph ?? {}, stops: "style" },
94
+ ...table,
79
95
  { values: style?.paragraph ?? {}, stops: "style" },
80
96
  { values: direct, stops: "direct" }
81
97
  ];
@@ -83,10 +99,11 @@ function resolveParagraph(pPr, context, placement = null) {
83
99
  explicit.map((layer) => layer.values),
84
100
  context
85
101
  );
102
+ const belowNumbering = 1 + table.length;
86
103
  const layers = [
87
- ...explicit.slice(0, 2),
104
+ ...explicit.slice(0, belowNumbering),
88
105
  { values: numberingLayer(level), stops: "numbering" },
89
- ...explicit.slice(2)
106
+ ...explicit.slice(belowNumbering)
90
107
  ];
91
108
  const values = layers.reduce(
92
109
  (base, layer) => layerValues(base, layer.values),
@@ -107,8 +124,10 @@ function resolveParagraph(pPr, context, placement = null) {
107
124
  ...displayDefaults
108
125
  } = context.runDefaults;
109
126
  const styleRun = {
110
- ...displayDefaults,
111
- ...tableStyle?.run,
127
+ ...conditions.reduce(
128
+ (run, condition) => ({ ...run, ...condition.run }),
129
+ { ...displayDefaults, ...tableStyle?.run }
130
+ ),
112
131
  ...style?.run
113
132
  };
114
133
  return {
@@ -136,5 +155,6 @@ function inheritedRunFormat(rPr, paragraph, context) {
136
155
  export {
137
156
  inheritedRunFormat,
138
157
  resolveParagraph,
139
- resolveRun
158
+ resolveRun,
159
+ tableStyleFor
140
160
  };
@@ -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,5 +1,6 @@
1
1
  // src/docx/formatting/styles.ts
2
2
  import {
3
+ TABLE_STYLE_CONDITIONS,
3
4
  toParagraphFormat,
4
5
  toRunFormat,
5
6
  toTableFormat
@@ -9,11 +10,16 @@ import { ST_OnOff } from "../../ooxml/simpleTypes.js";
9
10
  import { childValue, isOn, wAttr } from "../../ooxml/units.js";
10
11
  import { childByLocalName, elementChildren } from "../../ooxml/xml.js";
11
12
  import {
13
+ layerBandSizes,
12
14
  layerCellMargins,
15
+ layerCellStyleFormat,
13
16
  layerInsideBorders,
17
+ NO_BAND_SIZES,
14
18
  NO_CELL_MARGINS,
15
19
  NO_INSIDE_BORDERS,
20
+ readBandSizes,
16
21
  readCellMarginsOf,
22
+ readCellStyleFormat,
17
23
  readInsideBorders,
18
24
  readTableFormat
19
25
  } from "../tableFormatting.js";
@@ -35,23 +41,51 @@ function styleChain(id, sources) {
35
41
  return chain;
36
42
  }
37
43
  var EMPTY_STYLE_FORMAT = {
44
+ type: "paragraph",
38
45
  paragraph: {},
39
46
  run: {},
40
47
  table: {},
41
48
  tableInside: NO_INSIDE_BORDERS,
42
- tableCellMargins: NO_CELL_MARGINS
49
+ tableCellMargins: NO_CELL_MARGINS,
50
+ tableBands: NO_BAND_SIZES,
51
+ tableConditions: {}
43
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
+ }
44
74
  function readStyleFormat(source, themeFonts) {
45
75
  return {
76
+ type: source.type,
46
77
  paragraph: readParagraphFormat(source.pPr) ?? {},
47
78
  run: readRunFormat(source.rPr, themeFonts) ?? {},
48
79
  table: readTableFormat(source.tblPr) ?? {},
49
80
  tableInside: readInsideBorders(source.tblPr),
50
- tableCellMargins: readCellMarginsOf(source.tblPr, "tblCellMar")
81
+ tableCellMargins: readCellMarginsOf(source.tblPr, "tblCellMar"),
82
+ tableBands: readBandSizes(source.tblPr),
83
+ tableConditions: readConditions(source, themeFonts)
51
84
  };
52
85
  }
53
86
  function layerStyleFormat(base, over) {
54
87
  return {
88
+ type: over.type,
55
89
  paragraph: layerParagraphValues(base.paragraph, over.paragraph),
56
90
  run: { ...base.run, ...over.run },
57
91
  table: { ...base.table, ...over.table },
@@ -59,12 +93,45 @@ function layerStyleFormat(base, over) {
59
93
  tableCellMargins: layerCellMargins(
60
94
  base.tableCellMargins,
61
95
  over.tableCellMargins
96
+ ),
97
+ tableBands: layerBandSizes(base.tableBands, over.tableBands),
98
+ tableConditions: layerConditions(
99
+ base.tableConditions,
100
+ over.tableConditions
62
101
  )
63
102
  };
64
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
+ }
65
122
  function foldChain(chain, themeFonts) {
66
123
  return chain.map((source) => readStyleFormat(source, themeFonts)).reduce(layerStyleFormat, EMPTY_STYLE_FORMAT);
67
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
+ }
68
135
  function readStyles(styles, themeFonts = NO_THEME_FONTS) {
69
136
  const sources = /* @__PURE__ */ new Map();
70
137
  for (const el of elementChildren(styles.documentElement)) {
@@ -72,10 +139,14 @@ function readStyles(styles, themeFonts = NO_THEME_FONTS) {
72
139
  const id = wAttr(el, "styleId");
73
140
  if (id === null || id.length === 0) continue;
74
141
  sources.set(id, {
142
+ type: styleTypeOf(el),
75
143
  basedOn: childValue(el, "basedOn"),
76
144
  pPr: childByLocalName(el, "pPr"),
77
145
  rPr: childByLocalName(el, "rPr"),
78
- tblPr: childByLocalName(el, "tblPr")
146
+ tblPr: childByLocalName(el, "tblPr"),
147
+ tblStylePr: elementChildren(el).filter(
148
+ (child) => child.localName === "tblStylePr"
149
+ )
79
150
  });
80
151
  }
81
152
  const table = /* @__PURE__ */ new Map();
@@ -84,6 +155,15 @@ function readStyles(styles, themeFonts = NO_THEME_FONTS) {
84
155
  }
85
156
  return table;
86
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
+ }
87
167
  function isDefaultStyle(el) {
88
168
  return ST_OnOff.parse(wAttr(el, "default")) === true;
89
169
  }
@@ -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,
@@ -1,17 +1,25 @@
1
- /** Reads the first section's header and footer stories for the page preview. */
2
- import type { ParagraphAlign } from "../model/format";
3
- export type HeaderFooterVariant = "default" | "first" | "even";
4
- export type PageField = "PAGE" | "NUMPAGES";
5
- export type HeaderFooterSegment = {
6
- kind: "text";
7
- value: string;
8
- } | {
9
- kind: "field";
10
- field: PageField;
11
- };
12
- /** A display-only projection. The original part remains untouched in the package. */
1
+ /**
2
+ * The header and footer stories of a document: where each one is written, which section shows it,
3
+ * what it reads as on a given page, and where an edited one goes back out.
4
+ *
5
+ * A header part is a story of the same schema as the body (`./story`): its blocks are read by the
6
+ * same readers and sliced verbatim by the same scanner, so an edit to one rides a transaction and
7
+ * the part it stands in goes back out as the bytes it arrived as until somebody changes it. What
8
+ * the page preview draws is a projection of that story rather than a reading of its own.
9
+ *
10
+ * Which story a section shows is the section's question (`./sections`): every section names its own
11
+ * variants, so the second section of a document draws its own header and not the first section's.
12
+ */
13
+ import type { Node as PMNode } from "prosemirror-model";
14
+ import { type ParagraphAlign } from "../model/format";
15
+ import { type StoryKey } from "../schema/stories";
16
+ import type { PartPlanner } from "./partPlan";
17
+ import { type DocumentSection } from "./sections";
18
+ import { type ImportedStory, type StoryDeps } from "./story";
19
+ /** One story a section may show, as the document currently says it */
13
20
  export interface HeaderFooterContent {
14
- segments: readonly HeaderFooterSegment[];
21
+ story: PMNode;
22
+ /** What the first paragraph of the story is aligned to, which is what the preview is drawn with */
15
23
  align: ParagraphAlign | null;
16
24
  }
17
25
  export interface HeaderFooterVariants {
@@ -26,11 +34,72 @@ export interface HeadersFooters {
26
34
  evenAndOdd: boolean;
27
35
  pageNumberStart: number;
28
36
  }
29
- export declare const NO_HEADERS_FOOTERS: HeadersFooters;
30
- /** Reads the first section's display stories and section-level selection switches. */
31
- export declare function readHeadersFooters(parts: Map<string, Uint8Array>, mainPartPath: string, body: Element): HeadersFooters;
37
+ /**
38
+ * What picking one section's stories takes beyond the section itself.
39
+ *
40
+ * A section names a relationship, a relationship names a part, and a part is where a story stands,
41
+ * so the two ends are joined once when the document is opened. `w:evenAndOddHeaders` is a
42
+ * document-wide setting rather than a section's own (§17.15.1.29), so it rides along here.
43
+ */
44
+ export interface HeaderFooterStories {
45
+ /**
46
+ * The story each header or footer relationship of the main part names. The key says which of the
47
+ * two kinds it is, so a `w:headerReference` naming a footer relationship names no story.
48
+ */
49
+ readonly keyByRelId: ReadonlyMap<string, StoryKey>;
50
+ readonly evenAndOdd: boolean;
51
+ }
52
+ /**
53
+ * Every header and footer part a section of the document names, read as a story apiece, and the
54
+ * relationship each one answers to.
55
+ *
56
+ * A part is read once however many relationships point at it, and a part whose root is not the
57
+ * element its relationship promises is passed over: the reference names nothing this can draw, and
58
+ * the bytes stay where they are. A part no section names is not read at all, so an orphan a
59
+ * producer left behind - which may hold anything, a document this one never draws included - is
60
+ * neither a story of this document nor a reason to refuse the file, and its bytes go back out as
61
+ * they came.
62
+ */
63
+ export declare function readHeaderFooterStories(parts: Map<string, Uint8Array>, mainPartPath: string, referenced: ReadonlySet<string>, depsFor: (partPath: string) => StoryDeps): {
64
+ stories: readonly ImportedStory[];
65
+ refs: HeaderFooterStories;
66
+ };
67
+ /**
68
+ * The stories this section shows and the switches that pick between them.
69
+ *
70
+ * `storyOf` answers with what the document currently says rather than what the package arrived
71
+ * holding, so a header the editor rewrote is the one the preview draws.
72
+ */
73
+ export declare function variantsFor(section: DocumentSection, refs: HeaderFooterStories, storyOf: (key: StoryKey) => PMNode | null): HeadersFooters;
74
+ /**
75
+ * The number this visual page shows, counted from the start its section declares.
76
+ *
77
+ * `page` is the page's place in the whole document: the count is not restarted at a section
78
+ * boundary, which is what the editor's documented page numbering says.
79
+ */
32
80
  export declare function displayPageNumber(headersFooters: HeadersFooters, page: number): number;
33
- /** Resolves the section variant and evaluates PAGE and NUMPAGES for one visual page. */
34
- export declare function headerFooterText(variants: HeaderFooterVariants, headersFooters: HeadersFooters, page: number, totalPages: number): string | null;
35
- /** Resolves the direct alignment of the first paragraph in the selected story. */
36
- export declare function headerFooterAlign(variants: HeaderFooterVariants, headersFooters: HeadersFooters, page: number): ParagraphAlign | null;
81
+ /**
82
+ * The story this page of a section shows, and null where the section declares none for it.
83
+ *
84
+ * `pageInSection` is the page's place within its own section rather than in the document:
85
+ * `w:titlePg` selects the `first` story for the first page of every section it is written in
86
+ * (§17.10.1), and the odd or even story follows the number that page would carry counting from
87
+ * the section's own start (§17.10.6), so a second section opening halfway down a document draws
88
+ * its own first page as a first page.
89
+ */
90
+ export declare function headerFooterOn(variants: HeaderFooterVariants, headersFooters: HeadersFooters, pageInSection: number): HeaderFooterContent | null;
91
+ /**
92
+ * What the story reads as on one visual page: its paragraphs joined by newlines, with `PAGE` and
93
+ * `NUMPAGES` replaced by the numbers this page actually carries.
94
+ *
95
+ * `page` is the number the page shows rather than its place on the sheet, since that is what a
96
+ * `PAGE` field prints (§17.16.5.45).
97
+ */
98
+ export declare function headerFooterText(story: PMNode, page: number, totalPages: number): string;
99
+ /**
100
+ * Writes back the header and footer parts an edit changed, and no others.
101
+ *
102
+ * A story nobody touched is not written at all, so a document opened and exported hands every
103
+ * header part back as the bytes it arrived as, and editing one header leaves the rest untouched.
104
+ */
105
+ export declare const headerFooterPlanner: PartPlanner;