@beltype/cicero 0.1.8 → 0.1.10
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/README.md +7 -6
- package/dist/seam/client.d.ts +12 -4
- package/dist/seam/client.js +55 -19
- package/dist/seam/facsimile.d.ts +13 -5
- package/dist/seam/facsimile.js +28 -12
- package/dist/seam/rim.d.ts +6 -2
- package/dist/seam/rim.js +54 -11
- package/dist/src/capture.d.ts +28 -0
- package/dist/src/capture.js +114 -25
- package/dist/src/chase.js +3 -1
- package/dist/src/compose-dom.js +3 -2
- package/dist/src/compositor.d.ts +11 -2
- package/dist/src/compositor.js +47 -15
- package/dist/src/data-beltype.d.ts +5 -1
- package/dist/src/data-beltype.js +6 -1
- package/dist/src/document-state.d.ts +6 -2
- package/dist/src/document-state.js +87 -11
- package/dist/src/driver.d.ts +6 -0
- package/dist/src/driver.js +36 -46
- package/dist/src/forcing-memo.d.ts +10 -0
- package/dist/src/forcing-memo.js +22 -0
- package/dist/src/fragmentation.d.ts +4 -4
- package/dist/src/fragmentation.js +4 -4
- package/dist/src/fragments.d.ts +6 -0
- package/dist/src/fragments.js +90 -11
- package/dist/src/gauge.d.ts +0 -4
- package/dist/src/gauge.js +16 -30
- package/dist/src/measure.d.ts +17 -12
- package/dist/src/measure.js +30 -16
- package/dist/src/positions.js +21 -9
- package/dist/src/reads.js +3 -3
- package/dist/src/root.d.ts +18 -1
- package/dist/src/root.js +27 -1
- package/dist/src/stonehand.js +2 -6
- package/dist/src/word-space.d.ts +10 -8
- package/dist/src/word-space.js +44 -16
- package/package.json +5 -1
package/dist/src/reads.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import { READ_PREFIX, STRING_KEYWORDS, STRING_PROP_PREFIX, decodeRead, encodeStringProp, splitTopLevel } from './gcpm-encoding.js';
|
|
15
15
|
import { sheetsCountInPseudos, styleSheetsOf } from './capture.js';
|
|
16
16
|
import { format as formatCounter } from './counter-styles.js';
|
|
17
|
-
import { collapse, counterStatesAfter, counterValue, counterValues, documentOpsOf } from './document-state.js';
|
|
17
|
+
import { collapse, contentTextOf, counterStatesAfter, counterValue, counterValues, documentOpsOf } from './document-state.js';
|
|
18
18
|
import { indexBlocks, pageContaining, pageIntervals, pathOf } from './positions.js';
|
|
19
19
|
import { isInlineBox } from './word-space.js';
|
|
20
20
|
import { composeResumed } from './resume.js';
|
|
@@ -401,8 +401,8 @@ export function staticValues(sites, { doc, blocks, index = null, keep = null })
|
|
|
401
401
|
if (!s.target || isPageRead(s.read))
|
|
402
402
|
continue;
|
|
403
403
|
if (s.read.fn === 'text') {
|
|
404
|
-
// css-content-3 §2.6.3's `content` keyword is the element's string value, `content()`'s own reading (document-state's `collapse
|
|
405
|
-
put(values, s.key, s.prop, cssString(collapse(s.target
|
|
404
|
+
// css-content-3 §2.6.3's `content` keyword is the element's string value, `content()`'s own reading (document-state's `contentTextOf` and `collapse`, which leave out what a printer made from generated content); `before`, `after` and `first-letter` are read as `content`, the same stated limit `string-set` has.
|
|
405
|
+
put(values, s.key, s.prop, cssString(collapse(contentTextOf(s.target))));
|
|
406
406
|
continue;
|
|
407
407
|
}
|
|
408
408
|
const state = states.get(s.target);
|
package/dist/src/root.d.ts
CHANGED
|
@@ -87,7 +87,7 @@ export declare class BeltypeRoot extends HTMLElement {
|
|
|
87
87
|
/**
|
|
88
88
|
* THE INTAKE: the document's boxes become this element's light DOM (*content is one document*, I6), and are parked at once — before the first cut, not at the first presentation (*the pages are cut as far as they are asked*, 2026-10-12). A run that can stop at a page measures the sources while pages stand in the document, so it measures them where a resumed run always has: inside the root, in the flat tree under a slot that renders nothing, where `getComputedStyle` answers (*an unplaced original is parked, not unassigned*). Appended without parking they would answer nothing at all.
|
|
89
89
|
*
|
|
90
|
-
* @param boxes - the blocks, then the fixed boxes, then the running elements.
|
|
90
|
+
* @param boxes - the top-level boxes: the blocks, then the fixed boxes, then the running elements. A fixed box or running element inside a block comes in with its block.
|
|
91
91
|
*/
|
|
92
92
|
intake(...boxes: Element[]): void;
|
|
93
93
|
/**
|
|
@@ -125,6 +125,23 @@ export declare class BeltypeRoot extends HTMLElement {
|
|
|
125
125
|
oldTo: number;
|
|
126
126
|
priorLength: number;
|
|
127
127
|
} | null): void;
|
|
128
|
+
/**
|
|
129
|
+
* Draw again the chrome of every standing page that shows the running element at `at`, with nothing cut and nothing built (*the run resumes from an entry*, amended 2026-11-08): the seam's client replaced that element and the run's list now names the new one.
|
|
130
|
+
*
|
|
131
|
+
* @remarks A running element's edit is a chrome event: it is out of the flow, so no cut reads it, and which element a page shows is the page's `closes.running`, a fact about positions that did not move. So each page whose `closes.running` names the place lets go of its running-element clones and has its chrome drawn as a kept page whose chrome moved has it drawn in {@link present}, the bands measured again because a margin box sizes from what it says; its content, its key and every other page are left as they are.
|
|
132
|
+
* @param at - the element's place in `running`.
|
|
133
|
+
* @param running - the run's list, the new element in its place.
|
|
134
|
+
* @param marginBoxesFor - as {@link present} takes it.
|
|
135
|
+
* @returns how many pages were drawn again.
|
|
136
|
+
*/
|
|
137
|
+
redrawRunning(at: number, running: {
|
|
138
|
+
el: Element;
|
|
139
|
+
}[], marginBoxesFor: (cond: {
|
|
140
|
+
name: string;
|
|
141
|
+
first: boolean;
|
|
142
|
+
parity: string;
|
|
143
|
+
blank: boolean;
|
|
144
|
+
}) => object): number;
|
|
128
145
|
/**
|
|
129
146
|
* @returns how many pages there are and how many have their content.
|
|
130
147
|
*/
|
package/dist/src/root.js
CHANGED
|
@@ -120,7 +120,7 @@ export class BeltypeRoot extends HTMLElement {
|
|
|
120
120
|
/**
|
|
121
121
|
* THE INTAKE: the document's boxes become this element's light DOM (*content is one document*, I6), and are parked at once — before the first cut, not at the first presentation (*the pages are cut as far as they are asked*, 2026-10-12). A run that can stop at a page measures the sources while pages stand in the document, so it measures them where a resumed run always has: inside the root, in the flat tree under a slot that renders nothing, where `getComputedStyle` answers (*an unplaced original is parked, not unassigned*). Appended without parking they would answer nothing at all.
|
|
122
122
|
*
|
|
123
|
-
* @param boxes - the blocks, then the fixed boxes, then the running elements.
|
|
123
|
+
* @param boxes - the top-level boxes: the blocks, then the fixed boxes, then the running elements. A fixed box or running element inside a block comes in with its block.
|
|
124
124
|
*/
|
|
125
125
|
intake(...boxes) {
|
|
126
126
|
this.append(...boxes);
|
|
@@ -368,6 +368,32 @@ export class BeltypeRoot extends HTMLElement {
|
|
|
368
368
|
page.setMarginBox(box, t ? t.parts.map((part) => (typeof part === 'string' ? part : this.#runningPart(pg.closes.running?.[part.element]?.[part.which], running))) : null);
|
|
369
369
|
page.layoutBands();
|
|
370
370
|
}
|
|
371
|
+
/**
|
|
372
|
+
* Draw again the chrome of every standing page that shows the running element at `at`, with nothing cut and nothing built (*the run resumes from an entry*, amended 2026-11-08): the seam's client replaced that element and the run's list now names the new one.
|
|
373
|
+
*
|
|
374
|
+
* @remarks A running element's edit is a chrome event: it is out of the flow, so no cut reads it, and which element a page shows is the page's `closes.running`, a fact about positions that did not move. So each page whose `closes.running` names the place lets go of its running-element clones and has its chrome drawn as a kept page whose chrome moved has it drawn in {@link present}, the bands measured again because a margin box sizes from what it says; its content, its key and every other page are left as they are.
|
|
375
|
+
* @param at - the element's place in `running`.
|
|
376
|
+
* @param running - the run's list, the new element in its place.
|
|
377
|
+
* @param marginBoxesFor - as {@link present} takes it.
|
|
378
|
+
* @returns how many pages were drawn again.
|
|
379
|
+
*/
|
|
380
|
+
redrawRunning(at, running, marginBoxesFor) {
|
|
381
|
+
let drawn = 0;
|
|
382
|
+
for (const record of this.#records) {
|
|
383
|
+
const pg = record.ctx.pages[record.k];
|
|
384
|
+
if (!Object.values(pg.closes.running ?? {}).some((which) => Object.values(which).includes(at)))
|
|
385
|
+
continue;
|
|
386
|
+
for (const node of record.nodes)
|
|
387
|
+
if (!record.assigned.includes(node))
|
|
388
|
+
node.remove();
|
|
389
|
+
record.nodes = record.nodes.filter((node) => record.assigned.includes(node));
|
|
390
|
+
this.#collect = record.nodes;
|
|
391
|
+
this.#chrome(record.page, pg, this.#marginPlan(pg, record.ctx.account, marginBoxesFor), running);
|
|
392
|
+
this.#collect = null;
|
|
393
|
+
drawn++;
|
|
394
|
+
}
|
|
395
|
+
return drawn;
|
|
396
|
+
}
|
|
371
397
|
/**
|
|
372
398
|
* GCPM §1.2's `element()`, delivered — a clone of the running element per page, forwarded into the margin cell through a slot.
|
|
373
399
|
*
|
package/dist/src/stonehand.js
CHANGED
|
@@ -159,8 +159,6 @@ function walkOf(report, sourceOf, root = null, styleCache = new Map(), forcing =
|
|
|
159
159
|
const monolithic = (box) => {
|
|
160
160
|
if (box.anonymous)
|
|
161
161
|
return false; // a run of lines, never one unit
|
|
162
|
-
if (box.laidOutLast || box.laidOutFirst)
|
|
163
|
-
return true; // a footer written before its rows: its words stand before the rows in the word space, so no place inside it could be addressed (*the footer before the rows*)
|
|
164
162
|
const live = sourceOf(box.el) ?? box.el;
|
|
165
163
|
const held = isMonolith(box.el, styleOfBox(box), live);
|
|
166
164
|
// Named once per box, on the console, so a page that looks wrong for this reason says so.
|
|
@@ -210,7 +208,7 @@ function walkOf(report, sourceOf, root = null, styleCache = new Map(), forcing =
|
|
|
210
208
|
/**
|
|
211
209
|
* The walk stops at the edge (*the page asks the index*, 2026-09-25): a box the walk reads, in the procession, whose top lies below the limit. Nothing it or anything after it could offer can fit, so the walk takes the Class A boundary before it and stops.
|
|
212
210
|
*
|
|
213
|
-
* A float, an absolutely positioned box and a row are not where it stops: a float's top is where the float was pushed, not the procession's, and a row's first item is not the row's top. The premise is stated rather than proved — that in-flow tops do not go backward in document order — and a negative margin taller than the box above it, or a relative offset, would break it. A table's footer written before its rows broke it too, and is walked where it is laid out instead (`gauge.js
|
|
211
|
+
* A float, an absolutely positioned box and a row are not where it stops: a float's top is where the float was pushed, not the procession's, and a row's first item is not the row's top. The premise is stated rather than proved — that in-flow tops do not go backward in document order — and a negative margin taller than the box above it, or a relative offset, would break it. A table's footer written before its rows broke it too, and is walked where it is laid out instead (`gauge.js`, in display order, case 110).
|
|
214
212
|
*/
|
|
215
213
|
const standsBelow = (box, limit, eps) => !rowOf(box) && !parallelBox(box) && box.rect.top > limit + eps;
|
|
216
214
|
return { report, sourceOf, boxes, win, root, styleCache, forcing, styleOfBox, monolithic, insideMonolith, parallelBox, insideParallel, rowOf, insideRowItem, copy, walks, standsBelow };
|
|
@@ -355,9 +353,7 @@ function collect(w, { boxes, limit, pageStart, eps, stats }) {
|
|
|
355
353
|
// The root of a flow's own walk stands in no procession of its own: its row-mates are outside it, and a boundary before it is the outer walk's (*a parallel flow is a fragmentainer*, 2026-10-08).
|
|
356
354
|
const siblings = box === root ? [] : report.processionOf(box).filter((b) => !isAbsolutelyPositioned(styleOfBox(b)));
|
|
357
355
|
const si = siblings.indexOf(box);
|
|
358
|
-
|
|
359
|
-
// Nor does the box after a header written after its rows (the mirror): the place is after the header in the layout and before every row in the document, so the page would hold the header's copy alone.
|
|
360
|
-
if (si > 0 && !box.laidOutLast && !siblings[si - 1].laidOutFirst) {
|
|
356
|
+
if (si > 0) {
|
|
361
357
|
// Two siblings answer here, and they are not always the same one. **The keeps** are the immediately-adjacent box's, because §4.1 names *"a float and an immediately-adjacent in-flow or floated box"* as a Class A pair in as many words — a float's own `break-after` binds the boundary after it, which is §3.1's *should* on floats that this engine honours and Chromium declines. **The position** is the previous in-flow sibling's bottom border edge, because a parallel flow's extent is not a place in the procession the cuts divide (§2.1): the float is laid out beside the content, so the page closes where the previous in-flow box ended and the float's own bottom says nothing about it. Pricing this at the float's bottom is how a 96mm rail put every slab standing beside it off the page — measured, `cases/21-parallel-flows`, where the boundary before the first slab was priced at y 400 in a 264px page area.
|
|
362
358
|
const pair = siblings[si - 1];
|
|
363
359
|
const anchor = last(siblings.slice(0, si).filter((b) => !parallelBox(b))) ?? null;
|
package/dist/src/word-space.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ export declare const UNSPACED_SCRIPT: RegExp;
|
|
|
26
26
|
/**
|
|
27
27
|
* Could the browser have drawn a hyphen at a line boundary between these two characters that the source does not carry? The one question that decides whether a line inside a word may be a cut the fragment can write: a silent break needs nothing at the cut, and a break after U+00AD needs the soft hyphen the source holds written as the hyphenation character (`fragments.js`, *the hyphen is written at the cut*). What is left is a hyphen the browser drew between two letters under `hyphens: auto`, where no character of the source says where.
|
|
28
28
|
*
|
|
29
|
-
* **
|
|
29
|
+
* **Answered by measurement, read by the source on both sides.** Under `hyphens: auto` the browser may hyphenate between any two letters of a script that hyphenates, and nothing in the DOM says whether it did; the range rects do, an inked rect for the hyphen on the line the break ends. So the Gauge opens a piece at such a break only where it measured that hyphen (`gauge.js`, `drewHyphen`), and refuses one that drew none, where the page ends a line early rather than print a hyphen the browser did not draw; the fragment writer asks this same predicate of the same characters and adds the hyphenation character after the last kept letter (`fragments.js`). The address carries no mark: the measurement decides which breaks are cuts, and the source decides what the cut writes. `hyphens: none` and `manual` draw one only at a soft hyphen.
|
|
30
30
|
*
|
|
31
31
|
* @param before - the character before the break
|
|
32
32
|
* @param after - the character after it
|
|
@@ -209,21 +209,23 @@ export declare function clonesDecoration(el: Element): boolean;
|
|
|
209
209
|
*/
|
|
210
210
|
export declare function blockChildrenOf(el: Element, isInline?: (el: Element) => boolean): Element[];
|
|
211
211
|
/**
|
|
212
|
-
*
|
|
212
|
+
* A table's children in CSS 2.1 §17.2's display order: its header group before every other row and row group, its footer group after them, and everything else as written. Any other element's children are returned as they are, the same array.
|
|
213
213
|
*
|
|
214
|
-
* @remarks
|
|
214
|
+
* @remarks THE WORD SPACE follows this order inside a table (*the-word-space-follows-the-table-display-order*, 2026-11-07), and so does every reader of it: the position index numbers a table's words in it, a path's indices count a table's children in it, the Gauge walks a table's procession in it, and a fragment's two cuts put away the children standing before or after them in it. §17.2 lays a `table-header-group` out *"before all other rows and row groups"* and a `table-footer-group` *"after all other rows and row groups"*, wherever each is written, and Chromium paints them so; numbered in the order written, a header after its rows had its words last and its box first, which lost rows with no message (*thead-after-rows-and-tall-footer-lose-rows*). Only the first group of each kind moves, because §17.2 renders any later one as a row group. A move only ever goes toward the rows, so a table written in HTML's order is returned unchanged. Read by computed display, so a clone answers for its source, and a tree that cannot be asked (the DOM-free suites) keeps the order written.
|
|
215
215
|
*
|
|
216
|
-
* @param
|
|
216
|
+
* @param parent - the element whose children these are.
|
|
217
|
+
* @param items - its children, or what stands for them (the Gauge's boxes), in the order written.
|
|
218
|
+
* @param elOf - the element an item stands for; `null` for a text node, which stays where it is.
|
|
217
219
|
*/
|
|
218
|
-
export declare function
|
|
220
|
+
export declare function inDisplayOrder<T>(parent: Element, items: T[], elOf?: (item: T) => Element | null): T[];
|
|
219
221
|
/**
|
|
220
|
-
* Is this a table's
|
|
222
|
+
* Is this a table's footer group written before a row or row group of its table — HTML 4's order, still legal — which CSS 2.1 §17.2 lays out after them all the same?
|
|
221
223
|
*
|
|
222
|
-
* @remarks
|
|
224
|
+
* @remarks Asked by the driver alone, for the one shape that stays refused: such a footer taller than the page area (*the footer before the rows*, 2026-10-15). Its words follow the rows in the word space ({@link inDisplayOrder}), so everywhere else it is a footer like any other. Read by computed display, so a clone answers for its source.
|
|
223
225
|
*
|
|
224
226
|
* @param el - a clone or a source element.
|
|
225
227
|
*/
|
|
226
|
-
export declare function
|
|
228
|
+
export declare function footerBeforeRows(el: Element): boolean;
|
|
227
229
|
/**
|
|
228
230
|
* The computed style of the box an author declared — the clone's registered source, or the element itself where it is live and connected. `null` for everything else, which is the honest answer rather than a default: a detached clone with no registration is a `<br>` or a filler span the Compositor inserted, and an element nobody declared has no declaration to read.
|
|
229
231
|
*
|
package/dist/src/word-space.js
CHANGED
|
@@ -29,7 +29,7 @@ export const UNSPACED_SCRIPT = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Kata
|
|
|
29
29
|
/**
|
|
30
30
|
* Could the browser have drawn a hyphen at a line boundary between these two characters that the source does not carry? The one question that decides whether a line inside a word may be a cut the fragment can write: a silent break needs nothing at the cut, and a break after U+00AD needs the soft hyphen the source holds written as the hyphenation character (`fragments.js`, *the hyphen is written at the cut*). What is left is a hyphen the browser drew between two letters under `hyphens: auto`, where no character of the source says where.
|
|
31
31
|
*
|
|
32
|
-
* **
|
|
32
|
+
* **Answered by measurement, read by the source on both sides.** Under `hyphens: auto` the browser may hyphenate between any two letters of a script that hyphenates, and nothing in the DOM says whether it did; the range rects do, an inked rect for the hyphen on the line the break ends. So the Gauge opens a piece at such a break only where it measured that hyphen (`gauge.js`, `drewHyphen`), and refuses one that drew none, where the page ends a line early rather than print a hyphen the browser did not draw; the fragment writer asks this same predicate of the same characters and adds the hyphenation character after the last kept letter (`fragments.js`). The address carries no mark: the measurement decides which breaks are cuts, and the source decides what the cut writes. `hyphens: none` and `manual` draw one only at a soft hyphen.
|
|
33
33
|
*
|
|
34
34
|
* @param before - the character before the break
|
|
35
35
|
* @param after - the character after it
|
|
@@ -481,31 +481,59 @@ export function blockChildrenOf(el, isInline = isInlineBox) {
|
|
|
481
481
|
return out;
|
|
482
482
|
}
|
|
483
483
|
/**
|
|
484
|
-
*
|
|
484
|
+
* A table's children in CSS 2.1 §17.2's display order: its header group before every other row and row group, its footer group after them, and everything else as written. Any other element's children are returned as they are, the same array.
|
|
485
485
|
*
|
|
486
|
-
* @remarks
|
|
486
|
+
* @remarks THE WORD SPACE follows this order inside a table (*the-word-space-follows-the-table-display-order*, 2026-11-07), and so does every reader of it: the position index numbers a table's words in it, a path's indices count a table's children in it, the Gauge walks a table's procession in it, and a fragment's two cuts put away the children standing before or after them in it. §17.2 lays a `table-header-group` out *"before all other rows and row groups"* and a `table-footer-group` *"after all other rows and row groups"*, wherever each is written, and Chromium paints them so; numbered in the order written, a header after its rows had its words last and its box first, which lost rows with no message (*thead-after-rows-and-tall-footer-lose-rows*). Only the first group of each kind moves, because §17.2 renders any later one as a row group. A move only ever goes toward the rows, so a table written in HTML's order is returned unchanged. Read by computed display, so a clone answers for its source, and a tree that cannot be asked (the DOM-free suites) keeps the order written.
|
|
487
487
|
*
|
|
488
|
-
* @param
|
|
488
|
+
* @param parent - the element whose children these are.
|
|
489
|
+
* @param items - its children, or what stands for them (the Gauge's boxes), in the order written.
|
|
490
|
+
* @param elOf - the element an item stands for; `null` for a text node, which stays where it is.
|
|
489
491
|
*/
|
|
490
|
-
export function
|
|
491
|
-
if (sourceStyle(
|
|
492
|
-
return
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
492
|
+
export function inDisplayOrder(parent, items, elOf = (item) => item) {
|
|
493
|
+
if (items.length < 2 || !/^(inline-)?table$/.test(sourceStyle(parent)?.display ?? ''))
|
|
494
|
+
return items;
|
|
495
|
+
const displays = items.map((item) => {
|
|
496
|
+
const el = elOf(item);
|
|
497
|
+
return el?.nodeType === 1 ? sourceStyle(el)?.display ?? '' : '';
|
|
498
|
+
});
|
|
499
|
+
const h = displays.indexOf('table-header-group');
|
|
500
|
+
const f = displays.indexOf('table-footer-group');
|
|
501
|
+
const body = (i) => i !== h && i !== f && /^table-(row|row-group|header-group|footer-group)$/.test(displays[i]);
|
|
502
|
+
let first = -1;
|
|
503
|
+
let last = -1;
|
|
504
|
+
displays.forEach((_, i) => {
|
|
505
|
+
if (!body(i))
|
|
506
|
+
return;
|
|
507
|
+
if (first < 0)
|
|
508
|
+
first = i;
|
|
509
|
+
last = i;
|
|
510
|
+
});
|
|
511
|
+
const early = h >= 0 && first >= 0 && h > first;
|
|
512
|
+
const late = f >= 0 && last >= 0 && f < last;
|
|
513
|
+
if (!early && !late)
|
|
514
|
+
return items;
|
|
515
|
+
const out = [];
|
|
516
|
+
items.forEach((item, i) => {
|
|
517
|
+
if (early && i === first)
|
|
518
|
+
out.push(items[h]);
|
|
519
|
+
if (!((early && i === h) || (late && i === f)))
|
|
520
|
+
out.push(item);
|
|
521
|
+
if (late && i === last)
|
|
522
|
+
out.push(items[f]);
|
|
523
|
+
});
|
|
524
|
+
return out;
|
|
497
525
|
}
|
|
498
526
|
/**
|
|
499
|
-
* Is this a table's
|
|
527
|
+
* Is this a table's footer group written before a row or row group of its table — HTML 4's order, still legal — which CSS 2.1 §17.2 lays out after them all the same?
|
|
500
528
|
*
|
|
501
|
-
* @remarks
|
|
529
|
+
* @remarks Asked by the driver alone, for the one shape that stays refused: such a footer taller than the page area (*the footer before the rows*, 2026-10-15). Its words follow the rows in the word space ({@link inDisplayOrder}), so everywhere else it is a footer like any other. Read by computed display, so a clone answers for its source.
|
|
502
530
|
*
|
|
503
531
|
* @param el - a clone or a source element.
|
|
504
532
|
*/
|
|
505
|
-
export function
|
|
506
|
-
if (sourceStyle(el)?.display !== 'table-
|
|
533
|
+
export function footerBeforeRows(el) {
|
|
534
|
+
if (sourceStyle(el)?.display !== 'table-footer-group')
|
|
507
535
|
return false;
|
|
508
|
-
for (let s = el.
|
|
536
|
+
for (let s = el.nextElementSibling; s; s = s.nextElementSibling)
|
|
509
537
|
if (/^table-row(-group)?$/.test(sourceStyle(s)?.display ?? ''))
|
|
510
538
|
return true;
|
|
511
539
|
return false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@beltype/cicero",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "Cicero, a paged-media engine for the live browser: it cuts a document into pages under CSS Paged Media and presents them as real frames. Beta.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,6 +40,10 @@
|
|
|
40
40
|
"types": "./dist/seam/client.d.ts",
|
|
41
41
|
"import": "./dist/seam/client.js"
|
|
42
42
|
},
|
|
43
|
+
"./rim": {
|
|
44
|
+
"types": "./dist/seam/rim.d.ts",
|
|
45
|
+
"import": "./dist/seam/rim.js"
|
|
46
|
+
},
|
|
43
47
|
"./fragmentation": {
|
|
44
48
|
"types": "./dist/src/fragmentation.d.ts",
|
|
45
49
|
"import": "./dist/src/fragmentation.js"
|