@docx-editor.dev/core 0.0.1 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +92 -2
  3. package/THIRD_PARTY_NOTICES.md +18 -0
  4. package/dist/automation.cjs +1 -0
  5. package/dist/automation.d.cts +74 -0
  6. package/dist/automation.d.ts +74 -0
  7. package/dist/automation.js +1 -0
  8. package/dist/binding.cjs +1 -0
  9. package/dist/binding.d.cts +82 -0
  10. package/dist/binding.d.ts +82 -0
  11. package/dist/binding.js +1 -0
  12. package/dist/chunk-5KSCB2OZ.js +2 -0
  13. package/dist/chunk-BSC44TIT.js +5 -0
  14. package/dist/chunk-DLPL5DAG.js +12 -0
  15. package/dist/chunk-DOEIARE2.js +2 -0
  16. package/dist/chunk-G7YCQBZE.cjs +5 -0
  17. package/dist/chunk-HBL3NNH5.cjs +1 -0
  18. package/dist/chunk-HR7K3W6A.js +1 -0
  19. package/dist/chunk-HVAV2JSN.js +11 -0
  20. package/dist/chunk-MYH2HCUJ.cjs +2 -0
  21. package/dist/chunk-NSM75TN6.cjs +1 -0
  22. package/dist/chunk-PHDVKUWZ.js +1 -0
  23. package/dist/chunk-QADYGK5L.cjs +12 -0
  24. package/dist/chunk-REZUWYB7.js +1 -0
  25. package/dist/chunk-RNBHTPW7.js +10 -0
  26. package/dist/chunk-UD2ZXLFI.cjs +2 -0
  27. package/dist/chunk-VYAVK2AH.cjs +1 -0
  28. package/dist/chunk-YUK46A2N.cjs +11 -0
  29. package/dist/chunk-ZMIX42J7.cjs +10 -0
  30. package/dist/chunk-ZT55Q52J.cjs +2 -0
  31. package/dist/chunk-ZUALAR4M.js +2 -0
  32. package/dist/content-control-walk-CbTqHq6O.d.cts +56 -0
  33. package/dist/content-control-walk-D06GijR0.d.ts +56 -0
  34. package/dist/contracts/document.cjs +1 -0
  35. package/dist/contracts/document.d.cts +246 -0
  36. package/dist/contracts/document.d.ts +246 -0
  37. package/dist/contracts/document.js +0 -0
  38. package/dist/contracts/editor.cjs +1 -0
  39. package/dist/contracts/editor.d.cts +11 -0
  40. package/dist/contracts/editor.d.ts +11 -0
  41. package/dist/contracts/editor.js +1 -0
  42. package/dist/contracts/interaction.cjs +1 -0
  43. package/dist/contracts/interaction.d.cts +11 -0
  44. package/dist/contracts/interaction.d.ts +11 -0
  45. package/dist/contracts/interaction.js +0 -0
  46. package/dist/contracts/modules.cjs +1 -0
  47. package/dist/contracts/modules.d.cts +90 -0
  48. package/dist/contracts/modules.d.ts +90 -0
  49. package/dist/contracts/modules.js +1 -0
  50. package/dist/contracts/types.cjs +1 -0
  51. package/dist/contracts/types.d.cts +452 -0
  52. package/dist/contracts/types.d.ts +452 -0
  53. package/dist/contracts/types.js +0 -0
  54. package/dist/editor-C1QRi1v4.d.ts +1671 -0
  55. package/dist/editor-D0UDock4.d.cts +1671 -0
  56. package/dist/editor.cjs +1 -0
  57. package/dist/editor.css +6017 -0
  58. package/dist/editor.d.cts +271 -0
  59. package/dist/editor.d.ts +271 -0
  60. package/dist/editor.js +1 -0
  61. package/dist/hf-references-BdjsQNE_.d.ts +71 -0
  62. package/dist/hf-references-CgEOSw3i.d.cts +71 -0
  63. package/dist/image-resources-BJnTpG66.d.ts +195 -0
  64. package/dist/image-resources-BpIydXtU.d.cts +195 -0
  65. package/dist/index-CrW-IxXt.d.cts +2515 -0
  66. package/dist/index-ZqBEOrTV.d.ts +2515 -0
  67. package/dist/index.cjs +1 -0
  68. package/dist/index.d.cts +22 -0
  69. package/dist/index.d.ts +22 -0
  70. package/dist/index.js +1 -0
  71. package/dist/layout.cjs +1 -0
  72. package/dist/layout.d.cts +2316 -0
  73. package/dist/layout.d.ts +2316 -0
  74. package/dist/layout.js +1 -0
  75. package/dist/note-nodes-BPSTVDMr.d.ts +108 -0
  76. package/dist/note-nodes-C6DLxlvj.d.cts +108 -0
  77. package/dist/note-properties-CnmCoory.d.cts +68 -0
  78. package/dist/note-properties-m75hmP70.d.ts +68 -0
  79. package/dist/ooxml-package-CR5us6ad.d.cts +354 -0
  80. package/dist/ooxml-package-D_CtywTW.d.ts +354 -0
  81. package/dist/ooxml-tree-BU0e3DVi.d.cts +871 -0
  82. package/dist/ooxml-tree-BU0e3DVi.d.ts +871 -0
  83. package/dist/output.cjs +1 -0
  84. package/dist/output.d.cts +158 -0
  85. package/dist/output.d.ts +158 -0
  86. package/dist/output.js +1 -0
  87. package/dist/protocol-CAkOBBGE.d.cts +1201 -0
  88. package/dist/protocol-oxHaWmt4.d.ts +1201 -0
  89. package/dist/review-support-DS8DYX2a.d.cts +326 -0
  90. package/dist/review-support-Fy3vdIea.d.ts +326 -0
  91. package/dist/revision-projection-72ZApe-g.d.cts +84 -0
  92. package/dist/revision-projection-DHAkcD_L.d.ts +84 -0
  93. package/dist/semantic-cell-selection-CZjBSmMv.d.cts +427 -0
  94. package/dist/semantic-cell-selection-DsmHmLJ5.d.ts +427 -0
  95. package/dist/semantic-interaction-D-Dszxrn.d.cts +187 -0
  96. package/dist/semantic-interaction-Dy-dCUFF.d.ts +187 -0
  97. package/dist/semantic-paint-drawings-BA3z9jl8.d.ts +21 -0
  98. package/dist/semantic-paint-drawings-D7qbB0E2.d.cts +21 -0
  99. package/dist/semantic-records-CJR3BvHs.d.cts +1432 -0
  100. package/dist/semantic-records-CWodBJsz.d.ts +1432 -0
  101. package/dist/shaped-measurer-B-TAtcQU.d.ts +613 -0
  102. package/dist/shaped-measurer-CNIT_svZ.d.cts +613 -0
  103. package/dist/store.cjs +1 -0
  104. package/dist/store.d.cts +2247 -0
  105. package/dist/store.d.ts +2247 -0
  106. package/dist/store.js +1 -0
  107. package/dist/tree-op-types-CwOeiaQ8.d.ts +1431 -0
  108. package/dist/tree-op-types-DMiW6nIH.d.cts +1431 -0
  109. package/dist/tree-package-store-D5S7VKs5.d.ts +708 -0
  110. package/dist/tree-package-store-DOKMtCnh.d.cts +708 -0
  111. package/dist/tree-session-CiUel5Kz.d.ts +542 -0
  112. package/dist/tree-session-D47_imvR.d.cts +542 -0
  113. package/dist/tree-store-CxifqwIv.d.cts +273 -0
  114. package/dist/tree-store-hLtjeyWE.d.ts +273 -0
  115. package/package.json +105 -8
  116. package/index.js +0 -1
@@ -0,0 +1,84 @@
1
+ import { O as OoxmlNode } from './ooxml-tree-BU0e3DVi.cjs';
2
+
3
+ /**
4
+ * What a revision wrapper asserts about the content inside it.
5
+ *
6
+ * `moveFrom` / `moveTo` are deliberately distinct from `delete` / `insert`: a move is one
7
+ * decision with two halves, and presenting it as an unrelated deletion and insertion invites
8
+ * resolving one without the other, which duplicates or loses the content.
9
+ */
10
+ type RevisionKind = 'insert' | 'delete' | 'moveFrom' | 'moveTo' | 'format';
11
+ /**
12
+ * One revision wrapper's provenance, as authored.
13
+ *
14
+ * `id` is the verbatim `@w:id` string rather than a number: `ST_DecimalNumber` restricts
15
+ * `xsd:integer` with no bounds, so a file may carry a value outside the safe integer range, and
16
+ * parsing it to a number would silently merge two distinct revisions.
17
+ *
18
+ * `date` is absent when the file omits it. `@w:date` is optional on `CT_TrackChange`, and
19
+ * inventing one is a silent content change.
20
+ */
21
+ interface RevisionAttribution {
22
+ readonly kind: RevisionKind;
23
+ readonly id: string;
24
+ readonly author: string;
25
+ readonly date?: string;
26
+ /** The wrapper's node id, so a surface can address this exact site. */
27
+ readonly nodeId: string;
28
+ }
29
+ /**
30
+ * Which revisions layout resolves before producing pages.
31
+ *
32
+ * - `all-markup` shows both halves of every change.
33
+ * - `proposed` shows what the document becomes if every change is accepted.
34
+ * - `original` shows what it was before any of them.
35
+ *
36
+ * The last two are specified as equal to accept-all and reject-all OUTPUT, which is what makes
37
+ * them testable, without either applying an op.
38
+ */
39
+ type RevisionDisplayMode = 'all-markup' | 'proposed' | 'original';
40
+ /**
41
+ * How a document renders tracked changes when nothing says otherwise.
42
+ *
43
+ * `all-markup` matches Word's own default: a reader who opens a document with pending changes
44
+ * sees them, rather than a clean-looking document hiding edits nobody has accepted.
45
+ */
46
+ declare const DEFAULT_REVISION_DISPLAY_MODE: RevisionDisplayMode;
47
+ /**
48
+ * Whether content under this stack of revisions is laid out in the given mode.
49
+ *
50
+ * Containment governs, so a single enclosing wrapper the mode resolves away suppresses
51
+ * everything inside it regardless of what the inner wrappers say. An insertion inside a
52
+ * deletion does not survive the proposed result: the deletion it sits in was accepted.
53
+ */
54
+ declare function revisionsVisible(revisions: readonly RevisionAttribution[], mode: RevisionDisplayMode): boolean;
55
+ /**
56
+ * The revision on a paragraph's own MARK, from `w:pPr/w:rPr/w:ins|w:del`.
57
+ *
58
+ * `EG_ParaRPrTrackChanges` records that the pilcrow itself was inserted or deleted, which is how
59
+ * Word writes a paragraph split or merge. It is not content — there is no text to decorate — so
60
+ * a surface shows it as a mark of its own beside the paragraph, the way Word draws a struck-
61
+ * through ¶.
62
+ *
63
+ * Property-position `w:ins`/`w:del` stay `generic` in the tree deliberately, so this reads them
64
+ * by name rather than by kind.
65
+ */
66
+ declare function paragraphMarkRevisionOf(paragraph: OoxmlNode): RevisionAttribution | null;
67
+ /**
68
+ * The tracked FORMAT change on a property list, from `w:rPrChange` or `w:pPrChange`.
69
+ *
70
+ * A property change alters no characters, so it has no span of its own to strike or underline.
71
+ * Word marks the affected text and says what changed; the minimum a reader needs is to see that
72
+ * this text's formatting is itself a pending decision.
73
+ *
74
+ * Read from the flattened property list because that is what layout already carries — the
75
+ * change wrapper is a `w:rPr`/`w:pPr` child like any other.
76
+ */
77
+ declare function formatRevisionOf(properties: readonly {
78
+ readonly localName: string;
79
+ readonly attributes?: Readonly<Record<string, string>>;
80
+ }[]): RevisionAttribution | null;
81
+ /** True when this stack of revisions marks its content as deleted from the live document. */
82
+ declare function revisionsAreDeletion(revisions: readonly RevisionAttribution[]): boolean;
83
+
84
+ export { DEFAULT_REVISION_DISPLAY_MODE as D, type RevisionDisplayMode as R, type RevisionAttribution as a, type RevisionKind as b, revisionsVisible as c, formatRevisionOf as f, paragraphMarkRevisionOf as p, revisionsAreDeletion as r };
@@ -0,0 +1,84 @@
1
+ import { O as OoxmlNode } from './ooxml-tree-BU0e3DVi.js';
2
+
3
+ /**
4
+ * What a revision wrapper asserts about the content inside it.
5
+ *
6
+ * `moveFrom` / `moveTo` are deliberately distinct from `delete` / `insert`: a move is one
7
+ * decision with two halves, and presenting it as an unrelated deletion and insertion invites
8
+ * resolving one without the other, which duplicates or loses the content.
9
+ */
10
+ type RevisionKind = 'insert' | 'delete' | 'moveFrom' | 'moveTo' | 'format';
11
+ /**
12
+ * One revision wrapper's provenance, as authored.
13
+ *
14
+ * `id` is the verbatim `@w:id` string rather than a number: `ST_DecimalNumber` restricts
15
+ * `xsd:integer` with no bounds, so a file may carry a value outside the safe integer range, and
16
+ * parsing it to a number would silently merge two distinct revisions.
17
+ *
18
+ * `date` is absent when the file omits it. `@w:date` is optional on `CT_TrackChange`, and
19
+ * inventing one is a silent content change.
20
+ */
21
+ interface RevisionAttribution {
22
+ readonly kind: RevisionKind;
23
+ readonly id: string;
24
+ readonly author: string;
25
+ readonly date?: string;
26
+ /** The wrapper's node id, so a surface can address this exact site. */
27
+ readonly nodeId: string;
28
+ }
29
+ /**
30
+ * Which revisions layout resolves before producing pages.
31
+ *
32
+ * - `all-markup` shows both halves of every change.
33
+ * - `proposed` shows what the document becomes if every change is accepted.
34
+ * - `original` shows what it was before any of them.
35
+ *
36
+ * The last two are specified as equal to accept-all and reject-all OUTPUT, which is what makes
37
+ * them testable, without either applying an op.
38
+ */
39
+ type RevisionDisplayMode = 'all-markup' | 'proposed' | 'original';
40
+ /**
41
+ * How a document renders tracked changes when nothing says otherwise.
42
+ *
43
+ * `all-markup` matches Word's own default: a reader who opens a document with pending changes
44
+ * sees them, rather than a clean-looking document hiding edits nobody has accepted.
45
+ */
46
+ declare const DEFAULT_REVISION_DISPLAY_MODE: RevisionDisplayMode;
47
+ /**
48
+ * Whether content under this stack of revisions is laid out in the given mode.
49
+ *
50
+ * Containment governs, so a single enclosing wrapper the mode resolves away suppresses
51
+ * everything inside it regardless of what the inner wrappers say. An insertion inside a
52
+ * deletion does not survive the proposed result: the deletion it sits in was accepted.
53
+ */
54
+ declare function revisionsVisible(revisions: readonly RevisionAttribution[], mode: RevisionDisplayMode): boolean;
55
+ /**
56
+ * The revision on a paragraph's own MARK, from `w:pPr/w:rPr/w:ins|w:del`.
57
+ *
58
+ * `EG_ParaRPrTrackChanges` records that the pilcrow itself was inserted or deleted, which is how
59
+ * Word writes a paragraph split or merge. It is not content — there is no text to decorate — so
60
+ * a surface shows it as a mark of its own beside the paragraph, the way Word draws a struck-
61
+ * through ¶.
62
+ *
63
+ * Property-position `w:ins`/`w:del` stay `generic` in the tree deliberately, so this reads them
64
+ * by name rather than by kind.
65
+ */
66
+ declare function paragraphMarkRevisionOf(paragraph: OoxmlNode): RevisionAttribution | null;
67
+ /**
68
+ * The tracked FORMAT change on a property list, from `w:rPrChange` or `w:pPrChange`.
69
+ *
70
+ * A property change alters no characters, so it has no span of its own to strike or underline.
71
+ * Word marks the affected text and says what changed; the minimum a reader needs is to see that
72
+ * this text's formatting is itself a pending decision.
73
+ *
74
+ * Read from the flattened property list because that is what layout already carries — the
75
+ * change wrapper is a `w:rPr`/`w:pPr` child like any other.
76
+ */
77
+ declare function formatRevisionOf(properties: readonly {
78
+ readonly localName: string;
79
+ readonly attributes?: Readonly<Record<string, string>>;
80
+ }[]): RevisionAttribution | null;
81
+ /** True when this stack of revisions marks its content as deleted from the live document. */
82
+ declare function revisionsAreDeletion(revisions: readonly RevisionAttribution[]): boolean;
83
+
84
+ export { DEFAULT_REVISION_DISPLAY_MODE as D, type RevisionDisplayMode as R, type RevisionAttribution as a, type RevisionKind as b, revisionsVisible as c, formatRevisionOf as f, paragraphMarkRevisionOf as p, revisionsAreDeletion as r };
@@ -0,0 +1,427 @@
1
+ import { e as OoxmlPart, a as OoxmlElement, O as OoxmlNode } from './ooxml-tree-BU0e3DVi.cjs';
2
+ import { P as PageGeometry, I as InlineDrawingRecord, A as AnchoredDrawingRecord, T as TextMeasurer, L as LineRecord, S as SemanticLayout, C as ContentControlBoundaryRecord, a as StyleSpanRecord, b as TableRowFragmentRecord, c as TableCellFragmentRecord } from './semantic-records-CJR3BvHs.cjs';
3
+ import { R as RevisionDisplayMode } from './revision-projection-72ZApe-g.cjs';
4
+ import { S as SemanticPosition, C as CaretGeometry, a as SemanticSelection } from './semantic-interaction-D-Dszxrn.cjs';
5
+
6
+ /**
7
+ * Hard ceiling on sections enumerated from a document (matches write-path
8
+ * `MAX_SECTIONS` in note/hf lifecycle). Hostile packages with unbounded `w:sectPr`
9
+ * marks fail closed here rather than amplifying layout props arrays.
10
+ */
11
+ declare const MAX_DOCUMENT_SECTIONS = 4096;
12
+ /** A section's margins in twips, including the header and footer reserve bands. */
13
+ interface SectionMargins {
14
+ readonly topTwips: number;
15
+ readonly rightTwips: number;
16
+ readonly bottomTwips: number;
17
+ readonly leftTwips: number;
18
+ readonly headerTwips: number;
19
+ readonly footerTwips: number;
20
+ readonly gutterTwips: number;
21
+ }
22
+ /** One explicit `w:col`: its width and the gap after it. */
23
+ interface SectionColumnDefinition {
24
+ readonly widthTwips: number;
25
+ /** Space after this column; zero on the final column. */
26
+ readonly gapTwips: number;
27
+ }
28
+ /**
29
+ * A section's column layout.
30
+ *
31
+ * Equal-width and explicit-width columns are one type because a file may declare `w:num` with no
32
+ * `w:col` children at all, and layout must handle both without branching at every use site.
33
+ */
34
+ interface SectionColumns {
35
+ readonly count: number;
36
+ /** Shared gap for equal-width columns and fallback gap for incomplete explicit definitions. */
37
+ readonly gapTwips: number;
38
+ readonly equalWidth?: boolean;
39
+ readonly separator?: boolean;
40
+ /** Authored `w:col` geometry when `equalWidth` is false. */
41
+ readonly definitions?: readonly SectionColumnDefinition[];
42
+ }
43
+ /**
44
+ * How this section is placed relative to the previous one (ECMA-376 17.6.22,
45
+ * `ST_SectionMark`).
46
+ *
47
+ * All five schema values are read. `nextColumn` paginates like `nextPage` for now: in a
48
+ * single-column section that IS Word's behaviour, and multi-column flow is not modelled,
49
+ * so collapsing it at the parse boundary would only hide the authored value from a
50
+ * consumer that asks.
51
+ */
52
+ type SectionBreakType = 'nextPage' | 'continuous' | 'evenPage' | 'oddPage' | 'nextColumn';
53
+ /**
54
+ * Authored `w:pgNumType` (ECMA-376 CT_PageNumber).
55
+ *
56
+ * Distinguishes three states via {@link SectionProperties.pageNumbering}:
57
+ * - element absent → `undefined` (Word defaults; no empty element to re-emit)
58
+ * - empty `<w:pgNumType/>` → `{}` (present, no authored attrs; must round-trip empty)
59
+ * - attributes set → only those keys appear (never invent schema defaults like `fmt=decimal`)
60
+ *
61
+ * `chapStyle` / `chapSep` are preserved for consumers; PAGE projection does not yet compose
62
+ * chapter numbers (heading outline resolution is out of this slice).
63
+ */
64
+ interface SectionPageNumbering {
65
+ /** Authored `@w:start` when present and in range; otherwise omitted. */
66
+ readonly start?: number;
67
+ /** Authored `@w:fmt` (ST_NumberFormat) when present; otherwise omitted. */
68
+ readonly fmt?: string;
69
+ /** Authored `@w:chapStyle` outline level when present and in range. */
70
+ readonly chapStyle?: number;
71
+ /** Authored `@w:chapSep` when present (hyphen / period / colon / emDash / enDash). */
72
+ readonly chapSep?: string;
73
+ }
74
+ /**
75
+ * One section's resolved `w:sectPr`, as layout needs it.
76
+ *
77
+ * Resolved, not raw: defaults the file omitted are filled in here (an absent `w:type` is
78
+ * `nextPage`), so layout never has to know which attributes were authored and which were
79
+ * inherited.
80
+ */
81
+ interface SectionProperties {
82
+ readonly pageSize: {
83
+ readonly widthTwips: number;
84
+ readonly heightTwips: number;
85
+ };
86
+ readonly margins: SectionMargins;
87
+ readonly columns: SectionColumns;
88
+ readonly landscape: boolean;
89
+ readonly titlePage: boolean;
90
+ /** Absent `w:type` defaults to `nextPage`. */
91
+ readonly breakType: SectionBreakType;
92
+ /**
93
+ * Authored page-number type. Absent when `w:pgNumType` is missing; empty object when the
94
+ * element is present with no attributes (comprehensive-fixture shape).
95
+ */
96
+ readonly pageNumbering?: SectionPageNumbering;
97
+ }
98
+ /**
99
+ * One section of the body story: contiguous top-level blocks plus the properties that end it.
100
+ *
101
+ * `blockStart` / `blockEndExclusive` index into `storyBlocks(part)`.
102
+ */
103
+ interface DocumentSection {
104
+ readonly index: number;
105
+ readonly properties: SectionProperties;
106
+ readonly blockStart: number;
107
+ readonly blockEndExclusive: number;
108
+ }
109
+ /** US Letter, portrait, one-inch margins: Word's own default when a section says nothing. */
110
+ declare const DEFAULT_SECTION_PROPERTIES: SectionProperties;
111
+ /**
112
+ * Parse authored `w:pgNumType` without inventing schema defaults.
113
+ *
114
+ * Returns `undefined` when the element is absent. An empty element yields `{}` so callers
115
+ * can tell "present but unauthored" from "missing" and serialization can re-emit empty.
116
+ * Hostile / out-of-range attribute values are dropped rather than clamped into meaning.
117
+ */
118
+ declare function parsePageNumbering(sectPr: OoxmlNode): SectionPageNumbering | undefined;
119
+ /** Parse one `w:sectPr` into geometry/break properties (null reads as Word's defaults). */
120
+ declare function parseSectionProperties(sectPr: OoxmlNode | null | undefined): SectionProperties;
121
+ /** `w:sectPr` nested under a paragraph's `w:pPr`, if present. */
122
+ declare function paragraphSectionNode(paragraph: OoxmlElement): OoxmlElement | undefined;
123
+ /**
124
+ * The section properties a part declares, or Word's defaults where it says nothing.
125
+ *
126
+ * Returns the FINAL section (body-level `w:sectPr`, else the last paragraph-level one).
127
+ * Multi-section geometry belongs to `enumerateDocumentSections`; chrome that needs "the
128
+ * document's page" still reads the last section, which is what Word's body-level sectPr is.
129
+ */
130
+ declare function readSectionProperties(part: OoxmlPart): SectionProperties;
131
+ /**
132
+ * Split the body story into sections.
133
+ *
134
+ * A paragraph carrying `w:pPr/w:sectPr` ends the current section (that paragraph is IN the
135
+ * section being ended). The body-level `w:sectPr` ends the final section. A document with
136
+ * neither yields one section of Word defaults covering every block.
137
+ *
138
+ * Enumeration is capped at {@link MAX_DOCUMENT_SECTIONS}. Further paragraph-level section
139
+ * breaks are ignored and remaining blocks fold into the last accepted section (fail closed).
140
+ *
141
+ * `displayMode` MUST match the one the caller passes to `storyBlocks`. `blockStart` /
142
+ * `blockEndExclusive` are indices into that list, and the list changes shape with the mode:
143
+ * the proposed view drops a paragraph whose mark and content a revision both removed. Slicing
144
+ * a filtered list with indices counted over an unfiltered one puts body text under another
145
+ * section's page geometry — the wrong paper size, the wrong margins, the wrong header.
146
+ */
147
+ declare function enumerateDocumentSections(part: OoxmlPart, displayMode?: RevisionDisplayMode): DocumentSection[];
148
+ /**
149
+ * Every section in a document, with a flag saying whether the list was cut short.
150
+ *
151
+ * `truncated` is reported rather than silent: section count comes from a file, so a crafted
152
+ * document declaring thousands of paragraph-level `w:sectPr` marks is bounded, and a reader
153
+ * should be able to tell that happened.
154
+ */
155
+ interface DocumentSectionsEnumeration {
156
+ readonly sections: DocumentSection[];
157
+ /** True when paragraph-level sectPr marks beyond {@link MAX_DOCUMENT_SECTIONS} were dropped. */
158
+ readonly truncated: boolean;
159
+ }
160
+ /**
161
+ * Like {@link enumerateDocumentSections}, but reports whether the section bound clipped
162
+ * hostile input. Prefer the plain enumerator for normal layout; use this when a caller
163
+ * needs a named fail-closed diagnostic.
164
+ */
165
+ declare function enumerateDocumentSectionsBounded(part: OoxmlPart, displayMode?: RevisionDisplayMode): DocumentSectionsEnumeration;
166
+ /**
167
+ * Section properties as the geometry layout paginates against.
168
+ *
169
+ * The gutter is added to the LEFT margin: it is binding allowance, extra space on the inner
170
+ * edge, and folding it into the content width instead would silently narrow every line.
171
+ */
172
+ declare function geometryOfSection(section: SectionProperties): PageGeometry;
173
+
174
+ /** A point in the coordinate space named by the function taking it. */
175
+ interface HitPoint {
176
+ readonly x: number;
177
+ readonly y: number;
178
+ }
179
+ /** The innermost table cell a point resolved through. */
180
+ interface TableCellAddress {
181
+ /** Canonical node id of the `w:tbl`. */
182
+ readonly tableId: string;
183
+ /** Canonical node id of the `w:tr`. */
184
+ readonly rowId: string;
185
+ /** Canonical node id of the `w:tc`. */
186
+ readonly cellId: string;
187
+ /** Ordinal in the WHOLE table, stable across fragments and header repeats. */
188
+ readonly rowIndex: number;
189
+ readonly gridColumn: number;
190
+ readonly gridSpan: number;
191
+ }
192
+ /** Stable inline drawing identity when a hit resolves to a drawing atom. */
193
+ interface SemanticHitDrawing {
194
+ readonly drawingNodeId: string;
195
+ readonly paragraphId: string;
196
+ readonly start: number;
197
+ }
198
+ /** What a point landed on: a semantic position, its caret geometry, and where it sits. */
199
+ interface SemanticHit {
200
+ readonly position: SemanticPosition;
201
+ readonly caret: CaretGeometry;
202
+ readonly pageIndex: number;
203
+ readonly lineId: string;
204
+ /** Null outside a table; the innermost cell when tables nest. */
205
+ readonly cell: TableCellAddress | null;
206
+ /**
207
+ * True when the point was inside the resolved line's box AND inside one of its spans.
208
+ *
209
+ * A caller distinguishing a click ON text from a click BESIDE it — to decide whether to
210
+ * claim the gesture at all — needs this, and cannot recover it from the position.
211
+ */
212
+ readonly onGlyphs: boolean;
213
+ /**
214
+ * Innermost content-control boundary covering the hit point, or null outside every control.
215
+ *
216
+ * Resolved from layout-published boundary geometry (not DOM). Nested controls prefer the
217
+ * deepest {@link ContentControlBoundaryRecord.nestingDepth}.
218
+ */
219
+ readonly contentControlId: string | null;
220
+ /** Non-null when the hit resolved to an inline drawing atom. */
221
+ readonly drawing: SemanticHitDrawing | null;
222
+ }
223
+ /**
224
+ * How precisely a hit resolves within a run.
225
+ *
226
+ * Without a measurer the offset is INTERPOLATED across the span's advance, which is exact only
227
+ * for monospaced text — supply one for proportional fonts, or a click lands a character or two
228
+ * away from the glyph under the pointer.
229
+ */
230
+ interface HitTestOptions {
231
+ /**
232
+ * Exact resolution of the character within a run.
233
+ *
234
+ * Absent, the offset is interpolated across the span's own advance, which is exact only for
235
+ * a uniform advance. Pass the measurer layout was produced with, or the answer can disagree
236
+ * with what was painted.
237
+ */
238
+ readonly measurer?: TextMeasurer;
239
+ /** Vertical weight for the nearest-block rule. */
240
+ readonly verticalWeight?: number;
241
+ }
242
+ /**
243
+ * How much more a point of vertical distance counts than a point of horizontal distance.
244
+ *
245
+ * Without it, clicking far out in the right margin beside a two-word line picks whichever
246
+ * block happens to be directly below, because that block is horizontally nearer. Weighting
247
+ * the vertical axis makes "the line I am level with" win, which is what the pointer meant.
248
+ */
249
+ declare const DEFAULT_VERTICAL_WEIGHT = 8;
250
+ /**
251
+ * The page a sheet-space y belongs to.
252
+ *
253
+ * The gutter between page *i* and page *i+1* resolves to page *i*, because the nearest text
254
+ * to a point in that gap is the last line of the page above it. That falls out of searching
255
+ * for the last page whose top is at or above the point, with no special case: the gutter is
256
+ * inside `[top(i), top(i+1))` by construction. A point above the first page clamps to it, and
257
+ * a point past the last page clamps to that.
258
+ */
259
+ declare function pageAtY(layout: SemanticLayout, sheetY: number): number;
260
+ /** True when a sheet-space point falls inside a page's header or footer box. */
261
+ declare function isFurniturePoint(layout: SemanticLayout, point: HitPoint): boolean;
262
+ /** Hit test a point given in PAGE-CONTENT coordinates, the space the fragment boxes use. */
263
+ declare function hitTestPage(layout: SemanticLayout, pageIndex: number, point: HitPoint, options?: HitTestOptions): SemanticHit | null;
264
+ /**
265
+ * Hit test a point given in SHEET coordinates — the space `page.box` lives in, and the space
266
+ * a surface's own pixel offsets convert into.
267
+ */
268
+ declare function hitTestSheet(layout: SemanticLayout, point: HitPoint, options?: HitTestOptions): SemanticHit | null;
269
+ /**
270
+ * Innermost content control whose published boundary geometry contains `point` on `pageIndex`.
271
+ *
272
+ * Nested controls that share the same content box resolve to the deepest nesting depth.
273
+ */
274
+ declare function contentControlAtPoint(layout: SemanticLayout, pageIndex: number, point: HitPoint): ContentControlBoundaryRecord | null;
275
+ /**
276
+ * The end position of a line, as Word places it.
277
+ *
278
+ * On a SOFT-WRAPPED line the space that caused the break is painted at the end of the line
279
+ * but the caret belongs before it — otherwise clicking in the right margin puts the caret
280
+ * visually at the start of the NEXT line, which reads as the click having missed. The last
281
+ * line of a paragraph has no such space to discount.
282
+ *
283
+ * A HARD BREAK is the same story with a character that is always there: the position after
284
+ * it belongs to the line the break opened (`caretAt` places it there), so a click in the
285
+ * right margin of the line the break ENDED has to stop in front of it or the caret appears
286
+ * a row below the click.
287
+ *
288
+ * A PAGE break is discounted even on the paragraph's LAST line, which is the one case the
289
+ * last-line shortcut got wrong. The position after such a break is on the next page — and
290
+ * when the remainder is empty it has no line anywhere, because Word Online starts the
291
+ * following block flush at the top of that page. So the caret for it stays behind on the
292
+ * line the break ended, and a click in the wide blank space beside the mark resolved to a
293
+ * position a page away from where it landed: the caret appeared under the pointer and the
294
+ * typing came out on the next page. `<w:p><w:r><w:br w:type="page"/></w:r></w:p>` is the
295
+ * commonest way to end a page, so that blank space is most of a page wide.
296
+ */
297
+ declare function lineEndOffset(layout: SemanticLayout, line: LineRecord): number;
298
+ /**
299
+ * The x of a model offset inside a span — the inverse of {@link offsetWithinSpan}.
300
+ *
301
+ * Shares the measurement, and the cache, with the hit test. Interpolating across the span's
302
+ * advance instead is exact only for a uniform one: in a proportional face the caret for
303
+ * offset 4 of an 8-character span is drawn at half its width, which lands in the middle of a
304
+ * glyph rather than between two.
305
+ */
306
+ declare function spanOffsetX(span: StyleSpanRecord, offset: number, measurer: TextMeasurer | undefined): number;
307
+ /**
308
+ * Where a caret sits on a line: its x, and the box it should be drawn at.
309
+ *
310
+ * The height comes from the RUN at the insertion point, not from the line. A line is as tall
311
+ * as its largest run, so a caret in 11pt text on a line that also carries 36pt text was drawn
312
+ * three times the height of the text it sits in. Word sizes the insertion point to the run it
313
+ * would type into, which is also how the painter already draws the selection band: every run
314
+ * is its own inline box, and the band steps with the text.
315
+ *
316
+ * Affinity at a shared model boundary:
317
+ * - after a layout-sized atom (tab / projected field), prefer the DOWNSTREAM span so the
318
+ * caret sits at the aligned destination (e.g. before CONFIDENTIAL after a right tab),
319
+ * matching hit-testing and caretStops;
320
+ * - otherwise the run BEFORE the offset wins — the run a keystroke would continue —
321
+ * except at the start of the line, where there is nothing before it.
322
+ */
323
+ declare function caretBoxOnLine(line: LineRecord, offset: number, measurer: TextMeasurer | undefined): {
324
+ x: number;
325
+ y: number;
326
+ height: number;
327
+ };
328
+ /** Page-content overlay rectangle for a drawing's painted extent. */
329
+ interface DrawingOverlayFrame {
330
+ readonly pageIndex: number;
331
+ /** Relative to {@link PageRecord.contentBox}. */
332
+ readonly x: number;
333
+ readonly y: number;
334
+ readonly width: number;
335
+ readonly height: number;
336
+ readonly record: InlineDrawingRecord | AnchoredDrawingRecord;
337
+ }
338
+ /**
339
+ * Locate a drawing's painted extent on the published layout.
340
+ *
341
+ * Coordinates are page-content relative — the same space {@link hitTestPage} uses — so an
342
+ * overlay can position from records without reading painted DOM geometry.
343
+ */
344
+ declare function findDrawingOverlayFrameInLayout(layout: SemanticLayout, drawingNodeId: string): DrawingOverlayFrame | null;
345
+
346
+ /** A rectangle of table cells. */
347
+ interface CellSelection {
348
+ readonly kind: 'cells';
349
+ /** Canonical node id of the `w:tbl`. */
350
+ readonly tableId: string;
351
+ /** Every selected `w:tc`, in document order, with merges resolved. */
352
+ readonly cellIds: readonly string[];
353
+ /** Inclusive row ordinals within the table. */
354
+ readonly rows: {
355
+ readonly from: number;
356
+ readonly to: number;
357
+ };
358
+ /** Inclusive grid columns. */
359
+ readonly columns: {
360
+ readonly from: number;
361
+ readonly to: number;
362
+ };
363
+ /**
364
+ * The equivalent text range.
365
+ *
366
+ * Every existing reader of a selection — deletion, the clipboard, the DOM mirror, viewport
367
+ * pinning — takes this and needs no knowledge that a rectangle produced it.
368
+ */
369
+ readonly text: SemanticSelection;
370
+ }
371
+ /** One painted occurrence of a cell, and where it sits. */
372
+ interface PlacedCell {
373
+ readonly pageIndex: number;
374
+ readonly tableId: string;
375
+ readonly row: TableRowFragmentRecord;
376
+ readonly cell: TableCellFragmentRecord;
377
+ /** Ordinal within the whole table, shared by a header row and every repeat of it. */
378
+ readonly rowIndex: number;
379
+ readonly isHeaderRepeat: boolean;
380
+ }
381
+ /**
382
+ * The rectangle two cells define.
383
+ *
384
+ * Grown to a fixpoint rather than taken literally: a cell that spans two columns cannot be
385
+ * half selected, and a vertically merged run cannot be selected in the middle. Word grows the
386
+ * rectangle until every cell it touches is wholly inside it, so dragging into a merged cell
387
+ * pulls the selection out to that cell's full extent.
388
+ */
389
+ declare function cellSelectionBetween(layout: SemanticLayout, anchor: TableCellAddress, head: TableCellAddress): CellSelection | null;
390
+ /** Paragraph ids inside a set of cells, in document order, each once. */
391
+ declare function paragraphsInCells(layout: SemanticLayout, cellIds: readonly string[]): readonly string[];
392
+ /** The style spans a cell selection covers, for reporting active formatting. */
393
+ declare function spansInCells(layout: SemanticLayout, cellIds: readonly string[]): readonly StyleSpanRecord[];
394
+ /** One rectangle per painted occurrence of a selected cell, in page-content coordinates. */
395
+ declare function cellSelectionRects(layout: SemanticLayout, cellIds: readonly string[]): readonly {
396
+ pageIndex: number;
397
+ x: number;
398
+ y: number;
399
+ width: number;
400
+ height: number;
401
+ }[];
402
+ /**
403
+ * A cell selection as plain text: tabs between cells, newlines between rows.
404
+ *
405
+ * What a spreadsheet and every other word processor put on the clipboard for a rectangle, and
406
+ * the only shape that survives the trip: the text range a rectangle stands in for would paste
407
+ * back as one run of characters with the grid gone.
408
+ */
409
+ declare function cellSelectionText(layout: SemanticLayout, selection: CellSelection): string;
410
+ /** Where a paragraph sits in a table, if it sits in one. */
411
+ interface TableCellContext {
412
+ readonly tableId: string;
413
+ readonly rows: number;
414
+ readonly columns: number;
415
+ readonly rowIndex: number;
416
+ readonly columnIndex: number;
417
+ }
418
+ /**
419
+ * The table context of one paragraph — what a toolbar reflects when the caret is in a cell.
420
+ *
421
+ * Answers for a plain caret, not only for a cell selection, because "am I in a table" is a
422
+ * question about where the caret is and a toolbar that only knew during a rectangle drag
423
+ * would show its table controls disabled while the user was typing in a cell.
424
+ */
425
+ declare function tableContextAt(layout: SemanticLayout, paragraphId: string): TableCellContext | null;
426
+
427
+ export { pageAtY as A, paragraphSectionNode as B, type CellSelection as C, DEFAULT_SECTION_PROPERTIES as D, paragraphsInCells as E, parsePageNumbering as F, parseSectionProperties as G, type HitPoint as H, readSectionProperties as I, spanOffsetX as J, spansInCells as K, tableContextAt as L, MAX_DOCUMENT_SECTIONS as M, type PlacedCell as P, type SectionProperties as S, type TableCellAddress as T, type SectionColumns as a, DEFAULT_VERTICAL_WEIGHT as b, type DocumentSection as c, type DocumentSectionsEnumeration as d, type DrawingOverlayFrame as e, type HitTestOptions as f, type SectionBreakType as g, type SectionColumnDefinition as h, type SectionMargins as i, type SectionPageNumbering as j, type SemanticHit as k, type SemanticHitDrawing as l, type TableCellContext as m, caretBoxOnLine as n, cellSelectionBetween as o, cellSelectionRects as p, cellSelectionText as q, contentControlAtPoint as r, enumerateDocumentSections as s, enumerateDocumentSectionsBounded as t, findDrawingOverlayFrameInLayout as u, geometryOfSection as v, hitTestPage as w, hitTestSheet as x, isFurniturePoint as y, lineEndOffset as z };