-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
Copy pathcolors.js
executable file
·90 lines (83 loc) · 2.95 KB
/
colors.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
'use strict'
const fs = require('fs')
const colorConvert = require('color-convert')
const getImageColors = require('get-image-colors')
const mime = require('mime-types')
const path = require('path')
const pickAGoodColor = require('pick-a-good-color')
const revHash = require('rev-hash')
const stringify = require('json-stable-stringify')
/**
* Generates good colors for an image.
*
* @param slugsAndIconPaths [ { slug: foo, iconPath: bar } ... ]
* @param oldColors: reference colors from previous call to getColors()
* @param root: repo toplevel directory so that saved iconPaths are relative to it
* @return { slug: { palette, goodColorOnWhite, goodColorOnBlack, faintColorOnWhite, source: { revHash, iconPath } }
*/
async function getColors(slugsAndIconPaths, oldColors, root) {
return Promise.all(
slugsAndIconPaths.map(async (app) => {
const slug = app.slug
try {
const data = fs.readFileSync(app.iconPath)
const hash = revHash(data)
// if nothing's changed, don't recalculate
let o = oldColors[slug]
if (o && o.source && o.source.revHash === hash) return { [slug]: o }
console.info(`calculating good colors for ${slug}`)
return await getImageColors(data, mime.lookup(app.iconPath)).then(
(iconColors) => {
const palette = iconColors.map((color) => color.hex())
const goodColorOnWhite = pickAGoodColor(palette)
const goodColorOnBlack = pickAGoodColor(palette, {
background: 'black',
})
const faintColorOnWhite = `rgba(${colorConvert.hex
.rgb(goodColorOnWhite)
.join(', ')}, 0.1)`
return {
[slug]: {
source: {
revHash: hash,
path: path.relative(root, app.iconPath),
},
palette,
goodColorOnWhite,
goodColorOnBlack,
faintColorOnWhite,
},
}
}
)
} catch (e) {
console.error(`Error processing ${app.iconPath}`, e)
}
})
).then((values) => Object.assign({}, ...values))
}
/**
* Wrapper around getColors() that uses the same file for input & output,
* refreshing the file when the data changes
*
* @param slugsAndIconPaths [ { slug: foo, iconPath: bar } ... ]
* @param colorsFile: the file that keeps the list of complimentary colors
* @param root: repo toplevel directory so that saved iconPaths are relative to it
*/
const rebuildColorFile = (slugsAndIconPaths, colorsFile, root) => {
let oldColors
try {
oldColors = require(colorsFile)
} catch (e) {
oldColors = {}
}
getColors(slugsAndIconPaths, oldColors, root).then((colors) => {
try {
fs.writeFileSync(colorsFile, stringify(colors, { space: 2 }))
} catch (e) {
console.error(`Error writing ${colorsFile}`, e)
}
})
}
module.exports = rebuildColorFile
module.exports.getColors = getColors