Skip to content

Commit

Permalink
Merge pull request #109 from UrbanInstitute/feat-cli-init-component
Browse files Browse the repository at this point in the history
CLI command for initializing component boilerplate
  • Loading branch information
benkates authored Jul 25, 2024
2 parents 156c0b1 + 18b2ce6 commit cf8e5c9
Show file tree
Hide file tree
Showing 8 changed files with 533 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
72 changes: 72 additions & 0 deletions bin/createComponent/createComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env node
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";

// 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);
}

// 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() {
// 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);
8 changes: 8 additions & 0 deletions bin/createComponent/createDocs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export function createDocs(componentName) {
return `Esse ipsum deserunt dolor minim dolore sunt cillum.
\`\`\`js
import { ${componentName} } from "@urbaninstitute/dataviz-components";
\`\`\`
`;
}
32 changes: 32 additions & 0 deletions bin/createComponent/createStory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
export function createStory(componentName) {
return `<script context="module">
import TestingTree from "./TestingTree.svelte";
import docs from "./TestingTree.docs.md?raw";
export const meta = {
title: "Components/TestingTree",
component: TestingTree,
tags: ["autodocs"],
parameters: {
docs: {
description: {
component: docs
}
},
githubLink: {
url: "/TestingTree/TestingTree.svelte"
}
}
};
</script>
<script>
import { Story, Template } from "@storybook/addon-svelte-csf";
</script>
<Template let:args>
<TestingTree {...args} />
</Template>
<Story name="Default" />`;
}
Loading

0 comments on commit cf8e5c9

Please sign in to comment.