import inquirer from 'inquirer'; import inquirerFileTreeSelection from 'inquirer-file-tree-selection-prompt'; import colors from 'colors'; import path from 'path'; import fs from 'fs'; import Handlebars from 'handlebars'; inquirer.registerPrompt('file-tree-selection', inquirerFileTreeSelection); const STORY_TEMPLATE_PATH = path.resolve(__dirname, '../../templates/story-template.js'); const storyTemplate = Handlebars.compile(fs.readFileSync(STORY_TEMPLATE_PATH, 'utf-8')); export async function runStory(options: any) { const answers = await inquirer .prompt([ { type: 'input', name: 'title', message: "What's the title of this story (the name that shows up in storybook)?", validate: input => { if (!input) return 'A title is required'; return true; } }, { type: 'file-tree-selection', name: 'storyDir', message: 'Where should this story be generated?', onlyShowDir: true, onlyShowValid: true, validate: storyDir => { return !storyDir.endsWith('node_modules') && !storyDir.endsWith('.storybook'); } } ]); const { storyDir, title } = answers; const storyName = getStoryName(storyDir); const lwcClassName = storyName.substring(0,1).toUpperCase() + storyName.substring(1); const lwcFileName = storyName + '.js'; const lwcMetaFileName = storyName + '.js-meta.xml'; const storyFileName = storyName + '.stories.js'; const storyPath = path.resolve(storyDir, storyFileName); const lwcCustomElement = `${getStoryDirectoryName(storyDir)}-${toKebabCase(lwcClassName)}`; if (fs.existsSync(storyPath)) { console.error(colors.red(`A story already exists at: ${storyPath}`)); runStory(options); return; } const story = storyTemplate({ lwcClassName, lwcFileName, lwcCustomElement, lwcMetaFileName, title }); fs.writeFileSync(storyPath, story); console.log(colors.green(`Successfully generated story: `) + storyPath); } function getStoryName(storyDir: string): string { return storyDir.substring(storyDir.lastIndexOf('/') + 1); } function toKebabCase(str: string) { const match = str .match(/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g) if (!match) throw new Error('Invalid file name: ' + str); return match.map((x: string) => x.toLowerCase()) .join('-'); } function getStoryDirectoryName(storyDir: string): string { const storyFolderPath = storyDir.substring(0, storyDir.lastIndexOf('/')); return storyFolderPath.substring(storyFolderPath.lastIndexOf('/') + 1); }