mirror of
https://github.com/gorhill/uBlock.git
synced 2024-09-18 08:52:26 +02:00
replace csstext()
with more flexible/efficient matches-css()
This commit is contained in:
parent
1ca285f8bd
commit
a5a9e0ce7c
@ -117,7 +117,7 @@ var jobQueue = [
|
|||||||
{ t: 'css-csel', _0: [] } // to manually hide (not incremental)
|
{ t: 'css-csel', _0: [] } // to manually hide (not incremental)
|
||||||
];
|
];
|
||||||
|
|
||||||
var reParserEx = /:(?:csstext|has|style|xpath)\(.+?\)$/;
|
var reParserEx = /:(?:matches-css|has|style|xpath)\(.+?\)$/;
|
||||||
|
|
||||||
var allExceptions = Object.create(null);
|
var allExceptions = Object.create(null);
|
||||||
var allSelectors = Object.create(null);
|
var allSelectors = Object.create(null);
|
||||||
@ -172,7 +172,7 @@ var domFilterer = {
|
|||||||
// 2 = simple css selectors/hide
|
// 2 = simple css selectors/hide
|
||||||
// 3 = complex css selectors/hide
|
// 3 = complex css selectors/hide
|
||||||
// Custom jobs:
|
// Custom jobs:
|
||||||
// csstext/hide
|
// matches-css/hide
|
||||||
// has/hide
|
// has/hide
|
||||||
// xpath/hide
|
// xpath/hide
|
||||||
|
|
||||||
@ -200,10 +200,10 @@ var domFilterer = {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
sel0 = sel0.slice(0, sel0.length - sel1.length);
|
sel0 = sel0.slice(0, sel0.length - sel1.length);
|
||||||
if ( sel1.lastIndexOf(':csstext', 0) === 0 ) {
|
if ( sel1.lastIndexOf(':has', 0) === 0 ) {
|
||||||
this.jobQueue.push({ t: 'csstext-hide', raw: s, _0: sel0, _1: sel1.slice(9, -1) });
|
|
||||||
} else if ( sel1.lastIndexOf(':has', 0) === 0 ) {
|
|
||||||
this.jobQueue.push({ t: 'has-hide', raw: s, _0: sel0, _1: sel1.slice(5, -1) });
|
this.jobQueue.push({ t: 'has-hide', raw: s, _0: sel0, _1: sel1.slice(5, -1) });
|
||||||
|
} else if ( sel1.lastIndexOf(':matches-css', 0) === 0 ) {
|
||||||
|
this.jobQueue.push({ t: 'matches-css-hide', raw: s, _0: sel0, _1: sel1.slice(13, -1) });
|
||||||
} else if ( sel1.lastIndexOf(':style',0) === 0 ) {
|
} else if ( sel1.lastIndexOf(':style',0) === 0 ) {
|
||||||
this.job1._0.push(sel0 + ' { ' + sel1.slice(7, -1) + ' }');
|
this.job1._0.push(sel0 + ' { ' + sel1.slice(7, -1) + ' }');
|
||||||
this.job1._1 = undefined;
|
this.job1._1 = undefined;
|
||||||
@ -411,21 +411,6 @@ var domFilterer = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
runCSSTextJob: function(job, fn) {
|
|
||||||
var nodes = document.querySelectorAll(job._0),
|
|
||||||
i = nodes.length, node;
|
|
||||||
if ( i === 0 ) { return; }
|
|
||||||
if ( typeof job._1 === 'string' ) {
|
|
||||||
job._1 = new RegExp(job._1.replace(/\s*\*\s*/g, '.*?'));
|
|
||||||
}
|
|
||||||
while ( i-- ) {
|
|
||||||
node = nodes[i];
|
|
||||||
if ( job._1.test(window.getComputedStyle(node).cssText) ) {
|
|
||||||
fn(node, job);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
runHasJob: function(job, fn) {
|
runHasJob: function(job, fn) {
|
||||||
var nodes = document.querySelectorAll(job._0),
|
var nodes = document.querySelectorAll(job._0),
|
||||||
i = nodes.length, node;
|
i = nodes.length, node;
|
||||||
@ -437,6 +422,41 @@ var domFilterer = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
runMatchesCSSJob: function(job, fn) {
|
||||||
|
var nodes = document.querySelectorAll(job._0),
|
||||||
|
i = nodes.length;
|
||||||
|
if ( i === 0 ) { return; }
|
||||||
|
if ( typeof job._1 === 'string' ) {
|
||||||
|
var aa = job._1.split(/;(?:\s+|$)/),
|
||||||
|
j = aa.length,
|
||||||
|
dict = Object.create(null),
|
||||||
|
s, pos;
|
||||||
|
while ( j-- ) {
|
||||||
|
s = aa[j].trim();
|
||||||
|
if ( s === '' ) { continue; }
|
||||||
|
pos = s.indexOf(':');
|
||||||
|
if ( pos === -1 ) { continue; }
|
||||||
|
dict[s.slice(0, pos).trim()] = s.slice(pos + 1).trim();
|
||||||
|
}
|
||||||
|
job._1 = dict;
|
||||||
|
}
|
||||||
|
var node, match, style;
|
||||||
|
while ( i-- ) {
|
||||||
|
node = nodes[i];
|
||||||
|
style = window.getComputedStyle(node);
|
||||||
|
match = undefined;
|
||||||
|
for ( var prop in job._1 ) {
|
||||||
|
match = style[prop] === job._1[prop];
|
||||||
|
if ( match === false ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( match === true ) {
|
||||||
|
fn(node, job);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
runXpathJob: function(job, fn) {
|
runXpathJob: function(job, fn) {
|
||||||
if ( job._1 === undefined ) {
|
if ( job._1 === undefined ) {
|
||||||
job._1 = document.createExpression(job._0, null);
|
job._1 = document.createExpression(job._0, null);
|
||||||
@ -457,12 +477,12 @@ var domFilterer = {
|
|||||||
|
|
||||||
runJob: function(job, fn) {
|
runJob: function(job, fn) {
|
||||||
switch ( job.t ) {
|
switch ( job.t ) {
|
||||||
case 'csstext-hide':
|
|
||||||
this.runCSSTextJob(job, fn);
|
|
||||||
break;
|
|
||||||
case 'has-hide':
|
case 'has-hide':
|
||||||
this.runHasJob(job, fn);
|
this.runHasJob(job, fn);
|
||||||
break;
|
break;
|
||||||
|
case 'matches-css-hide':
|
||||||
|
this.runMatchesCSSJob(job, fn);
|
||||||
|
break;
|
||||||
case 'xpath-hide':
|
case 'xpath-hide':
|
||||||
this.runXpathJob(job, fn);
|
this.runXpathJob(job, fn);
|
||||||
break;
|
break;
|
||||||
|
@ -247,7 +247,7 @@ var FilterParser = function() {
|
|||||||
this.invalid = false;
|
this.invalid = false;
|
||||||
this.cosmetic = true;
|
this.cosmetic = true;
|
||||||
this.reScriptTagFilter = /^script:(contains|inject)\((.+?)\)$/;
|
this.reScriptTagFilter = /^script:(contains|inject)\((.+?)\)$/;
|
||||||
this.reNeedHostname = /^(?:.+?:csstext|.+?:has|:xpath)\(.+?\)$/;
|
this.reNeedHostname = /^(?:.+?:has|.+?:matches-css|:xpath)\(.+?\)$/;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -754,8 +754,8 @@ FilterContainer.prototype.isValidSelector = (function() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var reCSSTextSelector = /^(.+?):csstext\((.+?)\)$/;
|
|
||||||
var reHasSelector = /^(.+?):has\((.+?)\)$/;
|
var reHasSelector = /^(.+?):has\((.+?)\)$/;
|
||||||
|
var reMatchesCSSSelector = /^(.+?):matches-css\((.+?)\)$/;
|
||||||
var reXpathSelector = /^:xpath\((.+?)\)$/;
|
var reXpathSelector = /^:xpath\((.+?)\)$/;
|
||||||
var reStyleSelector = /^(.+?):style\((.+?)\)$/;
|
var reStyleSelector = /^(.+?):style\((.+?)\)$/;
|
||||||
var reStyleBad = /url\([^)]+\)/;
|
var reStyleBad = /url\([^)]+\)/;
|
||||||
@ -777,17 +777,17 @@ FilterContainer.prototype.isValidSelector = (function() {
|
|||||||
// We reach this point very rarely.
|
// We reach this point very rarely.
|
||||||
var matches;
|
var matches;
|
||||||
|
|
||||||
// Custom `:csstext`-based filter?
|
|
||||||
matches = reCSSTextSelector.exec(s);
|
|
||||||
if ( matches !== null ) {
|
|
||||||
return isValidCSSSelector(matches[1]);
|
|
||||||
}
|
|
||||||
// Future `:has`-based filter? If so, validate both parts of the whole
|
// Future `:has`-based filter? If so, validate both parts of the whole
|
||||||
// selector.
|
// selector.
|
||||||
matches = reHasSelector.exec(s);
|
matches = reHasSelector.exec(s);
|
||||||
if ( matches !== null ) {
|
if ( matches !== null ) {
|
||||||
return isValidCSSSelector(matches[1]) && isValidCSSSelector(matches[2]);
|
return isValidCSSSelector(matches[1]) && isValidCSSSelector(matches[2]);
|
||||||
}
|
}
|
||||||
|
// Custom `:matches-css`-based filter?
|
||||||
|
matches = reMatchesCSSSelector.exec(s);
|
||||||
|
if ( matches !== null ) {
|
||||||
|
return isValidCSSSelector(matches[1]);
|
||||||
|
}
|
||||||
// Custom `:xpath`-based filter?
|
// Custom `:xpath`-based filter?
|
||||||
matches = reXpathSelector.exec(s);
|
matches = reXpathSelector.exec(s);
|
||||||
if ( matches !== null ) {
|
if ( matches !== null ) {
|
||||||
|
Loading…
Reference in New Issue
Block a user