diff --git a/docs/manifest.json b/docs/manifest.json index b22e628e803e7..8c0881895f142 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -1805,6 +1805,12 @@ "markdown_source": "../packages/shortcode/README.md", "parent": "packages" }, + { + "title": "@wordpress/stylelint-config", + "slug": "packages-stylelint-config", + "markdown_source": "../packages/stylelint-config/README.md", + "parent": "packages" + }, { "title": "@wordpress/token-list", "slug": "packages-token-list", diff --git a/packages/stylelint-config/.npmrc b/packages/stylelint-config/.npmrc new file mode 100644 index 0000000000000..43c97e719a5a8 --- /dev/null +++ b/packages/stylelint-config/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/packages/stylelint-config/CHANGELOG.md b/packages/stylelint-config/CHANGELOG.md new file mode 100644 index 0000000000000..7c2e4e5592674 --- /dev/null +++ b/packages/stylelint-config/CHANGELOG.md @@ -0,0 +1,250 @@ + + +## Unreleased + +### Breaking Change + +- Removed stylelint `^10.1.0`, `^11.0.0`, and `^12.0.0` as peer dependency. + +### Internal + +- Imported from `WordPress-Coding-Standards/stylelint-config-wordpress` repository to `WordPress/gutenberg` ([#22777](https://github.com/WordPress/gutenberg/pull/22777)) + +## 17.0.0 (2020-05-31) + +- Updated: `stylelint-scss` to `3.17.2`. +- Updated: `stylelint` to `13.0.0`. + +## 16.0.0 (2019-12-31) + +- Fixed: `selector-class-pattern` rule regex to account for numerals, case detection, and ensure kebab-case over snake_case. +- Fixed: `selector-id-pattern` rule regex to account for numerals, case detection, and ensure kebab-case over snake_case. +- Updated: `stylelint-config-recommended-scss` to `4.1.0`. +- Updated: `stylelint-find-rules` to `2.2.0`. +- Updated: `stylelint-scss` to `3.13.0`. +- Updated: `stylelint` to `11.0.0`. + +## 15.0.0 (2019-10-05) + +- Added: NodeJS 12.x.x support. +- Updated: `stylelint` to `11.0.0`. +- Removed: `stylelint < 10.1.0` compatibility. +- Updated: `stylelint-config-recommended` to `3.0.0`. +- Updated: `stylelint-config-recommended-scss` to `4.0.0`. +- Updated: Bump minimum Node.js required version to `10.0.0`. + +## 14.0.0 (2019-04-18) + +- Updated: `stylelint` to `10.0.0`. +- Updated: `stylelint-scss` to `3.6.0`. +- Updated: `stylelint-config-recommended` to `2.2.0`. + +## 13.1.0 (2018-08-19) + +- Added: Added SCSS _shared config_ `extends` tests. +- Changed: `stylelint-config-wordpress/scss` now extends [`stylelint-config-recommended-scss`](https://github.com/kristerkari/stylelint-config-recommended-scss) (the net result of this change results in no rule changes for this SCSS config). +- Updated: `stylelint-scss` to `3.3.0`. +- Updated: `stylelint` to `9.5.0`. + +## 13.0.0 (2018-03-19) + +- Added: stylelint `9.1.3` support. +- Changed: Updated `stylelint` peer dependency version to `^9.1.3`. +- Changed: Improved `no-duplicate-selectors` tests. +- Removed: Jest snapshots. +- Removed: `stylelint < 9.1.3` compatibility. +- Updated: `selector-pseudo-element-colon-notation` to use `double` +- Updated: `stylelint-config-recommended` to `2.1.0`. +- Updated: `stylelint-scss` to `2.1.0`. +- Updated: Bump minimum Node.js required version to `8.9.3`. + +## 12.0.0 (2017-07-18) + +- Changed: `stylelint-config-wordpress` now extends [`stylelint-config-recommended`](https://github.com/stylelint/stylelint-config-recommended), which turns on the `at-rule-no-unknown`, `block-no-empty`, `comment-no-empty`, `declaration-block-no-ignored-properties`, `declaration-block-no-redundant-longhand-properties`, `font-family-no-duplicate-names`, `media-feature-name-no-unknown`, `no-empty-source` rule. These rules are part of stylelint's [possible errors](https://github.com/stylelint/stylelint/blob/master/docs/user-guide/rules.md#possible-errors) rules. +- Removed: `stylelint-scss < 1.5.1` compatibility. +- Removed: Removed style guide docs. +- Removed: `at-rule-no-unknown` custom `ignoreAtRules` options in `stylelint-config-wordpress/scss` shared config. +- Added: `scss/at-rule-no-unknown` rule in `stylelint-config-wordpress/scss` shared config. +- Added: NodeJS 8.x.x support. +- Added: npm 5.x.x support. +- Added: Jest snapshots to help detect and prevent regressions. + +## 11.0.0 (2017-05-16) + +- Added: `declaration-property-unit-whitelist` rule to allow `px` and exclude `%` and `em` units in `line-height` values. +- Changed: Relocated repo to https://github.com/WordPress-Coding-Standards. +- Fixed: Include CSS config `at-rule-empty-line-before` rules in SCSS config. + +## 10.0.2 (2017-04-29) + +- Added: Added `import` to `ignoreAtRules` option in `at-rule-empty-line-before` rule for SCSS config. + +## 10.0.1 (2017-04-21) + +- Removed: `rule-non-nested-empty-line-before` rule from SCSS config. This rule is deprecated in stylelint v8, the new `rule-empty-line-before` rule already exists in the primary config. + +## 10.0.0 (2017-04-21) + +- Added: `scss/selector-no-redundant-nesting-selector` rule in `stylelint-config-wordpress/scss` shared config. +- Added: `selector-no-empty` rule. +- Added: NodeJS 7.x.x support +- Fixed: Added `stylelint-scss` plugin @if/@else placement rules. +- Fixed: Ignore `relative` keyword names in `font-weight-notation` rule. +- Fixed: Ignore proprietary `DXImageTransform.Microsoft` MS filters +- Fixed: Removed `@debug` from `ignoreAtRules` array of `at-rule-no-unknown` rule in `stylelint-config-wordpress/scss` chared config. +- Deprecated `blockless-group` option for `at-rule-empty-line-before` rule. Use the new `blockless-after-blockless` option instead. +- Deprecated `media-feature-no-missing-punctuation` rule. +- Deprecated `rule-nested-empty-line-before` and `rule-non-nested-empty-line-before` rules. Use the new `rule-empty-line-before` rule instead. +- Deprecated `selector-no-empty` rule. +- Refactor: Switch from AVA to Jest for tests. +- Refactor: Switch from eslint-plugin-ava to eslint-plugin-jest. +- Removed: `stylelint < 7.10.1` compatibility. +- Removed: `stylelint-scss < 1.4.4` compatibility. +- Removed: NodeJS 4.x support, `stylelint` and `stylelint-config-wordpress` now require NodeJS > 6.9.1 LTS or greater + +## 9.1.1 (2016-09-30) + +- Fixed: Re-releasing failed npmjs.com 9.1.0 release as 9.1.1. + +## 9.1.0 (2016-09-30) + +- Added: `stylelint-config-wordpress/scss` preset. + +## 9.0.0 (2016-09-10) + +- Removed: `stylelint < 7.2.0` compatibility. +- Removed: NodeJS 0.12.x support, `stylelint` and `stylelint-config-wordpress` now require NodeJS > 4.2.1 LTS or greater +- Added: `at-rule-no-unknown` rule. +- Added: `selector-attribute-quotes` rule. +- Added: `font-weight-notation` rule. +- Added: `max-line-length` rule. +- Added: `property-no-unknown` rule. +- Added: `selector-class-pattern` rule. +- Added: `selector-id-pattern` rule. +- Deprecated `no-missing-eof-newline` rule. Use the new `no-missing-end-of-source-newline` rule instead. +- Fixed `font-family-name-quotes` test warning message in `values.js`. + +## 8.0.0 (2016-06-14) + +- Removed: `stylelint < 6.6.0` compatibility. +- Removed: `number-zero-length-no-unit` rule. +- Added: `length-zero-no-unit` rule. +- Added: `value-keyword-case` rule. + +## 7.1.1 (2016-05-30) + +- Fixed: Re-releasing failed npmjs.com 7.0.0 release as 7.1.1. + +## 7.1.0 (2016-05-30) + +- Fixed: `font-family-name-quotes` rule deprecated option `double-where-recommended` to new `always-where-recommended` option. +- Fixed: `function-url-quotes` rule deprecated option `none` to new `never` option. +- Removed: `stylelint < 6.5.1` compatibility. +- Changed: Improved tests and documentation. +- Added: `comment-empty-line-before` rule. + +## 7.0.0 (2016-05-20) + +- Added: `keyframe-declaration-no-important` rule. +- Added: `selector-pseudo-class-no-unknown` rule. +- Added: `selector-pseudo-element-no-unknown` rule. +- Added: `selector-type-no-unknown` rule. + +## 6.0.0 (2016-05-17) + +- Added: `at-rule-name-space-after` rule. +- Added: `no-extra-semicolons` rule. +- Added: `selector-attribute-operator-space-after` rule. +- Added: `selector-attribute-operator-space-before` rule. +- Added: `selector-max-empty-liness` rule. + +## 5.0.0 (2016-04-24) + +- Added: `at-rule-name-case` rule. +- Added: `declaration-block-no-duplicate-properties` rule. +- Added: `function-max-empty-lines` rule. +- Added: `function-name-case` rule. +- Added: `property-case` rule. +- Added: `selector-attribute-brackets-space-inside` rule. +- Added: `selector-pseudo-class-case` rule. +- Added: `selector-pseudo-class-parentheses-space-inside` rule. +- Added: `selector-pseudo-element-case` rule. +- Added: `shorthand-property-no-redundant-values` rule. +- Added: `unit-case` rule. +- Added: `unit-no-unknown` rule. + +## 4.0.0 (2016-03-25) + +- Removed: `stylelint < 5.2.0` compatibility. +- Added: `at-rule-semicolon-newline-after` rule. +- Added: `selector-type-case` rule. + +## 3.0.1 (2016-03-10) + +- Added: `stylelint` version `^4.5.0` as a peer dependency to `peerDependencies` in `package.json` + +## 3.0.0 (2016-03-08) + +- Removed: `stylelint < 4.5.0` compatibility. +- Deprecated: `rule-no-shorthand-property-overrides` rule. Use the new `declaration-block-no-shorthand-property-overrides` rule instead. +- Deprecated: `rule-trailing-semicolon` rule. Use the new `declaration-block-trailing-semicolon` rule instead. +- Added: `color-named` rule. +- Added: `declaration-block-no-shorthand-property-overrides` rule. +- Added: `declaration-block-trailing-semicolon` rule. +- Added: `string-no-newline` rule. + +## 2.1.0 (2016-03-03) + +- Added: `max-empty-lines` rule, limits the number of adjacent empty lines to 2. +- Changed: `rule-nested-empty-line-before` rule option `ignore: ["after-comment"]`. +- Removed all vendor prefixes, lets autoprefixer handle vendor prefixes: + - Removed: `at-rule-no-vendor-prefix` + - Removed: `media-feature-name-no-vendor-prefix` + - Removed: `property-no-vendor-prefix` + - Removed: `selector-no-vendor-prefix` + - Removed: `value-no-vendor-prefix` + +## 2.0.2 (2016-02-17) + +- Fixed another npmjs.com release issue + +## 2.0.1 (2016-02-17) + +- Fixed npmjs.com release + +## 2.0.0 (2016-02-17) + +- Removed: `media-query-parentheses-space-inside` rule. +- Removed: `stylelint < 4.3.4` compatibility. +- Added: `font-family-name-quotes` rule with double quotes where recommended option. +- Added: `media-feature-no-missing-punctuation` rule. +- Added: `no-invalid-double-slash-comments` rule. + +## 1.1.1 (2016-01-19) + +- Changed: `rule-non-nested-empty-line-before` with option `ignore: ["after-comment"],`. + +## 1.1.0 (2016-01-18) + +- Added: `selector-pseudo-element-colon-notation` with option `single` + +## 1.0.1 (2015-12-11) + +- Changed: config syntax. + +## 1.0.0 (2015-12-11) + +- Removed: `stylelint < 3.0.0` compatibility. +- Changed: renamed the `function-space-after` rule to `function-whitespace-after`. +- Changed: `at-rule-empty-line-before` with option `ignore: ["after-comment"],`. +- Changed: `declaration-colon-space-after` with option `always-single-line`. +- Added: `declaration-colon-newline-after` with option `always-multi-line`. +- Added: `function-linear-gradient-no-nonstandard-direction`. + +## 0.2.0 (2015-09-04) + +- Fixed: No quotes for URLs -> `"function-url-quotes": [ 2, "none" ]`. + +## 0.1.0 (2015-08-01) + +Initial release. diff --git a/packages/stylelint-config/LICENSE b/packages/stylelint-config/LICENSE new file mode 100644 index 0000000000000..8673b137beef4 --- /dev/null +++ b/packages/stylelint-config/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 stylelint + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/packages/stylelint-config/README.md b/packages/stylelint-config/README.md new file mode 100644 index 0000000000000..0989d54a20d08 --- /dev/null +++ b/packages/stylelint-config/README.md @@ -0,0 +1,57 @@ +# stylelint config + +[stylelint](https://stylelint.io/) configuration rules to ensure your CSS is compliant with the [WordPress CSS Coding Standards](https://developer.wordpress.org/coding-standards/wordpress-coding-standards/css/). + +## Installation + +```bash +$ npm install @wordpress/stylelint-config --save-dev +``` + +## Usage + +If you've installed `@wordpress/stylelint-config` locally within your project, just set your `stylelint` config to: + +```json +{ + "extends": "@wordpress/stylelint-config" +} +``` + +If you've globally installed `@wordpress/stylelint-config` using the `-g` flag, then you'll need to use the absolute path to `@wordpress/stylelint-config` in your config: + +```json +{ + "extends": "/absolute/path/to/@wordpress/stylelint-config" +} +``` + +## Presets + +In addition to the default preset, there is also a SCSS preset. This preset extends both `@wordpress/stylelint-config` and [`stylelint-config-recommended-scss`](https://github.com/kristerkari/stylelint-config-recommended-scss). + +### SCSS + +```json +{ + "extends": [ "@wordpress/stylelint-config/scss" ] +} +``` + +## Extending the config + +Simply add a `"rules"` key to your config and add your overrides there. + +For example, to change the `indentation` to four spaces and turn off the `number-leading-zero` rule: + +```json +{ + "extends": "@wordpress/stylelint-config", + "rules": { + "indentation": 4, + "number-leading-zero": null + } +} +``` + +

Code is Poetry.

diff --git a/packages/stylelint-config/index.js b/packages/stylelint-config/index.js new file mode 100644 index 0000000000000..490ab35d5b131 --- /dev/null +++ b/packages/stylelint-config/index.js @@ -0,0 +1,131 @@ +'use strict'; + +module.exports = { + extends: 'stylelint-config-recommended', + rules: { + 'at-rule-empty-line-before': [ + 'always', + { + except: [ 'blockless-after-blockless' ], + ignore: [ 'after-comment' ], + }, + ], + 'at-rule-name-case': 'lower', + 'at-rule-name-space-after': 'always-single-line', + 'at-rule-no-unknown': true, + 'at-rule-semicolon-newline-after': 'always', + 'block-closing-brace-newline-after': 'always', + 'block-closing-brace-newline-before': 'always', + 'block-opening-brace-newline-after': 'always', + 'block-opening-brace-space-before': 'always', + 'color-hex-case': 'lower', + 'color-hex-length': 'short', + 'color-named': 'never', + 'comment-empty-line-before': [ + 'always', + { + ignore: [ 'stylelint-commands' ], + }, + ], + 'declaration-bang-space-after': 'never', + 'declaration-bang-space-before': 'always', + 'declaration-block-no-duplicate-properties': [ + true, + { + ignore: [ 'consecutive-duplicates' ], + }, + ], + 'declaration-block-semicolon-newline-after': 'always', + 'declaration-block-semicolon-space-before': 'never', + 'declaration-block-trailing-semicolon': 'always', + 'declaration-colon-newline-after': 'always-multi-line', + 'declaration-colon-space-after': 'always-single-line', + 'declaration-colon-space-before': 'never', + 'declaration-property-unit-whitelist': { + 'line-height': [ 'px' ], + }, + 'font-family-name-quotes': 'always-where-recommended', + 'font-weight-notation': [ + 'numeric', + { + ignore: [ 'relative' ], + }, + ], + 'function-comma-space-after': 'always', + 'function-comma-space-before': 'never', + 'function-max-empty-lines': 1, + 'function-name-case': [ + 'lower', + { + ignoreFunctions: [ '/^DXImageTransform.Microsoft.*$/' ], + }, + ], + 'function-parentheses-space-inside': 'never', + 'function-url-quotes': 'never', + 'function-whitespace-after': 'always', + indentation: 'tab', + 'length-zero-no-unit': true, + 'max-empty-lines': 2, + 'max-line-length': [ + 80, + { + ignore: 'non-comments', + ignorePattern: [ + '/(https?://[0-9,a-z]*.*)|(^description\\:.+)|(^tags\\:.+)/i', + ], + }, + ], + 'media-feature-colon-space-after': 'always', + 'media-feature-colon-space-before': 'never', + 'media-feature-range-operator-space-after': 'always', + 'media-feature-range-operator-space-before': 'always', + 'media-query-list-comma-newline-after': 'always-multi-line', + 'media-query-list-comma-space-after': 'always-single-line', + 'media-query-list-comma-space-before': 'never', + 'no-eol-whitespace': true, + 'no-missing-end-of-source-newline': true, + 'number-leading-zero': 'always', + 'number-no-trailing-zeros': true, + 'property-case': 'lower', + 'rule-empty-line-before': [ + 'always', + { + ignore: [ 'after-comment' ], + }, + ], + 'selector-attribute-brackets-space-inside': 'never', + 'selector-attribute-operator-space-after': 'never', + 'selector-attribute-operator-space-before': 'never', + 'selector-attribute-quotes': 'always', + 'selector-class-pattern': [ + '^([a-z][a-z0-9]*)(-[a-z0-9]+)*$', + { + message: + 'Selector should use lowercase and separate words with hyphens (selector-class-pattern)', + }, + ], + 'selector-id-pattern': [ + '^([a-z][a-z0-9]*)(-[a-z0-9]+)*$', + { + message: + 'Selector should use lowercase and separate words with hyphens (selector-id-pattern)', + }, + ], + 'selector-combinator-space-after': 'always', + 'selector-combinator-space-before': 'always', + 'selector-list-comma-newline-after': 'always', + 'selector-list-comma-space-before': 'never', + 'selector-max-empty-lines': 0, + 'selector-pseudo-class-case': 'lower', + 'selector-pseudo-class-parentheses-space-inside': 'never', + 'selector-pseudo-element-case': 'lower', + 'selector-pseudo-element-colon-notation': 'double', + 'selector-type-case': 'lower', + 'string-quotes': 'double', + 'unit-case': 'lower', + 'value-keyword-case': 'lower', + 'value-list-comma-newline-after': 'always-multi-line', + 'value-list-comma-space-after': 'always-single-line', + 'value-list-comma-space-before': 'never', + }, +}; diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json new file mode 100644 index 0000000000000..8e7a90f8de2c1 --- /dev/null +++ b/packages/stylelint-config/package.json @@ -0,0 +1,52 @@ +{ + "name": "@wordpress/stylelint-config", + "version": "17.0.0", + "description": "stylelint config for WordPress development.", + "author": "The WordPress Contributors", + "license": "MIT", + "keywords": [ + "stylelint", + "stylelint-config", + "stylelint-config-wordpress", + "wordpress" + ], + "homepage": "https://github.com/WordPress/gutenberg/tree/master/packages/stylelint-config/README.md", + "repository": { + "type": "git", + "url": "https://github.com/WordPress/gutenberg.git", + "directory": "packages/stylelint-config" + }, + "bugs": { + "url": "https://github.com/WordPress/gutenberg/issues" + }, + "files": [ + "CHANGELOG.md", + "LICENSE", + "README.md", + "index.js", + "scss.js" + ], + "main": "index.js", + "dependencies": { + "stylelint-config-recommended": "^3.0.0", + "stylelint-config-recommended-scss": "^4.2.0", + "stylelint-scss": "^3.17.2" + }, + "peerDependencies": { + "stylelint": "^13.0.0" + }, + "npmpackagejsonlint": { + "extends": "@wordpress/npm-package-json-lint-config", + "rules": { + "valid-values-license": [ + "error", + [ + "MIT" + ] + ] + } + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/stylelint-config/scss.js b/packages/stylelint-config/scss.js new file mode 100644 index 0000000000000..09940642b218b --- /dev/null +++ b/packages/stylelint-config/scss.js @@ -0,0 +1,36 @@ +'use strict'; + +module.exports = { + extends: [ './', 'stylelint-config-recommended-scss' ].map( + require.resolve + ), + + plugins: [ 'stylelint-scss' ], + + rules: { + // @wordpress/stylelint-config CSS overrides. + 'at-rule-empty-line-before': [ + 'always', + { + except: [ 'blockless-after-blockless' ], + ignore: [ 'after-comment' ], + ignoreAtRules: [ 'else' ], + }, + ], + + 'block-opening-brace-space-before': 'always', + 'block-closing-brace-newline-after': [ + 'always', + { + ignoreAtRules: [ 'if', 'else' ], + }, + ], + 'at-rule-name-space-after': 'always', + 'scss/at-else-closing-brace-newline-after': 'always-last-in-chain', + 'scss/at-else-closing-brace-space-after': 'always-intermediate', + 'scss/at-else-empty-line-before': 'never', + 'scss/at-if-closing-brace-newline-after': 'always-last-in-chain', + 'scss/at-if-closing-brace-space-after': 'always-intermediate', + 'scss/selector-no-redundant-nesting-selector': true, + }, +}; diff --git a/packages/stylelint-config/test/.stylelintrc.json b/packages/stylelint-config/test/.stylelintrc.json new file mode 100644 index 0000000000000..99a3abd90cbcc --- /dev/null +++ b/packages/stylelint-config/test/.stylelintrc.json @@ -0,0 +1,6 @@ +{ + "extends": "stylelint-config-wordpress/scss", + "ignoreFiles": [ + "*-invalid.scss" + ] +} diff --git a/packages/stylelint-config/test/__snapshots__/commenting.js.snap b/packages/stylelint-config/test/__snapshots__/commenting.js.snap new file mode 100644 index 0000000000000..82a5c3efe8ff0 --- /dev/null +++ b/packages/stylelint-config/test/__snapshots__/commenting.js.snap @@ -0,0 +1,27 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`flags warnings with invalid commenting css snapshot matches warnings 1`] = ` +Array [ + Object { + "column": 1, + "line": 9, + "rule": "comment-empty-line-before", + "severity": "error", + "text": "Expected empty line before comment (comment-empty-line-before)", + }, + Object { + "column": 1, + "line": 18, + "rule": "comment-empty-line-before", + "severity": "error", + "text": "Expected empty line before comment (comment-empty-line-before)", + }, + Object { + "column": 131, + "line": 24, + "rule": "max-line-length", + "severity": "error", + "text": "Expected line length to be no more than 80 characters (max-line-length)", + }, +] +`; diff --git a/packages/stylelint-config/test/__snapshots__/functions.js.snap b/packages/stylelint-config/test/__snapshots__/functions.js.snap new file mode 100644 index 0000000000000..0e75e70fcf7b4 --- /dev/null +++ b/packages/stylelint-config/test/__snapshots__/functions.js.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`flags warnings with invalid functions css snapshot matches warnings 1`] = ` +Array [ + Object { + "column": 9, + "line": 4, + "rule": "function-name-case", + "severity": "error", + "text": "Expected \\"Calc\\" to be \\"calc\\" (function-name-case)", + }, +] +`; diff --git a/packages/stylelint-config/test/__snapshots__/index.js.snap b/packages/stylelint-config/test/__snapshots__/index.js.snap new file mode 100644 index 0000000000000..b0df67be5d2f9 --- /dev/null +++ b/packages/stylelint-config/test/__snapshots__/index.js.snap @@ -0,0 +1,13 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`flags warnings with invalid css snapshot matches warnings 1`] = ` +Array [ + Object { + "column": 7, + "line": 2, + "rule": "number-leading-zero", + "severity": "error", + "text": "Expected a leading zero (number-leading-zero)", + }, +] +`; diff --git a/packages/stylelint-config/test/__snapshots__/media-queries.js.snap b/packages/stylelint-config/test/__snapshots__/media-queries.js.snap new file mode 100644 index 0000000000000..e5f02f1c72b82 --- /dev/null +++ b/packages/stylelint-config/test/__snapshots__/media-queries.js.snap @@ -0,0 +1,83 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`flags warnings with invalid media queries css snapshot matches warnings 1`] = ` +Array [ + Object { + "column": 1, + "line": 31, + "rule": "at-rule-no-unknown", + "severity": "error", + "text": "Unexpected unknown at-rule \\"@mdia\\" (at-rule-no-unknown)", + }, + Object { + "column": 26, + "line": 1, + "rule": "media-feature-colon-space-after", + "severity": "error", + "text": "Expected single space after \\":\\" (media-feature-colon-space-after)", + }, + Object { + "column": 27, + "line": 6, + "rule": "media-feature-colon-space-after", + "severity": "error", + "text": "Expected single space after \\":\\" (media-feature-colon-space-after)", + }, + Object { + "column": 27, + "line": 6, + "rule": "media-feature-colon-space-before", + "severity": "error", + "text": "Unexpected whitespace before \\":\\" (media-feature-colon-space-before)", + }, + Object { + "column": 17, + "line": 11, + "rule": "media-feature-name-no-unknown", + "severity": "error", + "text": "Unexpected unknown media feature name \\"max-width 699px\\" (media-feature-name-no-unknown)", + }, + Object { + "column": 28, + "line": 16, + "rule": "media-feature-range-operator-space-after", + "severity": "error", + "text": "Expected single space after range operator (media-feature-range-operator-space-after)", + }, + Object { + "column": 29, + "line": 21, + "rule": "media-feature-range-operator-space-after", + "severity": "error", + "text": "Expected single space after range operator (media-feature-range-operator-space-after)", + }, + Object { + "column": 25, + "line": 16, + "rule": "media-feature-range-operator-space-before", + "severity": "error", + "text": "Expected single space before range operator (media-feature-range-operator-space-before)", + }, + Object { + "column": 25, + "line": 26, + "rule": "media-feature-range-operator-space-before", + "severity": "error", + "text": "Expected single space before range operator (media-feature-range-operator-space-before)", + }, + Object { + "column": 27, + "line": 36, + "rule": "media-query-list-comma-space-before", + "severity": "error", + "text": "Unexpected whitespace before \\",\\" (media-query-list-comma-space-before)", + }, + Object { + "column": 27, + "line": 40, + "rule": "media-query-list-comma-space-before", + "severity": "error", + "text": "Unexpected whitespace before \\",\\" (media-query-list-comma-space-before)", + }, +] +`; diff --git a/packages/stylelint-config/test/__snapshots__/properties.js.snap b/packages/stylelint-config/test/__snapshots__/properties.js.snap new file mode 100644 index 0000000000000..cb4c5a5bf2a9c --- /dev/null +++ b/packages/stylelint-config/test/__snapshots__/properties.js.snap @@ -0,0 +1,55 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`flags warnings with invalid properties css snapshot matches warnings 1`] = ` +Array [ + Object { + "column": 13, + "line": 2, + "rule": "color-hex-case", + "severity": "error", + "text": "Expected \\"#FFFFFF\\" to be \\"#ffffff\\" (color-hex-case)", + }, + Object { + "column": 13, + "line": 2, + "rule": "color-hex-length", + "severity": "error", + "text": "Expected \\"#FFFFFF\\" to be \\"#FFF\\" (color-hex-length)", + }, + Object { + "column": 2, + "line": 5, + "rule": "declaration-block-no-shorthand-property-overrides", + "severity": "error", + "text": "Unexpected shorthand \\"margin\\" after \\"margin-left\\" (declaration-block-no-shorthand-property-overrides)", + }, + Object { + "column": 13, + "line": 2, + "rule": "declaration-colon-space-after", + "severity": "error", + "text": "Expected single space after \\":\\" with a single-line declaration (declaration-colon-space-after)", + }, + Object { + "column": 2, + "line": 6, + "rule": "property-no-unknown", + "severity": "error", + "text": "Unexpected unknown property \\"argin\\" (property-no-unknown)", + }, + Object { + "column": 15, + "line": 4, + "rule": "unit-case", + "severity": "error", + "text": "Expected \\"PX\\" to be \\"px\\" (unit-case)", + }, + Object { + "column": 11, + "line": 3, + "rule": "value-keyword-case", + "severity": "error", + "text": "Expected \\"BLOCK\\" to be \\"block\\" (value-keyword-case)", + }, +] +`; diff --git a/packages/stylelint-config/test/__snapshots__/selectors-scss.js.snap b/packages/stylelint-config/test/__snapshots__/selectors-scss.js.snap new file mode 100644 index 0000000000000..30e2617192d20 --- /dev/null +++ b/packages/stylelint-config/test/__snapshots__/selectors-scss.js.snap @@ -0,0 +1,48 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`flags warnings with invalid selectors scss snapshot matches warnings 1`] = ` +Array [ + Object { + "column": 2, + "line": 3, + "rule": "scss/selector-no-redundant-nesting-selector", + "severity": "error", + "text": "Unnecessary nesting selector (&) (scss/selector-no-redundant-nesting-selector)", + }, + Object { + "column": 2, + "line": 10, + "rule": "scss/selector-no-redundant-nesting-selector", + "severity": "error", + "text": "Unnecessary nesting selector (&) (scss/selector-no-redundant-nesting-selector)", + }, + Object { + "column": 2, + "line": 17, + "rule": "scss/selector-no-redundant-nesting-selector", + "severity": "error", + "text": "Unnecessary nesting selector (&) (scss/selector-no-redundant-nesting-selector)", + }, + Object { + "column": 2, + "line": 24, + "rule": "scss/selector-no-redundant-nesting-selector", + "severity": "error", + "text": "Unnecessary nesting selector (&) (scss/selector-no-redundant-nesting-selector)", + }, + Object { + "column": 2, + "line": 31, + "rule": "scss/selector-no-redundant-nesting-selector", + "severity": "error", + "text": "Unnecessary nesting selector (&) (scss/selector-no-redundant-nesting-selector)", + }, + Object { + "column": 10, + "line": 31, + "rule": "selector-pseudo-element-colon-notation", + "severity": "error", + "text": "Expected double colon pseudo-element notation (selector-pseudo-element-colon-notation)", + }, +] +`; diff --git a/packages/stylelint-config/test/__snapshots__/selectors.js.snap b/packages/stylelint-config/test/__snapshots__/selectors.js.snap new file mode 100644 index 0000000000000..6debd6f6f38b0 --- /dev/null +++ b/packages/stylelint-config/test/__snapshots__/selectors.js.snap @@ -0,0 +1,62 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`flags warnings with invalid selectors css snapshot matches warnings 1`] = ` +Array [ + Object { + "column": 15, + "line": 18, + "rule": "declaration-property-unit-whitelist", + "severity": "error", + "text": "Unexpected unit \\"%\\" for property \\"line-height\\" (declaration-property-unit-whitelist)", + }, + Object { + "column": 1, + "line": 25, + "rule": "selector-class-pattern", + "severity": "error", + "text": "Selector should use lowercase and separate words with hyphens (selector-class-pattern)", + }, + Object { + "column": 1, + "line": 1, + "rule": "selector-id-pattern", + "severity": "error", + "text": "Selector should use lowercase and separate words with hyphens (selector-id-pattern)", + }, + Object { + "column": 1, + "line": 5, + "rule": "selector-id-pattern", + "severity": "error", + "text": "Selector should use lowercase and separate words with hyphens (selector-id-pattern)", + }, + Object { + "column": 4, + "line": 9, + "rule": "selector-id-pattern", + "severity": "error", + "text": "Selector should use lowercase and separate words with hyphens (selector-id-pattern)", + }, + Object { + "column": 1, + "line": 21, + "rule": "selector-id-pattern", + "severity": "error", + "text": "Selector should use lowercase and separate words with hyphens (selector-id-pattern)", + }, + Object { + "column": 10, + "line": 29, + "rule": "selector-pseudo-element-colon-notation", + "severity": "error", + "text": "Expected double colon pseudo-element notation (selector-pseudo-element-colon-notation)", + }, + Object { + "column": 12, + "line": 17, + "rule": "string-quotes", + "severity": "error", + "text": "Expected double quotes (string-quotes)", + }, +] +`; diff --git a/packages/stylelint-config/test/__snapshots__/structure.js.snap b/packages/stylelint-config/test/__snapshots__/structure.js.snap new file mode 100644 index 0000000000000..45da6df964818 --- /dev/null +++ b/packages/stylelint-config/test/__snapshots__/structure.js.snap @@ -0,0 +1,62 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`flags warnings with invalid structure css snapshot matches warnings 1`] = ` +Array [ + Object { + "column": 45, + "line": 7, + "rule": "block-closing-brace-newline-before", + "severity": "error", + "text": "Expected newline before \\"}\\" (block-closing-brace-newline-before)", + }, + Object { + "column": 14, + "line": 7, + "rule": "block-opening-brace-newline-after", + "severity": "error", + "text": "Expected newline after \\"{\\" (block-opening-brace-newline-after)", + }, + Object { + "column": 32, + "line": 7, + "rule": "declaration-block-semicolon-newline-after", + "severity": "error", + "text": "Expected newline after \\";\\" (declaration-block-semicolon-newline-after)", + }, + Object { + "column": 12, + "line": 1, + "rule": "selector-list-comma-newline-after", + "severity": "error", + "text": "Expected newline after \\",\\" (selector-list-comma-newline-after)", + }, + Object { + "column": 25, + "line": 1, + "rule": "selector-list-comma-newline-after", + "severity": "error", + "text": "Expected newline after \\",\\" (selector-list-comma-newline-after)", + }, + Object { + "column": 3, + "line": 4, + "rule": "indentation", + "severity": "error", + "text": "Expected indentation of 0 tabs (indentation)", + }, + Object { + "column": 3, + "line": 2, + "rule": "indentation", + "severity": "error", + "text": "Expected indentation of 1 tab (indentation)", + }, + Object { + "column": 3, + "line": 3, + "rule": "indentation", + "severity": "error", + "text": "Expected indentation of 1 tab (indentation)", + }, +] +`; diff --git a/packages/stylelint-config/test/__snapshots__/values.js.snap b/packages/stylelint-config/test/__snapshots__/values.js.snap new file mode 100644 index 0000000000000..20c229db69e23 --- /dev/null +++ b/packages/stylelint-config/test/__snapshots__/values.js.snap @@ -0,0 +1,69 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`flags warnings with invalid values css snapshot matches warnings 1`] = ` +Array [ + Object { + "column": 16, + "line": 2, + "rule": "declaration-block-trailing-semicolon", + "severity": "error", + "text": "Expected a trailing semicolon (declaration-block-trailing-semicolon)", + }, + Object { + "column": 13, + "line": 2, + "rule": "declaration-colon-space-after", + "severity": "error", + "text": "Expected single space after \\":\\" with a single-line declaration (declaration-colon-space-after)", + }, + Object { + "column": 15, + "line": 12, + "rule": "declaration-property-unit-whitelist", + "severity": "error", + "text": "Unexpected unit \\"em\\" for property \\"line-height\\" (declaration-property-unit-whitelist)", + }, + Object { + "column": 15, + "line": 10, + "rule": "font-family-name-quotes", + "severity": "error", + "text": "Expected quotes around \\"Times New Roman\\" (font-family-name-quotes)", + }, + Object { + "column": 15, + "line": 11, + "rule": "font-weight-notation", + "severity": "error", + "text": "Expected numeric font-weight notation (font-weight-notation)", + }, + Object { + "column": 11, + "line": 6, + "rule": "length-zero-no-unit", + "severity": "error", + "text": "Unexpected unit (length-zero-no-unit)", + }, + Object { + "column": 15, + "line": 6, + "rule": "length-zero-no-unit", + "severity": "error", + "text": "Unexpected unit (length-zero-no-unit)", + }, + Object { + "column": 24, + "line": 6, + "rule": "length-zero-no-unit", + "severity": "error", + "text": "Unexpected unit (length-zero-no-unit)", + }, + Object { + "column": 1, + "line": 15, + "rule": "no-duplicate-selectors", + "severity": "error", + "text": "Unexpected duplicate selector \\".selector\\", first used at line 1 (no-duplicate-selectors)", + }, +] +`; diff --git a/packages/stylelint-config/test/commenting-invalid.css b/packages/stylelint-config/test/commenting-invalid.css new file mode 100644 index 0000000000000..192f8ceae6036 --- /dev/null +++ b/packages/stylelint-config/test/commenting-invalid.css @@ -0,0 +1,24 @@ +/** +* #.# Section title +* +* Description of section, whether or not it has media queries, etc. +*/ +.selector { + float: left; +} +/** +* #.# Another section title +* +* Description of section, whether or not it has media queries, long comments +* should manually break the line length at 80 characters. +*/ +.another-selector { + float: right; +} +/* This is a comment about this selector */ +.one-more-another-selector { + position: absolute; + top: 0 !important; /* I should explain why this is so !important */ +} + +/* Comments shouldn't have a line length greater than 80 characters, they should manually break the line length at 80 characters */ diff --git a/packages/stylelint-config/test/commenting-valid.css b/packages/stylelint-config/test/commenting-valid.css new file mode 100644 index 0000000000000..e145e49471c7d --- /dev/null +++ b/packages/stylelint-config/test/commenting-valid.css @@ -0,0 +1,29 @@ +/** +* #.# Section title +* +* Description of section, whether or not it has media queries, etc. +*/ + +.selector { + float: left; +} + + +/** +* #.# Another section title +* +* Description of section, whether or not it has media queries, long comments +* should manually break the line length at 80 characters. +*/ + +.another-selector { + float: right; +} + +/* This is a comment about this selector */ +.one-more-selector { + position: absolute; + top: 0 !important; /* I should explain why this is so !important */ +} + +/* Long comments should manually break the line length at 80 characters. */ diff --git a/packages/stylelint-config/test/commenting.js b/packages/stylelint-config/test/commenting.js new file mode 100644 index 0000000000000..1a23a47434fc1 --- /dev/null +++ b/packages/stylelint-config/test/commenting.js @@ -0,0 +1,66 @@ +/** + * External dependencies + */ +const fs = require( 'fs' ), + stylelint = require( 'stylelint' ); + +/** + * Internal dependencies + */ +const config = require( '../' ), + validCss = fs.readFileSync( + './packages/stylelint-config/test/commenting-valid.css', + 'utf-8' + ), + invalidCss = fs.readFileSync( + './packages/stylelint-config/test/commenting-invalid.css', + 'utf-8' + ); + +describe( 'flags no warnings with valid commenting css', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: validCss, + config, + } ); + } ); + + it( 'did not error', () => { + return result.then( ( data ) => expect( data.errored ).toBeFalsy() ); + } ); + + it( 'flags no warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 0 ) + ); + } ); +} ); + +describe( 'flags warnings with invalid commenting css', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: invalidCss, + config, + } ); + } ); + + it( 'did error', () => { + return result.then( ( data ) => expect( data.errored ).toBeTruthy() ); + } ); + + it( 'flags correct number of warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 3 ) + ); + } ); + + it( 'snapshot matches warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toMatchSnapshot() + ); + } ); +} ); diff --git a/packages/stylelint-config/test/css-invalid.css b/packages/stylelint-config/test/css-invalid.css new file mode 100644 index 0000000000000..9b98086cd5f68 --- /dev/null +++ b/packages/stylelint-config/test/css-invalid.css @@ -0,0 +1,3 @@ +a { + top: .2em; +} diff --git a/packages/stylelint-config/test/css-valid.css b/packages/stylelint-config/test/css-valid.css new file mode 100644 index 0000000000000..363d12aed3ed6 --- /dev/null +++ b/packages/stylelint-config/test/css-valid.css @@ -0,0 +1,3 @@ +a { + top: 0.2em; +} diff --git a/packages/stylelint-config/test/functions-invalid.css b/packages/stylelint-config/test/functions-invalid.css new file mode 100644 index 0000000000000..33a93985335cf --- /dev/null +++ b/packages/stylelint-config/test/functions-invalid.css @@ -0,0 +1,5 @@ +/* function-name-case */ + +a { + width: Calc(5% - 10em); +} diff --git a/packages/stylelint-config/test/functions-valid.css b/packages/stylelint-config/test/functions-valid.css new file mode 100644 index 0000000000000..8219b38b2005c --- /dev/null +++ b/packages/stylelint-config/test/functions-valid.css @@ -0,0 +1,7 @@ +/* function-name-case */ + +a { + width: calc(5% - 10em); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#1e8cbe", endColorstr="#0074a2", GradientType=0); + filter: progid:DXImageTransform.Microsoft.Alpha(opacity=100); +} diff --git a/packages/stylelint-config/test/functions.js b/packages/stylelint-config/test/functions.js new file mode 100644 index 0000000000000..38b0fbf37a3a8 --- /dev/null +++ b/packages/stylelint-config/test/functions.js @@ -0,0 +1,66 @@ +/** + * External dependencies + */ +const fs = require( 'fs' ), + stylelint = require( 'stylelint' ); + +/** + * Internal dependencies + */ +const config = require( '../' ), + validCss = fs.readFileSync( + './packages/stylelint-config/test/functions-valid.css', + 'utf-8' + ), + invalidCss = fs.readFileSync( + './packages/stylelint-config/test/functions-invalid.css', + 'utf-8' + ); + +describe( 'flags no warnings with valid functions css', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: validCss, + config, + } ); + } ); + + it( 'did not error', () => { + return result.then( ( data ) => expect( data.errored ).toBeFalsy() ); + } ); + + it( 'flags no warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 0 ) + ); + } ); +} ); + +describe( 'flags warnings with invalid functions css', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: invalidCss, + config, + } ); + } ); + + it( 'did error', () => { + return result.then( ( data ) => expect( data.errored ).toBeTruthy() ); + } ); + + it( 'flags correct number of warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 1 ) + ); + } ); + + it( 'snapshot matches warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toMatchSnapshot() + ); + } ); +} ); diff --git a/packages/stylelint-config/test/index.js b/packages/stylelint-config/test/index.js new file mode 100644 index 0000000000000..dfc857e8a4504 --- /dev/null +++ b/packages/stylelint-config/test/index.js @@ -0,0 +1,66 @@ +/** + * External dependencies + */ +const fs = require( 'fs' ), + stylelint = require( 'stylelint' ); + +/** + * Internal dependencies + */ +const config = require( '../' ), + validCss = fs.readFileSync( + './packages/stylelint-config/test/css-valid.css', + 'utf-8' + ), + invalidCss = fs.readFileSync( + './packages/stylelint-config/test/css-invalid.css', + 'utf-8' + ); + +describe( 'flags no warnings with valid css', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: validCss, + config, + } ); + } ); + + it( 'did not error', () => { + return result.then( ( data ) => expect( data.errored ).toBeFalsy() ); + } ); + + it( 'flags no warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 0 ) + ); + } ); +} ); + +describe( 'flags warnings with invalid css', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: invalidCss, + config, + } ); + } ); + + it( 'did error', () => { + return result.then( ( data ) => expect( data.errored ).toBeTruthy() ); + } ); + + it( 'flags correct number of warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 1 ) + ); + } ); + + it( 'snapshot matches warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toMatchSnapshot() + ); + } ); +} ); diff --git a/packages/stylelint-config/test/media-queries-invalid.css b/packages/stylelint-config/test/media-queries-invalid.css new file mode 100644 index 0000000000000..c89a2776bb807 --- /dev/null +++ b/packages/stylelint-config/test/media-queries-invalid.css @@ -0,0 +1,43 @@ +@media all and (max-width:699px) { + + /* Your selectors */ +} + +@media all and (max-width :699px) { + + /* Your selectors */ +} + +@media all and (max-width 699px) { + + /* Your selectors */ +} + +@media all and (max-width>=699px) { + + /* Your selectors */ +} + +@media all and (max-width >=699px) { + + /* Your selectors */ +} + +@media all and (max-width>= 699px) { + + /* Your selectors */ +} + +@mdia all and (max-width>= 699px) { + + /* Your selectors */ +} + +@media screen and (color) , projection and (color) { + top: 0.2em; +} + +@media screen and (color) , + projection and (color) { + top: 0.2em; +} diff --git a/packages/stylelint-config/test/media-queries-valid.css b/packages/stylelint-config/test/media-queries-valid.css new file mode 100644 index 0000000000000..b373e6d8f1536 --- /dev/null +++ b/packages/stylelint-config/test/media-queries-valid.css @@ -0,0 +1,13 @@ +@media all and (max-width: 699px) and (min-width: 520px) { + + /* Your selectors */ +} + +@media screen and (color), + projection and (color) { + top: 0.2em; +} + +@media screen and (color), projection and (color) { + top: 0.2em; +} diff --git a/packages/stylelint-config/test/media-queries.js b/packages/stylelint-config/test/media-queries.js new file mode 100644 index 0000000000000..a3b59aa0fb541 --- /dev/null +++ b/packages/stylelint-config/test/media-queries.js @@ -0,0 +1,66 @@ +/** + * External dependencies + */ +const fs = require( 'fs' ), + stylelint = require( 'stylelint' ); + +/** + * Internal dependencies + */ +const config = require( '../' ), + validCss = fs.readFileSync( + './packages/stylelint-config/test/media-queries-valid.css', + 'utf-8' + ), + invalidCss = fs.readFileSync( + './packages/stylelint-config/test/media-queries-invalid.css', + 'utf-8' + ); + +describe( 'flags no warnings with valid media queries css', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: validCss, + config, + } ); + } ); + + it( 'did not error', () => { + return result.then( ( data ) => expect( data.errored ).toBeFalsy() ); + } ); + + it( 'flags no warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 0 ) + ); + } ); +} ); + +describe( 'flags warnings with invalid media queries css', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: invalidCss, + config, + } ); + } ); + + it( 'did error', () => { + return result.then( ( data ) => expect( data.errored ).toBeTruthy() ); + } ); + + it( 'flags correct number of warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 11 ) + ); + } ); + + it( 'snapshot matches warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toMatchSnapshot() + ); + } ); +} ); diff --git a/packages/stylelint-config/test/properties-invalid.css b/packages/stylelint-config/test/properties-invalid.css new file mode 100644 index 0000000000000..336b739f753b6 --- /dev/null +++ b/packages/stylelint-config/test/properties-invalid.css @@ -0,0 +1,7 @@ +#selector-1 { + background:#FFFFFF; + display: BLOCK; + margin-left: 20PX; + margin: 0; + argin: 20px; +} diff --git a/packages/stylelint-config/test/properties-valid.css b/packages/stylelint-config/test/properties-valid.css new file mode 100644 index 0000000000000..0fffa37ca4449 --- /dev/null +++ b/packages/stylelint-config/test/properties-valid.css @@ -0,0 +1,6 @@ +#selector-1 { + background: #fff; + display: block; + margin: 0; + margin-left: 20px; +} diff --git a/packages/stylelint-config/test/properties.js b/packages/stylelint-config/test/properties.js new file mode 100644 index 0000000000000..35cedc7697515 --- /dev/null +++ b/packages/stylelint-config/test/properties.js @@ -0,0 +1,66 @@ +/** + * External dependencies + */ +const fs = require( 'fs' ), + stylelint = require( 'stylelint' ); + +/** + * Internal dependencies + */ +const config = require( '../' ), + validCss = fs.readFileSync( + './packages/stylelint-config/test/properties-valid.css', + 'utf-8' + ), + invalidCss = fs.readFileSync( + './packages/stylelint-config/test/properties-invalid.css', + 'utf-8' + ); + +describe( 'flags no warnings with valid properties css', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: validCss, + config, + } ); + } ); + + it( 'did not error', () => { + return result.then( ( data ) => expect( data.errored ).toBeFalsy() ); + } ); + + it( 'flags no warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 0 ) + ); + } ); +} ); + +describe( 'flags warnings with invalid properties css', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: invalidCss, + config, + } ); + } ); + + it( 'did error', () => { + return result.then( ( data ) => expect( data.errored ).toBeTruthy() ); + } ); + + it( 'flags correct number of warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 7 ) + ); + } ); + + it( 'snapshot matches warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toMatchSnapshot() + ); + } ); +} ); diff --git a/packages/stylelint-config/test/scss-invalid.scss b/packages/stylelint-config/test/scss-invalid.scss new file mode 100644 index 0000000000000..c73e35ab61a25 --- /dev/null +++ b/packages/stylelint-config/test/scss-invalid.scss @@ -0,0 +1,32 @@ +@unknown { + display: block; +} + +a { + + @debug 1; +} + +@if $foo == block { + display: block; +} + +@else{ + display: inline-block; +} + +b { + + @include foo; + + @include bar; +} + +p { + + /* Test `stylelint-config-recommended` inherited `no-extra-semicolons` rule */ + @include foo;; + + /* Test `stylelint-config-wordpress` inherited `number-leading-zero` rule */ + top: .2em; +} diff --git a/packages/stylelint-config/test/scss-valid.scss b/packages/stylelint-config/test/scss-valid.scss new file mode 100644 index 0000000000000..e424c7cfe37a4 --- /dev/null +++ b/packages/stylelint-config/test/scss-valid.scss @@ -0,0 +1,32 @@ +@import "path/to/foo.scss"; + +@function fooBar { + + @return 1; +} + +@mixin foo { + + @content; +} + +$map: ( + "foo": 1, + "bar": 2, + "baz": 3 +); + +@if $foo == block { + display: block; +} @else { + display: inline-block; +} + +@import "../some/url"; +@import "../another/url"; + +b { + + @include foo; + @include bar; +} diff --git a/packages/stylelint-config/test/scss.js b/packages/stylelint-config/test/scss.js new file mode 100644 index 0000000000000..c64537ee07e6b --- /dev/null +++ b/packages/stylelint-config/test/scss.js @@ -0,0 +1,67 @@ +/** + * External dependencies + */ +const fs = require( 'fs' ), + stylelint = require( 'stylelint' ); + +/** + * Internal dependencies + */ +const config = require( '../scss' ), + validScss = fs.readFileSync( + './packages/stylelint-config/test/scss-valid.scss', + 'utf-8' + ), + invalidScss = fs.readFileSync( + './packages/stylelint-config/test/scss-invalid.scss', + 'utf-8' + ); + +describe( 'flags no warnings with valid scss', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: validScss, + config, + } ); + } ); + + it( 'did not error', () => { + return result.then( ( data ) => expect( data.errored ).toBeFalsy() ); + } ); + + it( 'flags no warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 0 ) + ); + } ); +} ); + +describe( 'flags warnings with invalid scss', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: invalidScss, + config, + } ); + } ); + + it( 'did error', () => { + return result.then( ( data ) => expect( data.errored ).toBeTruthy() ); + } ); + + it( 'flags correct number of warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 8 ) + ); + } ); + + // ToDo: Fix snapshot, as results differ between Node.js v10 & v12 + // it( 'snapshot matches warnings', () => { + // return result.then( ( data ) => ( + // expect( data.results[ 0 ].warnings ).toMatchSnapshot() + // ) ); + // } ); +} ); diff --git a/packages/stylelint-config/test/selectors-invalid.css b/packages/stylelint-config/test/selectors-invalid.css new file mode 100644 index 0000000000000..bf0716916420f --- /dev/null +++ b/packages/stylelint-config/test/selectors-invalid.css @@ -0,0 +1,31 @@ +#commentForm { /* Avoid camelcase. */ + margin: 0; +} + +#comment_form { /* Avoid underscores. */ + margin: 0; +} + +div#comment_form { /* Avoid over-qualification. */ + margin: 0; +} + +#c1-xr { /* What is a c1-xr?! Use a better name. */ + margin: 0; +} + +input[type='text'] { /* Should be [type="text"] */ + line-height: 110% /* Also doubly incorrect */ +} + +#Selector { + color: #000; +} + +.selectorA { + color: #000; +} + +.selector:after { + color: #000; +} diff --git a/packages/stylelint-config/test/selectors-invalid.scss b/packages/stylelint-config/test/selectors-invalid.scss new file mode 100644 index 0000000000000..d1bb44f841dba --- /dev/null +++ b/packages/stylelint-config/test/selectors-invalid.scss @@ -0,0 +1,34 @@ +.foo { + + & > .bar { + margin: 0; + } +} + +a { + + & a { + margin: 0; + } +} + +div { + + & > a { + margin: 0; + } +} + +p { + + & .class { + margin: 0; + } +} + +span { + + & .class:after { + margin: 0; + } +} diff --git a/packages/stylelint-config/test/selectors-scss.js b/packages/stylelint-config/test/selectors-scss.js new file mode 100644 index 0000000000000..94a85ff86543e --- /dev/null +++ b/packages/stylelint-config/test/selectors-scss.js @@ -0,0 +1,66 @@ +/** + * External dependencies + */ +const fs = require( 'fs' ), + stylelint = require( 'stylelint' ); + +/** + * Internal dependencies + */ +const config = require( '../scss' ), + validScss = fs.readFileSync( + './packages/stylelint-config/test/selectors-valid.scss', + 'utf-8' + ), + invalidScss = fs.readFileSync( + './packages/stylelint-config/test/selectors-invalid.scss', + 'utf-8' + ); + +describe( 'flags no warnings with valid selectors scss', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: validScss, + config, + } ); + } ); + + it( 'did not error', () => { + return result.then( ( data ) => expect( data.errored ).toBeFalsy() ); + } ); + + it( 'flags no warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 0 ) + ); + } ); +} ); + +describe( 'flags warnings with invalid selectors scss', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: invalidScss, + config, + } ); + } ); + + it( 'did error', () => { + return result.then( ( data ) => expect( data.errored ).toBeTruthy() ); + } ); + + it( 'flags correct number of warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 6 ) + ); + } ); + + it( 'snapshot matches warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toMatchSnapshot() + ); + } ); +} ); diff --git a/packages/stylelint-config/test/selectors-valid.css b/packages/stylelint-config/test/selectors-valid.css new file mode 100644 index 0000000000000..19a87ff51f35d --- /dev/null +++ b/packages/stylelint-config/test/selectors-valid.css @@ -0,0 +1,19 @@ +#comment-form { + margin: 1em 0; +} + +input[type="text"] { + line-height: 1.1; +} + +.selector::after { + color: #000; +} + +.selector-class { + color: #000; +} + +#selector-id { + color: #000; +} diff --git a/packages/stylelint-config/test/selectors-valid.scss b/packages/stylelint-config/test/selectors-valid.scss new file mode 100644 index 0000000000000..a6d4db9172be4 --- /dev/null +++ b/packages/stylelint-config/test/selectors-valid.scss @@ -0,0 +1,37 @@ +.foo { + + > .bar { + margin: 0; + } +} + +a { + + &.foo { + margin: 0; + } +} + +div { + + .foo > & { + margin: 0; + } +} + +p { + + &, + .foo, + .baz { + margin: 0; + } +} + +span { + + &, + .foo::after { + color: #000; + } +} diff --git a/packages/stylelint-config/test/selectors.js b/packages/stylelint-config/test/selectors.js new file mode 100644 index 0000000000000..337d1d00eed31 --- /dev/null +++ b/packages/stylelint-config/test/selectors.js @@ -0,0 +1,66 @@ +/** + * External dependencies + */ +const fs = require( 'fs' ), + stylelint = require( 'stylelint' ); + +/** + * Internal dependencies + */ +const config = require( '../' ), + validCss = fs.readFileSync( + './packages/stylelint-config/test/selectors-valid.css', + 'utf-8' + ), + invalidCss = fs.readFileSync( + './packages/stylelint-config/test/selectors-invalid.css', + 'utf-8' + ); + +describe( 'flags no warnings with valid selectors css', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: validCss, + config, + } ); + } ); + + it( 'did not error', () => { + return result.then( ( data ) => expect( data.errored ).toBeFalsy() ); + } ); + + it( 'flags no warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 0 ) + ); + } ); +} ); + +describe( 'flags warnings with invalid selectors css', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: invalidCss, + config, + } ); + } ); + + it( 'did error', () => { + return result.then( ( data ) => expect( data.errored ).toBeTruthy() ); + } ); + + it( 'flags correct number of warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 8 ) + ); + } ); + + it( 'snapshot matches warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toMatchSnapshot() + ); + } ); +} ); diff --git a/packages/stylelint-config/test/structure-invalid.css b/packages/stylelint-config/test/structure-invalid.css new file mode 100644 index 0000000000000..78820847ae9d8 --- /dev/null +++ b/packages/stylelint-config/test/structure-invalid.css @@ -0,0 +1,7 @@ +#selector-1, #selector-2, #selector-3 { + background: #fff; + color: #000; + } + + +#selector-1 { background: #fff; color: #000; } diff --git a/packages/stylelint-config/test/structure-valid.css b/packages/stylelint-config/test/structure-valid.css new file mode 100644 index 0000000000000..b7b28949f3cd5 --- /dev/null +++ b/packages/stylelint-config/test/structure-valid.css @@ -0,0 +1,29 @@ +#selector-1, +#selector-2, +#selector-3 { + background: #fff; + color: #000; +} + +#selector-4 { + background: #fff; + color: #000; +} + +h1, +.heading-size-1 { + background: #fff; + color: #000; +} + +h2, +.heading-size-2 { + background: #fff; + color: #000; +} + +h3, +.heading-size-3 { + background: #fff; + color: #000; +} diff --git a/packages/stylelint-config/test/structure.js b/packages/stylelint-config/test/structure.js new file mode 100644 index 0000000000000..7ec03a3b667ba --- /dev/null +++ b/packages/stylelint-config/test/structure.js @@ -0,0 +1,66 @@ +/** + * External dependencies + */ +const fs = require( 'fs' ), + stylelint = require( 'stylelint' ); + +/** + * Internal dependencies + */ +const config = require( '../' ), + validCss = fs.readFileSync( + './packages/stylelint-config/test/structure-valid.css', + 'utf-8' + ), + invalidCss = fs.readFileSync( + './packages/stylelint-config/test/structure-invalid.css', + 'utf-8' + ); + +describe( 'flags no warnings with valid structure css', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: validCss, + config, + } ); + } ); + + it( 'did not error', () => { + return result.then( ( data ) => expect( data.errored ).toBeFalsy() ); + } ); + + it( 'flags no warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 0 ) + ); + } ); +} ); + +describe( 'flags warnings with invalid structure css', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: invalidCss, + config, + } ); + } ); + + it( 'did error', () => { + return result.then( ( data ) => expect( data.errored ).toBeTruthy() ); + } ); + + it( 'flags correct number of warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 8 ) + ); + } ); + + it( 'snapshot matches warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toMatchSnapshot() + ); + } ); +} ); diff --git a/packages/stylelint-config/test/themes-valid.css b/packages/stylelint-config/test/themes-valid.css new file mode 100644 index 0000000000000..de9a2fb8193a6 --- /dev/null +++ b/packages/stylelint-config/test/themes-valid.css @@ -0,0 +1,16 @@ +/* +Theme Name: Twenty Ten +Theme URI: https://wordpress.org/themes/twentyten/themes/twentyten/themes/twentyten/themes/twentyten/ +Description: The 2010 theme for WordPress is stylish, customizable, simple, and readable -- make it yours with a custom menu, header image, and background. Twenty Ten supports six widgetized areas (two in the sidebar, four in the footer) and featured images (thumbnails for gallery posts and custom header images for posts and pages). It includes stylesheets for print and the admin Visual Editor, special styles for posts in the "Asides" and "Gallery" categories, and has an optional one-column page template that removes the sidebar. +Author: the WordPress team +Author URI: https://wordpress.org/ +Version: 2.3 +License: GNU General Public License v2 or later +License URI: http://www.gnu.org/licenses/gpl-2.0.html +Tags: blog, two-columns, custom-header, custom-background, threaded-comments, sticky-post, translation-ready, microformats, rtl-language-support, editor-style, custom-menu, flexible-header, featured-images, footer-widgets, featured-image-header +Text Domain: twentyten +*/ + +a { + top: 0.2em; +} diff --git a/packages/stylelint-config/test/themes.js b/packages/stylelint-config/test/themes.js new file mode 100644 index 0000000000000..f0016832b24d7 --- /dev/null +++ b/packages/stylelint-config/test/themes.js @@ -0,0 +1,35 @@ +/** + * External dependencies + */ +const fs = require( 'fs' ), + stylelint = require( 'stylelint' ); + +/** + * Internal dependencies + */ +const config = require( '../' ), + validCss = fs.readFileSync( + './packages/stylelint-config/test/themes-valid.css', + 'utf-8' + ); + +describe( 'flags no warnings with valid css', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: validCss, + config, + } ); + } ); + + it( 'did not error', () => { + return result.then( ( data ) => expect( data.errored ).toBeFalsy() ); + } ); + + it( 'flags no warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 0 ) + ); + } ); +} ); diff --git a/packages/stylelint-config/test/values-invalid.css b/packages/stylelint-config/test/values-invalid.css new file mode 100644 index 0000000000000..d9ce259e58c8c --- /dev/null +++ b/packages/stylelint-config/test/values-invalid.css @@ -0,0 +1,17 @@ +.selector { /* Avoid missing space and semicolon */ + background:#fff +} + +.another-selector { /* Avoid adding a unit on a zero value */ + margin: 0px 0px 20px 0px; +} + +.one-more-selector { + font-family: Times New Roman, serif; /* Quote font names when required */ + font-weight: bold; /* Avoid named font weights */ + line-height: 1.4em; +} + +.selector { /* Avoid duplicate selectors */ + background: #fff; +} diff --git a/packages/stylelint-config/test/values-valid.css b/packages/stylelint-config/test/values-valid.css new file mode 100644 index 0000000000000..ca9ccb5f188c2 --- /dev/null +++ b/packages/stylelint-config/test/values-valid.css @@ -0,0 +1,15 @@ +.selector { /* Correct usage of quotes */ + background-image: url(images/bg.png); + font-family: "Helvetica Neue", sans-serif; + font-weight: 700; + line-height: 14px; +} + +.another-selector { /* Correct usage of zero values */ + font-family: Georgia, serif; + font-weight: bolder; /* Ignore relative font weights */ + line-height: 1.4; + text-shadow: + 0 -1px 0 rgba(0, 0, 0, 0.5), + 0 1px 0 #fff; +} diff --git a/packages/stylelint-config/test/values.js b/packages/stylelint-config/test/values.js new file mode 100644 index 0000000000000..97cbc58e02f3b --- /dev/null +++ b/packages/stylelint-config/test/values.js @@ -0,0 +1,66 @@ +/** + * External dependencies + */ +const fs = require( 'fs' ), + stylelint = require( 'stylelint' ); + +/** + * Internal dependencies + */ +const config = require( '../' ), + validCss = fs.readFileSync( + './packages/stylelint-config/test/values-valid.css', + 'utf-8' + ), + invalidCss = fs.readFileSync( + './packages/stylelint-config/test/values-invalid.css', + 'utf-8' + ); + +describe( 'flags no warnings with valid values css', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: validCss, + config, + } ); + } ); + + it( 'did not error', () => { + return result.then( ( data ) => expect( data.errored ).toBeFalsy() ); + } ); + + it( 'flags no warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 0 ) + ); + } ); +} ); + +describe( 'flags warnings with invalid values css', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: invalidCss, + config, + } ); + } ); + + it( 'did error', () => { + return result.then( ( data ) => expect( data.errored ).toBeTruthy() ); + } ); + + it( 'flags correct number of warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 9 ) + ); + } ); + + it( 'snapshot matches warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toMatchSnapshot() + ); + } ); +} ); diff --git a/packages/stylelint-config/test/vendor-prefixes-valid.css b/packages/stylelint-config/test/vendor-prefixes-valid.css new file mode 100644 index 0000000000000..e46698570d9ff --- /dev/null +++ b/packages/stylelint-config/test/vendor-prefixes-valid.css @@ -0,0 +1,5 @@ +.sample-output { + -webkit-box-shadow: inset 0 0 1px 1px #eee; + -moz-box-shadow: inset 0 0 1px 1px #eee; + box-shadow: inset 0 0 1px 1px #eee; +} diff --git a/packages/stylelint-config/test/vendor-prefixes.js b/packages/stylelint-config/test/vendor-prefixes.js new file mode 100644 index 0000000000000..e3ec4d2a7e5df --- /dev/null +++ b/packages/stylelint-config/test/vendor-prefixes.js @@ -0,0 +1,35 @@ +/** + * External dependencies + */ +const fs = require( 'fs' ), + stylelint = require( 'stylelint' ); + +/** + * Internal dependencies + */ +const config = require( '../' ), + validCss = fs.readFileSync( + './packages/stylelint-config/test/vendor-prefixes-valid.css', + 'utf-8' + ); + +describe( 'flags no warnings with valid vendor prefixes css', () => { + let result; + + beforeEach( () => { + result = stylelint.lint( { + code: validCss, + config, + } ); + } ); + + it( 'did not error', () => { + return result.then( ( data ) => expect( data.errored ).toBeFalsy() ); + } ); + + it( 'flags no warnings', () => { + return result.then( ( data ) => + expect( data.results[ 0 ].warnings ).toHaveLength( 0 ) + ); + } ); +} );