Skip to content

Commit

Permalink
[docs-infra] Change CSS vars generation to be extracted from Enum (#4…
Browse files Browse the repository at this point in the history
  • Loading branch information
mnajdova authored Dec 3, 2024
1 parent 4b80171 commit ea60388
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 4 deletions.
12 changes: 8 additions & 4 deletions packages/api-docs-builder/ApiBuilders/ComponentApiBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
ParsedProperty,
} from '../types/ApiBuilder.types';
import { Slot, ComponentInfo } from '../types/utils.types';
import extractInfoFromType from '../utils/extractInfoFromType';
import extractInfoFromEnum from '../utils/extractInfoFromEnum';

const cssComponents = ['Box', 'Grid', 'Typography', 'Stack'];

Expand Down Expand Up @@ -645,10 +645,10 @@ const attachCssVariables = (reactApi: ComponentReactApi, params: ParsedProperty[
const deprecation = deprecationTag?.text?.[0]?.text;

const typeTag = propDescriptor.tags?.type;
const type = typeTag?.text?.[0]?.text ?? 'string';
const type = (typeTag?.text?.[0]?.text ?? 'string').replace(/{|}/g, '');

return {
name: `--${kebabCase(propName)}`,
name: propName,
description: propDescriptor.description,
type,
deprecated: !!deprecation || undefined,
Expand Down Expand Up @@ -820,7 +820,11 @@ export default async function generateComponentApi(

reactApi.deprecated = !!deprecation || undefined;

const cssVars = await extractInfoFromType(`${componentInfo.name}CssVars`, project);
const cssVars = await extractInfoFromEnum(
`${componentInfo.name}CssVars`,
new RegExp(`${componentInfo.name}(CssVars|Classes)?.tsx?$`, 'i'),
project,
);

attachPropsTable(reactApi, projectSettings.propsSettings);
attachCssVariables(reactApi, cssVars);
Expand Down
71 changes: 71 additions & 0 deletions packages/api-docs-builder/utils/extractInfoFromEnum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { Symbol, isPropertySignature, isEnumDeclaration, forEachChild, Node } from 'typescript';
import { TypeScriptProject } from './createTypeScriptProject';
import { ParsedProperty } from '../types/ApiBuilder.types';
import { getSymbolDescription, getSymbolJSDocTags, stringifySymbol } from '../buildApiUtils';

const parseProperty = async (
propertySymbol: Symbol,
project: TypeScriptProject,
name: string,
): Promise<ParsedProperty> => ({
name,
description: getSymbolDescription(propertySymbol, project),
tags: getSymbolJSDocTags(propertySymbol),
required: !propertySymbol.declarations?.find(isPropertySignature)?.questionToken,
typeStr: await stringifySymbol(propertySymbol, project),
});

const extractInfoFromEnum = async (
typeName: string,
sourceFileNamePattern: RegExp,
project: TypeScriptProject,
): Promise<ParsedProperty[]> => {
// Generate the params
let result: ParsedProperty[] = [];

try {
const cssVarDeclarationCandidates = project.program
.getSourceFiles()
.filter((file) => sourceFileNamePattern.test(file.fileName));

let enumSymbol: Symbol | null = null;
cssVarDeclarationCandidates.forEach((file) => {
forEachChild(file, (node: Node) => {
if (isEnumDeclaration(node) && node.name.getText() === typeName) {
enumSymbol = project.checker.getSymbolAtLocation(node.name)!;
}
});
});

if (!enumSymbol) {
return [];
}

const type = project.checker.getDeclaredTypeOfSymbol(enumSymbol!);

// @ts-ignore
const typeDeclaration = type?.types ?? [type];
if (!typeDeclaration) {
return [];
}
const properties: Record<string, ParsedProperty> = {};

// @ts-ignore
await Promise.all(
typeDeclaration.map(async (t: any) => {
const propertySymbol = t.symbol;
properties[t.value] = await parseProperty(propertySymbol, project, t.value);
}),
);

result = Object.values(properties)
.filter((property) => !property.tags.ignore)
.sort((a, b) => a.name.localeCompare(b.name));
} catch {
console.error(`No declaration for ${typeName}`);
}

return result;
};

export default extractInfoFromEnum;

0 comments on commit ea60388

Please sign in to comment.