color-sorter
Advanced tools
Comparing version 2.0.0 to 2.1.0
const tinycolor = require('tinycolor2') | ||
/* | ||
* Sort by saturation, high to low (ASC, 100% - 0%) | ||
*/ | ||
function sortBySaturation(colorA, colorB) { | ||
return colorA.saturation - colorB.saturation | ||
function normalizeColor(color) { | ||
const {h: hue, s: saturation, l: lightness, a: alpha} = tinycolor( | ||
color | ||
).toHsl() | ||
return {hue, saturation, lightness, alpha} | ||
} | ||
/* | ||
* Sort by hue, red-yellow-green-blue-purple (0-360) | ||
*/ | ||
function sortByHue({hsl: colorA}, {hsl: colorB}) { | ||
const {hue: hueA} = colorA | ||
const {hue: hueB} = colorB | ||
const sortFn = (a, b) => { | ||
const colorA = normalizeColor(a) | ||
const colorB = normalizeColor(b) | ||
// If the hues are the same, sort by saturation | ||
if (hueA === hueB) { | ||
return sortBySaturation(colorA, colorB) | ||
// Move grey-ish colors to the back of the list | ||
if ( | ||
(colorA.saturation === 0 || colorB.saturation === 0) && | ||
colorA.saturation !== colorB.saturation | ||
) { | ||
return 1 | ||
} | ||
return hueA - hueB | ||
} | ||
if (colorA.saturation !== colorB.saturation) { | ||
return colorA.saturation - colorB.saturation | ||
} | ||
/* | ||
* Sort by alpha channel, transparent to opaque | ||
*/ | ||
function sortByAlpha({hsl: colorA}, {hsl: colorB}) { | ||
if (colorA.alpha === colorB.alpha) { | ||
return sortByLightness(colorA, colorB) | ||
if (colorA.hue !== colorB.hue) { | ||
return colorA.hue - colorB.hue | ||
} | ||
return colorB.alpha - colorA.alpha | ||
} | ||
if (colorA.lightness !== colorB.lightness) { | ||
return colorB.lightness - colorA.lightness | ||
} | ||
/* | ||
* Sort by lightness, light to dark | ||
*/ | ||
function sortByLightness(colorA, colorB) { | ||
const {lightness: lightnessA} = colorA | ||
const {lightness: lightnessB} = colorB | ||
if (colorA.alpha !== colorB.alpha) { | ||
return colorB.alpha - colorA.alpha | ||
} | ||
return lightnessB - lightnessA | ||
} | ||
if (a.length !== b.length) { | ||
return a.length - b.length | ||
} | ||
/* | ||
* Determines if a given color is a pure grey | ||
*/ | ||
function isGrey(color) { | ||
return color.hsl.saturation === 0 | ||
return a.localeCompare(b) | ||
} | ||
/* | ||
* Sort an array of CSS colors | ||
* | ||
* @param colors An array of CSS colors | ||
* @returns array A new sorted array | ||
*/ | ||
module.exports = colors => { | ||
// Add an `hsl` prop to our array to use for sorting | ||
const mapped = colors.map(color => { | ||
const {h: hue, s: saturation, l: lightness, a: alpha} = tinycolor( | ||
color | ||
).toHsl() | ||
return { | ||
authored: color, | ||
hsl: {hue, saturation, lightness, alpha} | ||
} | ||
}) | ||
return ( | ||
mapped | ||
// Sort by hue | ||
.sort(sortByHue) | ||
// Remove the grey colors | ||
.filter(color => !isGrey(color)) | ||
.concat( | ||
// Shift the grey colors to the back | ||
mapped | ||
.filter(color => isGrey(color)) | ||
// And sort the greys by lightness | ||
.sort(sortByAlpha) | ||
) | ||
// Finally, return the array in the form it was given to us | ||
.map(color => color.authored) | ||
) | ||
} | ||
module.exports = colors => colors.sort(sortFn) | ||
module.exports.sortFn = sortFn | ||
module.exports.normalizeColor = normalizeColor |
{ | ||
"name": "color-sorter", | ||
"version": "2.0.0", | ||
"version": "2.1.0", | ||
"description": "Sort colors by hue, then saturation.", | ||
"main": "color-sorter.js", | ||
"scripts": { | ||
"test": "xo && ava" | ||
"test": "xo && ava", | ||
"test:watch": "ava --watch" | ||
}, | ||
@@ -9,0 +10,0 @@ "repository": { |
@@ -1,2 +0,2 @@ | ||
# color-sorter | ||
# color-sorter [![Build Status](https://travis-ci.org/bartveneman/color-sorter.svg?branch=master)](https://travis-ci.org/bartveneman/color-sorter) [![Known Vulnerabilities](https://snyk.io/test/github/bartveneman/color-sorter/badge.svg)](https://snyk.io/test/github/bartveneman/color-sorter) ![Dependencies Status](https://img.shields.io/david/bartveneman/color-sorter.svg) ![Dependencies Status](https://img.shields.io/david/dev/bartveneman/color-sorter.svg) | ||
@@ -10,5 +10,4 @@ Sort CSS colors by hue, then by saturation. Black-grey-white colors (colors with 0% saturation) are shifted to the end. | ||
```js | ||
const sortColors = require('color-sorter'); | ||
const colors = [ | ||
var sortColors = require('color-sorter'); | ||
var colors = [ | ||
'#000', | ||
@@ -19,4 +18,8 @@ 'red', | ||
const sorted = sortColors(colors); | ||
// Method 1: wrap array in a sort function | ||
var sorted = sortColors(colors); | ||
// Method 2: use Array.sort with a sort function | ||
var sorted = colors.sort(sortColors.sortFn) | ||
// => sorted: | ||
@@ -23,0 +26,0 @@ // [ |
106
test.js
const test = require('ava') | ||
const colorSort = require('./color-sorter.js') | ||
test('It exposes an composition api', t => { | ||
t.is(typeof colorSort, 'function') | ||
}) | ||
test('It exposes a sortFn', t => { | ||
t.is(typeof colorSort.sortFn, 'function') | ||
}) | ||
test('It exposes a normalizeColor method', t => { | ||
t.is(typeof colorSort.normalizeColor, 'function') | ||
}) | ||
test('sortFn takes two parameters and sorts using Array.sort()', t => { | ||
const colors = [ | ||
'red', | ||
'blue', | ||
'yellow', | ||
'purple', | ||
'green' | ||
] | ||
const expected = [ | ||
'red', | ||
'yellow', | ||
'green', | ||
'blue', | ||
'purple' | ||
] | ||
const actual = colors.sort(colorSort.sortFn) | ||
t.deepEqual(actual, expected) | ||
}) | ||
test('Colors are sorted by Hue', t => { | ||
@@ -26,10 +58,10 @@ const colors = [ | ||
const colors = [ | ||
'hsl(60, 100%, 50%)', | ||
'hsl(60, 50%, 50%)', | ||
'red' | ||
'hsl(0, 50%, 50%)', | ||
'hsl(0, 100%, 50%)', | ||
'hsl(0, 75%, 50%)' | ||
] | ||
const expected = [ | ||
'red', | ||
'hsl(60, 100%, 50%)', | ||
'hsl(60, 50%, 50%)' | ||
'hsl(0, 50%, 50%)', | ||
'hsl(0, 75%, 50%)', | ||
'hsl(0, 100%, 50%)' | ||
] | ||
@@ -46,3 +78,4 @@ const actual = colorSort(colors) | ||
'black', | ||
'red' | ||
'red', | ||
'whitesmoke' | ||
] | ||
@@ -53,2 +86,3 @@ const expected = [ | ||
'white', | ||
'whitesmoke', | ||
'black' | ||
@@ -63,14 +97,12 @@ ] | ||
const colors = [ | ||
'white', | ||
'red', | ||
'black', | ||
'grey', | ||
'whitesmoke' | ||
'hsl(0, 0%, 100%)', | ||
'hsl(0, 0%, 0%)', | ||
'hsl(0, 0%, 25%)', | ||
'hsl(0, 0%, 50%)' | ||
] | ||
const expected = [ | ||
'red', | ||
'white', | ||
'whitesmoke', | ||
'grey', | ||
'black' | ||
'hsl(0, 0%, 100%)', | ||
'hsl(0, 0%, 50%)', | ||
'hsl(0, 0%, 25%)', | ||
'hsl(0, 0%, 0%)' | ||
] | ||
@@ -82,17 +114,37 @@ const actual = colorSort(colors) | ||
test('Grey-ish colors are sorted by Lightness, then by Alpha', t => { | ||
test('Grey-ish colors with matching lightness are sorted by alpha', t => { | ||
const colors = [ | ||
'rgb(160, 160, 160)', | ||
'rgba(0, 0, 0, 0.33)', | ||
'rgb(0, 0, 0)', | ||
'rgba(0, 0, 0, 0.5)', | ||
'rgba(160, 160, 160, 0.5)' | ||
'hsla(0, 0%, 0%, 0.3)', | ||
'hsla(0, 0%, 0%, 0.5)', | ||
'hsla(0, 0%, 0%, 1.0)', | ||
'hsla(0, 0%, 0%, 0.1)', | ||
'hsla(0, 0%, 0%, 0.2)' | ||
] | ||
const expected = [ | ||
'rgb(160, 160, 160)', | ||
'hsla(0, 0%, 0%, 1.0)', | ||
'hsla(0, 0%, 0%, 0.5)', | ||
'hsla(0, 0%, 0%, 0.3)', | ||
'hsla(0, 0%, 0%, 0.2)', | ||
'hsla(0, 0%, 0%, 0.1)' | ||
] | ||
const actual = colorSort(colors) | ||
t.deepEqual(actual, expected) | ||
}) | ||
test('Grey-ish colors with matching lightness and alpha are sorted by string length and alphabet', t => { | ||
const colors = [ | ||
'hsl(0,0%,0%)', | ||
'rgb(0, 0, 0)', | ||
'rgba(160, 160, 160, 0.5)', | ||
'rgba(0, 0, 0, 0.5)', | ||
'rgba(0, 0, 0, 0.33)' | ||
'black', | ||
'#000', | ||
'#000000' | ||
] | ||
const expected = [ | ||
'#000', | ||
'black', | ||
'#000000', | ||
'hsl(0,0%,0%)', | ||
'rgb(0, 0, 0)' | ||
] | ||
const actual = colorSort(colors) | ||
@@ -99,0 +151,0 @@ |
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
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
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
13153
11
168
53
1