-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
documentHasStyleSheet.mjs
58 lines (52 loc) · 2.13 KB
/
documentHasStyleSheet.mjs
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
// @ts-check
/**
* Checks if the document has a style sheet that finished loading (successfully
* or not). This is not intended to detect pending or in progress reloading.
* It’s possible for the document to have multiple style sheets with the same
* `href`; if any are loaded the CSS is considered loaded.
* @param {string} href CSS URL that’s absolute or relative to the
* `document.baseURI`.
* @returns {boolean} Is the CSS loaded.
*/
export default function documentHasStyleSheet(href) {
if (typeof href !== "string") {
throw new TypeError("Argument 1 `href` must be a string.");
}
/** CSS absolute URL. */
const url = new URL(href, document.baseURI).href;
for (const cssStyleSheet of document.styleSheets) {
if (cssStyleSheet.href === url) {
// Note that reading the rules errors if the style sheet is cross-domain
// and it’s `link` element doesn’t have `crossorigin="anonymous"`.
// Apparently the rules can be read without error for unparsable CSS.
if (cssStyleSheet.cssRules.length) return true;
else {
// Possible reasons for no style sheet rules:
//
// 1. Loading isn’t done.
// 2. Network error.
// 3. Unparsable CSS.
// 4. Really it has none.
//
// Reason 1 can be identified if the CSS request started and the
// response hasn’t ended yet. Note that the CSS could be falsely
// considered not loaded if its performance resource timing data was
// cleared, e.g. because the entry limit was exceeded or via
// `performance.clearResourceTimings()`. It’s also assumed this data
// isn’t affected by browser private mode, etc.
const entries = /** @type {Array<PerformanceResourceTiming>} */ (
performance.getEntriesByName(url, "resource")
);
if (
entries.length &&
// Apparently `responseEnd` doesn’t just relate to a server response;
// it will be present if a network error ended the request.
entries[entries.length - 1].responseEnd
) {
return true;
}
}
}
}
return false;
}