mirror of
https://github.com/gorhill/uBlock.git
synced 2024-09-15 07:22:28 +02:00
fix #781: support for explicit style properties
This commit is contained in:
parent
09d35b65e0
commit
3752ac4880
@ -66,6 +66,7 @@ vAPI.domFilterer = {
|
||||
hiddenId: String.fromCharCode(Date.now() % 26 + 97) + Math.floor(Math.random() * 982451653 + 982451653).toString(36),
|
||||
hiddenNodeCount: 0,
|
||||
matchesProp: vAPI.matchesProp,
|
||||
newCSSRules: [],
|
||||
newDeclarativeSelectors: [],
|
||||
shadowId: String.fromCharCode(Date.now() % 26 + 97) + Math.floor(Math.random() * 982451653 + 982451653).toString(36),
|
||||
styleTags: [],
|
||||
@ -94,33 +95,14 @@ vAPI.domFilterer = {
|
||||
}
|
||||
},
|
||||
|
||||
addHasSelector: function(s1, s2) {
|
||||
var entry = { a: s1, b: s2.slice(5, -1) };
|
||||
if ( s1.indexOf(' ') === -1 ) {
|
||||
this.simpleHasSelectors.push(entry);
|
||||
} else {
|
||||
this.complexHasSelectors.push(entry);
|
||||
this.complexHasSelectorsCost = 0;
|
||||
}
|
||||
},
|
||||
|
||||
addSelector: function(s) {
|
||||
if ( this.allSelectors[s] || this.allExceptions[s] ) {
|
||||
return;
|
||||
}
|
||||
this.allSelectors[s] = true;
|
||||
var pos = s.indexOf(':');
|
||||
if ( pos !== -1 ) {
|
||||
pos = s.indexOf(':has(');
|
||||
if ( pos !== -1 ) {
|
||||
this.addHasSelector(s.slice(0, pos), s.slice(pos));
|
||||
if ( s.indexOf(':') !== -1 && this.addSelectorEx(s) ) {
|
||||
return;
|
||||
}
|
||||
if ( s.lastIndexOf(':xpath(', 0) === 0 ) {
|
||||
this.addXpathSelector('', s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ( s.indexOf(' ') === -1 ) {
|
||||
this.simpleSelectors.push(s);
|
||||
this.simpleGroupSelector = null;
|
||||
@ -132,18 +114,41 @@ vAPI.domFilterer = {
|
||||
this.newDeclarativeSelectors.push(s);
|
||||
},
|
||||
|
||||
addSelectorEx: function(s) {
|
||||
var pos = s.indexOf(':has(');
|
||||
if ( pos !== -1 ) {
|
||||
var entry = {
|
||||
a: s.slice(0, pos),
|
||||
b: s.slice(pos + 5, -1)
|
||||
};
|
||||
if ( entry.a.indexOf(' ') === -1 ) {
|
||||
this.simpleHasSelectors.push(entry);
|
||||
} else {
|
||||
this.complexHasSelectors.push(entry);
|
||||
this.complexHasSelectorsCost = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
pos = s.indexOf(':style(');
|
||||
if ( pos !== -1 ) {
|
||||
this.newCSSRules.push(s.slice(0, pos) + ' {' + s.slice(pos + 7, -1) + '}');
|
||||
return true;
|
||||
}
|
||||
if ( s.lastIndexOf(':xpath(', 0) === 0 ) {
|
||||
this.xpathExpression = null;
|
||||
this.xpathSelectorsCost = 0;
|
||||
this.addXpathSelector('', s.slice(7, -1));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
addSelectors: function(aa) {
|
||||
for ( var i = 0, n = aa.length; i < n; i++ ) {
|
||||
this.addSelector(aa[i]);
|
||||
}
|
||||
},
|
||||
|
||||
addXpathSelector: function(s1, s2) {
|
||||
this.xpathSelectors.push(s2.slice(7, -1));
|
||||
this.xpathExpression = null;
|
||||
this.xpathSelectorsCost = 0;
|
||||
},
|
||||
|
||||
checkStyleTags: function(commitIfNeeded) {
|
||||
var doc = document,
|
||||
html = doc.documentElement,
|
||||
@ -188,8 +193,9 @@ vAPI.domFilterer = {
|
||||
}
|
||||
|
||||
// Inject new declarative selectors.
|
||||
var styleTag;
|
||||
if ( this.newDeclarativeSelectors.length ) {
|
||||
var styleTag = document.createElement('style');
|
||||
styleTag = document.createElement('style');
|
||||
styleTag.setAttribute('type', 'text/css');
|
||||
styleTag.textContent =
|
||||
':root ' +
|
||||
@ -199,6 +205,15 @@ vAPI.domFilterer = {
|
||||
this.styleTags.push(styleTag);
|
||||
this.newDeclarativeSelectors.length = 0;
|
||||
}
|
||||
// Inject new CSS rules.
|
||||
if ( this.newCSSRules.length ) {
|
||||
styleTag = document.createElement('style');
|
||||
styleTag.setAttribute('type', 'text/css');
|
||||
styleTag.textContent = ':root ' + this.newCSSRules.join(',\n:root ');
|
||||
document.head.appendChild(styleTag);
|
||||
this.styleTags.push(styleTag);
|
||||
this.newCSSRules.length = 0;
|
||||
}
|
||||
|
||||
// Simple `:has()` selectors.
|
||||
if ( this.simpleHasSelectors.length ) {
|
||||
|
@ -297,18 +297,30 @@ FilterParser.prototype.parse = function(raw) {
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/952
|
||||
// Find out whether we are dealing with an Adguard-specific cosmetic
|
||||
// filter, and if so, discard the filter.
|
||||
// filter, and if so, translate it if supported, or discard it if not
|
||||
// supported.
|
||||
var cCode = raw.charCodeAt(rpos - 1);
|
||||
if ( cCode !== 0x23 /* '#' */ && cCode !== 0x40 /* '@' */ ) {
|
||||
// We have an Adguard cosmetic filter if and only if the character is
|
||||
// `$` or `%`, otherwise it's not a cosmetic filter.
|
||||
if ( cCode === 0x24 /* '$' */ || cCode === 0x25 /* '%' */ ) {
|
||||
this.invalid = true;
|
||||
} else {
|
||||
// Not a cosmetic filter.
|
||||
if ( cCode !== 0x24 /* '$' */ && cCode !== 0x25 /* '%' */ ) {
|
||||
this.cosmetic = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
// Not supported.
|
||||
if ( cCode !== 0x24 /* '$' */ ) {
|
||||
this.invalid = true;
|
||||
return this;
|
||||
}
|
||||
// CSS injection rule: supported, but translate into uBO's own format.
|
||||
raw = this.translateAdguardCSSInjectionFilter(raw);
|
||||
if ( raw === '' ) {
|
||||
this.invalid = true;
|
||||
return this;
|
||||
}
|
||||
rpos = raw.indexOf('#', lpos + 1);
|
||||
}
|
||||
|
||||
// Extract the hostname(s).
|
||||
if ( lpos !== 0 ) {
|
||||
@ -322,17 +334,6 @@ FilterParser.prototype.parse = function(raw) {
|
||||
return this;
|
||||
}
|
||||
|
||||
// Cosmetic filters with explicit style properties can apply only:
|
||||
// - to specific cosmetic filters (those which apply to a specific site)
|
||||
// - to block cosmetic filters (not exception cosmetic filters)
|
||||
if ( this.suffix.endsWith('}') ) {
|
||||
// Not supported for now: this code will ensure some backward
|
||||
// compatibility for when cosmetic filters with explicit style
|
||||
// properties start to be in use.
|
||||
this.invalid = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
// 2014-05-23:
|
||||
// https://github.com/gorhill/httpswitchboard/issues/260
|
||||
// Any sequence of `#` longer than one means the line is not a valid
|
||||
@ -380,6 +381,21 @@ FilterParser.prototype.parse = function(raw) {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Reference: https://adguard.com/en/filterrules.html#cssInjection
|
||||
|
||||
FilterParser.prototype.translateAdguardCSSInjectionFilter = function(raw) {
|
||||
var matches = /^([^#]*)#(@?)\$#([^{]+)\{([^}]+)\}$/.exec(raw);
|
||||
if ( matches === null ) {
|
||||
return '';
|
||||
}
|
||||
return matches[1] +
|
||||
'#' + matches[2] + '#' +
|
||||
matches[3].trim() +
|
||||
':style(' + matches[4].trim() + ')';
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
FilterParser.prototype.parseScriptTagFilter = function(matches) {
|
||||
// Currently supported only as non-generic selector. Also, exception
|
||||
// script tag filter makes no sense, ignore.
|
||||
@ -699,6 +715,10 @@ FilterContainer.prototype.reset = function() {
|
||||
// https://github.com/chrisaljoudi/uBlock/issues/1004
|
||||
// Detect and report invalid CSS selectors.
|
||||
|
||||
// Discard new ABP's `-abp-properties` directive until it is
|
||||
// implemented (if ever). Unlikely, see:
|
||||
// https://github.com/gorhill/uBlock/issues/1752
|
||||
|
||||
FilterContainer.prototype.isValidSelector = (function() {
|
||||
var div = document.createElement('div');
|
||||
var matchesProp = (function() {
|
||||
@ -722,18 +742,22 @@ FilterContainer.prototype.isValidSelector = (function() {
|
||||
}
|
||||
|
||||
var reHasSelector = /^(.+?):has\((.+?)\)$/;
|
||||
var reStyleSelector = /^(.+?):style\((.+?)\)$/;
|
||||
var reXpathSelector = /^:xpath\((.+?)\)$/;
|
||||
|
||||
return function(s) {
|
||||
// Keep in mind: https://github.com/gorhill/uBlock/issues/693
|
||||
var isValidCSSSelector = function(s) {
|
||||
try {
|
||||
// https://github.com/gorhill/uBlock/issues/693
|
||||
div[matchesProp](s + ',\n#foo');
|
||||
// Discard new ABP's `-abp-properties` directive until it is
|
||||
// implemented (if ever).
|
||||
if ( s.indexOf('[-abp-properties=') === -1 ) {
|
||||
return true;
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
} catch (e) {
|
||||
return true;
|
||||
};
|
||||
|
||||
return function(s) {
|
||||
if ( isValidCSSSelector(s) && s.indexOf('[-abp-properties=') === -1 ) {
|
||||
return true;
|
||||
}
|
||||
// We reach this point very rarely.
|
||||
var matches;
|
||||
@ -753,6 +777,11 @@ FilterContainer.prototype.isValidSelector = (function() {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// `:style` selector?
|
||||
matches = reStyleSelector.exec(s);
|
||||
if ( matches !== null ) {
|
||||
return isValidCSSSelector(matches[1]);
|
||||
}
|
||||
// Special `script:` filter?
|
||||
if ( s.startsWith('script') ) {
|
||||
if ( s.startsWith('?', 6) || s.startsWith('+', 6) ) {
|
||||
|
Loading…
Reference in New Issue
Block a user