clean-css
Advanced tools
Comparing version 0.7.0 to 0.8.0
@@ -0,1 +1,10 @@ | ||
0.8.0 / 2012-10-21 | ||
================== | ||
* Added removing url parentheses if possible. | ||
* Rewrote breaks processing. | ||
* Added (keepBreaks/-b) option to keep breaks in minimized file. | ||
* Reformatted lib/clean.js so it's eaasier to follow the rules. | ||
* Minimized test data is now kept with breaks so it's easier to compare the changes. | ||
0.7.0 / 2012-10-14 | ||
@@ -2,0 +11,0 @@ ================== |
137
lib/clean.js
@@ -32,2 +32,4 @@ var util = require('util'); | ||
options.keepBreaks = options.keepBreaks || false; | ||
// replace function | ||
@@ -56,16 +58,50 @@ if (options.debug) { | ||
replace(/;\s*;+/g, ';') // whitespace between semicolons & multiple semicolons | ||
replace(/\n/g, '') // line breaks | ||
replace(/\s+/g, ' ') // multiple whitespace | ||
replace(/ !important/g, '!important') // whitespace before !important | ||
replace(/[ ]?,[ ]?/g, ',') // space with a comma | ||
replace(/progid:[^(]+\(([^\)]+)/g, function(match, contents) { // restore spaces inside IE filters (IE 7 issue) | ||
// strip url's parentheses if possible (no spaces inside) | ||
replace(/url\(['"]([^\)]+)['"]\)/g, function(urlMatch) { | ||
if (urlMatch.match(/\s/g) != null) | ||
return urlMatch; | ||
else | ||
return urlMatch.replace(/\(['"]/, '(').replace(/['"]\)$/, ')'); | ||
}); | ||
// whitespace between semicolons & multiple semicolons | ||
replace(/;\s*;+/g, ';'); | ||
// line breaks | ||
if (!options.keepBreaks) | ||
replace(/[\r]?\n/g, ''); | ||
// multiple whitespace | ||
replace(/[\t ]+/g, ' '); | ||
// multiple line breaks to one | ||
replace(/ \n/g, '\n'); | ||
replace(/ \r\n/g, '\r\n'); | ||
replace(/\n+/g, '\n'); | ||
replace(/(\r\n)+/g, '\r\n'); | ||
// whitespace before !important | ||
replace(/ !important/g, '!important') | ||
// space with a comma | ||
replace(/[ ]?,[ ]?/g, ',') | ||
// restore spaces inside IE filters (IE 7 issue) | ||
replace(/progid:[^(]+\(([^\)]+)/g, function(match, contents) { | ||
return match.replace(/,/g, ', '); | ||
}) | ||
replace(/ ([+~>]) /g, '$1') // replace spaces around selectors | ||
replace(/\{([^}]+)\}/g, function(match, contents) { // whitespace inside content | ||
}); | ||
// replace spaces around selectors | ||
replace(/ ([+~>]) /g, '$1'); | ||
// whitespace inside content | ||
replace(/\{([^}]+)\}/g, function(match, contents) { | ||
return '{' + contents.trim().replace(/(\s*)([;:=\s])(\s*)/g, '$2') + '}'; | ||
}) | ||
replace(/;}/g, '}') // trailing semicolons | ||
replace(/rgb\s*\(([^\)]+)\)/g, function(match, color) { // rgb to hex colors | ||
}); | ||
// trailing semicolons | ||
replace(/;}/g, '}'); | ||
// rgb to hex colors | ||
replace(/rgb\s*\(([^\)]+)\)/g, function(match, color) { | ||
var parts = color.split(','); | ||
@@ -78,4 +114,6 @@ var encoded = '#'; | ||
return encoded; | ||
}) | ||
replace(/([^"'=\s])\s*#([0-9a-f]{6})/gi, function(match, prefix, color) { // long hex to short hex | ||
}); | ||
// long hex to short hex | ||
replace(/([^"'=\s])\s*#([0-9a-f]{6})/gi, function(match, prefix, color) { | ||
if (color[0] == color[1] && color[2] == color[3] && color[4] == color[5]) | ||
@@ -85,28 +123,58 @@ return (prefix + (/:$/.test(prefix) ? '' : ' ')) + '#' + color[0] + color[2] + color[4]; | ||
return (prefix + (/:$/.test(prefix) ? '' : ' ')) + '#' + color; | ||
}) | ||
replace(/(color|background):(\w+)/g, function(match, property, colorName) { // replace standard colors with hex values (only if color name is longer then hex value) | ||
}); | ||
// replace standard colors with hex values (only if color name is longer then hex value) | ||
replace(/(color|background):(\w+)/g, function(match, property, colorName) { | ||
if (CleanCSS.colors[colorName]) return property + ':' + CleanCSS.colors[colorName]; | ||
else return match; | ||
}) | ||
replace(/([: ,\(])#f00/g, '$1red') // replace #f00 with red as it's shorter | ||
replace(/font\-weight:(\w+)/g, function(match, weight) { // replace font weight with numerical value | ||
}); | ||
// replace #f00 with red as it's shorter | ||
replace(/([: ,\(])#f00/g, '$1red'); | ||
// replace font weight with numerical value | ||
replace(/font\-weight:(\w+)/g, function(match, weight) { | ||
if (weight == 'normal') return 'font-weight:400'; | ||
else if (weight == 'bold') return 'font-weight:700'; | ||
else return match; | ||
}) | ||
replace(/progid:DXImageTransform\.Microsoft\.(Alpha|Chroma)(\([^\)]+\))([;}'"])/g, function(match, filter, args, suffix) { // IE shorter filters but only if single (IE 7 issue) | ||
}); | ||
// IE shorter filters but only if single (IE 7 issue) | ||
replace(/progid:DXImageTransform\.Microsoft\.(Alpha|Chroma)(\([^\)]+\))([;}'"])/g, function(match, filter, args, suffix) { | ||
return filter.toLowerCase() + args + suffix; | ||
}) | ||
replace(/(\s|:)0(px|em|ex|cm|mm|in|pt|pc|%)/g, '$1' + '0') // zero + unit to zero | ||
replace(/(border|border-top|border-right|border-bottom|border-left|outline):none/g, '$1:0') // none to 0 | ||
replace(/(background):none([;}])/g, '$1:0$2') // background:none to 0 | ||
replace(/0 0 0 0([^\.])/g, '0$1') // multiple zeros into one | ||
replace(/([: ,=\-])0\.(\d)/g, '$1.$2') | ||
if (options.removeEmpty) replace(/[^}]+?{\s*?}/g, '') // empty elements | ||
if (data.indexOf('charset') > 0) replace(/(.+)(@charset [^;]+;)/, '$2$1') // move first charset to the beginning | ||
replace(/(.)(@charset [^;]+;)/g, '$1') // remove all extra charsets that are not at the beginning | ||
replace(/\*([\.#:\[])/g, '$1') // remove universal selector when not needed (*#id, *.class etc) | ||
replace(/ {/g, '{') // whitespace before definition | ||
replace(/\} /g, '}') // whitespace after definition | ||
}); | ||
// zero + unit to zero | ||
replace(/(\s|:)0(px|em|ex|cm|mm|in|pt|pc|%)/g, '$1' + '0'); | ||
// none to 0 | ||
replace(/(border|border-top|border-right|border-bottom|border-left|outline):none/g, '$1:0'); | ||
// background:none to 0 | ||
replace(/(background):none([;}])/g, '$1:0$2'); | ||
// multiple zeros into one | ||
replace(/0 0 0 0([^\.])/g, '0$1'); | ||
replace(/([: ,=\-])0\.(\d)/g, '$1.$2'); | ||
// empty elements | ||
if (options.removeEmpty) | ||
replace(/[^}]+?{\s*?}/g, ''); | ||
// move first charset to the beginning | ||
if (data.indexOf('charset') > 0) | ||
replace(/(.+)(@charset [^;]+;)/, '$2$1'); | ||
// remove all extra charsets that are not at the beginning | ||
replace(/(.)(@charset [^;]+;)/g, '$1'); | ||
// remove universal selector when not needed (*#id, *.class etc) | ||
replace(/\*([\.#:\[])/g, '$1'); | ||
// whitespace before definition | ||
replace(/ {/g, '{'); | ||
// whitespace after definition | ||
replace(/\} /g, '}'); | ||
// Get the special comments, content content, and spaces inside calc back | ||
@@ -134,3 +202,4 @@ var specialCommentsCount = context.specialComments.length; | ||
return data.trim() // trim spaces at beginning and end | ||
// trim spaces at beginning and end | ||
return data.trim(); | ||
}, | ||
@@ -137,0 +206,0 @@ |
@@ -11,3 +11,3 @@ { | ||
}, | ||
"version": "0.7.0", | ||
"version": "0.8.0", | ||
"main": "index.js", | ||
@@ -14,0 +14,0 @@ "bin": { |
@@ -19,3 +19,3 @@ [![build status](https://secure.travis-ci.org/GoalSmashers/clean-css.png)](http://travis-ci.org/GoalSmashers/clean-css) | ||
You can minify one file **public.css** into **public-min.css** via: | ||
To minify a **public.css** file into **public-min.css** do: | ||
@@ -52,5 +52,5 @@ cleancss -o public-min.css public.css | ||
You need vows testing framework (npm install vows) then simply run: | ||
First clone the source, then run: | ||
make test | ||
npm test | ||
@@ -66,2 +66,3 @@ on *nix systems. If you are under Windows then run: | ||
* Jan Michael Alonzo (@jmalonzo) for a patch removing node's old 'sys' package. | ||
* @XhmikosR for suggesting new features: option to remove special comments and strip out url's parentheses. | ||
@@ -68,0 +69,0 @@ ## License ## |
@@ -17,5 +17,8 @@ var vows = require('vows'), | ||
topic: function() { | ||
var plainPath = path.join(__dirname, 'data', testName + '.css'); | ||
var minPath = path.join(__dirname, 'data', testName + '-min.css'); | ||
return { | ||
plain: fs.readFileSync(path.join(__dirname, 'data', testName + '.css'), 'utf-8').replace(lineBreak, ''), | ||
minimized: fs.readFileSync(path.join(__dirname, 'data', testName + '-min.css'), 'utf-8').replace(lineBreak, '') | ||
plain: fs.readFileSync(plainPath, 'utf-8'), | ||
minimized: fs.readFileSync(minPath, 'utf-8') | ||
}; | ||
@@ -25,3 +28,14 @@ } | ||
context[testName]['minimizing ' + testName + '.css'] = function(data) { | ||
assert.equal(cleanCSS.process(data.plain, { removeEmpty: true }), data.minimized) | ||
var processed = cleanCSS.process(data.plain, { | ||
removeEmpty: true, | ||
keepBreaks: true | ||
}); | ||
var processedTokens = processed.split(lineBreak); | ||
var minimizedTokens = data.minimized.split(lineBreak); | ||
assert.equal(processedTokens.length, minimizedTokens.length); | ||
processedTokens.forEach(function(line, i) { | ||
assert.equal(line, minimizedTokens[i]); | ||
}); | ||
}; | ||
@@ -28,0 +42,0 @@ }); |
@@ -58,2 +58,6 @@ var vows = require('vows'), | ||
], | ||
'tabs': [ | ||
'div\t\ta{}\tp{color:red}', | ||
'div a{}p{color:red}' | ||
], | ||
'line breaks': [ | ||
@@ -67,2 +71,6 @@ 'div \na\r\n { width:500px }', | ||
], | ||
'line breaks with whitespace lines': [ | ||
'div \n \t\n \na\r\n, p { width:500px }', | ||
'div a,p{width:500px}' | ||
], | ||
'multiple arguments': [ | ||
@@ -101,2 +109,14 @@ 'a{color:#fff ; font-weight: bolder }', | ||
}), | ||
'line breaks': cssContext({ | ||
'line breaks': 'div\na\r\n{width:500px}', | ||
'line breaks #2': 'div\na\r\n,p{width:500px}', | ||
'multiple line breaks #2': [ | ||
'div \r\n\r\na\r\n,p{width:500px}', | ||
'div\r\na\r\n,p{width:500px}' | ||
], | ||
'line breaks with whitespace lines': [ | ||
'div \n \t\n \na\r\n, p { width:500px }', | ||
'div\na\r\n,p{width:500px}' | ||
] | ||
}, { keepBreaks: true }), | ||
'selectors': cssContext({ | ||
@@ -279,2 +299,21 @@ 'remove spaces around selectors': [ | ||
}), | ||
'urls': cssContext({ | ||
'keep urls without parentheses unchanged': 'a{background:url(/images/blank.png) 0 0 no-repeat}', | ||
'strip single parentheses': [ | ||
"a{background:url('/images/blank.png') 0 0 no-repeat}", | ||
"a{background:url(/images/blank.png) 0 0 no-repeat}" | ||
], | ||
'strip double parentheses': [ | ||
'a{background:url("/images/blank.png") 0 0 no-repeat}', | ||
'a{background:url(/images/blank.png) 0 0 no-repeat}' | ||
], | ||
'strip more': [ | ||
'a{background:url("/images/blank.png") 0 0 no-repeat}a{}a{background:url("/images/blank.png") 0 0 no-repeat}', | ||
'a{background:url(/images/blank.png) 0 0 no-repeat}a{}a{background:url(/images/blank.png) 0 0 no-repeat}' | ||
], | ||
'not strip comments if spaces inside': [ | ||
'a{background:url("/images/long image name.png") 0 0 no-repeat}a{}a{background:url("/images/no-spaces.png") 0 0 no-repeat}', | ||
'a{background:url("/images/long image name.png") 0 0 no-repeat}a{}a{background:url(/images/no-spaces.png) 0 0 no-repeat}' | ||
] | ||
}), | ||
'ie filters': cssContext({ | ||
@@ -286,3 +325,4 @@ 'short alpha': [ | ||
'short chroma': [ | ||
'a{filter:progid:DXImageTransform.Microsoft.Chroma(color=#919191)}', 'a{filter:chroma(color=#919191)}' | ||
'a{filter:progid:DXImageTransform.Microsoft.Chroma(color=#919191)}', | ||
'a{filter:chroma(color=#919191)}' | ||
], | ||
@@ -289,0 +329,0 @@ 'matrix filter spaces': [ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
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
716881
18003
69