From 5a1b3a6a414f4df182d1f3557d84b985d364c341 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowicz Date: Mon, 7 Feb 2011 17:08:11 +0100 Subject: [PATCH] First version of clean-css. * Implemented all standard transformations (cleaning up whitespace, semicolons, long color declarations, empty elements, etc...). * Added tests for all transformations. * Added tests cleaning up some standard libraries (reset.css, 960.gs, blueprint.css). --- .gitignore | 2 + Makefile | 9 + README.md | 41 +++ bin/cleancss | 47 +++ index.js | 1 + lib/clean.js | 123 ++++++++ lib/purify.js | 55 ---- package.json | 16 + test/batch-test.js | 31 ++ test/data/960-min.css | 1 + test/data/960.css | 602 ++++++++++++++++++++++++++++++++++++ test/data/blueprint-min.css | 245 +++++++++++++++ test/data/blueprint.css | 556 +++++++++++++++++++++++++++++++++ test/data/reset-min.css | 12 + test/data/reset.css | 64 ++++ test/purifier-test.js | 159 ---------- test/unit-test.js | 252 +++++++++++++++ 17 files changed, 2002 insertions(+), 214 deletions(-) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100755 bin/cleancss create mode 100644 index.js create mode 100644 lib/clean.js delete mode 100644 lib/purify.js create mode 100644 package.json create mode 100644 test/batch-test.js create mode 100755 test/data/960-min.css create mode 100755 test/data/960.css create mode 100644 test/data/blueprint-min.css create mode 100644 test/data/blueprint.css create mode 100644 test/data/reset-min.css create mode 100644 test/data/reset.css delete mode 100644 test/purifier-test.js create mode 100644 test/unit-test.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..5ca0973f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.DS_Store + diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..b60e628d --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +TEST_DIR = test + +all: test + +test: + @@echo "Running all tests via vows" + @@vows ${TEST_DIR}/*-test.js + +.PHONY: all test \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 00000000..8a6d038a --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +## What is clean-css? ## + +Clean-css is a node.js library for minifying CSS files. It does the same job as YUI Compressor's CSS minifier but much faster thanks to speed of node.js V8 engine. + +## Usage ## + +### How to install clean-css? ### + + npm install clean-css + + +### How to use clean-css? ### + +You can minify one file **public.css** into **public-min.css** via: + + cleancss -o public-min.css public.css + +To minify the same **public.css** into standard output skip the -o parameter: + + cleancss public.css + +Or more likely you would like to do something like this: + + cat one.css two.css three.css | cleancss -o merged-and-minified.css + +Or even gzip it at once: + + cat one.css two.css three.css | cleancss | gzip -9 -c > merged-minified-and-gzipped.css.gz + +### How to use clean-css programatically ### + + var CleanCSS = require('clean-css').CleanCSS; + + var source = "a{font-weight:bold}"; + var minimized = CleanCSS.process(source); + +### How to run clean-css tests? ### + +You need vows testing framework (npm install vows) then simply run: + + make test diff --git a/bin/cleancss b/bin/cleancss new file mode 100755 index 00000000..3d641ac4 --- /dev/null +++ b/bin/cleancss @@ -0,0 +1,47 @@ +#!/usr/bin/env node + +global.sys = require(/^v0\.[012]/.test(process.version) ? "sys" : "util"); +var CleanCSS = require('clean-css').CleanCSS, + fs = require('fs'); + +var options = { + source: null, + target: null +}; + +var args = process.argv.slice(2); +out: while (args.length > 0) { + var p = args.shift(); + switch(p) { + case '-o': + options.target = args.shift(); + break; + default: + options.source = args.shift(); + } +} + +if (options.source) { + fs.readFile(options.source, 'utf8', function(error, text) { + if (error) throw error; + output(CleanCSS.process(text)); + }); +} else { + var stdin = process.openStdin(); + stdin.setEncoding('utf-8'); + var text = ''; + stdin.on('data', function(chunk) { text += chunk; }); + stdin.on('end', function() { output(CleanCSS.process(text)); }); +} + +function output(cleaned) { + var out; + if (options.target) { + out = fs.createWriteStream(options.target, { flags: 'w', encoding: 'utf-8', mode: 0644 }); + } else { + out = process.stdout; + } + + out.write(cleaned); + out.end(); +}; diff --git a/index.js b/index.js new file mode 100644 index 00000000..1103bd38 --- /dev/null +++ b/index.js @@ -0,0 +1 @@ +exports.CleanCSS = require("./lib/clean"); \ No newline at end of file diff --git a/lib/clean.js b/lib/clean.js new file mode 100644 index 00000000..90c777d3 --- /dev/null +++ b/lib/clean.js @@ -0,0 +1,123 @@ +var sys = require('sys'); + +var CleanCSS = { + colors: { + white: '#fff', + black: '#000', + fuchsia: '#f0f', + yellow: '#ff0' + }, + + process: function(data) { + var specialComments = [], + contentBlocks = []; + + // replace function + var replace = function(pattern, replacement) { + var start = new Date().getTime(); + data = data.replace(pattern, replacement); + var end = new Date().getTime(); + + if (false && end > start) { + sys.print(pattern); + sys.print(' -> '); + sys.print(end - start); + sys.print(' milliseconds\n'); + } + }; + + // strip comments one by one + for (var end = 0; end < data.length; ) { + var start = data.indexOf('/*', end); + end = data.indexOf('*/', start); + if (start == -1 || end == -1) break; + + if (data[start + 2] == '!') { + // in case of special comments, replace them with a placeholder + specialComments.push(data.substring(start, end + 2)); + data = data.substring(0, start) + '__CSSCOMMENT__' + data.substring(end + 2); + } else { + data = data.substring(0, start) + data.substring(end + 2); + } + end = start; + } + + // replace content: with a placeholder + for (var end = 0; end < data.length; ) { + var start = data.indexOf('content', end); + if (start == -1) break; + + var wrapper = /[^ :]/.exec(data.substring(start + 7))[0]; + if (/['"]/.test(wrapper) == false) { + end = start + 7; + continue; + } + + var firstIndex = data.indexOf(wrapper, start); + var lastIndex = data.indexOf(wrapper, firstIndex + 1); + + contentBlocks.push(data.substring(firstIndex, lastIndex + 1)); + data = data.substring(0, firstIndex) + '__CSSCONTENT__' + data.substring(lastIndex + 1); + end = lastIndex + 1; + } + + replace(/;\s*;+/g, ';') // whitespace between semicolons & multiple semicolons + replace(/\n/g, '') // line breaks + replace(/\s+/g, ' ') // multiple whitespace + replace(/[ ]?,[ ]?/g, ',') // space with a comma + replace(/progid:[^(]+\(([^\)]+)/, function(match, contents) { // restore spaces inside IE filters (IE 7 issue) + return match.replace(/,/g, ', '); + }) + replace(/ ([+~>]) /g, '$1') // replace spaces around selectors + replace(/\{([^}]+)\}/g, function(match, contents) { // whitespace inside content + return '{' + contents.trim().replace(/(\s*)([;:=\s])(\s*)/g, '$2') + '}'; + }) + replace(/;}/g, '}') // trailing semicolons + replace(/rgb\s*\(([^\)]+)\)/g, function(match, color) { // rgb to hex colors + var parts = color.split(','); + var encoded = '#'; + for (var i = 0; i < 3; i++) { + var asHex = parseInt(parts[i], 10).toString(16); + encoded += asHex.length == 1 ? '0' + asHex : asHex; + } + return encoded; + }) + replace(/([^"'=\s])\s*#([0-9a-f]{6})/gi, function(match, prefix, color) { // long hex to short hex + if (color[0] == color[1] && color[2] == color[3] && color[4] == color[5]) + return prefix + '#' + color[0] + color[2] + color[4]; + else + return 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) + if (CleanCSS.colors[colorName]) return property + ':' + CleanCSS.colors[colorName]; + else return match; + }) + replace(/color:#f00/g, 'color:red') // replace #f00 with red as it's shorter + replace(/font\-weight:(\w+)/g, function(match, weight) { // replace font weight with numerical value + 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, contents) { // IE shorter filters + return contents.toLowerCase(); + }) + 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|background):none/g, '$1:0') // none to 0 + replace(/0 0 0 0/g, '0') // multiple zeros into one + replace(/([: ,=\-])0\.(\d)/g, '$1.$2') + replace(/[^\}]+{(;)*}/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 + + // Get the special comments && content back + replace(/__CSSCOMMENT__/g, function() { return specialComments.shift(); }); + replace(/__CSSCONTENT__/g, function() { return contentBlocks.shift(); }); + + return data.trim() // trim spaces at beginning and end + } +}; + +exports.CleanCSS = CleanCSS; \ No newline at end of file diff --git a/lib/purify.js b/lib/purify.js deleted file mode 100644 index e40ba5a8..00000000 --- a/lib/purify.js +++ /dev/null @@ -1,55 +0,0 @@ -var Purify = { - process: function(data) { - // strip comments one by one - for (var end = 0; end < data.length; ) { - var start = data.indexOf('/*', end); - if (data[start + 2] == '!') { // skip special comments: /*!...*/ - end = start + 1; - continue; - } - - end = data.indexOf('*/', start); - if (start == -1 || end == -1) break; - - data = data.substring(0, start) + data.substring(end + 2); - end = start; - } - - return data - .replace(/;\s*;/g, ';;') // whitespace between semicolons - .replace(/;+/g, ';') // multiple semicolons - .replace(/,[ ]+/g, ',') // comma - .replace(/\s+/g, ' ') // whitespace - .replace(/\{([^}]+)\}/g, function(match, contents) { // whitespace inside content - return '{' + contents.trim().replace(/(\s*)([;:=\s])(\s*)/g, '$2') + '}'; - }) - .replace(/;}/g, '}') // trailing semicolons - .replace(/rgb\s*\(([^\)]+)\)/g, function(match, color) { // rgb to hex colors - var parts = color.split(','); - var encoded = '#'; - for (var i = 0; i < 3; i++) { - var asHex = parseInt(parts[i], 10).toString(16); - encoded += asHex.length == 1 ? '0' + asHex : asHex; - } - return encoded; - }) - .replace(/([^"'=\s])\s*#([0-9a-f]{6})/gi, function(match, prefix, color) { // long hex to short hex - if (color[0] == color[1] && color[2] == color[3] && color[4] == color[5]) - return prefix + '#' + color[0] + color[2] + color[4]; - else - return prefix + '#' + color; - }) - .replace(/progid:DXImageTransform\.Microsoft\.Alpha/g, 'alpha') // IE alpha filter - .replace(/(\s|:)0(px|em|ex|cm|mm|in|pt|pc|%)/g, '$1' + '0') // zero + unit to zero - .replace(/none/g, '0') // none to 0 - .replace(/( 0){1,4}/g, '') // multiple zeros into one - .replace(/([: ,])0\.(\d)+/g, '$1.$2') - .replace(/[^\}]+{(;)*}/g, '') // empty elements - .replace(/(.+)(@charset [^;]+;)/, '$2$1') - .replace(/(.+)(@charset [^;]+;)/g, '$1') - .replace(/ {/g, '{') // whitespace before definition - .replace(/\} /g, '}') // whitespace after definition - } -}; - -exports.Purify = Purify; \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 00000000..4440d44d --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "name": "clean-css", + "author": "Jakub Pawlowicz (http://twitter.com/JakubPawlowicz)", + "description": "A well-tested CSS minifier", + "keywords": ["css", "minifier"], + "homepage": "http://github.com/jakubpawlowicz/clean-css", + "repository": { + "type" : "git", + "url" : "http://github.com/jakubpawlowicz/clean-css.git" + }, + "version": "0.1.0", + "main": "index.js", + "bin": { + "purifycss": "./bin/cleancss" + } +} \ No newline at end of file diff --git a/test/batch-test.js b/test/batch-test.js new file mode 100644 index 00000000..3e9f3e19 --- /dev/null +++ b/test/batch-test.js @@ -0,0 +1,31 @@ +var vows = require('vows'), + fs = require('fs'), + assert = require('assert'); + +var CleanCSS = require('../lib/clean').CleanCSS; + +var batchContexts = function() { + var context = {}; + fs.readdirSync('./test/data/').forEach(function(filename) { + if (/min.css$/.exec(filename)) return; + var testName = filename.split('.')[0]; + + context[testName] = { + topic: function() { + return { + plain: fs.readFileSync('./test/data/' + testName + '.css').toString('utf-8'), + minimized: fs.readFileSync('./test/data/' + testName + '-min.css').toString('utf-8').replace(/\n/g, '') + }; + } + } + context[testName]['minimizing ' + testName + '.css'] = function(data) { + assert.equal(CleanCSS.process(data.plain), data.minimized) + }; + }); + + return context; +}; + +vows.describe('clean-batch') + .addBatch(batchContexts()) + .export(module); \ No newline at end of file diff --git a/test/data/960-min.css b/test/data/960-min.css new file mode 100755 index 00000000..c064dd42 --- /dev/null +++ b/test/data/960-min.css @@ -0,0 +1 @@ +.container_24{margin-right:auto;margin-left:auto;width:960px}.grid_1,.grid_2,.grid_3,.grid_4,.grid_5,.grid_6,.grid_7,.grid_8,.grid_9,.grid_10,.grid_11,.grid_12,.grid_13,.grid_14,.grid_15,.grid_16,.grid_17,.grid_18,.grid_19,.grid_20,.grid_21,.grid_22,.grid_23,.grid_24{display:inline;float:right;margin-right:5px;margin-left:5px}.push_1,.pull_1,.push_2,.pull_2,.push_3,.pull_3,.push_4,.pull_4,.push_5,.pull_5,.push_6,.pull_6,.push_7,.pull_7,.push_8,.pull_8,.push_9,.pull_9,.push_10,.pull_10,.push_11,.pull_11,.push_12,.pull_12,.push_13,.pull_13,.push_14,.pull_14,.push_15,.pull_15,.push_16,.pull_16,.push_17,.pull_17,.push_18,.pull_18,.push_19,.pull_19,.push_20,.pull_20,.push_21,.pull_21,.push_22,.pull_22,.push_23,.pull_23{position:relative}.alpha{margin-right:0}.omega{margin-left:0}.container_24 .grid_1{width:30px}.container_24 .grid_2{width:70px}.container_24 .grid_3{width:110px}.container_24 .grid_4{width:150px}.container_24 .grid_5{width:190px}.container_24 .grid_6{width:230px}.container_24 .grid_7{width:270px}.container_24 .grid_8{width:310px}.container_24 .grid_9{width:350px}.container_24 .grid_10{width:390px}.container_24 .grid_11{width:430px}.container_24 .grid_12{width:470px}.container_24 .grid_13{width:510px}.container_24 .grid_14{width:550px}.container_24 .grid_15{width:590px}.container_24 .grid_16{width:630px}.container_24 .grid_17{width:670px}.container_24 .grid_18{width:710px}.container_24 .grid_19{width:750px}.container_24 .grid_20{width:790px}.container_24 .grid_21{width:830px}.container_24 .grid_22{width:870px}.container_24 .grid_23{width:910px}.container_24 .grid_24{width:950px}.container_24 .prefix_1{padding-right:40px}.container_24 .prefix_2{padding-right:80px}.container_24 .prefix_3{padding-right:120px}.container_24 .prefix_4{padding-right:160px}.container_24 .prefix_5{padding-right:200px}.container_24 .prefix_6{padding-right:240px}.container_24 .prefix_7{padding-right:280px}.container_24 .prefix_8{padding-right:320px}.container_24 .prefix_9{padding-right:360px}.container_24 .prefix_10{padding-right:400px}.container_24 .prefix_11{padding-right:440px}.container_24 .prefix_12{padding-right:480px}.container_24 .prefix_13{padding-right:520px}.container_24 .prefix_14{padding-right:560px}.container_24 .prefix_15{padding-right:600px}.container_24 .prefix_16{padding-right:640px}.container_24 .prefix_17{padding-right:680px}.container_24 .prefix_18{padding-right:720px}.container_24 .prefix_19{padding-right:760px}.container_24 .prefix_20{padding-right:800px}.container_24 .prefix_21{padding-right:840px}.container_24 .prefix_22{padding-right:880px}.container_24 .prefix_23{padding-right:920px}.container_24 .suffix_1{padding-left:40px}.container_24 .suffix_2{padding-left:80px}.container_24 .suffix_3{padding-left:120px}.container_24 .suffix_4{padding-left:160px}.container_24 .suffix_5{padding-left:200px}.container_24 .suffix_6{padding-left:240px}.container_24 .suffix_7{padding-left:280px}.container_24 .suffix_8{padding-left:320px}.container_24 .suffix_9{padding-left:360px}.container_24 .suffix_10{padding-left:400px}.container_24 .suffix_11{padding-left:440px}.container_24 .suffix_12{padding-left:480px}.container_24 .suffix_13{padding-left:520px}.container_24 .suffix_14{padding-left:560px}.container_24 .suffix_15{padding-left:600px}.container_24 .suffix_16{padding-left:640px}.container_24 .suffix_17{padding-left:680px}.container_24 .suffix_18{padding-left:720px}.container_24 .suffix_19{padding-left:760px}.container_24 .suffix_20{padding-left:800px}.container_24 .suffix_21{padding-left:840px}.container_24 .suffix_22{padding-left:880px}.container_24 .suffix_23{padding-left:920px}.container_24 .push_1{right:40px}.container_24 .push_2{right:80px}.container_24 .push_3{right:120px}.container_24 .push_4{right:160px}.container_24 .push_5{right:200px}.container_24 .push_6{right:240px}.container_24 .push_7{right:280px}.container_24 .push_8{right:320px}.container_24 .push_9{right:360px}.container_24 .push_10{right:400px}.container_24 .push_11{right:440px}.container_24 .push_12{right:480px}.container_24 .push_13{right:520px}.container_24 .push_14{right:560px}.container_24 .push_15{right:600px}.container_24 .push_16{right:640px}.container_24 .push_17{right:680px}.container_24 .push_18{right:720px}.container_24 .push_19{right:760px}.container_24 .push_20{right:800px}.container_24 .push_21{right:840px}.container_24 .push_22{right:880px}.container_24 .push_23{right:920px}.container_24 .pull_1{right:-40px}.container_24 .pull_2{right:-80px}.container_24 .pull_3{right:-120px}.container_24 .pull_4{right:-160px}.container_24 .pull_5{right:-200px}.container_24 .pull_6{right:-240px}.container_24 .pull_7{right:-280px}.container_24 .pull_8{right:-320px}.container_24 .pull_9{right:-360px}.container_24 .pull_10{right:-400px}.container_24 .pull_11{right:-440px}.container_24 .pull_12{right:-480px}.container_24 .pull_13{right:-520px}.container_24 .pull_14{right:-560px}.container_24 .pull_15{right:-600px}.container_24 .pull_16{right:-640px}.container_24 .pull_17{right:-680px}.container_24 .pull_18{right:-720px}.container_24 .pull_19{right:-760px}.container_24 .pull_20{right:-800px}.container_24 .pull_21{right:-840px}.container_24 .pull_22{right:-880px}.container_24 .pull_23{right:-920px}.clear{clear:both;display:block;overflow:hidden;visibility:hidden;width:0;height:0}.clearfix:before,.clearfix:after{content:'\0020';display:block;overflow:hidden;visibility:hidden;width:0;height:0}.clearfix:after{clear:both}.clearfix{zoom:1} \ No newline at end of file diff --git a/test/data/960.css b/test/data/960.css new file mode 100755 index 00000000..efcf7700 --- /dev/null +++ b/test/data/960.css @@ -0,0 +1,602 @@ +/* + 960 Grid System ~ Core CSS. + Learn more ~ http://960.gs/ + + Licensed under GPL and MIT. +*/ + +/* `Container >> 24 Columns +----------------------------------------------------------------------------------------------------*/ +.container_24 { + margin-right: auto; + margin-left: auto; + width: 960px; +} + +/* `Grid >> Global +----------------------------------------------------------------------------------------------------*/ + +.grid_1, +.grid_2, +.grid_3, +.grid_4, +.grid_5, +.grid_6, +.grid_7, +.grid_8, +.grid_9, +.grid_10, +.grid_11, +.grid_12, +.grid_13, +.grid_14, +.grid_15, +.grid_16, +.grid_17, +.grid_18, +.grid_19, +.grid_20, +.grid_21, +.grid_22, +.grid_23, +.grid_24 { + display: inline; + float: right; + margin-right: 5px; + margin-left: 5px; +} + +.push_1, .pull_1, +.push_2, .pull_2, +.push_3, .pull_3, +.push_4, .pull_4, +.push_5, .pull_5, +.push_6, .pull_6, +.push_7, .pull_7, +.push_8, .pull_8, +.push_9, .pull_9, +.push_10, .pull_10, +.push_11, .pull_11, +.push_12, .pull_12, +.push_13, .pull_13, +.push_14, .pull_14, +.push_15, .pull_15, +.push_16, .pull_16, +.push_17, .pull_17, +.push_18, .pull_18, +.push_19, .pull_19, +.push_20, .pull_20, +.push_21, .pull_21, +.push_22, .pull_22, +.push_23, .pull_23 { + position: relative; +} + +/* `Grid >> Children (Alpha ~ First, Omega ~ Last) +----------------------------------------------------------------------------------------------------*/ + +.alpha { + margin-right: 0; +} + +.omega { + margin-left: 0; +} + +/* `Grid >> 24 Columns +----------------------------------------------------------------------------------------------------*/ + +.container_24 .grid_1 { + width: 30px; +} + +.container_24 .grid_2 { + width: 70px; +} + +.container_24 .grid_3 { + width: 110px; +} + +.container_24 .grid_4 { + width: 150px; +} + +.container_24 .grid_5 { + width: 190px; +} + +.container_24 .grid_6 { + width: 230px; +} + +.container_24 .grid_7 { + width: 270px; +} + +.container_24 .grid_8 { + width: 310px; +} + +.container_24 .grid_9 { + width: 350px; +} + +.container_24 .grid_10 { + width: 390px; +} + +.container_24 .grid_11 { + width: 430px; +} + +.container_24 .grid_12 { + width: 470px; +} + +.container_24 .grid_13 { + width: 510px; +} + +.container_24 .grid_14 { + width: 550px; +} + +.container_24 .grid_15 { + width: 590px; +} + +.container_24 .grid_16 { + width: 630px; +} + +.container_24 .grid_17 { + width: 670px; +} + +.container_24 .grid_18 { + width: 710px; +} + +.container_24 .grid_19 { + width: 750px; +} + +.container_24 .grid_20 { + width: 790px; +} + +.container_24 .grid_21 { + width: 830px; +} + +.container_24 .grid_22 { + width: 870px; +} + +.container_24 .grid_23 { + width: 910px; +} + +.container_24 .grid_24 { + width: 950px; +} + +/* `Prefix Extra Space >> 24 Columns +----------------------------------------------------------------------------------------------------*/ + +.container_24 .prefix_1 { + padding-right: 40px; +} + +.container_24 .prefix_2 { + padding-right: 80px; +} + +.container_24 .prefix_3 { + padding-right: 120px; +} + +.container_24 .prefix_4 { + padding-right: 160px; +} + +.container_24 .prefix_5 { + padding-right: 200px; +} + +.container_24 .prefix_6 { + padding-right: 240px; +} + +.container_24 .prefix_7 { + padding-right: 280px; +} + +.container_24 .prefix_8 { + padding-right: 320px; +} + +.container_24 .prefix_9 { + padding-right: 360px; +} + +.container_24 .prefix_10 { + padding-right: 400px; +} + +.container_24 .prefix_11 { + padding-right: 440px; +} + +.container_24 .prefix_12 { + padding-right: 480px; +} + +.container_24 .prefix_13 { + padding-right: 520px; +} + +.container_24 .prefix_14 { + padding-right: 560px; +} + +.container_24 .prefix_15 { + padding-right: 600px; +} + +.container_24 .prefix_16 { + padding-right: 640px; +} + +.container_24 .prefix_17 { + padding-right: 680px; +} + +.container_24 .prefix_18 { + padding-right: 720px; +} + +.container_24 .prefix_19 { + padding-right: 760px; +} + +.container_24 .prefix_20 { + padding-right: 800px; +} + +.container_24 .prefix_21 { + padding-right: 840px; +} + +.container_24 .prefix_22 { + padding-right: 880px; +} + +.container_24 .prefix_23 { + padding-right: 920px; +} + +/* `Suffix Extra Space >> 24 Columns +----------------------------------------------------------------------------------------------------*/ + +.container_24 .suffix_1 { + padding-left: 40px; +} + +.container_24 .suffix_2 { + padding-left: 80px; +} + +.container_24 .suffix_3 { + padding-left: 120px; +} + +.container_24 .suffix_4 { + padding-left: 160px; +} + +.container_24 .suffix_5 { + padding-left: 200px; +} + +.container_24 .suffix_6 { + padding-left: 240px; +} + +.container_24 .suffix_7 { + padding-left: 280px; +} + +.container_24 .suffix_8 { + padding-left: 320px; +} + +.container_24 .suffix_9 { + padding-left: 360px; +} + +.container_24 .suffix_10 { + padding-left: 400px; +} + +.container_24 .suffix_11 { + padding-left: 440px; +} + +.container_24 .suffix_12 { + padding-left: 480px; +} + +.container_24 .suffix_13 { + padding-left: 520px; +} + +.container_24 .suffix_14 { + padding-left: 560px; +} + +.container_24 .suffix_15 { + padding-left: 600px; +} + +.container_24 .suffix_16 { + padding-left: 640px; +} + +.container_24 .suffix_17 { + padding-left: 680px; +} + +.container_24 .suffix_18 { + padding-left: 720px; +} + +.container_24 .suffix_19 { + padding-left: 760px; +} + +.container_24 .suffix_20 { + padding-left: 800px; +} + +.container_24 .suffix_21 { + padding-left: 840px; +} + +.container_24 .suffix_22 { + padding-left: 880px; +} + +.container_24 .suffix_23 { + padding-left: 920px; +} + +/* `Push Space >> 24 Columns +----------------------------------------------------------------------------------------------------*/ + +.container_24 .push_1 { + right: 40px; +} + +.container_24 .push_2 { + right: 80px; +} + +.container_24 .push_3 { + right: 120px; +} + +.container_24 .push_4 { + right: 160px; +} + +.container_24 .push_5 { + right: 200px; +} + +.container_24 .push_6 { + right: 240px; +} + +.container_24 .push_7 { + right: 280px; +} + +.container_24 .push_8 { + right: 320px; +} + +.container_24 .push_9 { + right: 360px; +} + +.container_24 .push_10 { + right: 400px; +} + +.container_24 .push_11 { + right: 440px; +} + +.container_24 .push_12 { + right: 480px; +} + +.container_24 .push_13 { + right: 520px; +} + +.container_24 .push_14 { + right: 560px; +} + +.container_24 .push_15 { + right: 600px; +} + +.container_24 .push_16 { + right: 640px; +} + +.container_24 .push_17 { + right: 680px; +} + +.container_24 .push_18 { + right: 720px; +} + +.container_24 .push_19 { + right: 760px; +} + +.container_24 .push_20 { + right: 800px; +} + +.container_24 .push_21 { + right: 840px; +} + +.container_24 .push_22 { + right: 880px; +} + +.container_24 .push_23 { + right: 920px; +} + +/* `Pull Space >> 24 Columns +----------------------------------------------------------------------------------------------------*/ + +.container_24 .pull_1 { + right: -40px; +} + +.container_24 .pull_2 { + right: -80px; +} + +.container_24 .pull_3 { + right: -120px; +} + +.container_24 .pull_4 { + right: -160px; +} + +.container_24 .pull_5 { + right: -200px; +} + +.container_24 .pull_6 { + right: -240px; +} + +.container_24 .pull_7 { + right: -280px; +} + +.container_24 .pull_8 { + right: -320px; +} + +.container_24 .pull_9 { + right: -360px; +} + +.container_24 .pull_10 { + right: -400px; +} + +.container_24 .pull_11 { + right: -440px; +} + +.container_24 .pull_12 { + right: -480px; +} + +.container_24 .pull_13 { + right: -520px; +} + +.container_24 .pull_14 { + right: -560px; +} + +.container_24 .pull_15 { + right: -600px; +} + +.container_24 .pull_16 { + right: -640px; +} + +.container_24 .pull_17 { + right: -680px; +} + +.container_24 .pull_18 { + right: -720px; +} + +.container_24 .pull_19 { + right: -760px; +} + +.container_24 .pull_20 { + right: -800px; +} + +.container_24 .pull_21 { + right: -840px; +} + +.container_24 .pull_22 { + right: -880px; +} + +.container_24 .pull_23 { + right: -920px; +} + +/* `Clear Floated Elements +----------------------------------------------------------------------------------------------------*/ + +/* http://sonspring.com/journal/clearing-floats */ + +.clear { + clear: both; + display: block; + overflow: hidden; + visibility: hidden; + width: 0; + height: 0; +} + +/* http://www.yuiblog.com/blog/2010/09/27/clearfix-reloaded-overflowhidden-demystified */ + +.clearfix:before, +.clearfix:after { + content: '\0020'; + display: block; + overflow: hidden; + visibility: hidden; + width: 0; + height: 0; +} + +.clearfix:after { + clear: both; +} + +/* + The following zoom:1 rule is specifically for IE6 + IE7. + Move to separate stylesheet if invalid CSS is a problem. +*/ + +.clearfix { + zoom: 1; +} \ No newline at end of file diff --git a/test/data/blueprint-min.css b/test/data/blueprint-min.css new file mode 100644 index 00000000..87525470 --- /dev/null +++ b/test/data/blueprint-min.css @@ -0,0 +1,245 @@ +html{margin:0;padding:0;border:0} +body,div,span,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,code,del,dfn,em,img,q,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,dialog,figure,footer,header,hgroup,nav,section{margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline} +article,aside,dialog,figure,footer,header,hgroup,nav,section{display:block} +body{line-height:1.5;background:#fff} +table{border-collapse:separate;border-spacing:0} +caption,th,td{text-align:left;font-weight:400;float:none !important} +table,th,td{vertical-align:middle} +blockquote:before,blockquote:after,q:before,q:after{content:''} +blockquote,q{quotes:"" ""} +a img{border:0} +:focus{outline:0} +html{font-size:100.01%} +body{font-size:75%;color:#222;background:#fff;font-family:"Helvetica Neue",Arial,Helvetica,sans-serif} +h1,h2,h3,h4,h5,h6{font-weight:400;color:#111} +h1{font-size:3em;line-height:1;margin-bottom:.5em} +h2{font-size:2em;margin-bottom:.75em} +h3{font-size:1.5em;line-height:1;margin-bottom:1em} +h4{font-size:1.2em;line-height:1.25;margin-bottom:1.25em} +h5{font-size:1em;font-weight:700;margin-bottom:1.5em} +h6{font-size:1em;font-weight:700} +h1 img,h2 img,h3 img,h4 img,h5 img,h6 img{margin:0} +p{margin:0 0 1.5em} +.left{float:left !important} +p .left{margin:1.5em 1.5em 1.5em 0;padding:0} +.right{float:right !important} +p .right{margin:1.5em 0 1.5em 1.5em;padding:0} +a:focus,a:hover{color:#09f} +a{color:#06c;text-decoration:underline} +blockquote{margin:1.5em;color:#666;font-style:italic} +strong,dfn{font-weight:700} +em,dfn{font-style:italic} +sup,sub{line-height:0} +abbr,acronym{border-bottom:1px dotted #666} +address{margin:0 0 1.5em;font-style:italic} +del{color:#666} +pre{margin:1.5em 0;white-space:pre} +pre,code,tt{font:1em 'andale mono','lucida console',monospace;line-height:1.5} +li ul,li ol{margin:0} +ul,ol{margin:0 1.5em 1.5em 0;padding-left:1.5em} +ul{list-style-type:disc} +ol{list-style-type:decimal} +dl{margin:0 0 1.5em 0} +dl dt{font-weight:700} +dd{margin-left:1.5em} +table{margin-bottom:1.4em;width:100%} +th{font-weight:700} +thead th{background:#c3d9ff} +th,td,caption{padding:4px 10px 4px 5px} +tbody tr:nth-child(even) td,tbody tr.even td{background:#e5ecf9} +tfoot{font-style:italic} +caption{background:#eee} +.small{font-size:.8em;margin-bottom:1.875em;line-height:1.875em} +.large{font-size:1.2em;line-height:2.5em;margin-bottom:1.25em} +.hide{display:none} +.quiet{color:#666} +.loud{color:#000} +.highlight{background:#ff0} +.added{background:#060;color:#fff} +.removed{background:#900;color:#fff} +.first{margin-left:0;padding-left:0} +.last{margin-right:0;padding-right:0} +.top{margin-top:0;padding-top:0} +.bottom{margin-bottom:0;padding-bottom:0} +label{font-weight:700} +fieldset{padding:0 1.4em 1.4em 1.4em;margin:0 0 1.5em 0;border:1px solid #ccc} +legend{font-weight:700;font-size:1.2em;margin-top:-.2em;margin-bottom:1em} +fieldset,#IE8#HACK{padding-top:1.4em} +legend,#IE8#HACK{margin-top:0;margin-bottom:0} +input[type=text],input[type=password],input.text,input.title,textarea{background-color:#fff;border:1px solid #bbb} +input[type=text]:focus,input[type=password]:focus,input.text:focus,input.title:focus,textarea:focus{border-color:#666} +select{background-color:#fff;border-width:1px;border-style:solid} +input[type=text],input[type=password],input.text,input.title,textarea,select{margin:.5em 0} +input.text,input.title{width:300px;padding:5px} +input.title{font-size:1.5em} +textarea{width:390px;height:250px;padding:5px} +form.inline{line-height:3} +form.inline p{margin-bottom:0} +.error,.alert,.notice,.success,.info{padding:.8em;margin-bottom:1em;border:2px solid #ddd} +.error,.alert{background:#fbe3e4;color:#8a1f11;border-color:#fbc2c4} +.notice{background:#fff6bf;color:#514721;border-color:#ffd324} +.success{background:#e6efc2;color:#264409;border-color:#c6d880} +.info{background:#d5edf8;color:#205791;border-color:#92cae4} +.error a,.alert a{color:#8a1f11} +.notice a{color:#514721} +.success a{color:#264409} +.info a{color:#205791} +.container{width:950px;margin:0 auto} +.showgrid{background:url(src/grid.png)} +.column,.span-1,.span-2,.span-3,.span-4,.span-5,.span-6,.span-7,.span-8,.span-9,.span-10,.span-11,.span-12,.span-13,.span-14,.span-15,.span-16,.span-17,.span-18,.span-19,.span-20,.span-21,.span-22,.span-23,.span-24{float:left;margin-right:10px} +.last{margin-right:0} +.span-1{width:30px} +.span-2{width:70px} +.span-3{width:110px} +.span-4{width:150px} +.span-5{width:190px} +.span-6{width:230px} +.span-7{width:270px} +.span-8{width:310px} +.span-9{width:350px} +.span-10{width:390px} +.span-11{width:430px} +.span-12{width:470px} +.span-13{width:510px} +.span-14{width:550px} +.span-15{width:590px} +.span-16{width:630px} +.span-17{width:670px} +.span-18{width:710px} +.span-19{width:750px} +.span-20{width:790px} +.span-21{width:830px} +.span-22{width:870px} +.span-23{width:910px} +.span-24{width:950px;margin-right:0} +input.span-1,textarea.span-1,input.span-2,textarea.span-2,input.span-3,textarea.span-3,input.span-4,textarea.span-4,input.span-5,textarea.span-5,input.span-6,textarea.span-6,input.span-7,textarea.span-7,input.span-8,textarea.span-8,input.span-9,textarea.span-9,input.span-10,textarea.span-10,input.span-11,textarea.span-11,input.span-12,textarea.span-12,input.span-13,textarea.span-13,input.span-14,textarea.span-14,input.span-15,textarea.span-15,input.span-16,textarea.span-16,input.span-17,textarea.span-17,input.span-18,textarea.span-18,input.span-19,textarea.span-19,input.span-20,textarea.span-20,input.span-21,textarea.span-21,input.span-22,textarea.span-22,input.span-23,textarea.span-23,input.span-24,textarea.span-24{border-left-width:1px;border-right-width:1px;padding-left:5px;padding-right:5px} +input.span-1,textarea.span-1{width:18px} +input.span-2,textarea.span-2{width:58px} +input.span-3,textarea.span-3{width:98px} +input.span-4,textarea.span-4{width:138px} +input.span-5,textarea.span-5{width:178px} +input.span-6,textarea.span-6{width:218px} +input.span-7,textarea.span-7{width:258px} +input.span-8,textarea.span-8{width:298px} +input.span-9,textarea.span-9{width:338px} +input.span-10,textarea.span-10{width:378px} +input.span-11,textarea.span-11{width:418px} +input.span-12,textarea.span-12{width:458px} +input.span-13,textarea.span-13{width:498px} +input.span-14,textarea.span-14{width:538px} +input.span-15,textarea.span-15{width:578px} +input.span-16,textarea.span-16{width:618px} +input.span-17,textarea.span-17{width:658px} +input.span-18,textarea.span-18{width:698px} +input.span-19,textarea.span-19{width:738px} +input.span-20,textarea.span-20{width:778px} +input.span-21,textarea.span-21{width:818px} +input.span-22,textarea.span-22{width:858px} +input.span-23,textarea.span-23{width:898px} +input.span-24,textarea.span-24{width:938px} +.append-1{padding-right:40px} +.append-2{padding-right:80px} +.append-3{padding-right:120px} +.append-4{padding-right:160px} +.append-5{padding-right:200px} +.append-6{padding-right:240px} +.append-7{padding-right:280px} +.append-8{padding-right:320px} +.append-9{padding-right:360px} +.append-10{padding-right:400px} +.append-11{padding-right:440px} +.append-12{padding-right:480px} +.append-13{padding-right:520px} +.append-14{padding-right:560px} +.append-15{padding-right:600px} +.append-16{padding-right:640px} +.append-17{padding-right:680px} +.append-18{padding-right:720px} +.append-19{padding-right:760px} +.append-20{padding-right:800px} +.append-21{padding-right:840px} +.append-22{padding-right:880px} +.append-23{padding-right:920px} +.prepend-1{padding-left:40px} +.prepend-2{padding-left:80px} +.prepend-3{padding-left:120px} +.prepend-4{padding-left:160px} +.prepend-5{padding-left:200px} +.prepend-6{padding-left:240px} +.prepend-7{padding-left:280px} +.prepend-8{padding-left:320px} +.prepend-9{padding-left:360px} +.prepend-10{padding-left:400px} +.prepend-11{padding-left:440px} +.prepend-12{padding-left:480px} +.prepend-13{padding-left:520px} +.prepend-14{padding-left:560px} +.prepend-15{padding-left:600px} +.prepend-16{padding-left:640px} +.prepend-17{padding-left:680px} +.prepend-18{padding-left:720px} +.prepend-19{padding-left:760px} +.prepend-20{padding-left:800px} +.prepend-21{padding-left:840px} +.prepend-22{padding-left:880px} +.prepend-23{padding-left:920px} +.border{padding-right:4px;margin-right:5px;border-right:1px solid #ddd} +.colborder{padding-right:24px;margin-right:25px;border-right:1px solid #ddd} +.pull-1{margin-left:-40px} +.pull-2{margin-left:-80px} +.pull-3{margin-left:-120px} +.pull-4{margin-left:-160px} +.pull-5{margin-left:-200px} +.pull-6{margin-left:-240px} +.pull-7{margin-left:-280px} +.pull-8{margin-left:-320px} +.pull-9{margin-left:-360px} +.pull-10{margin-left:-400px} +.pull-11{margin-left:-440px} +.pull-12{margin-left:-480px} +.pull-13{margin-left:-520px} +.pull-14{margin-left:-560px} +.pull-15{margin-left:-600px} +.pull-16{margin-left:-640px} +.pull-17{margin-left:-680px} +.pull-18{margin-left:-720px} +.pull-19{margin-left:-760px} +.pull-20{margin-left:-800px} +.pull-21{margin-left:-840px} +.pull-22{margin-left:-880px} +.pull-23{margin-left:-920px} +.pull-24{margin-left:-960px} +.pull-1,.pull-2,.pull-3,.pull-4,.pull-5,.pull-6,.pull-7,.pull-8,.pull-9,.pull-10,.pull-11,.pull-12,.pull-13,.pull-14,.pull-15,.pull-16,.pull-17,.pull-18,.pull-19,.pull-20,.pull-21,.pull-22,.pull-23,.pull-24{float:left;position:relative} +.push-1{margin:0 -40px 1.5em 40px} +.push-2{margin:0 -80px 1.5em 80px} +.push-3{margin:0 -120px 1.5em 120px} +.push-4{margin:0 -160px 1.5em 160px} +.push-5{margin:0 -200px 1.5em 200px} +.push-6{margin:0 -240px 1.5em 240px} +.push-7{margin:0 -280px 1.5em 280px} +.push-8{margin:0 -320px 1.5em 320px} +.push-9{margin:0 -360px 1.5em 360px} +.push-10{margin:0 -400px 1.5em 400px} +.push-11{margin:0 -440px 1.5em 440px} +.push-12{margin:0 -480px 1.5em 480px} +.push-13{margin:0 -520px 1.5em 520px} +.push-14{margin:0 -560px 1.5em 560px} +.push-15{margin:0 -600px 1.5em 600px} +.push-16{margin:0 -640px 1.5em 640px} +.push-17{margin:0 -680px 1.5em 680px} +.push-18{margin:0 -720px 1.5em 720px} +.push-19{margin:0 -760px 1.5em 760px} +.push-20{margin:0 -800px 1.5em 800px} +.push-21{margin:0 -840px 1.5em 840px} +.push-22{margin:0 -880px 1.5em 880px} +.push-23{margin:0 -920px 1.5em 920px} +.push-24{margin:0 -960px 1.5em 960px} +.push-1,.push-2,.push-3,.push-4,.push-5,.push-6,.push-7,.push-8,.push-9,.push-10,.push-11,.push-12,.push-13,.push-14,.push-15,.push-16,.push-17,.push-18,.push-19,.push-20,.push-21,.push-22,.push-23,.push-24{float:left;position:relative} +div.prepend-top,.prepend-top{margin-top:1.5em} +div.append-bottom,.append-bottom{margin-bottom:1.5em} +.box{padding:1.5em;margin-bottom:1.5em;background:#e5eCf9} +hr{background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:1px;margin:0 0 1.45em;border:0} +hr.space{background:#fff;color:#fff;visibility:hidden} +.clearfix:after,.container:after{content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden} +.clearfix,.container{display:block} +.clear{clear:both} \ No newline at end of file diff --git a/test/data/blueprint.css b/test/data/blueprint.css new file mode 100644 index 00000000..ed0bd155 --- /dev/null +++ b/test/data/blueprint.css @@ -0,0 +1,556 @@ +/* -------------------------------------------------------------- + + reset.css + * Resets default browser CSS. + +-------------------------------------------------------------- */ + +html { + margin:0; + padding:0; + border:0; +} + +body, div, span, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, code, +del, dfn, em, img, q, dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, dialog, figure, footer, header, +hgroup, nav, section { + margin: 0; + padding: 0; + border: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; +} + +/* This helps to make newer HTML5 elements behave like DIVs in older browers */ +article, aside, dialog, figure, footer, header, +hgroup, nav, section { + display:block; +} + +/* Line-height should always be unitless! */ +body { + line-height: 1.5; + background: white; +} + +/* Tables still need 'cellspacing="0"' in the markup. */ +table { + border-collapse: separate; + border-spacing: 0; +} +/* float:none prevents the span-x classes from breaking table-cell display */ +caption, th, td { + text-align: left; + font-weight: normal; + float:none !important; +} +table, th, td { + vertical-align: middle; +} + +/* Remove possible quote marks (") from ,
. */ +blockquote:before, blockquote:after, q:before, q:after { content: ''; } +blockquote, q { quotes: "" ""; } + +/* Remove annoying border on linked images. */ +a img { border: none; } + +/* Remember to define your own focus styles! */ +:focus { outline: 0; } + +/* -------------------------------------------------------------- + + typography.css + * Sets up some sensible default typography. + +-------------------------------------------------------------- */ + +/* Default font settings. + The font-size percentage is of 16px. (0.75 * 16px = 12px) */ +html { font-size:100.01%; } +body { + font-size: 75%; + color: #222; + background: #fff; + font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; +} + + +/* Headings +-------------------------------------------------------------- */ + +h1,h2,h3,h4,h5,h6 { font-weight: normal; color: #111; } + +h1 { font-size: 3em; line-height: 1; margin-bottom: 0.5em; } +h2 { font-size: 2em; margin-bottom: 0.75em; } +h3 { font-size: 1.5em; line-height: 1; margin-bottom: 1em; } +h4 { font-size: 1.2em; line-height: 1.25; margin-bottom: 1.25em; } +h5 { font-size: 1em; font-weight: bold; margin-bottom: 1.5em; } +h6 { font-size: 1em; font-weight: bold; } + +h1 img, h2 img, h3 img, +h4 img, h5 img, h6 img { + margin: 0; +} + + +/* Text elements +-------------------------------------------------------------- */ + +p { margin: 0 0 1.5em; } +/* + These can be used to pull an image at the start of a paragraph, so + that the text flows around it (usage:

Text

) + */ +.left { float: left !important; } +p .left { margin: 1.5em 1.5em 1.5em 0; padding: 0; } +.right { float: right !important; } +p .right { margin: 1.5em 0 1.5em 1.5em; padding: 0; } + +a:focus, +a:hover { color: #09f; } +a { color: #06c; text-decoration: underline; } + +blockquote { margin: 1.5em; color: #666; font-style: italic; } +strong,dfn { font-weight: bold; } +em,dfn { font-style: italic; } +sup, sub { line-height: 0; } + +abbr, +acronym { border-bottom: 1px dotted #666; } +address { margin: 0 0 1.5em; font-style: italic; } +del { color:#666; } + +pre { margin: 1.5em 0; white-space: pre; } +pre,code,tt { font: 1em 'andale mono', 'lucida console', monospace; line-height: 1.5; } + + +/* Lists +-------------------------------------------------------------- */ + +li ul, +li ol { margin: 0; } +ul, ol { margin: 0 1.5em 1.5em 0; padding-left: 1.5em; } + +ul { list-style-type: disc; } +ol { list-style-type: decimal; } + +dl { margin: 0 0 1.5em 0; } +dl dt { font-weight: bold; } +dd { margin-left: 1.5em;} + + +/* Tables +-------------------------------------------------------------- */ + +/* + Because of the need for padding on TH and TD, the vertical rhythm + on table cells has to be 27px, instead of the standard 18px or 36px + of other elements. + */ +table { margin-bottom: 1.4em; width:100%; } +th { font-weight: bold; } +thead th { background: #c3d9ff; } +th,td,caption { padding: 4px 10px 4px 5px; } +/* + You can zebra-stripe your tables in outdated browsers by adding + the class "even" to every other table row. + */ +tbody tr:nth-child(even) td, +tbody tr.even td { + background: #e5ecf9; +} +tfoot { font-style: italic; } +caption { background: #eee; } + + +/* Misc classes +-------------------------------------------------------------- */ + +.small { font-size: .8em; margin-bottom: 1.875em; line-height: 1.875em; } +.large { font-size: 1.2em; line-height: 2.5em; margin-bottom: 1.25em; } +.hide { display: none; } + +.quiet { color: #666; } +.loud { color: #000; } +.highlight { background:#ff0; } +.added { background:#060; color: #fff; } +.removed { background:#900; color: #fff; } + +.first { margin-left:0; padding-left:0; } +.last { margin-right:0; padding-right:0; } +.top { margin-top:0; padding-top:0; } +.bottom { margin-bottom:0; padding-bottom:0; } + +/* -------------------------------------------------------------- + + forms.css + * Sets up some default styling for forms + * Gives you classes to enhance your forms + + Usage: + * For text fields, use class .title or .text + * For inline forms, use .inline (even when using columns) + +-------------------------------------------------------------- */ + +/* + A special hack is included for IE8 since it does not apply padding + correctly on fieldsets + */ +label { font-weight: bold; } +fieldset { padding:0 1.4em 1.4em 1.4em; margin: 0 0 1.5em 0; border: 1px solid #ccc; } +legend { font-weight: bold; font-size:1.2em; margin-top:-0.2em; margin-bottom:1em; } + +fieldset, #IE8#HACK { padding-top:1.4em; } +legend, #IE8#HACK { margin-top:0; margin-bottom:0; } + +/* Form fields +-------------------------------------------------------------- */ + +/* + Attribute selectors are used to differentiate the different types + of input elements, but to support old browsers, you will have to + add classes for each one. ".title" simply creates a large text + field, this is purely for looks. + */ +input[type=text], input[type=password], +input.text, input.title, +textarea { + background-color:#fff; + border:1px solid #bbb; +} +input[type=text]:focus, input[type=password]:focus, +input.text:focus, input.title:focus, +textarea:focus { + border-color:#666; +} +select { background-color:#fff; border-width:1px; border-style:solid; } + +input[type=text], input[type=password], +input.text, input.title, +textarea, select { + margin:0.5em 0; +} + +input.text, +input.title { width: 300px; padding:5px; } +input.title { font-size:1.5em; } +textarea { width: 390px; height: 250px; padding:5px; } + +/* + This is to be used on forms where a variety of elements are + placed side-by-side. Use the p tag to denote a line. + */ +form.inline { line-height:3; } +form.inline p { margin-bottom:0; } + + +/* Success, info, notice and error/alert boxes +-------------------------------------------------------------- */ + +.error, +.alert, +.notice, +.success, +.info { padding: 0.8em; margin-bottom: 1em; border: 2px solid #ddd; } + +.error, .alert { background: #fbe3e4; color: #8a1f11; border-color: #fbc2c4; } +.notice { background: #fff6bf; color: #514721; border-color: #ffd324; } +.success { background: #e6efc2; color: #264409; border-color: #c6d880; } +.info { background: #d5edf8; color: #205791; border-color: #92cae4; } +.error a, .alert a { color: #8a1f11; } +.notice a { color: #514721; } +.success a { color: #264409; } +.info a { color: #205791; } + + +/* -------------------------------------------------------------- + + grid.css + * Sets up an easy-to-use grid of 24 columns. + + By default, the grid is 950px wide, with 24 columns + spanning 30px, and a 10px margin between columns. + + If you need fewer or more columns, namespaces or semantic + element names, use the compressor script (lib/compress.rb) + +-------------------------------------------------------------- */ + +/* A container should group all your columns. */ +.container { + width: 950px; + margin: 0 auto; +} + +/* Use this class on any .span / container to see the grid. */ +.showgrid { + background: url(src/grid.png); +} + + +/* Columns +-------------------------------------------------------------- */ + +/* Sets up basic grid floating and margin. */ +.column, .span-1, .span-2, .span-3, .span-4, .span-5, .span-6, .span-7, .span-8, .span-9, .span-10, .span-11, .span-12, .span-13, .span-14, .span-15, .span-16, .span-17, .span-18, .span-19, .span-20, .span-21, .span-22, .span-23, .span-24 { + float: left; + margin-right: 10px; +} + +/* The last column in a row needs this class. */ +.last { margin-right: 0; } + +/* Use these classes to set the width of a column. */ +.span-1 {width: 30px;} + +.span-2 {width: 70px;} +.span-3 {width: 110px;} +.span-4 {width: 150px;} +.span-5 {width: 190px;} +.span-6 {width: 230px;} +.span-7 {width: 270px;} +.span-8 {width: 310px;} +.span-9 {width: 350px;} +.span-10 {width: 390px;} +.span-11 {width: 430px;} +.span-12 {width: 470px;} +.span-13 {width: 510px;} +.span-14 {width: 550px;} +.span-15 {width: 590px;} +.span-16 {width: 630px;} +.span-17 {width: 670px;} +.span-18 {width: 710px;} +.span-19 {width: 750px;} +.span-20 {width: 790px;} +.span-21 {width: 830px;} +.span-22 {width: 870px;} +.span-23 {width: 910px;} +.span-24 {width:950px; margin-right:0;} + +/* Use these classes to set the width of an input. */ +input.span-1, textarea.span-1, input.span-2, textarea.span-2, input.span-3, textarea.span-3, input.span-4, textarea.span-4, input.span-5, textarea.span-5, input.span-6, textarea.span-6, input.span-7, textarea.span-7, input.span-8, textarea.span-8, input.span-9, textarea.span-9, input.span-10, textarea.span-10, input.span-11, textarea.span-11, input.span-12, textarea.span-12, input.span-13, textarea.span-13, input.span-14, textarea.span-14, input.span-15, textarea.span-15, input.span-16, textarea.span-16, input.span-17, textarea.span-17, input.span-18, textarea.span-18, input.span-19, textarea.span-19, input.span-20, textarea.span-20, input.span-21, textarea.span-21, input.span-22, textarea.span-22, input.span-23, textarea.span-23, input.span-24, textarea.span-24 { + border-left-width: 1px; + border-right-width: 1px; + padding-left: 5px; + padding-right: 5px; +} + +input.span-1, textarea.span-1 { width: 18px; } +input.span-2, textarea.span-2 { width: 58px; } +input.span-3, textarea.span-3 { width: 98px; } +input.span-4, textarea.span-4 { width: 138px; } +input.span-5, textarea.span-5 { width: 178px; } +input.span-6, textarea.span-6 { width: 218px; } +input.span-7, textarea.span-7 { width: 258px; } +input.span-8, textarea.span-8 { width: 298px; } +input.span-9, textarea.span-9 { width: 338px; } +input.span-10, textarea.span-10 { width: 378px; } +input.span-11, textarea.span-11 { width: 418px; } +input.span-12, textarea.span-12 { width: 458px; } +input.span-13, textarea.span-13 { width: 498px; } +input.span-14, textarea.span-14 { width: 538px; } +input.span-15, textarea.span-15 { width: 578px; } +input.span-16, textarea.span-16 { width: 618px; } +input.span-17, textarea.span-17 { width: 658px; } +input.span-18, textarea.span-18 { width: 698px; } +input.span-19, textarea.span-19 { width: 738px; } +input.span-20, textarea.span-20 { width: 778px; } +input.span-21, textarea.span-21 { width: 818px; } +input.span-22, textarea.span-22 { width: 858px; } +input.span-23, textarea.span-23 { width: 898px; } +input.span-24, textarea.span-24 { width: 938px; } + +/* Add these to a column to append empty cols. */ + +.append-1 { padding-right: 40px;} +.append-2 { padding-right: 80px;} +.append-3 { padding-right: 120px;} +.append-4 { padding-right: 160px;} +.append-5 { padding-right: 200px;} +.append-6 { padding-right: 240px;} +.append-7 { padding-right: 280px;} +.append-8 { padding-right: 320px;} +.append-9 { padding-right: 360px;} +.append-10 { padding-right: 400px;} +.append-11 { padding-right: 440px;} +.append-12 { padding-right: 480px;} +.append-13 { padding-right: 520px;} +.append-14 { padding-right: 560px;} +.append-15 { padding-right: 600px;} +.append-16 { padding-right: 640px;} +.append-17 { padding-right: 680px;} +.append-18 { padding-right: 720px;} +.append-19 { padding-right: 760px;} +.append-20 { padding-right: 800px;} +.append-21 { padding-right: 840px;} +.append-22 { padding-right: 880px;} +.append-23 { padding-right: 920px;} + +/* Add these to a column to prepend empty cols. */ + +.prepend-1 { padding-left: 40px;} +.prepend-2 { padding-left: 80px;} +.prepend-3 { padding-left: 120px;} +.prepend-4 { padding-left: 160px;} +.prepend-5 { padding-left: 200px;} +.prepend-6 { padding-left: 240px;} +.prepend-7 { padding-left: 280px;} +.prepend-8 { padding-left: 320px;} +.prepend-9 { padding-left: 360px;} +.prepend-10 { padding-left: 400px;} +.prepend-11 { padding-left: 440px;} +.prepend-12 { padding-left: 480px;} +.prepend-13 { padding-left: 520px;} +.prepend-14 { padding-left: 560px;} +.prepend-15 { padding-left: 600px;} +.prepend-16 { padding-left: 640px;} +.prepend-17 { padding-left: 680px;} +.prepend-18 { padding-left: 720px;} +.prepend-19 { padding-left: 760px;} +.prepend-20 { padding-left: 800px;} +.prepend-21 { padding-left: 840px;} +.prepend-22 { padding-left: 880px;} +.prepend-23 { padding-left: 920px;} + + +/* Border on right hand side of a column. */ +.border { + padding-right: 4px; + margin-right: 5px; + border-right: 1px solid #ddd; +} + +/* Border with more whitespace, spans one column. */ +.colborder { + padding-right: 24px; + margin-right: 25px; + border-right: 1px solid #ddd; +} + + +/* Use these classes on an element to push it into the +next column, or to pull it into the previous column. */ + + +.pull-1 { margin-left: -40px; } +.pull-2 { margin-left: -80px; } +.pull-3 { margin-left: -120px; } +.pull-4 { margin-left: -160px; } +.pull-5 { margin-left: -200px; } +.pull-6 { margin-left: -240px; } +.pull-7 { margin-left: -280px; } +.pull-8 { margin-left: -320px; } +.pull-9 { margin-left: -360px; } +.pull-10 { margin-left: -400px; } +.pull-11 { margin-left: -440px; } +.pull-12 { margin-left: -480px; } +.pull-13 { margin-left: -520px; } +.pull-14 { margin-left: -560px; } +.pull-15 { margin-left: -600px; } +.pull-16 { margin-left: -640px; } +.pull-17 { margin-left: -680px; } +.pull-18 { margin-left: -720px; } +.pull-19 { margin-left: -760px; } +.pull-20 { margin-left: -800px; } +.pull-21 { margin-left: -840px; } +.pull-22 { margin-left: -880px; } +.pull-23 { margin-left: -920px; } +.pull-24 { margin-left: -960px; } + +.pull-1, .pull-2, .pull-3, .pull-4, .pull-5, .pull-6, .pull-7, .pull-8, .pull-9, .pull-10, .pull-11, .pull-12, .pull-13, .pull-14, .pull-15, .pull-16, .pull-17, .pull-18, .pull-19, .pull-20, .pull-21, .pull-22, .pull-23, .pull-24 {float: left; position:relative;} + + +.push-1 { margin: 0 -40px 1.5em 40px; } +.push-2 { margin: 0 -80px 1.5em 80px; } +.push-3 { margin: 0 -120px 1.5em 120px; } +.push-4 { margin: 0 -160px 1.5em 160px; } +.push-5 { margin: 0 -200px 1.5em 200px; } +.push-6 { margin: 0 -240px 1.5em 240px; } +.push-7 { margin: 0 -280px 1.5em 280px; } +.push-8 { margin: 0 -320px 1.5em 320px; } +.push-9 { margin: 0 -360px 1.5em 360px; } +.push-10 { margin: 0 -400px 1.5em 400px; } +.push-11 { margin: 0 -440px 1.5em 440px; } +.push-12 { margin: 0 -480px 1.5em 480px; } +.push-13 { margin: 0 -520px 1.5em 520px; } +.push-14 { margin: 0 -560px 1.5em 560px; } +.push-15 { margin: 0 -600px 1.5em 600px; } +.push-16 { margin: 0 -640px 1.5em 640px; } +.push-17 { margin: 0 -680px 1.5em 680px; } +.push-18 { margin: 0 -720px 1.5em 720px; } +.push-19 { margin: 0 -760px 1.5em 760px; } +.push-20 { margin: 0 -800px 1.5em 800px; } +.push-21 { margin: 0 -840px 1.5em 840px; } +.push-22 { margin: 0 -880px 1.5em 880px; } +.push-23 { margin: 0 -920px 1.5em 920px; } +.push-24 { margin: 0 -960px 1.5em 960px; } + +.push-1, .push-2, .push-3, .push-4, .push-5, .push-6, .push-7, .push-8, .push-9, .push-10, .push-11, .push-12, .push-13, .push-14, .push-15, .push-16, .push-17, .push-18, .push-19, .push-20, .push-21, .push-22, .push-23, .push-24 {float: left; position:relative;} + + +/* Misc classes and elements +-------------------------------------------------------------- */ + +/* In case you need to add a gutter above/below an element */ +div.prepend-top, .prepend-top { + margin-top:1.5em; +} +div.append-bottom, .append-bottom { + margin-bottom:1.5em; +} + +/* Use a .box to create a padded box inside a column. */ +.box { + padding: 1.5em; + margin-bottom: 1.5em; + background: #e5eCf9; +} + +/* Use this to create a horizontal ruler across a column. */ +hr { + background: #ddd; + color: #ddd; + clear: both; + float: none; + width: 100%; + height: 1px; + margin: 0 0 1.45em; + border: none; +} + +hr.space { + background: #fff; + color: #fff; + visibility: hidden; +} + + +/* Clearing floats without extra markup + Based on How To Clear Floats Without Structural Markup by PiE + [http://www.positioniseverything.net/easyclearing.html] */ + +.clearfix:after, .container:after { + content: "\0020"; + display: block; + height: 0; + clear: both; + visibility: hidden; + overflow:hidden; +} +.clearfix, .container {display: block;} + +/* Regular clearing + apply to column that should drop below previous ones. */ + +.clear { clear:both; } + diff --git a/test/data/reset-min.css b/test/data/reset-min.css new file mode 100644 index 00000000..4dd39445 --- /dev/null +++ b/test/data/reset-min.css @@ -0,0 +1,12 @@ +html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline} +:focus{outline:0} +body{line-height:1;color:#000;background:#fff} +ol,ul{list-style:none} +table{border-collapse:separate;border-spacing:0} +caption,th,td{text-align:left;font-weight:400} +blockquote:before,blockquote:after,q:before,q:after{content:""} +blockquote,q{quotes:"" ""} +.clear{clear:both;display:inline-block} +.clear:after,.container:after{content:".";display:block;height:0;clear:both;visibility:hidden} +* html .clear{height:1%} +.clear{display:block} \ No newline at end of file diff --git a/test/data/reset.css b/test/data/reset.css new file mode 100644 index 00000000..cb2aabe3 --- /dev/null +++ b/test/data/reset.css @@ -0,0 +1,64 @@ +/*reset*/ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td { + margin: 0; + padding: 0; + border: 0; + outline: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; +} +/* remember to define focus styles! */ +:focus { + outline: 0; +} +body { + line-height: 1; + color: black; + background: white; +} +ol, ul { + list-style: none; +} +/* tables still need 'cellspacing="0"' in the markup */ +table { + border-collapse: separate; + border-spacing: 0; +} +caption, th, td { + text-align: left; + font-weight: normal; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ""; +} +blockquote, q { + quotes: "" ""; +} +.clear { + clear:both; + display: inline-block; +} +.clear:after, .container:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} +* html .clear { + height: 1%; +} +.clear { + display: block; +} \ No newline at end of file diff --git a/test/purifier-test.js b/test/purifier-test.js deleted file mode 100644 index 8abec44f..00000000 --- a/test/purifier-test.js +++ /dev/null @@ -1,159 +0,0 @@ -var vows = require('vows'), - assert = require('assert'); - -var Purify = require('../lib/purify').Purify; - -var cssContext = function(groups) { - var context = {}; - var clean = function(cleanCss) { - return function(css) { assert.equal(Purify.process(css), cleanCss); } - }; - - for (var g in groups) { - var transformation = groups[g]; - if (typeof transformation == 'string') transformation = [transformation, transformation]; - - context[g] = { - topic: transformation[0], - clean: clean(transformation[1]) - }; - } - - return context; -}; - -vows.describe('purify').addBatch({ - 'identity': cssContext({ - 'preserve minified content': 'a{color:#f00}' - }), - 'semicolons': cssContext({ - 'multiple semicolons': [ - 'a{color:#fff;;;width:0; ;}', - 'a{color:#fff;width:0}' - ], - 'trailing semicolon': [ - 'a{color:#fff;}', - 'a{color:#fff}' - ], - 'trailing semicolon and space': [ - 'a{color:#fff ; }', - 'a{color:#fff}' - ], - 'comma and space': [ - 'a{color:rgba(0, 0, 5, .5)}', - 'a{color:rgba(0,0,5,.5)}' - ] - }), - 'whitespace': cssContext({ - 'one argument': [ - 'div a { color:#fff }', - 'div a{color:#fff}' - ], - 'line breaks': [ - 'div \na\r\n { width:500px }', - 'div a{width:500px}' - ], - 'multiple arguments': [ - 'a{color:#fff ; font-weight: bold }', - 'a{color:#fff;font-weight:bold}' - ], - 'space delimited arguments': [ - 'a {border: 1px solid #f00; margin: 0 auto }', - 'a{border:1px solid #f00;margin:0 auto}' - ] - }), - 'empty elements': cssContext({ - 'single': [ - ' div p { \n}', - '' - ], - 'between non-empty': [ - 'div {color:#fff} a{ } p{ line-height:1.35em}', - 'div{color:#fff}p{line-height:1.35em}' - ], - 'just a semicolon': [ - 'div { ; }', - '' - ] - }), - 'comments': cssContext({ - 'single line': [ - 'a{color:#fff}/* some comment*/p{height:10px/* other comment */}', - 'a{color:#fff}p{height:10px}' - ], - 'multiline': [ - '/* \r\n multiline \n comment */a{color:rgba(0,0,0,0.8)}', - 'a{color:rgba(0,0,0,.8)}' - ], - 'comment chars in comments': [ - '/* \r\n comment chars * inside / comments */a{color:#fff}', - 'a{color:#fff}' - ], - 'comment inside block': [ - 'a{/* \r\n some comments */color:#fff}', - 'a{color:#fff}' - ], - 'special comments': [ - '/*! special comment */a{color:#f00} /* normal comment */', - '/*! special comment */a{color:#f00}' - ] - }), - 'zero values': cssContext({ - 'with units': [ - 'a{margin:0px 0pt 0em 0%;padding: 0in 0cm 0mm 0pc;border-top-width:0ex}', - 'a{margin:0;padding:0;border-top-width:0}' - ], - 'multiple into one': [ - 'a{margin:0 0 0 0;padding:0 0 0;border-width:0 0}', - 'a{margin:0;padding:0;border-width:0}' - ], - 'none to zeros': [ - 'a{border:none;background:none}', - 'a{border:0;background:0}' - ] - }), - 'floats': cssContext({ - 'strips zero in fractions': [ - 'a{ margin-bottom: 0.5em}', - 'a{margin-bottom:.5em}' - ], - 'not strips zero in fractions of numbers greater than zero': [ - 'a{ margin-bottom: 20.5em}', - 'a{margin-bottom:20.5em}' - ] - }), - 'colors': cssContext({ - 'shorten rgb to standard hexadecimal format': [ - 'a{ color:rgb (5, 10, 15) }', - 'a{color:#050a0f}' - ], - 'skip rgba shortening': [ - 'a{ color:rgba(5, 10, 15, 0.5)}', - 'a{color:rgba(5,10,15,.5)}' - ], - 'shorten colors to 3 digit hex instead of 6 digit': [ - 'a{ background-color: #ff0000; color:rgb(0, 17, 255)}', - 'a{background-color:#f00;color:#01f}' - ], - 'skip shortening IE filter colors': [ - 'a{ filter: chroma(color = "#ff0000")}', - 'a{filter:chroma(color="#ff0000")}' - ] - }), - 'ie filters': cssContext({ - 'alpha': [ - "a{ filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80); -ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=50)';}", - "a{filter:alpha(Opacity=80);-ms-filter:'alpha(Opacity=50)'}" - ] - }), - 'charsets': cssContext({ - 'not at beginning': [ - "a{ color: #f00; }@charset 'utf-8';b { font-weight: bold}", - "@charset 'utf-8';a{color:#f00}b{font-weight:bold}" - ], - 'multiple charsets': [ - "@charset 'utf-8';div :before { display: block }@charset 'utf-8';a { color: #f00 }", - "@charset 'utf-8';div :before{display:block}a{color:#f00}" - ] - }) -}).export(module); \ No newline at end of file diff --git a/test/unit-test.js b/test/unit-test.js new file mode 100644 index 00000000..77af20dd --- /dev/null +++ b/test/unit-test.js @@ -0,0 +1,252 @@ +var vows = require('vows'), + assert = require('assert'); + +var CleanCSS = require('../lib/clean').CleanCSS; + +var cssContext = function(groups) { + var context = {}; + var clean = function(cleanCss) { + return function(css) { + assert.equal(CleanCSS.process(css), cleanCss); + } + }; + + for (var g in groups) { + var transformation = groups[g]; + if (typeof transformation == 'string') transformation = [transformation, transformation]; + if (!transformation[0].push) { + transformation = [[transformation[0], transformation[1]]]; + } + + for (var i = 0, c = transformation.length; i < c; i++) { + context[g + ' #' + (i + 1)] = { + topic: transformation[i][0], + clean: clean(transformation[i][1]) + }; + } + } + + return context; +}; + +vows.describe('clean-units').addBatch({ + 'identity': cssContext({ + 'preserve minified content': 'a{color:#f10}' + }), + 'semicolons': cssContext({ + 'multiple semicolons': [ + 'a{color:#fff;;;width:0; ;}', + 'a{color:#fff;width:0}' + ], + 'trailing semicolon': [ + 'a{color:#fff;}', + 'a{color:#fff}' + ], + 'trailing semicolon and space': [ + 'a{color:#fff ; }', + 'a{color:#fff}' + ], + 'comma and space': [ + 'a{color:rgba(0, 0, 5, .5)}', + 'a{color:rgba(0,0,5,.5)}' + ] + }), + 'whitespace': cssContext({ + 'one argument': [ + 'div a { color:#fff }', + 'div a{color:#fff}' + ], + 'line breaks': [ + 'div \na\r\n { width:500px }', + 'div a{width:500px}' + ], + 'line breaks #2': [ + 'div \na\r\n, p { width:500px }', + 'div a,p{width:500px}' + ], + 'multiple arguments': [ + 'a{color:#fff ; font-weight: bolder }', + 'a{color:#fff;font-weight:bolder}' + ], + 'space delimited arguments': [ + 'a {border: 1px solid #f10; margin: 0 auto }', + 'a{border:1px solid #f10;margin:0 auto}' + ], + 'at beginning': [ + ' a {color:#fff}', + 'a{color:#fff}' + ], + 'at end': [ + 'a{color:#fff } ', + 'a{color:#fff}' + ] + }), + 'empty elements': cssContext({ + 'single': [ + ' div p { \n}', + '' + ], + 'between non-empty': [ + 'div {color:#fff} a{ } p{ line-height:1.35em}', + 'div{color:#fff}p{line-height:1.35em}' + ], + 'just a semicolon': [ + 'div { ; }', + '' + ] + }), + 'selectors': cssContext({ + 'remove spaces around selectors': [ + 'div + span > em', + 'div+span>em' + ], + 'not remove spaces for pseudo-classes': [ + 'div :first-child', + 'div :first-child' + ], + 'strip universal selector when coming with id/class/attribute selectors': [ + [ + '* > *#id > *.class', + '*>#id>.class' + ],[ + '*:first-child > *[data-id]', + ':first-child>[data-id]' + ] + ], + 'not strip standalone universal selector': [ + 'label ~ * + span', + 'label~*+span' + ] + }), + 'comments': cssContext({ + 'single line': [ + 'a{color:#fff}/* some comment*/p{height:10px/* other comment */}', + 'a{color:#fff}p{height:10px}' + ], + 'multiline': [ + '/* \r\n multiline \n comment */a{color:rgba(0,0,0,0.8)}', + 'a{color:rgba(0,0,0,.8)}' + ], + 'comment chars in comments': [ + '/* \r\n comment chars * inside / comments */a{color:#fff}', + 'a{color:#fff}' + ], + 'comment inside block': [ + 'a{/* \r\n some comments */color:#fff}', + 'a{color:#fff}' + ], + 'special comments': [ + '/*! special comment */a{color:#f10} /* normal comment */', + '/*! special comment */a{color:#f10}' + ], + 'should keep exact structure': [ + '/*! \n a > span { } with some content */', + '/*! \n a > span { } with some content */' + ] + }), + 'text content': cssContext({ + 'normal': 'a{content:"."}', + 'open quote': [ + 'a{content : open-quote;opacity:1}', + 'a{content:open-quote;opacity:1}' + ], + 'close quote': [ + 'a{content: close-quote;clear:left}', + 'a{content:close-quote;clear:left}' + ], + 'special characters': [ + 'a{content : " a > div { } "}', + 'a{content:" a > div { } "}' + ] + }), + 'zero values': cssContext({ + 'with units': [ + 'a{margin:0px 0pt 0em 0%;padding: 0in 0cm 0mm 0pc;border-top-width:0ex}', + 'a{margin:0;padding:0;border-top-width:0}' + ], + 'multiple into one': [ + 'a{margin:0 0 0 0;padding:0 0 0 0;border-width:0 0 0 0}', + 'a{margin:0;padding:0;border-width:0}' + ], + 'none to zeros': [ + 'a{border:none;background:none}', + 'a{border:0;background:0}' + ], + 'outline:none to outline:0': [ + 'a{outline:none}', + 'a{outline:0}' + ], + 'display:none not changed': 'a{display:none}', + 'mixed zeros not changed': 'div{margin:0 0 1px 0}', + 'mixed zeros not changed #2': 'div{padding:0 1px 0 0}' + }), + 'floats': cssContext({ + 'strips zero in fractions': [ + 'a{ margin-bottom: 0.5em}', + 'a{margin-bottom:.5em}' + ], + 'not strips zero in fractions of numbers greater than zero': [ + 'a{ margin-bottom: 20.5em}', + 'a{margin-bottom:20.5em}' + ] + }), + 'colors': cssContext({ + 'shorten rgb to standard hexadecimal format': [ + 'a{ color:rgb (5, 10, 15) }', + 'a{color:#050a0f}' + ], + 'skip rgba shortening': [ + 'a{ color:rgba(5, 10, 15, 0.5)}', + 'a{color:rgba(5,10,15,.5)}' + ], + 'shorten colors to 3 digit hex instead of 6 digit': [ + 'a{ background-color: #aa0000; color:rgb(0, 17, 255)}', + 'a{background-color:#a00;color:#01f}' + ], + 'skip shortening IE filter colors': [ + 'a{ filter: chroma(color = "#ff0000")}', + 'a{filter:chroma(color="#ff0000")}' + ], + 'color names to hex values': [ + 'a{color:white;border-color:black;background-color:fuchsia}p{background:yellow}', + 'a{color:#fff;border-color:#000;background-color:#f0f}p{background:#ff0}' + ], + 'hex value to color name': [ + 'p{color:#f00}', + 'p{color:red}' + ] + }), + 'font weights': cssContext({ + 'font-weight:normal to 400': [ + 'p{font-weight:normal}', + 'p{font-weight:400}' + ], + 'font-weight:bold to 700': [ + 'p{font-weight:bold}', + 'p{font-weight:700}' + ] + }), + 'ie filters': cssContext({ + 'short alpha': [ + "a{ filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80); -ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=50)';}", + "a{filter:alpha(Opacity=80);-ms-filter:'alpha(Opacity=50)'}" + ], + 'short chroma': [ + 'progid:DXImageTransform.Microsoft.Chroma(color=#919191)', 'chroma(color=#919191)' + ], + 'matrix filter spaces': [ + "progid:DXImageTransform.Microsoft.Matrix(M11=0.984, M22=0.984, M12=0.17, M21=-0.17, SizingMethod='auto expand')", + "progid:DXImageTransform.Microsoft.Matrix(M11=.984, M22=.984, M12=.17, M21=-.17, SizingMethod='auto expand')" + ] + }), + 'charsets': cssContext({ + 'not at beginning': [ + "a{ color: #f10; }@charset 'utf-8';b { font-weight: bolder}", + "@charset 'utf-8';a{color:#f10}b{font-weight:bolder}" + ], + 'multiple charsets': [ + "@charset 'utf-8';div :before { display: block }@charset 'utf-8';a { color: #f10 }", + "@charset 'utf-8';div :before{display:block}a{color:#f10}" + ] + }) +}).export(module); \ No newline at end of file -- 2.34.1