Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 🛠️ #5 discussion の問題解決 #8

Merged
merged 2 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions demo/react/src/components/TestA/TestA.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Meta, StoryObj } from '@storybook/react'

import { TestA } from './TestA'

const meta: Meta<typeof TestA> = {
title: 'components/TestA',
component: TestA,
tags: ['autodocs'],
args: { text: undefined },
argTypes: { text: { control: 'text' } },
}

export default meta
type Story = StoryObj<typeof meta>

export const Primary: Story = {}
8 changes: 8 additions & 0 deletions demo/react/src/components/TestA/TestA.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const TestA = ({ text }: { text: string }) => {
return (
<>
<div>TestA</div>
<p>{text}</p>
</>
)
}
16 changes: 16 additions & 0 deletions demo/react/src/components/TestB/TestB.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Meta, StoryObj } from '@storybook/react'

import { TestB } from './TestB'

const meta: Meta<typeof TestB> = {
title: 'components/TestB',
component: TestB,
tags: ['autodocs'],
args: { test: true },
argTypes: { test: { control: 'boolean' } },
}

export default meta
type Story = StoryObj<typeof meta>

export const Primary: Story = {}
13 changes: 13 additions & 0 deletions demo/react/src/components/TestB/TestB.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { FC, HTMLAttributes } from 'react'

type Props = {
test: boolean
} & HTMLAttributes<HTMLDivElement>

export const TestB: FC<Props> = (props) => {
return (
<>
<div {...props}>TestB</div>
</>
)
}
16 changes: 16 additions & 0 deletions demo/react/src/components/TestC/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Meta, StoryObj } from '@storybook/react'

import { TestC } from './index.tsx'

const meta: Meta<typeof TestC> = {
title: 'components/TestC',
component: TestC,
tags: ['autodocs'],
args: { test: true },
argTypes: { test: { control: 'boolean' } },
}

export default meta
type Story = StoryObj<typeof meta>

export const Primary: Story = {}
13 changes: 13 additions & 0 deletions demo/react/src/components/TestC/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { FC, HTMLAttributes } from 'react'

type Props = {
test: boolean
} & HTMLAttributes<HTMLDivElement>

export const TestC: FC<Props> = (props) => {
return (
<>
<div {...props}>TestB</div>
</>
)
}
5 changes: 4 additions & 1 deletion packages/auto-story-generator/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { consola } from "consola";

Check warning on line 1 in packages/auto-story-generator/src/index.ts

View workflow job for this annotation

GitHub Actions / eslint-check

Logs are output on the console

Check warning on line 1 in packages/auto-story-generator/src/index.ts

View workflow job for this annotation

GitHub Actions / eslint-check

Logs are output on the console
import { loadFile } from "magicast";
import { minimatch } from "minimatch";
import { Project } from "ts-morph";
Expand Down Expand Up @@ -43,11 +43,14 @@
const projectRootDir = process.cwd();
const fileName = file.split("/").pop();
const fileType = fileName?.split(".").slice(1).join(".");
const componentName = fileName?.replace(`.${fileType}`, "");
const componentName =
fileName?.replace(`.${fileType}`, "") === "index"
? file.split("/").slice(-2)[0]
: fileName?.replace(`.${fileType}`, "");
const relativeSourceFilePath = file.replace(projectRootDir, "");

if (!componentName || !fileName) {
return consola.error("Could not find component name");

Check warning on line 53 in packages/auto-story-generator/src/index.ts

View workflow job for this annotation

GitHub Actions / eslint-check

Logs are output on the console
}

// consola.info(`${componentName} component has been changed`);
Expand All @@ -56,7 +59,7 @@
const project = new Project();
const sourceFile = project.createSourceFile(fileName || "", mod.$code);

consola.start(`${componentName} Story file is being generated ....`);

Check warning on line 62 in packages/auto-story-generator/src/index.ts

View workflow job for this annotation

GitHub Actions / eslint-check

Logs are output on the console

switch (options.preset) {
case "lit": {
Expand Down Expand Up @@ -88,17 +91,17 @@
}

case "vue": {
consola.error("Not yet supported.");

Check warning on line 94 in packages/auto-story-generator/src/index.ts

View workflow job for this annotation

GitHub Actions / eslint-check

Logs are output on the console
break;
}

case "custom": {
consola.error("Not yet supported.");

Check warning on line 99 in packages/auto-story-generator/src/index.ts

View workflow job for this annotation

GitHub Actions / eslint-check

Logs are output on the console
break;
}

default: {
consola.error(

Check warning on line 104 in packages/auto-story-generator/src/index.ts

View workflow job for this annotation

GitHub Actions / eslint-check

Logs are output on the console
`Preset ${options.preset} is not supported. Please use one of the following: lit, react, vue, custom`,
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { consola } from "consola";

Check warning on line 1 in packages/auto-story-generator/src/presets/lit/genLitStoryFile.ts

View workflow job for this annotation

GitHub Actions / eslint-check

Logs are output on the console

Check warning on line 1 in packages/auto-story-generator/src/presets/lit/genLitStoryFile.ts

View workflow job for this annotation

GitHub Actions / eslint-check

Logs are output on the console
import { kebabCase, pascalCase } from "scule";

import { genLitPropTypes } from "~/src/presets/lit/genLitPropTypes";
import { getLitPropTypes } from "~/src/presets/lit/getLitPropTypes";
import { GenStoryFileOptions } from "~/src/types/GenStoryFileType";
import { genStoryFile } from "~/src/utils/genStoryFile";

Expand All @@ -14,10 +14,10 @@
sourceFile,
prettierConfigPath,
}: GenStoryFileOptions["fileOptions"]) => {
const propTypes = genLitPropTypes({ sourceFile, componentName });
const propTypes = getLitPropTypes({ sourceFile, componentName });
const pascalComponentName = pascalCase(componentName);

if (!propTypes) return consola.error("Could not find argTypes");

Check warning on line 20 in packages/auto-story-generator/src/presets/lit/genLitStoryFile.ts

View workflow job for this annotation

GitHub Actions / eslint-check

Logs are output on the console

const initialCode = `
import { html } from "lit";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
GenReactPropTypesReturn,
} from "~/src/types/GenPropTypeType";

export const genLitPropTypes = ({
export const getLitPropTypes = ({
sourceFile,
componentName,
}: GenReactPropTypesOptions): GenReactPropTypesReturn => {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { consola } from "consola";
import { pascalCase } from "scule";

import { genReactPropTypes } from "~/src/presets/react/genReactPropTypes";
import { getReactPropTypes } from "~/src/presets/react/getReactPropTypes";
import { GenStoryFileOptions } from "~/src/types/GenStoryFileType";
import { genStoryFile } from "~/src/utils/genStoryFile";

Expand All @@ -14,15 +14,18 @@ export const genReactStoryFile = async ({
sourceFile,
prettierConfigPath,
}: GenStoryFileOptions["fileOptions"]) => {
const propTypes = genReactPropTypes({ sourceFile, componentName });
const { propTypes } = getReactPropTypes({
sourceFile,
componentName,
});
const pascalComponentName = pascalCase(componentName);

if (!propTypes) return consola.error("Could not find argTypes");

const initialCode = `
import type { Meta, StoryObj } from "@storybook/react";

import { ${pascalComponentName} } from "./${pascalComponentName}";
import { ${pascalComponentName} } from "./${fileName}";

const meta: Meta<typeof ${pascalComponentName}> = {
title: "components/${pascalComponentName}",
Expand Down
124 changes: 124 additions & 0 deletions packages/auto-story-generator/src/presets/react/getReactPropTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { pascalCase } from "scule";
import { TypeFlags, ts, Symbol } from "ts-morph";

import {
GenReactPropTypesOptions,
GenReactPropTypesReturn,
} from "~/src/types/GenPropTypeType";

const getTypeFlagsName = (flags: TypeFlags) => {
// Get all the keys of TypeFlags
const keys = Object.keys(TypeFlags) as (keyof typeof TypeFlags)[];

// Filter the keys where the flag is set
const setFlags = keys.find((key) => flags === TypeFlags[key]);

return setFlags || "err";
};

export const getReactPropTypes = ({
sourceFile,
componentName,
}: GenReactPropTypesOptions): {
propsPattern?: "component-props" | "props" | "inline";
propTypes: GenReactPropTypesReturn;
} => {
let propsPattern: "component-props" | "props" | "inline" = "component-props";

const pascalComponentName = pascalCase(componentName);

const propsType = sourceFile.getTypeAlias(`${pascalComponentName}Props`);
const propsInterface = sourceFile.getInterface(`${pascalComponentName}Props`);
const propsOnlyType = sourceFile.getTypeAlias("Props");
const propsOnlyInterface = sourceFile.getInterface("Props");
const propsInline = sourceFile
.getVariableDeclaration(pascalComponentName)
?.getInitializerIfKindOrThrow(ts.SyntaxKind.ArrowFunction);

const props =
propsType?.getType() ||
propsInterface?.getType() ||
propsOnlyType?.getType() ||
propsOnlyInterface?.getType() ||
propsInline?.getParameters()[0].getType();

if (!props) {
return {
propTypes: undefined,
};
}

// eslint-disable-next-line @typescript-eslint/ban-types
let propsProperties: Symbol[] = [];
const isPropsIntersection = props.isIntersection();
if (isPropsIntersection) {
propsProperties = [];

const intersectionTypes = props.getIntersectionTypes();

intersectionTypes.forEach((intersectionType) => {
const intersectionTypeText = intersectionType.getText();

if (intersectionTypeText.includes("HTMLAttributes")) {
return;
}

return propsProperties.push(...intersectionType.getProperties());
});
} else {
propsProperties = props.getProperties();
}

if (propsOnlyType || propsOnlyInterface) {
propsPattern = "props";
}

if (propsInline) {
propsPattern = "inline";
}

const propTypes = propsProperties.map((prop) => {
const propName = prop.getName();
const propType = prop.getValueDeclaration()?.getType();

if (!propType) {
return {
name: propName,
type: ["err"],
isOptional: prop.isOptional(),
value: [],
};
}

if (propType.isUnion() && !propType.isBoolean()) {
const unionTypes = propType.getUnionTypes();

const type = Array.from(
new Set(
unionTypes.map((union) =>
getTypeFlagsName(union.getFlags().valueOf()),
),
),
);

return {
name: propName,
type,
isOptional: prop.isOptional(),
value: unionTypes.map((union) => union.getText().replace(/"/g, "")),
};
}

return {
name: propName,
type: [prop.getValueDeclaration()!.getType().getText()],
isOptional: prop.isOptional(),
value: [],
};
});

return {
propsPattern,
propTypes,
};
};
Loading