diff --git a/README.md b/README.md index 27aebcf..5a492b0 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,11 @@ const invert = require('invert-color'); - **`color`** : `String|Array|Object` Color in HEX string, RGB array or RGB object to be inverted. -- **`bw`** : `Boolean` -Optional. A boolean value indicating whether the output should be amplified to black (`#000000`) or white (`#ffffff`), according to the luminance of the original color. +- **`bw`** : `Boolean|Object` +Optional. A boolean value indicating whether the output should be amplified to black (`#000000`) or white (`#ffffff`), according to the luminance of the original color. +When it's an object, it should be shaped like `{ black: String?, white: String? }`, +where `black` and `white` are expressed as HEX strings and will be used as target +amplified values. When any of them is missing, the default black/white will be assumed. ```js @@ -36,6 +39,9 @@ invert('#282b35') // —> #d7d4ca // amplify to black or white invert('#282b35', true) // —> #ffffff +// amplify to custom black or white color +invert('#282b35', { black: '#3a3a3a', white: '#fafafa' }) // —> #fafafa + // input color as RGB array or object invert([69, 191, 189]) // —> #ba4042 invert({ r: 249, g: 119, b: 121 }) // —> #068886 @@ -59,6 +65,30 @@ invert.asRgbObject('#fff') // —> { r: 0, g: 0, b: 0 } This is useful in case, you need to create contrast (i.e. background vs foreground, for better readability). The animation at the top is a demonstration. +## Contributing + +Clone original project (or fork and clone that): + +```sh +git clone https://github.com/onury/invert-color.git +``` + +Install dependencies: + +```sh +npm install +``` + +There's nothing to build. Run tests: + +```sh +npm test +``` + +Add (failing) tests into [test/unit.spec.js](test/unit.spec.js) file. +Add implementation. +Pass tests. +Refactor and repeat. ## License diff --git a/index.js b/index.js index 7c985b2..4832fc8 100644 --- a/index.js +++ b/index.js @@ -43,26 +43,33 @@ function getLuminance(c) { return 0.2126 * a[0] + 0.7152 * a[1] + 0.0722 * a[2]; } -function invertToBW(color, asArr) { +function invertToBW(color, bw, asArr) { + const defaultColors = { + black: '#000000', + white: '#ffffff', + }; + const bwColors = (bw === true) + ? defaultColors + : Object.assign({}, defaultColors, bw); return getLuminance(color) > BW_TRESHOLD - ? (asArr ? [0, 0, 0] : '#000000') - : (asArr ? [255, 255, 255] : '#ffffff'); + ? (asArr ? hexToRGB(bwColors.black) : bwColors.black) + : (asArr ? hexToRGB(bwColors.white) : bwColors.white); } function invert(color, bw) { color = toRGB(color); - if (bw) return invertToBW(color); + if (bw) return invertToBW(color, bw); return '#' + color.map(c => padz((255 - c).toString(16))).join(''); } invert.asRgbArray = (color, bw) => { color = toRGB(color); - return bw ? invertToBW(color, true) : color.map(c => 255 - c); + return bw ? invertToBW(color, bw, true) : color.map(c => 255 - c); }; invert.asRgbObject = (color, bw) => { color = toRGB(color); - return toObj(bw ? invertToBW(color, true) : color.map(c => 255 - c)); + return toObj(bw ? invertToBW(color, bw, true) : color.map(c => 255 - c)); }; diff --git a/test/unit.spec.js b/test/unit.spec.js index 2f59c5e..6b98581 100644 --- a/test/unit.spec.js +++ b/test/unit.spec.js @@ -11,6 +11,16 @@ describe('test: invert-color', () => { const A_WHITE = [255, 255, 255]; const O_BLACK = { r: 0, g: 0, b: 0 }; const O_WHITE = { r: 255, g: 255, b: 255 }; + const CUSTOM_BLACK = '#303030'; + const CUSTOM_WHITE = '#fafafa'; + const A_CUSTOM_BLACK = [48, 48, 48]; + const O_CUSTOM_BLACK = { r: 48, g: 48, b: 48 }; + const A_CUSTOM_WHITE = [250, 250, 250]; + const O_CUSTOM_WHITE = { r: 250, g: 250, b: 250 }; + const CUSTOM_BW_COLORS = { + black: CUSTOM_BLACK, + white: CUSTOM_WHITE, + }; it('should invert & match photoshop inverted colors', () => { // ORIGINAL PHOTOSHOP @@ -102,6 +112,27 @@ describe('test: invert-color', () => { expect(invert('#fff', true)).toEqual('#000000'); }); + it('should invert to custom black and white colors', () => { + expect(invert('#631746', CUSTOM_BW_COLORS)).toEqual(CUSTOM_WHITE); + expect(invert('#655c42', CUSTOM_BW_COLORS)).toEqual(CUSTOM_WHITE); + expect(invert('#166528', CUSTOM_BW_COLORS)).toEqual(CUSTOM_WHITE); + expect(invert('#4c2946', CUSTOM_BW_COLORS)).toEqual(CUSTOM_WHITE); + expect(invert('#002d26', CUSTOM_BW_COLORS)).toEqual(CUSTOM_WHITE); + expect(invert('#e71398', CUSTOM_BW_COLORS)).toEqual(CUSTOM_BLACK); + expect(invert('#3ab3af', CUSTOM_BW_COLORS)).toEqual(CUSTOM_BLACK); + expect(invert('#76ff98', CUSTOM_BW_COLORS)).toEqual(CUSTOM_BLACK); + expect(invert('#bbb962', CUSTOM_BW_COLORS)).toEqual(CUSTOM_BLACK); + expect(invert('#52838b', CUSTOM_BW_COLORS)).toEqual(CUSTOM_BLACK); + expect(invert('#000', CUSTOM_BW_COLORS)).toEqual(CUSTOM_WHITE); + expect(invert('#fff', CUSTOM_BW_COLORS)).toEqual(CUSTOM_BLACK); + }); + + it('should support true/false/object for black and white parameter', () => { + expect(invert('#201395', true)).toEqual('#ffffff'); + expect(invert('#201395', false)).toEqual('#dfec6a'); + expect(invert('#201395', CUSTOM_BW_COLORS)).toEqual(CUSTOM_WHITE); + }); + it('should invert to/from array/object to B/W', () => { // this test also checks for object mutation @@ -128,6 +159,32 @@ describe('test: invert-color', () => { expect(invert.asRgbObject(O_WHITE, true)).toEqual(O_BLACK); }); + it('should invert to/from array/object to custom B/W', () => { + // this test also checks for object mutation + + // hex as array + expect(invert.asRgbArray('#631746', CUSTOM_BW_COLORS)).toEqual(A_CUSTOM_WHITE); + expect(invert.asRgbArray('#655c42', CUSTOM_BW_COLORS)).toEqual(A_CUSTOM_WHITE); + expect(invert.asRgbArray('#e71398', CUSTOM_BW_COLORS)).toEqual(A_CUSTOM_BLACK); + + // hex as object + expect(invert.asRgbObject('#4c2946', CUSTOM_BW_COLORS)).toEqual(O_CUSTOM_WHITE); + expect(invert.asRgbObject('#002d26', CUSTOM_BW_COLORS)).toEqual(O_CUSTOM_WHITE); + expect(invert.asRgbObject('#76ff98', CUSTOM_BW_COLORS)).toEqual(O_CUSTOM_BLACK); + + // array as array + expect(invert.asRgbArray(A_WHITE, CUSTOM_BW_COLORS)).toEqual(A_CUSTOM_BLACK); + expect(invert.asRgbArray(A_BLACK, CUSTOM_BW_COLORS)).toEqual(A_CUSTOM_WHITE); + + // object as array + expect(invert.asRgbArray(O_BLACK, CUSTOM_BW_COLORS)).toEqual(A_CUSTOM_WHITE); + expect(invert.asRgbArray(O_WHITE, CUSTOM_BW_COLORS)).toEqual(A_CUSTOM_BLACK); + + // object as object + expect(invert.asRgbObject(O_BLACK, CUSTOM_BW_COLORS)).toEqual(O_CUSTOM_WHITE); + expect(invert.asRgbObject(O_WHITE, CUSTOM_BW_COLORS)).toEqual(O_CUSTOM_BLACK); + }); + it('should modulo exceeding RGB comps', () => { expect(invert([300, 300, 300])).toEqual('#2d2d2d'); expect(invert({ r: -46, g: -46, b: -46 })).toEqual('#2d2d2d');