-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathCSSRuleWrapper.ts
96 lines (84 loc) · 2.49 KB
/
CSSRuleWrapper.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
import { PostCSSRule } from "../../Types";
import {
cleanSelector,
cssRuleMatchesPrefixSelector,
isKeyframes,
isNotRootTag,
isValidCSSSelector,
} from "./CSSSelector";
export const prefixWrapCSSRule = (
cssRule: PostCSSRule,
nested: string | null,
ignoredSelectors: (string | RegExp)[],
prefixSelector: string,
prefixRootTags: boolean,
): void => {
// Check each rule to see if it exactly matches our prefix selector, when
// this happens, don't try to prefix that selector.
const rules = cssRule.selector
.split(",")
.filter(
(selector) =>
!cssRuleMatchesPrefixSelector(
{ selector: selector },
prefixSelector,
),
);
if (rules.length === 0) {
return;
}
cssRule.selector = rules
.map((cssSelector) =>
prefixWrapCSSSelector(
cssSelector,
cssRule,
nested,
ignoredSelectors,
prefixSelector,
prefixRootTags,
),
)
.filter(isValidCSSSelector)
.join(", ");
};
export const prefixWrapCSSSelector = (
cssSelector: string,
cssRule: PostCSSRule,
nested: string | null,
ignoredSelectors: (string | RegExp)[],
prefixSelector: string,
prefixRootTags: boolean,
): string | null => {
const cleanedSelector = cleanSelector(cssSelector);
if (cleanedSelector === "") {
return null;
}
// Don't prefix nested selected.
if (nested !== null && cleanedSelector.startsWith(nested, 0)) {
return cleanedSelector;
}
// Do not prefix keyframes rules.
if (isKeyframes(cssRule)) {
return cleanedSelector;
}
// Check for matching ignored selectors
if (
ignoredSelectors.some((currentValue) =>
cleanedSelector.match(currentValue),
)
) {
return cleanedSelector;
}
// Anything other than a root tag is always prefixed.
if (isNotRootTag(cleanedSelector)) {
return prefixSelector + " " + cleanedSelector;
}
// Handle special case where root tags should be converted into classes
// rather than being replaced.
if (prefixRootTags) {
return prefixSelector + " ." + cleanedSelector;
}
// HTML and Body elements cannot be contained within our container so lets
// extract their styles.
return cleanedSelector.replace(/^(body|html|:root)/, prefixSelector);
};