diff --git a/.circleci/config.yml b/.circleci/config.yml index c5186160e0..d4d2a03a19 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,12 +21,21 @@ jobs: - run: name: Rollout minimal scenario command: VUE_TEMPL_TEST=minimal node_modules/.bin/vue init . test-minimal + - store_artifacts: + path: test-minimal + destination: Rollout minimal scenario - run: name: Rollout full scenario command: VUE_TEMPL_TEST=full node_modules/.bin/vue init . test-full + - store_artifacts: + path: test-full + destination: Rollout full scenario - run: name: Rollout full-karma-airbnb scenario command: VUE_TEMPL_TEST=full-karma-airbnb node_modules/.bin/vue init . test-full-karma-airbnb + - store_artifacts: + path: test-full-karma-airbnb + destination: Rollout full-karma-airbnb scenario - persist_to_workspace: root: ~/project/webpack-template paths: @@ -73,7 +82,7 @@ jobs: - node_modules - run: name: Run Lint - command: npm run lint -- --fix + command: npm run lint:fix - run: name: Run Unit tests command: npm run unit @@ -106,7 +115,7 @@ jobs: - node_modules - run: name: Run Lint - command: npm run lint -- --fix + command: npm run lint:fix - run: name: Run Unit tests command: npm run unit diff --git a/docs/commands.md b/docs/commands.md index 7a8d48963b..5deac48aae 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -39,4 +39,4 @@ All build commands are executed via [NPM Scripts](https://docs.npmjs.com/misc/sc ### `npm run lint` -> Runs eslint and reports any linting errors in your code. See [Linter Configuration](linter.md) +> Runs eslint and stylelint, then reports any linting errors in your code. See [Linter Configuration](linter.md) diff --git a/docs/linter.md b/docs/linter.md index 478c1a111d..5add35ff16 100644 --- a/docs/linter.md +++ b/docs/linter.md @@ -1,14 +1,15 @@ # Linter Configuration -This boilerplate uses [ESLint](https://eslint.org/) as the linter, and uses the [Standard](https://github.com/feross/standard/blob/master/RULES.md) preset with some small customizations. +## ESLint +This boilerplate uses [ESLint](https://eslint.org/) for JavaScript linting, and uses the [Standard](https://github.com/feross/standard/blob/master/RULES.md) preset with some small customizations. -## eslint-plugin-vue +### eslint-plugin-vue We always add [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue) as well, which comes with a whole bunch of helpful rules to write consistent Vue components - it can also lint templates! You can find an overview of all the available rules on [github](https://github.com/vuejs/eslint-plugin-vue#gear-configs). We chose to add the `essential` configs, but we recommend to switch to the bigger `strongly-recommended` or `recommended` rulesets once you are familiar with them. -## Customizing +### Customizing If you are not happy with the default linting rules, you have several options: @@ -23,13 +24,24 @@ If you are not happy with the default linting rules, you have several options: 3. Pick "none" for ESLint preset when generating the project and define your own rules. See [ESLint documentation](https://eslint.org/docs/rules/) for more details. +## stylelint +This boilerplate uses [stylelint](https://stylelint.io/) as for style linting, and uses the [Standard](https://github.com/stylelint/stylelint-config-standard) preset. + +If you are not happy with the default linting rules, you have several options: + +1. Overwrite individual rules in `.stylelintrc.js`. For example, you can add the following rule to enforce tabs. + + ``` js + // .stylelintrc.js + "indentation": "tab", + ``` + +2. Pick "none" for stylelint preset when generating the project and define your own rules. See [Stylelint documentation](http://stylelint.io/user-guide/rules/) for more details. + ## Fixing Linting Errors You can run the following command to let eslint fix any errors it finds (if it can - not all errors are fixable like this): ``` -npm run lint -- --fix +npm run lint:fix ``` - -*(The `--` in the middle is necessary to ensure the `--fix` option is passdd to `eslint`, not to `npm`. It can be omitted whne using yarn)* - diff --git a/docs/structure.md b/docs/structure.md index 75c958a42f..88b5459f61 100644 --- a/docs/structure.md +++ b/docs/structure.md @@ -34,6 +34,8 @@ ├── .eslintignore # eslint ignore rules ├── .gitignore # sensible defaults for gitignore ├── .postcssrc.js # postcss config +├── .stylelintrc.js # stylelint config +├── .stylelintignore # stylelint ignore rules ├── index.html # index.html template ├── package.json # build scripts and dependencies └── README.md # Default README file diff --git a/meta.js b/meta.js index a521f9bdd0..26b7b797da 100644 --- a/meta.js +++ b/meta.js @@ -74,13 +74,13 @@ module.exports = { type: 'confirm', message: 'Install vue-router?', }, - lint: { + eslint: { when: 'isNotTest', type: 'confirm', message: 'Use ESLint to lint your code?', }, - lintConfig: { - when: 'isNotTest && lint', + eslintConfig: { + when: 'isNotTest && eslint', type: 'list', message: 'Pick an ESLint preset', choices: [ @@ -94,6 +94,38 @@ module.exports = { value: 'airbnb', short: 'Airbnb', }, + { + name: 'none (configure it yourself)', + value: 'none', + short: 'none' + } + ] + }, + stylelint: { + when: 'isNotTest', + type: 'confirm', + message: 'Use stylelint to lint your code?' + }, + stylelintConfig: { + when: 'isNotTest && stylelint', + type: 'list', + message: 'Pick a stylelint preset', + choices: [ + { + name: 'Standard (https://github.com/stylelint/stylelint-config-standard)', + value: 'standard', + short: 'Standard' + }, + { + name: 'Recommended (https://github.com/stylelint/stylelint-config-recommended)', + value: 'recommended', + short: 'Recommended' + }, + { + name: 'Wikimedia (https://github.com/wikimedia/stylelint-config-wikimedia)', + value: 'wikimedia', + short: 'Wikimedia' + }, { name: 'none (configure it yourself)', value: 'none', @@ -158,8 +190,10 @@ module.exports = { }, }, filters: { - '.eslintrc.js': 'lint', - '.eslintignore': 'lint', + '.eslintrc.js': 'eslint', + '.eslintignore': 'eslint', + '.stylelintrc.js': 'stylelint', + '.stylelintignore': 'stylelint', 'config/test.env.js': 'unit || e2e', 'build/webpack.test.conf.js': "unit && runner === 'karma'", 'test/unit/**/*': 'unit', diff --git a/scenarios/full-karma-airbnb.json b/scenarios/full-karma-airbnb.json index 4e70e573b2..41f63ba8d0 100644 --- a/scenarios/full-karma-airbnb.json +++ b/scenarios/full-karma-airbnb.json @@ -5,8 +5,10 @@ "author": "CircleCI", "build": "standalone", "router": false, - "lint": true, - "lintConfig": "airbnb", + "eslint": true, + "eslintConfig": "airbnb", + "stylelint": true, + "stylelintConfig": "recommended", "unit": true, "runner": "karma", "e2e": true, diff --git a/scenarios/full.json b/scenarios/full.json index f12d01e828..b8644a8c04 100644 --- a/scenarios/full.json +++ b/scenarios/full.json @@ -5,8 +5,10 @@ "author": "CircleCI", "build": "runtime", "router": false, - "lint": true, - "lintConfig": "standard", + "eslint": true, + "eslintConfig": "standard", + "stylelint": true, + "stylelintConfig": "standard", "unit": true, "runner": "jest", "e2e": true, diff --git a/scenarios/minimal.json b/scenarios/minimal.json index abf2637541..c5e0938da2 100644 --- a/scenarios/minimal.json +++ b/scenarios/minimal.json @@ -5,8 +5,10 @@ "author": "CircleCI", "build": "standalone", "router": false, - "lint": false, - "lintConfig": "standard", + "eslint": true, + "eslintConfig": "standard", + "stylelint": true, + "stylelintConfig": "standard", "unit": false, "runner": "jest", "e2e": false, diff --git a/template/.eslintrc.js b/template/.eslintrc.js index 30593179e2..f0cebff2fe 100644 --- a/template/.eslintrc.js +++ b/template/.eslintrc.js @@ -8,7 +8,7 @@ module.exports = { env: { browser: true, }, - {{#if_eq lintConfig "standard"}} + {{#if_eq eslintConfig "standard"}} extends: [ // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules. @@ -17,12 +17,12 @@ module.exports = { 'standard' ], {{/if_eq}} - {{#if_eq lintConfig "airbnb"}} + {{#if_eq eslintConfig "airbnb"}} // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules. extends: ['plugin:vue/essential', 'airbnb-base'], {{/if_eq}} - {{#if_eq lintConfig "none"}} + {{#if_eq eslintConfig "none"}} // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules. extends: ['plugin:vue/essential'], @@ -31,7 +31,7 @@ module.exports = { plugins: [ 'vue' ], - {{#if_eq lintConfig "airbnb"}} + {{#if_eq eslintConfig "airbnb"}} // check if imports actually resolve settings: { 'import/resolver': { @@ -43,11 +43,11 @@ module.exports = { {{/if_eq}} // add your custom rules here rules: { - {{#if_eq lintConfig "standard"}} + {{#if_eq eslintConfig "standard"}} // allow async-await 'generator-star-spacing': 'off', {{/if_eq}} - {{#if_eq lintConfig "airbnb"}} + {{#if_eq eslintConfig "airbnb"}} // don't require .vue extension when importing 'import/extensions': ['error', 'always', { js: 'never', diff --git a/template/.stylelintignore b/template/.stylelintignore new file mode 100644 index 0000000000..9c72cce6db --- /dev/null +++ b/template/.stylelintignore @@ -0,0 +1,7 @@ +/build/ +/config/ +/dist/ +/node_modules/ +{{#unit}} +/test/unit/coverage/ +{{/unit}} diff --git a/template/.stylelintrc.js b/template/.stylelintrc.js new file mode 100644 index 0000000000..6ef3fd2f25 --- /dev/null +++ b/template/.stylelintrc.js @@ -0,0 +1,14 @@ +module.exports = { + {{#if_eq eslintConfig "standard"}} + extends: 'stylelint-config-standard', + {{/if_eq}} + {{#if_eq eslintConfig "recommended"}} + extends: 'stylelint-config-recommended', + {{/if_eq}} + {{#if_eq eslintConfig "wikimedia"}} + extends: 'stylelint-config-wikimedia', + {{/if_eq}} + // add your custom rules here + rules: { + } +}; diff --git a/template/build/webpack.base.conf.js b/template/build/webpack.base.conf.js index 391160c571..54ae279b61 100644 --- a/template/build/webpack.base.conf.js +++ b/template/build/webpack.base.conf.js @@ -3,12 +3,15 @@ const path = require('path') const utils = require('./utils') const config = require('../config') const vueLoaderConfig = require('./vue-loader.conf') +{{#stylelint}} +const StyleLintPlugin = require('stylelint-webpack-plugin'); +{{/stylelint}} function resolve (dir) { return path.join(__dirname, '..', dir) } -{{#lint}}const createLintingRule = () => ({ +{{#eslint}}const createLintingRule = () => ({ test: /\.(js|vue)$/, loader: 'eslint-loader', enforce: 'pre', @@ -17,7 +20,7 @@ function resolve (dir) { formatter: require('eslint-friendly-formatter'), emitWarning: !config.dev.showEslintErrorsInOverlay } -}){{/lint}} +}){{/eslint}} module.exports = { context: path.resolve(__dirname, '../'), @@ -31,6 +34,15 @@ module.exports = { ? config.build.assetsPublicPath : config.dev.assetsPublicPath }, + {{#stylelint}} + plugins: [ + // Stylelint for all imports + // https://github.com/vieron/stylelint-webpack-plugin + new StyleLintPlugin({ + files: ['src/**/*.{vue,htm,html,css,sss,less,scss}'], + }) + ], + {{/stylelint}} resolve: { extensions: ['.js', '.vue', '.json'], alias: { @@ -42,9 +54,9 @@ module.exports = { }, module: { rules: [ - {{#lint}} + {{#eslint}} ...(config.dev.useEslint ? [createLintingRule()] : []), - {{/lint}} + {{/eslint}} { test: /\.vue$/, loader: 'vue-loader', diff --git a/template/config/index.js b/template/config/index.js index 820109957f..0c80ad1db5 100644 --- a/template/config/index.js +++ b/template/config/index.js @@ -20,14 +20,14 @@ module.exports = { notifyOnErrors: true, poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- - {{#lint}}// Use Eslint Loader? + {{#eslint}}// Use Eslint Loader? // If true, your code will be linted during bundling and // linting errors and warnings will be shown in the console. useEslint: true, // If true, eslint errors and warnings will also be shown in the error overlay // in the browser. showEslintErrorsInOverlay: false, - {{/lint}} + {{/eslint}} /** * Source Maps diff --git a/template/package.json b/template/package.json index 60b5ee202a..5dfb3b951b 100644 --- a/template/package.json +++ b/template/package.json @@ -19,9 +19,16 @@ {{#if_or unit e2e}} "test": "{{#unit}}npm run unit{{/unit}}{{#unit}}{{#e2e}} && {{/e2e}}{{/unit}}{{#e2e}}npm run e2e{{/e2e}}", {{/if_or}} - {{#lint}} - "lint": "eslint --ext .js,.vue src{{#unit}} test/unit{{/unit}}{{#e2e}} test/e2e/specs{{/e2e}}", - {{/lint}} + {{#eslint}} + "lint:eslint": "eslint --ext .js,.vue src{{#unit}} test/unit{{/unit}}{{#e2e}} test/e2e/specs{{/e2e}}", + {{/eslint}} + {{#stylelint}} + "lint:stylelint": "stylelint \"src/**/*.{vue,htm,html,css,sss,less,scss}\"", + {{/stylelint}} + {{#if_or eslint stylelint}} + "lint": "{{#eslint}}npm run lint:eslint{{/eslint}}{{#eslint}}{{#stylelint}} && {{/stylelint}}{{/eslint}}{{#stylelint}}npm run lint:stylelint{{/stylelint}}", + "lint:fix": "{{#eslint}}npm run lint:eslint -- --fix{{/eslint}}{{#eslint}}{{#stylelint}} && {{/stylelint}}{{/eslint}}{{#stylelint}}npm run lint:stylelint -- --fix{{/stylelint}}", + {{/if_or}} "build": "node build/build.js" }, "dependencies": { @@ -29,25 +36,38 @@ "vue-router": "^3.0.1"{{/router}} }, "devDependencies": { - {{#lint}} + {{#eslint}} "babel-eslint": "^8.2.1", "eslint": "^4.15.0", "eslint-friendly-formatter": "^3.0.0", "eslint-loader": "^1.7.1", "eslint-plugin-vue": "^4.0.0", - {{#if_eq lintConfig "standard"}} + {{#if_eq eslintConfig "standard"}} "eslint-config-standard": "^10.2.1", "eslint-plugin-promise": "^3.4.0", "eslint-plugin-standard": "^3.0.1", "eslint-plugin-import": "^2.7.0", "eslint-plugin-node": "^5.2.0", {{/if_eq}} - {{#if_eq lintConfig "airbnb"}} + {{#if_eq eslintConfig "airbnb"}} "eslint-config-airbnb-base": "^11.3.0", "eslint-import-resolver-webpack": "^0.8.3", "eslint-plugin-import": "^2.7.0", {{/if_eq}} - {{/lint}} + {{/eslint}} + {{#stylelint}} + "stylelint": "^8.4.0", + "stylelint-webpack-plugin": "^0.10.1", + {{#if_eq stylelintConfig "standard"}} + "stylelint-config-standard": "^18.0.0", + {{/if_eq}} + {{#if_eq stylelintConfig "recommended"}} + "stylelint-config-recommended": "^2.0.1", + {{/if_eq}} + {{#if_eq stylelintConfig "wikimedia"}} + "stylelint-config-wikimedia": "^0.4.2", + {{/if_eq}} + {{/stylelint}} {{#if_eq runner "jest"}} "babel-jest": "^21.0.2", "babel-plugin-dynamic-import-node": "^1.2.0", diff --git a/template/src/components/HelloWorld.vue b/template/src/components/HelloWorld.vue index ce0edd8ac1..86586e1295 100644 --- a/template/src/components/HelloWorld.vue +++ b/template/src/components/HelloWorld.vue @@ -96,17 +96,21 @@ export default {