postcss-sorting
Advanced tools
Comparing version 2.1.0 to 3.0.0
@@ -5,2 +5,17 @@ # Change Log | ||
## 3.0.0 | ||
This is a cleanup release. Removed everything not related to ordering stylesheets. I recommend to use combination [stylelint 7.11+](https://stylelint.io/) with `--fix` option and [stylelint-order 0.5+](https://github.com/hudochenkov/stylelint-order) plugin instead of this plugin. Using combination above you'll receive linting and autofixing using only one tool! | ||
* Removed options: | ||
* `at-rule-nested-empty-line-before` | ||
* `clean-empty-lines` | ||
* `comment-empty-line-before` | ||
* `custom-property-empty-line-before` | ||
* `declaration-empty-line-before` | ||
* `dollar-variable-empty-line-before` | ||
* `rule-nested-empty-line-before` | ||
* Changes to `properties-order`: | ||
* Removed `emptyLineBefore` option. | ||
* Removed objects support in configuration. Use plain arrays instead. | ||
## 2.1.0 | ||
@@ -7,0 +22,0 @@ * Added: `order` supports new `rule` extended object, which has new `selector` option. Rules in `order` can be specified by their selector. |
17
index.js
@@ -6,5 +6,4 @@ 'use strict'; | ||
const features = require('./lib/features'); | ||
const isSet = require('./lib/isSet'); | ||
const normalizeOptions = require('./lib/normalizeOptions'); | ||
const order = require('./lib/order'); | ||
const propertiesOrder = require('./lib/properties-order'); | ||
const validateOptions = require('./lib/validateOptions'); | ||
@@ -29,9 +28,9 @@ | ||
opts = normalizeOptions(opts); | ||
if (opts.order) { | ||
order(css, opts); | ||
} | ||
Object.keys(features).forEach(function (featureName) { | ||
if (isSet(opts[featureName])) { | ||
features[featureName](css, opts); | ||
} | ||
}); | ||
if (opts['properties-order']) { | ||
propertiesOrder(css, opts); | ||
} | ||
} |
@@ -34,10 +34,2 @@ 'use strict'; | ||
if ( | ||
!_.isUndefined(options['clean-empty-lines']) | ||
&& !_.isNull(options['clean-empty-lines']) | ||
&& !validateCleanEmptyLines(options['clean-empty-lines']) | ||
) { | ||
return reportInvalidOption('clean-empty-lines'); | ||
} | ||
if ( | ||
!_.isUndefined(options['unspecified-properties-position']) | ||
@@ -50,50 +42,2 @@ && !_.isNull(options['unspecified-properties-position']) | ||
if ( | ||
!_.isUndefined(options['custom-property-empty-line-before']) | ||
&& !_.isNull(options['custom-property-empty-line-before']) | ||
&& !validateCustomPropertyEmptyLineBefore(options['custom-property-empty-line-before']) | ||
) { | ||
return reportInvalidOption('custom-property-empty-line-before'); | ||
} | ||
if ( | ||
!_.isUndefined(options['dollar-variable-empty-line-before']) | ||
&& !_.isNull(options['dollar-variable-empty-line-before']) | ||
&& !validateDollarVariableEmptyLineBefore(options['dollar-variable-empty-line-before']) | ||
) { | ||
return reportInvalidOption('dollar-variable-empty-line-before'); | ||
} | ||
if ( | ||
!_.isUndefined(options['declaration-empty-line-before']) | ||
&& !_.isNull(options['declaration-empty-line-before']) | ||
&& !validateDeclarationEmptyLineBefore(options['declaration-empty-line-before']) | ||
) { | ||
return reportInvalidOption('declaration-empty-line-before'); | ||
} | ||
if ( | ||
!_.isUndefined(options['rule-nested-empty-line-before']) | ||
&& !_.isNull(options['rule-nested-empty-line-before']) | ||
&& !validateRuleNestedEmptyLineBefore(options['rule-nested-empty-line-before']) | ||
) { | ||
return reportInvalidOption('rule-nested-empty-line-before'); | ||
} | ||
if ( | ||
!_.isUndefined(options['at-rule-nested-empty-line-before']) | ||
&& !_.isNull(options['at-rule-nested-empty-line-before']) | ||
&& !validateAtRuleNestedEmptyLineBefore(options['at-rule-nested-empty-line-before']) | ||
) { | ||
return reportInvalidOption('at-rule-nested-empty-line-before'); | ||
} | ||
if ( | ||
!_.isUndefined(options['comment-empty-line-before']) | ||
&& !_.isNull(options['comment-empty-line-before']) | ||
&& !validateCommentEmptyLineBefore(options['comment-empty-line-before']) | ||
) { | ||
return reportInvalidOption('comment-empty-line-before'); | ||
} | ||
return true; | ||
@@ -110,42 +54,2 @@ }; | ||
function validateSecondaryOptions(opts) { | ||
if (!_.isUndefined(opts.options[1])) { | ||
if (!_.isPlainObject(opts.options[1])) { | ||
return false; | ||
} | ||
if (!validateSingleSecondaryOption({ | ||
opts: opts.options[1], | ||
name: 'except', | ||
possible: opts.exceptPossible, | ||
})) { | ||
return false; | ||
} | ||
if (!validateSingleSecondaryOption({ | ||
opts: opts.options[1], | ||
name: 'ignore', | ||
possible: opts.ignorePossible, | ||
})) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
function validateSingleSecondaryOption(option) { | ||
if (!_.isUndefined(option.opts[option.name])) { | ||
if (!_.isArray(option.opts[option.name])) { | ||
return false; | ||
} | ||
if (!option.opts[option.name].every((item) => _.includes(option.possible, item))) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
function validateOrder(options) { | ||
@@ -222,35 +126,10 @@ // Otherwise, begin checking array options | ||
// Every item in the array must be a string or an object | ||
// with a "properties" property | ||
let shouldBeStringsOrObjects = false; | ||
if (options.every((item) => _.isString(item))) { | ||
shouldBeStringsOrObjects = true; | ||
} else if (options.every((item) => _.isPlainObject(item) && !_.isUndefined(item.properties))) { | ||
shouldBeStringsOrObjects = true; | ||
} | ||
if (!shouldBeStringsOrObjects) { | ||
// Every item in the array must be a string | ||
if (!options.every((item) => _.isString(item))) { | ||
return false; | ||
} | ||
const objectItems = options.filter(_.isPlainObject); | ||
if (!objectItems.every((item) => { | ||
if (!_.isUndefined(item.emptyLineBefore) && !_.isBoolean(item.emptyLineBefore)) { | ||
return false; | ||
} | ||
return true; | ||
})) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
function validateCleanEmptyLines(options) { | ||
return _.isBoolean(options); | ||
} | ||
function validateUnspecifiedPropertiesPosition(options) { | ||
@@ -260,161 +139,1 @@ return _.isString(options) | ||
} | ||
function validateCustomPropertyEmptyLineBefore(options) { | ||
if (_.isBoolean(options)) { | ||
return true; | ||
} | ||
if (!_.isArray(options)) { | ||
return false; | ||
} | ||
if (!_.isBoolean(options[0])) { | ||
return false; | ||
} | ||
if (!validateSecondaryOptions({ | ||
options, | ||
exceptPossible: ['after-comment', 'after-custom-property', 'first-nested'], | ||
ignorePossible: ['after-comment', 'inside-single-line-block'], | ||
})) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
function validateDollarVariableEmptyLineBefore(options) { | ||
if (_.isBoolean(options)) { | ||
return true; | ||
} | ||
if (!_.isArray(options)) { | ||
return false; | ||
} | ||
if (!_.isBoolean(options[0])) { | ||
return false; | ||
} | ||
if (!validateSecondaryOptions({ | ||
options, | ||
exceptPossible: ['after-comment', 'after-dollar-variable', 'first-nested'], | ||
ignorePossible: ['after-comment', 'inside-single-line-block'], | ||
})) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
function validateDeclarationEmptyLineBefore(options) { | ||
if (_.isBoolean(options)) { | ||
return true; | ||
} | ||
if (!_.isArray(options)) { | ||
return false; | ||
} | ||
if (!_.isBoolean(options[0])) { | ||
return false; | ||
} | ||
if (!validateSecondaryOptions({ | ||
options, | ||
exceptPossible: ['after-comment', 'after-declaration', 'first-nested'], | ||
ignorePossible: ['after-comment', 'after-declaration', 'inside-single-line-block'], | ||
})) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
function validateRuleNestedEmptyLineBefore(options) { | ||
if (_.isBoolean(options)) { | ||
return true; | ||
} | ||
if (_.isString(options)) { | ||
return _.includes(['always-multi-line', 'never-multi-line'], options); | ||
} | ||
if (!_.isArray(options)) { | ||
return false; | ||
} | ||
if (!_.includes([true, false, 'always-multi-line', 'never-multi-line'], options[0])) { | ||
return false; | ||
} | ||
if (!validateSecondaryOptions({ | ||
options, | ||
exceptPossible: ['first-nested', 'after-rule'], | ||
ignorePossible: ['after-comment'], | ||
})) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
function validateAtRuleNestedEmptyLineBefore(options) { | ||
if (_.isBoolean(options)) { | ||
return true; | ||
} | ||
if (!_.isArray(options)) { | ||
return false; | ||
} | ||
if (!_.isBoolean(options[0])) { | ||
return false; | ||
} | ||
if (!validateSecondaryOptions({ | ||
options, | ||
exceptPossible: ['blockless-after-same-name-blockless', 'blockless-after-blockless', 'first-nested', 'after-same-name'], | ||
ignorePossible: ['blockless-after-same-name-blockless', 'blockless-after-blockless', 'after-comment'], | ||
})) { | ||
return false; | ||
} | ||
if (!_.isUndefined(options[1])) { | ||
if (!_.isUndefined(options[1].ignoreAtRules)) { | ||
if (!_.isArray(options[1].ignoreAtRules)) { | ||
return false; | ||
} | ||
if (!options[1].ignoreAtRules.every((item) => _.isString(item))) { | ||
return false; | ||
} | ||
} | ||
} | ||
return true; | ||
} | ||
function validateCommentEmptyLineBefore(options) { | ||
if (_.isBoolean(options)) { | ||
return true; | ||
} | ||
if (!_.isArray(options)) { | ||
return false; | ||
} | ||
if (!_.isBoolean(options[0])) { | ||
return false; | ||
} | ||
if (!validateSecondaryOptions({ | ||
options, | ||
exceptPossible: ['first-nested'], | ||
ignorePossible: ['after-comment', 'stylelint-command'], | ||
})) { | ||
return false; | ||
} | ||
return true; | ||
} |
{ | ||
"name": "postcss-sorting", | ||
"version": "2.1.0", | ||
"version": "3.0.0", | ||
"description": "PostCSS plugin to keep rules and at-rules content in order.", | ||
@@ -20,4 +20,4 @@ "keywords": [ | ||
"files": [ | ||
"docs", | ||
"lib", | ||
"!lib/**/__tests__", | ||
"index.js" | ||
@@ -30,3 +30,3 @@ ], | ||
"lodash": "^4.17.4", | ||
"postcss": "^5.2.17" | ||
"postcss": "^6.0.1" | ||
}, | ||
@@ -43,3 +43,3 @@ "devDependencies": { | ||
"coverage": "jest --coverage", | ||
"lint": "eslint index.js lib/*.js __tests__/*.js" | ||
"lint": "eslint *.js 'lib/**/*.js'" | ||
}, | ||
@@ -46,0 +46,0 @@ "jest": { |
153
README.md
@@ -5,5 +5,5 @@ # PostCSS Sorting [![Build Status][ci-img]][ci] [![npm version][npm-version-img]][npm] [![npm downloads last month][npm-downloads-img]][npm] [![Dependency status][dependencies-img]][dependencies-status] | ||
Also available as [Sublime Text plugin], [Atom plugin], and [VS Code plugin]. | ||
Also available as [Sublime Text], [Atom], [VS Code], and [Emacs] plugin. | ||
Lint style sheets order with [stylelint-order]. | ||
Lint and autofix style sheets order with [stylelint-order]. | ||
@@ -16,3 +16,2 @@ ## Features | ||
* Groups properties, custom properties, dollar variables, nested rules, nested at-rules. | ||
* Adds empty lines before different types of nodes. | ||
* Supports CSS, SCSS (if [postcss-scss] parser is used), [PreCSS] and most likely any other syntax added by other PostCSS plugins. | ||
@@ -30,54 +29,12 @@ | ||
### Order | ||
- [`order`](./lib/order/README.md): Specify the order of content within declaration blocks. | ||
- [`properties-order`](./lib/properties-order/README.md): Specify the order of properties within declaration blocks. | ||
- [`unspecified-properties-position`](./lib/properties-order/unspecified-properties-position.md): Specify position for properties not specified in `properties-order`. | ||
- [`order`](./docs/order.md): Specify the order of content within declaration blocks. | ||
- [`properties-order`](./docs/properties-order.md): Specify the order of properties within declaration blocks. Can specify empty line before property groups. | ||
- [`unspecified-properties-position`](./docs/unspecified-properties-position.md): Specify position for properties not specified in `properties-order`. | ||
### Empty lines | ||
- [`clean-empty-lines`](./docs/clean-empty-lines.md): Remove all empty lines. Runs before all other rules. | ||
- [`rule-nested-empty-line-before`](./docs/rule-nested-empty-line-before.md): Specify an empty line before nested rules. | ||
- [`at-rule-nested-empty-line-before`](./docs/at-rule-nested-empty-line-before.md): Specify an empty line before nested at-rules. | ||
- [`declaration-empty-line-before`](./docs/declaration-empty-line-before.md): Specify an empty line before declarations. | ||
- [`custom-property-empty-line-before`](./docs/custom-property-empty-line-before.md): Specify an empty line before custom properties. | ||
- [`dollar-variable-empty-line-before`](./docs/dollar-variable-empty-line-before.md): Specify an empty line before `$`-variable declarations. | ||
- [`comment-empty-line-before`](./docs/comment-empty-line-before.md): Specify an empty line before comments. | ||
## Handling comments | ||
Shared-line comments are comments which are located after a node and on the same line as a node. | ||
Comments that are before node and on a separate line linked to that node. Shared-line comments are also linked to that node. Shared-line comments are comments which are located after a node and on the same line as a node. | ||
```css | ||
a { | ||
/* regular comment */ | ||
color: pink; /* shared-line comment */ | ||
} | ||
``` | ||
Shared-line comments are always ignored in all “empty lines before” options. The plugin always looks “through” these comments. For example: | ||
```js | ||
{ | ||
"declaration-empty-line-before": [true, { | ||
except: "after-declaration" | ||
}] | ||
} | ||
``` | ||
Technically there is a comment before `bottom`. But it's a shared line comment, so plugin looks before this comment and sees `top`: | ||
```css | ||
a { | ||
--prop: pink; | ||
top: 5px; /* shared-line comment */ | ||
bottom: 15px; | ||
} | ||
``` | ||
For “order” options comments that are before node and on a separate line linked to that node. Shared-line comments are also linked to that node. | ||
```css | ||
a { | ||
top: 5px; /* shared-line comment belongs to `top` */ | ||
@@ -90,71 +47,14 @@ /* comment belongs to `bottom` */ | ||
## Migration from `1.x` | ||
## Migration from `2.x` | ||
If you have been using [predefined configs], you can look at [migrated predefined configs]. | ||
Remove all `*-empty-line-before` and `clean-empty-lines` options. Use [stylelint] with `--fix` option instead. | ||
`sort-order` was split into [`order`](./docs/order.md) and [`properties-order`](./docs/properties-order.md). | ||
`properties-order` doesn't support property groups. Convert it to simple array. Use [stylelint-order] with `--fix` option for empty line before property groups. | ||
`properties-order` now uses an array of objects for grouping. | ||
`sort-order` keywords to new config conversion: | ||
| `1.x` | `2.x` | | ||
| --- | --- | | ||
| `@atrule` | `{ order: ["at-rules"] }` or `{ order: [{ type: "at-rule" }] }` | | ||
| `@atrulename` | `{ order: [{ type: "at-rule", name: "atrulename" }] }` | | ||
| `@atrulename parameter` | `{ order: [{ type: "at-rule", name: "atrulename", parameter: "parameter" }] }` | | ||
| `>child` | `{ order: ["rules"] }` | | ||
| `$variable` | `{ order: ["custom-properties", "dollar-variables"] }` | | ||
| “leftovers” token `...` | `{ "unspecified-properties-position": "bottom" }` | | ||
Config for `1.x`: | ||
```js | ||
{ | ||
"sort-order": [ | ||
[ | ||
"$variable" | ||
], | ||
[ | ||
"margin", | ||
"padding" | ||
], | ||
[ | ||
"border", | ||
"background" | ||
], | ||
[ | ||
'...', | ||
"at-rule", | ||
"@include", | ||
"@include media", | ||
">child" | ||
] | ||
] | ||
} | ||
``` | ||
Config for `2.x`: | ||
```js | ||
```json | ||
{ | ||
"order": [ | ||
"custom-properties", | ||
"dollar-variables", | ||
"declarations", | ||
"at-rules", | ||
{ | ||
"type": "at-rule", | ||
"name": "include" | ||
}, | ||
{ | ||
"type": "at-rule", | ||
"name": "include", | ||
"parameter": "icon" | ||
}, | ||
"rules" | ||
], | ||
"properties-order": [ | ||
{ | ||
"emptyLineBefore": true, | ||
"properties": [ | ||
@@ -172,7 +72,19 @@ "margin", | ||
} | ||
], | ||
"unspecified-properties-position": "bottom" | ||
] | ||
} | ||
``` | ||
Config for `3.x`: | ||
```json | ||
{ | ||
"properties-order": [ | ||
"margin", | ||
"padding" | ||
"border", | ||
"background" | ||
] | ||
} | ||
``` | ||
## Usage | ||
@@ -184,3 +96,3 @@ | ||
This plugin available as [Sublime Text plugin], [Atom plugin], and [VS Code plugin]. | ||
This plugin available as [Sublime Text], [Atom], [VS Code], and [Emacs] plugin. | ||
@@ -245,6 +157,2 @@ ### Gulp | ||
## Thanks | ||
This plugin is heavily inspired by [stylelint]. Some code logic, tests, and documentation parts are taken from this tool. | ||
[ci-img]: https://travis-ci.org/hudochenkov/postcss-sorting.svg | ||
@@ -259,7 +167,6 @@ [ci]: https://travis-ci.org/hudochenkov/postcss-sorting | ||
[PostCSS]: https://github.com/postcss/postcss | ||
[Sublime Text plugin]: https://github.com/hudochenkov/sublime-postcss-sorting | ||
[Atom plugin]: https://github.com/lysyi3m/atom-postcss-sorting | ||
[VS Code plugin]: https://github.com/mrmlnc/vscode-postcss-sorting | ||
[predefined configs]: https://github.com/hudochenkov/postcss-sorting/tree/ee71c3b61eea8fa11bc3aa2d26dd99a832df6d54/configs | ||
[migrated predefined configs]: https://gist.github.com/hudochenkov/b7127590d3013a5982ed90ad63a85306 | ||
[Sublime Text]: https://github.com/hudochenkov/sublime-postcss-sorting | ||
[Atom]: https://github.com/lysyi3m/atom-postcss-sorting | ||
[VS Code]: https://github.com/mrmlnc/vscode-postcss-sorting | ||
[Emacs]: https://github.com/P233/postcss-sorting.el | ||
@@ -272,3 +179,3 @@ [Gulp PostCSS]: https://github.com/postcss/gulp-postcss | ||
[stylefmt]: https://github.com/morishitter/stylefmt | ||
[stylelint]: http://stylelint.io/ | ||
[stylelint]: https://stylelint.io/ | ||
[stylelint-order]: https://github.com/hudochenkov/stylelint-order |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
44267
26
691
173
1
+ Addedansi-styles@3.2.1(transitive)
+ Addedchalk@2.4.2(transitive)
+ Addedcolor-convert@1.9.3(transitive)
+ Addedcolor-name@1.1.3(transitive)
+ Addedhas-flag@3.0.0(transitive)
+ Addedpostcss@6.0.23(transitive)
+ Addedsource-map@0.6.1(transitive)
+ Addedsupports-color@5.5.0(transitive)
- Removedansi-regex@2.1.1(transitive)
- Removedansi-styles@2.2.1(transitive)
- Removedchalk@1.1.3(transitive)
- Removedhas-ansi@2.0.0(transitive)
- Removedhas-flag@1.0.0(transitive)
- Removedjs-base64@2.6.4(transitive)
- Removedpostcss@5.2.18(transitive)
- Removedsource-map@0.5.7(transitive)
- Removedstrip-ansi@3.0.1(transitive)
- Removedsupports-color@2.0.03.2.3(transitive)
Updatedpostcss@^6.0.1