Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | 8x 39x 39x 39x 39x 39x 39x 39x 39x 39x 39x 39x 39x 39x 39x 5x 28x 39x 2x | /**
* UIF Analyzer
*
* Extracts component metadata from resolved UIFs for code generation.
* Uses extraction utilities from @fds-uif/core.
*/
import type { ResolvedUIF } from '@fds-uif/schema';
import {
validateResolved,
UifResolvedValidationError,
getStates,
getModifiers,
getVariants,
getSlots,
getBoundAttributes,
getStateClasses,
} from '@fds-uif/core/browser';
import type { ComponentMetadata, AnalyzerOptions } from '../types/index.js';
import { buildProps } from './props.js';
import { analyzeStructure } from './structure.js';
import { buildClassNameRules } from './classNames.js';
import { detectDependencies } from './dependencies.js';
const DEFAULT_ELEMENT = 'div';
/**
* Error thrown during UIF analysis
*/
export class UifAnalyzerError extends Error {
constructor(
message: string,
public readonly componentName?: string,
public readonly details?: Record<string, unknown>,
) {
super(message);
this.name = 'UifAnalyzerError';
}
}
/**
* Analyze a resolved UIF and extract component metadata
*
* @param uif - Resolved UIF (with $extends already merged)
* @param options - Analyzer options
* @returns Component metadata for code generation
*/
export function analyzeUif(uif: ResolvedUIF | unknown, options: AnalyzerOptions = {}): ComponentMetadata {
const { defaultElement = DEFAULT_ELEMENT, inferDescriptions = false, validate = true } = options;
// Validate before analysis
if (validate) {
const validation = validateResolved(uif);
if (!validation.valid) {
const messages = validation.errors?.map((e) => `${e.path}: ${e.message}`).join('; ');
throw new UifResolvedValidationError(`Invalid UIF: ${messages}`, validation.errors);
}
}
const resolvedUif = uif as ResolvedUIF;
try {
// Use schema extraction utilities
const states = getStates(resolvedUif);
const modifiers = getModifiers(resolvedUif);
const variants = getVariants(resolvedUif);
const slots = getSlots(resolvedUif);
const boundAttrs = getBoundAttributes(resolvedUif);
const stateClasses = getStateClasses(resolvedUif);
// Build props from extracted data
const props = buildProps(states, modifiers, variants, slots, boundAttrs, inferDescriptions);
// Analyze structure for rendering
const structure = analyzeStructure(resolvedUif.structure, defaultElement);
// Build class name rules
const classNames = buildClassNameRules(resolvedUif, modifiers, stateClasses);
// Detect dependencies
const dependencies = detectDependencies(resolvedUif.structure, defaultElement);
const metadata: ComponentMetadata = {
name: resolvedUif.name,
description: resolvedUif.description,
props,
structure,
classNames,
dependencies,
};
if (resolvedUif.accessibility) {
metadata.accessibility = {
role: resolvedUif.accessibility.role,
ariaProps: props.filter((p) => p.name.startsWith('aria')).map((p) => p.name),
landmarks: resolvedUif.accessibility.landmarks,
};
}
if (resolvedUif.behavior) {
metadata.behavior = resolvedUif.behavior;
}
return metadata;
} catch (error) {
if (error instanceof UifAnalyzerError) throw error;
if (error instanceof UifResolvedValidationError) throw error;
throw new UifAnalyzerError(
`Failed to analyze UIF: ${error instanceof Error ? error.message : String(error)}`,
resolvedUif.name,
);
}
}
/**
* Analyze multiple UIFs
*/
export function analyzeMultipleUifs(uifs: ResolvedUIF[], options: AnalyzerOptions = {}): ComponentMetadata[] {
return uifs.map((uif) => analyzeUif(uif, options));
}
// Re-export sub-modules for advanced usage
export { buildProps } from './props.js';
export { analyzeStructure, extractComponentPropsMetadata } from './structure.js';
export { buildClassNameRules } from './classNames.js';
export { detectDependencies } from './dependencies.js';
|