Socket
Socket
Sign inDemoInstall

css-declaration-sorter

Package Overview
Dependencies
Maintainers
1
Versions
45
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

css-declaration-sorter - npm Package Compare versions

Comparing version 4.0.1 to 5.0.0

src/shorthand-data.js

14

changelog.md

@@ -5,2 +5,13 @@ # Changelog

## [5.0.0] - 2019-12-16
### Added
- Option `keepOverrides` to keep overrides in place, useful for legacy CSS where shorthand declarations override longhand declarations.
### Changed
- Default sorting order renamed to `alphabetical`.
- Custom sorting order as a JSON file replaced in favor of the option to pass a custom sorting function.
### Removed
- Node.js 6 and 8 support.
## [4.0.1] - 2018-07-30

@@ -16,3 +27,3 @@ ### Fixed

### Removed
- Node 4 support.
- Node.js 4 support.
- Deprecated grid properties.

@@ -46,2 +57,3 @@

[5.0.0]: https://github.com/Siilwyn/css-declaration-sorter/compare/v4.0.1...v5.0.0
[4.0.1]: https://github.com/Siilwyn/css-declaration-sorter/compare/v4.0.0...v4.0.1

@@ -48,0 +60,0 @@ [4.0.0]: https://github.com/Siilwyn/css-declaration-sorter/compare/v3.0.1...v4.0.0

11

package.json
{
"name": "css-declaration-sorter",
"version": "4.0.1",
"version": "5.0.0",
"description": "Sorts CSS declarations fast and automatically in a certain order.",

@@ -8,2 +8,3 @@ "main": "src/index.js",

"src/index.js",
"src/shorthand-data.js",
"orders"

@@ -20,3 +21,3 @@ ],

"dependencies": {
"postcss": "^7.0.1",
"postcss": "^7.0.25",
"timsort": "^0.3.0"

@@ -26,7 +27,7 @@ },

"benchmark": "^2.1.4",
"eslint": "^5.0.0",
"tape": "^4.2.1"
"eslint": "^6.7.2",
"tape": "^4.11.0"
},
"engines": {
"node": ">4"
"node": ">= 10"
},

@@ -33,0 +34,0 @@ "repository": {

@@ -5,8 +5,15 @@ <img alt='CSS declaration sorter logo' src='https://cdn.rawgit.com/Siilwyn/css-declaration-sorter/master/logo.svg' height='260' align='right'>

[![Travis Build Status][travis-icon]][travis]
[![npm version][npm-icon]][npm]
[![David Dependencies Status][david-icon]][david]
[![David devDependencies Status][david-dev-icon]][david-dev]
[![LGTM Grade][lgtm-icon]][lgtm]
[![npm][npm-icon]][npm]
A Node.js module and [PostCSS] plugin to sort CSS declarations based on their property names. Ensuring the CSS is organized, more consistent and in order... Besides, sorted CSS is smaller when gzipped because there will be more similar strings. The intention of this module is to sort the source CSS code of a project in the build process. Check out [the Atom package](https://github.com/Siilwyn/css-declaration-sorter-atom) for individual usage.
A Node.js module and [PostCSS] plugin to sort CSS, SCSS or Less declarations based on their property names. Ensuring styling is organized, more consistent and in order... The goal of this package is to sort the source code of a project in the build process or to decrease the distributed CSS gzipped size. Check out [the Atom package](https://github.com/Siilwyn/css-declaration-sorter-atom) for individual usage.
## Niceness
- Up-to-date CSS properties fetched from the [MDN Web Platform](https://developer.mozilla.org/).
- Choose your wanted order or provide your own.
- Nested rules sorting support.
- SCSS and Less support when combined with either [postcss-scss](https://github.com/postcss/postcss-scss) or [postcss-less](https://github.com/webschik/postcss-less).
- Thought-out sorting orders out of the box, **approved by their authors**.
## Alphabetical example

@@ -33,35 +40,25 @@ Input:

## Niceness
- Up-to-date CSS properties fetched from the [MDN Web Platform](https://developer.mozilla.org/).
- Sort using your own defined order.
- Nested rules sorting support.
- Less and SCSS support when combined with either [postcss-scss](https://github.com/postcss/postcss-scss) or [postcss-less](https://github.com/webschik/postcss-less).
- Thought-out sorting orders out of the box, **approved by their authors**.
## Built-in sorting orders
- Alphabetical
`alphabetical`
*Default, order in a simple alphabetical manner from a - z.*
## Sorting orders
- Alphabetically
`alphabetically`
*Default, ordering in a simple alphabetical manner from a - z.*
- [SMACSS](https://smacss.com/book/formatting#grouping)
`smacss`
*Ordering from most important, flow affecting properties, to least important properties.*
- Box
- Border
- Background
- Text
- Other
*Order from most important, flow affecting properties, to least important properties.*
1. Box
2. Border
3. Background
4. Text
5. Other
- [Concentric CSS](https://github.com/brandon-rhodes/Concentric-CSS)
`concentric-css`
*Starts outside the box model, moves inward.*
- Positioning
- Visibility
- Box model
- Dimensions
- Text
*Order properties applying outside the box model, moving inward to intrinsic changes.*
1. Positioning
2. Visibility
3. Box model
4. Dimensions
5. Text
- Custom order
*Provide your own order by passing the location of a JSON file containing an array.*
## Usage

@@ -71,3 +68,3 @@ `npm install css-declaration-sorter --save-dev`

### CLI
This module does not include its own CLI but works with the official [PostCSS CLI](https://github.com/postcss/postcss-cli). To use the examples below, install `postcss-cli` or prefix with `npx`.
This module does not include its own CLI but works with the official [PostCSS CLI](https://github.com/postcss/postcss-cli). To use the examples below, the `postcss-cli` package is a required dependency.

@@ -82,3 +79,2 @@ Piping out result from file:

```js
const fs = require('fs');
const postcss = require('postcss');

@@ -88,6 +84,6 @@ const cssDeclarationSorter = require('css-declaration-sorter');

postcss([cssDeclarationSorter({order: 'smacss'})])
.process(fs.readFileSync('some.css'))
.then(function (result) {
fs.writeFileSync('some.css', result.css);
});
.process('a { color: hyperblue; display: block; }')
.then(result =>
result.css === 'a { display: block; color: hyperblue; }'
);
```

@@ -109,10 +105,25 @@

## API
### cssDeclarationSorter({ order, keepOverrides })
#### order
Type: `string` or `function`
Default: `alphabetical`
Options: `alphabetical`, `smacss`, `concentric-css`
Provide the name of one of the built-in sort orders or a comparison function that is passed to ([`Array.sort`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)). This function receives two declaration names and is expected to return `-1`, `0` or `1` depending on the wanted order.
#### keepOverrides
Type: `Boolean`
Default: `false`
To prevent breaking legacy CSS where shorthand declarations override longhand declarations this option can enabled. For example `animation-name: some; animation: greeting;` will be kept in this order when `keepOverrides` is `true`.
[PostCSS]: https://github.com/postcss/postcss
[travis]: https://travis-ci.org/Siilwyn/css-declaration-sorter
[travis-icon]: https://img.shields.io/travis/Siilwyn/css-declaration-sorter/master.svg?style=flat-square
[npm]: https://npmjs.com/css-declaration-sorter
[lgtm]: https://lgtm.com/projects/g/Siilwyn/css-declaration-sorter/
[lgtm-icon]: https://img.shields.io/lgtm/grade/javascript/g/Siilwyn/css-declaration-sorter.svg?style=flat-square
[npm]: https://www.npmjs.com/package/css-declaration-sorter
[npm-icon]: https://img.shields.io/npm/v/css-declaration-sorter.svg?style=flat-square
[david]: https://david-dm.org/Siilwyn/css-declaration-sorter
[david-icon]: https://img.shields.io/david/Siilwyn/css-declaration-sorter.svg?style=flat-square
[david-dev]: https://david-dm.org/Siilwyn/css-declaration-sorter?type=dev
[david-dev-icon]: https://img.shields.io/david/dev/Siilwyn/css-declaration-sorter.svg?style=flat-square
'use strict';
const fs = require('fs');
const { readFile } = require('fs').promises;
const path = require('path');

@@ -9,35 +9,50 @@

module.exports = postcss.plugin('css-declaration-sorter', function (options) {
return function (css) {
let sortOrderPath;
const builtInOrders = [
'alphabetical',
'concentric-css',
'smacss',
];
options = options || {};
module.exports = postcss.plugin(
'css-declaration-sorter',
({ order = 'alphabetical', keepOverrides = false } = {}) => css => {
let withKeepOverrides = comparator => comparator;
if (keepOverrides) {
const shorthandData = require('./shorthand-data.js');
withKeepOverrides = withOverridesComparator(shorthandData);
}
// Use included sorting order if order is passed and not alphabetically
if (options.order && options.order !== 'alphabetically') {
sortOrderPath = path.join(__dirname, '../orders/', options.order) + '.json';
} else if (options.customOrder) {
sortOrderPath = options.customOrder;
} else {
// Fallback to the default sorting order
return processCss(css, 'alphabetically');
if (typeof order === 'function') {
return processCss({ css, comparator: withKeepOverrides(order) });
}
// Load in the array containing the order from a JSON file
return new Promise(function (resolve, reject) {
fs.readFile(sortOrderPath, function (error, data) {
if (error) return reject(error);
resolve(data);
if (!builtInOrders.includes(order))
return Promise.reject(
Error([
`Invalid built-in order '${order}' provided.`,
`Available built-in orders are: ${builtInOrders}`,
].join('\n'))
);
if (order === 'alphabetical') {
return processCss({
css,
comparator: withKeepOverrides(defaultComparator),
});
}).then(function (data) {
return processCss(css, JSON.parse(data));
});
};
});
}
function processCss (css, sortOrder) {
// Load in the array containing the order from a JSON file
return readFile(path.join(__dirname, '..', 'orders', order) + '.json')
.then(data => processCss({
css,
comparator: withKeepOverrides(orderComparator(JSON.parse(data))),
}));
}
);
function processCss ({ css, comparator }) {
const comments = [];
const rulesCache = [];
css.walk(function (node) {
css.walk(node => {
const nodes = node.nodes;

@@ -48,3 +63,3 @@ const type = node.type;

// Don't do anything to root comments or the last newline comment
const isNewlineNode = ~node.raws.before.indexOf('\n');
const isNewlineNode = node.raws.before && ~node.raws.before.indexOf('\n');
const lastNewlineNode = isNewlineNode && !node.next();

@@ -90,8 +105,8 @@ const onlyNode = !node.prev() && !node.next();

// Perform a sort once all comment nodes are removed
rulesCache.forEach(function (nodes) {
sortCssDecls(nodes, sortOrder);
rulesCache.forEach(nodes => {
sortCssDeclarations({ nodes, comparator });
});
// Add comments back to the nodes they are paired with
comments.forEach(function (node) {
comments.forEach(node => {
const pairedNode = node.pairedNode;

@@ -103,26 +118,33 @@ node.comment.remove();

// Sort CSS declarations alphabetically or using the set sorting order
function sortCssDecls (cssDecls, sortOrder) {
if (sortOrder === 'alphabetically') {
timsort(cssDecls, function (a, b) {
if (a.type === 'decl' && b.type === 'decl') {
return comparator(a.prop, b.prop);
} else {
return compareDifferentType(a, b);
}
});
} else {
timsort(cssDecls, function (a, b) {
if (a.type === 'decl' && b.type === 'decl') {
const aIndex = sortOrder.indexOf(a.prop);
const bIndex = sortOrder.indexOf(b.prop);
return comparator(aIndex, bIndex);
} else {
return compareDifferentType(a, b);
}
});
}
function sortCssDeclarations ({ nodes, comparator }) {
timsort(nodes, (a, b) => {
if (a.type === 'decl' && b.type === 'decl') {
return comparator(a.prop, b.prop);
} else {
return compareDifferentType(a, b);
}
});
}
function comparator (a, b) {
function withOverridesComparator (shorthandData) {
return function (comparator) {
return function (a, b) {
if (shorthandData[a] && shorthandData[a].includes(b)) return 0;
if (shorthandData[b] && shorthandData[b].includes(a)) return 0;
return comparator(a, b);
};
};
}
function orderComparator (order) {
return function (a, b) {
const aIndex = order.indexOf(a);
const bIndex = order.indexOf(b);
return defaultComparator(aIndex, bIndex);
};
}
function defaultComparator (a, b) {
return a === b ? 0 : a < b ? -1 : 1;

@@ -132,5 +154,7 @@ }

function compareDifferentType (a, b) {
if (b.type === 'atrule') { return 0; }
if (b.type === 'atrule') {
return 0;
}
return (a.type === 'decl') ? -1 : (b.type === 'decl') ? 1 : 0;
return a.type === 'decl' ? -1 : b.type === 'decl' ? 1 : 0;
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc