diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b7d272c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..79bdb1b --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v18.7.0 diff --git a/README.md b/README.md index b8c62ae..bb70a08 100644 --- a/README.md +++ b/README.md @@ -1,104 +1,31 @@ -#A17 Generator +# A17 Generator -A17 Generator is used to quickly generate an [A17 Boilerplate](https://code.area17.com/a17/fe-boilerplate/tree/master). +A17 Generator is used to quickly install A17 FE libraries. It can: -## Usage - -**Install A17 Generator globally** - - ```shell - $ npm install -g @area17/a17-generator - ``` - -**Go to the root of your project** - - ```shell - $ cd project-root - ``` - -**Initialize the A17 Boilerplate** - - ```shell - # @ ~/project-root - $ a17-generator [project-name] - ``` - -Now you will have a `frontend` folder, a `package.json` file and all the node modules. - -A17 Boilerplate is installed too which can help you to run all your dev tasks through npm script, e.g.: - - ```shell - npm run build - ``` - -For more details, please refer to [A17 Boilerplate](https://code.area17.com/a17/fe-boilerplate/tree/master). - -## Change Log - -**0.1.16** - -Update to latest version of boilerplate and helpers - -**0.1.15** - -Update to latest version of boilerplate - -**0.1.14** - -Update to latest version of boilerplate - -**0.1.13** - -Update to latest version of boilerplate +* generate a `package.json` for you, +* initialise Git, +* set up a Webpack build process, +* add helpful dot files, +* set up linting, +* set up a pre-commit hook, +* generate a `frontend` folder structure, +* generate a `README.md`, +* install a pattern library, -**0.1.12** +Plus, it has ASCII art. -Update to latest version of boilerplate - -**0.1.11** - -Update to latest version of boilerplate - -**0.1.10** - -Update to latest version of node, npm, boilerplate and helpers - -**0.1.9** - -Readme updates - -**0.1.8** - -Update to latest version of boilerplate and helpers - -**0.1.7** - -Update to latest version of boilerplate - -**0.1.6** - -Update to latest version of boilerplate - -**0.1.5** - -Update to latest version of boilerplate - -**0.1.4** - -Publish to npm - -**0.1.3** - -Make install information more clear - -**0.1.2** +## Usage -Add engines property to package.json +Firstly, you'll want to `cd` into a project folder if it already exists, or if not: -**0.1.1** +```shell +$ mkdir project-name && cd project-name +``` -Updated default git packages link +And then run `a17-generator`; -**0.1.0** +```shell +$ npx @area17/a17-generator +``` -The birth of A17 Generator +You may be asked to install `a17-generator`. And then `a17-generator` will then ask you a series of questions and then begin installing and setting up as needed. diff --git a/bin/a17_generator.js b/bin/a17_generator.js index 3f9e74e..d4dd4eb 100755 --- a/bin/a17_generator.js +++ b/bin/a17_generator.js @@ -1,95 +1,68 @@ #!/usr/bin/env node 'use strict'; -const path = require('path'); -const fs = require('fs-extra'); -const chalk = require('chalk'); -const spawn = require('cross-spawn'); -const _ = require('lodash'); -const readlineSync = require('readline-sync'); +import child_process from 'child_process'; +import chalk from 'chalk'; +import path from 'path'; +import readlineSync from 'readline-sync'; -const processArgv = _.toArray(process.argv); -const args = processArgv.slice(2); -const appName = args[0]; - - -// Main install process -console.log(chalk.green('Start to install')); - -console.log(`Creating '${appName}' at ${process.cwd()} \n`); - -console.log(chalk.blue(`[1/3] Create package.json file`)); -writePkgJson(); -console.log(chalk.blue(`[2/3] Install packages(This might take some time)`)); -installPackage(); -console.log(chalk.blue(`[3/3] Generate boilerplate files`)); -init(); - -console.log(chalk.green('Finished, enjoy!')); -// End of install process +import libs from '../src/libs.js'; +import writePkgJson from '../src/writePkgJson.js'; +import applicationOptions from '../src/applicationOptions.js'; +import installPackages from '../src/installPackages.js'; +import copySetupFiles from '../src/copySetupFiles.js'; +import postInstall from '../src/postInstall.js'; +import initialiseGit from '../src/initialiseGit.js'; -// Generate package.json file for the project -function writePkgJson() { - - if(fs.existsSync(path.join(process.cwd(),'package.json'))) { - let answer = readlineSync.question('Existing package.json is found, continue will overwrite, are you sure?(y/n)'); - if(answer !== 'y') { - process.exit(); - } - } - - const packageJson = { - name: appName, - version: '0.1.0', - private: true, - dependencies: { - '@area17/a17-helpers': '^2.0.2', - }, - devDependencies: { - '@area17/a17-boilerplate': '^7.1.3' - }, - scripts: { - 'init': 'a17-bp init' - }, - engines: { - 'node': '>= 10.15.0', - 'npm': '>= 6.4.1' - } - }; - - fs.writeFileSync( - path.join(process.cwd(),'package.json'), - JSON.stringify(packageJson, null, 2) - ); - - console.log(chalk.green('package.json is created')); +const processArgv = [...process.argv]; +const args = processArgv.slice(2); +const maxSteps = 5; +const printStep = (str) => { + console.log(chalk.magenta(`\n[${ currentStep++ }/${ maxSteps }] ${ str }`)); +}; +let currentStep = 1; +let appName = args[0] === undefined ? path.basename(process.cwd()) : args[0]; + +console.clear(); +console.log(` + 17771 /7A + /77777/ /A7/ + /A777777/ A7/ + A77A/A777/ 171 + A777/ /A77A/ 171 + 1777/ /777A 17A + 17777777777777A /7A + /777A1111111A7771 /7A/ + /777A 17771 /77/ + A777/ 7777/ A71 +`); + +printStep('Choose application name'); +console.log(chalk.cyan(`\nIs "${ chalk.white(appName) }" your application name?`)); +if (readlineSync.keyInSelect(['Yes'], null, { cancel: 'No'}) !== 0) { + appName = readlineSync.question('What is your application name? ', { + defaultInput: appName, + }); } -// Install necessary packages (a17-helpers / a17-scripts) -function installPackage() { - let result = spawn.sync('npm', ['install'], {stdio: 'inherit'}); +printStep('First, lets choose application options'); +const installOptions = applicationOptions(); - if(result.status === 1) { - console.log(chalk.red('Exit with an error')); - process.exit(); - } else { - console.log(chalk.green('Packages are successfully installed')); - } -} +console.log(chalk.green(`\nCreating '${ chalk.white(appName) }' at ${process.cwd()}`)); -// Initialize files (using a17-script init function) -function init() { - console.log(`Start to initialize project`); - let result = spawn.sync('npm', ['run','init'], {stdio: 'inherit'}); +printStep('Create package.json file'); +writePkgJson(appName, installOptions); - if(result.status === 1) { - console.log(chalk.red('Exit with an error')); - process.exit(); - } else { - console.log(chalk.green('Files are generated')); - } +if (installOptions.git.init) { + printStep('Initialise Git'); + initialiseGit(installOptions); } +printStep('Install packages (This might take some time)'); +installPackages(installOptions); +printStep('Copy setup files and folders'); +copySetupFiles(installOptions, processArgv, appName); +postInstall(installOptions, appName); diff --git a/core_files/behaviors/application.js b/core_files/behaviors/application.js new file mode 100644 index 0000000..e72ebae --- /dev/null +++ b/core_files/behaviors/application.js @@ -0,0 +1,13 @@ +import { manageBehaviors } from '@area17/a17-behaviors'; +import * as Behaviors from './behaviors'; // Critical behaviors + +window.A17 = window.A17 || {}; // currently namespaced name *is* important + +document.addEventListener('DOMContentLoaded', () => { + // expose manageBehaviors + window.A17.behaviors = manageBehaviors; + // init behaviors! + window.A17.behaviors.init(Behaviors, { + breakpoints: ['sm', 'md', 'lg', 'xl'] // tell this app what your breakpoint names are, in size order, manageBehaviors will read a CSS variable and compare for media scoped behaviors, default is ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'] + }); +}); diff --git a/core_files/behaviors/index.js b/core_files/behaviors/index.js new file mode 100644 index 0000000..8ae0c26 --- /dev/null +++ b/core_files/behaviors/index.js @@ -0,0 +1 @@ +export { default as myBehavior } from './myBehavior'; diff --git a/core_files/behaviors/myBehavior.js b/core_files/behaviors/myBehavior.js new file mode 100644 index 0000000..dc635e8 --- /dev/null +++ b/core_files/behaviors/myBehavior.js @@ -0,0 +1,19 @@ +import { createBehavior } from '@area17/a17-behaviors'; + +const myBehavior = createBehavior('myBehavior', + { + alert(val) { + window.alert('Hello world!'); + } + }, + { + init() { + this.$node.addEventListener('click', this.alert); + }, + destroy() { + this.$node.removeEventListener('click', this.alert); + } + } +); + +export default myBehavior; diff --git a/core_files/dot_files/.editorconfig b/core_files/dot_files/.editorconfig new file mode 100644 index 0000000..b7d272c --- /dev/null +++ b/core_files/dot_files/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/core_files/dot_files/.gitignore b/core_files/dot_files/.gitignore new file mode 100644 index 0000000..3d53a6d --- /dev/null +++ b/core_files/dot_files/.gitignore @@ -0,0 +1,35 @@ +# Node +/vendor/ +node_modules/ +npm-debug.log +yarn-error.log + +# MacOS System +.DS_Store + +# Laravel 4 specific +bootstrap/compiled.php +app/storage/ + +# Laravel 5 & Lumen specific +public/storage +public/hot + +# Laravel 5 & Lumen specific with changed public path +public_html/storage +public_html/hot + +# SCSS +.sass-cache/ +*.css.map +*.sass.map +*.scss.map + +storage/*.key +.env +Homestead.yaml +Homestead.json +/.vagrant +.phpunit.result.cache +/public +/dist diff --git a/core_files/lintconfigs/.eslintignore b/core_files/lintconfigs/.eslintignore new file mode 100644 index 0000000..17ac95a --- /dev/null +++ b/core_files/lintconfigs/.eslintignore @@ -0,0 +1,12 @@ +node_modules +dist +public +storage +vendor +.vagrant +.phpunit.result.cache +.sass-cache +*.css.map +*.sass.map +*.scss.map +.DS_Store diff --git a/core_files/lintconfigs/.eslintrc b/core_files/lintconfigs/.eslintrc new file mode 100644 index 0000000..d560c95 --- /dev/null +++ b/core_files/lintconfigs/.eslintrc @@ -0,0 +1,16 @@ +{ + "root": true, + "env": { + "browser": true, + "node": true + }, + "parserOptions": { + "ecmaVersion": 2018, + "sourceType": "module" + }, + "extends": ["prettier", "plugin:prettier/recommended"], + "plugins": ["prettier"], + "rules": { + "prettier/prettier": "error" + } +} diff --git a/core_files/lintconfigs/.lintstagedrc b/core_files/lintconfigs/.lintstagedrc new file mode 100644 index 0000000..e0cd0ff --- /dev/null +++ b/core_files/lintconfigs/.lintstagedrc @@ -0,0 +1,6 @@ +{ + "*.scss": ["stylelint --syntax=scss", "prettier --list-different"], + "*.css": ["stylelint", "prettier --list-different"], + ".js": ["eslint", "prettier --list-different"], + "*.md": "prettier --list-different" +} diff --git a/core_files/lintconfigs/.prettierignore b/core_files/lintconfigs/.prettierignore new file mode 100644 index 0000000..a3b2509 --- /dev/null +++ b/core_files/lintconfigs/.prettierignore @@ -0,0 +1,18 @@ +node_modules +dist +public +storage +vendor +.vagrant +.phpunit.result.cache +.sass-cache +*.css.map +*.sass.map +*.scss.map +.DS_Store +*.woff2 +*.woff +*.ttf +*.eot +*.otf +*.txt diff --git a/core_files/lintconfigs/.prettierrc b/core_files/lintconfigs/.prettierrc new file mode 100644 index 0000000..f26d081 --- /dev/null +++ b/core_files/lintconfigs/.prettierrc @@ -0,0 +1,6 @@ +{ + "semi": true, + "arrowParens": "always", + "singleQuote": true, + "trailingComma": "none" +} diff --git a/core_files/lintconfigs/.stylelintignore b/core_files/lintconfigs/.stylelintignore new file mode 100644 index 0000000..217622f --- /dev/null +++ b/core_files/lintconfigs/.stylelintignore @@ -0,0 +1,13 @@ +node_modules +dist +public +storage +vendor +.vagrant +.phpunit.result.cache +.sass-cache +*.css.map +*.sass.map +*.scss.map +.DS_Store +html4css.css diff --git a/core_files/lintconfigs/.stylelintrc b/core_files/lintconfigs/.stylelintrc new file mode 100644 index 0000000..666fee0 --- /dev/null +++ b/core_files/lintconfigs/.stylelintrc @@ -0,0 +1,140 @@ +{ + "extends": "stylelint-config-recommended", + "plugins": [ + "stylelint-order", + "stylelint-prettier" + ], + "rules": { + "at-rule-no-unknown": null, + "prettier/prettier": true, + "order/properties-order": [ + "extend", + "content", + "display", + "position", + "z-index", + "top", + "bottom", + "left", + "right", + "flex", + "flex-basis", + "flex-direction", + "flex-flow", + "flex-grow", + "flex-shrink", + "flex-wrap", + "align-content", + "align-items", + "align-self", + "justify-content", + "order", + "float", + "clear", + "width", + "min-width", + "max-width", + "height", + "min-height", + "max-height", + "margin", + "margin-top", + "margin-bottom", + "margin-left", + "margin-right", + "padding", + "padding-top", + "padding-bottom", + "padding-left", + "padding-right", + "border", + "border-top", + "border-bottom", + "border-left", + "border-right", + "border-width", + "border-top-width", + "border-bottom-width", + "border-left-width", + "border-right-width", + "border-style", + "border-top-style", + "border-bottom-style", + "border-left-style", + "border-right-style", + "border-color", + "border-top-color", + "border-bottom-color", + "border-left-color", + "border-right-color", + "border-radius", + "border-top-left-radius", + "border-top-right-radius", + "border-bottom-left-radius", + "border-bottom-right-radius", + "background", + "background-attachment", + "background-color", + "background-image", + "background-repeat", + "background-position", + "background-size", + "color", + "font", + "font-family", + "font-size", + "font-smoothing", + "font-style", + "font-variant", + "font-weight", + "line-height", + "letter-spacing", + "list-style", + "text-align", + "text-decoration", + "text-indent", + "text-overflow", + "text-rendering", + "text-shadow", + "text-transform", + "text-wrap", + "white-space", + "word-spacing", + "border-collapse", + "border-spacing", + "caption-side", + "cursor", + "empty-cells", + "opacity", + "overflow", + "quotes", + "speak", + "table-layout", + "vertical-align", + "visibility", + "pointer-events", + "outline", + "outline-color", + "outline-offset", + "outline-style", + "outline-width", + "box-shadow", + "columns", + "column-gap", + "column-fill", + "column-rule", + "column-span", + "column-count", + "column-width", + "transform", + "transform-box", + "transform-origin", + "transform-style", + "transition", + "transition-delay", + "transition-duration", + "transition-property", + "transition-timing-function" + ], + } +} diff --git a/core_files/scssUtilities/application.scss b/core_files/scssUtilities/application.scss new file mode 100644 index 0000000..3358652 --- /dev/null +++ b/core_files/scssUtilities/application.scss @@ -0,0 +1 @@ +@import '@area17/scss-utilities/a17-scss-utilities'; diff --git a/core_files/scssUtilities/frontend.config.json b/core_files/scssUtilities/frontend.config.json new file mode 100644 index 0000000..261e7f4 --- /dev/null +++ b/core_files/scssUtilities/frontend.config.json @@ -0,0 +1,208 @@ +{ + "structure": { + "breakpoints": { + "xs": "0", + "sm": "544px", + "md": "650px", + "lg": "990px", + "xl": "1300px", + "xxl": "1520px" + }, + "columns": { + "xs": "4", + "sm": "4", + "md": "8", + "lg": "12", + "xl": "12", + "xxl": "12" + }, + "container": { + "xs": "auto", + "sm": "auto", + "md": "auto", + "lg": "auto", + "xl": "auto", + "xxl": "1440px" + }, + "gutters": { + "inner": { + "xs": "10px", + "sm": "15px", + "md": "20px", + "lg": "30px", + "xl": "40px", + "xxl": "40px" + }, + "outer": { + "xs": "20px", + "sm": "30px", + "md": "40px", + "lg": "40px", + "xl": "40px", + "xxl": "0px" + } + } + }, + "spacing": { + "outer-1": { + "xs": 64, + "lg": 96 + }, + "inner-1": { + "xs": 24, + "md": 40, + "lg": 64 + }, + "inner-2": { + "xs": 16, + "md": 24, + "lg": 32 + } + }, + "color": { + "tokens": { + "white": "#fff", + "grey-3": "#f8f8f8", + "grey-5": "#f2f2f2", + "grey-10": "#e6e6e6", + "grey-15": "#d9d9d9", + "grey-54": "#757575", + "grey-90": "#1a1a1a", + "black": "#000", + "blue-01": "#0A152B", + "blue-02": "#001F5C", + "blue-03": "#004F91", + "blue-04": "#313BFB", + "blue-05": "#81EEF3", + "blue-06": "#ADD8E6", + "red-01": "#f00" + }, + "border": { + "primary": "black", + "secondary": "grey-15", + "tertiary": "grey-54", + "code-example-filename": "blue-05" + }, + "text": { + "title": "black", + "primary": "grey-90", + "inverse": "white", + "secondary": "grey-54", + "accent": "blue-03", + "code": "black", + "code-example": "grey-3", + "code-example-filename": "blue-05" + }, + "background": { + "primary": "white", + "header": "grey-10", + "footer": "grey-10", + "banner": "grey-90", + "accent": "blue-03", + "column": "blue-05", + "column-alt": "blue-04", + "code": "grey-10", + "code-example": "grey-90", + "quote": "grey-5" + } + }, + "typography": { + "families": { + "sans": "'SuisseIntl, Helvetica, Arial, sans-serif'", + "serif": "'\"Times New Roman\", Georgia, serif'", + "mono": "'\"Lucida Console\", Courier, monospace'" + }, + "typesets": { + "h1": { + "xs": { + "font-family": "var(--sans)", + "font-weight": "500", + "bold-weight": "500", + "font-size": "32px", + "line-height": "1.2", + "letter-spacing": "-0.02em", + "font-smoothing": "true" + }, + "md": { + "font-size": "36px" + }, + "lg": { + "font-size": "48px" + } + }, + "h2": { + "xs": { + "font-family": "var(--sans)", + "font-weight": "500", + "bold-weight": "500", + "font-size": "20px", + "line-height": "1.2", + "letter-spacing": "-0.02em", + "font-smoothing": "true" + }, + "md": { + "font-size": "24px" + }, + "lg": { + "font-size": "28px" + } + }, + "h3": { + "xs": { + "font-family": "var(--sans)", + "bold-weight": "500", + "font-weight": "500", + "font-size": "16px", + "line-height": "1.2", + "letter-spacing": "-0.02em", + "font-smoothing": "true" + }, + "md": { + "font-size": "20px" + } + }, + "h4": { + "xs": { + "font-family": "var(--sans)", + "bold-weight": "500", + "font-weight": "500", + "font-size": "14px", + "line-height": "1.2", + "letter-spacing": "-0.02em", + "font-smoothing": "true" + }, + "md": { + "font-size": "16px" + } + }, + "body": { + "xs": { + "font-family": "var(--sans)", + "bold-weight": "500", + "font-size": "14px", + "line-height": "1.7", + "font-smoothing": "true" + }, + "md": { + "font-size": "16px" + } + }, + "ui": { + "xs": { + "font-family": "var(--sans)", + "font-size": "12px", + "line-height": 1.2, + "font-weight": 400 + } + }, + "code": { + "xs": { + "font-family": "var(--mono)", + "font-size": "14px", + "line-height": 1.2, + "font-weight": 400 + } + } + } + } +} diff --git a/core_files/tailwindPlugins/_base.css b/core_files/tailwindPlugins/_base.css new file mode 100644 index 0000000..b87fdc9 --- /dev/null +++ b/core_files/tailwindPlugins/_base.css @@ -0,0 +1,11 @@ +/** + * This injects Tailwind's base styles, which is a combination of + * Normalize.css and some additional base styles. + */ +@import 'tailwindcss/base'; + +/** + * Here we add custom base styles, applied after the tailwind-base + * classes + * + */ diff --git a/core_files/tailwindPlugins/_components.css b/core_files/tailwindPlugins/_components.css new file mode 100644 index 0000000..9303551 --- /dev/null +++ b/core_files/tailwindPlugins/_components.css @@ -0,0 +1,18 @@ +/** + * This injects any component classes registered by plugins. + * + */ +@import 'tailwindcss/components'; + +/** + * Here we add custom component classes; stuff we want loaded + * *before* the utilities so that the utilities can still + * override them. + * + */ + + +/** + * Include styles for individual pages + * + */ diff --git a/core_files/tailwindPlugins/_utilities.css b/core_files/tailwindPlugins/_utilities.css new file mode 100644 index 0000000..304d59b --- /dev/null +++ b/core_files/tailwindPlugins/_utilities.css @@ -0,0 +1,17 @@ +/** + * This injects all of Tailwind's utility classes, generated based on your + * config file. + * + */ +@import "tailwindcss/utilities"; + +/** + * Here we add custom utilities + * + */ + + +/** + * Include vendor css. + * + */ diff --git a/core_files/tailwindPlugins/application.css b/core_files/tailwindPlugins/application.css new file mode 100644 index 0000000..d9d4890 --- /dev/null +++ b/core_files/tailwindPlugins/application.css @@ -0,0 +1,8 @@ +/* + * structure from: + * https://nystudio107.com/blog/speeding-up-tailwind-css-builds + * dropped Mike's build times when running webpack's watch +*/ +@import './_base'; +@import './_components'; +@import './_utilities'; diff --git a/core_files/webpack/index.html b/core_files/webpack/index.html new file mode 100644 index 0000000..a46acbf --- /dev/null +++ b/core_files/webpack/index.html @@ -0,0 +1,157 @@ + + + + + + + AREA 17 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+

A17

+
+ +
+ +

This is the default page viewed on initial run of npm run dev after running A17 generator. It contains the HTML from A17 HTML Boilerplate. You will want to configure your application Webpack dev server and delete this HTML. See webpack.config.js.

+
+ + + + +
+ + +
+ + +
+ + + + + + + + diff --git a/core_files/webpack/webpack.config.js b/core_files/webpack/webpack.config.js new file mode 100644 index 0000000..dc3e6b5 --- /dev/null +++ b/core_files/webpack/webpack.config.js @@ -0,0 +1,69 @@ +const path = require('path'); +const webpack = require('webpack'); +const { WebpackManifestPlugin } = require('webpack-manifest-plugin'); +const TerserPlugin = require("terser-webpack-plugin"); +const CopyPlugin = require("copy-webpack-plugin"); +::CSS_REQUIRES:: + +const devMode = process.env.NODE_ENV !== 'production'; + +module.exports = { + mode: devMode ? 'development' : 'production', + devtool: devMode ? 'inline-source-map' : false, + entry: { + 'js/application': './::FOLDER_PREFIX::frontend/js/application.js', + ::CSS_ENTRY:: + }, + output: { + filename: devMode ? '[name].js' : '[name].[contenthash].js', + chunkFilename: devMode ? 'js/[id].js' : 'js/[id].[contenthash].js', + path: path.resolve(__dirname, 'public/assets/'), + clean: true, + //publicPath: '/', + }, + optimization: { + minimize: !devMode, + minimizer: [ + new TerserPlugin(), + ::CSS_MINIMIZER:: + ] + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env.MODE': JSON.stringify(devMode ? 'development' : 'production') + }), + new WebpackManifestPlugin({ + fileName: 'manifest.json', + basePath: '/', + publicPath: '/' + }), + new CopyPlugin({ + patterns: [ + { + from: './::FOLDER_PREFIX::frontend/fonts/*.*', + to: './public/assets/fonts/[name][ext]', + noErrorOnMissing: true, + }, + ], + }), + ::CSS_PLUGINS:: + ], + module: { + rules: [ + ::CSS_MODULES:: + ] + }, + devServer: { + port: 3000, + open: false, + hot: false, + compress: true, + // proxy: { + // '/': 'APP_URL', + // }, + // devMiddleware: { + // publicPath: '/', + // }, + //watchFiles: ['./public/*.html'], + }, +}; diff --git a/package-lock.json b/package-lock.json index 5d31a67..f9700d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,150 +1,132 @@ { - "name": "a17-generator", - "version": "0.1.16", - "lockfileVersion": 1, + "name": "@area17/a17-generator", + "version": "1.0.0", + "lockfileVersion": 2, "requires": true, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=", - "requires": { - "color-convert": "1.9.0" + "packages": { + "": { + "name": "@area17/a17-generator", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "chalk": "^5.0.1", + "figlet": "^1.5.2", + "fs-extra": "^10.1.0", + "readline-sync": "^1.4.10" + }, + "bin": { + "a17-generator": "bin/a17_generator.js" } }, - "chalk": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", - "integrity": "sha1-rFvs8U+iG5nGySynp9fP1bF+dD4=", - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.4.0" + "node_modules/chalk": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", + "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "color-convert": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", - "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", - "requires": { - "color-name": "1.1.3" + "node_modules/figlet": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.5.2.tgz", + "integrity": "sha512-WOn21V8AhyE1QqVfPIVxe3tupJacq1xGkPTB4iagT6o+P2cAgEOOwIxMftr4+ZCTI6d551ij9j61DFr0nsP2uQ==", + "engines": { + "node": ">= 0.4.0" } }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "requires": { - "lru-cache": "4.1.1", - "shebang-command": "1.2.0", - "which": "1.3.0" + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" } }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "fs-extra": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", - "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", - "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "4.0.0", - "universalify": "0.1.1" + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + "node_modules/readline-sync": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", + "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==", + "engines": { + "node": ">= 0.8.0" + } }, - "isexe": { + "node_modules/universalify": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "4.1.11" + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" } + } + }, + "dependencies": { + "chalk": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", + "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==" }, - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + "figlet": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.5.2.tgz", + "integrity": "sha512-WOn21V8AhyE1QqVfPIVxe3tupJacq1xGkPTB4iagT6o+P2cAgEOOwIxMftr4+ZCTI6d551ij9j61DFr0nsP2uQ==" }, - "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=", + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" } }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, - "readline-sync": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.7.tgz", - "integrity": "sha1-ABv91MBhEMPAhMY798alYCIhPzA=" + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "requires": { - "shebang-regex": "1.0.0" + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" } }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" - }, - "supports-color": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha1-iD992rwWUUKyphQn8zUt7RldGj4=", - "requires": { - "has-flag": "2.0.0" - } + "readline-sync": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", + "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==" }, "universalify": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", - "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" - }, - "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", - "requires": { - "isexe": "2.0.0" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" } } } diff --git a/package.json b/package.json index aba7dca..6cbea48 100644 --- a/package.json +++ b/package.json @@ -1,24 +1,21 @@ { "name": "@area17/a17-generator", - "version": "0.1.16", + "version": "1.0.0", "description": "The generator of A17 Bolierplate", + "author": "A17 (https://area17.com/)", + "license": "MIT", + "type": "module", "bin": { "a17-generator": "bin/a17_generator.js" }, - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, "repository": { "type": "git", "url": "https://code.area17.com/a17/a17-generator" }, - "author": "A17 (https://area17.com/)", - "license": "MIT", "dependencies": { - "chalk": "^2.1.0", - "cross-spawn": "^5.1.0", - "fs-extra": "^4.0.2", - "lodash": "^4.17.4", - "readline-sync": "^1.4.7" + "chalk": "^5.0.1", + "figlet": "^1.5.2", + "fs-extra": "^10.1.0", + "readline-sync": "^1.4.10" } } diff --git a/src/applicationOptions.js b/src/applicationOptions.js new file mode 100644 index 0000000..6d28ea7 --- /dev/null +++ b/src/applicationOptions.js @@ -0,0 +1,160 @@ +import fs from 'fs-extra'; +import chalk from 'chalk'; +import readlineSync from 'readline-sync'; + +import libs from './libs.js'; + +const applicationOptions = () => { + + const opts = { + styling: -1, + scripting: -1, + jsHelpers: false, + patternLibrary: -1, + dotFiles: false, + lintFiles: false, + git: { + init: false, + origin: null, + }, + installing: { + behaviors: false, + scssUtilities: false, + folderStructure: false, + tailwindPlugins: false, + vue: false, + webpack: false, + linters: false, + laravel: false, + preCommitHook: false, + }, + }; + + if (!fs.existsSync('.git')) { + console.log(chalk.cyan(`\nInitialise Git?`)); + opts.git.init = readlineSync.keyInSelect(['Yes'], null, { cancel: 'No'}); + opts.git.init = opts.git.init === 0; + console.log(chalk.gray(`${ opts.git.init ? 'Initialise Git' : 'Don\'t initialise Git' }`)); + + if (opts.git.init) { + console.log(chalk.cyan(`\nDo you have your Git remote URL?`)); + if (readlineSync.keyInSelect(['Yes'], null, { cancel: 'No'}) === 0) { + opts.git.origin = readlineSync.question('What is your Git remote URL? $ '); + } else { + console.log(chalk.gray(`No Git remote URL specified - will need manually setting later`)); + } + } + } + + console.log(chalk.cyan(`\nApplication styling with:`)); + opts.styling = readlineSync.keyInSelect(libs.styling.map(type => type.name), null, + { cancel: 'None' } + ); + if (opts.styling > -1) { + console.log(chalk.gray(`${ libs.styling[opts.styling].name } selected`)); + } else { + console.log(chalk.gray(`No styling selected`)); + } + + opts.installing.scssUtilities = opts.styling > -1 && libs.styling[opts.styling].name.indexOf('SCSS') > -1; + opts.installing.tailwindPlugins = opts.styling > -1 && libs.styling[opts.styling].name.indexOf('Tailwind') > -1; + + console.log(chalk.cyan(`\nApplication JavaScript with:`)); + opts.scripting = readlineSync.keyInSelect(libs.scripting.map(type => type.name), null, + { cancel: 'None' } + ); + if (opts.scripting > -1) { + console.log(chalk.gray(`${ libs.scripting[opts.scripting].name } selected`)); + } else { + console.log(chalk.gray(`No scripting selected`)); + } + + opts.installing.behaviors = opts.scripting > -1 && libs.scripting[opts.scripting].name.indexOf('Behaviors') > -1; + opts.installing.vue = opts.scripting > -1 && libs.scripting[opts.scripting].name.indexOf('Vue') > -1; + + if (opts.scripting === -1 || !opts.installing.behaviors) { + console.log(chalk.cyan(`\nInclude A17 JS Helpers:`)); + opts.jsHelpers = readlineSync.keyInSelect(['Yes'], null, { cancel: 'No'}); + opts.jsHelpers = opts.jsHelpers === 0; + console.log(chalk.gray(`${ opts.jsHelpers ? 'Install A17 JS Helpers' : 'Don\'t install A17 JS Helpers' }`)); + } + + console.log(chalk.cyan(`\nPattern Library:`)); + opts.patternLibrary = readlineSync.keyInSelect(libs.patternLibraries.map(type => type.name), null, + { cancel: 'None' } + ); + if (opts.patternLibrary > -1) { + console.log(chalk.gray(`${ libs.scripting[opts.patternLibrary].name } selected`)); + } else { + console.log(chalk.gray(`No Pattern Library selected`)); + } + + if (!opts.installing.vue) { + console.log(chalk.cyan(`\nAdd basic webpack setup?`)); + console.log(chalk.gray(`(will also add a default 'frontend' folder)`)); + opts.installing.webpack = readlineSync.keyInSelect(['Yes'], null, { cancel: 'No'}); + opts.installing.webpack = opts.installing.webpack === 0; + console.log(chalk.gray(`${ opts.installing.webpack ? 'Add Webpack' : 'Don\'t add Webpack' }`)); + + if (opts.installing.webpack) { + opts.installing.folderStructure = true; + } else { + console.log(chalk.cyan(`\nAdd default 'frontend' folder?`)); + console.log(chalk.gray(`eg: /frontend/, /frontend/fonts/, /frontend/js/`)); + opts.installing.folderStructure = readlineSync.keyInSelect(['Yes'], null, { cancel: 'No'}); + opts.installing.folderStructure = opts.installing.folderStructure === 0; + console.log(chalk.gray(`${ opts.installing.folderStructure ? 'Add folder structure' : 'Don\'t add folder structure' }`)); + } + + if (opts.installing.folderStructure) { + console.log(chalk.cyan(`\nIs this a Laravel app?`)); + console.log(chalk.gray(`eg: a Twill PHP app`)); + opts.installing.laravel = readlineSync.keyInSelect(['Yes'], null, { cancel: 'No'}); + opts.installing.laravel = opts.installing.laravel === 0; + console.log(chalk.gray(`${ opts.installing.laravel ? 'Is a Laravel app' : 'Is not a Laravel app' }`)); + } + + console.log(chalk.cyan(`\nAdd dot files?`)); + console.log(chalk.gray(`.editorconfig, .gitignore`)); + opts.dotFiles = readlineSync.keyInSelect(['Yes'], null, { cancel: 'No'}); + opts.dotFiles = opts.dotFiles === 0; + console.log(chalk.gray(`${ opts.dotFiles? 'Add dot files' : 'Don\'t add dot files' }`)); + + console.log(chalk.cyan(`\nAdd lint setup dot files?`)); + console.log(chalk.gray(`.lintstagedrc, .eslintrc, .prettierrc and .stylelintrc`)); + opts.lintFiles = readlineSync.keyInSelect(['Yes'], null, { cancel: 'No'}); + opts.lintFiles = opts.lintFiles === 0; + console.log(chalk.gray(`${ opts.lintFiles ? 'Add lint setup dot files' : 'Don\'t add lint setup dot files' }`)); + + if (opts.lintFiles) { + console.log(chalk.cyan(`\nAdd lint tasks?`)); + console.log(chalk.gray(`Installs lintstaged, eslint, prettier and stylelint`)); + opts.installing.linters = readlineSync.keyInSelect(['Yes'], null, { cancel: 'No'}); + opts.installing.linters = opts.installing.linters === 0; + console.log(chalk.gray(`${ opts.installing.linters ? 'Add lint tasks' : 'Don\'t add lint tasks' }`)); + } + + if (opts.installing.linters) { + console.log(chalk.cyan(`\nAdd pre-commit hook to lint staged files?`)); + console.log(chalk.gray(`Installs Husky and sets a pre-commit hook`)); + opts.installing.preCommitHook = readlineSync.keyInSelect(['Yes'], null, { cancel: 'No'}); + opts.installing.preCommitHook = opts.installing.preCommitHook === 0; + console.log(chalk.gray(`${ opts.installing.preCommitHook ? 'Add pre-commit hook' : 'Don\'t add pre-commit hook' }`)); + } + + console.log(chalk.cyan(`\nAdd README.md?`)); + opts.readme = readlineSync.keyInSelect(['Yes'], null, { cancel: 'No'}); + opts.readme = opts.readme === 0; + console.log(chalk.gray(`${ opts.readme ? 'Add README.md' : 'Don\'t add README.md' }`)); + + console.log(chalk.cyan(`\nAdd .nvmrc?`)); + console.log(chalk.gray(`Sets to current node version`)); + opts.nvmrc = readlineSync.keyInSelect(['Yes'], null, { cancel: 'No'}); + opts.nvmrc = opts.nvmrc === 0; + console.log(chalk.gray(`${ opts.nvmrc ? 'Add .nvmrc' : 'Don\'t add .nvmrc' }`)); + } + + return opts; +}; + +export default applicationOptions; diff --git a/src/copySetupFiles.js b/src/copySetupFiles.js new file mode 100644 index 0000000..88af4e2 --- /dev/null +++ b/src/copySetupFiles.js @@ -0,0 +1,158 @@ +import child_process from 'child_process'; +import chalk from 'chalk'; +import fs from 'fs-extra'; +import path from 'path'; + +import runCommand from './runCommand.js'; +import generateWebpackConfig from './generateWebpackConfig.js'; +import generateReadme from './generateReadme.js'; +import libs from './libs.js'; + +const copyFile = (filePath, targetPath = './') => { + const fileName = path.basename(filePath); + console.log(chalk.gray(`Copying ${ fileName }`)); + try { + if (fs.existsSync(filePath)) { + fs.copyFileSync(filePath, path.resolve(targetPath, fileName)); + } else { + console.log(`Error: ${ filePath } doesn't exist`); + } + } catch(err) { + console.log(`Error copying ${ filePath }`); + console.error(err); + } +}; + + +const copySetupFiles = (opts, processArgv, appName) => { + const folderStructurePrefix = opts.installing.laravel ? 'resources/' : ''; + + if (opts.installing.folderStructure) { + console.log(chalk.yellow(`Generating frontend folder structure`)); + if (opts.installing.laravel) { + fs.mkdirSync(path.resolve(process.cwd(), 'resources')); + } + fs.mkdirSync(path.resolve(process.cwd(), `${ folderStructurePrefix }frontend`)); + fs.mkdirSync(path.resolve(process.cwd(), `${ folderStructurePrefix }frontend/fonts`)); + fs.mkdirSync(path.resolve(process.cwd(), `${ folderStructurePrefix }frontend/js`)); + + if (opts.installing.scssUtilities) { + fs.mkdirSync(path.resolve(process.cwd(), `${ folderStructurePrefix }frontend/scss`)); + } + + if (opts.installing.tailwindPlugins) { + fs.mkdirSync(path.resolve(process.cwd(), `${ folderStructurePrefix }frontend/css`)); + } + + if (opts.installing.behaviors) { + console.log(chalk.yellow(`Generating A17-behaviors file and folder structure`)); + fs.mkdirSync(path.resolve(process.cwd(), `${ folderStructurePrefix }frontend/js/behaviors`)); + fs.mkdirSync(path.resolve(process.cwd(), `${ folderStructurePrefix }frontend/js/helpers`)); + copyFile(path.resolve(processArgv[1], '../../core_files/behaviors/application.js'), `${ folderStructurePrefix }frontend/js/`); + copyFile(path.resolve(processArgv[1], '../../core_files/behaviors/index.js'), `${ folderStructurePrefix }frontend/js/behaviors`); + copyFile(path.resolve(processArgv[1], '../../core_files/behaviors/myBehavior.js'), `${ folderStructurePrefix }frontend/js/behaviors`); + } + } + + if (opts.installing.webpack) { + console.log(chalk.yellow(`Setting up Webpack`)); + console.log(chalk.gray(`Generating Webpack config file`)); + const webpackConfig = generateWebpackConfig(opts, processArgv); + console.log(chalk.gray(`Writing Webpack config file`)); + fs.writeFileSync(path.resolve(process.cwd(), 'webpack.config.js'), webpackConfig, { encoding: "utf8" }); + + console.log(chalk.gray(`Set up default index file`)); + fs.mkdirSync(path.resolve(process.cwd(), 'public')); + copyFile(path.resolve(processArgv[1], '../../core_files/webpack/index.html'), 'public'); + + if (!opts.installing.behaviors) { + console.log(chalk.gray(`Generating empty application.js`)); + fs.ensureFileSync(path.resolve(process.cwd(), `${ folderStructurePrefix }frontend/js/application.js`)); + } + + if (opts.installing.scssUtilities) { + copyFile(path.resolve(processArgv[1], '../../core_files/scssUtilities/frontend.config.json'), `${ folderStructurePrefix }frontend`); + } + } + + if (opts.nvmrc) { + if(!fs.existsSync(path.join(process.cwd(),'.nvmrc'))) { + console.log(chalk.yellow(`Generating .nvmrc file`)); + runCommand('node -v > .nvmrc'); + } else { + console.log(chalk.gray(`.nvmrc file already exists, skipping generation`)); + } + } + + if (opts.dotFiles) { + try { + fs.copySync(path.resolve(processArgv[1], '../../core_files/dot_files'), process.cwd(), { overwrite: false }) + console.log(chalk.yellow(`dot files added`)); + } catch (err) { + console.log(chalk.red(`Adding dot files failed`)); + console.error(err); + } + } + + if (opts.lintFiles) { + try { + fs.copySync(path.resolve(processArgv[1], '../../core_files/lintconfigs'), process.cwd(), { overwrite: false }) + console.log(chalk.yellow(`Lint setup dot files added`)); + } catch (err) { + console.log(chalk.red(`Adding lint setup dot files failed`)); + console.error(err); + } + } + + if (opts.installing.preCommitHook) { + if (fs.existsSync('.git')) { + console.log(chalk.yellow(`Set up pre-commit hook (Husky)`)); + runCommand(`npx Husky install`); + if (fs.existsSync('package.json')) { + console.log(chalk.gray(`add Husky prepare script to package.json`)); + runCommand(`npx pkg set scripts.prepare "husky install"`); + } else { + console.log(chalk.gray(`warn user no package.json - will need to manually add Husky prepare script`)); + } + runCommand(`npx husky add .husky/pre-commit "npm run lint:staged"`); + console.log(chalk.gray(`pre-commit hook added`)); + runCommand(`git add .husky/pre-commit`); + runCommand(`git commit -m "adds husky pre-commit hook"`); + console.log(chalk.gray(`Committing .husky/pre-commit`)); + } else { + console.log(chalk.gray(`warn user git not initiated - will need to set up Husky`)); + } + } + + if (opts.readme) { + console.log(chalk.yellow(`Generating README.md`)); + const readme = generateReadme(opts, process, appName); + console.log(chalk.gray(`Writing README.md`)); + fs.writeFileSync(path.resolve(process.cwd(), 'README.md'), readme, { encoding: "utf8" }); + } + + if (opts.styling > -1) { + const selectedStyling = libs.styling[opts.styling]; + if (selectedStyling.files && selectedStyling.files.length) { + console.log(chalk.yellow(`Copy ${ selectedStyling.name } set up files`)); + const targetPath = opts.installing.folderStructure ? `${ folderStructurePrefix }frontend` : null; + selectedStyling.files.forEach(file => { + copyFile(file, targetPath); + }); + } + + if (opts.installing.scssUtilities) { + console.log(chalk.gray(`Adding an application.scss file`)); + fs.ensureDirSync(`${ folderStructurePrefix }frontend/scss`); + copyFile(path.resolve(processArgv[1], '../../core_files/scssUtilities/application.scss'), `${ folderStructurePrefix }frontend/scss`); + } + + if (opts.installing.tailwindPlugins) { + console.log(chalk.gray(`Adding an application.css file`)); + fs.copySync(path.resolve(processArgv[1], '../../core_files/tailwindPlugins'), `${ folderStructurePrefix }frontend/css`, { overwrite: false }) + } + } + +}; + +export default copySetupFiles; diff --git a/src/generateReadme.js b/src/generateReadme.js new file mode 100644 index 0000000..306683d --- /dev/null +++ b/src/generateReadme.js @@ -0,0 +1,70 @@ +const generateReadme = (opts, process, appName) => { + const nodeVersion = process.versions.node; + let readme = `# ${ appName }`; + + if (opts.installing.webpack) { + readme += `\n +## Front End Setup + +Requires Node v${ nodeVersion } + +* Run \`npm install\` from the project root +* Compile assets using \`npm run build\` +* For local development with file watching, use \`npm run watch\` +* For local development with live reloading, use \`npm run dev\` and open \`http://localhost:3000/\` in a browser +* For production, run \`npm run prod\` for a minified output`; + + if (opts.lintFiles && opts.installing.linters) { + readme += `\n +## Linting + +* \`npm run lint\` runs linters on changed files only +* \`npm run lint:staged\` runs linters on staged files only +* \`npm run lint:all\` runs linters on all files + +* \`npm run eslint\` runs eslint on changed files only +* \`npm run prettier\` runs prettier on changed files only +* \`npm run stylelint\` runs stylelint on changed files only + +* \`npm run eslint:all\` runs eslint on all files +* \`npm run prettier:all\` runs prettier on all files +* \`npm run stylelint:all\` runs stylelint on all files`; + } + + if (opts.installing.scssUtilities) { + readme += `\n +## CSS + +Styling is done using Tailwind CSS. See \`tailwind.config.js\` for the Tailwind configuration and \`frontend.config.json\` for front end token configuration. + +* A17 Tailwind Plugins documentation: http://tailwind-plugins.dev.area17.com/`; + } + + if (opts.installing.tailwindPlugins) { + readme += `\n +## CSS + +Styling is done using SCSS and A17 SCSS Utilities. See \`frontend.config.json\` for front end token configuration. + +* A17 SCSS Utilities documentation: http://scss-utilities.dev.area17.com/`; + } + + if (opts.installing.behaviors) { + readme += `\n +## JavaScript + +JavaScript uses A17 Behaviors and vanilla JavaScript. + +* A17 Behaviors documentation: https://github.com/area17/a17-behaviors/wiki`; + + if (opts.jsHelpers) { + readme += ` +* A17 JS Helpers documentation: https://github.com/area17/js-helpers/wiki`; + } + } + } + + return readme; +} + +export default generateReadme; diff --git a/src/generateWebpackConfig.js b/src/generateWebpackConfig.js new file mode 100644 index 0000000..3d8aaa1 --- /dev/null +++ b/src/generateWebpackConfig.js @@ -0,0 +1,112 @@ +import chalk from 'chalk'; +import fs from 'fs-extra'; +import path from 'path'; + +const generateWebpackConfig = (opts, processArgv) => { + const folderStructurePrefix = opts.installing.laravel ? 'resources/' : ''; + let webpackConfig = fs.readFileSync(path.resolve(processArgv[1], '../../core_files/webpack/webpack.config.js'), { encoding:'utf8' } ); + + webpackConfig = webpackConfig.replace(/::FOLDER_PREFIX::/ig, folderStructurePrefix); + + console.log(chalk.gray(`Update Webpack config options`)); + if (opts.installing.scssUtilities) { + webpackConfig = webpackConfig.replace(/(?:\r\n|\r|\n)::CSS_REQUIRES::/, `\nconst CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const FixStyleOnlyEntriesPlugin = require('webpack-fix-style-only-entries'); +const DartScss = require('sass');`); + webpackConfig = webpackConfig.replace(/(?:\r\n|\r|\n) ::CSS_ENTRY::/, `\n 'css/application': './${ folderStructurePrefix }frontend/scss/application.scss',`); + webpackConfig = webpackConfig.replace(/(?:\r\n|\r|\n) ::CSS_MINIMIZER::/, `\n new CssMinimizerPlugin({ + minimizerOptions: { + preset: [ + 'default', + { + discardComments: { removeAll: !devMode }, + }, + ], + }, + minify: CssMinimizerPlugin.cssoMinify, + }),`); + webpackConfig = webpackConfig.replace(/(?:\r\n|\r|\n) ::CSS_PLUGINS::/, `\n new FixStyleOnlyEntriesPlugin(), + new MiniCssExtractPlugin({ + filename: devMode ? '[name].css' : '[name].[contenthash].css', + }),`); + webpackConfig = webpackConfig.replace(/(?:\r\n|\r|\n) ::CSS_MODULES::/, `\n { + test: /\.s[ac]ss$/i, + use: [ + MiniCssExtractPlugin.loader, + 'css-loader', + { + loader: 'sass-loader', + options: { + implementation: DartScss + } + }, + { + loader: "@epegzz/sass-vars-loader", + options: { + syntax: 'scss', + files: [ + path.resolve(__dirname, '${ folderStructurePrefix }frontend', 'frontend.config.json') + ] + } + }, + ], + },`); + } else if (opts.installing.tailwindPlugins) { + webpackConfig = webpackConfig.replace(/(?:\r\n|\r|\n)::CSS_REQUIRES::/, `\nconst MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const CssMinimizerPlugin = require('css-minimizer-webpack-plugin'); +const FixStyleOnlyEntriesPlugin = require('webpack-fix-style-only-entries');`); + webpackConfig = webpackConfig.replace(/(?:\r\n|\r|\n) ::CSS_ENTRY::/, `\n 'css/application': './${ folderStructurePrefix }frontend/css/application.css',`); + webpackConfig = webpackConfig.replace(/(?:\r\n|\r|\n) ::CSS_MINIMIZER::/, `\n new CssMinimizerPlugin({ + minimizerOptions: { + preset: [ + 'default', + { + discardComments: { removeAll: !devMode }, + }, + ], + }, + minify: CssMinimizerPlugin.cssoMinify, + }),`); + webpackConfig = webpackConfig.replace(/(?:\r\n|\r|\n) ::CSS_PLUGINS::/, `\n new FixStyleOnlyEntriesPlugin(), + new MiniCssExtractPlugin({ + filename: devMode ? '[name].css' : '[name].[contenthash].css', + }),`); + webpackConfig = webpackConfig.replace(/(?:\r\n|\r|\n) ::CSS_MODULES::/, `\n { + test: /application\.css$/, + use: [ + { + loader: MiniCssExtractPlugin.loader, + }, + { + loader: 'css-loader', + options: { + importLoaders: 1, + } + }, + { + loader: 'postcss-loader', + options: { + postcssOptions: { + plugins: [ + require('postcss-import'), + require('tailwindcss')('./${ folderStructurePrefix }frontend/tailwind.config.js'), + require("autoprefixer"), + ] + } + } + } + ] + },`); + } else { + webpackConfig = webpackConfig.replace(/(?:\r\n|\r|\n)::CSS_REQUIRES::/, ''); + webpackConfig = webpackConfig.replace(/(?:\r\n|\r|\n) ::CSS_ENTRY::/, ''); + webpackConfig = webpackConfig.replace(/(?:\r\n|\r|\n) ::CSS_MINIMIZER::/, ''); + webpackConfig = webpackConfig.replace(/(?:\r\n|\r|\n) ::CSS_PLUGINS::/, ''); + webpackConfig = webpackConfig.replace(/(?:\r\n|\r|\n) ::CSS_MODULES::/, ''); + } + + return webpackConfig; +}; + +export default generateWebpackConfig; diff --git a/src/initialiseGit.js b/src/initialiseGit.js new file mode 100644 index 0000000..0010b51 --- /dev/null +++ b/src/initialiseGit.js @@ -0,0 +1,17 @@ +import chalk from 'chalk'; + +import runCommand from './runCommand.js'; + +const initialiseGit = (opts) => { + runCommand('git init --initial-branch=main'); + + if (opts.git.origin && opts.git.origin !== '') { + let origin = opts.git.origin.replace('git clone', ''); + console.log(chalk.yellow(`Setting remote origin to ${ origin }`)); + runCommand(`git remote add origin ${ origin }`); + } + + console.log(chalk.yellow(`Git initialised`)); +}; + +export default initialiseGit; diff --git a/src/installPackages.js b/src/installPackages.js new file mode 100644 index 0000000..7bcea09 --- /dev/null +++ b/src/installPackages.js @@ -0,0 +1,82 @@ +import child_process from 'child_process'; +import chalk from 'chalk'; +import fs from 'fs-extra'; +import path from 'path'; + +import runCommand from './runCommand.js'; +import libs from './libs.js'; + +const installPackage = (cmd) => { + if (typeof cmd === 'string') { + runCommand(cmd); + return; + } + + if (Array.isArray(cmd)) { + cmd.forEach(command => { + runCommand(command); + }); + return; + } + + console.log(chalk.red(`Unknown command ${ cmd } - type ${ typeof cmd }`)); +}; + +function installPackages(opts) { + // install scripting first because VUE will want to overrite the dir + if (opts.scripting > -1) { + const selectedScripting = libs.scripting[opts.scripting]; + console.log(chalk.yellow(`Installing ${ selectedScripting.name }`)); + installPackage(selectedScripting.cmd); + } + + if (opts.jsHelpers) { + console.log(chalk.yellow(`Installing ${ libs.jsHelpers.name }`)); + installPackage(libs.jsHelpers.cmd); + } + + if (opts.styling > -1) { + const selectedStyling = libs.styling[opts.styling]; + console.log(chalk.yellow(`Installing ${ selectedStyling.name }`)); + installPackage(selectedStyling.cmd); + } + + if (opts.patternLibrary > -1) { + const selectedPatternLibrary = libs.patternLibraries[opts.patternLibrary]; + console.log(chalk.yellow(`Installing ${ selectedPatternLibrary.name }`)); + installPackage(selectedPatternLibrary.cmd); + } + + if (opts.installing.webpack) { + console.log(chalk.yellow(`Installing Webpack`)); + runCommand('npm install webpack webpack-cli webpack-dev-server webpack-watch-files-plugin copy-webpack-plugin terser-webpack-plugin webpack-manifest-plugin'); + + if (opts.installing.scssUtilities) { + runCommand('npm install @epegzz/sass-vars-loader mini-css-extract-plugin sass css-minimizer-webpack-plugin css-loader sass-loader style-loader webpack-fix-style-only-entries'); + } + + if (opts.installing.tailwindPlugins) { + runCommand('npm install tailwindcss autoprefixer css-loader css-minimizer-webpack-plugin mini-css-extract-plugin postcss-import postcss-loader webpack-fix-style-only-entries'); + } + } + + if (opts.lintFiles && opts.installing.linters) { + console.log(chalk.yellow(`Installing Linters`)); + runCommand(`npm install --save-dev stylelint stylelint-config-recommended stylelint-order stylelint-config-prettier stylelint-prettier lint-staged eslint prettier eslint-plugin-prettier eslint-config-prettier @prettier/plugin-php`); + + if (!opts.installing.tailwindPlugins) { + runCommand(`npm install --save-dev stylelint-scss`); + } + } + + if (opts.installing.preCommitHook) { + runCommand('npm install husky --save-dev'); + } + + // vue adds things to the package json that will need installing + if (opts.installing.vue) { + runCommand('npm install') + } +} + +export default installPackages; diff --git a/src/libs.js b/src/libs.js new file mode 100644 index 0000000..467871e --- /dev/null +++ b/src/libs.js @@ -0,0 +1,46 @@ +const libs = { + styling: [ + { + name: 'A17 Tailwind Plugins', + cmd: 'npm install @area17/a17-tailwind-plugins', + docs: 'http://tailwind-plugins.dev.area17.com/', + files: ['./node_modules/@area17/a17-tailwind-plugins/docs/tailwind.config.js', './node_modules/@area17/a17-tailwind-plugins/docs/frontend.config.json'], + }, + { + name: 'A17 SCSS Utilities', + cmd: 'npm install @area17/scss-utilities', + docs: 'http://scss-utilities.dev.area17.com/', + } + ], + scripting: [ + { + name: 'A17 Behaviors', + cmd: 'npm install @area17/a17-behaviors', + docs: 'https://github.com/area17/a17-behaviors/wiki', + }, + { + name: 'Vue', + cmd: 'npm init vue@latest .', + docs: 'https://vuejs.org/guide/introduction.html', + } + ], + jsHelpers: { + name: 'A17 JS Helpers', + cmd: 'npm install @area17/a17-helpers', + docs: 'https://github.com/area17/js-helpers/wiki', + }, + patternLibraries: [ + { + name: 'Storybook', + cmd: 'npx storybook init', + docs: 'https://storybook.js.org/docs/react/get-started/introduction' + }, + { + name: 'Fractal', + cmd: ['npm install @frctl/fractal','npm i -g @frctl/fractal'], + docs: 'https://fractal.build/guide/' + } + ], +}; + +export default libs; diff --git a/src/postInstall.js b/src/postInstall.js new file mode 100644 index 0000000..5ae25a8 --- /dev/null +++ b/src/postInstall.js @@ -0,0 +1,107 @@ +import fs from 'fs-extra'; +import child_process from 'child_process'; +import chalk from 'chalk'; +import figlet from 'figlet'; +import readline from 'readline'; +import readlineSync from 'readline-sync'; + +import libs from './libs.js'; + +function postInstall(opts, appName) { + console.log('\n_______________________________________________________________________________\n\n'); + + console.log(chalk.cyan(figlet.textSync(appName, { + font: 'Standard', + horizontalLayout: 'default', + verticalLayout: 'default', + width: 80, + whitespaceBreak: true + }))); + + console.log('\n v0.0.1\n'); + + console.log(chalk.green(` ${ appName } created`)); + readlineSync.keyInPause(` Hit any key to see post installation notes\n\n\n`, { guide: false }); + readline.moveCursor(process.stdout, 0, -4); + readline.clearLine(process.stdout, 3); + + if (opts.styling > -1) { + const selectedStyling = libs.styling[opts.styling]; + console.log(chalk.yellow(` Docs for ${ selectedStyling.name }: ${ chalk.white(selectedStyling.docs) }`)); + } + + if (opts.scripting > -1) { + const selectedScripting = libs.scripting[opts.scripting]; + console.log(chalk.yellow(` Docs for ${ selectedScripting.name }: ${ chalk.white(selectedScripting.docs) }`)); + } + + if (opts.jsHelpers) { + console.log(chalk.yellow(` Docs for ${ libs.jsHelpers.name }: ${ chalk.white(libs.jsHelpers.docs) }`)); + } + + if (opts.patternLibrary > -1) { + const selectedPatternLibrary = libs.patternLibraries[opts.patternLibrary]; + console.log(chalk.yellow(` Docs for ${ selectedPatternLibrary.name }: ${ chalk.white(selectedPatternLibrary.docs) }`)); + } + + console.log(chalk.yellow(`\n A17 Dev Docs: ${ chalk.white('http://docs.dev.area17.com/') }`)); + + if (opts.installing.webpack) { + console.log(chalk.yellow(`\n Webpack setup added`)); + console.log(` See package.json for available build, dev and prod tasks. It is a basic setup\n and will likely need to be updated to suit your project needs - for example \n updating the 'output.path' from './public' and updating 'devServer' settings.`); + console.log(`\n Tasks added:`); + console.log(chalk.white(` • npm run build`, chalk.gray(`builds assets, copies fonts`))); + console.log(chalk.white(` • npm run dev`, chalk.gray(`starts a webpack dev server (NB: generates assets in memory, ie. doesn't generate new asset files in the filesystem)`))); + console.log(chalk.white(` • npm run prod`, chalk.gray(`builds minified assets, copies fonts`))); + console.log(chalk.white(` • npm run watch`, chalk.gray(`builds assets, copies fonts, watches for changes and rebuilds`))); + } + + if (opts.lintFiles && opts.installing.linters) { + console.log(chalk.yellow(`\n Lint tasks added`)); + console.log(chalk.white(` • lint`, chalk.gray(`runs linters on changed files only`))); + console.log(chalk.white(` • lint:staged`, chalk.gray(`runs linters on staged files only`))); + console.log(chalk.white(` • lint:all`, chalk.gray(`runs linters on all files`))); + + console.log(chalk.white(`\n • eslint`, chalk.gray(`runs eslint on changed files only`))); + console.log(chalk.white(` • prettier`, chalk.gray(`runs prettier on changed files only`))); + console.log(chalk.white(` • stylelint`, chalk.gray(`runs stylelint on changed files only`))); + + console.log(chalk.white(`\n • eslint:all`, chalk.gray(`runs eslint on all files`))); + console.log(chalk.white(` • prettier:all`, chalk.gray(`runs prettier on all files`))); + console.log(chalk.white(` • stylelint:all`, chalk.gray(`runs stylelint on all files`))); + } + + if (opts.git.init) { + console.log(chalk.yellow(`\n Git initialised - branch is '${ chalk.white('main') }'`)); + if (!opts.git.origin || opts.git.origin === '') { + console.log(chalk.red(` No Git remote specified. You will need to manually set your origin:`)); + console.log(chalk.white(` git remote add origin YOUR_GIT_ORIGIN`)); + } + } + + if (opts.installing.preCommitHook) { + console.log(chalk.yellow(`\n Husky pre-commit hook added`)); + if (!fs.existsSync('package.json')) { + console.log(chalk.red(` You currently don't have a package.json.\n When you make one, you will need to manually add Husky prepare script:`)); + console.log(chalk.gray(` // package.json`)); + console.log(chalk.white(` { + "scripts": { + "prepare": "husky install" + } + }`)); + } + + if (!fs.existsSync('.git')) { + console.log(chalk.red(` Your app currently isn't under Git source control.\n When you init git, you will need to add the Husky pre-commit hook to your repo:`)); + console.log(chalk.white(` npx husky install + npm pkg set scripts.prepare "husky install" + npx husky add .husky/pre-commit "npm run lint:staged" + git add .husky/pre-commit + git commit -m "adds husky pre-commit hook"`)); + } + } + + console.log(`\n\n`); +} + +export default postInstall; diff --git a/src/runCommand.js b/src/runCommand.js new file mode 100644 index 0000000..206b316 --- /dev/null +++ b/src/runCommand.js @@ -0,0 +1,16 @@ +import child_process from 'child_process'; +import chalk from 'chalk'; + +function runCommand(cmd) { + if (cmd.indexOf('vue') > -1) { + child_process.execSync(cmd, { stdio: 'inherit' }); + } else { + try { + return child_process.execSync(cmd).toString(); + } catch (error) { + console.error(chalk.red(`${cmd} failed`)); + } + } +} + +export default runCommand; diff --git a/src/writePkgJson.js b/src/writePkgJson.js new file mode 100644 index 0000000..8c467d1 --- /dev/null +++ b/src/writePkgJson.js @@ -0,0 +1,59 @@ +import chalk from 'chalk'; +import fs from 'fs-extra'; +import path from 'path'; +import readlineSync from 'readline-sync'; + +import libs from './libs.js'; + +// Generate package.json file for the project +const writePkgJson = (appName, opts) => { + const folderStructurePrefix = opts.installing.laravel ? 'resources/' : ''; + + if(!fs.existsSync(path.join(process.cwd(),'package.json')) && !opts.installing.vue) { + const packageJson = { + name: appName, + version: '0.0.1', + description: "The generator of A17 Bolierplate", + author: "A17 (https://area17.com/)", + license: "MIT", + }; + + if (opts.installing.webpack) { + packageJson.scripts = packageJson.scripts || {}; + packageJson.scripts.build = 'webpack'; + packageJson.scripts.dev = 'webpack serve --open'; + packageJson.scripts.prod = 'NODE_ENV=production webpack'; + packageJson.scripts.watch = 'webpack --watch'; + } + + if (opts.lintFiles && opts.installing.linters) { + packageJson.scripts = packageJson.scripts || {}; + packageJson.scripts.eslint = `npx eslint $(git diff --name-only HEAD | xargs)`; + packageJson.scripts.prettier = `prettier --list-different $(git diff --name-only HEAD | xargs)`; + packageJson.scripts.stylelint = `npx stylelint $(git diff --name-only HEAD | xargs)`; + + packageJson.scripts['eslint:all'] = `npx eslint "${ folderStructurePrefix }/**/*.js"`; + packageJson.scripts['prettier:all'] = `prettier --list-different "**/*.*"`; + packageJson.scripts['stylelint:all'] = `npx stylelint "${ folderStructurePrefix }/**/*.(css|scss|sass)"`; + + packageJson.scripts.lint = `npm run eslint && npm run stylelint && npm run prettier`; + packageJson.scripts['lint:all'] = `npm run eslint:all && npm run stylelint:all && npm run prettier:all`; + packageJson.scripts['lint:staged'] = `lint-staged`; + } + + fs.writeFileSync( + path.join(process.cwd(),'package.json'), + JSON.stringify(packageJson, null, 2) + ); + + console.log(chalk.yellow('package.json is created')); + } else { + if (opts.installing.vue) { + console.log(chalk.yellow('Skipping package.json creation, Vue will create one')); + } else { + console.log(chalk.yellow('Existing package.json found, skipping creation')); + } + } +} + +export default writePkgJson; diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..79f412a --- /dev/null +++ b/todo.md @@ -0,0 +1,13 @@ +# todo + +* if vue, set up for tailwind or scss with vite? +* check Vue install +* check Storybook install + * Blast?? + + +# Local build testing + +```shell +$ rm -rf * & rm -rf *.* & rm -rf .* & node ../a17-generator/bin/a17_generator.js +```