diff --git a/packages/frontend/.storybook/generate.tsx b/packages/frontend/.storybook/generate.tsx index 60f7d26d7b..49304602d8 100644 --- a/packages/frontend/.storybook/generate.tsx +++ b/packages/frontend/.storybook/generate.tsx @@ -32,14 +32,18 @@ const generator = { state.write(' satisfies ', node as unknown as estree.Expression); this[node.reference.type](node.reference, state); }, -} +}; -type SplitCamel = T extends `${infer XH}${infer XR}` +type SplitCamel< + T extends string, + YC extends string = '', + YN extends readonly string[] = [] +> = T extends `${infer XH}${infer XR}` ? XR extends '' ? [...YN, Uncapitalize<`${YC}${XH}`>] : XH extends Uppercase - ? SplitCamel, [...YN, YC]> - : SplitCamel + ? SplitCamel, [...YN, YC]> + : SplitCamel : YN; // @ts-ignore @@ -47,25 +51,36 @@ type SplitKebab = T extends `${infer XH}-${infer XR}` ? [XH, ...SplitKebab] : [T]; -type ToKebab = T extends readonly [infer XO extends string] +type ToKebab = T extends readonly [ + infer XO extends string +] ? XO - : T extends readonly [infer XH extends string, ...infer XR extends readonly string[]] - ? `${XH}${XR extends readonly string[] ? `-${ToKebab}` : ''}` - : ''; + : T extends readonly [ + infer XH extends string, + ...infer XR extends readonly string[] + ] + ? `${XH}${XR extends readonly string[] ? `-${ToKebab}` : ''}` + : ''; // @ts-ignore -type ToPascal = T extends readonly [infer XH extends string, ...infer XR extends readonly string[]] +type ToPascal = T extends readonly [ + infer XH extends string, + ...infer XR extends readonly string[] +] ? `${Capitalize}${ToPascal}` : ''; -function h(component: T['type'], props: Omit): T { +function h( + component: T['type'], + props: Omit +): T { const type = component.replace(/(?:^|-)([a-z])/g, (_, c) => c.toUpperCase()); return Object.assign(props, { type }) as T; } declare global { namespace JSX { - type Element = never; + type Element = estree.Node; type ElementClass = never; type ElementAttributesProperty = never; type ElementChildrenAttribute = never; @@ -73,7 +88,10 @@ declare global { type IntrinsicClassAttributes = never; type IntrinsicElements = { [T in keyof typeof generator as ToKebab>>]: { - [K in keyof Omit[0], 'type'>]?: Parameters[0][K]; + [K in keyof Omit< + Parameters<(typeof generator)[T]>[0], + 'type' + >]?: Parameters<(typeof generator)[T]>[0][K]; }; }; } @@ -88,217 +106,391 @@ function toStories(component: string): string { const dir = dirname(component); const literal = ( - ) as unknown as estree.Literal; + ) as estree.Literal; const identifier = ( - - ) as unknown as estree.Identifier; + + ) as estree.Identifier; const parameters = ( } - value={} - kind={'init' as const} - />, - ...hasMsw + ( + ) as estree.Identifier} + value={ + ( + + ) as estree.Literal + } + kind={'init' as const} + /> + ) as estree.Property, + ...(hasMsw ? [ - } - value={} - kind={'init' as const} - shorthand - />, - ] - : [], + ( + ) as estree.Identifier} + value={() as estree.Identifier} + kind={'init' as const} + shorthand + /> + ) as estree.Property, + ] + : []), ]} /> - ); + ) as estree.ObjectExpression; const program = ( } - specifiers={[ - } - imported={} - />, - ...hasImplStories - ? [] - : [ - } - imported={} - />, - ], - ]} - />, - ...hasMsw + ( + ) as estree.Literal} + specifiers={[ + ( + ) as estree.Identifier} + imported={() as estree.Identifier} + /> + ) as estree.ImportSpecifier, + ...(hasImplStories + ? [] + : [ + ( + ) as estree.Identifier + } + imported={ + () as estree.Identifier + } + /> + ) as estree.ImportSpecifier, + ]), + ]} + /> + ) as estree.ImportDeclaration, + ...(hasMsw ? [ - } - specifiers={[ - } - />, - ]} - />, - ] - : [], - ...hasImplStories + ( + ) as estree.Literal + } + specifiers={[ + ( + ) as estree.Identifier} + /> + ) as estree.ImportNamespaceSpecifier, + ]} + /> + ) as estree.ImportDeclaration, + ] + : []), + ...(hasImplStories ? [] : [ - } - specifiers={[ - , - ]} - />, - ], - } - init={ - } - value={literal} - kind={'init' as const} - />, - } - value={identifier} - kind={'init' as const} - />, - ]} - /> - } - reference={`} />} + ( + ) as estree.Literal} + specifiers={[ + ( + + ) as estree.ImportDefaultSpecifier, + ]} /> - } - />, - ]} - />, - ...hasImplStories - ? [ - ] - : [ - } - init={ - ) as estree.Identifier} + init={ + ( + } - value={ - , - } - value={} - kind={'init' as const} - shorthand - />, - ]} - />, - ]} - body={ - } - value={ - , - ]} - /> - } - kind={'init' as const} - />, - } - value={ - } - property={} - /> - } - arguments={[ - , - ]} - /> - } - kind={'init' as const} - />, - } - value={`} />} - kind={'init' as const} - />, - ]} - /> - } - />, - ]} - /> - } - /> + key={ + ( + + ) as estree.Identifier } - method + value={literal} kind={'init' as const} - />, + /> + ) as estree.Property, + ( } - value={parameters} + key={ + ( + + ) as estree.Identifier + } + value={identifier} kind={'init' as const} - />, - ]} - /> - } - reference={`} />} - /> + /> + ) as estree.Property, + ]} + /> + ) as estree.ObjectExpression } - />, - ]} - /> - } - />, - ], - } - />, + reference={ + ( + `} + /> + ) as estree.Identifier + } + /> + ) as estree.Expression + } + /> + ) as estree.VariableDeclarator, + ]} + /> + ) as estree.VariableDeclaration, + ...(hasImplStories + ? [] + : [ + ( + + ) as estree.Identifier + } + init={ + ( + + ) as estree.Identifier + } + value={ + ( + + ) as estree.Identifier, + ( + + ) as estree.Identifier + } + value={ + ( + + ) as estree.Identifier + } + kind={ + 'init' as const + } + shorthand + /> + ) as estree.AssignmentProperty, + ]} + /> + ) as estree.ObjectPattern, + ]} + body={ + ( + + ) as estree.Identifier + } + value={ + ( + + ) as estree.Property, + ]} + /> + ) as estree.ObjectExpression + } + kind={ + 'init' as const + } + /> + ) as estree.Property, + ( + + ) as estree.Identifier + } + value={ + ( + + ) as estree.Identifier + } + property={ + ( + + ) as estree.Identifier + } + /> + ) as estree.MemberExpression + } + arguments={[ + ( + + ) as estree.Identifier, + ]} + /> + ) as estree.CallExpression + } + kind={ + 'init' as const + } + /> + ) as estree.Property, + ( + + ) as estree.Identifier + } + value={ + ( + `} + /> + ) as estree.Literal + } + kind={ + 'init' as const + } + /> + ) as estree.Property, + ]} + /> + ) as estree.ObjectExpression + } + /> + ) as estree.ReturnStatement, + ]} + /> + ) as estree.BlockStatement + } + /> + ) as estree.FunctionExpression + } + method + kind={'init' as const} + /> + ) as estree.Property, + ( + + ) as estree.Identifier + } + value={parameters} + kind={'init' as const} + /> + ) as estree.Property, + ]} + /> + ) as estree.ObjectExpression + } + reference={ + ( + `} + /> + ) as estree.Identifier + } + /> + ) as estree.Expression + } + /> + ) as estree.VariableDeclarator, + ]} + /> + ) as estree.VariableDeclaration + } + /> + ) as estree.ExportNamedDeclaration, + ]), + ( + ) as estree.Identifier} + /> + ) as estree.ExportDefaultDeclaration, ]} /> - ) as unknown as estree.Program; + ) as estree.Program; return format( '/* eslint-disable @typescript-eslint/explicit-function-return-type */\n' + '/* eslint-disable import/no-default-export */\n' + @@ -312,9 +504,12 @@ function toStories(component: string): string { ); } -promisify(glob)('src/{components,pages,ui,widgets}/**/*.vue').then((components) => Promise.all( - components.map((component) => { - const stories = component.replace(/\.vue$/, '.stories.ts'); - return writeFile(stories, toStories(component)); - }) -)); +promisify(glob)('src/{components,pages,ui,widgets}/**/*.vue').then( + (components) => + Promise.all( + components.map((component) => { + const stories = component.replace(/\.vue$/, '.stories.ts'); + return writeFile(stories, toStories(component)); + }) + ) +);