import type { PostextContent, PostextConfig } from '../types.js'; import { type VDTDocument } from '../vdt.js'; import type { MeasurementCache } from '../measure/index.js'; import { type FontFaceSetLike } from '../fonts/faces.js'; import { type LooseBudget } from './columnBalancing.js'; import { type BandCap, type BandPassReport } from './bandCaps.js'; export interface BuildDocumentOptions { /** * Cooperative cancellation hook. Called once per top-level content block * during placement. Throw (or return a truthy value checked by the caller) * to abort. Intended for running `buildDocument` inside a Web Worker where * a newer request has superseded this one. */ shouldCancel?: () => boolean; /** * Progress hook, called as placement advances: once per top-level content * block of every pass (the engine re-places the document several times — * band caps, column balancing — so `pass` counts up and the block counter * restarts). A long build can show a bar from it. */ onProgress?: (progress: BuildProgress) => void; /** * Called after every placement pass with its wall time — the engine * re-places the document several times (band caps, column balancing, * contents rounds); dev tooling shows where a build's time went. */ onPass?: (info: BuildPassInfo) => void; /** * The font set the build measures against (#629): by default * `document.fonts`, or `self.fonts` in a worker. At its start the build * drops what was measured in families whose faces changed since the * last build; at its end it lists the faces its text was set in that * the set could not give (`fontFallback` content warnings). `null` * skips both. */ fontSet?: FontFaceSetLike | null; } /** One placement pass of a build, as reported to {@link BuildDocumentOptions.onPass}. */ export interface BuildPassInfo { /** 1-based pass within its contents round. */ pass: number; /** 0-based round of a document laying out its own contents (see `MAX_TOC_ROUNDS`). */ tocRound: number; /** Wall time of the pass in ms. */ ms: number; /** Pages the pass produced. */ pages: number; } export interface BuildProgress { /** 1-based placement pass. */ pass: number; /** Top-level content blocks placed so far in this pass, and how many * there are in the document. */ blocks: number; totalBlocks: number; /** Pages opened so far in this pass. */ pages: number; } export declare class BuildCancelledError extends Error { constructor(); } /** Cross-pass hints a placement pass consumes. All keyed by content-block * index; every map is optional so the plain first pass carries none. */ export interface PassHints { /** Column balancing: extra top spacing (px) per heading / list-end target. */ balanceExtraPx?: ReadonlyMap; /** Column balancing: K-P looseness per paragraph re-broken one line longer. */ balanceLooseness?: ReadonlyMap; /** Column balancing: shared budget of the loose candidates offered together * (the pass stops loosening a column once it gained what it needs). */ balanceLooseBudget?: ReadonlyMap; /** Band caps keyed by the span block's content index (see `bandCaps.ts`). */ bandCaps?: ReadonlyMap; /** Figures (resource ids) whose side caption (`placement.captionSide`) * goes under the figure instead: an earlier pass found the side column * too short for a side box or side float once the caption had taken its * foot, and the box spilled over the caption. */ captionUnder?: ReadonlySet; /** `footnotes.numbering: 'page'` / `'column'`: the number each note got * where the previous build set it (see `numberFootnotesByPlacement`). */ footnoteNumbers?: ReadonlyMap; /** Trailing-cap passes: the page each floated resource took in the layout * the caps level (see `proposeTrailingCap`). */ floatPages?: ReadonlyMap; /** Floats (resource ids) that head the page or column their citing line * lands on (`placement.citingPage`, #633): an earlier pass found the line * there and the float on a later page or column. The page is opened * with the float at its head, before any text. */ citingPageFloats?: ReadonlyMap; } /** Where a float set at the head of its citing page goes (#633): the page * and the band-0 text column its citing line landed in. */ export interface CitingPageSlot { pageIndex: number; columnIndex: number; } export interface PassResult extends BandPassReport { doc: VDTDocument; /** Pages whose break into the next page was explicit (`:::pagebreak`, * heading `breakBefore`, chapter opener) rather than natural content * overflow — those pages keep their short last column. */ forcedBreakPages: Set; bandCapProposals: Map; spanPlacedInBand: Set; bandCapsApplied: Set; /** Column balancing: per loose paragraph tried in this pass, the tracking * (thousandths of an em) that gained its extra line — `null` when no rung * of the ladder did, so the driver can blacklist it. Candidates left * untried because their column's budget was already met are absent. */ looseOutcome: Map; /** Column balancing on a character grid (#632): the loose paragraphs of * this pass that would have gained their line only off the grid. */ looseOffGrid: Set; /** Figures whose side caption this pass found in the way of a side box or * side float that had to overflow the side column: candidates for * `PassHints.captionUnder` in the next pass. */ captionUnderProposals: Set; /** Floats that may head the page or column their citing line landed on * in this pass (`placement.citingPage`, #633) and landed later: * candidates for `PassHints.citingPageFloats`. */ citingPageProposals: Map; /** Floats of `PassHints.citingPageFloats` this pass could not keep at the * head of their citing page: not set there (it did not fit, an earlier * float of its sequence was still waiting, the page opened at a break), * or set there and the text it pushed down took the citing line to * another page or column. With the reason, for the record. */ citingPageRefused: Map; } /** Why a float was not kept at the head of its citing page (#633). */ export type CitingPageRefusal = 'notSet' | 'citationMoved'; /** * Single placement pass. `hints` carries the cross-pass adjustments: the * column-balancing spacing / looseness and the band caps of page-span * blocks. Besides the document it reports `forcedBreakPages` (for * balancing) and the band-cap bookkeeping the driver in `buildDocument` * needs — new cap proposals, the span blocks that landed in their capped * band, and the caps that were actually applied. * * @internal Exposed for tests only; use `buildDocument`. */ export declare function buildDocumentPass(content: PostextContent, config?: PostextConfig, cache?: MeasurementCache, options?: BuildDocumentOptions, hints?: PassHints): PassResult; export declare function buildDocument(content: PostextContent, config?: PostextConfig, cache?: MeasurementCache, options?: BuildDocumentOptions): VDTDocument; /** Let the event loop turn: `scheduler.yield()` where it exists, else a * message-channel hop (a `setTimeout(0)` is clamped to 4 ms once nested). */ export declare function yieldToEventLoop(): Promise; /** * {@link buildDocument}, yielding to the event loop between placement * passes. A build is several passes (band caps, column balancing, contents * rounds), each a synchronous re-placement of the document; in a worker * this lets a `cancel` posted mid-build be observed at the next pass * boundary — `shouldCancel` is polled there as well as inside a pass — * instead of after the whole build. */ export declare function buildDocumentAsync(content: PostextContent, config?: PostextConfig, cache?: MeasurementCache, options?: BuildDocumentOptions & { yieldBetweenPasses?: () => Promise; }): Promise; /** The build as a generator: one `yield` after every placement pass. */ export declare function buildDocumentGen(content: PostextContent, config?: PostextConfig, cache?: MeasurementCache, options?: BuildDocumentOptions): Generator; /** * Link the stories that jump from one chapter to a page of another (#943) * and write the page numbers into their continuation marks. `docs` is the * book laid out, one document per chapter, in the order of the book (a * story's `chapter` is its position in it): the sending frame gets the * frame that took the rest (`continuesTo`, its `continued` event the page * and frame there), and every mark naming a page of another chapter * prints that page's label as its chapter numbered it. Marks within a * chapter were filled by its own build. Safe to run again on the same * documents. */ export declare function resolveJumpMarks(docs: readonly VDTDocument[]): void; //# sourceMappingURL=build.d.ts.map