diff --git a/README.md b/README.md
index 798b09a..8d50b6c 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,30 @@
-# vue-wp-bootstrap
\ No newline at end of file
+# Vue WordPress Plugin Boilerplate
+
+### Usage
+
+This is a project template for [@vue/cli](https://cli.vuejs.org).
+
+``` bash
+$ npm install -g @vue/cli
+$ npm install -g @vue/cli-init
+$ vue init abaicus/vue-wp-bootstrap my-project
+$ cd my-project
+$ composer install
+$ npm install
+$ npm run dev
+```
+
+### What's Included
+- `docker-compose up`: the template comes with a preconfigured `docker-compose` file that will run a full WordPress instance. If you want to use that, you might want to look into that one first.
+
+- `npm run dev`: WebPack, SCSS, Eslint watching.
+
+- `npm run build`: WebPack, SCSS build for production.
+
+- `npm run lint`: Lint `.js` and `.vue` files with ESLint.
+- `npm run pre-commit`: PHPCBF, PHPCS, Lint and add to git. This is ran automatically on commit if you initialize the project with commit lint.
+
+### Customizations
+You will likely need to do some tuning to suit your own needs:
+
+- Install additional libraries that you need, e.g. `vue-router`, `vue-resource`, `vuex`, etc...
diff --git a/meta.js b/meta.js
new file mode 100644
index 0000000..6cabf8b
--- /dev/null
+++ b/meta.js
@@ -0,0 +1,101 @@
+module.exports = {
+ helpers: {
+ lowercase: str => str.toLowerCase(),
+ abbreviate: str => {
+ if (str.indexOf('-') > -1) {
+ let matches = str.match(/\b(\w)/g);
+ return matches.join('')
+ .toUpperCase();
+ }
+ return str.toUpperCase();
+ },
+ lowercaseAbbrev: str => {
+ if (str.indexOf('-') > -1) {
+ let matches = str.match(/\b(\w)/g);
+ return matches.join('')
+ .toLowerCase();
+ }
+ return str.toLowerCase();
+ },
+ },
+ 'prompts': {
+ 'name': {
+ 'type': 'string',
+ 'required': true,
+ 'label': 'Plugin Slug (Must be Hyphened)',
+ 'default': 'wordpress-vue-js-bootstrap'
+ },
+ 'niceName': {
+ 'type': 'string',
+ 'required': true,
+ 'label': 'Plugin Nice Name',
+ 'default': 'WordPress Vue.js Bootstrap'
+ },
+ 'textdomain': {
+ 'type': 'string',
+ 'required': true,
+ 'label': 'Plugin Text Domain',
+ 'default': 'textdomain'
+ },
+ 'version': {
+ 'type': 'string',
+ 'required': true,
+ 'label': 'The version of the package',
+ 'default': '0.0.1'
+ },
+ 'description': {
+ 'type': 'string',
+ 'required': true,
+ 'label': 'Project description',
+ 'default': 'A Vue.js WordPress Plugin'
+ },
+ 'author': {
+ 'type': 'string',
+ 'label': 'Author'
+ },
+ 'authorUrl': {
+ 'type': 'string',
+ 'label': 'Author URI',
+ 'default': 'https://themeisle.com'
+ },
+ 'license': {
+ 'type': 'string',
+ 'label': 'License',
+ 'default': 'GPL-2.0+'
+ },
+ 'licenseUrl': {
+ 'type': 'string',
+ 'label': 'License',
+ 'default': 'https://www.gnu.org/licenses/gpl-2.0.html'
+ },
+ 'build': {
+ 'type': 'list',
+ 'message': 'Vue build',
+ 'choices': [
+ {
+ 'name': 'Runtime + Compiler: recommended for most users',
+ 'value': 'standalone',
+ 'short': 'standalone'
+ },
+ {
+ 'name': 'Runtime-only: about 6KB lighter min+gzip, but templates (or any Vue-specific HTML) are ONLY allowed in .vue files - render functions are required elsewhere',
+ 'value': 'runtime',
+ 'short': 'runtime'
+ }
+ ]
+ },
+ 'lint': {
+ 'type': 'confirm',
+ 'message': 'Use ESLint to lint your code?'
+ },
+ 'commitlint': {
+ 'type': 'confirm',
+ 'message': 'Setup Commit Lint and Pre-Commit Hooks?'
+ }
+ },
+ 'filters': {
+ '.eslintrc.js': 'lint',
+ '.commitlintrc.js' : 'commitlint'
+ },
+ 'completeMessage': 'To get started:\n\n cd {{destDirName}}\n composer install\n npm install\n npm run dev'
+};
diff --git a/template/.babelrc b/template/.babelrc
new file mode 100644
index 0000000..7a8bc5a
--- /dev/null
+++ b/template/.babelrc
@@ -0,0 +1,4 @@
+{
+ "presets": ["env"],
+ "plugins": ["transform-object-rest-spread"]
+}
diff --git a/template/.commitlintrc.js b/template/.commitlintrc.js
new file mode 100644
index 0000000..2b47d7d
--- /dev/null
+++ b/template/.commitlintrc.js
@@ -0,0 +1,29 @@
+const Configuration = {
+ extends: [ '@commitlint/config-conventional' ],
+ rules: {
+ 'subject-case': [
+ 2,
+ 'never',
+ ['start-case', 'pascal-case', 'upper-case']
+ ],
+ 'type-enum': [
+ 2,
+ 'always',
+ [
+ 'build',
+ 'chore',
+ 'ci',
+ 'docs',
+ 'feat',
+ 'fix',
+ 'perf',
+ 'refactor',
+ 'revert',
+ 'style',
+ 'test'
+ ]
+ ]
+ }
+};
+
+module.exports = Configuration;
diff --git a/template/.eslintrc b/template/.eslintrc
new file mode 100644
index 0000000..89f65dc
--- /dev/null
+++ b/template/.eslintrc
@@ -0,0 +1,9 @@
+{
+ "extends": "standard",
+ "plugins": [
+ "html"
+ ],
+ "env": {
+ "jasmine": true
+ }
+}
diff --git a/template/.gitignore b/template/.gitignore
new file mode 100644
index 0000000..72d0900
--- /dev/null
+++ b/template/.gitignore
@@ -0,0 +1,11 @@
+.idea
+node_modules
+logs
+dist
+artifact
+vendor
+bin
+composer.lock
+**/*.js.map
+**/*.css.map
+**/.DS_Store
diff --git a/template/README.md b/template/README.md
new file mode 100644
index 0000000..20aef7d
--- /dev/null
+++ b/template/README.md
@@ -0,0 +1,24 @@
+# {{ name }}
+
+> {{ description }}
+
+## Build Setup
+
+``` bash
+# install dependencies
+npm install
+
+# serve with hot reload at localhost:8080
+npm run dev
+
+# build for production with minification
+npm run build
+
+# lint all *.js and *.vue files
+npm run lint
+
+# run unit tests
+npm test
+```
+
+For more information see the [docs for vueify](https://github.com/vuejs/vueify).
diff --git a/template/assets/css/style.css b/template/assets/css/style.css
new file mode 100644
index 0000000..e69de29
diff --git a/template/assets/css/style.css.map b/template/assets/css/style.css.map
new file mode 100644
index 0000000..2d06e40
--- /dev/null
+++ b/template/assets/css/style.css.map
@@ -0,0 +1,9 @@
+{
+ "version": 3,
+ "file": "style.css",
+ "sources": [
+ "../scss/style.scss"
+ ],
+ "names": [],
+ "mappings": "AAAA,AAAA,KAAK,CAAC;EACJ,KAAK,EAAE,IAAI;EACX,gBAAgB,EAAE,IAAI,GACvB"
+}
\ No newline at end of file
diff --git a/template/assets/js/build.js b/template/assets/js/build.js
new file mode 100644
index 0000000..e69de29
diff --git a/template/assets/scss/style.scss b/template/assets/scss/style.scss
new file mode 100644
index 0000000..919de8c
--- /dev/null
+++ b/template/assets/scss/style.scss
@@ -0,0 +1,10 @@
+.{{lowercaseAbbrev name}}-wrap {
+ background-color: #fff;
+ padding: 20px;
+ margin-right: 20px;
+ margin-top: 20px;
+ margin-bottom: 20px;
+ box-shadow: 0 0 10px -5px rgba(0,0,0,0.5);
+ border-radius: 3px;
+ text-align: center;
+}
diff --git a/template/assets/src/App.vue b/template/assets/src/App.vue
new file mode 100644
index 0000000..8bc707e
--- /dev/null
+++ b/template/assets/src/App.vue
@@ -0,0 +1,23 @@
+/* jshint esversion: 6 */
+
+
+
\{{this.strings.title}}
+
\{{this.strings.description}}
+
+
+
+
+
+
diff --git a/template/assets/src/main.js b/template/assets/src/main.js
new file mode 100644
index 0000000..6fce796
--- /dev/null
+++ b/template/assets/src/main.js
@@ -0,0 +1,11 @@
+/* jshint esversion: 6 */
+import Vue from 'vue'
+import App from './App.vue'
+
+window.addEventListener('load', function () {
+ new Vue({ // eslint-disable-line no-new
+ el: '#{{lowercaseAbbrev name}}-app',
+ components: { App },
+ render: (h) => h(App)
+ })
+})
diff --git a/template/composer.json b/template/composer.json
new file mode 100644
index 0000000..dabdd03
--- /dev/null
+++ b/template/composer.json
@@ -0,0 +1,26 @@
+{
+ "name": "codeinwp/{{slug}}",
+ "description": "{{description}}",
+ "homepage": "{{authorUrl}}",
+ "license": "{{license}}",
+ "authors": [
+ {
+ "name": "{{author}}",
+ "email": "friends@themeisle.com",
+ "homepage": "{{authorUrl}}"
+ }
+ ],
+ "scripts": {
+ "format": "phpcbf --standard=phpcs.xml --report-summary --report-source -s --runtime-set testVersion 5.4- ",
+ "phpcs": "phpcs --standard=phpcs.xml -s --runtime-set testVersion 5.4-",
+ "lint": "composer run-script phpcs"
+ },
+ "minimum-stability": "dev",
+ "prefer-stable": true,
+ "extra": {
+ "installer-disable": "true"
+ },
+ "require-dev": {
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.5.0"
+ }
+}
diff --git a/template/docker-compose.yml b/template/docker-compose.yml
new file mode 100644
index 0000000..a23735f
--- /dev/null
+++ b/template/docker-compose.yml
@@ -0,0 +1,27 @@
+version: '3.1'
+
+services:
+ wordpress:
+ depends_on:
+ - mysql
+ image: hardeepasrani/pirate-brewery
+ ports:
+ - 998:80
+ volumes:
+ - ./:/var/www/html/wp-content/plugins/{{name}}
+ restart: always
+ environment:
+ WORDPRESS_DB_NAME: wordpress
+ WORDPRESS_DB_USER: wordpress
+ WORDPRESS_DB_PASSWORD: wordpress
+ WORDPRESS_DB_ROOT_PASSWORD: wordpress
+ mysql:
+ image: mysql:5.7
+ volumes:
+ - ~/db_data{{abbreviation}}:/var/lib/mysql
+ restart: always
+ environment:
+ MYSQL_ROOT_PASSWORD: wordpress
+ MYSQL_DATABASE: wordpress
+ MYSQL_USER: wordpress
+ MYSQL_PASSWORD: wordpress
diff --git a/template/includes/admin.php b/template/includes/admin.php
new file mode 100644
index 0000000..8c8a6c7
--- /dev/null
+++ b/template/includes/admin.php
@@ -0,0 +1,46 @@
+
';
+ }
+}
diff --git a/template/includes/assets.php b/template/includes/assets.php
new file mode 100644
index 0000000..d302604
--- /dev/null
+++ b/template/includes/assets.php
@@ -0,0 +1,66 @@
+base ) || $screen->base !== 'toplevel_page_{{lowercaseAbbrev name}}-app' ) {
+ return;
+ }
+
+ wp_register_style( $this->handle, {{abbreviate name}}_URL . 'assets/css/style.css', [], {{abbreviate name}}_VERSION );
+ wp_enqueue_style( $this->handle );
+
+ wp_register_script( $this->handle, {{abbreviate name}}_URL . 'assets/js/build.js', [], {{abbreviate name}}_VERSION, true );
+ wp_localize_script( $this->handle, '{{abbreviate name}}', $this->app_localization() );
+ wp_enqueue_script( $this->handle );
+ }
+
+ /**
+ * Localize main application script.
+ *
+ * @access private
+ * @return array
+ */
+ private function app_localization() {
+ return [
+ 'strings' => [
+ 'title' => 'Hello from VUE.JS',
+ 'description' => 'This text is passed through the {{abbreviate name}} localized object.',
+ ],
+ ];
+ }
+}
diff --git a/template/includes/rest.php b/template/includes/rest.php
new file mode 100644
index 0000000..9d97b25
--- /dev/null
+++ b/template/includes/rest.php
@@ -0,0 +1,41 @@
+namespace = '{{lowercaseAbbrev name}}/v1';
+ add_action( 'rest_api_init', [ $this, 'register_routes' ] );
+ }
+
+ /**
+ * Register rest routes.
+ *
+ * @access public
+ * @hooked `rest_api_init`
+ * @return void
+ */
+ public function register_routes() {}
+}
diff --git a/template/package.json b/template/package.json
new file mode 100644
index 0000000..537665e
--- /dev/null
+++ b/template/package.json
@@ -0,0 +1,71 @@
+{
+ "name": "{{ name }}",
+ "version": "{{ version }}",
+ "description": "{{ description }}",
+ "author": "{{ author }}",
+ "scripts": {
+ "build": "npm-run-all --parallel build:js build:css",
+ "dev": "npm-run-all --parallel watch:js{{#lint}} watch:eslint{{/lint}} watch:css",
+ {{#lint}}
+ "lint": "eslint --ext .js,.vue assets/src",
+ "watch:eslint": "esw -w --ext .js,.vue assets/src --color",
+ {{/lint}}
+ "watch:js": "cross-env NODE_ENV=development webpack --watch --progress --hide-modules",
+ "watch:css": "./node_modules/.bin/node-sass --watch assets/scss -o assets/css --source-map true",
+ "build:js": "cross-env NODE_ENV=production webpack --progress --hide-modules",
+ "phpcbf": "composer run-script format || true ",
+ "phpcs": "composer run-script phpcs",
+ "build:css": "node-sass assets/scss -o assets/css"{{#commitlint}},
+ "git:add": "git add assets/**/*",
+ "pre-commit": "npm-run-all phpcbf phpcs lint build git:add"
+ {{/commitlint}}
+ },
+ {{#if_eq build "standalone"}}
+ "browser": {
+ "vue": "vue/dist/vue.common.js"
+ },
+ {{/if_eq}}
+ "dependencies": {
+ "vue": "^2.6.10"
+ },
+ "devDependencies": {
+ "babel-core": "^6.26.3",
+ "babel-loader": "^7.1.2",
+ "babel-plugin-transform-object-rest-spread": "^6.26.0",
+ "babel-polyfill": "^6.26.0",
+ "babel-preset-env": "^1.7.0",
+ {{#commitlint}}
+ "@commitlint/cli": "^7.2.1",
+ "@commitlint/config-conventional": "^7.1.2",
+ {{/commitlint}}
+ "cross-env": "^3.2.4",
+ "css-loader": "^0.28.7",
+ "extract-text-webpack-plugin": "^3.0.2",
+ "file-loader": "^1.1.4",
+ "style-loader": "^0.23.1",
+ "uglifyjs-webpack-plugin": "^1.2.5",
+ "vue-loader": "^14.2.4",
+ "vue-template-compiler": "^2.4.4",
+ {{#lint}}
+ "eslint": "^3.3.0",
+ "eslint-config-standard": "^5.3.5",
+ "eslint-plugin-html": "^1.5.2",
+ "eslint-plugin-promise": "^2.0.1",
+ "eslint-plugin-standard": "^2.0.0",
+ "eslint-watch": "^5.0.1",
+ {{/lint}}
+ {{#commitlint}}
+ "husky": "^1.2.0",
+ {{/commitlint}}
+ "node-sass": "^4.11.0",
+ "npm-run-all": "^2.3.0",
+ "webpack": "^3.12.0"
+ }{{#commitlint}},
+ "husky": {
+ "hooks": {
+ "pre-commit": "npm run pre-commit",
+ "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
+ }
+ }
+ {{/commitlint}}
+}
diff --git a/template/phpcs.xml b/template/phpcs.xml
new file mode 100644
index 0000000..81a8ca5
--- /dev/null
+++ b/template/phpcs.xml
@@ -0,0 +1,36 @@
+
+
+ Themeisle rules for PHP_CodeSniffer
+
+ .
+
+ node_modules/*
+ vendor/*
+ tests/*
+ *.min.js
+ *.min.css
+ *.js
+ *.css
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
diff --git a/template/plugin.php b/template/plugin.php
new file mode 100644
index 0000000..d115f34
--- /dev/null
+++ b/template/plugin.php
@@ -0,0 +1,111 @@
+define_constants();
+ $instance->run();
+ }
+
+ return $instance;
+ }
+
+ /**
+ * Define the plugins constants.
+ *
+ * @access public
+ * @return void
+ */
+ public function define_constants() {
+ define( '{{abbreviate name}}_VERSION', $this->version );
+ define( '{{abbreviate name}}_FILE', __FILE__ );
+ define( '{{abbreviate name}}_PATH', dirname( {{abbreviate name}}_FILE ) );
+ define( '{{abbreviate name}}_INCLUDES', {{abbreviate name}}_PATH . '/includes' );
+ define( '{{abbreviate name}}_URL', trailingslashit( plugins_url( '', {{abbreviate name}}_FILE ) ) );
+ }
+
+ /**
+ * Initialize the plugins main components.
+ *
+ * @access private
+ * @return void
+ */
+ private function run() {
+ require_once {{abbreviate name}}_INCLUDES . '/admin.php';
+ require_once {{abbreviate name}}_INCLUDES . '/rest.php';
+ require_once {{abbreviate name}}_INCLUDES . '/assets.php';
+
+ $this->entities['admin'] = new Admin();
+ $this->entities['server'] = new Rest();
+ $this->entities['assets'] = new Assets();
+ }
+
+ /**
+ * Get plugin version.
+ *
+ * @access public
+ * @return string
+ */
+ public function get_version() {
+ return $this->version;
+ }
+
+ /**
+ * Get plugin components instances.
+ *
+ * @access public
+ * @return array
+ */
+ public function get_components() {
+ return $this->entities;
+ }
+}
+
+Plugin::get_instance();
diff --git a/template/webpack.config.js b/template/webpack.config.js
new file mode 100644
index 0000000..949a8d6
--- /dev/null
+++ b/template/webpack.config.js
@@ -0,0 +1,112 @@
+const ExtractTextPlugin = require('extract-text-webpack-plugin');
+const webpack = require('webpack');
+const path = require('path');
+const env = process.env.NODE_ENV;
+const plugins = [];
+
+if (env === 'production') {
+ const UglifyJsPlugin = webpack.optimize.UglifyJsPlugin;
+ plugins.push(new UglifyJsPlugin({ minimize: true }));
+ plugins.push(
+ new webpack.DefinePlugin(
+ {
+ 'process.env': {
+ NODE_ENV: '"production"'
+ }
+ }
+ )
+ );
+}
+
+module.exports = {
+ entry: {
+ 'build': ['./assets/src/main.js']
+ },
+ stats: { warnings: false }, // Hide warnings
+ output: {
+ path: path.resolve(__dirname, 'assets/js'),
+ filename: '[name].js'
+ },
+ module: {
+ rules: [
+ {
+ test: /\.vue$/,
+ loader: 'vue-loader',
+ options: {
+ loaders: {
+ // Since sass-loader (weirdly) has SCSS as its default parse mode, we map
+ // the "scss" and "sass" values for the lang attribute to the right configs here.
+ // other preprocessors should work out of the box, no loader config like this necessary.
+ scss: 'vue-style-loader!css-loader!sass-loader',
+ sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax'
+ }
+ }
+ },
+ {
+ test: /\.js$/,
+ exclude: /(node_modules)/,
+ use: {
+ loader: 'babel-loader',
+ options: {
+ presets: [
+ [
+ 'env',
+ {
+ targets: {
+ browsers: [
+ 'Chrome >= 52',
+ 'FireFox >= 44',
+ 'Safari >= 7',
+ 'Explorer 11',
+ 'last 4 Edge versions'
+ ]
+ },
+ useBuiltIns: true
+ }
+ ]
+ ]
+ }
+ }
+ },
+ {
+ test: /\.css$/,
+ use: ExtractTextPlugin.extract({
+ fallback: 'style-loader',
+ use: [
+ {
+ loader: 'css-loader',
+ options: { importLoaders: 1 }
+ },
+ 'postcss-loader'
+ ]
+ })
+ },
+ {
+ test: /\.(png|svg|jpg|gif)$/,
+ use: [
+ {
+ loader: 'file-loader',
+ options: {
+ name: 'img/[name].[ext]'
+ }
+ }
+ ]
+ },
+ {
+ test: /\.(png|woff|woff2|eot|ttf|svg)$/,
+ use: {
+ loader: 'file-loader',
+ options: {
+ name: 'fonts/[name].[ext]'
+ }
+ }
+ }
+ ]
+ },
+ resolve: {
+ alias: {
+ vue$: 'vue/dist/vue.esm.js'
+ }
+ },
+ plugins
+};