mirror of https://github.com/nextcloud/calendar
chore: vendor closest-css-color and its dependencies
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
This commit is contained in:
parent
38e76af521
commit
5358d5637d
|
@ -32,12 +32,13 @@
|
|||
"@nextcloud/vue": "^7.6.0",
|
||||
"@nextcloud/vue-dashboard": "^2.0.1",
|
||||
"autosize": "^6.0.1",
|
||||
"closest-css-color": "^1.0.0",
|
||||
"color-convert": "^2.0.1",
|
||||
"color-string": "^1.9.1",
|
||||
"core-js": "^3.28.0",
|
||||
"css-color-names": "^1.0.1",
|
||||
"debounce": "^1.2.1",
|
||||
"jstz": "^2.1.1",
|
||||
"lodash": "^4.17.21",
|
||||
"md5": "^2.3.0",
|
||||
"p-limit": "^4.0.0",
|
||||
"v-tooltip": "^2.1.3",
|
||||
|
@ -5844,19 +5845,6 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/closest-css-color": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/closest-css-color/-/closest-css-color-1.0.0.tgz",
|
||||
"integrity": "sha512-tSBfCvnaW4d2gSTg/yKRhZXarp6lDFM0FQthfMWweOiLa2fqVyWJhDO7PXxT7PX//xT+Ci8iPJKaZCIhwGDFHw==",
|
||||
"dependencies": {
|
||||
"colour-proximity": "0.0.2",
|
||||
"css-color-names": "1.0.1",
|
||||
"lodash": "^4.17.21"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/co": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||
|
@ -5890,19 +5878,12 @@
|
|||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"node_modules/color-string": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-string/-/color-string-0.1.3.tgz",
|
||||
"integrity": "sha512-ERkoOp/s/VSrQ5OyH1Gs9LCgFWnTlQXUqAaGNBJzV2gjuunWuxISth8lOaDqfPfDIjiR9MI7WrzH1hDNRVOCfQ==",
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
|
||||
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
|
||||
"dependencies": {
|
||||
"color-convert": "0.2.x"
|
||||
}
|
||||
},
|
||||
"node_modules/color-string/node_modules/color-convert": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.2.1.tgz",
|
||||
"integrity": "sha512-FWbwpCgyRV41Vml0iKU9UmL0dVTKORnm7ZC8h8cdfvutk2bU7ZcMLtSleggScK/IpUVXILg9Pw86LhPUQyTaVg==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
"color-name": "^1.0.0",
|
||||
"simple-swizzle": "^0.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/colord": {
|
||||
|
@ -5919,14 +5900,6 @@
|
|||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/colour-proximity": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/colour-proximity/-/colour-proximity-0.0.2.tgz",
|
||||
"integrity": "sha512-jaV4uLTEreh/6dXr1WW0sC0B9HEdUhho9MbOmgQxDPKR33/FrdAXXC/cgC6k9UdXbT5Dwy8d05z+R9FEo9PVEw==",
|
||||
"dependencies": {
|
||||
"color-string": "~0.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
|
@ -14142,6 +14115,19 @@
|
|||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/simple-swizzle": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
||||
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
|
||||
"dependencies": {
|
||||
"is-arrayish": "^0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/simple-swizzle/node_modules/is-arrayish": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
|
||||
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
|
||||
},
|
||||
"node_modules/sisteransi": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
|
||||
|
@ -21049,16 +21035,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"closest-css-color": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/closest-css-color/-/closest-css-color-1.0.0.tgz",
|
||||
"integrity": "sha512-tSBfCvnaW4d2gSTg/yKRhZXarp6lDFM0FQthfMWweOiLa2fqVyWJhDO7PXxT7PX//xT+Ci8iPJKaZCIhwGDFHw==",
|
||||
"requires": {
|
||||
"colour-proximity": "0.0.2",
|
||||
"css-color-names": "1.0.1",
|
||||
"lodash": "^4.17.21"
|
||||
}
|
||||
},
|
||||
"co": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
|
||||
|
@ -21085,18 +21061,12 @@
|
|||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"color-string": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-string/-/color-string-0.1.3.tgz",
|
||||
"integrity": "sha512-ERkoOp/s/VSrQ5OyH1Gs9LCgFWnTlQXUqAaGNBJzV2gjuunWuxISth8lOaDqfPfDIjiR9MI7WrzH1hDNRVOCfQ==",
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
|
||||
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
|
||||
"requires": {
|
||||
"color-convert": "0.2.x"
|
||||
},
|
||||
"dependencies": {
|
||||
"color-convert": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.2.1.tgz",
|
||||
"integrity": "sha512-FWbwpCgyRV41Vml0iKU9UmL0dVTKORnm7ZC8h8cdfvutk2bU7ZcMLtSleggScK/IpUVXILg9Pw86LhPUQyTaVg=="
|
||||
}
|
||||
"color-name": "^1.0.0",
|
||||
"simple-swizzle": "^0.2.2"
|
||||
}
|
||||
},
|
||||
"colord": {
|
||||
|
@ -21113,14 +21083,6 @@
|
|||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"colour-proximity": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/colour-proximity/-/colour-proximity-0.0.2.tgz",
|
||||
"integrity": "sha512-jaV4uLTEreh/6dXr1WW0sC0B9HEdUhho9MbOmgQxDPKR33/FrdAXXC/cgC6k9UdXbT5Dwy8d05z+R9FEo9PVEw==",
|
||||
"requires": {
|
||||
"color-string": "~0.1.2"
|
||||
}
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
|
@ -27335,6 +27297,21 @@
|
|||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
|
||||
"dev": true
|
||||
},
|
||||
"simple-swizzle": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
||||
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
|
||||
"requires": {
|
||||
"is-arrayish": "^0.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"is-arrayish": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
|
||||
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"sisteransi": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
|
||||
|
|
|
@ -59,12 +59,13 @@
|
|||
"@nextcloud/vue": "^7.6.0",
|
||||
"@nextcloud/vue-dashboard": "^2.0.1",
|
||||
"autosize": "^6.0.1",
|
||||
"closest-css-color": "^1.0.0",
|
||||
"color-convert": "^2.0.1",
|
||||
"color-string": "^1.9.1",
|
||||
"core-js": "^3.28.0",
|
||||
"css-color-names": "^1.0.1",
|
||||
"debounce": "^1.2.1",
|
||||
"jstz": "^2.1.1",
|
||||
"lodash": "^4.17.21",
|
||||
"md5": "^2.3.0",
|
||||
"p-limit": "^4.0.0",
|
||||
"v-tooltip": "^2.1.3",
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/**
|
||||
* @copyright Copyright (c) 2023 Richard Steinmetz <richard@steinmetz.cloud>
|
||||
*
|
||||
* @author Richard Steinmetz <richard@steinmetz.cloud>
|
||||
*
|
||||
* @license AGPL-3.0-or-later
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// Code was taken from:
|
||||
// - https://github.com/juliuste/closest-css-color
|
||||
// - https://github.com/gausie/colour-proximity
|
||||
// - https://github.com/gausie/colour-proximity/pull/3
|
||||
|
||||
import cssColors from 'css-color-names'
|
||||
import sortBy from 'lodash/sortBy.js'
|
||||
import pick from 'lodash/pick.js'
|
||||
import uniqBy from 'lodash/uniqBy.js'
|
||||
import { get } from 'color-string'
|
||||
|
||||
const uniqColorKeys = uniqBy(Object.keys(cssColors), c => cssColors[c])
|
||||
const filteredColors = pick(cssColors, uniqColorKeys)
|
||||
|
||||
const colors = sortBy(
|
||||
Object.keys(filteredColors).map(name => ({
|
||||
name,
|
||||
hex: filteredColors[name],
|
||||
})),
|
||||
c => c.hex,
|
||||
)
|
||||
|
||||
const defaults = {
|
||||
detailed: false,
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the closest CSS color to a given hex color.
|
||||
*
|
||||
* @param {string} hex Hex color string
|
||||
* @param {object} opt Options
|
||||
* @param {boolean=} opt.detailed Return color object instead of just the name
|
||||
* @return {string|{name: string, hex: string}} Closest color name or object
|
||||
*/
|
||||
export default function closestColor(hex, opt = {}) {
|
||||
const options = { ...defaults, ...opt }
|
||||
const sortedColors = sortBy(colors, c => proximity(hex, c.hex))
|
||||
if (options.detailed) {
|
||||
return sortedColors[0]
|
||||
}
|
||||
return sortedColors[0].name
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the proximity between two colors.
|
||||
*
|
||||
* @param {string} s1 Hex color string 1
|
||||
* @param {string} s2 Hex color string 2
|
||||
* @return {number}
|
||||
*/
|
||||
function proximity(s1, s2) {
|
||||
const c1 = rgb2lab(get.rgb(s1))
|
||||
const c2 = rgb2lab(get.rgb(s2))
|
||||
return Math.sqrt(
|
||||
Math.pow(c1[0] - c2[0], 2)
|
||||
+ Math.pow(c1[1] - c2[1], 2)
|
||||
+ Math.pow(c1[2] - c2[2], 2)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number[]} input RGB array
|
||||
*/
|
||||
function rgb2lab(input) {
|
||||
// This code is adapted from various functions at http://www.easyrgb.com/index.php?X=MATH
|
||||
|
||||
const rgb = [0, 0, 0]
|
||||
const xyz = [0, 0, 0]
|
||||
const Lab = [0, 0, 0]
|
||||
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
let value = input[i] / 255
|
||||
|
||||
if (value > 0.04045) {
|
||||
value = Math.pow(((value + 0.055) / 1.055), 2.4)
|
||||
} else {
|
||||
value = value / 12.92
|
||||
}
|
||||
|
||||
rgb[i] = value * 100
|
||||
}
|
||||
|
||||
xyz[0] = (rgb[0] * 0.4124 + rgb[1] * 0.3576 + rgb[2] * 0.1805) / 95.047 // ref_X = 95.047 Observer= 2°, Illuminant= D65
|
||||
xyz[1] = (rgb[0] * 0.2126 + rgb[1] * 0.7152 + rgb[2] * 0.0722) / 100.0 // ref_Y = 100.000
|
||||
xyz[2] = (rgb[0] * 0.0193 + rgb[1] * 0.1192 + rgb[2] * 0.9505) / 108.883 // ref_Z = 108.883
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
let value = xyz[i]
|
||||
if (value > 0.008856) {
|
||||
value = Math.pow(value, 1 / 3)
|
||||
} else {
|
||||
value = (7.787 * value) + (16 / 116)
|
||||
}
|
||||
xyz[i] = value
|
||||
}
|
||||
|
||||
Lab[0] = parseFloat(((116 * xyz[1]) - 16).toFixed(3))
|
||||
Lab[1] = parseFloat((500 * (xyz[0] - xyz[1])).toFixed(3))
|
||||
Lab[2] = parseFloat((200 * (xyz[1] - xyz[2])).toFixed(3))
|
||||
|
||||
return Lab
|
||||
}
|
|
@ -22,7 +22,7 @@
|
|||
import convert from 'color-convert'
|
||||
import { uidToColor } from './uidToColor.js'
|
||||
import css3Colors from 'css-color-names'
|
||||
import closestColor from 'closest-css-color'
|
||||
import closestColor from './closestColor.js'
|
||||
|
||||
/**
|
||||
* Detect if a color is light or dark
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* @copyright Copyright (c) 2023 Richard Steinmetz <richard@steinmetz.cloud>
|
||||
*
|
||||
* @author Richard Steinmetz <richard@steinmetz.cloud>
|
||||
*
|
||||
* @license AGPL-3.0-or-later
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
// Code was taken from:
|
||||
// - https://github.com/juliuste/closest-css-color
|
||||
|
||||
import closestColor from '../../../../src/utils/closestColor.js'
|
||||
import cssColors from 'css-color-names'
|
||||
import uniqBy from 'lodash/uniqBy.js'
|
||||
import pick from 'lodash/pick.js'
|
||||
|
||||
describe('utils/closestColor test suite', () => {
|
||||
it('should calculate the closest color', () => {
|
||||
const uniqColorKeys = uniqBy(Object.keys(cssColors), c => cssColors[c])
|
||||
const filteredColors = pick(cssColors, uniqColorKeys)
|
||||
|
||||
const color1 = closestColor('#fff')
|
||||
expect(color1).toBe('white')
|
||||
|
||||
const color2 = closestColor('#a00a0a', { detailed: false })
|
||||
expect(color2).toBe('darkred')
|
||||
|
||||
const color3 = closestColor('#1019a6', { detailed: true })
|
||||
expect(color3).toEqual({
|
||||
name: 'darkblue',
|
||||
hex: '#00008b',
|
||||
})
|
||||
|
||||
for (const color of Object.keys(filteredColors)) {
|
||||
expect(closestColor(filteredColors[color])).toBe(color)
|
||||
}
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue