Skip to content

Commit

Permalink
Add preserve-empty-lines-between-children-rules option #20
Browse files Browse the repository at this point in the history
  • Loading branch information
hudochenkov committed May 8, 2016
1 parent 6a961c9 commit 0cdf35f
Show file tree
Hide file tree
Showing 9 changed files with 198 additions and 6 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## 1.4.0
* Added `preserve-empty-lines-between-children-rules`, which preserve empty lines between children rules and preserve empty lines for comments between children rules. #20

## 1.3.1
* Fix adding additional empty line if both `empty-lines-between-children-rules` and `empty-lines-between-media-rules` are not 0. #19

Expand Down
38 changes: 37 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Also available as [Sublime Text plugin], [Atom plugin], and [VS Code plugin].
* [Predefined configs](#predefined-configs)
* [`empty-lines-between-children-rules`](#empty-lines-between-children-rules)
* [`empty-lines-between-media-rules`](#empty-lines-between-media-rules)
* [`preserve-empty-lines-between-children-rules`](#preserve-empty-lines-between-children-rules)
* [Migration from CSSComb](#migration-from-csscomb)
* [Usage](#usage)
* [Text editor](#text-editor)
Expand All @@ -50,7 +51,8 @@ $ npm install postcss-sorting
{
"sort-order": "default",
"empty-lines-between-children-rules": 0,
"empty-lines-between-media-rules": 0
"empty-lines-between-media-rules": 0,
"preserve-empty-lines-between-children-rules": false
}
```

Expand Down Expand Up @@ -342,6 +344,40 @@ Example: `{ "empty-lines-between-media-rules": 1, "sort-order": ["@media"] }`
}
```

### `preserve-empty-lines-between-children-rules`

Preserve empty lines between children rules and preserve empty lines for comments between children rules.

Acceptable value: `true`

Example: `{ "preserve-empty-lines-between-children-rules": true }`

```scss
/* before */
.block {
&:before {}
&:after {}

.element {}

/* comment */

.child {}
}

/* after (nothing changed) */
.block {
&:before {}
&:after {}

.element {}

/* comment */

.child {}
}
```

### Migration from CSSComb

If you used to use custom sorting order in [CSSComb] you can easily use this sorting order in PostCSS Sorting. `sort-order` option in this plugin is compatible with `sort-order` in CSSComb. Just copy `sort-order` value from CSSComb config to PostCSS Sorting config.
Expand Down
38 changes: 34 additions & 4 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ function verifyOptions(options) {
options['sort-order'] = options['sort-order'] || 'default';
options['empty-lines-between-children-rules'] = options['empty-lines-between-children-rules'] || 0;
options['empty-lines-between-media-rules'] = options['empty-lines-between-media-rules'] || 0;
options['preserve-empty-lines-between-children-rules'] = options['preserve-empty-lines-between-children-rules'] || false;

return options;
}
Expand Down Expand Up @@ -157,8 +158,7 @@ function fetchAllCommentsBeforeNode(comments, previousNode, node, currentInitial
previousNode.propertyIndex = node.propertyIndex;
previousNode.initialIndex = currentInitialIndex - 0.0001;

var previousNodeClone = cleanLineBreaks(previousNode);
var newComments = [previousNodeClone].concat(comments);
var newComments = [previousNode].concat(comments);

return fetchAllCommentsBeforeNode(newComments, previousNode.prev(), node, previousNode.initialIndex);
}
Expand Down Expand Up @@ -196,6 +196,16 @@ function getApplicableNode(lookFor, node) {
return false;
}

function countEmptyLines(str) {
var lineBreaks = (str.match(/\n/g) || []).length;

if (lineBreaks > 0) {
lineBreaks -= 1;
}

return lineBreaks;
}

module.exports = postcss.plugin('postcss-sorting', function (opts) {
// Verify options and use defaults if not specified
opts = verifyOptions(opts);
Expand All @@ -204,6 +214,7 @@ module.exports = postcss.plugin('postcss-sorting', function (opts) {
var order = getSortOrderFromOptions(opts);
var linesBetweenChildrenRules = getLinesBetweenRulesFromOptions('children', opts);
var linesBetweenMediaRules = getLinesBetweenRulesFromOptions('media', opts);
var preserveLinesBetweenChildren = opts['preserve-empty-lines-between-children-rules'];

css.walk(function (rule) {
// Process only rules and atrules with nodes
Expand Down Expand Up @@ -268,7 +279,17 @@ module.exports = postcss.plugin('postcss-sorting', function (opts) {

// Remove all empty lines and add empty lines between groups
rule.each(function (node) {
node = cleanLineBreaks(node);
// don't remove empty lines if they are should be preserved
if (
!(
preserveLinesBetweenChildren &&
(node.type === 'rule' || node.type === 'comment') &&
node.prev() &&
getApplicableNode('rule', node)
)
) {
node = cleanLineBreaks(node);
}

var prevNode = node.prev();

Expand All @@ -285,7 +306,16 @@ module.exports = postcss.plugin('postcss-sorting', function (opts) {
applicableNode = getApplicableNode('rule', node);

if (applicableNode) {
applicableNode.raws.before = createLineBreaks(linesBetweenChildrenRules) + applicableNode.raws.before;
// add lines only if source empty lines not preserved, or if there are less empty lines then should be
if (
!preserveLinesBetweenChildren ||
(
preserveLinesBetweenChildren &&
countEmptyLines(applicableNode.raws.before) < linesBetweenChildrenRules
)
) {
applicableNode.raws.before = createLineBreaks(linesBetweenChildrenRules) + applicableNode.raws.before;
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "postcss-sorting",
"version": "1.3.1",
"version": "1.4.0",
"description": "PostCSS plugin to sort rules content with specified order.",
"keywords": [
"postcss",
Expand Down
27 changes: 27 additions & 0 deletions test/fixtures/preserve-empty-lines-between-children-2.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.block {
div {}
/* comment 1 */
section {}




article {}


/* comment 2 */

.child {}
}
.block {
div {}
/* comment 1 */
section {}




/* comment 2 */
/* comment 3 */
.child {}
}
29 changes: 29 additions & 0 deletions test/fixtures/preserve-empty-lines-between-children-2.expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
.block {
div {}

/* comment 1 */
section {}




article {}


/* comment 2 */

.child {}
}
.block {
div {}

/* comment 1 */
section {}




/* comment 2 */
/* comment 3 */
.child {}
}
27 changes: 27 additions & 0 deletions test/fixtures/preserve-empty-lines-between-children.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.block {
div {}
/* comment 1 */
section {}




article {}


/* comment 2 */

.child {}
}
.block {
div {}
/* comment 1 */
section {}




/* comment 2 */
/* comment 3 */
.child {}
}
27 changes: 27 additions & 0 deletions test/fixtures/preserve-empty-lines-between-children.expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.block {
div {}
/* comment 1 */
section {}




article {}


/* comment 2 */

.child {}
}
.block {
div {}
/* comment 1 */
section {}




/* comment 2 */
/* comment 3 */
.child {}
}
13 changes: 13 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,19 @@ test('Should not insert additional line between @media and children rules if the
});
});

test('Should preserve empty lines between children rules', t => {
return run(t, 'preserve-empty-lines-between-children', {
'preserve-empty-lines-between-children-rules': true
});
});

test('Should preserve empty lines between children rules and don\'t create unneeded empty lines if \'empty-lines-between-children-rules\' enabled', t => {
return run(t, 'preserve-empty-lines-between-children-2', {
'empty-lines-between-children-rules': 1,
'preserve-empty-lines-between-children-rules': true
});
});

// test('Should sort LESS files', t => {
// return run(t, 'less.less', {}, 'less');
// });

0 comments on commit 0cdf35f

Please sign in to comment.