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

Side by Side Diff: lib/filterClasses.js

Issue 29453590: Issue 5287 - Change syntax for element hiding emulation filters and remove simplified element hidin… (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Patch Set: Created June 1, 2017, 12:01 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2017 eyeo GmbH 3 * Copyright (C) 2006-2017 eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 /** 80 /**
81 * Cache for known filters, maps string representation to filter objects. 81 * Cache for known filters, maps string representation to filter objects.
82 * @type {Object} 82 * @type {Object}
83 */ 83 */
84 Filter.knownFilters = Object.create(null); 84 Filter.knownFilters = Object.create(null);
85 85
86 /** 86 /**
87 * Regular expression that element hiding filters should match 87 * Regular expression that element hiding filters should match
88 * @type {RegExp} 88 * @type {RegExp}
89 */ 89 */
90 Filter.elemhideRegExp = /^([^/*|@"!]*?)#(@)?(?:([\w-]+|\*)((?:\([\w-]+(?:[$^*]?= [^()"]*)?\))*)|#(.+))$/; 90 Filter.elemhideRegExp = /^([^/*|@"!]*?)#([@?])?#(.+)$/;
91 /** 91 /**
92 * Regular expression that RegExp filters specified as RegExps should match 92 * Regular expression that RegExp filters specified as RegExps should match
93 * @type {RegExp} 93 * @type {RegExp}
94 */ 94 */
95 Filter.regexpRegExp = /^(@@)?\/.*\/(?:\$~?[\w-]+(?:=[^,\s]+)?(?:,~?[\w-]+(?:=[^, \s]+)?)*)?$/; 95 Filter.regexpRegExp = /^(@@)?\/.*\/(?:\$~?[\w-]+(?:=[^,\s]+)?(?:,~?[\w-]+(?:=[^, \s]+)?)*)?$/;
96 /** 96 /**
97 * Regular expression that options on a RegExp filter should match 97 * Regular expression that options on a RegExp filter should match
98 * @type {RegExp} 98 * @type {RegExp}
99 */ 99 */
100 Filter.optionsRegExp = /\$(~?[\w-]+(?:=[^,\s]+)?(?:,~?[\w-]+(?:=[^,\s]+)?)*)$/; 100 Filter.optionsRegExp = /\$(~?[\w-]+(?:=[^,\s]+)?(?:,~?[\w-]+(?:=[^,\s]+)?)*)$/;
101 101
102 /** 102 /**
103 * Creates a filter of correct type from its text representation - does the 103 * Creates a filter of correct type from its text representation - does the
104 * basic parsing and calls the right constructor then. 104 * basic parsing and calls the right constructor then.
105 * 105 *
106 * @param {string} text as in Filter() 106 * @param {string} text as in Filter()
107 * @return {Filter} 107 * @return {Filter}
108 */ 108 */
109 Filter.fromText = function(text) 109 Filter.fromText = function(text)
110 { 110 {
111 if (text in Filter.knownFilters) 111 if (text in Filter.knownFilters)
112 return Filter.knownFilters[text]; 112 return Filter.knownFilters[text];
113 113
114 let ret; 114 let ret;
115 let match = (text.includes("#") ? Filter.elemhideRegExp.exec(text) : null); 115 let match = (text.includes("#") ? Filter.elemhideRegExp.exec(text) : null);
116 if (match) 116 if (match)
117 { 117 {
118 let propsMatch;
119 if (!match[2] &&
120 (propsMatch = /\[-abp-properties=(["'])([^"']+)\1\]/.exec(match[3])))
121 {
122 // This is legacy CSS properties syntax, convert to current syntax
123 let prefix = match[3].substr(0, propsMatch.index);
124 let expression = propsMatch[2];
125 let suffix = match[3].substr(propsMatch.index + propsMatch[0].length);
126 return Filter.fromText(`${match[1]}#?#` +
127 `${prefix}:-abp-properties(${expression})${suffix}`);
128 }
129
118 ret = ElemHideBase.fromText( 130 ret = ElemHideBase.fromText(
119 text, match[1], !!match[2], match[3], match[4], match[5] 131 text, match[1], match[2], match[3]
120 ); 132 );
121 } 133 }
122 else if (text[0] == "!") 134 else if (text[0] == "!")
123 ret = new CommentFilter(text); 135 ret = new CommentFilter(text);
124 else 136 else
125 ret = RegExpFilter.fromText(text); 137 ret = RegExpFilter.fromText(text);
126 138
127 Filter.knownFilters[ret.text] = ret; 139 Filter.knownFilters[ret.text] = ret;
128 return ret; 140 return ret;
129 }; 141 };
(...skipping 793 matching lines...) Expand 10 before | Expand all | Expand 10 after
923 * CSS selector for the HTML elements that should be hidden 935 * CSS selector for the HTML elements that should be hidden
924 * @type {string} 936 * @type {string}
925 */ 937 */
926 selector: null 938 selector: null
927 }); 939 });
928 940
929 /** 941 /**
930 * Creates an element hiding filter from a pre-parsed text representation 942 * Creates an element hiding filter from a pre-parsed text representation
931 * 943 *
932 * @param {string} text same as in Filter() 944 * @param {string} text same as in Filter()
933 * @param {string} domain 945 * @param {string?} domain
934 * domain part of the text representation (can be empty) 946 * domain part of the text representation
935 * @param {boolean} isException exception rule indicator 947 * @param {string?} type
936 * @param {string} tagName tag name part (can be empty) 948 * rule type, either empty or @ (exception) or ? (emulation rule)
937 * @param {string} attrRules attribute matching rules (can be empty) 949 * @param {string} selector raw CSS selector
938 * @param {string} selector raw CSS selector (can be empty)
939 * @return {ElemHideFilter|ElemHideException| 950 * @return {ElemHideFilter|ElemHideException|
940 * ElemHideEmulationFilter|InvalidFilter} 951 * ElemHideEmulationFilter|InvalidFilter}
941 */ 952 */
942 ElemHideBase.fromText = function(text, domain, isException, tagName, attrRules, 953 ElemHideBase.fromText = function(text, domain, type, selector)
943 selector)
944 { 954 {
945 if (!selector)
946 {
947 if (tagName == "*")
948 tagName = "";
949
950 let id = null;
951 let additional = "";
952 if (attrRules)
953 {
954 attrRules = attrRules.match(/\([\w-]+(?:[$^*]?=[^()"]*)?\)/g);
955 for (let rule of attrRules)
956 {
957 rule = rule.substr(1, rule.length - 2);
958 let separatorPos = rule.indexOf("=");
959 if (separatorPos > 0)
960 {
961 rule = rule.replace(/=/, '="') + '"';
962 additional += "[" + rule + "]";
963 }
964 else
965 {
966 if (id)
967 return new InvalidFilter(text, "filter_elemhide_duplicate_id");
968
969 id = rule;
970 }
971 }
972 }
973
974 if (id)
975 selector = `${tagName}.${id}${additional},${tagName}#${id}${additional}`;
976 else if (tagName || additional)
977 selector = tagName + additional;
978 else
979 return new InvalidFilter(text, "filter_elemhide_nocriteria");
980 }
981
982 // We don't allow ElemHide filters which have any empty domains. 955 // We don't allow ElemHide filters which have any empty domains.
983 // Note: The ElemHide.prototype.domainSeparator is duplicated here, if that 956 // Note: The ElemHide.prototype.domainSeparator is duplicated here, if that
984 // changes this must be changed too. 957 // changes this must be changed too.
985 if (domain && /(^|,)~?(,|$)/.test(domain)) 958 if (domain && /(^|,)~?(,|$)/.test(domain))
986 return new InvalidFilter(text, "filter_invalid_domain"); 959 return new InvalidFilter(text, "filter_invalid_domain");
987 960
988 if (isException) 961 if (type == "@")
989 return new ElemHideException(text, domain, selector); 962 return new ElemHideException(text, domain, selector);
990 963
991 if (selector.indexOf("[-abp-properties=") != -1) 964 if (type == "?")
992 { 965 {
993 // Element hiding emulation filters are inefficient so we need to make sure 966 // Element hiding emulation filters are inefficient so we need to make sure
994 // that they're only applied if they specify active domains 967 // that they're only applied if they specify active domains
995 if (!/,[^~][^,.]*\.[^,]/.test("," + domain)) 968 if (!/,[^~][^,.]*\.[^,]/.test("," + domain))
996 return new InvalidFilter(text, "filter_elemhideemulation_nodomain"); 969 return new InvalidFilter(text, "filter_elemhideemulation_nodomain");
997 970
971 // The selector should contain at least one :-abp-foo() pseudo-class
972 if (!/:-abp-[\w-]+\(/.test(selector))
973 return new InvalidFilter(text, "filter_elemhideemulation_plainselector");
974
998 return new ElemHideEmulationFilter(text, domain, selector); 975 return new ElemHideEmulationFilter(text, domain, selector);
999 } 976 }
1000 977
1001 return new ElemHideFilter(text, domain, selector); 978 return new ElemHideFilter(text, domain, selector);
1002 }; 979 };
1003 980
1004 /** 981 /**
1005 * Class for element hiding filters 982 * Class for element hiding filters
1006 * @param {string} text see Filter() 983 * @param {string} text see Filter()
1007 * @param {string} domains see ElemHideBase() 984 * @param {string} domains see ElemHideBase()
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1047 */ 1024 */
1048 function ElemHideEmulationFilter(text, domains, selector) 1025 function ElemHideEmulationFilter(text, domains, selector)
1049 { 1026 {
1050 ElemHideBase.call(this, text, domains, selector); 1027 ElemHideBase.call(this, text, domains, selector);
1051 } 1028 }
1052 exports.ElemHideEmulationFilter = ElemHideEmulationFilter; 1029 exports.ElemHideEmulationFilter = ElemHideEmulationFilter;
1053 1030
1054 ElemHideEmulationFilter.prototype = extend(ElemHideBase, { 1031 ElemHideEmulationFilter.prototype = extend(ElemHideBase, {
1055 type: "elemhideemulation" 1032 type: "elemhideemulation"
1056 }); 1033 });
OLDNEW

Powered by Google App Engine
This is Rietveld