color-name-list 13.19.0 → 13.19.1

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 (42) hide show
  1. package/README.md +2 -2
  2. package/changes.svg +3 -3
  3. package/dist/colornames.bestof.csv +40 -31
  4. package/dist/colornames.bestof.esm.js +1 -1
  5. package/dist/colornames.bestof.esm.mjs +1 -1
  6. package/dist/colornames.bestof.html +1 -1
  7. package/dist/colornames.bestof.json +1 -1
  8. package/dist/colornames.bestof.min.json +1 -1
  9. package/dist/colornames.bestof.scss +1 -1
  10. package/dist/colornames.bestof.toon +41 -32
  11. package/dist/colornames.bestof.umd.js +1 -1
  12. package/dist/colornames.bestof.xml +67 -31
  13. package/dist/colornames.bestof.yaml +58 -31
  14. package/dist/colornames.csv +120 -127
  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 +8 -8
  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.toon +9 -9
  29. package/dist/colornames.short.umd.js +1 -1
  30. package/dist/colornames.short.xml +8 -8
  31. package/dist/colornames.short.yaml +8 -8
  32. package/dist/colornames.toon +121 -128
  33. package/dist/colornames.umd.js +1 -1
  34. package/dist/colornames.xml +141 -169
  35. package/dist/colornames.yaml +134 -155
  36. package/dist/history.json +1 -1
  37. package/package.json +1 -1
  38. package/scripts/lib.js +27 -2
  39. package/src/colornames.csv +120 -127
  40. package/tests/duplicates.test.js +65 -0
  41. package/tests/title-case-allowlist.json +46 -0
  42. package/tests/title-case.test.js +4 -2
@@ -253,6 +253,71 @@ describe('Duplicate-like color names', () => {
253
253
  expect(conflicts[0].entries.length).toBe(2);
254
254
  });
255
255
 
256
+ it('should treat different forms of "and" as near-duplicates when stopword folding is enabled', () => {
257
+ const items = [
258
+ { name: 'Berries and Cream' },
259
+ { name: 'Berries n Cream' },
260
+ { name: 'Berries & Cream' },
261
+ { name: 'Berries + Cream' },
262
+ ];
263
+
264
+ const conflicts = findNearDuplicateNameConflicts(items, {
265
+ foldStopwords: true,
266
+ stopwords: STOPWORDS,
267
+ });
268
+
269
+ // All variants should collapse into a single conflict group
270
+ expect(conflicts.length).toBe(1);
271
+ expect(conflicts[0].entries.length).toBe(4);
272
+ });
273
+
274
+ it('should treat numeral/phonetic swaps (2/to, 4/for, u/you, r/are) as near-duplicates', () => {
275
+ const items1 = [
276
+ { name: 'Back to the Future' },
277
+ { name: 'Back 2 the Future' },
278
+ ];
279
+ const items2 = [
280
+ { name: 'Music for the People' },
281
+ { name: 'Music 4 the People' },
282
+ ];
283
+ const items3 = [
284
+ { name: 'Songs for You' },
285
+ { name: 'Songs 4 U' },
286
+ ];
287
+ const items4 = [
288
+ { name: 'We Are the Champions' },
289
+ { name: 'We R the Champions' },
290
+ ];
291
+
292
+ const opts = { foldStopwords: true, stopwords: STOPWORDS };
293
+ expect(findNearDuplicateNameConflicts(items1, opts).length).toBe(1);
294
+ expect(findNearDuplicateNameConflicts(items2, opts).length).toBe(1);
295
+ expect(findNearDuplicateNameConflicts(items3, opts).length).toBe(1);
296
+ expect(findNearDuplicateNameConflicts(items4, opts).length).toBe(1);
297
+ });
298
+
299
+ it('should treat symbol/slashed forms (@/at, w//with, w/o/without) as near-duplicates', () => {
300
+ const items1 = [
301
+ { name: 'Meet at the Park' },
302
+ { name: 'Meet @ the Park' },
303
+ ];
304
+ const items2 = [
305
+ { name: 'Coffee with Cream' },
306
+ { name: 'Coffee w/ Cream' },
307
+ ];
308
+ const items3 = [
309
+ { name: 'Coffee without Sugar' },
310
+ { name: 'Coffee w/o Sugar' },
311
+ ];
312
+
313
+ const opts = { foldStopwords: true, stopwords: STOPWORDS };
314
+ expect(findNearDuplicateNameConflicts(items1, opts).length).toBe(1);
315
+ expect(findNearDuplicateNameConflicts(items2, opts).length).toBe(1);
316
+ expect(findNearDuplicateNameConflicts(items3, opts).length).toBe(1);
317
+ });
318
+
319
+ // Intentionally not normalizing marketing spellings (lite/thru/nite) or business suffixes globally
320
+
256
321
  it('should not contain two-word names that are exact reversals of each other', () => {
257
322
  expect(csvTestData.lineCount).toBeGreaterThan(1);
258
323
 
@@ -0,0 +1,46 @@
1
+ [
2
+ "Rock’n’Rose",
3
+ "UP Forest Green",
4
+ "UP Maroon",
5
+ "No$GMB Yellow",
6
+ "LeChuck’s Beard",
7
+ "Marilyn MonRouge",
8
+ "Mint-o-licious",
9
+ "Mauve-a-Lish",
10
+ "Peek-a-Blue",
11
+ "Apple-a-Day",
12
+ "Banan-appeal",
13
+ "Fly-by-Night",
14
+ "Down-to-Earth",
15
+ "Iron-ic",
16
+ "Mid-century Gem",
17
+ "Mee-hua Sunset",
18
+ "Sci-fi Petrol",
19
+ "Peaches’n’Cream",
20
+ "Will o’ the Wisp",
21
+ "G.I.",
22
+ "À l’Orange",
23
+ "Acini di Pepe",
24
+ "Big Dip O’ruby",
25
+ "Vinho do Porto",
26
+ "Blush d’Amour",
27
+ "Casa del Mar",
28
+ "Chicco d’Oro",
29
+ "Cor-de-Pele",
30
+ "Cote D’Azur",
31
+ "Je t’aime",
32
+ "Jet d’Eau",
33
+ "La Vie en Rose",
34
+ "Les Demoiselles d’Avignon",
35
+ "O’Brien Orange",
36
+ "O’Neal Green",
37
+ "Parfait d’Amour",
38
+ "Pesto di Noce",
39
+ "Pesto di Pistacchio",
40
+ "Pesto di Rucola",
41
+ "Pomodoro e Mozzarella",
42
+ "Rage of Quel’Danas",
43
+ "Ravioli al Limone",
44
+ "Ryoku-Ou-Shoku Yellow",
45
+ "Tête-à-Tête"
46
+ ]
@@ -1,5 +1,6 @@
1
1
  import { describe, it, expect, beforeAll } from 'vitest';
2
2
  import { csvTestData } from './csv-test-data.js';
3
+ import titleCaseAllowlist from './title-case-allowlist.json';
3
4
  import { buildFailureMessage } from './_utils/report.js';
4
5
 
5
6
  describe('APA Title Case Validation', () => {
@@ -328,11 +329,11 @@ describe('APA Title Case Validation', () => {
328
329
  return name === expectedTitleCase;
329
330
  }
330
331
 
331
- it.skip('should follow APA title case capitalization rules', () => {
332
+ it('should follow APA title case capitalization rules', () => {
332
333
  const invalidNames = [];
333
334
 
334
335
  csvTestData.data.values['name'].forEach((name, index) => {
335
- if (!isValidTitleCase(name)) {
336
+ if (!isValidTitleCase(name) && !((Array.isArray(titleCaseAllowlist) ? titleCaseAllowlist : []).includes(name))) {
336
337
  const entry = csvTestData.data.entries[index];
337
338
  const expectedTitleCase = toTitleCase(name);
338
339
  invalidNames.push({
@@ -373,6 +374,7 @@ describe('APA Title Case Validation', () => {
373
374
  'Examples: "Red and Blue" → "Red and Blue" (correct)',
374
375
  'Examples: "A Shade Of Green" → "A Shade of Green" (of should be lowercase)',
375
376
  'Examples: "Self-Report Blue" → "Self-Report Blue" (both parts capitalized)',
377
+ 'If a capitalization is intentional, add the exact name to tests/title-case-allowlist.json',
376
378
  'After changes, run: npm run sort-colors',
377
379
  ],
378
380
  })