-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
64 lines (46 loc) · 1.54 KB
/
index.ts
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
import { createHash } from 'crypto';
// creates a base64-encoded md5 hash of the original class name
// and removes chars that are invalid for CSS class names
const md5 = (originalClassName: string) =>
createHash('md5')
.update(originalClassName)
.digest('base64')
.replace(/\/|\+|==/g, '');
const TARGET_HASH_LENGTH: number = 5;
const isLetter = (char: string): boolean => /[a-zA-Z]/.test(char);
const isLetterOrNumber = (char: string): boolean => /[A-Za-z0-9]/.test(char);
const hashClassName = (originalClassName: string): string => {
const rawHash: string = md5(originalClassName);
let cssClass: string = '';
let idx: number = 0;
while (cssClass.length < TARGET_HASH_LENGTH) {
const char: string = rawHash[idx];
// our hashed CSS class name should start with a letter
// and then continue with either a letter or digit
if (cssClass.length && isLetterOrNumber(char)) {
cssClass = `${cssClass}${char}`;
} else if (!cssClass.length && isLetter(char)) {
cssClass = char;
}
// else, skip `char`
idx += 1;
}
return cssClass;
};
type Dictionary = { [key: string]: string };
const hashClassNameWithCache = (
originalClassName: string,
dictionary?: Dictionary,
): string => {
if (!dictionary) {
return hashClassName(originalClassName);
}
const cached = dictionary[originalClassName];
if (cached) {
return cached;
}
const cssClass = hashClassName(originalClassName);
dictionary[originalClassName] = cssClass;
return cssClass;
};
export default hashClassNameWithCache;