-
-
Notifications
You must be signed in to change notification settings - Fork 59
/
merge-classlist.ts
99 lines (80 loc) · 3.23 KB
/
merge-classlist.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import { ConfigUtils } from './config-utils'
import { IMPORTANT_MODIFIER, sortModifiers } from './modifier-utils'
const SPLIT_CLASSES_REGEX = /\s+/
export function mergeClassList(classList: string, configUtils: ConfigUtils) {
const { splitModifiers, getClassGroupId, getConflictingClassGroupIds } = configUtils
/**
* Set of classGroupIds in following format:
* `{importantModifier}{variantModifiers}{classGroupId}`
* @example 'float'
* @example 'hover:focus:bg-color'
* @example 'md:!pr'
*/
const classGroupsInConflict = new Set<string>()
return (
classList
.trim()
.split(SPLIT_CLASSES_REGEX)
.map((originalClassName) => {
const {
modifiers,
hasImportantModifier,
baseClassName,
maybePostfixModifierPosition,
} = splitModifiers(originalClassName)
let classGroupId = getClassGroupId(
maybePostfixModifierPosition
? baseClassName.substring(0, maybePostfixModifierPosition)
: baseClassName,
)
let hasPostfixModifier = Boolean(maybePostfixModifierPosition)
if (!classGroupId) {
if (!maybePostfixModifierPosition) {
return {
isTailwindClass: false as const,
originalClassName,
}
}
classGroupId = getClassGroupId(baseClassName)
if (!classGroupId) {
return {
isTailwindClass: false as const,
originalClassName,
}
}
hasPostfixModifier = false
}
const variantModifier = sortModifiers(modifiers).join(':')
const modifierId = hasImportantModifier
? variantModifier + IMPORTANT_MODIFIER
: variantModifier
return {
isTailwindClass: true as const,
modifierId,
classGroupId,
originalClassName,
hasPostfixModifier,
}
})
.reverse()
// Last class in conflict wins, so we need to filter conflicting classes in reverse order.
.filter((parsed) => {
if (!parsed.isTailwindClass) {
return true
}
const { modifierId, classGroupId, hasPostfixModifier } = parsed
const classId = modifierId + classGroupId
if (classGroupsInConflict.has(classId)) {
return false
}
classGroupsInConflict.add(classId)
getConflictingClassGroupIds(classGroupId, hasPostfixModifier).forEach((group) =>
classGroupsInConflict.add(modifierId + group),
)
return true
})
.reverse()
.map((parsed) => parsed.originalClassName)
.join(' ')
)
}