Skip to content

Commit 0fb2320

Browse files
authored
Merge pull request #45 from mll-lab/feat-add-stringToHslaColor
2 parents d8abb2c + 48fea4d commit 0fb2320

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

src/stringToColor.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { uniq } from 'lodash';
2+
3+
import { randomString, stringToHslaColor } from './stringToColor';
4+
5+
describe('stringToHslaColor', () => {
6+
it.each(['test', 'test'])(
7+
'is a pure function returning the same hsla for the same string',
8+
(testString) => {
9+
expect(stringToHslaColor(testString)).toStrictEqual(
10+
'hsla(58, 98%, 48%, 1)',
11+
);
12+
},
13+
);
14+
15+
it('returns various hsla colors for various inputs', () => {
16+
const testStrings = ['t', 'te', 'tes', 'test'];
17+
expect(uniq(testStrings.map(stringToHslaColor)).length).toBe(
18+
testStrings.length,
19+
);
20+
});
21+
22+
it('returns a valid color for a random string', () => {
23+
expect(isValidColor(stringToHslaColor(randomString()))).toBe(true);
24+
});
25+
});
26+
27+
function isValidColor(color: string): boolean {
28+
// Use the browser's validation. Create a dummy HTML element, assign the color and check if it's set.
29+
const element = document.createElement('div');
30+
element.style.borderColor = '';
31+
element.style.borderColor = color;
32+
33+
return element.style.borderColor.length !== 0;
34+
}

src/stringToColor.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
function hashCode(string: string): number {
2+
let hash = 0;
3+
// eslint-disable-next-line no-plusplus
4+
for (let i = 0; i < string.length; i++) {
5+
// eslint-disable-next-line no-bitwise
6+
hash = string.charCodeAt(i) + ((hash << 5) - hash);
7+
}
8+
9+
return hash;
10+
}
11+
12+
function getHslColor(hash: number): string {
13+
const h = range(hash, 0, 360);
14+
const s = range(hash, 50, 100);
15+
const l = range(hash, 20, 50);
16+
17+
return `hsla(${h}, ${s}%, ${l}%, 1)`;
18+
}
19+
20+
function range(hash: number, min: number, max: number): number {
21+
const diff = max - min;
22+
const x = ((hash % diff) + diff) % diff;
23+
24+
return x + min;
25+
}
26+
27+
export function stringToHslaColor(string: string): string {
28+
return getHslColor(hashCode(string));
29+
}
30+
31+
/**
32+
* Generates a random string with a length of 1-11 chars.
33+
*/
34+
export function randomString(): string {
35+
// Cut off the constant 0. from the beginning
36+
const fractionStart = 2;
37+
38+
// Unequal distribution at the edges, but sufficiently random for the purposes of this function
39+
const randomLengthEnd = Math.round(Math.random() * 11) + 3;
40+
41+
return Math.random().toString(36).substring(fractionStart, randomLengthEnd);
42+
}

0 commit comments

Comments
 (0)