add-react-fn-component
Version:
Create a react component in your '/src' or '/src/components' directory from the command-line by specifying the components name and HTML element. You can choose to create the component using styled-components boilerplate or an external css importing to the
151 lines (138 loc) • 4.73 kB
JavaScript
import inquirer from "inquirer";
import fs from "node:fs";
import { readFile } from "node:fs/promises";
import process from "node:process";
if (fs.existsSync("./src/components")) {
process.chdir("./src/components");
} else if (fs.existsSync("../src/components")) {
process.chdir("../src/components");
} else if (fs.existsSync("./src")) {
process.chdir("./src");
} else if (fs.existsSync("../src")) {
process.chdir("../src");
} else {
throw new Error(
"Not able to locate a path of ./src, ../src, ./src/components or ../src/components and therefore cannot execute add-react-fn-component script. Please ensure one of the above paths in your project exists before retrying the script"
);
}
const html = JSON.parse(
await readFile(new URL("./html-lib.json", import.meta.url))
);
function validatePascalCase(str) {
if (!str[0].match(/[A-Z]/)) {
throw new Error(
"The first word of your react component does not have a capitalized first letter and therefore is not PascalCase. Please adjust."
);
} else return true;
}
inquirer
.prompt([
{
name: "componentName",
message: "Enter React Component Name: ",
validate: validatePascalCase,
},
{
name: "componentHTML",
type: "input",
message: "Which HTML element will the component return?: ",
default: "div",
},
{
name: "cssOption",
message: "CSS or styled-components?: ",
choices: ["styled-components", "css", "neither"],
type: "list",
suggestOnly: true,
},
])
.then((answers) => {
console.log("answers:", answers);
if (Object.hasOwn(html, answers.componentHTML)) {
if (answers.componentName.length === 0) {
console.log(
"You must specify a component name. Pascal Case is recommended for React components."
);
if (answers.componentHTML.length === 0) {
console.log(
"You must specify a component Type. Standard HTML ONLY!."
);
}
} else {
fs.mkdirSync(answers.componentName);
if (answers.cssOption === "styled-components") {
fs.writeFileSync(
`./${answers.componentName}/${answers.componentName}.jsx`,
`
import styled from 'styled-components';
export default function ${answers.componentName}() {
return (
<Styled${answers.componentName}>
</Styled${answers.componentName}>
);
}
const Styled${answers.componentName} = styled.${answers.componentHTML}\`\`;
`
);
console.log(
`Component ${answers.componentName} created successfully with styled-component boiler-plate!`
);
}
if (answers.cssOption === "css") {
let className = "";
for (let i = 0; i < answers.componentName.length; i++) {
console.log("answers.componentName[i]:", answers.componentName[i]);
// is letter a capital?
if (answers.componentName[i].match(/[A-Z]/)) {
// if 1st char in str, no hyphen, else hyphen
i === 0
? (className += answers.componentName[i])
: (className += "-" + answers.componentName[i]);
} else {
className += answers.componentName[i];
}
}
const finalClassName = className.toLowerCase();
fs.writeFileSync(
`./${answers.componentName}/${answers.componentName}.css`,
`.${finalClassName} {
display: visible;
/* enter css here */
}
`
);
fs.writeFileSync(
`./${answers.componentName}/${answers.componentName}.jsx`,
`import '${answers.componentName}.css';
export default function ${answers.componentName}() {
return (
<${answers.componentName} className="${finalClassName}">
</${answers.componentName}>
);
}
`
);
console.log(
`Component ${answers.componentName} created successfully with css boiler-plate!`
);
}
if (answers.cssOption === "neither") {
fs.writeFileSync(
`./${answers.componentName}/${answers.componentName}.jsx`,
`
export default function ${answers.componentName}() {
return (
<${answers.componentName}>
</${answers.componentName}>
);
}
`
);
}
}
} else
throw new Error(
`the html element you entered: ${answers.componentHTML} is NOT VALID. Please check your spelling`
);
});