Skip to content

Commit

Permalink
Merge pull request #26 from eduardconstantin/feat/template
Browse files Browse the repository at this point in the history
Feat/template
  • Loading branch information
eduardconstantin authored Mar 5, 2024
2 parents 3ed0143 + 895d5ca commit 92c660e
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 28 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<h1 align="center">Storybook Genie</h1>
<div align="center"><img src="sgLOGO.png"/></div>
<br />

Storybook Genie is a command line interface tool that can be used to convert files that contain React components into
Expand All @@ -20,9 +21,10 @@ Storybook stories.

## 🌟 Features

- Select preferred model
- Select preferred GPT model
- File selection input
- JS beautify
- Use custom story template
- A small number of dependencies

## 📦 Installation
Expand Down Expand Up @@ -61,6 +63,8 @@ following code:
}
```

A default story template can be set in storybook-genie.template.js/ts file, just create on in the root of the project

To use Storybook Genie, run the following command:

```bash
Expand Down
18 changes: 14 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env node

import path from "path";
import { glob } from "glob";
import { readFileSync, writeFileSync, existsSync } from "fs";
import dotenv from "universal-dotenv";
import beautify from "js-beautify";
Expand Down Expand Up @@ -49,6 +50,7 @@ const showLoading = (message) => {
async function run() {
const configPath = path.resolve(process.cwd(), "storybook-genie.config.json");
let model;
let template;

if (existsSync(configPath)) {
const data = fs.readFileSync(configPath);
Expand All @@ -58,6 +60,12 @@ async function run() {
}
}

const templateFilePath = glob.sync("storybook-genie.template.*")[0];
if (templateFilePath) {
const data = readFileSync(templateFilePath, "utf8");
template = data.trim();
}

if (!model) {
const answer = await inquirer.prompt([
{
Expand All @@ -77,10 +85,12 @@ async function run() {
const extension = path.extname(file);
const spinner = showLoading("Generating story...");
try {
const story = await componentConverter(input.replace(/^\s*[\r\n]/gm, "").trim(), model).then((story) => {
story = beautify(story, resetOptions);
return beautify(story, options);
});
const story = await componentConverter(input.replace(/^\s*[\r\n]/gm, "").trim(), model, template).then(
(story) => {
story = beautify(story, resetOptions);
return beautify(story, options);
}
);
writeFileSync(file.replace(extension, `.story${extension}`), story);
spinner.stopLoading("Story generated!", "\x1b[32m");
} catch (error) {
Expand Down
34 changes: 17 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "storybook-genie",
"version": "1.1.1",
"version": "1.2.0",
"description": "Storybook Genie is a command line interface tool that can generate Storybook stories from React components.",
"keywords": [
"storybook",
Expand Down Expand Up @@ -33,7 +33,7 @@
"url": "https://github.com/eduardconstantin/storybook-genie"
},
"dependencies": {
"@inquirer/core": "^5.1.1",
"@inquirer/core": "7.0.0",
"inquirer": "^9.2.12",
"js-beautify": "^1.14.11",
"openai": "^4.25.0",
Expand Down
Binary file added sgLOGO.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 5 additions & 3 deletions src/converter.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import getClient from "./client.js";

export async function componentConverter(component, model) {
const template = `import type { Meta, StoryObj } from '@storybook/react';\n/* import component file */\nconst meta = {\n title: /* Component title */,\n component: /* Component name */,\n parameters: {\n layout: 'centered'\n },\n tags: ['autodocs'],\n} satisfies Meta<typeof /* Component name */>\n\nexport default meta\n\ntype Story = StoryObj<typeof meta>\n\nexport const /* StoryName */ : Story = {\n args: {\n /* args */\n },\n}`;
const prompt = `You are a senior web developer. You are specialized in creating Storybook stories for React components. Your focus is on aiding expert frontend developers by generating clean, readable, and standardized story code. You strictly adhere to CSF3 conventions and do not use Component Story Format 2 (CSF2).\nThe user will give you the react component and you will reply with the code and nothing else, avoiding comments.\nBelow, here's the template you will stick to. Keep the provided format and add component variants if possible:\n${template}`;
export async function componentConverter(component, model, template) {
const defaultTemplate =
template ||
`import type { Meta, StoryObj } from '@storybook/react';\n/* import component file */\nconst meta = {\n title: /* Component title */,\n component: /* Component name */,\n parameters: {\n layout: 'centered'\n },\n tags: ['autodocs'],\n} satisfies Meta<typeof /* Component name */>\n\nexport default meta\n\ntype Story = StoryObj<typeof meta>\n\nexport const /* StoryName */ : Story = {\n args: {\n /* args */\n },\n}`;
const prompt = `You are a senior web developer. You are specialized in creating Storybook stories for React components. Your focus is on aiding expert frontend developers by generating clean, readable, and standardized story code. You strictly adhere to CSF3 conventions and do not use Component Story Format 2 (CSF2).\nThe user will give you the react component and you will reply with the code and nothing else, avoiding comments.\nBelow, here's the template you will stick to. Keep the provided format and add component variants if possible:\n${defaultTemplate}`;

const response = await getClient().chat.completions.create({
model,
Expand Down
4 changes: 3 additions & 1 deletion src/models.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import getClient from "./client.js";

const getModels = async () => {
const models = await getClient().models.list();
const modelsId = models.data.filter((model) => model.id.includes("gpt")).map((el) => el.id);
const modelsId = models.data
.filter((model) => model.id.includes("gpt") && !model.id.includes("gpt-4-vision"))
.map((el) => el.id);
return modelsId;
};

Expand Down

0 comments on commit 92c660e

Please sign in to comment.