-
Notifications
You must be signed in to change notification settings - Fork 448
Several small fixes and fix for #67 #80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,3 +2,5 @@ node_modules | |
|
|
||
| .idea | ||
| *.iml | ||
|
|
||
| .DS_Store | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| module.exports = { | ||
|
|
||
| /** | ||
| * Sets handler value. | ||
| * | ||
| * @param {String} value Option value | ||
| * @returns {Object|undefined} | ||
| */ | ||
| setValue: function(value) { | ||
| if (value === true) { | ||
| this._value = value; | ||
| return this; | ||
| } | ||
| }, | ||
|
|
||
| /** | ||
| * Remove rulesets with no declarations. | ||
| * | ||
| * @param {String} nodeType | ||
| * @param {Array} nodeContent | ||
| */ | ||
| process: function(nodeType, nodeContent) { | ||
| if (nodeType === 'stylesheet') { | ||
| this._processStylesheetContent(nodeContent); | ||
| } | ||
| }, | ||
|
|
||
| _processStylesheetContent: function(nodeContent) { | ||
| this._removeEmptyRulesets(nodeContent); | ||
| this._mergeAdjacentWhitespace(nodeContent); | ||
| }, | ||
|
|
||
| _removeEmptyRulesets: function(nodeContent) { | ||
| var i = nodeContent.length; | ||
| while (i--) { | ||
| if (this._isRuleset(nodeContent[i]) && this._isEmptyRuleset(nodeContent[i])) { | ||
| nodeContent.splice(i, 1); | ||
| } | ||
| } | ||
| }, | ||
|
|
||
| /** | ||
| * Removing ruleset nodes from tree may result in two adjacent whitespace nodes which is not correct AST: | ||
| * [space, ruleset, space] => [space, space] | ||
| * To ensure correctness of further processing we should merge such nodes into one. | ||
| * [space, space] => [space] | ||
| */ | ||
| _mergeAdjacentWhitespace: function(nodeContent) { | ||
| var i = nodeContent.length - 1; | ||
| while (i-- > 0) { | ||
| if (this._isWhitespace(nodeContent[i]) && this._isWhitespace(nodeContent[i + 1])) { | ||
| nodeContent[i][1] += nodeContent[i + 1][1]; | ||
| nodeContent.splice(i + 1, 1); | ||
| } | ||
| } | ||
| }, | ||
|
|
||
| _isEmptyRuleset: function(ruleset) { | ||
| return ruleset.filter(this._isBlock).every(this._isEmptyBlock, this); | ||
| }, | ||
|
|
||
| /** | ||
| * Block considered empty when it has no declarations or comments. | ||
| */ | ||
| _isEmptyBlock: function(node) { | ||
| return !node.some(this._isDeclarationOrComment); | ||
| }, | ||
|
|
||
| _isDeclarationOrComment: function(node) { | ||
| return node[0] === 'declaration' || node[0] === 'comment'; | ||
| }, | ||
|
|
||
| _isRuleset: function(node) { | ||
| return node[0] === 'ruleset'; | ||
| }, | ||
|
|
||
| _isBlock: function(node) { | ||
| return node[0] === 'block'; | ||
| }, | ||
|
|
||
| _isWhitespace: function(node) { | ||
| return node[0] === 's'; | ||
| } | ||
|
|
||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| var Comb = require('../lib/csscomb'); | ||
| var assert = require('assert'); | ||
|
|
||
| describe('options/remove-empty-rulesets', function() { | ||
| var comb; | ||
|
|
||
| beforeEach(function() { | ||
| comb = new Comb(); | ||
| }); | ||
|
|
||
| describe('configured with invalid value', function() { | ||
| beforeEach(function() { | ||
| comb.configure({ 'remove-empty-rulesets': 'foobar' }); | ||
| }); | ||
|
|
||
| it('should not remove empty ruleset', function() { | ||
| assert.equal(comb.processString('a { width: 10px; } b {}'), 'a { width: 10px; } b {}'); | ||
| }); | ||
| }); | ||
|
|
||
| describe('configured with Boolean "true" value', function() { | ||
| beforeEach(function() { | ||
| comb.configure({ 'remove-empty-rulesets': true }); | ||
| }); | ||
|
|
||
| it('should remove empty ruleset', function() { | ||
| assert.equal(comb.processString(' b {} '), ' '); | ||
| }); | ||
|
|
||
| it('should leave ruleset with declarations', function() { | ||
| assert.equal(comb.processString('a { width: 10px; }\nb {} '), 'a { width: 10px; }\n '); | ||
| }); | ||
|
|
||
| it('should leave ruleset with comments', function() { | ||
| assert.equal(comb.processString('a { /* comment */ }\nb {} '), 'a { /* comment */ }\n '); | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| describe('options/remove-empty-rulesets AST manipulation', function() { | ||
| var rule; | ||
| var nodeContent; | ||
|
|
||
| beforeEach(function() { | ||
| rule = require('../lib/options/remove-empty-rulesets.js'); | ||
| }); | ||
|
|
||
| describe('merge adjacent whitespace', function() { | ||
| it('should do nothing with empty content', function() { | ||
| nodeContent = []; | ||
| rule._mergeAdjacentWhitespace(nodeContent); | ||
| assert.deepEqual(nodeContent, []); | ||
| }); | ||
|
|
||
| it('should do nothing with only one whitespace', function() { | ||
| nodeContent = [['s', ' ']]; | ||
| rule._mergeAdjacentWhitespace(nodeContent); | ||
| assert.deepEqual(nodeContent, [['s', ' ']]); | ||
| }); | ||
|
|
||
| it('should merge two adjacent whitespaces', function() { | ||
| nodeContent = [['s', ' '], ['s', ' \n']]; | ||
| rule._mergeAdjacentWhitespace(nodeContent); | ||
| assert.deepEqual(nodeContent, [['s', ' \n']]); | ||
| }); | ||
|
|
||
| it('should merge three adjacent whitespaces', function() { | ||
| nodeContent = [['s', ' '], ['s', ' \n'], ['s', ' \n']]; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. synthetic test, can't be in real life
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And previous too.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree, accepted. |
||
| rule._mergeAdjacentWhitespace(nodeContent); | ||
| assert.deepEqual(nodeContent, [['s', ' \n \n']]); | ||
| }); | ||
| }); | ||
|
|
||
| describe('remove empty rulesets', function() { | ||
| it('should do nothing with empty content', function() { | ||
| nodeContent = []; | ||
| rule._removeEmptyRulesets(nodeContent); | ||
| assert.deepEqual(nodeContent, []); | ||
| }); | ||
|
|
||
| it('should do nothing with no rulesets', function() { | ||
| nodeContent = [['s', ' ']]; | ||
| rule._removeEmptyRulesets(nodeContent); | ||
| assert.deepEqual(nodeContent, [['s', ' ']]); | ||
| }); | ||
|
|
||
| it('should remove empty ruleset', function() { | ||
| nodeContent = [['ruleset', []]]; | ||
| rule._removeEmptyRulesets(nodeContent); | ||
| assert.deepEqual(nodeContent, []); | ||
| }); | ||
|
|
||
| it('should remove two empty rulesets', function() { | ||
| nodeContent = [['s', ' '], ['ruleset', []], ['s', ' \n'], ['ruleset', []]]; | ||
| rule._removeEmptyRulesets(nodeContent); | ||
| assert.deepEqual(nodeContent, [['s', ' '], ['s', ' \n']]); | ||
| }); | ||
| }); | ||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add some comments into a tested string.