Przeglądaj źródła

remove invalid declarations

Gildas 7 lat temu
rodzic
commit
0a71537936
1 zmienionych plików z 25 dodań i 11 usunięć
  1. 25 11
      lib/single-file/css-matched-rules.js

+ 25 - 11
lib/single-file/css-matched-rules.js

@@ -24,7 +24,7 @@ this.matchedRules = this.matchedRules || (() => {
 
 	const MEDIA_ALL = "all";
 	const IGNORED_PSEUDO_ELEMENTS = ["after", "before", "first-letter", "first-line", "selection"];
-	const REGEXP_VENDOR_PSEUDO = /:-(ms|webkit|moz|o)-/;
+	const REGEXP_VENDOR_IDENTIFIER = /-(ms|webkit|moz|o)-/;
 	const DEBUG = false;
 
 	class MatchedRules {
@@ -45,7 +45,6 @@ this.matchedRules = this.matchedRules || (() => {
 				}
 				sheetIndex++;
 			});
-			styleElement.remove();
 			let startTime;
 			if (DEBUG) {
 				startTime = Date.now();
@@ -57,7 +56,8 @@ this.matchedRules = this.matchedRules || (() => {
 				startTime = Date.now();
 				log("  -- STARTED computeCascade");
 			}
-			computeCascade(this.mediaAllInfo, [], this.mediaAllInfo);
+			computeCascade(this.mediaAllInfo, [], this.mediaAllInfo, styleElement.sheet);
+			styleElement.remove();
 			if (DEBUG) {
 				log("  -- ENDED computeCascade", Date.now() - startTime);
 			}
@@ -124,7 +124,7 @@ this.matchedRules = this.matchedRules || (() => {
 			stylesheet.insertRule(selectorText + "{}");
 			stylesheet.deleteRule(0);
 		} catch (error) {
-			if (!selectorText.match(REGEXP_VENDOR_PSEUDO)) {
+			if (!selectorText.match(REGEXP_VENDOR_IDENTIFIER)) {
 				invalidSelector = true;
 			}
 		}
@@ -231,8 +231,8 @@ this.matchedRules = this.matchedRules || (() => {
 		elementInfo.push(selectorInfo);
 	}
 
-	function computeCascade(mediaInfo, parentMediaInfo, mediaAllInfo) {
-		mediaInfo.elements.forEach((elementInfo, element) => getStylesInfo(elementInfo, element).forEach((elementStyleInfo, styleName) => {
+	function computeCascade(mediaInfo, parentMediaInfo, mediaAllInfo, stylesheet) {
+		mediaInfo.elements.forEach((elementInfo, element) => getStylesInfo(elementInfo, stylesheet, element).forEach((elementStyleInfo, styleName) => {
 			if (elementStyleInfo.selectorInfo.ruleInfo || mediaInfo == mediaAllInfo) {
 				let info;
 				if (elementStyleInfo.selectorInfo.ruleInfo) {
@@ -258,21 +258,23 @@ this.matchedRules = this.matchedRules || (() => {
 			}
 		}));
 		delete mediaInfo.elements;
-		mediaInfo.medias.forEach(childMediaInfo => computeCascade(childMediaInfo, [mediaInfo, ...parentMediaInfo], mediaAllInfo));
+		mediaInfo.medias.forEach(childMediaInfo => computeCascade(childMediaInfo, [mediaInfo, ...parentMediaInfo], mediaAllInfo, stylesheet));
 	}
 
-	function getStylesInfo(elementInfo) {
+	function getStylesInfo(elementInfo, stylesheet/*, element */) {
 		const elementStylesInfo = new Map();
 		elementInfo.forEach(selectorInfo => {
 			if (selectorInfo.styleInfo) {
 				const cssStyle = selectorInfo.styleInfo.cssStyle;
 				cssStyle.children.forEach(declaration => {
-					const styleValue = cssTree.generate(declaration);
-					elementStylesInfo.set(declaration.property, { selectorInfo, styleValue, important: declaration.important });
+					if (declaration.type == "Declaration" && !invalidDeclaration(cssTree.generate(declaration), stylesheet)) {
+						const styleValue = cssTree.generate(declaration);
+						elementStylesInfo.set(declaration.property, { selectorInfo, styleValue, important: declaration.important });
+					}
 				});
 			} else {
 				selectorInfo.ruleInfo.cssRule.block.children.forEach(declaration => {
-					if (declaration.type == "Declaration") {
+					if (declaration.type == "Declaration" && !invalidDeclaration(cssTree.generate(declaration), stylesheet)) {
 						const styleValue = cssTree.generate(declaration.value);
 						const elementStyleInfo = elementStylesInfo.get(declaration.property);
 						if (styleValue.trim() && (!elementStyleInfo || (declaration.important && !elementStyleInfo.important))) {
@@ -285,6 +287,18 @@ this.matchedRules = this.matchedRules || (() => {
 		return elementStylesInfo;
 	}
 
+	function invalidDeclaration(declarationText, stylesheet) {
+		let invalidDeclaration;
+		stylesheet.insertRule("single-file-declaration { " + declarationText + "}");
+		if (!stylesheet.cssRules[0].style.length) {
+			if (!declarationText.match(REGEXP_VENDOR_IDENTIFIER)) {
+				invalidDeclaration = true;
+			}
+		}
+		stylesheet.deleteRule(0);
+		return invalidDeclaration;
+	}
+
 	function sortRules(media) {
 		media.elements.forEach(elementRules => elementRules.sort((ruleInfo1, ruleInfo2) =>
 			ruleInfo1.styleInfo && !ruleInfo2.styleInfo ? -1 :