-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathCssCustomProperties.ts
More file actions
130 lines (116 loc) · 4.71 KB
/
CssCustomProperties.ts
File metadata and controls
130 lines (116 loc) · 4.71 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
120
121
122
123
124
125
126
127
128
129
130
/**
* Based on CSS Tricks tutorial.
* @see https://css-tricks.com/how-to-get-all-custom-properties-on-a-page-in-javascript/
*/
type AllowedCSSRule = CSSStyleRule | CSSPageRule; // they have necessary `selectorText` and `style` properties
interface getLocalCssStyleRulesProps {
cssRuleType?: "CSSStyleRule";
selectorText?: string;
}
interface getLocalCssStyleRulePropertiesProps extends getLocalCssStyleRulesProps {
propertyType?: "all" | "normal" | "custom";
}
interface getCustomPropertiesProps extends getLocalCssStyleRulesProps {
filterName?: (name: string) => boolean;
removeDashPrefix?: boolean;
returnObject?: boolean;
}
export default class CssCustomProperties {
getterDefaultProps = {} as getCustomPropertiesProps;
customprops = {};
constructor(props: getCustomPropertiesProps = {}) {
this.getterDefaultProps = props;
}
// Methods
customProperties = (props: getCustomPropertiesProps = {}): [string, string][] | Record<string, string> => {
// FIXME:
// in case of performance issues results should get saved at least into intern variables
// other cache strategies could be also tested
if (Object.keys(this.customprops).length > 1) {
return this.customprops;
}
const customprops = CssCustomProperties.listCustomProperties({
...this.getterDefaultProps,
...props,
});
this.customprops = customprops;
return customprops;
};
static listLocalStylesheets = (): CSSStyleSheet[] => {
if (document && document.styleSheets) {
return (Array.from(document.styleSheets) as CSSStyleSheet[]).filter((stylesheet) => {
// is inline stylesheet or from same domain
if (!stylesheet.href) {
return true;
}
return stylesheet.href.indexOf(window.location.origin) === 0;
});
}
return [] as CSSStyleSheet[];
};
static listLocalCssRules = (): CSSRule[] => {
return CssCustomProperties.listLocalStylesheets()
.map((stylesheet) => {
return Array.from(stylesheet.cssRules);
})
.flat();
};
static listLocalCssStyleRules = (filter: getLocalCssStyleRulesProps = {}): CSSStyleRule[] => {
const { cssRuleType = "CSSStyleRule", selectorText } = filter;
const cssStyleRules = CssCustomProperties.listLocalCssRules().filter((rule) => {
const cssrule = rule as AllowedCSSRule;
if (cssrule.style) {
if (cssrule.constructor.name !== cssRuleType) {
return false;
}
if (!!selectorText && cssrule.selectorText !== selectorText) {
return false;
}
return true;
} else {
return false;
}
});
return cssStyleRules as CSSStyleRule[];
};
static listLocalCssStyleRuleProperties = (filter: getLocalCssStyleRulePropertiesProps = {}): string[][] => {
const { propertyType = "all", ...otherFilters } = filter;
return CssCustomProperties.listLocalCssStyleRules(otherFilters)
.map((cssrule) => {
return [...(cssrule as CSSStyleRule).style].map((propertyname) => {
return [propertyname.trim(), (cssrule as CSSStyleRule).style.getPropertyValue(propertyname).trim()];
});
})
.flat()
.filter((declaration) => {
switch (propertyType) {
case "normal":
return declaration[0].indexOf("--") !== 0;
case "custom":
return declaration[0].indexOf("--") === 0;
}
return true; // case "all"
});
};
static listCustomProperties = (
props: getCustomPropertiesProps = {}
): [string, string][] | Record<string, string> => {
const { removeDashPrefix = true, returnObject = true, filterName = () => true, ...filterProps } = props;
const customProperties = CssCustomProperties.listLocalCssStyleRuleProperties({
...filterProps,
propertyType: "custom",
})
.filter((declaration) => {
return filterName(declaration[0]);
})
.map((declaration) => {
if (removeDashPrefix) {
return [declaration[0].substr(2), declaration[1]];
}
return declaration;
});
return returnObject
? (Object.fromEntries(customProperties) as Record<string, string>)
: (customProperties as [string, string][]);
};
}