var links = document.querySelectorAll(`link[rel="stylesheet"][media="async"], link[rel="async-styles"]`); for (var link of links) { var resolved = new URL(link.href, window.location); var processed = await getSheet(resolved.toString()); var style = document.createElement("style"); var constructed = new CSSStyleSheet(); var output = serializeCSS(processed); constructed.replaceSync(output); // console.log(output); document.adoptedStyleSheets.push(constructed); } function serializeCSS(sheet) { var output = ""; for (var rule of Array.from(sheet.cssRules)) { output += rule.cssText + "\n"; } return output; } async function getSheet(url, cache = new Set()) { if (cache.has(url)) { console.log(`Skipping import for ${url}, already loaded elsewhere`); return { cssRules: [], url } } cache.add(url); var response = await fetch(url); var text = await response.text(); var sheet = parseSheet(text); sheet.url = url; var processed = await processSheet(sheet, cache); return processed; } function parseSheet(text) { var parser = new DOMParser(); var html = parser.parseFromString(``, "text/html"); var style = html.querySelector("style"); return style.sheet; } async function processSheet(stylesheet, cache) { for (var i = 0; i < stylesheet.cssRules.length; i++) { var rule = stylesheet.cssRules[i]; if (rule instanceof CSSImportRule) { stylesheet.deleteRule(i); var resolved = new URL(rule.href, stylesheet.url).toString(); var imported = await getSheet(resolved, cache); for (var j = imported.cssRules.length - 1; j >= 0; j--) { var insert = imported.cssRules[j]; stylesheet.insertRule(insert.cssText, i); } i += imported.cssRules.length; } } return stylesheet; }