@mui/internal-docs-infra
Version:
MUI Infra - internal documentation creation tools.
108 lines • 5.06 kB
TypeScript
import { Code, VariantExtraFiles, VariantSource } from "./types.js";
/**
* Type guard function that determines if we have sufficient data to render a code highlighter
* component immediately, or if we need to start loading data first.
*
* This function acts as a validation layer to ensure we have the minimal required data
* to render either a fallback state or the actual code content, helping to prevent
* rendering errors and provide better user experience.
*
* ## Usage Contexts
*
* This function is used in two main scenarios:
*
* 1. **Server-side rendering (CodeHighlighter)**: Determines if we can render with initial
* source content immediately, or if we need to load fallback data via `CodeInitialSourceLoader`
*
* 2. **Client-side hydration (CodeHighlighterClient)**: Within `useInitialData` hook to determine
* if we should trigger loading effects or if we can render with available data
*
* ## Decision Flow
*
* The function checks data availability in this order:
* 1. Code object exists and contains the requested variant
* 2. All required variants are available (if `needsAllVariants` is true)
* 3. Requested file exists (main file or in extraFiles)
* 4. All extra files are loaded (if `needsAllFiles` is true)
* 5. Source content is properly highlighted (if `needsHighlight` is true)
*
* ## Synchronous vs Asynchronous Behavior
*
* This function operates **synchronously** and only validates existing data - it never triggers
* any loading operations. This design is crucial for performance and rendering strategies:
*
* - **Synchronous validation** allows immediate decisions about rendering paths without async overhead
* - **Enables build-time optimization**: When code is precomputed (e.g., via build-time processing),
* this function can immediately return `initialData`, avoiding async components entirely
* - **Separates concerns**: Data validation is separate from data loading, making the codebase
* more predictable and easier to reason about
*
* When `initialData: false` is returned, the calling component is responsible for initiating
* asynchronous loading operations (e.g., `loadFallbackCode`, `CodeInitialSourceLoader`).
*
* @param variants - Array of all available variant names for this code block (e.g., ['javascript', 'typescript'])
* @param variant - The specific variant we want to display (must exist in variants array)
* @param code - The code object containing all variant data (may be undefined if not loaded)
* @param fileName - Optional specific file to display. Resolution logic:
* - When it matches `variantCode.fileName`, uses the main variant source
* - When it doesn't match, looks for the file in `variantCode.extraFiles`
* - When undefined, defaults to the main file of the variant
* @param needsHighlight - Whether the code needs to be syntax highlighted (source must be highlighted object, not string)
* @param needsAllFiles - Whether all extra files must be loaded before rendering (checks that all extraFiles have source content)
* @param needsAllVariants - Whether all variants must be available before rendering (validates using hasAllVariants)
*
* @returns Object with either:
* - `initialData: false` with a `reason` string explaining why data is insufficient for rendering
* - `initialData: object` containing the validated data ready for immediate rendering, including:
* - `code`: The full code object
* - `initialFilename`: The resolved filename (may be undefined if variant has no fileName)
* - `initialSource`: The source content for the requested file
* - `initialExtraFiles`: Extra files associated with the variant (if any)
*
* @example
* ```typescript
* // Server-side: Check if we can render with initial source or need to load fallback
* const { initialData, reason } = maybeInitialData(
* variants,
* initialKey,
* code || props.precompute,
* undefined,
* highlightAfter === 'init',
* props.fallbackUsesExtraFiles,
* props.fallbackUsesAllVariants,
* );
*
* if (!initialData) {
* // Need to load fallback data
* return <CodeInitialSourceLoader {...props} />;
* }
*
* // Client-side: Check if we need to trigger loading effects
* const { initialData, reason } = React.useMemo(() =>
* maybeInitialData(
* variants,
* variantName,
* code,
* fileName,
* highlightAfter === 'init',
* fallbackUsesExtraFiles,
* fallbackUsesAllVariants,
* ), [dependencies]);
*
* React.useEffect(() => {
* if (initialData || isControlled) {
* return; // No loading needed
* }
* // Trigger loadFallbackCode...
* }, [initialData, reason, ...]);
* ```
*/
export declare function maybeInitialData(variants: string[], variant: string, code?: Code, fileName?: string, needsHighlight?: boolean, needsAllFiles?: boolean, needsAllVariants?: boolean): {
initialData: false | {
code: Code;
initialFilename: string | undefined;
initialSource: VariantSource;
initialExtraFiles?: VariantExtraFiles;
};
reason?: string;
};