|
|
@@ -29,14 +29,15 @@ this.RulesMatcher = this.RulesMatcher || (() => {
|
|
|
constructor(doc) {
|
|
|
this.doc = doc;
|
|
|
this.mediaAllInfo = createMediaInfo(MEDIA_ALL);
|
|
|
+ const matchedElementsCache = new Map();
|
|
|
doc.querySelectorAll("style").forEach((styleElement, styleIndex) => {
|
|
|
if (styleElement.sheet) {
|
|
|
if (styleElement.media && styleElement.media != MEDIA_ALL) {
|
|
|
const mediaInfo = createMediaInfo(styleElement.media);
|
|
|
this.mediaAllInfo.medias.set(styleElement.media, mediaInfo);
|
|
|
- getMatchedElementsRules(doc, styleElement.sheet.cssRules, mediaInfo, styleIndex);
|
|
|
+ getMatchedElementsRules(doc, styleElement.sheet.cssRules, mediaInfo, styleIndex, matchedElementsCache);
|
|
|
} else {
|
|
|
- getMatchedElementsRules(doc, styleElement.sheet.cssRules, this.mediaAllInfo, styleIndex);
|
|
|
+ getMatchedElementsRules(doc, styleElement.sheet.cssRules, this.mediaAllInfo, styleIndex, matchedElementsCache);
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
@@ -59,18 +60,18 @@ this.RulesMatcher = this.RulesMatcher || (() => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- function getMatchedElementsRules(doc, cssRules, mediaInfo, sheetIndex) {
|
|
|
+ function getMatchedElementsRules(doc, cssRules, mediaInfo, sheetIndex, matchedElementsCache) {
|
|
|
Array.from(cssRules).forEach((cssRule, ruleIndex) => {
|
|
|
if (cssRule.type == CSSRule.MEDIA_RULE) {
|
|
|
const ruleMediaInfo = createMediaInfo(cssRule.media);
|
|
|
mediaInfo.medias.set(cssRule.media, ruleMediaInfo);
|
|
|
- getMatchedElementsRules(doc, cssRule.cssRules, ruleMediaInfo, sheetIndex);
|
|
|
+ getMatchedElementsRules(doc, cssRule.cssRules, ruleMediaInfo, sheetIndex, matchedElementsCache);
|
|
|
} else if (cssRule.type == CSSRule.STYLE_RULE) {
|
|
|
if (cssRule.selectorText) {
|
|
|
try {
|
|
|
let selectors = cssWhat.parse(cssRule.selectorText);
|
|
|
const selectorsText = selectors.map(selector => cssWhat.stringify([selector]));
|
|
|
- selectors.forEach(selector => getMatchedElementsSelector(doc, cssRule, selector, selectorsText, mediaInfo, ruleIndex, sheetIndex));
|
|
|
+ selectors.forEach(selector => getMatchedElementsSelector(doc, cssRule, selector, selectorsText, mediaInfo, ruleIndex, sheetIndex, matchedElementsCache));
|
|
|
} catch (error) {
|
|
|
/* ignored */
|
|
|
}
|
|
|
@@ -79,9 +80,13 @@ this.RulesMatcher = this.RulesMatcher || (() => {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- function getMatchedElementsSelector(doc, cssRule, selector, selectorsText, mediaInfo, ruleIndex, sheetIndex) {
|
|
|
+ function getMatchedElementsSelector(doc, cssRule, selector, selectorsText, mediaInfo, ruleIndex, sheetIndex, matchedElementsCache) {
|
|
|
const selectorText = cssWhat.stringify([selector]);
|
|
|
- const matchedElements = doc.querySelectorAll(selectorText);
|
|
|
+ let matchedElements = matchedElementsCache.get(selectorText);
|
|
|
+ if (!matchedElements) {
|
|
|
+ matchedElements = doc.querySelectorAll(selectorText);
|
|
|
+ matchedElementsCache.set(selectorText, matchedElements);
|
|
|
+ }
|
|
|
if (matchedElements.length) {
|
|
|
matchedElements.forEach(element => {
|
|
|
let elementInfo;
|