style: typing
This commit is contained in:
parent
1d0ca7eecf
commit
bf5fff879f
1 changed files with 402 additions and 207 deletions
|
@ -32,9 +32,13 @@ const generator = {
|
|||
state.write(' satisfies ', node as unknown as estree.Expression);
|
||||
this[node.reference.type](node.reference, state);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
type SplitCamel<T extends string, YC extends string = '', YN extends readonly string[] = []> = 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<XH>
|
||||
|
@ -47,25 +51,36 @@ type SplitKebab<T extends string> = T extends `${infer XH}-${infer XR}`
|
|||
? [XH, ...SplitKebab<XR>]
|
||||
: [T];
|
||||
|
||||
type ToKebab<T extends readonly string[]> = T extends readonly [infer XO extends string]
|
||||
type ToKebab<T extends readonly string[]> = T extends readonly [
|
||||
infer XO extends string
|
||||
]
|
||||
? XO
|
||||
: T extends readonly [infer XH extends string, ...infer XR extends readonly string[]]
|
||||
: T extends readonly [
|
||||
infer XH extends string,
|
||||
...infer XR extends readonly string[]
|
||||
]
|
||||
? `${XH}${XR extends readonly string[] ? `-${ToKebab<XR>}` : ''}`
|
||||
: '';
|
||||
|
||||
// @ts-ignore
|
||||
type ToPascal<T extends readonly string[]> = T extends readonly [infer XH extends string, ...infer XR extends readonly string[]]
|
||||
type ToPascal<T extends readonly string[]> = T extends readonly [
|
||||
infer XH extends string,
|
||||
...infer XR extends readonly string[]
|
||||
]
|
||||
? `${Capitalize<XH>}${ToPascal<XR>}`
|
||||
: '';
|
||||
|
||||
function h<T extends estree.Node>(component: T['type'], props: Omit<T, 'type'>): T {
|
||||
function h<T extends estree.Node>(
|
||||
component: T['type'],
|
||||
props: Omit<T, 'type'>
|
||||
): 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<T> = never;
|
||||
type IntrinsicElements = {
|
||||
[T in keyof typeof generator as ToKebab<SplitCamel<Uncapitalize<T>>>]: {
|
||||
[K in keyof Omit<Parameters<typeof generator[T]>[0], 'type'>]?: Parameters<typeof generator[T]>[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 = (
|
||||
<literal value={component.slice('src/'.length, -'.vue'.length)} />
|
||||
) as unknown as estree.Literal;
|
||||
) as estree.Literal;
|
||||
const identifier = (
|
||||
<identifier name={base.slice(0, -'.vue'.length).replace(/[-.]|^(?=\d)/g, '_').replace(/(?<=^[^A-Z_]*$)/, '_')} />
|
||||
) as unknown as estree.Identifier;
|
||||
<identifier
|
||||
name={base
|
||||
.slice(0, -'.vue'.length)
|
||||
.replace(/[-.]|^(?=\d)/g, '_')
|
||||
.replace(/(?<=^[^A-Z_]*$)/, '_')}
|
||||
/>
|
||||
) as estree.Identifier;
|
||||
const parameters = (
|
||||
<object-expression
|
||||
properties={[
|
||||
(
|
||||
<property
|
||||
key={<identifier name='layout' />}
|
||||
value={<literal value={`${dir}/`.startsWith('src/pages/') ? 'fullscreen' : 'centered'} />}
|
||||
key={(<identifier name='layout' />) as estree.Identifier}
|
||||
value={
|
||||
(
|
||||
<literal
|
||||
value={
|
||||
`${dir}/`.startsWith('src/pages/')
|
||||
? 'fullscreen'
|
||||
: 'centered'
|
||||
}
|
||||
/>
|
||||
) as estree.Literal
|
||||
}
|
||||
kind={'init' as const}
|
||||
/>,
|
||||
...hasMsw
|
||||
/>
|
||||
) as estree.Property,
|
||||
...(hasMsw
|
||||
? [
|
||||
(
|
||||
<property
|
||||
key={<identifier name='msw' />}
|
||||
value={<identifier name='msw' />}
|
||||
key={(<identifier name='msw' />) as estree.Identifier}
|
||||
value={(<identifier name='msw' />) as estree.Identifier}
|
||||
kind={'init' as const}
|
||||
shorthand
|
||||
/>,
|
||||
/>
|
||||
) as estree.Property,
|
||||
]
|
||||
: [],
|
||||
: []),
|
||||
]}
|
||||
/>
|
||||
);
|
||||
) as estree.ObjectExpression;
|
||||
const program = (
|
||||
<program
|
||||
body={[
|
||||
(
|
||||
<import-declaration
|
||||
source={<literal value='@storybook/vue3' />}
|
||||
source={(<literal value='@storybook/vue3' />) as estree.Literal}
|
||||
specifiers={[
|
||||
(
|
||||
<import-specifier
|
||||
local={<identifier name='Meta' />}
|
||||
imported={<identifier name='Meta' />}
|
||||
/>,
|
||||
...hasImplStories
|
||||
local={(<identifier name='Meta' />) as estree.Identifier}
|
||||
imported={(<identifier name='Meta' />) as estree.Identifier}
|
||||
/>
|
||||
) as estree.ImportSpecifier,
|
||||
...(hasImplStories
|
||||
? []
|
||||
: [
|
||||
(
|
||||
<import-specifier
|
||||
local={<identifier name='StoryObj' />}
|
||||
imported={<identifier name='StoryObj' />}
|
||||
/>,
|
||||
],
|
||||
local={
|
||||
(<identifier name='StoryObj' />) as estree.Identifier
|
||||
}
|
||||
imported={
|
||||
(<identifier name='StoryObj' />) as estree.Identifier
|
||||
}
|
||||
/>
|
||||
) as estree.ImportSpecifier,
|
||||
]),
|
||||
]}
|
||||
/>,
|
||||
...hasMsw
|
||||
/>
|
||||
) as estree.ImportDeclaration,
|
||||
...(hasMsw
|
||||
? [
|
||||
(
|
||||
<import-declaration
|
||||
source={<literal value={`./${basename(msw)}`} />}
|
||||
source={
|
||||
(<literal value={`./${basename(msw)}`} />) as estree.Literal
|
||||
}
|
||||
specifiers={[
|
||||
(
|
||||
<import-namespace-specifier
|
||||
local={<identifier name='msw' />}
|
||||
/>,
|
||||
local={(<identifier name='msw' />) as estree.Identifier}
|
||||
/>
|
||||
) as estree.ImportNamespaceSpecifier,
|
||||
]}
|
||||
/>,
|
||||
/>
|
||||
) as estree.ImportDeclaration,
|
||||
]
|
||||
: [],
|
||||
...hasImplStories
|
||||
: []),
|
||||
...(hasImplStories
|
||||
? []
|
||||
: [
|
||||
(
|
||||
<import-declaration
|
||||
source={<literal value={`./${base}`} />}
|
||||
source={(<literal value={`./${base}`} />) as estree.Literal}
|
||||
specifiers={[
|
||||
<import-default-specifier
|
||||
local={identifier}
|
||||
/>,
|
||||
(
|
||||
<import-default-specifier local={identifier} />
|
||||
) as estree.ImportDefaultSpecifier,
|
||||
]}
|
||||
/>,
|
||||
],
|
||||
/>
|
||||
) as estree.ImportDeclaration,
|
||||
]),
|
||||
(
|
||||
<variable-declaration
|
||||
kind={'const' as const}
|
||||
declarations={[
|
||||
(
|
||||
<variable-declarator
|
||||
id={<identifier name='meta' />}
|
||||
id={(<identifier name='meta' />) as estree.Identifier}
|
||||
init={
|
||||
(
|
||||
<satisfies-expression
|
||||
expression={
|
||||
(
|
||||
<object-expression
|
||||
properties={[
|
||||
(
|
||||
<property
|
||||
key={<identifier name='title' />}
|
||||
key={
|
||||
(
|
||||
<identifier name='title' />
|
||||
) as estree.Identifier
|
||||
}
|
||||
value={literal}
|
||||
kind={'init' as const}
|
||||
/>,
|
||||
/>
|
||||
) as estree.Property,
|
||||
(
|
||||
<property
|
||||
key={<identifier name='component' />}
|
||||
key={
|
||||
(
|
||||
<identifier name='component' />
|
||||
) as estree.Identifier
|
||||
}
|
||||
value={identifier}
|
||||
kind={'init' as const}
|
||||
/>,
|
||||
/>
|
||||
) as estree.Property,
|
||||
]}
|
||||
/>
|
||||
) as estree.ObjectExpression
|
||||
}
|
||||
reference={<identifier name={`Meta<typeof ${identifier.name}>`} />}
|
||||
reference={
|
||||
(
|
||||
<identifier
|
||||
name={`Meta<typeof ${identifier.name}>`}
|
||||
/>
|
||||
) as estree.Identifier
|
||||
}
|
||||
/>,
|
||||
/>
|
||||
) as estree.Expression
|
||||
}
|
||||
/>
|
||||
) as estree.VariableDeclarator,
|
||||
]}
|
||||
/>,
|
||||
...hasImplStories
|
||||
? [
|
||||
]
|
||||
/>
|
||||
) as estree.VariableDeclaration,
|
||||
...(hasImplStories
|
||||
? []
|
||||
: [
|
||||
(
|
||||
<export-named-declaration
|
||||
declaration={
|
||||
(
|
||||
<variable-declaration
|
||||
kind={'const' as const}
|
||||
declarations={[
|
||||
(
|
||||
<variable-declarator
|
||||
id={<identifier name='Default' />}
|
||||
id={
|
||||
(
|
||||
<identifier name='Default' />
|
||||
) as estree.Identifier
|
||||
}
|
||||
init={
|
||||
(
|
||||
<satisfies-expression
|
||||
expression={
|
||||
(
|
||||
<object-expression
|
||||
properties={[
|
||||
(
|
||||
<property
|
||||
key={<identifier name='render' />}
|
||||
key={
|
||||
(
|
||||
<identifier name='render' />
|
||||
) as estree.Identifier
|
||||
}
|
||||
value={
|
||||
(
|
||||
<function-expression
|
||||
params={[
|
||||
<identifier name='args' />,
|
||||
(
|
||||
<identifier name='args' />
|
||||
) as estree.Identifier,
|
||||
(
|
||||
<object-pattern
|
||||
properties={[
|
||||
(
|
||||
<property
|
||||
key={<identifier name='argTypes' />}
|
||||
value={<identifier name='argTypes' />}
|
||||
kind={'init' as const}
|
||||
key={
|
||||
(
|
||||
<identifier name='argTypes' />
|
||||
) as estree.Identifier
|
||||
}
|
||||
value={
|
||||
(
|
||||
<identifier name='argTypes' />
|
||||
) as estree.Identifier
|
||||
}
|
||||
kind={
|
||||
'init' as const
|
||||
}
|
||||
shorthand
|
||||
/>,
|
||||
/>
|
||||
) as estree.AssignmentProperty,
|
||||
]}
|
||||
/>,
|
||||
/>
|
||||
) as estree.ObjectPattern,
|
||||
]}
|
||||
body={
|
||||
(
|
||||
<block-statement
|
||||
body={[
|
||||
(
|
||||
<return-statement
|
||||
argument={
|
||||
(
|
||||
<object-expression
|
||||
properties={[
|
||||
(
|
||||
<property
|
||||
key={<identifier name='components' />}
|
||||
key={
|
||||
(
|
||||
<identifier name='components' />
|
||||
) as estree.Identifier
|
||||
}
|
||||
value={
|
||||
(
|
||||
<object-expression
|
||||
properties={[
|
||||
(
|
||||
<property
|
||||
key={identifier}
|
||||
value={identifier}
|
||||
kind={'init' as const}
|
||||
key={
|
||||
identifier
|
||||
}
|
||||
value={
|
||||
identifier
|
||||
}
|
||||
kind={
|
||||
'init' as const
|
||||
}
|
||||
shorthand
|
||||
/>,
|
||||
/>
|
||||
) as estree.Property,
|
||||
]}
|
||||
/>
|
||||
) as estree.ObjectExpression
|
||||
}
|
||||
kind={'init' as const}
|
||||
/>,
|
||||
kind={
|
||||
'init' as const
|
||||
}
|
||||
/>
|
||||
) as estree.Property,
|
||||
(
|
||||
<property
|
||||
key={<identifier name='props' />}
|
||||
key={
|
||||
(
|
||||
<identifier name='props' />
|
||||
) as estree.Identifier
|
||||
}
|
||||
value={
|
||||
(
|
||||
<call-expression
|
||||
callee={
|
||||
(
|
||||
<member-expression
|
||||
object={<identifier name='Object' />}
|
||||
property={<identifier name='keys' />}
|
||||
object={
|
||||
(
|
||||
<identifier name='Object' />
|
||||
) as estree.Identifier
|
||||
}
|
||||
property={
|
||||
(
|
||||
<identifier name='keys' />
|
||||
) as estree.Identifier
|
||||
}
|
||||
/>
|
||||
) as estree.MemberExpression
|
||||
}
|
||||
arguments={[
|
||||
<identifier name='argTypes' />,
|
||||
(
|
||||
<identifier name='argTypes' />
|
||||
) as estree.Identifier,
|
||||
]}
|
||||
/>
|
||||
) as estree.CallExpression
|
||||
}
|
||||
kind={'init' as const}
|
||||
/>,
|
||||
kind={
|
||||
'init' as const
|
||||
}
|
||||
/>
|
||||
) as estree.Property,
|
||||
(
|
||||
<property
|
||||
key={<identifier name='template' />}
|
||||
value={<literal value={`<${identifier.name} v-bind="$props" />`} />}
|
||||
kind={'init' as const}
|
||||
/>,
|
||||
]}
|
||||
/>
|
||||
key={
|
||||
(
|
||||
<identifier name='template' />
|
||||
) as estree.Identifier
|
||||
}
|
||||
/>,
|
||||
]}
|
||||
value={
|
||||
(
|
||||
<literal
|
||||
value={`<${identifier.name} v-bind="$props" />`}
|
||||
/>
|
||||
) 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,
|
||||
(
|
||||
<property
|
||||
key={<identifier name='parameters' />}
|
||||
key={
|
||||
(
|
||||
<identifier name='parameters' />
|
||||
) as estree.Identifier
|
||||
}
|
||||
value={parameters}
|
||||
kind={'init' as const}
|
||||
/>,
|
||||
/>
|
||||
) as estree.Property,
|
||||
]}
|
||||
/>
|
||||
) as estree.ObjectExpression
|
||||
}
|
||||
reference={<identifier name={`StoryObj<typeof ${identifier.name}>`} />}
|
||||
reference={
|
||||
(
|
||||
<identifier
|
||||
name={`StoryObj<typeof ${identifier.name}>`}
|
||||
/>
|
||||
) as estree.Identifier
|
||||
}
|
||||
/>,
|
||||
/>
|
||||
) as estree.Expression
|
||||
}
|
||||
/>
|
||||
) as estree.VariableDeclarator,
|
||||
]}
|
||||
/>
|
||||
) as estree.VariableDeclaration
|
||||
}
|
||||
/>,
|
||||
],
|
||||
/>
|
||||
) as estree.ExportNamedDeclaration,
|
||||
]),
|
||||
(
|
||||
<export-default-declaration
|
||||
declaration={<identifier name='meta' />}
|
||||
/>,
|
||||
declaration={(<identifier name='meta' />) 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(
|
||||
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));
|
||||
})
|
||||
));
|
||||
)
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue