color-name-list 9.8.0 → 9.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "color-name-list",
3
- "version": "9.8.0",
3
+ "version": "9.9.0",
4
4
  "description": "long list of color names",
5
5
  "main": "dist/colornames.json",
6
6
  "browser": "dist/colornames.umd.js",
@@ -33,10 +33,12 @@
33
33
  "homepage": "https://github.com/meodai/color-names#readme",
34
34
  "devDependencies": {
35
35
  "closestvector": "^0.6.0",
36
+ "color-name-lists": "^1.1.0",
36
37
  "commitizen": "^4.2.4",
37
38
  "eslint": "^5.15.1",
38
39
  "eslint-config-google": "^0.10.0",
39
40
  "ghooks": "^2.0.4",
41
+ "seedrandom": "^3.0.5",
40
42
  "semantic-release": "^17.4.2"
41
43
  },
42
44
  "engines": {
@@ -2,7 +2,7 @@ const lib = require('./lib.js');
2
2
  const ClosestVector = require('closestvector');
3
3
 
4
4
  /**
5
- * entriches color object and fills RGB color arrays
5
+ * enriches color object and fills RGB color arrays
6
6
  * Warning: Not a pure function at all :D
7
7
  * @param {object} colorObj hex representation of color
8
8
  * @param {array} rgbColorArrRef reference to RGB color array
@@ -24,24 +24,34 @@ const enrichColorObj = (colorObj, rgbColorArrRef) => {
24
24
  };
25
25
 
26
26
  module.exports = class FindColors {
27
- constructor(colors, colorsBestOf) {
28
-
29
- this.colors = colors;
30
- this.colorsBestOf = colorsBestOf;
27
+ constructor(colorsListsObj) {
28
+ this.colorLists = colorsListsObj;
31
29
 
32
30
  // object containing the name:hex pairs for nearestColor()
33
- this.rgbColorsArr = [];
34
- this.rgbColorsArrBestOf = [];
31
+ this.colorListsRGBArrays = {};
32
+ this.closestInstances = {};
35
33
 
36
34
  // prepare color array
37
- this.colors.forEach((c) => enrichColorObj(c, this.rgbColorsArr));
38
- this.colorsBestOf.forEach((c) => enrichColorObj(c, this.rgbColorsArrBestOf));
35
+ Object.keys(this.colorLists).forEach((listName) => {
36
+ this.colorListsRGBArrays[listName] = [];
37
+
38
+ this.colorLists[listName].forEach(c => {
39
+ enrichColorObj(c, this.colorListsRGBArrays[listName]);
40
+ });
39
41
 
40
- Object.freeze(this.colors);
41
- Object.freeze(this.colorsBestOf);
42
+ Object.freeze(this.colorLists[listName]);
43
+ this.closestInstances[listName] = new ClosestVector(
44
+ this.colorListsRGBArrays[listName]
45
+ );
46
+ });
47
+ }
42
48
 
43
- this.closest = new ClosestVector(this.rgbColorsArr);
44
- this.closestBestOf = new ClosestVector(this.rgbColorsArrBestOf);
49
+ _validateListKey (listKey) {
50
+ if (!this.colorLists[listKey]) {
51
+ throw new Error(`List key "${listKey}" is not valid.`);
52
+ } else {
53
+ return true;
54
+ }
45
55
  }
46
56
 
47
57
  /**
@@ -49,9 +59,11 @@ module.exports = class FindColors {
49
59
  * @param {string} searchStr search term
50
60
  * @param {boolen} bestOf if set only returns good names
51
61
  */
52
- searchNames (searchStr, bestOf = false) {
53
- const colors = bestOf ? this.colorsBestOf : this.colors;
54
- return colors.filter(color => color.name.toLowerCase().includes(searchStr.toLowerCase()));
62
+ searchNames (searchStr, listKey = 'default') {
63
+ this._validateListKey(listKey);
64
+ return this.colorLists[listKey].filter(
65
+ color => color.name.toLowerCase().includes(searchStr.toLowerCase())
66
+ );
55
67
  }
56
68
 
57
69
  /**
@@ -61,24 +73,30 @@ module.exports = class FindColors {
61
73
  * @param {boolean} bestOf if set only returns good names
62
74
  * @return {object} object containing all nearest colors
63
75
  */
64
- getNamesForValues (colorArr, unique = false, bestOf = false) {
65
- let localClosest = bestOf ? this.closestBestOf : this.closest;
76
+ getNamesForValues(colorArr, unique = false, listKey = 'default') {
77
+ let localClosest = this.closestInstances[listKey];
66
78
 
67
79
  if (unique) {
68
80
  localClosest = new ClosestVector(
69
- bestOf ? this.rgbColorsArrBestOf : this.rgbColorsArr,
81
+ this.colorListsRGBArrays[listKey],
70
82
  true
71
83
  );
72
84
  }
73
85
 
86
+ let lastResult = null;
87
+
74
88
  const colorResp = colorArr.map((hex) => {
75
89
  // calculate RGB values for passed color
76
90
  const rgb = lib.hexToRgb(hex);
77
91
 
78
92
  // get the closest named colors
79
- const closestColor = localClosest.get([rgb.r, rgb.g, rgb.b]);
80
- const color = bestOf ? this.colorsBestOf[closestColor.index] :
81
- this.colors[closestColor.index];
93
+ let closestColor = localClosest.get([rgb.r, rgb.g, rgb.b]);
94
+ if (closestColor && unique) {
95
+ lastResult = closestColor;
96
+ } else if (unique) {
97
+ closestColor = lastResult;
98
+ }
99
+ const color = this.colorLists[listKey][closestColor.index];
82
100
 
83
101
  return {
84
102
  ...color,
@@ -0,0 +1,48 @@
1
+ const seedrandom = require('seedrandom');
2
+
3
+ /**
4
+ * getPaletteTitle
5
+ * @param {string[]} namesArr
6
+ * @param {int(0-1)} rnd1
7
+ * @param {int(0-1)} rnd2
8
+ * @param {int(0-1)} longPartFirst
9
+ * @param {RegExp} separatorRegex
10
+ * @returns {string}
11
+ */
12
+
13
+ module.exports = function getPaletteTitle(
14
+ namesArr, // array of names
15
+ separatorRegex = /(\s|-)+/g
16
+ ) {
17
+ let localnames = [...namesArr];
18
+
19
+ const rng = seedrandom(namesArr.join('-'));
20
+ const rnd1 = rng();
21
+ const rnd2 = rng();
22
+ const longPartFirst = rng() < .5;
23
+
24
+ // select a random name from the list for the first word in the palette title
25
+ const indexFirst = Math.round(rnd1 * (localnames.length - 1));
26
+
27
+ // remove the selected name from the list
28
+ const firstName = localnames.splice(indexFirst, 1)[0];
29
+
30
+ // select a random name from the list as a last word in the palette title
31
+ const lastIndex = Math.round(rnd2 * (localnames.length - 1));
32
+ const lastName = localnames[lastIndex];
33
+
34
+ const partsFirst = firstName.split(separatorRegex);
35
+ const partsLast = lastName.split(separatorRegex);
36
+
37
+ if (longPartFirst) {
38
+ partsFirst.length > 1 ?
39
+ partsFirst.pop() :
40
+ partsFirst[0] = `${partsFirst[0]} `;
41
+ return partsFirst.join('') + partsLast.pop();
42
+ } else {
43
+ partsLast.length > 1 ?
44
+ partsLast.shift() :
45
+ partsLast[0] = ` ${partsLast[0]}`;
46
+ return partsFirst.shift() + partsLast.join('');
47
+ }
48
+ }
package/scripts/server.js CHANGED
@@ -2,6 +2,7 @@ const http = require('http');
2
2
  const url = require('url');
3
3
  const fs = require('fs');
4
4
  const zlib = require('zlib');
5
+ const colorNameLists = require('color-name-lists');
5
6
  const colors = JSON.parse(
6
7
  fs.readFileSync(__dirname + '/../dist/colornames.json', 'utf8')
7
8
  );
@@ -9,6 +10,7 @@ const colorsBestOf = JSON.parse(
9
10
  fs.readFileSync(__dirname + '/../dist/colornames.bestof.json', 'utf8')
10
11
  );
11
12
  const FindColors = require('./findColors.js');
13
+ const getPaletteTitle = require('./generatePaletteName.js');
12
14
  const port = process.env.PORT || 8080;
13
15
  const currentVersion = 'v1';
14
16
  const urlNameSubpath = 'names';
@@ -26,7 +28,18 @@ const responseHeaderObj = {
26
28
  'Content-Type': 'application/json; charset=utf-8',
27
29
  };
28
30
 
29
- const findColors = new FindColors(colors, colorsBestOf);
31
+ // [{name: 'red', value: '#f00'}, ...]
32
+ const colorsLists = {
33
+ default: colors,
34
+ colors: colors,
35
+ bestOf: colorsBestOf,
36
+ };
37
+
38
+ Object.assign(colorsLists, colorNameLists);
39
+
40
+ const avalibleColorNameLists = Object.keys(colorsLists);
41
+
42
+ const findColors = new FindColors(colorsLists);
30
43
 
31
44
  /**
32
45
  * validates a hex color
@@ -53,7 +66,7 @@ const httpRespond = (response, responseObj = {}, statusCode = 200) => {
53
66
 
54
67
  const respondNameSearch = (
55
68
  searchParams = new URLSearchParams(''),
56
- goodNamesMode = false,
69
+ listKey = 'default',
57
70
  requestUrl,
58
71
  request,
59
72
  response
@@ -77,13 +90,13 @@ const respondNameSearch = (
77
90
  }
78
91
 
79
92
  return httpRespond(response, {
80
- colors: findColors.searchNames(searchString, goodNamesMode),
93
+ colors: findColors.searchNames(searchString, listKey),
81
94
  }, 200);
82
95
  };
83
96
 
84
97
  const respondValueSearch = (
85
98
  searchParams = new URLSearchParams(''),
86
- goodNamesMode = false,
99
+ listKey = 'default',
87
100
  requestUrl,
88
101
  request,
89
102
  response
@@ -116,10 +129,32 @@ const respondValueSearch = (
116
129
  }}, 404);
117
130
  }
118
131
 
132
+ let paletteTitle;
133
+ let colorsResponse;
134
+
135
+ if (urlColorList[0]) {
136
+ colorsResponse = findColors.getNamesForValues(
137
+ urlColorList, uniqueMode, listKey
138
+ );
139
+ } else {
140
+ colorsResponse = colorsLists[listKey];
141
+ }
142
+
143
+ if (urlColorList.length === 1) {
144
+ // if there is only one color, just return its name as palette title
145
+ paletteTitle = colorsResponse[0].name;
146
+ } else if (urlColorList.length > 1) {
147
+ // get a palette title for the returned colors
148
+ paletteTitle = getPaletteTitle(colorsResponse.map((color) => color.name));
149
+ } else {
150
+ // return all colors if no colors were given
151
+ paletteTitle = `All the ${listKey} names`;
152
+ }
153
+
154
+ // actual http response
119
155
  return httpRespond(response, {
120
- colors: urlColorList[0] ?
121
- findColors.getNamesForValues(urlColorList, uniqueMode, goodNamesMode):
122
- (goodNamesMode ? colorsBestOf : colors),
156
+ paletteTitle,
157
+ colors: colorsResponse,
123
158
  }, 200);
124
159
  };
125
160
 
@@ -159,10 +194,25 @@ const requestHandler = (request, response) => {
159
194
  const goodNamesMode = searchParams.has('goodnamesonly')
160
195
  && searchParams.get('goodnamesonly') === 'true';
161
196
 
197
+ let listKey = searchParams.has('list')
198
+ && searchParams.get('list');
199
+
200
+ listKey = goodNamesMode ? 'bestOf' : listKey;
201
+ listKey = listKey || 'default';
202
+
203
+ const isValidListKey = listKey && avalibleColorNameLists.includes(listKey);
204
+
205
+ if (!isValidListKey) {
206
+ return httpRespond(response, {error: {
207
+ status: 404,
208
+ message: `invalid list key: '${listKey}, available keys are: ${avalibleColorNameLists.join(', ')}`,
209
+ }}, 404);
210
+ }
211
+
162
212
  if (!isNamesAPI) {
163
213
  return respondValueSearch(
164
214
  searchParams,
165
- goodNamesMode,
215
+ listKey,
166
216
  requestUrl,
167
217
  request,
168
218
  response
@@ -170,7 +220,7 @@ const requestHandler = (request, response) => {
170
220
  } else {
171
221
  return respondNameSearch(
172
222
  searchParams,
173
- goodNamesMode,
223
+ listKey,
174
224
  requestUrl,
175
225
  request,
176
226
  response