Skip to content

Commit

Permalink
Fix colormin function and add colormin tests
Browse files Browse the repository at this point in the history
  • Loading branch information
TrySound authored and ben-eb committed Feb 27, 2017
1 parent bff8660 commit 0de8842
Show file tree
Hide file tree
Showing 9 changed files with 197 additions and 126 deletions.
1 change: 1 addition & 0 deletions packages/postcss-colormin/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules
npm-debug.log
dist
98 changes: 0 additions & 98 deletions packages/postcss-colormin/lib/colormin.js

This file was deleted.

11 changes: 7 additions & 4 deletions packages/postcss-colormin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
"name": "postcss-colormin",
"version": "2.1.4",
"description": "Minify colors in your CSS files with PostCSS.",
"main": "index.js",
"main": "dist/index.js",
"files": [
"lib",
"index.js",
"dist",
"LICENSE-MIT"
],
"scripts": {
"test": "tape test.js | tap-spec"
"prepublish": "babel src --out-dir dist --ignore /__tests__/",
"test-unformatted": "babel-tape-runner \"src/**/__tests__/*.js\"",
"test": "npm run test-unformatted | tap-spec"
},
"keywords": [
"color",
Expand All @@ -22,6 +23,8 @@
],
"license": "MIT",
"devDependencies": {
"babel": "^5.8.23",
"babel-tape-runner": "^1.2.0",
"tap-spec": "^4.1.0",
"tape": "^4.2.0"
},
Expand Down
34 changes: 34 additions & 0 deletions packages/postcss-colormin/src/__tests__/colormin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use strict';

import test from 'tape';
import min from '../lib/colormin';

test('should return the smallest colour', t => {
t.plan(20);
t.equal(min('RED'), 'red', 'should lowercase keywords');
t.equal(min('#f00'), 'red', 'should convert shorthand hex to keyword');
t.equal(min('#ff0000'), 'red', 'should convert longhand hex to keyword');
t.equal(min('rgb', [255, 0, 0]), 'red', 'should convert rgb to keyword');
t.equal(min('rgba', [255, 0, 0, 1]), 'red', 'should convert fully opaque rgb to keyword');
t.equal(min('hsl', [0, 100, 50]), 'red', 'should convert hsl to keyword');
t.equal(min('hsla', [0, 100, 50, 1]), 'red', 'should convert fully oqaque hsl to keyword');
t.equal(min('hsla', [0, 100, 50, 0.5]), 'rgba(255,0,0,.5)', 'should convert translucent hsla to rgba');
t.equal(min('#FFFFFF'), '#fff', 'should convert longhand hex to shorthand, case insensitive');
t.equal(min('WHiTE'), '#fff', 'should convert keyword to hex, case insensitive');
t.equal(min('yellow'), '#ff0', 'should convert keyword to hex');
t.equal(min('rgb', [12, 134, 29]), '#0c861d', 'should convert rgb to hex');
t.equal(min('hsl', [230, 50, 40]), '#349', 'should convert hsl to hex');
t.equal(min('#000080'), 'navy', 'should convert another longhand hex to keyword');
t.equal(min('rgba', [199, 190, 179, 0.8]), 'hsla(33,15%,74%,.8)', 'should convert rgba to hsla when shorter');
t.equal(min('rgba', [0, 0, 0, 0]), 'transparent', 'should convert this specific rgba value to "transparent"');
t.equal(min('hsla', [0, 0, 0, 0]), 'transparent', 'should convert this specific hsla value to "transparent"');
t.equal(min('hsla', [200, 0, 0, 0]), 'transparent', 'should convert hsla values with 0 saturation & 0 lightness to "transparent"');
t.equal(min('transparent'), 'transparent', 'should leave transparent as it is');
t.equal(min('#696969'), '#696969', 'should prefer to output hex rather than keywords when they are the same length');
});

test('should pass through if not recognised', t => {
t.plan(2);
t.equal(min('Unrecognised'), 'Unrecognised');
t.equal(min('inherit'), 'inherit');
});
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
'use strict';

var test = require('tape');
var postcss = require('postcss');
var plugin = require('./');
var name = require('./package.json').name;
import test from 'tape';
import postcss from 'postcss';
import plugin from '..';
import {name} from '../../package.json';

var tests = module.exports = [{
let tests = [{
message: 'should minify color values',
fixture: 'h1{color:yellow}',
expected: 'h1{color:#ff0}'
Expand All @@ -32,7 +32,7 @@ var tests = module.exports = [{
}, {
message: 'should minify color values in background gradients',
fixture: 'h1{background:linear-gradient( #ff0000,yellow )}',
expected: 'h1{background:linear-gradient(red,#ff0)}'
expected: 'h1{background:linear-gradient( red,#ff0 )}'
}, {
message: 'should minify color values in background gradients (2)',
fixture: 'h1{background:linear-gradient(yellow, orange), linear-gradient(black, rgba(255, 255, 255, 0))}',
Expand Down Expand Up @@ -87,16 +87,16 @@ function process (css, options) {
return postcss(plugin(options)).process(css).css;
}

test(name, function (t) {
test(name, t => {
t.plan(tests.length);

tests.forEach(function (test) {
var options = test.options || {};
tests.forEach(test => {
let options = test.options || {};
t.equal(process(test.fixture, options), test.expected, test.message);
});
});

test('should use the postcss plugin api', function (t) {
test('should use the postcss plugin api', t => {
t.plan(2);
t.ok(plugin().postcssVersion, 'should be able to access version');
t.equal(plugin().postcssPlugin, name, 'should be able to access name');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
'use strict';

var colormin = require('./lib/colormin');
var postcss = require('postcss');
var parser = require('postcss-value-parser');
import postcss from 'postcss';
import valueParser from 'postcss-value-parser';
import colormin from './lib/colormin';

function extractColorArguments(nodes) {
var i, max;
var result = [];
for (i = 0, max = nodes.length; i < max; i += 1) {
let result = [];
for (let i = 0, max = nodes.length; i < max; i += 1) {
if (nodes[i].type === 'word') {
result.push(parseFloat(nodes[i].value));
let val = parseFloat(nodes[i].value);
if (isNaN(val)) {
return false;
}
result.push(val);
}
}

return result;
}

function reduceColor (decl) {
decl.value = parser(decl.value).walk(function (node) {
decl.value = valueParser(decl.value).walk(node => {
if (node.type === 'function') {
if (/^(rgb|hsl)a?$/.test(node.value)) {
node.value = colormin(node.value, extractColorArguments(node.nodes));
node.type = 'word';
} else {
node.before = node.after = '';
let args = extractColorArguments(node.nodes);
if (args) {
node.value = colormin(node.value, args);
node.type = 'word';
}
}
} else if (node.type === 'word') {
node.value = colormin(node.value);
Expand All @@ -32,7 +36,7 @@ function reduceColor (decl) {
}

function reduceWhitespaces (decl) {
decl.value = parser(decl.value).walk(function (node) {
decl.value = valueParser(decl.value).walk(node => {
if (node.type === 'function' || node.type === 'div') {
node.before = node.after = '';
}
Expand All @@ -50,7 +54,7 @@ function transform (decl) {
}
}

module.exports = postcss.plugin('postcss-colormin', function () {
export default postcss.plugin('postcss-colormin', () => {
return function (css) {
css.walkDecls(transform);
};
Expand Down
78 changes: 78 additions & 0 deletions packages/postcss-colormin/src/lib/colormin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
'use strict';

import convert from 'colr-convert';
import keywords from 'css-color-names';
import dropLeadingZero from './drop-leading-zero';
import {isHex, toShorthand, toLonghand} from './hex';
let hexes = {};
let round = Math.round;

Object.keys(keywords).forEach(keyword => hexes[keywords[keyword]] = keyword);

let shorter = (a, b) => (a && a.length < b.length ? a : b);

export default function (name, args) {
var word = name.toLowerCase();
if (word === 'rgb' || word === 'rgba' || word === 'hsl' || word === 'hsla') {
if (!args) {
return name;
}
if (word[3] === 'a') {
if (args[1] === 0 && args[2] === 0 && args[3] === 0) {
if (word === 'hsla' || args[0] === 0) {
return 'transparent';
}
}
if (args[3] === 1) {
word = word.slice(0, 3);
} else {
args[3] = dropLeadingZero(args[3]);
}
}
if (word === 'hsl') {
word = 'rgb';
args = convert.hsl.rgb(args);
args[0] = round(args[0]);
args[1] = round(args[1]);
args[2] = round(args[2]);
}
if (word === 'rgb') {
word = convert.rgb.hex(args);
} else {
let rgba, hsla;
// alpha conversion
if (word === 'rgba') {
rgba = args;
hsla = convert.rgb.hsl(args);
hsla[0] = round(hsla[0]);
hsla[1] = round(hsla[1]);
hsla[2] = round(hsla[2]);
hsla.push(args[3]);
} else {
hsla = args;
rgba = convert.hsl.rgb(args);
rgba[0] = round(rgba[0]);
rgba[1] = round(rgba[1]);
rgba[2] = round(rgba[2]);
rgba.push(args[3]);
}
hsla[1] = hsla[1] + '%';
hsla[2] = hsla[2] + '%';
return shorter(`hsla(${hsla.join()})`, `rgba(${rgba.join()})`);
}
}

if (isHex(word)) {
word = toLonghand(word);
if (word in hexes) {
return shorter(hexes[word], toShorthand(word));
}
return toShorthand(word);
}

if (word in keywords) {
return shorter(toShorthand(keywords[word]), word);
}

return name;
};
17 changes: 17 additions & 0 deletions packages/postcss-colormin/src/lib/drop-leading-zero.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use strict';

export default number => {
let value = String(number);

if (number % 1) {
if (value[0] === '0') {
return value.slice(1);
}

if (value[0] === '-' && value[1] === '0') {
return '-' + value.slice(2);
}
}

return value;
}
Loading

0 comments on commit 0de8842

Please sign in to comment.