forked from freeCodeCamp/freeCodeCamp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcss-help.ts
More file actions
119 lines (115 loc) · 3.87 KB
/
css-help.ts
File metadata and controls
119 lines (115 loc) · 3.87 KB
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
export interface ExtendedStyleRule extends CSSStyleRule {
isDeclaredAfter: (selector: string) => boolean;
}
interface ExtendedStyleDeclaration extends CSSStyleDeclaration {
getPropVal: (prop: string, strip?: boolean) => string;
}
const getIsDeclaredAfter = (styleRule: CSSStyleRule) => (selector: string) => {
const cssStyleRules = Array.from(
styleRule.parentStyleSheet?.cssRules || []
)?.filter(ele => ele.type === CSSRule.STYLE_RULE) as CSSStyleRule[];
const previousStyleRule = cssStyleRules.find(
ele => ele?.selectorText === selector
);
if (!previousStyleRule) return false;
const currPosition = Array.from(
styleRule.parentStyleSheet?.cssRules || []
).indexOf(styleRule);
const prevPosition = Array.from(
previousStyleRule?.parentStyleSheet?.cssRules || []
).indexOf(previousStyleRule);
return currPosition > prevPosition;
};
class CSSHelp {
doc: HTMLDocument;
constructor(doc: HTMLDocument) {
this.doc = doc;
}
private _getStyleRules() {
const styleSheet = this.getStyleSheet();
return this.styleSheetToCssRulesArray(styleSheet).filter(
ele => ele.type === CSSRule.STYLE_RULE
) as CSSStyleRule[];
}
getStyleDeclarations(selector: string): CSSStyleDeclaration[] {
return this._getStyleRules()
?.filter(ele => ele?.selectorText === selector)
.map(x => x.style);
}
getStyle(selector: string): ExtendedStyleDeclaration | null {
const style = this._getStyleRules().find(
ele => ele?.selectorText === selector
)?.style as ExtendedStyleDeclaration | undefined;
if (!style) return null;
style.getPropVal = (prop: string, strip = false) => {
return strip
? style.getPropertyValue(prop).replace(/\s+/g, '')
: style.getPropertyValue(prop);
};
return style;
}
getStyleRule(selector: string): ExtendedStyleRule | null {
const styleRule = this._getStyleRules()?.find(
ele => ele?.selectorText === selector
);
if (styleRule) {
return {
...styleRule,
isDeclaredAfter: (selector: string) =>
getIsDeclaredAfter(styleRule)(selector)
};
} else {
return null;
}
}
getCSSRules(element?: string): CSSRule[] {
const styleSheet = this.getStyleSheet();
const cssRules = this.styleSheetToCssRulesArray(styleSheet);
switch (element) {
case 'media':
return cssRules.filter(ele => ele.type === CSSRule.MEDIA_RULE);
case 'fontface':
return cssRules.filter(ele => ele.type === CSSRule.FONT_FACE_RULE);
case 'import':
return cssRules.filter(ele => ele.type === CSSRule.IMPORT_RULE);
case 'keyframes':
return cssRules.filter(ele => ele.type === CSSRule.KEYFRAMES_RULE);
default:
return cssRules;
}
}
isPropertyUsed(property: string): boolean {
return this._getStyleRules().some(ele =>
ele.style?.getPropertyValue(property)
);
}
getRuleListsWithinMedia(mediaText: string): CSSStyleRule[] {
const medias = this.getCSSRules('media') as CSSMediaRule[];
const cond = medias?.find(x => x?.media?.mediaText === mediaText);
const cssRules = cond?.cssRules;
return Array.from(cssRules || []) as CSSStyleRule[];
}
getStyleSheet(): CSSStyleSheet | null {
// TODO: Change selector to match exactly 'styles.css'
const link: HTMLLinkElement | null = this.doc?.querySelector(
"link[href*='styles']"
);
// Most* browser extensions inject styles with class/media attributes
const style: HTMLStyleElement | null = this.doc?.querySelector(
'style:not([class]):not([media])'
);
if (link?.sheet?.cssRules?.length) {
return link.sheet;
} else if (style) {
return style.sheet;
} else {
return null;
}
}
styleSheetToCssRulesArray(
styleSheet: ReturnType<CSSHelp['getStyleSheet']>
): CSSRule[] {
return Array.from(styleSheet?.cssRules || []);
}
}
export default CSSHelp;