Warning
This is an internal project, and is not intended for public use. No support or stability guarantees are provided.
The hastUtils module provides utilities for converting between HAST (Hypertext Abstract Syntax Tree) nodes, strings, and React JSX elements. These utilities are essential for processing syntax-highlighted code and converting markdown/HTML structures to React components.
hastCompressed format)import {
hastToJsx,
hastOrJsonToJsx,
stringOrHastToString,
stringOrHastToJsx,
} from '@mui/internal-docs-infra/pipeline/hastUtils';
// Convert HAST to React JSX
const jsxElement = hastToJsx(hastNode);
// Convert HAST or serialized JSON to JSX
const jsxFromJson = hastOrJsonToJsx({ hastJson: '{"type":"element",...}' });
// Extract plain text from string or HAST
const plainText = stringOrHastToString(hastNodeOrString);
// Convert to JSX with optional highlighting
const jsx = stringOrHastToJsx(hastNodeOrString, true);
The module also implements the hastCompressed serialization format — the
mechanism behind the small precomputed payloads that CodeHighlighter ships
(the output: 'hastCompressed' option of the
loaders):
import { compressHast, decompressHast } from '@mui/internal-docs-infra/pipeline/hastUtils';
const compressed = compressHast(JSON.stringify(hastRoot), plainText); // base64
const json = decompressHast(compressed, plainText);
JSON-serialized HAST is extremely repetitive — and its text nodes repeat the code's plain text, which the page has already shipped as the loading fallback. The compressor exploits both:
buildDictionary(textContent) prepends the block's plain text to a
static ~3 KB dictionary (HAST_DICTIONARY) of byte sequences common in
highlighted HAST JSON ({"type":"element","tagName":"span",...). DEFLATE
back-references can then point into the dictionary instead of repeating the
bytes, so a highlighted tree compresses to a fraction of its size — the
fallback the page already rendered does double duty as the dictionary.compressHast(json, textContent) deflates at maximum level with that
dictionary and embeds a 4-byte checksum (CHECKSUM_BYTES) of the dictionary
in the payload.decompressHast(base64, textContent) rebuilds the same dictionary on the
client and verifies the checksum first — if the supplied textContent
differs from the one used at compression time, it throws
HastDictionaryMismatchError instead of silently producing corrupt output.Omitting textContent uses only the static dictionary and skips the checksum.
Both directions have async variants (compressHastAsync /
decompressHastAsync) that keep large payloads off the main thread, and
string-payload equivalents (compressString / decompressString and their
async forms) for non-HAST content. The maximum dictionary window is
MAX_DICTIONARY_SIZE (32 KiB — DEFLATE only reads the last 32 KiB).
Warning
The static
HAST_DICTIONARYis embedded in both the server build and the client bundle and must stay byte-compatible across them: entries are prepend-only (DEFLATE back-references reach into the dictionary from its end, so the existing tail must stay byte-identical for older payloads to decode). The checksum turns any drift on the text path into a loudHastDictionaryMismatchErrorrather than silent corruption.
Two related helpers support the fallback pipeline: stripHighlightingSpans
removes highlighting spans from a tree (producing the plain-text-equivalent
structure fallbacks are built from), and frameFallbackFromSpans converts a
list of spans into the compact frame-based fallback format.
hastOrJsonToJsx| Parameter | Type | Description |
|---|---|---|
| hastOrJson | | |
| components | | |
| fallback | |
React.ReactNodehastToJsx| Parameter | Type | Description |
|---|---|---|
| hast | | |
| components | |
React.ReactNodestringOrHastToJsx| Parameter | Type | Description |
|---|---|---|
| source | | |
| highlighted | | |
| components | | |
| fallback | |
React.ReactNodestringOrHastToString| Parameter | Type | Description |
|---|---|---|
| source | | |
| fallback | |
stringChecksum byte length embedded in compressed payloads that use a text
dictionary. The checksum lets decompressHast verify that the caller
supplied the same textContent that was used during compression.
type CHECKSUM_BYTES = 4Shared dictionary for DEFLATE compression of HAST JSON.
Contains byte sequences that frequently appear in JSON-serialized HAST trees (syntax-highlighted TypeScript type documentation). The dictionary is embedded in both the server build and the client bundle, so it must stay small — currently ~3 KB uncompressed.
type HAST_DICTIONARY = Uint8ArrayMaximum size of the DEFLATE dictionary in bytes.
DEFLATE uses only the last 32 KiB of the dictionary buffer. Any content beyond this limit is ignored by the compressor.
type MAX_DICTIONARY_SIZE = numberCodeHighlighter