css-inline-stream
Version:
Inline CSS classes into styles from HTML streams
49 lines (42 loc) • 1.68 kB
JavaScript
module.exports = async function inlineCSSFromLinks(htmlString) {
// Regex to match link tags with rel="stylesheet"
const linkRegex =/<link\s+(?=[^>]*stylesheet)(?=[^>]*href\s*=\s*['"]([^'"]+)['"])[^>]*>/gi;
// Store all promises for CSS fetching
const cssPromises = [];
// Store link tags and their corresponding positions
const linkMatches = [];
// Find all link tags and create fetch promises
let match;
while ((match = linkRegex.exec(htmlString)) !== null) {
const [fullMatch, href] = match;
const cssPromise = fetch(href)
.then(response => {
if (!response.ok) {
throw new Error(`Failed to fetch CSS from ${href}: ${response.status}`);
}
return response.text();
})
.catch(error => {
console.error(error);
return ''; // Return empty string if fetch fails
});
cssPromises.push(cssPromise);
linkMatches.push({
fullMatch,
start: match.index,
end: match.index + fullMatch.length
});
}
console.error({linkMatches})
// Wait for all CSS content to be fetched
const cssContents = await Promise.all(cssPromises);
// Replace link tags with style tags, starting from the end to maintain indices
let resultHtml = htmlString;
for (let i = linkMatches.length - 1; i >= 0; i--) {
const { fullMatch, start, end } = linkMatches[i];
const cssContent = cssContents[i];
const styleTag = `<style>${cssContent}</style>`;
resultHtml = resultHtml.slice(0, start) + styleTag + resultHtml.slice(end);
}
return resultHtml;
}