@sobree/core 0.1.18 → 0.1.20
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/fields.d.ts +11 -0
- package/dist/doc/types.d.ts +9 -0
- package/dist/editor/view/docRenderer/outlineNumbering.d.ts +8 -0
- package/dist/index.css +1 -1
- package/dist/index.js +2000 -1869
- package/dist/index.js.map +1 -1
- package/dist/paperStack/paperStack.d.ts +0 -18
- package/package.json +1 -1
- package/dist/paperStack/paginationV2/apply.d.ts +0 -18
- package/dist/paperStack/paginationV2/engine.d.ts +0 -7
- package/dist/paperStack/paginationV2/measure.d.ts +0 -9
- package/dist/paperStack/paginationV2/types.d.ts +0 -273
|
@@ -216,22 +216,4 @@ export declare class PaperStack {
|
|
|
216
216
|
* a real "last page with just a signature line" still gets its own
|
|
217
217
|
* page. Idempotent; safe to call on a single-page result.
|
|
218
218
|
*/
|
|
219
|
-
/**
|
|
220
|
-
* Walk paginator output forward, absorbing pages whose total content
|
|
221
|
-
* height is ≤ 15% of `budgetPx` (the page-content budget) into the
|
|
222
|
-
* previous page. These tiny tail-pages are paginator widows — usually
|
|
223
|
-
* a 1-line overflow or an LRPB-induced sub-section that didn't have
|
|
224
|
-
* room. Both Word and LO tolerate a bit of bottom-margin spill in
|
|
225
|
-
* exchange for not spending an entire fresh page on the runt.
|
|
226
|
-
*
|
|
227
|
-
* Safety: only absorbs pages whose content height is smaller than the
|
|
228
|
-
* previous page's slack PLUS the widow tolerance (~20% of budget).
|
|
229
|
-
* If absorbing would visibly push content far past the page bottom,
|
|
230
|
-
* we leave the runt page alone — better an underfilled page than
|
|
231
|
-
* unreadable overflow.
|
|
232
|
-
*
|
|
233
|
-
* Run AFTER `collapseTrailingEmptyPages` so trailing whitespace is
|
|
234
|
-
* already merged and we're working on the real content layout.
|
|
235
|
-
*/
|
|
236
|
-
export declare function collapseUnderfilledPages(pages: readonly HTMLElement[][], budgetPx: number): HTMLElement[][];
|
|
237
219
|
export declare function collapseTrailingEmptyPages(pages: readonly HTMLElement[][]): HTMLElement[][];
|
package/package.json
CHANGED
|
@@ -1,18 +0,0 @@
|
|
|
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[][];
|
|
@@ -1,7 +0,0 @@
|
|
|
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;
|
|
@@ -1,9 +0,0 @@
|
|
|
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[];
|
|
@@ -1,273 +0,0 @@
|
|
|
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;
|