@sobree/core 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/doc/styles.d.ts +12 -0
- package/dist/doc/types.d.ts +68 -31
- package/dist/docx/export/contentTypes.d.ts +1 -0
- package/dist/docx/export/context.d.ts +1 -1
- package/dist/docx/export/numbering.d.ts +2 -0
- package/dist/docx/import/anchoredFrames.d.ts +4 -0
- package/dist/docx/import/borders.d.ts +12 -0
- package/dist/docx/import/floatFrames.d.ts +11 -0
- package/dist/docx/import/inlineFrames.d.ts +4 -0
- package/dist/docx/import/paragraphs.d.ts +6 -1
- package/dist/docx/import/styles.d.ts +13 -0
- package/dist/docx/shared/drawingColor.d.ts +30 -0
- package/dist/docx/shared/units.d.ts +3 -2
- package/dist/docx/shared/xml.d.ts +12 -0
- package/dist/docx/types.d.ts +4 -0
- package/dist/editor/commands.d.ts +14 -0
- package/dist/editor/context.d.ts +71 -0
- package/dist/editor/dom.d.ts +21 -0
- package/dist/editor/events.d.ts +29 -0
- package/dist/editor/index.d.ts +85 -663
- package/dist/editor/internal/mutations.d.ts +1 -1
- package/dist/editor/ops/blocks.d.ts +42 -0
- package/dist/editor/ops/comments.d.ts +12 -0
- package/dist/editor/ops/parts.d.ts +71 -0
- package/dist/editor/ops/review.d.ts +67 -0
- package/dist/editor/ops/runs.d.ts +83 -0
- package/dist/editor/ops/trackedInput.d.ts +44 -0
- package/dist/editor/query.d.ts +22 -0
- package/dist/editor/revisionRuns.d.ts +56 -0
- package/dist/editor/selection.d.ts +34 -0
- package/dist/editor/types.d.ts +292 -0
- package/dist/editor/view/docRenderer/anchorPosition.d.ts +18 -0
- package/dist/editor/view/docRenderer/fontFallback.d.ts +18 -5
- package/dist/editor/view/docRenderer/inline.d.ts +2 -2
- package/dist/editor/view/docRenderer/lists.d.ts +22 -11
- package/dist/editor/view/docRenderer/sectionFlow.d.ts +23 -0
- package/dist/editor/view/docRenderer/table.d.ts +11 -2
- package/dist/index.css +1 -1
- package/dist/index.js +5481 -5060
- package/dist/index.js.map +1 -1
- package/dist/paperStack/paginationV2/apply.d.ts +18 -0
- package/dist/paperStack/paginationV2/engine.d.ts +7 -0
- package/dist/paperStack/paginationV2/measure.d.ts +9 -0
- package/dist/paperStack/paginationV2/types.d.ts +273 -0
- package/dist/paperStack/paper.d.ts +31 -9
- package/dist/paperStack/paperStack.d.ts +13 -1
- package/dist/paperStack/paperZone.d.ts +35 -0
- package/dist/plugins/marks.d.ts +4 -4
- package/dist/ydoc/runs.d.ts +14 -18
- package/dist/ydoc/schema.d.ts +5 -0
- package/package.json +1 -1
- package/dist/__vite-browser-external-DYxpcVy9.js +0 -5
- package/dist/__vite-browser-external-DYxpcVy9.js.map +0 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { PaginatedDoc } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Apply a PaginatedDoc to the source DOM. The `sourceBlocks` array
|
|
4
|
+
* must be the SAME elements (same `data-meas-id` stamps) the measure
|
|
5
|
+
* pass walked — the applicator uses the id to resolve a `PageSegment`
|
|
6
|
+
* back to the originating element.
|
|
7
|
+
*
|
|
8
|
+
* Returns one `HTMLElement[]` per page, in the order the page should
|
|
9
|
+
* render. The caller (paperStack) appends these into paper-content boxes.
|
|
10
|
+
*
|
|
11
|
+
* SIDE EFFECTS on the source DOM:
|
|
12
|
+
* - Paragraph / list-item splits clone the source element, replacing
|
|
13
|
+
* it with a head fragment in place.
|
|
14
|
+
* - List / table clones MOVE their LI / TR children out of the source
|
|
15
|
+
* into per-page clones; the source container is removed if emptied.
|
|
16
|
+
* Source DOM should be treated as consumed after this call.
|
|
17
|
+
*/
|
|
18
|
+
export declare function applyPaginatedDoc(doc: PaginatedDoc, sourceBlocks: readonly HTMLElement[]): HTMLElement[][];
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { BlockMeasurement, PaginatedDoc, PaginationConstraints } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Pure paginator over the new typed contract. Determinism, totality,
|
|
4
|
+
* forced-break semantics — all from the existing engine; this wrapper
|
|
5
|
+
* just translates.
|
|
6
|
+
*/
|
|
7
|
+
export declare function paginateMeasurements(measurements: ReadonlyArray<BlockMeasurement>, constraints: PaginationConstraints): PaginatedDoc;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BlockMeasurement } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Measure a flat list of top-level block elements.
|
|
4
|
+
*
|
|
5
|
+
* `blocks` is the same `HTMLElement[]` shape `paginateBlocks` takes
|
|
6
|
+
* today — caller's responsibility to filter to direct flow children of
|
|
7
|
+
* the source paper-content.
|
|
8
|
+
*/
|
|
9
|
+
export declare function measureBlocks(blocks: readonly HTMLElement[]): BlockMeasurement[];
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 2 paginator contract — the typed boundary between the renderer
|
|
3
|
+
* and the pagination engine.
|
|
4
|
+
*
|
|
5
|
+
* Today's flow (the layer this replaces):
|
|
6
|
+
*
|
|
7
|
+
* blocks: HTMLElement[]
|
|
8
|
+
* → buildItems() (reads live DOM `offsetHeight`,
|
|
9
|
+
* stamps `data-pag-*` ids,
|
|
10
|
+
* emits an Item[] stream)
|
|
11
|
+
* → paginate() (the pure engine — already first-class)
|
|
12
|
+
* → distributePages() (mutates DOM: splits <p>/<ol>/<table>)
|
|
13
|
+
* → collapse*Pages() (post-process passes that re-read heights
|
|
14
|
+
* from blocks in the WRONG DOM context,
|
|
15
|
+
* source of the worst recurring bugs)
|
|
16
|
+
*
|
|
17
|
+
* Why that's wrong (recorded in `packages/core/docs/SESSION_HANDOFF.md`):
|
|
18
|
+
* - Forced breaks are smuggled in as `Penalty(-Infinity)` inside the
|
|
19
|
+
* Item stream, NOT as first-class constraints. The engine can
|
|
20
|
+
* refuse to grow the page array when honouring them would create
|
|
21
|
+
* overflow — so a `<w:pageBreakBefore/>` that doesn't fit silently
|
|
22
|
+
* shortens the document.
|
|
23
|
+
* - Inter-module signalling is ad-hoc: `data-page-break-before`,
|
|
24
|
+
* `data-keep-next`, `data-pag-pid`, `data-pag-lid`, `data-pag-tid`,
|
|
25
|
+
* `.keep-together`, etc. — none of it typed.
|
|
26
|
+
* - The post-process passes re-measure block heights after some
|
|
27
|
+
* blocks have moved and others haven't, producing nonsense values
|
|
28
|
+
* (a 268px table measured as 36px in firstContent → mistakenly
|
|
29
|
+
* classified as a widow → absorbed onto the previous page → 268px
|
|
30
|
+
* overflow into the footer band).
|
|
31
|
+
*
|
|
32
|
+
* The new contract:
|
|
33
|
+
*
|
|
34
|
+
* BlockMeasurement[] ← computed ONCE from source DOM
|
|
35
|
+
* PaginationConstraints ← typed budget + rules
|
|
36
|
+
* → purePaginate() ← engine: pure (measurements,
|
|
37
|
+
* constraints) → PaginatedDoc
|
|
38
|
+
* PaginatedDoc ← partition, NOT a DOM mutation
|
|
39
|
+
* → applyPaginatedDoc() ← single DOM pass: splits + moves
|
|
40
|
+
*
|
|
41
|
+
* Pure. Typed. Forced-breaks-as-boundaries. One DOM mutation pass.
|
|
42
|
+
*
|
|
43
|
+
* This file is types only. The measurement pass, engine wrapper, and
|
|
44
|
+
* DOM applicator land in sibling files in subsequent steps and are
|
|
45
|
+
* gated behind a flag until per-fixture verification passes.
|
|
46
|
+
*/
|
|
47
|
+
/**
|
|
48
|
+
* One block as the paginator sees it. All quantities are pre-measured;
|
|
49
|
+
* the engine NEVER reads the DOM.
|
|
50
|
+
*
|
|
51
|
+
* Multi-line paragraphs, multi-item lists, multi-row tables are SINGLE
|
|
52
|
+
* BlockMeasurements with non-empty `splitPoints` — the engine breaks
|
|
53
|
+
* within the block when it chooses one of those points.
|
|
54
|
+
*/
|
|
55
|
+
export interface BlockMeasurement {
|
|
56
|
+
/**
|
|
57
|
+
* Stable identifier. The engine refers to blocks (and segments within
|
|
58
|
+
* blocks) only by id — never by DOM reference. The DOM applicator
|
|
59
|
+
* holds the `blockId → HTMLElement` map.
|
|
60
|
+
*
|
|
61
|
+
* Ids must be stable across pagination retries (footnote-zone budget
|
|
62
|
+
* recalc, e.g.). Caller's choice; typically derived from the source
|
|
63
|
+
* AST's `block-index` or from the rendered DOM's `data-block-index`.
|
|
64
|
+
*/
|
|
65
|
+
blockId: string;
|
|
66
|
+
/**
|
|
67
|
+
* Natural rendered height of this block in CSS px when placed in its
|
|
68
|
+
* canonical context (the source paper's `.paper-content`). Measured
|
|
69
|
+
* once by the measurement pass.
|
|
70
|
+
*
|
|
71
|
+
* For a splittable block (paragraph with multiple lines, list with
|
|
72
|
+
* multiple items, table with multiple rows), this is the height when
|
|
73
|
+
* the WHOLE block lands on one page. When the engine chooses to split
|
|
74
|
+
* at a `splitPoint`, the page-end segment's height is
|
|
75
|
+
* `splitPoint.yOffset`; the next-page segment's height is
|
|
76
|
+
* `height - splitPoint.yOffset`.
|
|
77
|
+
*/
|
|
78
|
+
height: number;
|
|
79
|
+
/**
|
|
80
|
+
* Inter-block gap that appears BEFORE this block in flow — the
|
|
81
|
+
* post-margin-collapse vertical distance between the previous block's
|
|
82
|
+
* bottom and this block's top. Encoded as Glue in the engine's
|
|
83
|
+
* stream; counted against page height only between non-trailing
|
|
84
|
+
* blocks (trailing glue discards at page boundaries).
|
|
85
|
+
*
|
|
86
|
+
* 0 for the first block in the stream.
|
|
87
|
+
*/
|
|
88
|
+
gapBefore: number;
|
|
89
|
+
/**
|
|
90
|
+
* Points at which the engine may break this block across pages.
|
|
91
|
+
* Empty / undefined → the block is monolithic (whole thing moves
|
|
92
|
+
* together). For paragraphs, one entry per line break. For lists,
|
|
93
|
+
* one per `<li>`. For tables, one per `<tr>`.
|
|
94
|
+
*
|
|
95
|
+
* The yOffset is the height consumed by the on-page side of the
|
|
96
|
+
* split, measured from the block's top edge. The breakpoint after
|
|
97
|
+
* the LAST line/item/row is implicit (it's the block's bottom edge)
|
|
98
|
+
* and not included.
|
|
99
|
+
*/
|
|
100
|
+
splitPoints?: ReadonlyArray<SplitPoint>;
|
|
101
|
+
/**
|
|
102
|
+
* The block carries an explicit forced page break BEFORE it
|
|
103
|
+
* (`<w:pageBreakBefore/>` on the paragraph, or
|
|
104
|
+
* `<w:br w:type="page"/>` in its runs). The engine MUST start a new
|
|
105
|
+
* page at this block — and MUST grow the page array if the previous
|
|
106
|
+
* page is already full.
|
|
107
|
+
*
|
|
108
|
+
* This is the field forced-break semantics hang on. The engine
|
|
109
|
+
* doesn't read `data-page-break-before` from DOM; it reads this.
|
|
110
|
+
*/
|
|
111
|
+
pageBreakBefore?: boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Keep on the same page as the NEXT block in the stream. Heading
|
|
114
|
+
* styles set this so the heading stays with its first content
|
|
115
|
+
* paragraph. If both don't fit, the break moves to BEFORE this
|
|
116
|
+
* block.
|
|
117
|
+
*/
|
|
118
|
+
keepWithNext?: boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Keep all of this block's split points together (i.e. the whole
|
|
121
|
+
* block stays on one page). Stronger than monolithic: a
|
|
122
|
+
* `keepTogether` block CAN have splitPoints (so the engine knows
|
|
123
|
+
* the block's internal structure for cost estimation) but is
|
|
124
|
+
* penalised heavily for actually breaking. Used for figures /
|
|
125
|
+
* `.keep-together` groups.
|
|
126
|
+
*/
|
|
127
|
+
keepTogether?: boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Out-of-flow blocks (`position: absolute` / `fixed`) contribute 0
|
|
130
|
+
* to the page budget. The engine still emits them in document order
|
|
131
|
+
* so the DOM applicator can route them to the right page, but their
|
|
132
|
+
* height doesn't compete with in-flow content for space.
|
|
133
|
+
*
|
|
134
|
+
* Anchored frames are intended to render via the floating layer
|
|
135
|
+
* (anchorLayer.ts) and not appear here at all; this flag covers the
|
|
136
|
+
* fallback where an out-of-flow block still ended up in the body
|
|
137
|
+
* block stream.
|
|
138
|
+
*/
|
|
139
|
+
outOfFlow?: boolean;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* A position within a block where the engine may break across a page
|
|
143
|
+
* boundary. The block stays as one DOM element when not broken; when
|
|
144
|
+
* the engine chooses to break here, the DOM applicator slices it.
|
|
145
|
+
*/
|
|
146
|
+
export interface SplitPoint {
|
|
147
|
+
/**
|
|
148
|
+
* Height (px) consumed by the on-page portion if the engine breaks
|
|
149
|
+
* AT this point. Equivalently: the position of this break within
|
|
150
|
+
* the block's natural rendered height.
|
|
151
|
+
*/
|
|
152
|
+
yOffset: number;
|
|
153
|
+
/**
|
|
154
|
+
* Stable identifier for the on-page segment ending here. For
|
|
155
|
+
* paragraphs, the line index. For lists, the `<li>` index. For
|
|
156
|
+
* tables, the `<tr>` index. The DOM applicator uses this to know
|
|
157
|
+
* where to cut.
|
|
158
|
+
*/
|
|
159
|
+
segmentId: string;
|
|
160
|
+
/**
|
|
161
|
+
* Cost added if the engine breaks at this point. 0 = neutral,
|
|
162
|
+
* `Number.POSITIVE_INFINITY` = forbidden. Used for widow / orphan
|
|
163
|
+
* penalties (e.g. forbidding a break that leaves 1 line of a
|
|
164
|
+
* 3-line paragraph alone).
|
|
165
|
+
*/
|
|
166
|
+
penalty?: number;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Engine constraints — the budget and rules the engine optimises
|
|
170
|
+
* within. Separate from `BlockMeasurement[]` so the same stream can
|
|
171
|
+
* be re-paginated under different budgets (footnote-zone recalc)
|
|
172
|
+
* without re-measuring.
|
|
173
|
+
*/
|
|
174
|
+
export interface PaginationConstraints {
|
|
175
|
+
/**
|
|
176
|
+
* Body-area height for page index `i`, in px. The engine uses
|
|
177
|
+
* `pageHeights[i]` when present, falling back to
|
|
178
|
+
* `defaultPageHeight` for pages beyond the array's length.
|
|
179
|
+
*
|
|
180
|
+
* Today's paginator computes per-page heights iteratively because
|
|
181
|
+
* footnote zones eat budget on specific pages; that signal flows in
|
|
182
|
+
* here once, instead of being re-discovered through retry loops.
|
|
183
|
+
*/
|
|
184
|
+
pageHeights: ReadonlyArray<number>;
|
|
185
|
+
/** Default body-area height for pages past `pageHeights.length`. */
|
|
186
|
+
defaultPageHeight: number;
|
|
187
|
+
/** Minimum lines of a paragraph that may sit on the new page. Default 1. */
|
|
188
|
+
widows?: number;
|
|
189
|
+
/** Minimum lines of a paragraph that may sit on the current page. Default 1. */
|
|
190
|
+
orphans?: number;
|
|
191
|
+
/**
|
|
192
|
+
* Penalty cost added to breaks that would create a widow or orphan
|
|
193
|
+
* inside `widows` / `orphans` limits. Default 10000 — high enough
|
|
194
|
+
* to win against natural breaks but finite so it doesn't escalate
|
|
195
|
+
* to `Infinity` and create unsatisfiable constraints.
|
|
196
|
+
*/
|
|
197
|
+
widowOrphanPenalty?: number;
|
|
198
|
+
/**
|
|
199
|
+
* Penalty cost added to breaks inside a `keepWithNext` adjacency or
|
|
200
|
+
* across a `keepTogether` block. Default 10000.
|
|
201
|
+
*/
|
|
202
|
+
keepPenalty?: number;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* The paginator's output: a partition of the input stream into pages,
|
|
206
|
+
* expressed as data. NO DOM mutation has happened yet.
|
|
207
|
+
*
|
|
208
|
+
* The DOM applicator reads this and performs the necessary splits +
|
|
209
|
+
* moves in a single pass. Snapshot tests bite at THAT layer.
|
|
210
|
+
*/
|
|
211
|
+
export interface PaginatedDoc {
|
|
212
|
+
pages: ReadonlyArray<PaginatedPage>;
|
|
213
|
+
/**
|
|
214
|
+
* Sum of penalty costs the engine accepted for this partition.
|
|
215
|
+
* Diagnostic: a high value means widow/orphan/keep rules were
|
|
216
|
+
* violated to satisfy a forced break.
|
|
217
|
+
*/
|
|
218
|
+
totalCost: number;
|
|
219
|
+
/**
|
|
220
|
+
* Whether the engine had to grow the page array beyond what the
|
|
221
|
+
* `pageHeights` array sized. True when a forced break landed on a
|
|
222
|
+
* page that wasn't accounted for in the constraints — the caller
|
|
223
|
+
* may want to re-measure footnote zones for the new page.
|
|
224
|
+
*/
|
|
225
|
+
grewPageArray: boolean;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* One page's assignment, in document order.
|
|
229
|
+
*/
|
|
230
|
+
export interface PaginatedPage {
|
|
231
|
+
segments: ReadonlyArray<PageSegment>;
|
|
232
|
+
/**
|
|
233
|
+
* Total height the engine packed onto this page, excluding trailing
|
|
234
|
+
* glue. Useful for the DOM applicator to know how much space the
|
|
235
|
+
* placed content needs (e.g. for vertical alignment within the
|
|
236
|
+
* paper-content box).
|
|
237
|
+
*/
|
|
238
|
+
usedHeight: number;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* One block's contribution to a page. When `range` is absent the
|
|
242
|
+
* whole block lands here. When present, only the slice from
|
|
243
|
+
* `startSegmentId` (exclusive of any earlier-page slice) to
|
|
244
|
+
* `endSegmentId` (last segment on this page) lands here.
|
|
245
|
+
*
|
|
246
|
+
* Continuation across pages of the same block is recognised by
|
|
247
|
+
* matching `blockId` between adjacent pages — both halves carry the
|
|
248
|
+
* same id; the segment ids tell the DOM applicator where to cut.
|
|
249
|
+
*/
|
|
250
|
+
export interface PageSegment {
|
|
251
|
+
blockId: string;
|
|
252
|
+
range?: SegmentRange;
|
|
253
|
+
}
|
|
254
|
+
export interface SegmentRange {
|
|
255
|
+
/** First on-page segment (inclusive). */
|
|
256
|
+
startSegmentId: string;
|
|
257
|
+
/** Last on-page segment (inclusive). */
|
|
258
|
+
endSegmentId: string;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* The pure paginator: typed in, typed out, no I/O, no globals.
|
|
262
|
+
*
|
|
263
|
+
* - Determinism: same inputs ⇒ same `PaginatedDoc` (modulo undefined
|
|
264
|
+
* behaviour on tied costs, which the engine MUST resolve in a
|
|
265
|
+
* stable, documented way — typically by preferring earlier breaks).
|
|
266
|
+
* - Totality: defined for every legal input. Empty `measurements` ⇒
|
|
267
|
+
* `{ pages: [], totalCost: 0, grewPageArray: false }`.
|
|
268
|
+
* - Forced-break correctness: if any `BlockMeasurement` has
|
|
269
|
+
* `pageBreakBefore: true`, the returned page assignment places it
|
|
270
|
+
* at the START of some page — never mid-page. The page array
|
|
271
|
+
* grows as needed.
|
|
272
|
+
*/
|
|
273
|
+
export type PurePaginate = (measurements: ReadonlyArray<BlockMeasurement>, constraints: PaginationConstraints) => PaginatedDoc;
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import { PageSetup } from './pageSetup';
|
|
2
2
|
import { AnchorLayerContext } from '../editor/view/docRenderer/anchorLayer';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
numbering: readonly NumberingDefinition[];
|
|
7
|
-
styles: readonly NamedStyle[];
|
|
8
|
-
rawParts: Record<string, Uint8Array>;
|
|
9
|
-
pageNumber: number;
|
|
10
|
-
totalPages: number;
|
|
11
|
-
}
|
|
3
|
+
import { ZoneRenderContext } from './paperZone';
|
|
4
|
+
import { AnchoredFrame, SectionProperties } from '../doc/types';
|
|
5
|
+
export type { ZoneRenderContext } from './paperZone';
|
|
12
6
|
/**
|
|
13
7
|
* A single paper — exactly one page. Fixed width and height from the page
|
|
14
8
|
* setup. Has a header zone, a content area, and a footer zone. The content
|
|
@@ -53,6 +47,15 @@ export declare class Paper {
|
|
|
53
47
|
readonly comments: HTMLElement;
|
|
54
48
|
private readonly header;
|
|
55
49
|
private readonly footer;
|
|
50
|
+
/**
|
|
51
|
+
* Floating overlays for the header / footer zones. Unlike `.paper-
|
|
52
|
+
* anchors` (which overlays only the content rectangle), these span the
|
|
53
|
+
* whole paper card so a header frame's page/margin-relative offsets
|
|
54
|
+
* land at the right spot above the content area. Painted from
|
|
55
|
+
* `headerFooterFrames[partId]` — a zone is flow + floats, like the body.
|
|
56
|
+
*/
|
|
57
|
+
private readonly headerAnchors;
|
|
58
|
+
private readonly footerAnchors;
|
|
56
59
|
constructor(container: HTMLElement, setup: PageSetup);
|
|
57
60
|
applySetup(setup: PageSetup): void;
|
|
58
61
|
/**
|
|
@@ -70,6 +73,25 @@ export declare class Paper {
|
|
|
70
73
|
*/
|
|
71
74
|
setHeaderBlocks(ctx: ZoneRenderContext): void;
|
|
72
75
|
setFooterBlocks(ctx: ZoneRenderContext): void;
|
|
76
|
+
/**
|
|
77
|
+
* Paint the header zone's floating frames. Resolved against the header
|
|
78
|
+
* flow (so `verticalFrom="paragraph"` anchors to a header paragraph).
|
|
79
|
+
* Pass `[]` to clear. Mirrors `setAnchoredFrames` for body.
|
|
80
|
+
*/
|
|
81
|
+
setHeaderFrames(frames: readonly AnchoredFrame[], ctx: AnchorLayerContext): void;
|
|
82
|
+
setFooterFrames(frames: readonly AnchoredFrame[], ctx: AnchorLayerContext): void;
|
|
83
|
+
/**
|
|
84
|
+
* Resolve each frame's `relativeFrom` origin to an absolute card-relative
|
|
85
|
+
* position, returning clones whose `offsetX/YEmu` are the final
|
|
86
|
+
* coordinates the (full-card, `inset:0`) overlay paints at. The pure
|
|
87
|
+
* `resolveAnchorPosition` owns the semantics; here we just supply the
|
|
88
|
+
* measured geometry: page margins (from the CSS vars) and — for
|
|
89
|
+
* `verticalFrom="paragraph"` — the anchor paragraph's rendered top,
|
|
90
|
+
* located within `zoneFlow` by the `data-block-index` `renderBlocks`
|
|
91
|
+
* stamps. `offsetTop` is zoom-invariant in Chromium, so the measurement
|
|
92
|
+
* stays logical at any render tier.
|
|
93
|
+
*/
|
|
94
|
+
private resolveFrames;
|
|
73
95
|
/**
|
|
74
96
|
* When a rich header (or footer) renders taller than the page's
|
|
75
97
|
* reserved margin, push body content out of the overlap.
|
|
@@ -10,6 +10,9 @@ import { AnchoredFrame, Block, NamedStyle, NumberingDefinition, SectionPropertie
|
|
|
10
10
|
*/
|
|
11
11
|
export interface RichZonesSource {
|
|
12
12
|
headerFooterBodies: Record<string, Block[]>;
|
|
13
|
+
/** Floating frames per header/footer part, keyed by the same partId as
|
|
14
|
+
* `headerFooterBodies`. Absent for docs whose zones have no floats. */
|
|
15
|
+
headerFooterFrames?: Record<string, AnchoredFrame[]>;
|
|
13
16
|
numbering: readonly NumberingDefinition[];
|
|
14
17
|
styles: readonly NamedStyle[];
|
|
15
18
|
rawParts: Record<string, Uint8Array>;
|
|
@@ -171,6 +174,15 @@ export declare class PaperStack {
|
|
|
171
174
|
private collectAllBlocks;
|
|
172
175
|
private ensurePaperCount;
|
|
173
176
|
private renderAllZones;
|
|
177
|
+
/**
|
|
178
|
+
* Build the `AnchorLayerContext` shared by body + zone overlays. The
|
|
179
|
+
* injected `renderBody` routes textbox bodies through the full
|
|
180
|
+
* `renderBlocks` pipeline so anchored text matches body formatting,
|
|
181
|
+
* keeping `anchorLayer` decoupled from `block.ts`.
|
|
182
|
+
*/
|
|
183
|
+
private anchorLayerCtx;
|
|
184
|
+
/** Context for clearing an overlay to empty (no rich zones to draw). */
|
|
185
|
+
private emptyAnchorCtx;
|
|
174
186
|
/**
|
|
175
187
|
* Filter the document's `anchoredFrames` per paper and ask each Paper
|
|
176
188
|
* to swap its anchor-layer DOM accordingly. A frame's destination
|
|
@@ -190,7 +202,7 @@ export declare class PaperStack {
|
|
|
190
202
|
* this is the only piece of mutual knowledge between body flow and
|
|
191
203
|
* the floating layer needed for paragraph anchoring.
|
|
192
204
|
*/
|
|
193
|
-
private
|
|
205
|
+
private buildParagraphIndex;
|
|
194
206
|
/**
|
|
195
207
|
* Section index a paper belongs to. Read off the first content
|
|
196
208
|
* block's `data-section-index` (stamped by `renderBlocks`). Empty
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { AnchorLayerContext } from '../editor/view/docRenderer/anchorLayer';
|
|
2
|
+
import { AnchoredFrame, Block, NamedStyle, NumberingDefinition } from '../doc/types';
|
|
3
|
+
/**
|
|
4
|
+
* Everything a header/footer zone needs to render its FLOW content. The
|
|
5
|
+
* floating layer (anchored frames) is painted separately via
|
|
6
|
+
* {@link paintZoneFrames} — a zone is a flow layer + a float layer, the
|
|
7
|
+
* same two-layer model the body uses.
|
|
8
|
+
*/
|
|
9
|
+
export interface ZoneRenderContext {
|
|
10
|
+
blocks: readonly Block[];
|
|
11
|
+
numbering: readonly NumberingDefinition[];
|
|
12
|
+
styles: readonly NamedStyle[];
|
|
13
|
+
rawParts: Record<string, Uint8Array>;
|
|
14
|
+
pageNumber: number;
|
|
15
|
+
totalPages: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Render a zone's flow blocks. Uses the same `renderBlocks` walker as
|
|
19
|
+
* body content so drawings, formatting, hyperlinks and tables all carry
|
|
20
|
+
* through. `PAGE` / `NUMPAGES` field nodes are substituted with this
|
|
21
|
+
* paper's page number / the total count.
|
|
22
|
+
*
|
|
23
|
+
* "Empty" here = no rendered text anywhere; an image-only header still
|
|
24
|
+
* counts as non-empty so the `is-empty` CSS doesn't collapse its space.
|
|
25
|
+
*/
|
|
26
|
+
export declare function renderZone(zone: HTMLElement, ctx: ZoneRenderContext): void;
|
|
27
|
+
/**
|
|
28
|
+
* Paint a zone's floating frames into its overlay element. Mirrors
|
|
29
|
+
* `Paper.setAnchoredFrames` for the body: `renderAnchorLayer` builds a
|
|
30
|
+
* fresh layer, we copy its children into the persistent overlay node so
|
|
31
|
+
* external observers keep a stable reference, and `is-empty` collapses
|
|
32
|
+
* the overlay when there are no frames.
|
|
33
|
+
*/
|
|
34
|
+
export declare function paintZoneFrames(overlay: HTMLElement, frames: readonly AnchoredFrame[], ctx: AnchorLayerContext): void;
|
|
35
|
+
export declare function setZoneText(zone: HTMLElement, text: string): void;
|
package/dist/plugins/marks.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Range as ApiRange } from '../doc/api';
|
|
2
2
|
import { RunProperties } from '../doc/types';
|
|
3
|
-
import {
|
|
3
|
+
import { EditorLike, WrapTag } from '../editor/types';
|
|
4
4
|
/**
|
|
5
5
|
* Mark toggle helpers — shared by the floating toolbar's mark buttons
|
|
6
6
|
* and the keyboard plugin (Ctrl+B / I / U / …).
|
|
@@ -34,16 +34,16 @@ export declare const MARK_COMMAND_DEFS: readonly MarkCommandDef[];
|
|
|
34
34
|
* `mark` (highlight) is delegated straight to `wrapRange` — it's not a
|
|
35
35
|
* toggle since highlight is a colour, not a boolean.
|
|
36
36
|
*/
|
|
37
|
-
export declare function toggleMark(editor:
|
|
37
|
+
export declare function toggleMark(editor: EditorLike, range: ApiRange, tag: WrapTag): void;
|
|
38
38
|
/**
|
|
39
39
|
* True when every non-empty text run inside `range` has the mark's "on"
|
|
40
40
|
* value. Walks hyperlink children. Multi-block ranges always read as
|
|
41
41
|
* inactive so a click sets the mark before clearing it.
|
|
42
42
|
*/
|
|
43
|
-
export declare function isMarkActive(editor:
|
|
43
|
+
export declare function isMarkActive(editor: EditorLike, range: ApiRange, tag: string): boolean;
|
|
44
44
|
/**
|
|
45
45
|
* Pick the right range to operate on: live DOM selection if any,
|
|
46
46
|
* otherwise the full extent of the block at the caret. Matches the
|
|
47
47
|
* "press Ctrl+B with caret only → bold the whole paragraph" UX.
|
|
48
48
|
*/
|
|
49
|
-
export declare function rangeAtSelection(editor:
|
|
49
|
+
export declare function rangeAtSelection(editor: EditorLike): ApiRange | null;
|
package/dist/ydoc/runs.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BreakRun, DrawingRun, InlineRun, RunProperties } from '../doc/types';
|
|
1
|
+
import { BreakRun, CommentRefRun, DrawingRun, FieldRun, FootnoteRefRun, HyperlinkRun, InlineRun, RunProperties, TabRun, TextRun } from '../doc/types';
|
|
2
2
|
export interface DeltaOp {
|
|
3
3
|
/** Text content (string) or embed (object literal). Y.Text differentiates by typeof. */
|
|
4
4
|
insert: string | EmbedContent;
|
|
@@ -6,24 +6,19 @@ export interface DeltaOp {
|
|
|
6
6
|
* no marks apply (Yjs preference: omit rather than set empty). */
|
|
7
7
|
attributes?: Record<string, unknown>;
|
|
8
8
|
}
|
|
9
|
-
/**
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
__sobree: "drawing";
|
|
21
|
-
partPath: string;
|
|
22
|
-
widthEmu: number;
|
|
23
|
-
heightEmu: number;
|
|
24
|
-
placement: DrawingRun["placement"];
|
|
25
|
-
altText?: string;
|
|
9
|
+
/** Run kinds that travel as atomic embeds (everything except text,
|
|
10
|
+
* which is the Y.Text string itself, and hyperlink, which flattens to
|
|
11
|
+
* a `link` mark on its children). */
|
|
12
|
+
type EmbedRun = Exclude<InlineRun, TextRun | HyperlinkRun>;
|
|
13
|
+
/** An embed is the run itself, structurally: `kind` becomes the
|
|
14
|
+
* `__sobree` discriminator and `properties` move to the op's
|
|
15
|
+
* attributes. DERIVED from the AST type — a new field on any embed
|
|
16
|
+
* run kind is carried automatically; there is no per-field whitelist
|
|
17
|
+
* that could silently drop it. */
|
|
18
|
+
type EmbedOf<R extends EmbedRun> = Omit<R, "kind" | "properties"> & {
|
|
19
|
+
__sobree: R["kind"];
|
|
26
20
|
};
|
|
21
|
+
export type EmbedContent = EmbedOf<BreakRun> | EmbedOf<TabRun> | EmbedOf<FieldRun> | EmbedOf<DrawingRun> | EmbedOf<FootnoteRefRun> | EmbedOf<CommentRefRun>;
|
|
27
22
|
/** The `link` mark — stamped on every char inside a HyperlinkRun. */
|
|
28
23
|
export interface LinkMark {
|
|
29
24
|
href: string;
|
|
@@ -49,3 +44,4 @@ export declare function attrsToRunProps(attrs: Record<string, unknown> | undefin
|
|
|
49
44
|
* Y.Text diff to detect cells that haven't changed.
|
|
50
45
|
*/
|
|
51
46
|
export declare function deepEqual(a: unknown, b: unknown): boolean;
|
|
47
|
+
export {};
|
package/dist/ydoc/schema.d.ts
CHANGED
|
@@ -117,6 +117,11 @@ export declare const Y_BLOCK_AST_KEY = "_ast";
|
|
|
117
117
|
export declare const Y_META_FIELDS: {
|
|
118
118
|
readonly sections: "sections";
|
|
119
119
|
readonly headerFooterBodies: "headerFooterBodies";
|
|
120
|
+
readonly anchoredFrames: "anchoredFrames";
|
|
121
|
+
readonly headerFooterFrames: "headerFooterFrames";
|
|
122
|
+
readonly footnotes: "footnotes";
|
|
123
|
+
readonly comments: "comments";
|
|
124
|
+
readonly settings: "settings";
|
|
120
125
|
readonly styles: "styles";
|
|
121
126
|
readonly numbering: "numbering";
|
|
122
127
|
readonly fonts: "fonts";
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"__vite-browser-external-DYxpcVy9.js","sources":["../__vite-browser-external"],"sourcesContent":["export default {}"],"names":["__viteBrowserExternal"],"mappings":"AAAA,MAAAA,IAAe,CAAA;"}
|