Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: lib/filterClasses.js

Issue 5730585574113280: Issue 2390 - Created filter class for CSS property filters (Closed)
Patch Set: Created May 4, 2015, 6:05 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/locale/en-US/global.properties ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/filterClasses.js
===================================================================
--- a/lib/filterClasses.js
+++ b/lib/filterClasses.js
@@ -20,6 +20,7 @@
*/
let {FilterNotifier} = require("filterNotifier");
+let {Utils} = require("utils");
/**
* Abstract base class for filters
@@ -85,6 +86,11 @@
* @type RegExp
*/
Filter.optionsRegExp = /\$(~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:=[^,\s]+)?)*)$/;
+/**
+ * Regular expression that CSS property filters should match
+ * @type RegExp
+ */
+Filter.csspropertyRegExp = /\[\-abp\-properties=(["'])([^"']+)\1\]/;
Sebastian Noack 2015/05/05 15:47:02 So we don't allow quotes in the value here. Should
Thomas Greiner 2015/05/06 12:08:32 Done, I added a comment as suggested. We could cha
Thomas Greiner 2015/05/06 15:33:07 Yes, there's currently no negative lookbehind in J
Sebastian Noack 2015/05/06 15:42:29 Yeah, let's stick to not allowing any quotes for n
/**
* Creates a filter of correct type from its text representation - does the basic parsing and
@@ -160,6 +166,27 @@
};
/**
+ * Converts filter text into regular expression string
+ * @param {String} text as in Filter()
+ * @return {String} regular expression representation of filter text
+ */
+Filter.toRegExp = function(text)
+{
+ return text
+ .replace(/\*+/g, "*") // remove multiple wildcards
+ .replace(/\^\|$/, "^") // remove anchors following separator placeholder
+ .replace(/\W/g, "\\$&") // escape special symbols
+ .replace(/\\\*/g, ".*") // replace wildcards by .*
+ // process separator placeholders (all ANSI characters but alphanumeric characters and _%.-)
+ .replace(/\\\^/g, "(?:[\\x00-\\x24\\x26-\\x2C\\x2F\\x3A-\\x40\\x5B-\\x5E\\x60\\x7B-\\x7F]|$)")
+ .replace(/^\\\|\\\|/, "^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?") // process extended anchor at expression start
+ .replace(/^\\\|/, "^") // process anchor at expression start
+ .replace(/\\\|$/, "$") // process anchor at expression end
+ .replace(/^(\.\*)/, "") // remove leading wildcards
+ .replace(/(\.\*)$/, ""); // remove trailing wildcards
+}
+
+/**
* Class for invalid filters
* @param {String} text see Filter()
* @param {String} reason Reason why this filter is invalid
@@ -543,20 +570,7 @@
if (prop)
return prop.value;
- // Remove multiple wildcards
- let source = this.regexpSource
- .replace(/\*+/g, "*") // remove multiple wildcards
- .replace(/\^\|$/, "^") // remove anchors following separator placeholder
- .replace(/\W/g, "\\$&") // escape special symbols
- .replace(/\\\*/g, ".*") // replace wildcards by .*
- // process separator placeholders (all ANSI characters but alphanumeric characters and _%.-)
- .replace(/\\\^/g, "(?:[\\x00-\\x24\\x26-\\x2C\\x2F\\x3A-\\x40\\x5B-\\x5E\\x60\\x7B-\\x7F]|$)")
- .replace(/^\\\|\\\|/, "^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?") // process extended anchor at expression start
- .replace(/^\\\|/, "^") // process anchor at expression start
- .replace(/\\\|$/, "$") // process anchor at expression end
- .replace(/^(\.\*)/, "") // remove leading wildcards
- .replace(/(\.\*)$/, ""); // remove trailing wildcards
-
+ let source = Filter.toRegExp(this.regexpSource);
let regexp = new RegExp(source, this.matchCase ? "" : "i");
Object.defineProperty(this, "regexp", {value: regexp});
return regexp;
@@ -861,7 +875,7 @@
* @param {String} tagName tag name part (can be empty)
* @param {String} attrRules attribute matching rules (can be empty)
* @param {String} selector raw CSS selector (can be empty)
- * @return {ElemHideFilter|ElemHideException|InvalidFilter}
+ * @return {ElemHideFilter|ElemHideException|CSSPropertyFilter|InvalidFilter}
*/
ElemHideBase.fromText = function(text, domain, isException, tagName, attrRules, selector)
{
@@ -883,10 +897,7 @@
}
else {
if (id)
- {
- let {Utils} = require("utils");
return new InvalidFilter(text, Utils.getString("filter_elemhide_duplicate_id"));
- }
else
Sebastian Noack 2015/05/05 15:47:02 Nit: Redundant else statement.
Thomas Greiner 2015/05/06 12:08:32 Done.
id = rule;
}
@@ -898,15 +909,24 @@
else if (tagName || additional)
selector = tagName + additional;
else
- {
- let {Utils} = require("utils");
return new InvalidFilter(text, Utils.getString("filter_elemhide_nocriteria"));
- }
}
if (isException)
return new ElemHideException(text, domain, selector);
else
Sebastian Noack 2015/05/05 15:47:02 Nit: Redundant else statement.
Thomas Greiner 2015/05/06 12:08:32 Done.
- return new ElemHideFilter(text, domain, selector);
+ {
+ if (Filter.csspropertyRegExp.test(selector))
+ {
+ // CSS property filters are inefficient so we need to make sure that
+ // they're only applied if they specify active domains
+ if (/,[^~]/.test("," + domain))
Sebastian Noack 2015/05/05 15:47:02 I wonder whether we should also look for at least
Thomas Greiner 2015/05/06 12:08:32 Good point but note that this still doesn't cover
Sebastian Noack 2015/05/06 13:07:48 Hmm, if we want to do it properly, I suppose we ha
+ return new CSSPropertyFilter(text, domain, selector);
+ else
Sebastian Noack 2015/05/05 15:47:02 Nit: Redundant else statement.
+ return new InvalidFilter(text, Utils.getString("filter_cssproperty_nodomain"));
+ }
+ else
Sebastian Noack 2015/05/05 15:47:02 Nit: Redundant else statement.
Thomas Greiner 2015/05/06 12:08:32 Done.
+ return new ElemHideFilter(text, domain, selector);
+ }
};
/**
@@ -946,3 +966,64 @@
{
__proto__: ElemHideBase.prototype
};
+
+/**
+ * Class for CSS property filters
+ * @param {String} text see Filter()
+ * @param {String} domains see ElemHideBase()
+ * @param {String} selector see ElemHideBase()
+ * @constructor
+ * @augments ElemHideBase
+ */
+function CSSPropertyFilter(text, domains, selector)
+{
+ ElemHideBase.call(this, text, domains, selector);
+
+ let properties;
+ [properties, , this.regexpSource] = selector.match(Filter.csspropertyRegExp);
+ [this.selectorPrefix, this.selectorSuffix] = selector.split(properties);
+}
+exports.CSSPropertyFilter = CSSPropertyFilter;
+
+CSSPropertyFilter.prototype =
+{
+ __proto__: ElemHideBase.prototype,
+
+ /**
+ * Expression from which a regular expression should be generated for matching
+ * CSS properties - for delayed creation of the regexp property
+ * @type String
+ */
+ regexpSource: null,
+ /**
+ * Substring of CSS selector before properties for the HTML elements that
+ * should be hidden
+ * @type String
+ */
+ selectorPrefix: null,
+ /**
+ * Substring of CSS selector after properties for the HTML elements that
+ * should be hidden
+ * @type String
+ */
+ selectorSuffix: null,
+
+ /**
+ * Regular expression to be used when testing CSS properties against
+ * this filter
+ * @type RegExp
+ */
+ get regexp()
Sebastian Noack 2015/05/05 15:47:02 Hmm, this is almost the same code we already have
Thomas Greiner 2015/05/06 12:08:32 You're right, the issue description doesn't explic
Sebastian Noack 2015/05/06 13:07:48 Well, objects get serialized when passed to conten
+ {
+ // Despite this property being cached, the getter is called
+ // several times on Safari, due to WebKit bug 132872
+ let prop = Object.getOwnPropertyDescriptor(this, "regexp");
+ if (prop)
+ return prop.value;
+
+ let source = Filter.toRegExp(this.regexpSource);
+ let regexp = new RegExp(source, "");
+ Object.defineProperty(this, "regexp", {value: regexp});
+ return regexp;
+ }
+};
« no previous file with comments | « chrome/locale/en-US/global.properties ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld