From e00df5d5609fccbba9629ffe99d134fa0047ebbe Mon Sep 17 00:00:00 2001 From: Ben Kates Date: Tue, 23 Jul 2024 18:09:03 -0400 Subject: [PATCH 1/8] init cli tool --- bin/createComponent/createComponent.js | 55 ++++ bin/createComponent/createDocs.js | 9 + bin/createComponent/createStory.js | 35 ++ package-lock.json | 433 ++++++++++++++++++++++++- package.json | 4 +- 5 files changed, 532 insertions(+), 4 deletions(-) create mode 100644 bin/createComponent/createComponent.js create mode 100644 bin/createComponent/createDocs.js create mode 100644 bin/createComponent/createStory.js diff --git a/bin/createComponent/createComponent.js b/bin/createComponent/createComponent.js new file mode 100644 index 00000000..4b8f9934 --- /dev/null +++ b/bin/createComponent/createComponent.js @@ -0,0 +1,55 @@ +#!/usr/bin/env node +import inquirer from "inquirer"; +import fs from "fs"; +import path from "path"; +import { createStory } from "./createStory.js"; + +async function main() { + const answers = await inquirer + .prompt([ + { + type: "input", + name: "componentName", + message: "What is the name of your component? (ie: MyComponent)", + validate: (componentName) => { + if (componentName) { + return true; + } else { + console.log("Please enter a component name"); + return false; + } + } + } + // TODO: subdir of src/lib + // TODO: ask about .docs.mdx + // TODO: check PascalCase + ]) + .then((answers) => { + const { componentName } = answers; + const dir = path.join(process.cwd(), "src", "lib", componentName); + // if directory doesn't exist, create it + if (!fs.existsSync(dir)) { + // create directory + fs.mkdirSync(dir, { recursive: true }); + + // create Component.svelte (blank) + const svelteFilePath = path.join(dir, `${componentName}.svelte`); + fs.writeFileSync(svelteFilePath, "", "utf8"); + + // create Component.docs.md + const docsFilePath = path.join(dir, `${componentName}.docs.md`); + fs.writeFileSync(docsFilePath, createDocs(componentName), "utf8"); + + // create Component.stories.svelte + const storyFilePath = path.join(dir, `${componentName}.stories.svelte`); + fs.writeFileSync(storyFilePath, createStory(componentName), "utf8"); + } else { + console.error("Directory already exists"); + } + }); +} + +main().catch(() => { + console.error(); + // process.exit(); +}); diff --git a/bin/createComponent/createDocs.js b/bin/createComponent/createDocs.js new file mode 100644 index 00000000..060c91a1 --- /dev/null +++ b/bin/createComponent/createDocs.js @@ -0,0 +1,9 @@ +export function createDocs(componentName) { + return ` +Esse ipsum deserunt dolor minim dolore sunt cillum. + +\`\`\`js +import { ${componentName} } from "@urbaninstitute/dataviz-components"; +\`\`\` +`; +} diff --git a/bin/createComponent/createStory.js b/bin/createComponent/createStory.js new file mode 100644 index 00000000..682a2da9 --- /dev/null +++ b/bin/createComponent/createStory.js @@ -0,0 +1,35 @@ +export function createStory(componentName) { + return ` + + + + + + +`; +} diff --git a/package-lock.json b/package-lock.json index 8b6679e8..cc9e194f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,6 +43,7 @@ "@sveltejs/package": "^2.3.0", "concurrently": "^8.2.2", "http-server": "^14.1.1", + "inquirer": "^10.1.2", "prettier": "^3.2.5", "prettier-plugin-svelte": "^3.2.2", "publint": "^0.1.9", @@ -2603,6 +2604,307 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@inquirer/checkbox": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-2.4.2.tgz", + "integrity": "sha512-iZRNbTlSB9xXt/+jdMFViBdxw1ILWu3365rzfM5OLwAyOScbDFFGSH7LEUwoq1uOIo48ymOEwYSqP5y8hQMlmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^9.0.5", + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.1", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/confirm": { + "version": "3.1.17", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.17.tgz", + "integrity": "sha512-qCpt/AABzPynz8tr69VDvhcjwmzAryipWXtW8Vi6m651da4H/d0Bdn55LkxXD7Rp2gfgxvxzTdb66AhIA8gzBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^9.0.5", + "@inquirer/type": "^1.5.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.0.5.tgz", + "integrity": "sha512-QWG41I7vn62O9stYKg/juKXt1PEbr/4ZZCPb4KgXDQGwgA9M5NBTQ7FnOvT1ridbxkm/wTxLCNraUs7y47pIRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.1", + "@types/mute-stream": "^0.0.4", + "@types/node": "^20.14.11", + "@types/wrap-ansi": "^3.0.0", + "ansi-escapes": "^4.3.2", + "cli-spinners": "^2.9.2", + "cli-width": "^4.1.0", + "mute-stream": "^1.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@inquirer/core/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@inquirer/core/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/editor": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-2.1.17.tgz", + "integrity": "sha512-hwx3VpFQzOY2hFWnY+XPsUGCIUVQ5kYxH6+CExv/RbMiAoN3zXtzj8DyrWBOHami0vBrrnPS8CTq3uQWc7N2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^9.0.5", + "@inquirer/type": "^1.5.1", + "external-editor": "^3.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/expand": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-2.1.17.tgz", + "integrity": "sha512-s4V/dC+GeE5s97xoTtZSmC440uNKePKqZgzqEf0XM63ciilnXAtKGvoAWOePFdlK+oGTz0d8bhbPKwpKGvRYfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^9.0.5", + "@inquirer/type": "^1.5.1", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.5.tgz", + "integrity": "sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/input": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-2.2.4.tgz", + "integrity": "sha512-wvYnDITPQn+ltktj/O9kQjPxOvpmwcpxLWh8brAyD+jlEbihxtrx9cZdZcxqaCVQj3caw4eZa2Uq5xELo4yXkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^9.0.5", + "@inquirer/type": "^1.5.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/number": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-1.0.5.tgz", + "integrity": "sha512-+H6TJPU2AJEcoF6nVTWssxS7gnhxWvf6CkILAdfq/yGm/htBKNDrvYLYaJvi1Be/aXQoKID9FaP94bUCjOvJNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^9.0.5", + "@inquirer/type": "^1.5.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/password": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-2.1.17.tgz", + "integrity": "sha512-/u6DM/fDHXoBWyA+9aRhghkeo5smE7wO9k4E2UoJbgiRCkt3JjBEuBqLOJNrz8E16M0ez4UM1vd5cXrmICHW+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^9.0.5", + "@inquirer/type": "^1.5.1", + "ansi-escapes": "^4.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/prompts": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-5.3.2.tgz", + "integrity": "sha512-8Jv+6rbY98ilFAZMYYfetu6XGXF/ZU44i5Z6Jx4t0xmwDh/AihdBV/FgetzDDZZMv5AMW1MT35LI0FiS55LoXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/checkbox": "^2.4.2", + "@inquirer/confirm": "^3.1.17", + "@inquirer/editor": "^2.1.17", + "@inquirer/expand": "^2.1.17", + "@inquirer/input": "^2.2.4", + "@inquirer/number": "^1.0.5", + "@inquirer/password": "^2.1.17", + "@inquirer/rawlist": "^2.1.17", + "@inquirer/search": "^1.0.2", + "@inquirer/select": "^2.4.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/rawlist": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-2.1.17.tgz", + "integrity": "sha512-RFrw34xU5aVlMA3ZJCaeKGxYjhu3j4i46O2GMmaRRGeLObCRM1yOKQOsRclSTzjd4A7+M5QleR2iuW/68J9Kwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^9.0.5", + "@inquirer/type": "^1.5.1", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/search": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-1.0.2.tgz", + "integrity": "sha512-E/JD3MeJwJeNilOnRDmHGnlUksyVqrTQEUNqkRpioj8J0sVxW7+pFRHBM2coFsiCpvI4XKRRhWsai5VP8rrfrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^9.0.5", + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.1", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/select": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-2.4.2.tgz", + "integrity": "sha512-r78JlgShqRxyAtBDeBHSDtfrOhSQwm2ecWGGaxe7kD9JwgL3UN563G1ncVRYdsWD7/tigflcskfipVeoDLhLJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/core": "^9.0.5", + "@inquirer/figures": "^1.0.5", + "@inquirer/type": "^1.5.1", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.1.tgz", + "integrity": "sha512-m3YgGQlKNS0BM+8AFiJkCsTqHEFCWn6s/Rqye3mYwvqY6LdfUv12eSwbsgNzrYyrLXiy7IrrjDLPysaSBwEfhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mute-stream": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -6024,11 +6326,22 @@ "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "dev": true }, + "node_modules/@types/mute-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", + "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { - "version": "20.12.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.11.tgz", - "integrity": "sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==", + "version": "20.14.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz", + "integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==", "dev": true, + "license": "MIT", "dependencies": { "undici-types": "~5.26.4" } @@ -6133,6 +6446,13 @@ "@types/node": "*" } }, + "node_modules/@types/wrap-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", + "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/yargs": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", @@ -7376,6 +7696,13 @@ "node": ">=10" } }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true, + "license": "MIT" + }, "node_modules/check-error": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", @@ -7531,6 +7858,16 @@ "node": ">=8" } }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -9559,6 +9896,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "license": "MIT", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -11077,6 +11429,25 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, + "node_modules/inquirer": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-10.1.2.tgz", + "integrity": "sha512-rwoy4e2xFz3rru5Q5695rKXLbNlVfODRhRftBEPdxHfbGzN1T8Fxzszcb//SaRnQHsRdiwR8dOZOV+y4SoZ4KQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@inquirer/prompts": "^5.3.2", + "@inquirer/type": "^1.5.1", + "@types/mute-stream": "^0.0.4", + "ansi-escapes": "^4.3.2", + "mute-stream": "^1.0.0", + "run-async": "^3.0.0", + "rxjs": "^7.8.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/internal-slot": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", @@ -14541,6 +14912,16 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -15463,6 +15844,16 @@ "node": ">=0.10.0" } }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -16727,6 +17118,16 @@ "fsevents": "~2.3.2" } }, + "node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -18034,6 +18435,19 @@ "node": ">=14.0.0" } }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -19252,6 +19666,19 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", + "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 950462f3..45cab396 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "build-storybook:test": "storybook build --quiet --test", "test-storybook": "test-storybook", "test-storybook-run": "npx concurrently -k -s first -n 'SB,TEST' -c 'magenta,blue' 'npx http-server storybook-static --port 6006 --silent' 'npx wait-on tcp:6006 && npm run test-storybook -- --index-json'", - "compile-theme-styles": "node ./bin/compileTheme.js" + "compile-theme-styles": "node ./bin/compileTheme.js", + "create-component": "node ./bin/createComponent/createComponent.js" }, "exports": { ".": { @@ -72,6 +73,7 @@ "@sveltejs/package": "^2.3.0", "concurrently": "^8.2.2", "http-server": "^14.1.1", + "inquirer": "^10.1.2", "prettier": "^3.2.5", "prettier-plugin-svelte": "^3.2.2", "publint": "^0.1.9", From c47259d066cfd34c226531dfbbc17dbbc446c6fd Mon Sep 17 00:00:00 2001 From: Ben Kates Date: Wed, 24 Jul 2024 10:49:11 -0400 Subject: [PATCH 2/8] fix file writing --- bin/createComponent/createComponent.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bin/createComponent/createComponent.js b/bin/createComponent/createComponent.js index 4b8f9934..4f48db47 100644 --- a/bin/createComponent/createComponent.js +++ b/bin/createComponent/createComponent.js @@ -3,9 +3,10 @@ import inquirer from "inquirer"; import fs from "fs"; import path from "path"; import { createStory } from "./createStory.js"; +import { createDocs } from "./createDocs.js"; async function main() { - const answers = await inquirer + await inquirer .prompt([ { type: "input", From 134977a693c1453c84e90d6f04d8abf39e0316c7 Mon Sep 17 00:00:00 2001 From: Ben Kates Date: Wed, 24 Jul 2024 10:59:00 -0400 Subject: [PATCH 3/8] add comments + cleanup --- bin/createComponent/createComponent.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/bin/createComponent/createComponent.js b/bin/createComponent/createComponent.js index 4f48db47..09d19193 100644 --- a/bin/createComponent/createComponent.js +++ b/bin/createComponent/createComponent.js @@ -5,6 +5,11 @@ import path from "path"; import { createStory } from "./createStory.js"; import { createDocs } from "./createDocs.js"; +// check if PascalCase https://www.w3resource.com/javascript-exercises/javascript-string-exercise-56.php +function isPascalCase(str) { + return /^[A-Z][A-Za-z]*$/.test(str); +} + async function main() { await inquirer .prompt([ @@ -13,17 +18,19 @@ async function main() { name: "componentName", message: "What is the name of your component? (ie: MyComponent)", validate: (componentName) => { - if (componentName) { - return true; + // if not present + if (!componentName) { + return "Please enter a component name"; + // if not PascalCase + } else if (!isPascalCase(componentName)) { + return "Component name must be in PascalCase"; } else { - console.log("Please enter a component name"); - return false; + return true; } } } // TODO: subdir of src/lib // TODO: ask about .docs.mdx - // TODO: check PascalCase ]) .then((answers) => { const { componentName } = answers; @@ -50,7 +57,4 @@ async function main() { }); } -main().catch(() => { - console.error(); - // process.exit(); -}); +main().catch(console.error); From 7c880a145cbe71c582bb578ffe549d59b988738e Mon Sep 17 00:00:00 2001 From: Ben Kates Date: Wed, 24 Jul 2024 11:02:42 -0400 Subject: [PATCH 4/8] add to readme/changelog --- CHANGELOG.md | 1 + README.md | 8 ++++++++ src/docs/Intro.docs.mdx | 8 ++++++++ 3 files changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6854c3e8..5cf4a346 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Feature: GitHub source links for components via [@etchteam/storybook-addon-github-link](https://storybook.js.org/addons/@etchteam/storybook-addon-github-link) in storybook docs - Patch: Update method of declaring Storybook component descriptions and add import instructions to components - Patch: Remove description field from top level `meta` object in component `.stories.svelte` files (do not render) +- Feature: CLI command to generate new component boilerplate (`npm run create-component`) ## v0.10.2 diff --git a/README.md b/README.md index 58666e5f..7a537e38 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,14 @@ To build your library: npm run package ``` +### CLI-based command for creating new component boilerplate + +To create three boilerplate files for a new component (`ComponentName.svelte`, `ComponentName.stories.svelte`, and `ComponentName.docs.md`), run the following command: + +```bash +npm run create-component +``` + ## Contributing to this library When contributing to this library, keep the following guidelines in mind. The [pull request template](https://github.com/UrbanInstitute/dataviz-components/blob/main/.github/pull_request_template.md) requires explanation of changes and provides a checklist of tasks to ensure clean code and documentation. Please name all branches in `kebab-case`, beginning with "patch", "feature", or "bugfix", and provide insightful commit messages. diff --git a/src/docs/Intro.docs.mdx b/src/docs/Intro.docs.mdx index 5102a141..b1c3363e 100644 --- a/src/docs/Intro.docs.mdx +++ b/src/docs/Intro.docs.mdx @@ -47,3 +47,11 @@ You can either wrap your entire page with a `` instance, or you can wrap ## Contributing to this library We welcome contributions to this library! The [pull request template](https://github.com/UrbanInstitute/dataviz-components/blob/main/.github/pull_request_template.md) requires explanation of changes and provides a checklist of tasks to ensure clean code and documentation. Please name all branches in `kebab-case`, beginning with "patch", "feature", or "bugfix", and provide insightful commit messages. + +### CLI-based command for creating new component boilerplate + +To create three boilerplate files for a new component (`ComponentName.svelte`, `ComponentName.stories.svelte`, and `ComponentName.docs.md`), run the following command: + +```bash +npm run create-component +``` From 91917321218d2b0673e7a7e92dbb990aeed549d3 Mon Sep 17 00:00:00 2001 From: Ben Kates Date: Wed, 24 Jul 2024 13:09:56 -0400 Subject: [PATCH 5/8] remove TODOs --- bin/createComponent/createComponent.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/bin/createComponent/createComponent.js b/bin/createComponent/createComponent.js index 09d19193..d49b283c 100644 --- a/bin/createComponent/createComponent.js +++ b/bin/createComponent/createComponent.js @@ -29,8 +29,6 @@ async function main() { } } } - // TODO: subdir of src/lib - // TODO: ask about .docs.mdx ]) .then((answers) => { const { componentName } = answers; From 236c034300dd0c9503eeadf3b577f7329255e102 Mon Sep 17 00:00:00 2001 From: Ben Kates Date: Wed, 24 Jul 2024 14:32:29 -0400 Subject: [PATCH 6/8] Add feedback that the files were created --- bin/createComponent/createComponent.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bin/createComponent/createComponent.js b/bin/createComponent/createComponent.js index d49b283c..991fde30 100644 --- a/bin/createComponent/createComponent.js +++ b/bin/createComponent/createComponent.js @@ -49,6 +49,9 @@ async function main() { // create Component.stories.svelte const storyFilePath = path.join(dir, `${componentName}.stories.svelte`); fs.writeFileSync(storyFilePath, createStory(componentName), "utf8"); + + // Confirmation text + console.log(`Boilerplate files created in ${dir}`); } else { console.error("Directory already exists"); } From ef6791b352ce57953276b1ad67ea434d1f5aaa70 Mon Sep 17 00:00:00 2001 From: Ben Kates Date: Thu, 25 Jul 2024 12:23:52 -0400 Subject: [PATCH 7/8] remove leading whitespace --- bin/createComponent/createDocs.js | 3 +-- bin/createComponent/createStory.js | 19 ++++++++----------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/bin/createComponent/createDocs.js b/bin/createComponent/createDocs.js index 060c91a1..0519e64b 100644 --- a/bin/createComponent/createDocs.js +++ b/bin/createComponent/createDocs.js @@ -1,6 +1,5 @@ export function createDocs(componentName) { - return ` -Esse ipsum deserunt dolor minim dolore sunt cillum. + return `Esse ipsum deserunt dolor minim dolore sunt cillum. \`\`\`js import { ${componentName} } from "@urbaninstitute/dataviz-components"; diff --git a/bin/createComponent/createStory.js b/bin/createComponent/createStory.js index 682a2da9..78af2849 100644 --- a/bin/createComponent/createStory.js +++ b/bin/createComponent/createStory.js @@ -1,12 +1,11 @@ export function createStory(componentName) { - return ` - -`; +`; } From 18b2ce6ba539971db8b7d954ebcdf03ed96b9d9b Mon Sep 17 00:00:00 2001 From: Ben Kates Date: Thu, 25 Jul 2024 12:46:17 -0400 Subject: [PATCH 8/8] update component creation logic to handle command arguments, DRY --- bin/createComponent/createComponent.js | 103 ++++++++++++++----------- package-lock.json | 31 +------- package.json | 2 +- 3 files changed, 59 insertions(+), 77 deletions(-) diff --git a/bin/createComponent/createComponent.js b/bin/createComponent/createComponent.js index 991fde30..435443cb 100644 --- a/bin/createComponent/createComponent.js +++ b/bin/createComponent/createComponent.js @@ -1,7 +1,8 @@ #!/usr/bin/env node -import inquirer from "inquirer"; +import { input } from "@inquirer/prompts"; import fs from "fs"; import path from "path"; +import process from "process"; import { createStory } from "./createStory.js"; import { createDocs } from "./createDocs.js"; @@ -10,52 +11,62 @@ function isPascalCase(str) { return /^[A-Z][A-Za-z]*$/.test(str); } +// check if name is valid +function validateName(componentName) { + if (!componentName) { + return "Please enter a component name"; + } else if (!isPascalCase(componentName)) { + return "Component name must be in PascalCase"; + } else { + return true; + } +} + +function createFiles(componentName) { + // validate file name + const validated = validateName(componentName); + if (validated !== true) { + return console.error(validated); + } + + // declare dir + const dir = path.join(process.cwd(), "src", "lib", componentName); + + // if directory exists show error, else create files + if (fs.existsSync(dir)) { + console.error("Directory already exists"); + } else { + // create directory + fs.mkdirSync(dir, { recursive: true }); + + // create Component.svelte (blank) + const svelteFilePath = path.join(dir, `${componentName}.svelte`); + fs.writeFileSync(svelteFilePath, "", "utf8"); + + // create Component.docs.md + const docsFilePath = path.join(dir, `${componentName}.docs.md`); + fs.writeFileSync(docsFilePath, createDocs(componentName), "utf8"); + + // create Component.stories.svelte + const storyFilePath = path.join(dir, `${componentName}.stories.svelte`); + fs.writeFileSync(storyFilePath, createStory(componentName), "utf8"); + + // Confirmation text + console.log(`Boilerplate files created in ${dir}`); + } +} + async function main() { - await inquirer - .prompt([ - { - type: "input", - name: "componentName", - message: "What is the name of your component? (ie: MyComponent)", - validate: (componentName) => { - // if not present - if (!componentName) { - return "Please enter a component name"; - // if not PascalCase - } else if (!isPascalCase(componentName)) { - return "Component name must be in PascalCase"; - } else { - return true; - } - } - } - ]) - .then((answers) => { - const { componentName } = answers; - const dir = path.join(process.cwd(), "src", "lib", componentName); - // if directory doesn't exist, create it - if (!fs.existsSync(dir)) { - // create directory - fs.mkdirSync(dir, { recursive: true }); - - // create Component.svelte (blank) - const svelteFilePath = path.join(dir, `${componentName}.svelte`); - fs.writeFileSync(svelteFilePath, "", "utf8"); - - // create Component.docs.md - const docsFilePath = path.join(dir, `${componentName}.docs.md`); - fs.writeFileSync(docsFilePath, createDocs(componentName), "utf8"); - - // create Component.stories.svelte - const storyFilePath = path.join(dir, `${componentName}.stories.svelte`); - fs.writeFileSync(storyFilePath, createStory(componentName), "utf8"); - - // Confirmation text - console.log(`Boilerplate files created in ${dir}`); - } else { - console.error("Directory already exists"); - } - }); + // if there's an argument in the command, use it (but no more) + if (process.argv[2] && !process.argv[3]) { + createFiles(process.argv[2]); + } else { + // show input + await input({ + message: "What is the name of your component? (ie: MyComponent)", + validate: validateName + }).then(createFiles); + } } main().catch(console.error); diff --git a/package-lock.json b/package-lock.json index cc9e194f..6493ff3d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ }, "devDependencies": { "@etchteam/storybook-addon-github-link": "^1.0.1", + "@inquirer/prompts": "^5.3.2", "@storybook/addon-a11y": "^8.0.5", "@storybook/addon-essentials": "^8.0.5", "@storybook/addon-interactions": "^8.0.5", @@ -43,7 +44,6 @@ "@sveltejs/package": "^2.3.0", "concurrently": "^8.2.2", "http-server": "^14.1.1", - "inquirer": "^10.1.2", "prettier": "^3.2.5", "prettier-plugin-svelte": "^3.2.2", "publint": "^0.1.9", @@ -11429,25 +11429,6 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, - "node_modules/inquirer": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-10.1.2.tgz", - "integrity": "sha512-rwoy4e2xFz3rru5Q5695rKXLbNlVfODRhRftBEPdxHfbGzN1T8Fxzszcb//SaRnQHsRdiwR8dOZOV+y4SoZ4KQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/prompts": "^5.3.2", - "@inquirer/type": "^1.5.1", - "@types/mute-stream": "^0.0.4", - "ansi-escapes": "^4.3.2", - "mute-stream": "^1.0.0", - "run-async": "^3.0.0", - "rxjs": "^7.8.1" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/internal-slot": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", @@ -17118,16 +17099,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/run-async": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", - "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", diff --git a/package.json b/package.json index 45cab396..dbd6fdb3 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ }, "devDependencies": { "@etchteam/storybook-addon-github-link": "^1.0.1", + "@inquirer/prompts": "^5.3.2", "@storybook/addon-a11y": "^8.0.5", "@storybook/addon-essentials": "^8.0.5", "@storybook/addon-interactions": "^8.0.5", @@ -73,7 +74,6 @@ "@sveltejs/package": "^2.3.0", "concurrently": "^8.2.2", "http-server": "^14.1.1", - "inquirer": "^10.1.2", "prettier": "^3.2.5", "prettier-plugin-svelte": "^3.2.2", "publint": "^0.1.9",