diff --git a/History.md b/History.md index b33d4c17f..9171db5fe 100644 --- a/History.md +++ b/History.md @@ -4,6 +4,7 @@ * Adds a better algorithm for quotation marks' removal. * Adds a better non-adjacent optimizer compatible with the upcoming new property optimizer. * Adds minifying remote files directly from CLI. +* Adds `--rounding-precision` to control rounding precision. * Moves quotation matching into a `QuoteScanner` class. * Fixed issue [#134](https://github.com/GoalSmashers/clean-css/issues/134) - merges properties into shorthand form. * Fixed issue [#164](https://github.com/GoalSmashers/clean-css/issues/164) - removes default values if not needed. diff --git a/README.md b/README.md index 047b58422..79d1979b6 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ cleancss [options] source-file, [source-file, ...] --skip-rebase Disable URLs rebasing --skip-advanced Disable advanced optimizations - selector & property merging, reduction, etc. +--rounding-precision [value] Rounding precision, defaults to 2 -c, --compatibility [ie7|ie8] Force compatibility mode -d, --debug Shows debug information (minification time & compression efficiency) ``` diff --git a/bin/cleancss b/bin/cleancss index 413ef3941..8def84dca 100755 --- a/bin/cleancss +++ b/bin/cleancss @@ -24,6 +24,7 @@ commands .option('-s, --skip-import', 'Disable @import processing') .option('--skip-rebase', 'Disable URLs rebasing') .option('--skip-advanced', 'Disable advanced optimizations - selector & property merging, reduction, etc.') + .option('--rounding-precision [value]', 'Rounding precision, defaults to 2', parseInt) .option('-c, --compatibility [ie7|ie8]', 'Force compatibility mode') .option('-t, --timeout [seconds]', 'Per connection timeout when fetching remote @imports (defaults to 5 seconds)') .option('-d, --debug', 'Shows debug information (minification time & compression efficiency)'); @@ -76,6 +77,8 @@ if (commands.skipAdvanced) cleanOptions.noAdvanced = true; if (commands.compatibility) cleanOptions.compatibility = commands.compatibility; +if (commands.roundingPrecision !== undefined) + cleanOptions.roundingPrecision = commands.roundingPrecision; if (commands.debug) cleanOptions.debug = true; if (commands.timeout) diff --git a/lib/clean.js b/lib/clean.js index 51bf84c9e..c27607616 100644 --- a/lib/clean.js +++ b/lib/clean.js @@ -263,8 +263,12 @@ var minify = function(data, callback) { replace(/(\s|:|,)0+([1-9])/g, '$1$2'); // round pixels to 2nd decimal place - replace(/\.(\d{3,})px/g, function(match, decimalPlaces) { - return '.' + Math.round(parseFloat('.' + decimalPlaces) * 100) + 'px'; + var precision = 'roundingPrecision' in options ? options.roundingPrecision : 2; + var decimalMultiplier = Math.pow(10, precision); + replace(new RegExp('\\.(\\d{' + (precision + 1) + ',})px', 'g'), function(match, decimalPlaces) { + return precision === 0 ? + 'px' : + '.' + Math.round(parseFloat('.' + decimalPlaces) * decimalMultiplier) / decimalMultiplier + 'px'; }); // .0 to 0 diff --git a/test/binary-test.js b/test/binary-test.js index 68d627d2a..e9731a378 100644 --- a/test/binary-test.js +++ b/test/binary-test.js @@ -290,5 +290,22 @@ exports.commandsSuite = vows.describe('binary commands').addBatch({ 'should not transform source': function(error, stdout) { assert.equal(stdout, readFile('./test/data/unsupported/selectors-ie8.css')); } - }) + }), + 'rounding precision': { + defaults: pipedContext('div{width:0.10051px}', '', { + 'should keep 2 decimal places': function(error, stdout) { + assert.equal(stdout, 'div{width:.1px}'); + } + }), + custom: pipedContext('div{width:0.00051px}', '--rounding-precision 4', { + 'should keep 4 decimal places': function(error, stdout) { + assert.equal(stdout, 'div{width:.0005px}'); + } + }), + zero: pipedContext('div{width:1.5051px}', '--rounding-precision 0', { + 'should keep 0 decimal places': function(error, stdout) { + assert.equal(stdout, 'div{width:1px}'); + } + }) + } }); diff --git a/test/unit-test.js b/test/unit-test.js index 52b89b12f..623c8534d 100644 --- a/test/unit-test.js +++ b/test/unit-test.js @@ -602,6 +602,12 @@ vows.describe('clean-units').addBatch({ 'do not round percentages': 'div{left:20.505%}', 'do not round ems': 'div{font-size:1.505em}' }), + 'floats custom rounding': cssContext({ + 'rounds to 4 values': [ + 'div{transform:translateY(-418.505123px)}', + 'div{transform:translateY(-418.5051px)}' + ] + }, { roundingPrecision: 4 }), 'colors': cssContext({ 'shorten rgb to standard hexadecimal format': [ 'a{ color:rgb(5, 10, 15) }',