color-name-list 12.1.0 → 13.0.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.
Files changed (48) hide show
  1. package/.vscode/tasks.json +10 -0
  2. package/README.md +2 -2
  3. package/changes.svg +3 -3
  4. package/dist/colornames.bestof.csv +22 -20
  5. package/dist/colornames.bestof.esm.js +1 -1
  6. package/dist/colornames.bestof.esm.mjs +1 -1
  7. package/dist/colornames.bestof.html +1 -1
  8. package/dist/colornames.bestof.json +1 -1
  9. package/dist/colornames.bestof.min.json +1 -1
  10. package/dist/colornames.bestof.scss +1 -1
  11. package/dist/colornames.bestof.umd.js +1 -1
  12. package/dist/colornames.bestof.xml +59 -51
  13. package/dist/colornames.bestof.yaml +47 -41
  14. package/dist/colornames.csv +38 -135
  15. package/dist/colornames.esm.js +1 -1
  16. package/dist/colornames.esm.mjs +1 -1
  17. package/dist/colornames.html +1 -1
  18. package/dist/colornames.json +1 -1
  19. package/dist/colornames.min.json +1 -1
  20. package/dist/colornames.scss +1 -1
  21. package/dist/colornames.short.csv +12 -17
  22. package/dist/colornames.short.esm.js +1 -1
  23. package/dist/colornames.short.esm.mjs +1 -1
  24. package/dist/colornames.short.html +1 -1
  25. package/dist/colornames.short.json +1 -1
  26. package/dist/colornames.short.min.json +1 -1
  27. package/dist/colornames.short.scss +1 -1
  28. package/dist/colornames.short.umd.js +1 -1
  29. package/dist/colornames.short.xml +25 -45
  30. package/dist/colornames.short.yaml +21 -36
  31. package/dist/colornames.umd.js +1 -1
  32. package/dist/colornames.xml +69 -457
  33. package/dist/colornames.yaml +56 -347
  34. package/dist/history.json +1 -1
  35. package/package.json +1 -1
  36. package/scripts/build.js +33 -161
  37. package/scripts/lib.js +60 -5
  38. package/scripts/sortSrc.js +4 -5
  39. package/src/colornames.csv +42 -139
  40. package/tests/_utils/report.js +76 -0
  41. package/tests/csv-test-data.js +108 -0
  42. package/tests/duplicate-allowlist.json +28 -1
  43. package/tests/duplicate-plurals-allowlist.json +10 -0
  44. package/tests/duplicates.test.js +135 -40
  45. package/tests/formats.test.js +9 -8
  46. package/tests/imports.test.js +12 -14
  47. package/tests/sorting.test.js +10 -12
  48. package/tests/validations.test.js +219 -0
@@ -0,0 +1,219 @@
1
+ import { describe, it, expect, beforeAll } from 'vitest';
2
+ import { csvTestData } from './csv-test-data.js';
3
+ import { buildFailureMessage } from './_utils/report.js';
4
+
5
+ describe('CSV Data Validations', () => {
6
+ const bestOfKey = 'good name';
7
+
8
+ // Validation patterns from build.js
9
+ const hexColorValidation = /^#[0-9a-f]{6}$/;
10
+ const spacesValidation = /^\s+|\s{2,}|\s$/;
11
+ const quoteValidation = /"|'|`/;
12
+
13
+ beforeAll(() => {
14
+ // Load CSV data once for all tests
15
+ csvTestData.load();
16
+ });
17
+
18
+ it('should contain only valid 6-character hex color codes', () => {
19
+ const invalidHexCodes = [];
20
+
21
+ csvTestData.data.values['hex'].forEach((hex, index) => {
22
+ if (!hexColorValidation.test(hex)) {
23
+ const entry = csvTestData.data.entries[index];
24
+ invalidHexCodes.push({
25
+ hex,
26
+ name: entry.name,
27
+ lineNumber: index + 2, // +2 for header and 0-based index
28
+ });
29
+ }
30
+ });
31
+
32
+ if (invalidHexCodes.length) {
33
+ const details = invalidHexCodes.map(
34
+ ({ hex, name, lineNumber }) => ` * line ${lineNumber}: "${name}" -> ${hex}`
35
+ );
36
+ throw new Error(
37
+ buildFailureMessage({
38
+ title: 'Found {n} invalid hex color {items}:',
39
+ offenders: invalidHexCodes.map((i) => i.hex),
40
+ offenderLabel: 'code',
41
+ details: [
42
+ ...details,
43
+ '',
44
+ 'Hex codes must be exactly 6 characters long (no shorthand) and contain only lowercase letters a-f and numbers 0-9.',
45
+ 'Examples of valid hex codes: #ff0000, #a1b2c3, #000000',
46
+ 'Examples of invalid hex codes: #f00 (too short), #FF0000 (uppercase), #gghhii (invalid characters)',
47
+ ],
48
+ tips: [
49
+ 'Edit src/colornames.csv and fix the hex values',
50
+ 'Use lowercase letters only: a-f',
51
+ 'Always use 6 characters: #rrggbb format',
52
+ 'After changes, run: npm run sort-colors',
53
+ ],
54
+ })
55
+ );
56
+ }
57
+
58
+ expect(invalidHexCodes.length).toBe(0);
59
+ });
60
+
61
+ it('should not contain color names with invalid spacing', () => {
62
+ const invalidNames = [];
63
+
64
+ csvTestData.data.values['name'].forEach((name, index) => {
65
+ if (spacesValidation.test(name)) {
66
+ const entry = csvTestData.data.entries[index];
67
+ invalidNames.push({
68
+ name,
69
+ hex: entry.hex,
70
+ lineNumber: index + 2, // +2 for header and 0-based index
71
+ });
72
+ }
73
+ });
74
+
75
+ if (invalidNames.length) {
76
+ const details = invalidNames.map(
77
+ ({ name, hex, lineNumber }) => ` * line ${lineNumber}: "${name}" (${hex})`
78
+ );
79
+ throw new Error(
80
+ buildFailureMessage({
81
+ title: 'Found {n} color {items} with invalid spacing:',
82
+ offenders: invalidNames.map((i) => `"${i.name}"`),
83
+ offenderLabel: 'name',
84
+ details: [
85
+ ...details,
86
+ '',
87
+ 'Color names cannot have leading spaces, trailing spaces, or multiple consecutive spaces.',
88
+ 'This ensures consistent formatting and prevents parsing issues.',
89
+ ],
90
+ tips: [
91
+ 'Edit src/colornames.csv and remove extra spaces',
92
+ 'Use single spaces between words only',
93
+ 'After changes, run: npm run sort-colors',
94
+ ],
95
+ })
96
+ );
97
+ }
98
+
99
+ expect(invalidNames.length).toBe(0);
100
+ });
101
+
102
+ it('should not contain color names with quote characters', () => {
103
+ const invalidNames = [];
104
+
105
+ csvTestData.data.values['name'].forEach((name, index) => {
106
+ if (quoteValidation.test(name)) {
107
+ const entry = csvTestData.data.entries[index];
108
+ invalidNames.push({
109
+ name,
110
+ hex: entry.hex,
111
+ lineNumber: index + 2, // +2 for header and 0-based index
112
+ });
113
+ }
114
+ });
115
+
116
+ if (invalidNames.length) {
117
+ const details = invalidNames.map(
118
+ ({ name, hex, lineNumber }) => ` * line ${lineNumber}: "${name}" (${hex})`
119
+ );
120
+ throw new Error(
121
+ buildFailureMessage({
122
+ title: 'Found {n} color {items} with quote characters:',
123
+ offenders: invalidNames.map((i) => `"${i.name}"`),
124
+ offenderLabel: 'name',
125
+ details: [
126
+ ...details,
127
+ '',
128
+ 'Color names should not contain double quotes or backticks.',
129
+ 'Use apostrophes instead of double quotes for possessives or contractions.',
130
+ ],
131
+ tips: [
132
+ 'Edit src/colornames.csv and replace quote characters',
133
+ 'Use apostrophes for possessives; avoid double quotes in names',
134
+ 'After changes, run: npm run sort-colors',
135
+ ],
136
+ })
137
+ );
138
+ }
139
+
140
+ expect(invalidNames.length).toBe(0);
141
+ });
142
+
143
+ it('should have valid "good name" markers', () => {
144
+ const invalidMarkers = [];
145
+
146
+ if (csvTestData.data.values[bestOfKey]) {
147
+ csvTestData.data.values[bestOfKey].forEach((marker, index) => {
148
+ // Check for spacing issues
149
+ if (spacesValidation.test(marker)) {
150
+ const entry = csvTestData.data.entries[index];
151
+ invalidMarkers.push({
152
+ marker,
153
+ name: entry.name,
154
+ hex: entry.hex,
155
+ lineNumber: index + 2,
156
+ issue: 'invalid spacing',
157
+ });
158
+ }
159
+
160
+ // Check for invalid values (must be 'x' or empty)
161
+ if (!(marker === 'x' || marker === '')) {
162
+ const entry = csvTestData.data.entries[index];
163
+ invalidMarkers.push({
164
+ marker,
165
+ name: entry.name,
166
+ hex: entry.hex,
167
+ lineNumber: index + 2,
168
+ issue: 'invalid value',
169
+ });
170
+ }
171
+ });
172
+ }
173
+
174
+ if (invalidMarkers.length) {
175
+ const spacingIssues = invalidMarkers.filter((item) => item.issue === 'invalid spacing');
176
+ const valueIssues = invalidMarkers.filter((item) => item.issue === 'invalid value');
177
+
178
+ const details = [];
179
+ if (spacingIssues.length) {
180
+ details.push(' Spacing issues:');
181
+ spacingIssues.forEach(({ marker, name, lineNumber }) => {
182
+ details.push(` * line ${lineNumber}: "${name}" -> "${marker}"`);
183
+ });
184
+ details.push('');
185
+ }
186
+ if (valueIssues.length) {
187
+ details.push(' Invalid values:');
188
+ valueIssues.forEach(({ marker, name, lineNumber }) => {
189
+ details.push(` * line ${lineNumber}: "${name}" -> "${marker}"`);
190
+ });
191
+ details.push('');
192
+ }
193
+
194
+ throw new Error(
195
+ buildFailureMessage({
196
+ title: 'Found {n} invalid "good name" {items}:',
197
+ offenders: invalidMarkers.map((m) => `"${m.marker}"`),
198
+ offenderLabel: 'marker',
199
+ details: [
200
+ ...details,
201
+ '',
202
+ 'The "good name" column must contain either:',
203
+ ' - lowercase "x" to mark a color as a good/recommended name',
204
+ ' - empty string (blank) for regular colors',
205
+ '',
206
+ 'No spaces, uppercase letters, or other characters are allowed.',
207
+ ],
208
+ tips: [
209
+ 'Edit src/colornames.csv and fix the "good name" column',
210
+ 'Use lowercase "x" or leave blank',
211
+ 'After changes, run: npm run sort-colors',
212
+ ],
213
+ })
214
+ );
215
+ }
216
+
217
+ expect(invalidMarkers.length).toBe(0);
218
+ });
219
+ });