create-project-boilerplate
Version:
ES6+ boilerplate to create websites and web apps using tailwind, Babel and Parcel
939 lines (795 loc) • 24.6 kB
JavaScript
#!/usr/bin/env node
// #################################### IMPORTS ####################################
const fs = require("fs");
const execSync = require("child_process").execSync;
// #################################### VARIABLES ####################################
// Variables
let isCliCmdfailed = false;
const INSTALL_LOG = "\x1b[33m%s\x1b[0m";
const SUCCESS_LOG = "\x1b[32m%s\x1b[0m";
const SRC_DIR_PATH = "/src";
const SRC_SCRIPTS_DIR_PATH = SRC_DIR_PATH + "/scripts";
const SRC_STYLES_DIR_PATH = SRC_DIR_PATH + "/styles";
const SRC_INDEX_CSS_FILE_PATH = process.cwd() + SRC_STYLES_DIR_PATH + "/index.css";
const SRC_BASE_CSS_FILE_PATH = process.cwd() + SRC_STYLES_DIR_PATH + "/base.css";
const SRC_MAIN_CSS_FILE_PATH = process.cwd() + SRC_STYLES_DIR_PATH + "/main.css";
const SRC_SCRIPT_FILE_PATH = process.cwd() + SRC_SCRIPTS_DIR_PATH + "/main.js";
const SRC_APP_TEST_FILE_PATH = process.cwd() + SRC_DIR_PATH + "/main.test.js";
const INDEX_HTML_FILE_PATH = process.cwd() + SRC_DIR_PATH + "/index.html";
const PORT = "3000";
const PACKAGE_JSON_FILE_PATH = process.cwd() + "/package.json";
const CREATE_PACKAGE_JSON_DEFAULT = "npm init -y";
const BABELRC_FILE_PATH = process.cwd() + "/.babelrc";
// Babel command
const INSTALL_BABEL =
"npm i -D babel-loader babel-jest @babel/core @babel/cli @babel/plugin-transform-runtime @babel/runtime @babel/runtime-corejs3";
// Parcel command
const INSTALL_PARCEL = "npm i -D parcel @parcel/transformer-sass";
// Sass command
const INSTALL_SASS = "npm i -D sass";
// Tailwindcss command
const INSTALL_TAILWINDCSS = "npm install -D tailwindcss postcss";
const CONFIG_TAILWINDCSS = "npx tailwindcss init";
const TAILWINDCSS_CONFIG_FILE_PATH = process.cwd() + "/tailwind.config.js";
const TAILWINDCSS_CONFIG_FILE_CONTENT = `module.exports = {
content: [
"./src/**/*.{html,js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
`;
// .postcssrc file
const POSTCSSRC_FILE_PATH = process.cwd() + "/.postcssrc";
const POSTCSSRC_FILE_CONTENT = `{
"plugins": {
"tailwindcss": true
}
}
`;
// ESLint command
const INSTALL_ESLINT = "npm install eslint --save-dev";
// Jest command
const INSTALL_JEST = "npm install --save-dev jest";
// Install jsdom
const INSTALL_JSDOM = "npm i --save-dev jest-environment-jsdom"
// testing-library/dom command
const INSTALL_TESTING_LIBRARY_DOM = "npm install --save-dev @testing-library/dom";
// testing-library/jest-dom command
const INSTALL_TESTING_LIBRARY_JEST_DOM = "npm install --save-dev @testing-library/jest-dom";
// Start server command
const START = `parcel src/index.html --open -p ${PORT}`;
// #################################### FILES ####################################
// package.json file
const PACKAGE_JSON_CONTENT = `{
"name": "test",
"version": "1.0.0",
"description": "",
"browserslist": "> 0.5%, last 2 versions, not dead",
"main": "index.js",
"targets": { "main": false },
"scripts": {
"start": "parcel src/index.html -p 3000 --open",
"test": "jest"
},
"keywords": [],
"author": "",
"license": "ISC"
}`
// .babelrc file
const BABELRC_CONTENT = `{
"presets": [],
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"corejs": 3,
"regenerator": true
}
]
]
}
`;
const GITIGNORE_FILE_PATH = process.cwd() + "/.gitignore";
const GITIGNORE_FILE_CONTENT = `node_modules
.parcel-cache
`;
// HTML file
const INDEX_HTML_CONTENT = `<!DOCTYPE html>
<html lang="en">
<head>
<!-- Metadata -->
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- App title -->
<title>Boilerplate app</title>
<!-- Stylesheets -->
<link rel="stylesheet" href="./styles/index.css" />
<link rel="stylesheet" href="./styles/base.css" />
<link rel="stylesheet" href="./styles/main.css" />
<!-- Fontawesome icon library -->
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css"
integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
/>
<!-- General Sans Font - fontshare -->
<link
href="https://api.fontshare.com/v2/css?f[]=general-sans@200,500,300,600,400,700&display=swap"
rel="stylesheet"
/>
<!-- Favicon (Remove default PATH and add favicon PATH in href attribute) -->
<link
rel="shortcut icon"
href="https://i.ibb.co/7YC6F5B/favicon.jpg"
type="image/x-icon"
/>
<!-- Alpine.js CDN -->
<script
defer
src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"
></script>
<!-- Scripts -->
</head>
<body>
<!-- App -->
<div id="root"></div>
<!-- Script files -->
<script type="module" src="./scripts/main.js" defer></script>
</body>
</html>
`;
// CSS files
const INDEX_CSS_STYLES = `@tailwind base;
@tailwind components;
@tailwind utilities;
`;
const BASE_CSS_STYLES = `/* Box sizing rules */
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
/* Remove default margin */
body,
h1,
h2,
h3,
h4,
p,
figure,
blockquote,
dl,
dd {
margin: 0;
}
/* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */
ul[role="list"],
ol[role="list"] {
list-style: none;
}
/* Set core root defaults */
html {
height: 100vh;
width: 100vw;
}
html:focus-within {
scroll-behavior: smooth;
}
/* Set core body defaults */
body {
text-rendering: optimizeSpeed;
font: 400 1rem/1.54 Arial, sans-serif;
height: 100%;
width: 100%;
-webkit-font-smoothing: antialiased;
}
/* A elements that don't have a class get default styles */
a {
color: inherit;
font: inherit;
text-decoration: none;
}
a:not([class]) {
text-decoration-skip-ink: auto;
}
/* Make images easier to work with */
img,
picture {
max-width: 100%;
display: block;
}
/* Inherit fonts for inputs and buttons */
input,
button,
textarea,
select {
font: inherit;
}
/* Remove all animations, transitions and smooth scroll for people that prefer not to see them */
@media (prefers-reduced-motion: reduce) {
html:focus-within {
scroll-behavior: auto;
}
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
`;
const MAIN_CSS_STYLES = `@import url("https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&family=Source+Code+Pro&display=swap");
:root {
--bg-dark: #1e1e1e;
--clr-primary-300: #92e7fc;
--clr-primary-400: #62d9fb;
--clr-primary-500: #2ecefa;
--clr-primary-600: #06bcef;
--off-white: #f4f4f4;
--ff-prim: "Inter", "General Sans", Arial, Helvetica, sans-serif;
--ff-code: "Source Code Pro", monospace;
}
body {
font-family: var(--ff-prim);
}
#root {
background: var(--bg-dark);
color: var(--off-white);
display: flex;
flex-direction: column;
height: 100%;
}
.app {
display: flex;
flex-direction: column;
margin: auto;
}
.app .app__icon {
display: flex;
align-items: baseline;
}
.app__icon .icon__primary {
position: relative;
left: 4.25rem;
}
.app__icon .icon__secondary {
position: relative;
left: -2rem;
top: -16rem;
}
.app__icon .icon__tertiary {
position: relative;
left: -8.5rem;
top: -2rem;
}
.app .app__text {
color: var(--off-white);
font: inherit;
font-size: 1.25rem;
font-weight: 300;
padding-top: 0.25rem;
text-align: center;
}
.app .app__text > code {
font-family: var(--ff-code);
font-weight: 400;
}
.link-wrapper {
background: inherit;
color: inherit;
padding-top: 1.25rem;
}
.app .app__link {
align-items: center;
background: inherit;
color: var(--clr-primary-400);
display: flex;
font-size: 2rem;
gap: 0.6rem;
justify-content: center;
padding: 6px;
transition: color 0.15s ease;
}
.app__link:hover,
.app__link:active {
color: var(--clr-primary-600);
}
.app .app__link .link__icon,
.app .app__link .link__text {
display: flex;
flex-direction: column;
}
.app .app__link .link__icon > *,
.app .app__link .link__text > * {
color: inherit;
margin: auto;
vertical-align: middle;
}
.app__link .link__text {
text-decoration: underline;
}
.app__link span {
font-size: 1.2rem;
font-weight: 400;
}
/* Loading animation styling */
/* Primary */
@keyframes ldio-q9zcyp9hx3l {
0% {
transform: rotate(0deg);
}
50% {
transform: rotate(22.5deg);
}
100% {
transform: rotate(45deg);
}
}
.ldio-q9zcyp9hx3l > div {
transform-origin: 180px 180px;
animation: ldio-q9zcyp9hx3l 0.2s infinite linear;
}
.ldio-q9zcyp9hx3l > div div {
position: absolute;
width: 39.6px;
height: 273.6px;
background: #62d9fb;
left: 180px;
top: 180px;
transform: translate(-50%, -50%);
}
.ldio-q9zcyp9hx3l > div div:nth-child(1) {
width: 216px;
height: 216px;
border-radius: 50%;
}
.ldio-q9zcyp9hx3l > div div:nth-child(6) {
width: 144px;
height: 144px;
background: rgba(NaN, NaN, NaN, 0);
border-radius: 50%;
}
.ldio-q9zcyp9hx3l > div div:nth-child(3) {
transform: translate(-50%, -50%) rotate(45deg);
}
.ldio-q9zcyp9hx3l > div div:nth-child(4) {
transform: translate(-50%, -50%) rotate(90deg);
}
.ldio-q9zcyp9hx3l > div div:nth-child(5) {
transform: translate(-50%, -50%) rotate(135deg);
}
.loadingio-spinner-gear-w89dy36c15 {
width: 360px;
height: 360px;
display: inline-block;
overflow: hidden;
background: none;
}
.ldio-q9zcyp9hx3l {
width: 100%;
height: 100%;
position: relative;
transform: translateZ(0) scale(1);
backface-visibility: hidden;
transform-origin: 0 0;
}
.ldio-q9zcyp9hx3l div {
box-sizing: content-box;
}
/* Secondary */
@keyframes ldio-hzck34v74cs {
0% {
transform: rotate(0deg);
}
50% {
transform: rotate(22.5deg);
}
100% {
transform: rotate(45deg);
}
}
.ldio-hzck34v74cs > div {
transform-origin: 56.00000000000001px 56.00000000000001px;
animation: ldio-hzck34v74cs 0.2s infinite linear;
}
.ldio-hzck34v74cs > div div {
position: absolute;
width: 12.32px;
height: 85.12px;
background: #62d9fb;
left: 56.00000000000001px;
top: 56.00000000000001px;
transform: translate(-50%, -50%);
}
.ldio-hzck34v74cs > div div:nth-child(1) {
width: 67.2px;
height: 67.2px;
border-radius: 50%;
}
.ldio-hzck34v74cs > div div:nth-child(6) {
width: 44.800000000000004px;
height: 44.800000000000004px;
background: rgba(NaN, NaN, NaN, 0);
border-radius: 50%;
}
.ldio-hzck34v74cs > div div:nth-child(3) {
transform: translate(-50%, -50%) rotate(45deg);
}
.ldio-hzck34v74cs > div div:nth-child(4) {
transform: translate(-50%, -50%) rotate(90deg);
}
.ldio-hzck34v74cs > div div:nth-child(5) {
transform: translate(-50%, -50%) rotate(135deg);
}
.loadingio-spinner-gear-i3gj8syr46e {
width: 112px;
height: 112px;
display: inline-block;
overflow: hidden;
background: none;
}
.ldio-hzck34v74cs {
width: 100%;
height: 100%;
position: relative;
transform: translateZ(0) scale(1);
backface-visibility: hidden;
transform-origin: 0 0;
}
.ldio-hzck34v74cs div {
box-sizing: content-box;
}
/* Tertiary */
@keyframes ldio-jz6mqe92nkl {
0% {
transform: rotate(0deg);
}
50% {
transform: rotate(22.5deg);
}
100% {
transform: rotate(45deg);
}
}
.ldio-jz6mqe92nkl > div {
transform-origin: 50px 50px;
animation: ldio-jz6mqe92nkl 0.2s infinite linear;
}
.ldio-jz6mqe92nkl > div div {
position: absolute;
width: 11px;
height: 76px;
background: #62d9fb;
left: 50px;
top: 50px;
transform: translate(-50%, -50%);
}
.ldio-jz6mqe92nkl > div div:nth-child(1) {
width: 60px;
height: 60px;
border-radius: 50%;
}
.ldio-jz6mqe92nkl > div div:nth-child(6) {
width: 40px;
height: 40px;
background: rgba(NaN, NaN, NaN, 0);
border-radius: 50%;
}
.ldio-jz6mqe92nkl > div div:nth-child(3) {
transform: translate(-50%, -50%) rotate(45deg);
}
.ldio-jz6mqe92nkl > div div:nth-child(4) {
transform: translate(-50%, -50%) rotate(90deg);
}
.ldio-jz6mqe92nkl > div div:nth-child(5) {
transform: translate(-50%, -50%) rotate(135deg);
}
.loadingio-spinner-gear-140cq0efhkd {
width: 56px;
height: 56px;
display: inline-block;
overflow: hidden;
background: none;
}
.ldio-jz6mqe92nkl {
width: 100%;
height: 100%;
position: relative;
transform: translateZ(0) scale(0.56);
backface-visibility: hidden;
transform-origin: 0 0;
}
.ldio-jz6mqe92nkl div {
box-sizing: content-box;
}
`;
// Javascript file
const SCRIPT_CONTENT = `"use strict";
const REPO_NAME = "create-project-boilerplate";
const REPO_LINK = "https://github.com/Biswajit-Mukherjee/" + REPO_NAME;
// Root element
const rootElement = document.getElementById("root");
// Create and append app div inside root div
const appElement = document.createElement("div");
appElement.setAttribute("id", "app");
appElement.setAttribute("class", "app");
rootElement.appendChild(appElement);
// Create app div structure
const appIconElement = document.createElement("div");
appIconElement.setAttribute("class", "app__icon");
appElement.appendChild(appIconElement);
// Primary Loader inside app icon div
const primarySpinnerContainerElement = document.createElement("div");
primarySpinnerContainerElement.setAttribute("class", "icon__primary");
appIconElement.appendChild(primarySpinnerContainerElement);
const primarySpinnerOuterLoaderContainerElement = document.createElement("div");
primarySpinnerOuterLoaderContainerElement.setAttribute(
"class",
"loadingio-spinner-gear-w89dy36c15"
);
primarySpinnerContainerElement.appendChild(
primarySpinnerOuterLoaderContainerElement
);
const primarySpinnerInnerLoaderContainerElement = document.createElement("div");
primarySpinnerInnerLoaderContainerElement.setAttribute(
"class",
"ldio-q9zcyp9hx3l"
);
primarySpinnerOuterLoaderContainerElement.appendChild(
primarySpinnerInnerLoaderContainerElement
);
const primarySpinnerInnerLoaderInnerDivList = document.createElement("div");
primarySpinnerInnerLoaderContainerElement.appendChild(
primarySpinnerInnerLoaderInnerDivList
);
for (let i = 0; i < 6; i++) {
const primarySpinnerInnerLoaderInnerDivListItem =
document.createElement("div");
primarySpinnerInnerLoaderInnerDivList.appendChild(
primarySpinnerInnerLoaderInnerDivListItem
);
}
// Secondary Loader inside app icon div
const secondarySpinnerContainerElement = document.createElement("div");
secondarySpinnerContainerElement.setAttribute("class", "icon__secondary");
appIconElement.appendChild(secondarySpinnerContainerElement);
const secondarySpinnerOuterLoaderContainerElement =
document.createElement("div");
secondarySpinnerOuterLoaderContainerElement.setAttribute(
"class",
"loadingio-spinner-gear-i3gj8syr46e"
);
secondarySpinnerContainerElement.appendChild(
secondarySpinnerOuterLoaderContainerElement
);
const secondarySpinnerInnerLoaderContainerElement =
document.createElement("div");
secondarySpinnerInnerLoaderContainerElement.setAttribute(
"class",
"ldio-hzck34v74cs"
);
secondarySpinnerOuterLoaderContainerElement.appendChild(
secondarySpinnerInnerLoaderContainerElement
);
const secondarySpinnerInnerLoaderInnerDivList = document.createElement("div");
secondarySpinnerInnerLoaderContainerElement.appendChild(
secondarySpinnerInnerLoaderInnerDivList
);
for (let i = 0; i < 6; i++) {
const secondarySpinnerInnerLoaderInnerDivListItem =
document.createElement("div");
secondarySpinnerInnerLoaderInnerDivList.appendChild(
secondarySpinnerInnerLoaderInnerDivListItem
);
}
// Tertiary Loader inside app icon div
const tertiarySpinnerContainerElement = document.createElement("div");
tertiarySpinnerContainerElement.setAttribute("class", "icon__tertiary");
appIconElement.appendChild(tertiarySpinnerContainerElement);
const tertiarySpinnerOuterLoaderContainerElement =
document.createElement("div");
tertiarySpinnerOuterLoaderContainerElement.setAttribute(
"class",
"loadingio-spinner-gear-140cq0efhkd"
);
tertiarySpinnerContainerElement.appendChild(
tertiarySpinnerOuterLoaderContainerElement
);
const tertiarySpinnerInnerLoaderContainerElement =
document.createElement("div");
tertiarySpinnerInnerLoaderContainerElement.setAttribute(
"class",
"ldio-jz6mqe92nkl"
);
tertiarySpinnerOuterLoaderContainerElement.appendChild(
tertiarySpinnerInnerLoaderContainerElement
);
const tertiarySpinnerInnerLoaderInnerDivList = document.createElement("div");
tertiarySpinnerInnerLoaderContainerElement.appendChild(
tertiarySpinnerInnerLoaderInnerDivList
);
for (let i = 0; i < 6; i++) {
const tertiarySpinnerInnerLoaderInnerDivListItem =
document.createElement("div");
tertiarySpinnerInnerLoaderInnerDivList.appendChild(
tertiarySpinnerInnerLoaderInnerDivListItem
);
}
// Paragraph element inside app div
const paragraphElement = document.createElement("p");
paragraphElement.setAttribute("class", "app__text");
const paragraphFirstSpanElement = document.createElement("span");
paragraphFirstSpanElement.textContent = "Edit ";
paragraphElement.append(paragraphFirstSpanElement);
const paragraphCodeElement = document.createElement("code");
paragraphCodeElement.innerHTML = "src/index.html";
paragraphElement.append(paragraphCodeElement);
const paragraphSecondSpanElement = document.createElement("span");
paragraphSecondSpanElement.textContent = " and save to see changes";
paragraphElement.append(paragraphSecondSpanElement);
appElement.appendChild(paragraphElement);
// Link elements inside app div
const linkWrapperElement = document.createElement("div");
linkWrapperElement.setAttribute("class", "link-wrapper");
appElement.appendChild(linkWrapperElement);
// Set up anchor element
const anchorLinkElement = document.createElement("a");
anchorLinkElement.setAttribute("class", "app__link");
anchorLinkElement.href = REPO_LINK;
anchorLinkElement.setAttribute("target", "_blank");
linkWrapperElement.appendChild(anchorLinkElement);
// Set anchor link icon
const anchorLinkIconContainerElement = document.createElement("div");
anchorLinkIconContainerElement.setAttribute("class", "link__icon");
anchorLinkElement.appendChild(anchorLinkIconContainerElement);
const anchorLinkIconElement = document.createElement("i");
anchorLinkIconElement.classList.add("fa-brands");
anchorLinkIconElement.classList.add("fa-github");
anchorLinkIconContainerElement.appendChild(anchorLinkIconElement);
// Set up anchor link text
const anchorLinkTextContainerElement = document.createElement("div");
anchorLinkTextContainerElement.setAttribute("class", "link__text");
anchorLinkElement.appendChild(anchorLinkTextContainerElement);
const anchorLinkTextSpanElement = document.createElement("span");
anchorLinkTextSpanElement.textContent = "create-project-boilerplate";
anchorLinkTextContainerElement.appendChild(anchorLinkTextSpanElement);
`;
// const APP_TEST_CONTENT = `import { screen } from '@testing-library/dom';
// test("Check if main text is on screen", () => {
// // Arrange
// // Act
// // Assert
// const mainText = screen.getByText(/create-project-boilerplate/i);
// expect(mainText).toBeInTheDocument();
// });
// `;
// #################################### FUNCTIONS ####################################
// Create directory
const createDir = (dirPath) => {
fs.mkdirSync(process.cwd() + dirPath, { recursive: true }, (error) => {
if (error) {
console.log(error);
} else {
null;
}
});
};
// Create file
const createFile = (filePath, fileContent = "") => {
fs.writeFile(filePath, fileContent, (error) => {
if (error) {
console.log(error);
} else {
null;
}
});
};
// Write to file
const writeToFile = (filePath, fileContent) => {
try {
// file written successfully
fs.writeFileSync(filePath, fileContent);
} catch (err) {
// Log the error
console.error('Error occured while writing to file: ' + err);
}
};
// Execute cli command
const runCliCommand = command => {
if (isCliCmdfailed) {
return;
}
try {
// Run the node/ cli command
execSync(`${command}`, { stdio: 'inherit' });
} catch (e) {
isCliCmdfailed = true;
console.error(`Failed to execute ${command}`, e);
}
};
// #################################### CLI ####################################
// Create & configure package.json
console.log(`${SUCCESS_LOG}`, "\n Generating package.json file... \n");
runCliCommand(CREATE_PACKAGE_JSON_DEFAULT);
writeToFile(PACKAGE_JSON_FILE_PATH, "");
writeToFile(PACKAGE_JSON_FILE_PATH, PACKAGE_JSON_CONTENT);
// Create & configure .gitignore file
console.log(`${SUCCESS_LOG}`, "\n Generating .gitignore file... \n");
createFile(GITIGNORE_FILE_PATH);
writeToFile(GITIGNORE_FILE_PATH, GITIGNORE_FILE_CONTENT);
// Initialize project
console.log("\nCreating project boilerplate. This might take a while.\n");
console.log(`${SUCCESS_LOG}`, "Initializing project...");
// Create src folder
createDir(SRC_DIR_PATH);
// Create src/index.html file
createFile(INDEX_HTML_FILE_PATH);
// Create src/scripts folder
createDir(SRC_SCRIPTS_DIR_PATH);
// Create src/scripts/main.js file
createFile(SRC_SCRIPT_FILE_PATH);
// Create src/styles folder
createDir(SRC_STYLES_DIR_PATH);
// Create src/styles/base.css & main.css files
createFile(SRC_BASE_CSS_FILE_PATH);
createFile(SRC_MAIN_CSS_FILE_PATH);
// Create src/main.test.js file
// createFile(SRC_APP_TEST_FILE_PATH);
// Write to HTML file
writeToFile(INDEX_HTML_FILE_PATH, INDEX_HTML_CONTENT);
// Write to CSS file
writeToFile(SRC_INDEX_CSS_FILE_PATH, INDEX_CSS_STYLES);
writeToFile(SRC_BASE_CSS_FILE_PATH, BASE_CSS_STYLES);
writeToFile(SRC_MAIN_CSS_FILE_PATH, MAIN_CSS_STYLES);
// Write to JS file
writeToFile(SRC_SCRIPT_FILE_PATH, SCRIPT_CONTENT);
// Write to Test file
// writeToFile(SRC_APP_TEST_FILE_PATH, APP_TEST_CONTENT);
// ################################# INSTALL DEPENDENCIES #################################
console.log(`${SUCCESS_LOG}`, "\nInstalling dependencies...\n");
// Install babel
console.log(`${INSTALL_LOG}`, "\nInstalling Babel...\n");
runCliCommand(INSTALL_BABEL);
// Install parcel-bundler
console.log(`${INSTALL_LOG}`, "\nInstalling Parcel...\n");
runCliCommand(INSTALL_PARCEL);
// Install SASS
console.log(`${INSTALL_LOG}`, "\nInstalling SASS...\n");
runCliCommand(INSTALL_SASS);
// Install tailwindcss
console.log(`${INSTALL_LOG}`, "\nInstalling tailwindcss...\n");
runCliCommand(INSTALL_TAILWINDCSS);
runCliCommand(CONFIG_TAILWINDCSS);
writeToFile(POSTCSSRC_FILE_PATH, POSTCSSRC_FILE_CONTENT);
writeToFile(TAILWINDCSS_CONFIG_FILE_PATH, TAILWINDCSS_CONFIG_FILE_CONTENT);
// Install ESLint
console.log(`${INSTALL_LOG}`, "\nInstalling ESLint...\n");
runCliCommand(INSTALL_ESLINT);
// Install Jest
console.log(`${INSTALL_LOG}`, "\nInstalling Jest...\n");
runCliCommand(INSTALL_JEST);
// Install jsdom
console.log(`${INSTALL_LOG}`, "\nInstalling jsdom...\n");
runCliCommand(INSTALL_JSDOM);
// Install testing-library/dom
console.log(`${INSTALL_LOG}`, "\nInstalling DOM Testing Library...\n");
runCliCommand(INSTALL_TESTING_LIBRARY_DOM);
// Install testing-library/jest-dom
console.log(`${INSTALL_LOG}`, "\nInstalling Jest-dom Testing Library...\n");
runCliCommand(INSTALL_TESTING_LIBRARY_JEST_DOM);
// Create & configure .babelrc file
console.log("\nFinishing setup... \n");
createFile(BABELRC_FILE_PATH);
writeToFile(BABELRC_FILE_PATH, BABELRC_CONTENT);
// Setup finished
console.log(`${SUCCESS_LOG}`, "\nAll set! You're good to go...");