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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+```