From 5814ee93e3014ce7c30034e81d1ca8159801f656 Mon Sep 17 00:00:00 2001 From: Jason Wohlgemuth Date: Fri, 7 Jul 2017 17:25:51 -0500 Subject: [PATCH] Removed csslint and added stylelint as postcss plugin --- generators/app/README.md | 2 +- generators/app/gruntTaskConfigs.js | 30 ++-- .../project/templates/config/_default.json | 5 +- generators/webapp/index.js | 11 +- generators/webapp/templates/_README.md | 4 +- .../templates/config/stylelint.config.js | 165 ++++++++++++++++++ generators/webapp/templates/tasks/webapp.js | 2 - test/lib/common.js | 3 +- 8 files changed, 189 insertions(+), 33 deletions(-) create mode 100644 generators/webapp/templates/config/stylelint.config.js diff --git a/generators/app/README.md b/generators/app/README.md index f321ecc..33f34de 100644 --- a/generators/app/README.md +++ b/generators/app/README.md @@ -9,7 +9,7 @@ Technologies | task runner | [Grunt](./Gruntfile.js) | [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/gruntjs/grunt.svg)](http://isitmaintained.com/project/gruntjs/grunt "Average time to resolve an issue") [![Percentage of issues still open](http://isitmaintained.com/badge/open/gruntjs/grunt.svg)](http://isitmaintained.com/project/gruntjs/grunt "Percentage of issues still open") | | pre-process CSS | [less.js](https://github.com/gruntjs/grunt-contrib-less) or [Sass](https://github.com/gruntjs/grunt-contrib-sass) | | | post-process CSS | [PostCSS](http://postcss.org/) | [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/postcss/postcss.svg)](http://isitmaintained.com/project/postcss/postcss "Average time to resolve an issue") [![Percentage of issues still open](http://isitmaintained.com/badge/open/postcss/postcss.svg)](http://isitmaintained.com/project/postcss/postcss "Percentage of issues still open") | -| lint CSS | [CSSLint](https://github.com/gruntjs/grunt-contrib-csslint) | | +| lint CSS | [stylelint](https://stylelint.io/) | [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/stylelint/stylelint.svg)](http://isitmaintained.com/project/stylelint/stylelint "Average time to resolve an issue") [![Percentage of issues still open](http://isitmaintained.com/badge/open/stylelint/stylelint.svg)](http://isitmaintained.com/project/stylelint/stylelint "Percentage of issues still open") | | lint HTML | [HTML Hint Plus](https://github.com/poppinlp/grunt-htmlhint-plus) | | | lint JavaScript | [ESLint](./.config/.eslintrc.js) | [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/eslint/eslint.svg)](http://isitmaintained.com/project/eslint/eslint "Average time to resolve an issue") [![Percentage of issues still open](http://isitmaintained.com/badge/open/eslint/eslint.svg)](http://isitmaintained.com/project/eslint/eslint "Percentage of issues still open") | | pre-compile templates | [grunt plugin](https://github.com/gruntjs/grunt-contrib-handlebars) | | diff --git a/generators/app/gruntTaskConfigs.js b/generators/app/gruntTaskConfigs.js index 116251e..7dbae27 100644 --- a/generators/app/gruntTaskConfigs.js +++ b/generators/app/gruntTaskConfigs.js @@ -159,14 +159,6 @@ module.exports = { force: true } }`, - /** - * Lint compiled CSS output file - * @see {@link https://github.com/gruntjs/grunt-contrib-csslint} - **/ - csslint: `{ - options: {csslintrc: '<%= files.config.csslint %>'}, - src: ['<%= folders.app %>/style.css'] - }`, /** * Validate files with ESLint * @see {@link https://www.npmjs.com/package/grunt-eslint} @@ -311,7 +303,7 @@ module.exports = { * @see {@link https://github.com/brandonramirez/grunt-jsonlint} **/ jsonlint: `{ - project: {src: ['./*.json', '<%= files.config.csslint %>']} + project: {src: ['./*.json']} }`, /** * Pre-compile templates @@ -428,21 +420,23 @@ module.exports = { postcss: function(sourceDirectory) { return `{ options: { - parser: require("postcss-safe-parser"), + parser: require('postcss-safe-parser'), processors: [ - require("autoprefixer")({browsers: "last 2 versions"}), - require("cssnano")() + require('autoprefixer')({browsers: 'last 2 versions'}), + require('stylelint')(), + require('cssnano')(), + require('postcss-reporter')({clearReportedMessages: true}) ] }, dev: { options: { map: { inline: false, - annotation: "<%= folders.app %>" + annotation: '<%= folders.app %>' } }, - src: ["<%= folders.app %>/*.css", "<%= folders.assets %>/css/style.css"], - dest: "<%= folders.app %>/style.css" + src: ['<%= folders.app %>/*.css', '<%= folders.assets %>/css/style.css'], + dest: '<%= folders.app %>/style.css' }, prod: { src: "<%= folders.app %>/*.css", @@ -540,7 +534,7 @@ module.exports = { watch: `{ style: { files: ['<%= folders.assets %>/<%= files.styles %>'], - tasks: ['process-styles', 'csslint'], + tasks: ['process-styles'], options: {spawn: false} }, eslint: { @@ -550,8 +544,8 @@ module.exports = { }, lint: { files: [ - '<%= folders.app %>/style.css', //CSS - '<%= folders.app %>/<%= files.scripts %>' //Scripts + '<%= folders.app %>/style.css',// CSS + '<%= folders.app %>/<%= files.scripts %>'// Scripts ], tasks: ['lint'], options: {spawn: false} diff --git a/generators/project/templates/config/_default.json b/generators/project/templates/config/_default.json index eb5d95d..68187a3 100644 --- a/generators/project/templates/config/_default.json +++ b/generators/project/templates/config/_default.json @@ -20,9 +20,8 @@ }, "files": { "config": { - "csslint": "./config/.csslintrc", - "eslint": "./config/.eslintrc.js", - "karma": "./config/karma.conf.js" + "eslint": "./config/.eslintrc.js", + "karma": "./config/karma.conf.js" }, "index": "index.html", "scripts": "**/*.js", diff --git a/generators/webapp/index.js b/generators/webapp/index.js index 8e671b6..23714ea 100644 --- a/generators/webapp/index.js +++ b/generators/webapp/index.js @@ -137,7 +137,7 @@ module.exports = Generator.extend({ config.set('useImagemin', useImagemin); config.set('pluginDirectory', sourceDirectory); _copyTpl('_README.md', 'README.md'); - _copyTpl('config/_csslintrc', 'config/.csslintrc'); + _copyTpl('config/stylelint.config.js', 'config/stylelint.config.js'); _copyTpl('tasks/webapp.js', 'tasks/webapp.js'); _copyTpl('_config.js', `${sourceDirectory}app/config.js`); }, @@ -200,10 +200,11 @@ module.exports = Generator.extend({ 'grunt-htmlhint-plus' ]; let cssDevDependencies = [ - 'grunt-contrib-csslint', 'grunt-postcss', 'autoprefixer', + 'stylelint', 'cssnano', + 'postcss-reporter', 'postcss-safe-parser', 'mdcss', 'mdcss-theme-github' @@ -310,7 +311,7 @@ module.exports = Generator.extend({ let scripts = { lint: 'grunt eslint:src', 'lint:watch': 'grunt eslint:ing watch:eslint', - 'lnit:tests': 'grunt eslint:tests', + 'lint:tests': 'grunt eslint:tests', test: 'grunt test', 'test:watch': 'grunt karma:covering' }; @@ -378,7 +379,8 @@ module.exports = Generator.extend({ presets = presets.concat('babili'); } let babel = {plugins, presets}; - updatePackageJson({main, scripts, babel}); + let stylelint = {extends: './config/stylelint.config.js'}; + updatePackageJson({main, scripts, babel, stylelint}); }, configureWorkflowTasks: function() { const placeholder = '/* -- load tasks placeholder -- */'; @@ -428,7 +430,6 @@ function getTasks(generator) { 'browserSync', 'clean', 'copy', - 'csslint', 'eslint', 'htmlmin', 'htmlhintplus', diff --git a/generators/webapp/templates/_README.md b/generators/webapp/templates/_README.md index 402d166..1b76a03 100644 --- a/generators/webapp/templates/_README.md +++ b/generators/webapp/templates/_README.md @@ -29,10 +29,10 @@ Folder Structure | |- reset.scss | \- style.scss<% } %> +- config - | |- .csslintrc | |- .eslintrc.js | |- default.js - | \- karma.conf.js + | |- karma.conf.js + | \- stylelint.config.js +- tasks | \- webapp.js +- test diff --git a/generators/webapp/templates/config/stylelint.config.js b/generators/webapp/templates/config/stylelint.config.js new file mode 100644 index 0000000..e8b44f9 --- /dev/null +++ b/generators/webapp/templates/config/stylelint.config.js @@ -0,0 +1,165 @@ +module.exports = { + rules: { + // 'at-rule-blacklist': string|[], + // 'at-rule-empty-line-before': 'always'|'never', + // 'at-rule-name-case': 'lower'|'upper', + // 'at-rule-name-newline-after': 'always'|'always-multi-line', + // 'at-rule-name-space-after': 'always'|'always-single-line', + // 'at-rule-no-unknown': true, + // 'at-rule-no-vendor-prefix': true, + // 'at-rule-semicolon-newline-after': 'always', + // 'at-rule-semicolon-space-before': 'always'|'never', + // 'at-rule-whitelist': string|[], + // 'block-closing-brace-empty-line-before': 'always-multi-line'|'never', + // 'block-closing-brace-newline-after': 'always'|'always-single-line'|'never-single-line'|'always-multi-line'|'never-multi-line', + // 'block-closing-brace-newline-before': 'always'|'always-multi-line'|'never-multi-line', + // 'block-closing-brace-space-after': 'always'|'always-single-line'|'never-single-line'|'always-multi-line'|'never-multi-line', + // 'block-closing-brace-space-before': 'always'|'never'|'always-single-line'|'never-single-line'|'always-multi-line'|'never-multi-line', + // 'block-no-empty': true, + // 'block-opening-brace-newline-after': 'always'|'always-multi-line'|'never-multi-line', + // 'block-opening-brace-newline-before': 'always'|'always-single-line'|'never-single-line'|'always-multi-line'|'never-multi-line', + // 'block-opening-brace-space-after': 'always'|'always-single-line'|'never-single-line'|'always-multi-line'|'never-multi-line', + // 'block-opening-brace-space-before': 'always'|'always-single-line'|'never-single-line'|'always-multi-line'|'never-multi-line', + // 'color-hex-case': 'upper', + // 'color-hex-length': 'short'|'long', + // 'color-named': 'always-where-possible'|'never', + // 'color-no-hex': true, + // 'color-no-invalid-hex': true, + // 'comment-empty-line-before': 'always'|'never', + // 'comment-no-empty': true, + // 'comment-whitespace-inside': 'always'|'never', + // 'comment-word-blacklist': string|[], + // 'custom-media-pattern': string, + // 'custom-property-empty-line-before': 'always'|'never', + // 'custom-property-pattern': string, + // 'declaration-bang-space-after': 'always'|'never', + // 'declaration-bang-space-before': 'always'|'never', + // 'declaration-block-no-duplicate-properties': true, + // 'declaration-block-no-redundant-longhand-properties': true, + // 'declaration-block-no-shorthand-property-overrides': true, + // 'declaration-block-semicolon-newline-after': 'always'|'always-multi-line'|'never-multi-line', + // 'declaration-block-semicolon-newline-before': 'always'|'always-multi-line'|'never-multi-line', + // 'declaration-block-semicolon-space-after': 'always'|'never'|'always-single-line'|'never-single-line', + // 'declaration-block-semicolon-space-before': 'always'|'never'|'always-single-line'|'never-single-line', + // 'declaration-block-single-line-max-declarations': int, + // 'declaration-block-trailing-semicolon': 'always'|'never', + // 'declaration-colon-newline-after': 'always'|'always-multi-line', + // 'declaration-colon-space-after': 'always'|'never'|'always-single-line', + // 'declaration-colon-space-before': 'always'|'never', + // 'declaration-empty-line-before': 'always'|'never', + // 'declaration-no-important': true, + // 'declaration-property-unit-blacklist': {}, + // 'declaration-property-unit-whitelist': {}, + // 'declaration-property-value-blacklist': {}, + // 'declaration-property-value-whitelist': {}, + // 'font-family-name-quotes': 'always-where-required'|'always-where-recommended'|'always-unless-keyword', + // 'font-family-no-duplicate-names': true, + // 'font-weight-notation': 'numeric'|'named', + // 'function-blacklist': string|[], + // 'function-calc-no-unspaced-operator': true, + // 'function-comma-newline-after': 'always'|'always-multi-line'|'never-multi-line', + // 'function-comma-newline-before': 'always'|'always-multi-line'|'never-multi-line', + // 'function-comma-space-after': 'always'|'never'|'always-single-line'|'never-single-line', + // 'function-comma-space-before': 'always'|'never'|'always-single-line'|'never-single-line', + // 'function-linear-gradient-no-nonstandard-direction': true, + // 'function-max-empty-lines': int, + // 'function-name-case': 'lower'|'upper', + // 'function-parentheses-newline-inside': 'always'|'always-multi-line'|'never-multi-line', + // 'function-parentheses-space-inside': 'always'|'never'|'always-single-line'|'never-single-line', + // 'function-url-no-scheme-relative': true, + // 'function-url-quotes': 'always'|'never', + // 'function-url-scheme-blacklist': string|[], + // 'function-url-scheme-whitelist': string|[], + // 'function-whitelist': string|[], + // 'function-whitespace-after': 'always'|'never', + // 'indentation': int|'tab', + // 'keyframe-declaration-no-important': true, + // 'length-zero-no-unit': true, + // 'max-empty-lines': int, + // 'max-line-length': int, + // 'max-nesting-depth': int, + // 'media-feature-colon-space-after': 'always'|'never', + // 'media-feature-colon-space-before': 'always'|'never', + // 'media-feature-name-blacklist': string|[], + // 'media-feature-name-case': 'lower'|'upper', + // 'media-feature-name-no-unknown': true, + // 'media-feature-name-no-vendor-prefix': true, + // 'media-feature-name-whitelist': string|[], + // 'media-feature-parentheses-space-inside': 'always'|'never', + // 'media-feature-range-operator-space-after': 'always'|'never', + // 'media-feature-range-operator-space-before': 'always'|'never', + // 'media-query-list-comma-newline-after': 'always'|'always-multi-line'|'never-multi-line', + // 'media-query-list-comma-newline-before': 'always'|'always-multi-line'|'never-multi-line', + // 'media-query-list-comma-space-after': 'always'|'never'|'always-single-line'|'never-single-line', + // 'media-query-list-comma-space-before': 'always'|'never'|'always-single-line'|'never-single-line', + // 'no-descending-specificity': true, + // 'no-duplicate-selectors': true, + // 'no-empty-source': true, + // 'no-eol-whitespace': true, + // 'no-extra-semicolons': true, + // 'no-invalid-double-slash-comments': true, + // 'no-missing-end-of-source-newline': true, + // 'no-unknown-animations': true, + 'number-leading-zero': 'always', + // 'number-max-precision': int, + // 'number-no-trailing-zeros': true, + // 'property-blacklist': string|[], + // 'property-case': 'lower'|'upper', + // 'property-no-unknown': true, + // 'property-no-vendor-prefix': true, + // 'property-whitelist': string|[], + // 'rule-empty-line-before': 'always'|'never'|'always-multi-line'|'never-multi-line', + // 'selector-attribute-brackets-space-inside': 'always'|'never', + // 'selector-attribute-operator-blacklist': string|[], + // 'selector-attribute-operator-space-after': 'always'|'never', + // 'selector-attribute-operator-space-before': 'always'|'never', + // 'selector-attribute-operator-whitelist': string|[], + // 'selector-attribute-quotes': 'always'|'never', + // 'selector-class-pattern': string, + // 'selector-combinator-space-after': 'always'|'never', + // 'selector-combinator-space-before': 'always'|'never', + // 'selector-descendant-combinator-no-non-space': true, + // 'selector-id-pattern': string, + // 'selector-list-comma-newline-after': 'always'|'always-multi-line'|'never-multi-line', + // 'selector-list-comma-newline-before': 'always'|'always-multi-line'|'never-multi-line', + // 'selector-list-comma-space-after': 'always'|'never'|'always-single-line'|'never-single-line', + // 'selector-list-comma-space-before': 'always'|'never'|'always-single-line'|'never-single-line', + // 'selector-max-attribute': int, + // 'selector-max-class': int, + // 'selector-max-combinators': int, + // 'selector-max-compound-selectors': int, + // 'selector-max-empty-lines': int, + // 'selector-max-id': int, + // 'selector-max-specificity': string, + // 'selector-max-type': int, + // 'selector-max-universal': int, + // 'selector-nested-pattern': string, + // 'selector-no-qualifying-type': true, + // 'selector-no-vendor-prefix': true, + // 'selector-pseudo-class-blacklist': string|[], + // 'selector-pseudo-class-case': 'lower'|'upper', + // 'selector-pseudo-class-no-unknown': true, + // 'selector-pseudo-class-parentheses-space-inside': 'always'|'never', + // 'selector-pseudo-class-whitelist': string|[], + // 'selector-pseudo-element-case': 'lower'|'upper', + // 'selector-pseudo-element-colon-notation': 'single'|'double', + // 'selector-pseudo-element-no-unknown': true, + // 'selector-type-case': 'lower'|'upper', + // 'selector-type-no-unknown': true, + // 'shorthand-property-no-redundant-values': true, + // 'string-no-newline': true, + // 'string-quotes': 'single'|'double', + // 'time-min-milliseconds': int, + // 'unit-blacklist': string|[], + // 'unit-case': 'lower'|'upper', + // 'unit-no-unknown': true, + // 'unit-whitelist': string|[], + // 'value-keyword-case': 'lower'|'upper', + // 'value-list-comma-newline-after': 'always'|'always-multi-line'|'never-multi-line', + // 'value-list-comma-newline-before': 'always'|'always-multi-line'|'never-multi-line', + // 'value-list-comma-space-after': 'always'|'never'|'always-single-line'|'never-single-line', + // 'value-list-comma-space-before': 'always'|'never'|'always-single-line'|'never-single-line', + // 'value-list-max-empty-lines': int, + // 'value-no-vendor-prefix': true + } +}; diff --git a/generators/webapp/templates/tasks/webapp.js b/generators/webapp/templates/tasks/webapp.js index dd48c38..41cc61c 100644 --- a/generators/webapp/templates/tasks/webapp.js +++ b/generators/webapp/templates/tasks/webapp.js @@ -12,7 +12,6 @@ module.exports = function(grunt) { task('lint', 'Lint JSON, CSS, and JS code', [ 'jsonlint', 'htmlhintplus', - 'csslint', 'eslint:src' ]); task('linting', 'Watch task for real-time linting', [ @@ -21,7 +20,6 @@ module.exports = function(grunt) { ]); task('styling', 'Watch task for real-time styling', [ 'process-styles', - 'csslint', 'watch:style' ]); task('test', 'Run full test and validation battery', [ diff --git a/test/lib/common.js b/test/lib/common.js index 5e7d413..3c8de2e 100644 --- a/test/lib/common.js +++ b/test/lib/common.js @@ -36,7 +36,7 @@ function verifyCoreFiles() { 'Gruntfile.js', 'config/default.json', 'config/karma.conf.js', - 'config/.csslintrc', + 'config/stylelint.config.js', 'tasks/webapp.js' ]; ALWAYS_INCLUDED.forEach(file => assert.file(file)); @@ -69,7 +69,6 @@ function verifyBoilerplateFiles(sourceDirectory) { function verifyDefaultConfiguration(sourceDirectory) { verifyCoreFiles(); verifyLessConfigured(sourceDirectory); - assert.fileContent('Gruntfile.js', 'csslint: '); assert.fileContent(ariaContent); assert.fileContent('Gruntfile.js', 'imagemin: '); assert.noFileContent(browserifyContent); // script bundler