Răsfoiți Sursa

improved stylesheet processing

Gildas 7 ani în urmă
părinte
comite
56dfb7fc28
1 a modificat fișierele cu 34 adăugiri și 35 ștergeri
  1. 34 35
      lib/single-file/single-file-core.js

+ 34 - 35
lib/single-file/single-file-core.js

@@ -1034,65 +1034,64 @@ this.SingleFileCore = this.SingleFileCore || (() => {
 		}
 
 		static async processStylesheet(doc, stylesheetContent, cssRules, baseURI, options, batchRequest) {
-			let sheetContent = "", variablesInfo = { index: 0, cssText: "" };
-			const urlFunctions = DomUtil.getUrlFunctions(stylesheetContent);
-			const resourceInfos = new Map();
-			await Promise.all(urlFunctions.map(async urlFunction => {
+			const urlFunctions = getURLFunctions(cssRules);
+			const styleResources = Promise.all(urlFunctions.style.map(urlFunction => processURLFunction(urlFunction, true)));
+			const otherResources = Promise.all(urlFunctions.other.map(urlFunction => processURLFunction(urlFunction, false)));
+			await Promise.all([styleResources, otherResources]);
+			return stylesheetContent;
+
+			async function processURLFunction(urlFunction, groupDuplicates) {
 				const originalResourceURL = DomUtil.matchURL(urlFunction);
 				const resourceURL = DomUtil.normalizeURL(originalResourceURL);
 				if (!DomUtil.testIgnoredPath(resourceURL)) {
-					if (DomUtil.testValidURL(resourceURL, baseURI, options.url) && stylesheetContent.includes(urlFunction)) {
+					if (DomUtil.testValidURL(resourceURL, baseURI, options.url)) {
 						const { content, indexResource, duplicate } = await batchRequest.addURL(resourceURL);
-						urlFunction = "url(" + JSON.stringify(originalResourceURL) + ")";
-						const regExpUrlFunction = DomUtil.getRegExp(urlFunction);
-						if (duplicate && options.groupDuplicateImages) {
-							resourceInfos.set(resourceURL, { regExpUrlFunction, indexResource, dataURI: content, variableName: "var(" + SINGLE_FILE_VARIABLE_NAME_PREFIX + indexResource + ")" });
-						} else {
-							resourceInfos.set(resourceURL, { regExpUrlFunction, indexResource, dataURI: content });
+						let regExpUrlFunction = DomUtil.getRegExp(urlFunction);
+						if (!stylesheetContent.match(regExpUrlFunction)) {
+							urlFunction = "url(" + originalResourceURL + ")";
+							regExpUrlFunction = DomUtil.getRegExp(urlFunction);
+						}
+						if (!stylesheetContent.match(regExpUrlFunction)) {
+							urlFunction = "url('" + originalResourceURL + "')";
+							regExpUrlFunction = DomUtil.getRegExp(urlFunction);
+						}
+						if (stylesheetContent.match(regExpUrlFunction)) {
+							if (duplicate && options.groupDuplicateImages && groupDuplicates) {
+								stylesheetContent = stylesheetContent.replace(regExpUrlFunction, "var(" + SINGLE_FILE_VARIABLE_NAME_PREFIX + indexResource + ")");
+								DomUtil.insertVariable(doc, indexResource, content, options);
+							} else {
+								stylesheetContent = stylesheetContent.replace(regExpUrlFunction, urlFunction.replace(originalResourceURL, content));
+							}
 						}
 					}
 				}
-			}));
-			const rulesContent = processRules(cssRules);
-			if (variablesInfo.cssText) {
-				sheetContent += ":root{" + variablesInfo.cssText + "}";
 			}
-			return sheetContent + rulesContent;
 
-			function processRules(cssRules) {
-				let rulesContent = "";
+			function getURLFunctions(cssRules, urlFunctions = { style: new Set(), other: new Set() }) {
 				Array.from(cssRules).forEach(cssRule => {
 					if (cssRule.type == CSSRule.MEDIA_RULE) {
-						const mediaRulesContent = processRules(cssRule.cssRules);
-						rulesContent += "@media " + Array.from(cssRule.media).join(",") + "{" + mediaRulesContent + "}";
+						getURLFunctions(cssRule.cssRules, urlFunctions);
 					} else if (cssRule.type == CSSRule.STYLE_RULE) {
-						rulesContent += processURLFunctions(cssRule.cssText);
+						getURLFunctionsRule(cssRule.cssText, urlFunctions.style);
 					} else {
-
-						rulesContent += processURLFunctions(cssRule.cssText, true);
+						getURLFunctionsRule(cssRule.cssText, urlFunctions.other);
 					}
 				});
-				return rulesContent;
+				return { style: Array.from(urlFunctions.style), other: Array.from(urlFunctions.other) };
 			}
 
-			function processURLFunctions(cssText, preventGrouping) {
-				const urlFunctions = DomUtil.getUrlFunctions(cssText);
-				urlFunctions.forEach(urlFunction => {
+			function getURLFunctionsRule(cssText, urlFunctions) {
+				const urlFunctionsRule = DomUtil.getUrlFunctions(cssText);
+				urlFunctionsRule.forEach(urlFunction => {
 					const originalResourceURL = DomUtil.matchURL(urlFunction);
 					const resourceURL = DomUtil.normalizeURL(originalResourceURL);
 					if (!DomUtil.testIgnoredPath(resourceURL)) {
 						if (DomUtil.testValidURL(resourceURL, baseURI, options.url) && cssText.includes(urlFunction)) {
-							const resourceInfo = resourceInfos.get(resourceURL);
-							if (options.groupDuplicateImages && resourceInfo.variableName && !preventGrouping) {
-								cssText = cssText.replace(resourceInfo.regExpUrlFunction, resourceInfo.variableName);
-								DomUtil.insertVariable(doc, resourceInfo.indexResource, resourceInfo.dataURI, options);
-							} else {
-								cssText = cssText.replace(resourceInfo.regExpUrlFunction, urlFunction.replace(originalResourceURL, resourceInfo.dataURI));
-							}
+							urlFunctions.add(urlFunction);
 						}
 					}
 				});
-				return cssText;
+				return urlFunctions;
 			}
 		}