diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2494eb2..6e98150 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,13 +10,12 @@ jobs: fail-fast: false matrix: node-version: - - 17 - - 16 - - 14 - - 12 + - 22 + - 20 + - 18 steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - run: npm install diff --git a/.npmrc b/.npmrc index 07cae4a..43c97e7 100644 --- a/.npmrc +++ b/.npmrc @@ -1,3 +1 @@ -save-exact = true -package-lock = false -update-notifier = false +package-lock=false diff --git a/README.md b/README.md index e58670c..9651e4e 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,8 @@ ## Install -With [npm](http://npmjs.org/): - -```console -$ npm install color-string +```sh +npm install color-string ``` ## Usage @@ -44,19 +42,18 @@ colorString.get.rgb('invalid color string') // null ### Generation ```js -colorString.to.hex([255, 255, 255]) // "#FFFFFF" -colorString.to.hex([0, 0, 255, 0.4]) // "#0000FF66" -colorString.to.hex([0, 0, 255], 0.4) // "#0000FF66" -colorString.to.rgb([255, 255, 255]) // "rgb(255, 255, 255)" -colorString.to.rgb([0, 0, 255, 0.4]) // "rgba(0, 0, 255, 0.4)" -colorString.to.rgb([0, 0, 255], 0.4) // "rgba(0, 0, 255, 0.4)" -colorString.to.rgb.percent([0, 0, 255]) // "rgb(0%, 0%, 100%)" -colorString.to.keyword([255, 255, 0]) // "yellow" -colorString.to.hsl([360, 100, 100]) // "hsl(360, 100%, 100%)" -colorString.to.hwb([50, 3, 15]) // "hwb(50, 3%, 15%)" - -// all functions also support swizzling -colorString.to.rgb(0, [0, 255], 0.4) // "rgba(0, 0, 255, 0.4)" -colorString.to.rgb([0, 0], [255], 0.4) // "rgba(0, 0, 255, 0.4)" -colorString.to.rgb([0], 0, [255, 0.4]) // "rgba(0, 0, 255, 0.4)" +colorString.to.hex(255, 255, 255) // "#FFFFFF" +colorString.to.hex(0, 0, 255, 0.4) // "#0000FF66" +colorString.to.hex(0, 0, 255, 0.4) // "#0000FF66" +colorString.to.rgb(255, 255, 255) // "rgb(255, 255, 255)" +colorString.to.rgb(0, 0, 255, 0.4) // "rgba(0, 0, 255, 0.4)" +colorString.to.rgb(0, 0, 255, 0.4) // "rgba(0, 0, 255, 0.4)" +colorString.to.rgb.percent(0, 0, 255) // "rgb(0%, 0%, 100%)" +colorString.to.keyword(255, 255, 0) // "yellow" +colorString.to.hsl(360, 100, 100) // "hsl(360, 100%, 100%)" +colorString.to.hwb(50, 3, 15) // "hwb(50, 3%, 15%)" ``` + +## License + +MIT diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..d7490a8 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,23 @@ +export type Model = 'rgb' | 'hsl' | 'hwb'; + +export type ColorString = { + get: { + (color: string): {model: Model; value: number[]} | undefined; + rgb: (color: string) => number[] | undefined; + hsl: (color: string) => number[] | undefined; + hwb: (color: string) => number[] | undefined; + }; + to: { + hex: (r: number, g: number, b: number, a?: number) => string | undefined; + rgb: { + (r: number, g: number, b: number, a?: number): string | undefined; + percent: (r: number, g: number, b: number, a?: number) => string | undefined; + }; + keyword: (r: number, g: number, b: number, a?: number) => string | undefined; + hsl: (h: number, s: number, l: number, a?: number) => string | undefined; + hwb: (h: number, w: number, b: number, a?: number) => string | undefined; + }; +}; + +declare const colorString: ColorString; +export default colorString; diff --git a/index.js b/index.js index dd5d2b7..f175c23 100644 --- a/index.js +++ b/index.js @@ -1,46 +1,48 @@ -/* MIT license */ -var colorNames = require('color-name'); -var swizzle = require('simple-swizzle'); -var hasOwnProperty = Object.hasOwnProperty; +import colorNames from 'color-name'; -var reverseNames = Object.create(null); +const reverseNames = Object.create(null); -// create a list of reverse color names -for (var name in colorNames) { - if (hasOwnProperty.call(colorNames, name)) { +// Create a list of reverse color names +for (const name in colorNames) { + if (Object.hasOwn(colorNames, name)) { reverseNames[colorNames[name]] = name; } } -var cs = module.exports = { +const cs = { to: {}, - get: {} + get: {}, }; cs.get = function (string) { - var prefix = string.substring(0, 3).toLowerCase(); - var val; - var model; + const prefix = string.slice(0, 3).toLowerCase(); + let value; + let model; switch (prefix) { - case 'hsl': - val = cs.get.hsl(string); + case 'hsl': { + value = cs.get.hsl(string); model = 'hsl'; break; - case 'hwb': - val = cs.get.hwb(string); + } + + case 'hwb': { + value = cs.get.hwb(string); model = 'hwb'; break; - default: - val = cs.get.rgb(string); + } + + default: { + value = cs.get.rgb(string); model = 'rgb'; break; + } } - if (!val) { + if (!value) { return null; } - return {model: model, value: val}; + return {model, value}; }; cs.get.rgb = function (string) { @@ -48,16 +50,16 @@ cs.get.rgb = function (string) { return null; } - var abbr = /^#([a-f0-9]{3,4})$/i; - var hex = /^#([a-f0-9]{6})([a-f0-9]{2})?$/i; - var rgba = /^rgba?\(\s*([+-]?\d+)(?=[\s,])\s*(?:,\s*)?([+-]?\d+)(?=[\s,])\s*(?:,\s*)?([+-]?\d+)\s*(?:[,|\/]\s*([+-]?[\d\.]+)(%?)\s*)?\)$/; - var per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,?\s*([+-]?[\d\.]+)\%\s*,?\s*([+-]?[\d\.]+)\%\s*(?:[,|\/]\s*([+-]?[\d\.]+)(%?)\s*)?\)$/; - var keyword = /^(\w+)$/; + const abbr = /^#([a-f\d]{3,4})$/i; + const hex = /^#([a-f\d]{6})([a-f\d]{2})?$/i; + const rgba = /^rgba?\(\s*([+-]?\d+)(?=[\s,])\s*(?:,\s*)?([+-]?\d+)(?=[\s,])\s*(?:,\s*)?([+-]?\d+)\s*(?:[,|/]\s*([+-]?[\d.]+)(%?)\s*)?\)$/; + const per = /^rgba?\(\s*([+-]?[\d.]+)%\s*,?\s*([+-]?[\d.]+)%\s*,?\s*([+-]?[\d.]+)%\s*(?:[,|/]\s*([+-]?[\d.]+)(%?)\s*)?\)$/; + const keyword = /^(\w+)$/; - var rgb = [0, 0, 0, 1]; - var match; - var i; - var hexAlpha; + let rgb = [0, 0, 0, 1]; + let match; + let i; + let hexAlpha; if (match = string.match(hex)) { hexAlpha = match[2]; @@ -65,54 +67,46 @@ cs.get.rgb = function (string) { for (i = 0; i < 3; i++) { // https://jsperf.com/slice-vs-substr-vs-substring-methods-long-string/19 - var i2 = i * 2; - rgb[i] = parseInt(match.slice(i2, i2 + 2), 16); + const i2 = i * 2; + rgb[i] = Number.parseInt(match.slice(i2, i2 + 2), 16); } if (hexAlpha) { - rgb[3] = parseInt(hexAlpha, 16) / 255; + rgb[3] = Number.parseInt(hexAlpha, 16) / 255; } } else if (match = string.match(abbr)) { match = match[1]; hexAlpha = match[3]; for (i = 0; i < 3; i++) { - rgb[i] = parseInt(match[i] + match[i], 16); + rgb[i] = Number.parseInt(match[i] + match[i], 16); } if (hexAlpha) { - rgb[3] = parseInt(hexAlpha + hexAlpha, 16) / 255; + rgb[3] = Number.parseInt(hexAlpha + hexAlpha, 16) / 255; } } else if (match = string.match(rgba)) { for (i = 0; i < 3; i++) { - rgb[i] = parseInt(match[i + 1], 0); + rgb[i] = Number.parseInt(match[i + 1], 10); } if (match[4]) { - if (match[5]) { - rgb[3] = parseFloat(match[4]) * 0.01; - } else { - rgb[3] = parseFloat(match[4]); - } + rgb[3] = match[5] ? Number.parseFloat(match[4]) * 0.01 : Number.parseFloat(match[4]); } } else if (match = string.match(per)) { for (i = 0; i < 3; i++) { - rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55); + rgb[i] = Math.round(Number.parseFloat(match[i + 1]) * 2.55); } if (match[4]) { - if (match[5]) { - rgb[3] = parseFloat(match[4]) * 0.01; - } else { - rgb[3] = parseFloat(match[4]); - } + rgb[3] = match[5] ? Number.parseFloat(match[4]) * 0.01 : Number.parseFloat(match[4]); } } else if (match = string.match(keyword)) { if (match[1] === 'transparent') { return [0, 0, 0, 0]; } - if (!hasOwnProperty.call(colorNames, match[1])) { + if (!Object.hasOwn(colorNames, match[1])) { return null; } @@ -127,6 +121,7 @@ cs.get.rgb = function (string) { for (i = 0; i < 3; i++) { rgb[i] = clamp(rgb[i], 0, 255); } + rgb[3] = clamp(rgb[3], 0, 1); return rgb; @@ -137,15 +132,15 @@ cs.get.hsl = function (string) { return null; } - var hsl = /^hsla?\(\s*([+-]?(?:\d{0,3}\.)?\d+)(?:deg)?\s*,?\s*([+-]?[\d\.]+)%\s*,?\s*([+-]?[\d\.]+)%\s*(?:[,|\/]\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/; - var match = string.match(hsl); + const hsl = /^hsla?\(\s*([+-]?(?:\d{0,3}\.)?\d+)(?:deg)?\s*,?\s*([+-]?[\d.]+)%\s*,?\s*([+-]?[\d.]+)%\s*(?:[,|/]\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/; + const match = string.match(hsl); if (match) { - var alpha = parseFloat(match[4]); - var h = ((parseFloat(match[1]) % 360) + 360) % 360; - var s = clamp(parseFloat(match[2]), 0, 100); - var l = clamp(parseFloat(match[3]), 0, 100); - var a = clamp(isNaN(alpha) ? 1 : alpha, 0, 1); + const alpha = Number.parseFloat(match[4]); + const h = ((Number.parseFloat(match[1]) % 360) + 360) % 360; + const s = clamp(Number.parseFloat(match[2]), 0, 100); + const l = clamp(Number.parseFloat(match[3]), 0, 100); + const a = clamp(Number.isNaN(alpha) ? 1 : alpha, 0, 1); return [h, s, l, a]; } @@ -158,24 +153,22 @@ cs.get.hwb = function (string) { return null; } - var hwb = /^hwb\(\s*([+-]?\d{0,3}(?:\.\d+)?)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/; - var match = string.match(hwb); + const hwb = /^hwb\(\s*([+-]?\d{0,3}(?:\.\d+)?)(?:deg)?\s*,\s*([+-]?[\d.]+)%\s*,\s*([+-]?[\d.]+)%\s*(?:,\s*([+-]?(?=\.\d|\d)(?:0|[1-9]\d*)?(?:\.\d*)?(?:[eE][+-]?\d+)?)\s*)?\)$/; + const match = string.match(hwb); if (match) { - var alpha = parseFloat(match[4]); - var h = ((parseFloat(match[1]) % 360) + 360) % 360; - var w = clamp(parseFloat(match[2]), 0, 100); - var b = clamp(parseFloat(match[3]), 0, 100); - var a = clamp(isNaN(alpha) ? 1 : alpha, 0, 1); + const alpha = Number.parseFloat(match[4]); + const h = ((Number.parseFloat(match[1]) % 360) + 360) % 360; + const w = clamp(Number.parseFloat(match[2]), 0, 100); + const b = clamp(Number.parseFloat(match[3]), 0, 100); + const a = clamp(Number.isNaN(alpha) ? 1 : alpha, 0, 1); return [h, w, b, a]; } return null; }; -cs.to.hex = function () { - var rgba = swizzle(arguments); - +cs.to.hex = function (...rgba) { return ( '#' + hexDouble(rgba[0]) + @@ -187,39 +180,32 @@ cs.to.hex = function () { ); }; -cs.to.rgb = function () { - var rgba = swizzle(arguments); - +cs.to.rgb = function (...rgba) { return rgba.length < 4 || rgba[3] === 1 ? 'rgb(' + Math.round(rgba[0]) + ', ' + Math.round(rgba[1]) + ', ' + Math.round(rgba[2]) + ')' : 'rgba(' + Math.round(rgba[0]) + ', ' + Math.round(rgba[1]) + ', ' + Math.round(rgba[2]) + ', ' + rgba[3] + ')'; }; -cs.to.rgb.percent = function () { - var rgba = swizzle(arguments); - - var r = Math.round(rgba[0] / 255 * 100); - var g = Math.round(rgba[1] / 255 * 100); - var b = Math.round(rgba[2] / 255 * 100); +cs.to.rgb.percent = function (...rgba) { + const r = Math.round(rgba[0] / 255 * 100); + const g = Math.round(rgba[1] / 255 * 100); + const b = Math.round(rgba[2] / 255 * 100); return rgba.length < 4 || rgba[3] === 1 ? 'rgb(' + r + '%, ' + g + '%, ' + b + '%)' : 'rgba(' + r + '%, ' + g + '%, ' + b + '%, ' + rgba[3] + ')'; }; -cs.to.hsl = function () { - var hsla = swizzle(arguments); +cs.to.hsl = function (...hsla) { return hsla.length < 4 || hsla[3] === 1 ? 'hsl(' + hsla[0] + ', ' + hsla[1] + '%, ' + hsla[2] + '%)' : 'hsla(' + hsla[0] + ', ' + hsla[1] + '%, ' + hsla[2] + '%, ' + hsla[3] + ')'; }; -// hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax +// Hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax // (hwb have alpha optional & 1 is default value) -cs.to.hwb = function () { - var hwba = swizzle(arguments); - - var a = ''; +cs.to.hwb = function (...hwba) { + let a = ''; if (hwba.length >= 4 && hwba[3] !== 1) { a = ', ' + hwba[3]; } @@ -227,16 +213,18 @@ cs.to.hwb = function () { return 'hwb(' + hwba[0] + ', ' + hwba[1] + '%, ' + hwba[2] + '%' + a + ')'; }; -cs.to.keyword = function (rgb) { +cs.to.keyword = function (...rgb) { return reverseNames[rgb.slice(0, 3)]; }; -// helpers -function clamp(num, min, max) { - return Math.min(Math.max(min, num), max); +// Helpers +function clamp(number_, min, max) { + return Math.min(Math.max(min, number_), max); } -function hexDouble(num) { - var str = Math.round(num).toString(16).toUpperCase(); - return (str.length < 2) ? '0' + str : str; +function hexDouble(number_) { + const string_ = Math.round(number_).toString(16).toUpperCase(); + return (string_.length < 2) ? '0' + string_ : string_; } + +export default cs; diff --git a/index.test-d.ts b/index.test-d.ts new file mode 100644 index 0000000..7347147 --- /dev/null +++ b/index.test-d.ts @@ -0,0 +1,44 @@ +import {expectType} from 'tsd'; +import colorString, {type Model} from './index.js'; + +type GetColorResult = {model: Model; value: number[]} | undefined; +type GetSpecificTypeResult = number[] | undefined; + +type ToColorResult = string | undefined; + +expectType(colorString.get('#FFF')); +expectType(colorString.get('#FFFA')); +expectType(colorString.get('hsl(360, 100%, 50%)')); +expectType(colorString.get('hsl(360 100% 50%)')); +expectType(colorString.get('hwb(60, 3%, 60%)')); + +expectType(colorString.get.rgb('#FFF')); +expectType(colorString.get.rgb('blue')); +expectType(colorString.get.rgb('#FFF')); +expectType(colorString.get.rgb('blue')); +expectType(colorString.get.rgb('rgba(200, 60, 60, 0.3)')); +expectType(colorString.get.rgb('rgba(200 60 60 / 0.3)')); +expectType(colorString.get.rgb('rgba(200 60 60 / 30%)')); +expectType(colorString.get.rgb('rgb(200, 200, 200)')); +expectType(colorString.get.rgb('rgb(200 200 200)')); + +expectType(colorString.get.hsl('hsl(360, 100%, 50%)')); +expectType(colorString.get.hsl('hsl(360 100% 50%)')); +expectType(colorString.get.hsl('hsla(360, 60%, 50%, 0.4)')); +expectType(colorString.get.hsl('hsl(360 60% 50% / 0.4)')); + +expectType(colorString.get.hwb('hwb(60, 3%, 60%)')); +expectType(colorString.get.hwb('hwb(60, 3%, 60%, 0.6)')); + +expectType(colorString.get.rgb('invalid color string')); + +expectType(colorString.to.hex(255, 255, 255)); +expectType(colorString.to.hex(0, 0, 255, 0.4)); +expectType(colorString.to.hex(0, 0, 255, 0.4)); +expectType(colorString.to.rgb(255, 255, 255)); +expectType(colorString.to.rgb(0, 0, 255, 0.4)); +expectType(colorString.to.rgb(0, 0, 255, 0.4)); +expectType(colorString.to.rgb.percent(0, 0, 255)); +expectType(colorString.to.keyword(255, 255, 0)); +expectType(colorString.to.hsl(360, 100, 100)); +expectType(colorString.to.hwb(50, 3, 15)); diff --git a/package.json b/package.json index f34ee98..5d7164c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "color-string", "description": "Parser and generator for CSS color strings", - "version": "1.9.1", + "version": "2.0.0", "author": "Heather Arthur ", "contributors": [ "Maxime Thirouin", @@ -9,13 +9,19 @@ "Josh Junon" ], "repository": "Qix-/color-string", + "type": "module", + "exports": "./index.js", + "types": "./index.d.ts", + "engines": { + "node": ">=18" + }, "scripts": { - "pretest": "xo", - "test": "node test/basic.js" + "test": "xo && tsd && node test.js" }, "license": "MIT", "files": [ - "index.js" + "index.js", + "index.d.ts" ], "xo": { "rules": { @@ -24,11 +30,11 @@ } }, "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" + "color-name": "^2.0.0" }, "devDependencies": { - "xo": "^0.12.1" + "tsd": "^0.31.2", + "xo": "^0.60.0" }, "keywords": [ "color", diff --git a/test/basic.js b/test.js similarity index 80% rename from test/basic.js rename to test.js index db4cbe4..e7f6cc6 100644 --- a/test/basic.js +++ b/test.js @@ -1,13 +1,14 @@ -var assert = require('assert'); -var string = require('../'); - -function normalizeAlpha(res) { - if (res.model === 'rgb' && res.value.length >= 4) { - res.value[3] = res.value[3].toFixed(2); - } else if (res.length >= 4) { - res[3] = res[3].toFixed(2); +import assert from 'node:assert'; +import string from './index.js'; + +function normalizeAlpha(result) { + if (result.model === 'rgb' && result.value.length >= 4) { + result.value[3] = result.value[3].toFixed(2); + } else if (result.length >= 4) { + result[3] = result[3].toFixed(2); } - return res; + + return result; } assert.deepEqual(string.get.rgb('#fef'), [255, 238, 255, 1]); @@ -24,7 +25,8 @@ assert.deepEqual(string.get.hsl('hsl(240deg 100% 50.5%)'), [240, 100, 50.5, 1]); assert.deepEqual(string.get.hwb('hwb(240, 100%, 50.5%)'), [240, 100, 50.5, 1]); assert.deepEqual(string.get.hwb('hwb(240deg, 100%, 50.5%)'), [240, 100, 50.5, 1]); -// generic .get() +// Generic .get() +assert.deepEqual(string.get('invalid'), null); assert.deepEqual(string.get('#fef'), {model: 'rgb', value: [255, 238, 255, 1]}); assert.deepEqual(string.get('#fffFEF'), {model: 'rgb', value: [255, 255, 239, 1]}); assert.deepEqual(string.get('#fffFEFff'), {model: 'rgb', value: [255, 255, 239, 1]}); @@ -43,7 +45,7 @@ assert.deepEqual(string.get('hsl(240deg 100% 50.5%)'), {model: 'hsl', value: [24 assert.deepEqual(string.get('hwb(240, 100%, 50.5%)'), {model: 'hwb', value: [240, 100, 50.5, 1]}); assert.deepEqual(string.get('hwb(240deg, 100%, 50.5%)'), {model: 'hwb', value: [240, 100, 50.5, 1]}); -// invalid generic .get() calls +// Invalid generic .get() calls assert.deepEqual(string.get('hsla(250, 100%, 50%, 50%)'), null); assert.deepEqual(string.get('hsl(250 100% 50% / 50%)'), null); assert.deepEqual(string.get('rgba(250, 100%, 50%, 50%)'), null); @@ -64,7 +66,7 @@ assert.strictEqual(string.get('rgb(10%, 2%, 2348723dskjfs%)'), null); assert.strictEqual(string.get('rgb(10$,3)'), null); assert.strictEqual(string.get('rgba(10, 3)'), null); -// with sign +// With sign assert.deepEqual(string.get.rgb('rgb(-244, +233, -100)'), [0, 233, 0, 1]); assert.deepEqual(string.get.rgb('rgb(-244 +233 -100)'), [0, 233, 0, 1]); assert.deepEqual(string.get.hsl('hsl(+240, 100%, 50.5%)'), [240, 100, 50.5, 1]); @@ -100,11 +102,11 @@ assert.deepEqual(string.get.hwb('hwb(10.0deg, 100%, 50.5%)'), [10, 100, 50.5, 1] assert.deepEqual(string.get.hwb('hwb(-.5, 100%, 50.5%)'), [359.5, 100, 50.5, 1]); assert.deepEqual(string.get.hwb('hwb(-10.0deg, 100%, 50.5%, +0.6)'), [350, 100, 50.5, 0.6]); -// subsequent return values should not change array +// Subsequent return values should not change array assert.deepEqual(string.get.rgb('blue'), [0, 0, 255, 1]); assert.deepEqual(string.get.rgb('blue'), [0, 0, 255, 1]); -// alpha +// Alpha assert.deepEqual(normalizeAlpha(string.get.rgb('#fffa')), [255, 255, 255, '0.67']); assert.deepEqual(string.get.rgb('#c814e933'), [200, 20, 233, 0.2]); assert.deepEqual(string.get.rgb('#c814e900'), [200, 20, 233, 0]); @@ -125,7 +127,7 @@ assert.deepEqual(string.get.hsl('hsl(200 20% 33% / 1e-7)'), [200, 20, 33, 1e-7]) assert.deepEqual(string.get.hwb('hwb(200, 20%, 33%, 0.2)'), [200, 20, 33, 0.2]); assert.deepEqual(string.get.hwb('hwb(200, 20%, 33%, 1e-7)'), [200, 20, 33, 1e-7]); -// no alpha +// No alpha assert.deepEqual(string.get.rgb('#fef'), [255, 238, 255, 1]); assert.deepEqual(string.get.rgb('rgba(200, 20, 233)'), [200, 20, 233, 1]); assert.deepEqual(string.get.rgb('rgba(200 20 233)'), [200, 20, 233, 1]); @@ -138,7 +140,7 @@ assert.deepEqual(string.get.hsl('hsl(0 0% 0% / 0)'), [0, 0, 0, 0]); assert.deepEqual(string.get.hsl('hsl(0deg 0% 0% / 0)'), [0, 0, 0, 0]); assert.deepEqual(string.get.hwb('hwb(400, 10%, 200%, 0)'), [40, 10, 100, 0]); -// range +// Range assert.deepEqual(string.get.rgb('rgba(300, 600, 100, 3)'), [255, 255, 100, 1]); assert.deepEqual(string.get.rgb('rgba(300 600 100 / 3)'), [255, 255, 100, 1]); assert.deepEqual(string.get.rgb('rgba(8000%, 100%, 333%, 88)'), [255, 255, 255, 1]); @@ -147,7 +149,7 @@ assert.deepEqual(string.get.hsl('hsla(400, 10%, 200%, 10)'), [40, 10, 100, 1]); assert.deepEqual(string.get.hsl('hsl(400 10% 200% / 10)'), [40, 10, 100, 1]); assert.deepEqual(string.get.hwb('hwb(400, 10%, 200%, 10)'), [40, 10, 100, 1]); -// invalid +// Invalid assert.strictEqual(string.get.rgb('yellowblue'), null); assert.strictEqual(string.get.rgb('hsl(100, 10%, 10%)'), null); assert.strictEqual(string.get.rgb('hsl(100 10% 10%)'), null); @@ -177,51 +179,30 @@ assert.strictEqual(string.get.hwb('hwb(240, 100%, 0e-'), null); assert.strictEqual(string.get.hwb('hwb(240, 100%, 0e+'), null); assert.strictEqual(string.get.hwb('hwb(240, 100%, +000e33'), null); -// generators -assert.equal(string.to.hex([255, 10, 35]), '#FF0A23'); -assert.equal(string.to.hex([255, 10, 35, 1]), '#FF0A23'); -assert.equal(string.to.hex([255, 10, 35], 1), '#FF0A23'); -assert.equal(string.to.hex([255, 10, 35, 0.3]), '#FF0A234D'); -assert.equal(string.to.hex([255, 10, 35], 0.3), '#FF0A234D'); -assert.equal(string.to.hex([255, 10, 35, 0]), '#FF0A2300'); -assert.equal(string.to.hex([255, 10, 35], 0), '#FF0A2300'); - -assert.equal(string.to.rgb([255, 10, 35]), 'rgb(255, 10, 35)'); -assert.equal(string.to.rgb([255, 10, 35, 0.3]), 'rgba(255, 10, 35, 0.3)'); -assert.equal(string.to.rgb([255, 10, 35], 0.3), 'rgba(255, 10, 35, 0.3)'); -assert.equal(string.to.rgb([255, 10, 35, 0.3]), 'rgba(255, 10, 35, 0.3)'); -assert.equal(string.to.rgb([255, 10, 35], 0.3), 'rgba(255, 10, 35, 0.3)'); -assert.equal(string.to.rgb([255, 10, 35]), 'rgb(255, 10, 35)'); -assert.equal(string.to.rgb([255, 10, 35, 0]), 'rgba(255, 10, 35, 0)'); - -assert.equal(string.to.rgb.percent([255, 10, 35]), 'rgb(100%, 4%, 14%)'); - -assert.equal(string.to.rgb.percent([255, 10, 35, 0.3]), 'rgba(100%, 4%, 14%, 0.3)'); -assert.equal(string.to.rgb.percent([255, 10, 35], 0.3), 'rgba(100%, 4%, 14%, 0.3)'); -assert.equal(string.to.rgb.percent([255, 10, 35, 0.3]), 'rgba(100%, 4%, 14%, 0.3)'); -assert.equal(string.to.rgb.percent([255, 10, 35], 0.3), 'rgba(100%, 4%, 14%, 0.3)'); -assert.equal(string.to.rgb.percent([255, 10, 35]), 'rgb(100%, 4%, 14%)'); - -assert.equal(string.to.hsl([280, 40, 60]), 'hsl(280, 40%, 60%)'); -assert.equal(string.to.hsl([280, 40, 60, 0.3]), 'hsla(280, 40%, 60%, 0.3)'); -assert.equal(string.to.hsl([280, 40, 60], 0.3), 'hsla(280, 40%, 60%, 0.3)'); -assert.equal(string.to.hsl([280, 40, 60, 0.3]), 'hsla(280, 40%, 60%, 0.3)'); -assert.equal(string.to.hsl([280, 40, 60], 0.3), 'hsla(280, 40%, 60%, 0.3)'); -assert.equal(string.to.hsl([280, 40, 60], 0), 'hsla(280, 40%, 60%, 0)'); -assert.equal(string.to.hsl([280, 40, 60]), 'hsl(280, 40%, 60%)'); - -assert.equal(string.to.hwb([280, 40, 60]), 'hwb(280, 40%, 60%)'); -assert.equal(string.to.hwb([280, 40, 60, 0.3]), 'hwb(280, 40%, 60%, 0.3)'); -assert.equal(string.to.hwb([280, 40, 60], 0.3), 'hwb(280, 40%, 60%, 0.3)'); -assert.equal(string.to.hwb([280, 40, 60], 0), 'hwb(280, 40%, 60%, 0)'); - -assert.equal(string.to.keyword([255, 255, 0]), 'yellow'); -assert.equal(string.to.keyword(['constructor']), undefined); -assert.equal(string.to.keyword([100, 255, 0]), undefined); +// Generators +assert.equal(string.to.hex(255, 10, 35), '#FF0A23'); +assert.equal(string.to.hex(255, 10, 35, 1), '#FF0A23'); + +assert.equal(string.to.rgb(255, 10, 35), 'rgb(255, 10, 35)'); +assert.equal(string.to.rgb(255, 10, 35, 0.3), 'rgba(255, 10, 35, 0.3)'); + +assert.equal(string.to.rgb.percent(255, 10, 35), 'rgb(100%, 4%, 14%)'); + +assert.equal(string.to.rgb.percent(255, 10, 35), 'rgb(100%, 4%, 14%)'); +assert.equal(string.to.rgb.percent(255, 10, 35, 0.3), 'rgba(100%, 4%, 14%, 0.3)'); + +assert.equal(string.to.hsl(280, 40, 60), 'hsl(280, 40%, 60%)'); +assert.equal(string.to.hsl(280, 40, 60, 0.3), 'hsla(280, 40%, 60%, 0.3)'); + +assert.equal(string.to.hwb(280, 40, 60), 'hwb(280, 40%, 60%)'); +assert.equal(string.to.hwb(280, 40, 60, 0.3), 'hwb(280, 40%, 60%, 0.3)'); + +assert.equal(string.to.keyword(255, 255, 0), 'yellow'); +assert.equal(string.to.keyword(100, 255, 0), undefined); // Make sure .get() doesn't return object prototype values (regression test, #44) Object.keys(Object.getOwnPropertyDescriptors(Object.prototype)) .map(property => assert.deepStrictEqual([property, string.get(property)], [property, null])); // Make sure writing decimal values as hex doesn't cause bizarre output (regression test, #25) -assert.equal(string.to.hex([44.2, 83.8, 44]), '#2C542C'); +assert.equal(string.to.hex(44.2, 83.8, 44), '#2C542C');