|
@@ -34,9 +34,9 @@ this.RulesMatcher = this.RulesMatcher || (() => {
|
|
|
if (styleElement.media && styleElement.media != MEDIA_ALL) {
|
|
if (styleElement.media && styleElement.media != MEDIA_ALL) {
|
|
|
const mediaInfo = createMediaInfo(styleElement.media);
|
|
const mediaInfo = createMediaInfo(styleElement.media);
|
|
|
this.mediaAllInfo.medias.set(styleElement.media, mediaInfo);
|
|
this.mediaAllInfo.medias.set(styleElement.media, mediaInfo);
|
|
|
- getMatchedElements(doc, styleElement.sheet.cssRules, mediaInfo, styleIndex);
|
|
|
|
|
|
|
+ getMatchedElementsRules(doc, styleElement.sheet.cssRules, mediaInfo, styleIndex);
|
|
|
} else {
|
|
} else {
|
|
|
- getMatchedElements(doc, styleElement.sheet.cssRules, this.mediaAllInfo, styleIndex);
|
|
|
|
|
|
|
+ getMatchedElementsRules(doc, styleElement.sheet.cssRules, this.mediaAllInfo, styleIndex);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
@@ -53,79 +53,58 @@ this.RulesMatcher = this.RulesMatcher || (() => {
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- function getMatchedElements(doc, cssRules, mediaInfo, sheetIndex) {
|
|
|
|
|
|
|
+ function getMatchedElementsRules(doc, cssRules, mediaInfo, sheetIndex) {
|
|
|
Array.from(cssRules).forEach((cssRule, ruleIndex) => {
|
|
Array.from(cssRules).forEach((cssRule, ruleIndex) => {
|
|
|
if (cssRule.type == CSSRule.MEDIA_RULE) {
|
|
if (cssRule.type == CSSRule.MEDIA_RULE) {
|
|
|
const ruleMediaInfo = createMediaInfo(cssRule.media);
|
|
const ruleMediaInfo = createMediaInfo(cssRule.media);
|
|
|
mediaInfo.medias.set(cssRule.media, ruleMediaInfo);
|
|
mediaInfo.medias.set(cssRule.media, ruleMediaInfo);
|
|
|
- getMatchedElements(doc, cssRule.cssRules, ruleMediaInfo, sheetIndex);
|
|
|
|
|
|
|
+ getMatchedElementsRules(doc, cssRule.cssRules, ruleMediaInfo, sheetIndex);
|
|
|
} else if (cssRule.type == CSSRule.STYLE_RULE) {
|
|
} else if (cssRule.type == CSSRule.STYLE_RULE) {
|
|
|
if (cssRule.selectorText) {
|
|
if (cssRule.selectorText) {
|
|
|
let selectors = cssWhat.parse(cssRule.selectorText);
|
|
let selectors = cssWhat.parse(cssRule.selectorText);
|
|
|
const selectorsText = selectors.map(selector => cssWhat.stringify([selector]));
|
|
const selectorsText = selectors.map(selector => cssWhat.stringify([selector]));
|
|
|
- selectors.forEach((selector) => {
|
|
|
|
|
- const selectorText = cssWhat.stringify([selector]);
|
|
|
|
|
- const matchedElements = doc.querySelectorAll(selectorText);
|
|
|
|
|
- if (matchedElements.length) {
|
|
|
|
|
- matchedElements.forEach(element => {
|
|
|
|
|
- let elementInfo;
|
|
|
|
|
- if (mediaInfo.elements.has(element)) {
|
|
|
|
|
- elementInfo = mediaInfo.elements.get(element);
|
|
|
|
|
- } else {
|
|
|
|
|
- elementInfo = [];
|
|
|
|
|
- const elementStyle = element.getAttribute("style");
|
|
|
|
|
- if (elementStyle) {
|
|
|
|
|
- elementInfo.push({ cssStyle: element.style });
|
|
|
|
|
- }
|
|
|
|
|
- mediaInfo.elements.set(element, elementInfo);
|
|
|
|
|
- }
|
|
|
|
|
- const specificity = computeSpecificity(selector);
|
|
|
|
|
- specificity.ruleIndex = ruleIndex;
|
|
|
|
|
- specificity.sheetIndex = sheetIndex;
|
|
|
|
|
- let ruleInfo = elementInfo.find(ruleInfo => ruleInfo.cssRule == cssRule);
|
|
|
|
|
- if (ruleInfo) {
|
|
|
|
|
- if (compareSpecificity(ruleInfo.specificity, specificity)) {
|
|
|
|
|
- ruleInfo.specificity = specificity;
|
|
|
|
|
- ruleInfo.selectorText = selectorText;
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- ruleInfo = { cssRule, specificity, selectorText, selectorsText };
|
|
|
|
|
- elementInfo.push(ruleInfo);
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ selectors.forEach(selector => getMatchedElementsSelector(doc, cssRule, selector, selectorsText, mediaInfo, ruleIndex, sheetIndex));
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- function computeCascade(mediaInfo, parentMediaInfos = []) {
|
|
|
|
|
- mediaInfo.elements.forEach((elementInfo) => {
|
|
|
|
|
- const elementStylesInfo = new Map();
|
|
|
|
|
- elementInfo.forEach(ruleInfo => {
|
|
|
|
|
- if (ruleInfo.cssStyle) {
|
|
|
|
|
- const cssStyle = ruleInfo.cssStyle;
|
|
|
|
|
- const stylesInfo = parseCss.parseAListOfDeclarations(cssStyle.cssText);
|
|
|
|
|
- stylesInfo.forEach(styleInfo => {
|
|
|
|
|
- const important = cssStyle.getPropertyPriority(styleInfo.name) == PRIORITY_IMPORTANT;
|
|
|
|
|
- const styleValue = cssStyle.getPropertyValue(styleInfo.name) + (important ? " !" + PRIORITY_IMPORTANT : "");
|
|
|
|
|
- elementStylesInfo.set(styleInfo.name, { styleValue, cssStyle: ruleInfo.cssStyle });
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ function getMatchedElementsSelector(doc, cssRule, selector, selectorsText, mediaInfo, ruleIndex, sheetIndex) {
|
|
|
|
|
+ const selectorText = cssWhat.stringify([selector]);
|
|
|
|
|
+ const matchedElements = doc.querySelectorAll(selectorText);
|
|
|
|
|
+ if (matchedElements.length) {
|
|
|
|
|
+ matchedElements.forEach(element => {
|
|
|
|
|
+ let elementInfo;
|
|
|
|
|
+ if (mediaInfo.elements.has(element)) {
|
|
|
|
|
+ elementInfo = mediaInfo.elements.get(element);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ elementInfo = [];
|
|
|
|
|
+ const elementStyle = element.getAttribute("style");
|
|
|
|
|
+ if (elementStyle) {
|
|
|
|
|
+ elementInfo.push({ cssStyle: element.style });
|
|
|
|
|
+ }
|
|
|
|
|
+ mediaInfo.elements.set(element, elementInfo);
|
|
|
|
|
+ }
|
|
|
|
|
+ const specificity = computeSpecificity(selector);
|
|
|
|
|
+ specificity.ruleIndex = ruleIndex;
|
|
|
|
|
+ specificity.sheetIndex = sheetIndex;
|
|
|
|
|
+ let ruleInfo = elementInfo.find(ruleInfo => ruleInfo.cssRule == cssRule);
|
|
|
|
|
+ if (ruleInfo) {
|
|
|
|
|
+ if (compareSpecificity(ruleInfo.specificity, specificity)) {
|
|
|
|
|
+ ruleInfo.specificity = specificity;
|
|
|
|
|
+ ruleInfo.selectorText = selectorText;
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
- const cssStyle = ruleInfo.cssRule.style;
|
|
|
|
|
- const stylesInfo = parseCss.parseAListOfDeclarations(cssStyle.cssText);
|
|
|
|
|
- stylesInfo.forEach(styleInfo => {
|
|
|
|
|
- const important = cssStyle.getPropertyPriority(styleInfo.name) == PRIORITY_IMPORTANT;
|
|
|
|
|
- const styleValue = cssStyle.getPropertyValue(styleInfo.name) + (important ? " !" + PRIORITY_IMPORTANT : "");
|
|
|
|
|
- let elementStyleInfo = elementStylesInfo.get(styleInfo.name);
|
|
|
|
|
- if (!elementStyleInfo || (important && !elementStyleInfo.important)) {
|
|
|
|
|
- elementStylesInfo.set(styleInfo.name, { styleValue, cssRule: ruleInfo.cssRule, selectorText: ruleInfo.selectorText, selectorsText: ruleInfo.selectorsText });
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ ruleInfo = { cssRule, specificity, selectorText, selectorsText };
|
|
|
|
|
+ elementInfo.push(ruleInfo);
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
- elementStylesInfo.forEach((elementStyleInfo, styleName) => {
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function computeCascade(mediaInfo, parentMediaInfos = []) {
|
|
|
|
|
+ mediaInfo.elements.forEach((elementInfo) => {
|
|
|
|
|
+ getStylesInfo(elementInfo).forEach((elementStyleInfo, styleName) => {
|
|
|
let ruleInfo, ascendantMedia, allMedia;
|
|
let ruleInfo, ascendantMedia, allMedia;
|
|
|
if (elementStyleInfo.cssRule) {
|
|
if (elementStyleInfo.cssRule) {
|
|
|
ascendantMedia = [mediaInfo, ...parentMediaInfos].find(media => media.rules.get(elementStyleInfo.cssRule)) || mediaInfo;
|
|
ascendantMedia = [mediaInfo, ...parentMediaInfos].find(media => media.rules.get(elementStyleInfo.cssRule)) || mediaInfo;
|
|
@@ -153,6 +132,33 @@ this.RulesMatcher = this.RulesMatcher || (() => {
|
|
|
mediaInfo.medias.forEach(childMediaInfo => computeCascade(childMediaInfo, [mediaInfo, ...parentMediaInfos]));
|
|
mediaInfo.medias.forEach(childMediaInfo => computeCascade(childMediaInfo, [mediaInfo, ...parentMediaInfos]));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ function getStylesInfo(elementInfo) {
|
|
|
|
|
+ const elementStylesInfo = new Map();
|
|
|
|
|
+ elementInfo.forEach(ruleInfo => {
|
|
|
|
|
+ if (ruleInfo.cssStyle) {
|
|
|
|
|
+ const cssStyle = ruleInfo.cssStyle;
|
|
|
|
|
+ const stylesInfo = parseCss.parseAListOfDeclarations(cssStyle.cssText);
|
|
|
|
|
+ stylesInfo.forEach(styleInfo => {
|
|
|
|
|
+ const important = cssStyle.getPropertyPriority(styleInfo.name) == PRIORITY_IMPORTANT;
|
|
|
|
|
+ const styleValue = cssStyle.getPropertyValue(styleInfo.name) + (important ? " !" + PRIORITY_IMPORTANT : "");
|
|
|
|
|
+ elementStylesInfo.set(styleInfo.name, { styleValue, cssStyle: ruleInfo.cssStyle });
|
|
|
|
|
+ });
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const cssStyle = ruleInfo.cssRule.style;
|
|
|
|
|
+ const stylesInfo = parseCss.parseAListOfDeclarations(cssStyle.cssText);
|
|
|
|
|
+ stylesInfo.forEach(styleInfo => {
|
|
|
|
|
+ const important = cssStyle.getPropertyPriority(styleInfo.name) == PRIORITY_IMPORTANT;
|
|
|
|
|
+ const styleValue = cssStyle.getPropertyValue(styleInfo.name) + (important ? " !" + PRIORITY_IMPORTANT : "");
|
|
|
|
|
+ let elementStyleInfo = elementStylesInfo.get(styleInfo.name);
|
|
|
|
|
+ if (!elementStyleInfo || (important && !elementStyleInfo.important)) {
|
|
|
|
|
+ elementStylesInfo.set(styleInfo.name, { styleValue, cssRule: ruleInfo.cssRule, selectorText: ruleInfo.selectorText, selectorsText: ruleInfo.selectorsText });
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ return elementStylesInfo;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
function createMediaInfo(media) {
|
|
function createMediaInfo(media) {
|
|
|
const mediaInfo = { media: media, elements: new Map(), medias: new Map(), rules: new Map() };
|
|
const mediaInfo = { media: media, elements: new Map(), medias: new Map(), rules: new Map() };
|
|
|
if (media == MEDIA_ALL) {
|
|
if (media == MEDIA_ALL) {
|