@@ -26,35 +26,85 @@ public static async Task<string> GenerateAsync(IReadOnlyCollection<string>urls)
26
26
27
27
var usedCss = await page . EvaluateAsync < string [ ] > (
28
28
"""
29
- () => {
30
- const styleSheets = Array.from(document.styleSheets);
31
- const usedRules = new Set();
29
+ async () => {
30
+ const styleSheets = Array.from(document.styleSheets);
31
+ const usedRules = new Set();
32
+ const processedUrls = new Set();
32
33
33
- const viewportHeight = window.innerHeight;
34
- const elements = document.querySelectorAll('*');
35
- const aboveFold = Array.from(elements).filter(el => {
36
- const rect = el.getBoundingClientRect();
37
- return rect.top < viewportHeight;
38
- });
34
+ const viewportHeight = window.innerHeight;
35
+ const elements = document.querySelectorAll('*');
36
+ const aboveFold = Array.from(elements).filter(el => {
37
+ const rect = el.getBoundingClientRect();
38
+ return rect.top < viewportHeight;
39
+ });
39
40
40
- styleSheets.forEach(sheet => {
41
- try {
42
- Array.from(sheet.cssRules).forEach(rule => {
43
- if (rule.type === 1) {
44
- aboveFold.forEach(el => {
45
- if (el.matches(rule.selectorText)) {
46
- usedRules.add(rule.cssText);
47
- }
48
- });
49
- }
50
- });
51
- } catch (e) {
41
+ async function fetchExternalStylesheet(url) {
42
+ if (processedUrls.has(url)) return;
43
+ processedUrls.add(url);
44
+
45
+ try {
46
+ const response = await fetch(url);
47
+ const text = await response.text();
48
+ const blob = new Blob([text], { type: 'text/css' });
49
+ const styleSheet = new CSSStyleSheet();
50
+ await styleSheet.replace(text);
51
+ return styleSheet;
52
+ } catch (e) {
53
+ console.error('Failed to fetch:', url, e);
54
+ return null;
55
+ }
56
+ }
57
+
58
+ async function processStyleSheet(sheet) {
59
+ try {
60
+ if (sheet.href) {
61
+ const externalSheet = await fetchExternalStylesheet(sheet.href);
62
+ if (externalSheet) {
63
+ Array.from(externalSheet.cssRules).forEach(processRule);
52
64
}
53
- });
65
+ }
66
+
67
+ Array.from(sheet.cssRules).forEach(processRule);
68
+ } catch (e) {
69
+ if (sheet.href) {
70
+ console.error('CORS issue with:', sheet.href);
71
+ }
72
+ }
73
+ }
54
74
55
- return Array.from(usedRules);
75
+ function processRule(rule) {
76
+ switch (rule.type) {
77
+ case CSSRule.STYLE_RULE:
78
+ aboveFold.forEach(el => {
79
+ try {
80
+ if (el.matches(rule.selectorText)) {
81
+ usedRules.add(rule.cssText);
82
+ }
83
+ } catch (e) {}
84
+ });
85
+ break;
86
+ case CSSRule.MEDIA_RULE:
87
+ if (window.matchMedia(rule.conditionText).matches) {
88
+ Array.from(rule.cssRules).forEach(processRule);
89
+ }
90
+ break;
91
+ case CSSRule.IMPORT_RULE:
92
+ processStyleSheet(rule.styleSheet);
93
+ break;
94
+ case CSSRule.FONT_FACE_RULE:
95
+ case CSSRule.KEYFRAMES_RULE:
96
+ usedRules.add(rule.cssText);
97
+ break;
56
98
}
57
- """ ) ;
99
+ }
100
+
101
+ for (const sheet of styleSheets) {
102
+ await processStyleSheet(sheet);
103
+ }
104
+
105
+ return Array.from(usedRules);
106
+ }
107
+ """ ) ;
58
108
59
109
foreach ( var css in usedCss )
60
110
{
0 commit comments