@mui/internal-docs-infra
Version:
MUI Infra - internal documentation creation tools.
137 lines • 7.61 kB
text/typescript
import type { Root as HastRoot } from 'hast';
/**
* Compact serialization format for fallback HAST trees.
*
* A `FallbackNode` is either:
* - a plain string (text node), or
* - a variable-length tuple whose meaning is determined by length:
* - `[tagName, children]` – no class, no props
* - `[tagName, className, children]` – has class, no props
* - `[tagName, className, properties, children]` – has class and props
* - `[tagName, className, properties, children, extra]` – full
*
* Where:
* - `tagName` – HTML element name (e.g. `'span'`, `'a'`)
* - `className` – space-joined class string
* - `properties` – remaining HTML properties (without `className`)
* - `children` – a single text string **or** an array of child `FallbackNode`s
* - `extra` – optional bag for anything else (data attributes, etc.)
*
* This eliminates the repeated `type`, `tagName`, `properties`, `children`,
* and `value` keys that make raw HAST costly in RSC payloads.
*/
export type FallbackNode = string | FallbackElement;
/**
* A residual fallback that has been DEFLATE-compressed on its own. Mirrors the
* `{ hastCompressed }` shape of `VariantSource`.
*
* Used for the parts of a variant's fallback that the `ContentLoading`
* component never renders (extra files when the loading UI shows a single file,
* extra variants when it shows a single variant). Those residual fallbacks
* exist only as the DEFLATE dictionary for decompressing `hastCompressed`, so
* shipping them as plain `FallbackNode[]` text would be dead weight in the
* initial payload. They are compressed standalone — no preset text dictionary,
* so the blob is self-contained — and decompressed back to `FallbackNode[]`
* (via `decompressFallback`) only when the full content swaps in.
*/
export type CompressedFallback = {
fallbackCompressed: string;
};
export type FallbackElement = [tagName: string, children: string | FallbackNode[]] | [tagName: string, className: string, children: string | FallbackNode[]] | [tagName: string, className: string, properties: Record<string, unknown>, children: string | FallbackNode[]] | [tagName: string, className: string, properties: Record<string, unknown>, children: string | FallbackNode[], extra: Record<string, unknown>];
/**
* Convert a HAST root into the compact `FallbackNode[]` format.
*/
export declare function hastToFallback(root: HastRoot): FallbackNode[];
/**
* Convert the compact `FallbackNode[]` format back into a HAST root.
*/
export declare function fallbackToHast(nodes: FallbackNode[]): HastRoot;
/**
* Extract the text content from compact `FallbackNode[]` without
* converting back to HAST. Used to build DEFLATE dictionaries.
*/
export declare function fallbackToText(nodes: FallbackNode[]): string;
/**
* Builds the variant-level root fallback from a final (post-enhancer) HAST
* root. Each `span.frame` becomes a compact frame element whose single text
* child is the frame's precomputed plain text (`frame.data.fallback`), so the
* result is directly renderable as the pre-hydration code block **and** can be
* redistributed back onto the decoded HAST's frames (see
* `redistributeRootFallback`).
*
* The frame's `data-lined` attribute is dropped (line spans don't exist in the
* fallback) while other frame attributes (e.g. `data-frame-type`) are kept so
* the fallback's layout matches the highlighted render. Non-frame top-level
* nodes (e.g. whitespace text between frames) are preserved in place.
*/
export declare function buildRootFallback(root: HastRoot): FallbackNode[];
/**
* Whether a compact `fallback` already carries highlighting — i.e. at least one frame
* keeps nested token spans (array children) instead of flat plain text. True exactly for
* the promoted {@link promoteCriticalFallback} form; a plain {@link buildRootFallback} has
* a string child on every frame. `<Pre>` uses this to defer the decompressing decode ONLY
* when the first paint is already highlighted, so it never flashes plain → highlighted.
*/
export declare function fallbackIsHighlighted(fallback: FallbackNode[]): boolean;
/**
* The **sparse** highlighted-visible fallback: a map from frame index to the
* highlighted `FallbackNode` for ONLY the frames visible on the initial collapsed
* render (`visibleFrames`). Off-screen frames are omitted — they flatten to exactly
* {@link buildRootFallback}'s plain output, so storing them would just duplicate
* `fallback` in the precompute. {@link promoteCriticalFallback} splices these back
* over the plain fallback for `highlightAt: 'init'` (paint highlighted on the first
* render, zero decompression). Frame indices count `span.frame` children only,
* matching `getInitialVisibleFrames`.
*
* The decoded `root` is shared/read-only; this only reads its frames (the synthetic
* visible frame reuses the frame's `children` array without mutating it, and
* `data-lined` is dropped via destructuring, not deletion).
*/
export declare function buildCriticalFallback(root: HastRoot, visibleFrames: {
[key: number]: boolean;
}): {
[frameIndex: number]: FallbackNode;
};
/**
* Splice a sparse {@link buildCriticalFallback} diff back onto a plain `fallback`,
* replacing each visible frame (matched by index in document order) with its
* highlighted node. The result is the full highlighted-visible fallback; its text is
* byte-identical to `fallback` (the highlight spans only wrap the same characters), so
* it stays a valid DEFLATE dictionary — asserted by tests. Returns a new array; the
* input is not mutated.
*/
export declare function promoteCriticalFallback(fallback: FallbackNode[], critical: {
[frameIndex: number]: FallbackNode;
}): FallbackNode[];
/**
* Redistributes a root fallback (built by `buildRootFallback`) back onto the
* frames of a decoded HAST root, setting each frame's `data.fallback` to the
* corresponding fallback frame's text nodes (as HAST, not the compact form).
*
* Frames align 1:1 by position because the root fallback and the decoded HAST
* are both derived from the same final tree. Non-frame fallback entries (e.g.
* inter-frame whitespace) advance the cursor without being assigned. Mutates
* `root` in place and returns it.
*/
export declare function redistributeRootFallback(root: HastRoot, fallback: FallbackNode[]): HastRoot;
/**
* Reduce a root fallback to the frames visible while the code block is
* collapsed — the contiguous focused window (`padding-top`, `highlighted` /
* `focus`, `padding-bottom`). Inter-frame nodes inside that window are kept so
* the slice renders with the same spacing as the full fallback.
*
* Matches the runtime rule in `Pre.tsx`: when a block has no emphasis frames
* (the whole source is the focused window) the first frame stands in. Returns
* the input unchanged when it has no frames at all.
*
* When `collapsesToEmpty` is `true` the source records `focusedLines === 0`
* (the `oversizedFocus: 'hide'` collapse-to-nothing case): the collapsed window
* is intentionally empty, so the first-frame fallback is skipped and an empty
* array is returned. Mirrors the runtime rule in `Pre.tsx` /
* `getInitialVisibleSourceLines`.
*
* Used by `fallbackCollapsed` to paint only the on-screen lines while the
* file's full fallback rides along compressed (see the prop-compression
* pattern's "Splitting the Fallback by Visibility").
*/
export declare function collapsedVisibleFallback(fallback: FallbackNode[], collapsesToEmpty?: boolean): FallbackNode[];