Index: lib/filterValidation.js |
=================================================================== |
--- a/lib/filterValidation.js |
+++ b/lib/filterValidation.js |
@@ -19,58 +19,75 @@ |
let {Filter, InvalidFilter, ElemHideBase} = require("filterClasses"); |
+function isValidCSSSelector(selector) |
+{ |
+ let style = document.createElement("style"); |
+ document.documentElement.appendChild(style); |
+ let sheet = style.sheet; |
+ document.documentElement.removeChild(style); |
+ |
+ try |
+ { |
+ document.querySelector(selector); |
+ sheet.insertRule(selector + "{}", 0); |
+ } |
+ catch (e) |
+ { |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+/** |
+ * @typedef ParsedFilter |
+ * @property {?Filter} [filter] The parsed filter if it is valid. Or null if |
+ * the given string is empty or a filter list header. |
+ * @property {string} [error] An error message indicated that the filter cannot |
+ * be parsed or contains an invalid CSS selector. |
+ */ |
+ |
+let parseFilter = |
/** |
* Parses and validates a filter given by the user. |
* |
* @param {string} text |
- * @param {Boolean} [ignoreHeaders=false] If true, no exception is raised |
- * for filter list headers, instead |
- * the function will return null. |
- * @return {Filter} |
- * @throws Will throw an exception if filter cannot be |
- * parsed or contains an invalid CSS selector. |
- * @static |
+ * @param {Boolean} [ignoreHeaders=false] If true, {filter: null} is |
+ returned instead an error |
+ for filter list headers. |
+ * @return {ParsedFilter} |
*/ |
-function parseFilter(text, ignoreHeaders) |
+exports.parseFilter = function(text, ignoreHeaders) |
{ |
+ let filter = null; |
text = Filter.normalize(text); |
- if (!text) |
- return null; |
- if (text[0] == "[") |
+ if (text) |
{ |
- if (ignoreHeaders) |
- return null; |
+ if (text[0] != "[") |
+ { |
+ filter = Filter.fromText(text); |
- throw ext.i18n.getMessage("unexpected_filter_list_header"); |
- } |
+ if (filter instanceof InvalidFilter) |
+ return {error: filter.reason}; |
- let filter = Filter.fromText(text); |
- |
- if (filter instanceof InvalidFilter) |
- throw filter.reason; |
- |
- if (filter instanceof ElemHideBase) |
- { |
- let style = document.createElement("style"); |
- document.documentElement.appendChild(style); |
- let sheet = style.sheet; |
- document.documentElement.removeChild(style); |
- |
- try |
+ if (filter instanceof ElemHideBase && !isValidCSSSelector(filter.selector)) |
+ return {error: ext.i18n.getMessage("invalid_css_selector", "'" + filter.selector + "'")}; |
+ } |
+ else if (!ignoreHeaders) |
{ |
- document.querySelector(filter.selector); |
- sheet.insertRule(filter.selector + "{}", 0); |
- } |
- catch (error) |
- { |
- throw ext.i18n.getMessage("invalid_css_selector", "'" + filter.selector + "'"); |
+ return {error: ext.i18n.getMessage("unexpected_filter_list_header")}; |
} |
} |
- return filter; |
-} |
-exports.parseFilter = parseFilter; |
+ return {filter: filter}; |
+}; |
+ |
+/** |
+ * @typedef ParsedFilters |
+ * @property {Filter[]} [filters] The parsed filters if all of them are valid. |
+ * @property {string} [error] An error message indicated that any filter cannot |
+ * be parsed or contains an invalid CSS selector. |
+ */ |
/** |
* Parses and validates a newline-separated list of filters given by the user. |
@@ -78,10 +95,8 @@ |
* @param {string} text |
* @param {Boolean} [ignoreHeaders=false] If true, filter list headers |
* will be stripped instead of |
- * raising an exception. |
- * @return {Filter[]} |
- * @throws Will throw an exception if one of the filters cannot |
- be parsed or contains an invalid CSS selector. |
+ * returning an error. |
+ * @return {ParsedFilters} |
*/ |
exports.parseFilters = function(text, ignoreHeaders) |
{ |
@@ -90,19 +105,14 @@ |
for (let i = 0; i < lines.length; i++) |
{ |
- let filter; |
- try |
- { |
- filter = parseFilter(lines[i], ignoreHeaders); |
- } |
- catch (error) |
- { |
- throw ext.i18n.getMessage("line", (i + 1).toString()) + ": " + error; |
- } |
+ let {filter, error} = parseFilter(lines[i], ignoreHeaders); |
+ |
+ if (error) |
+ return {error: ext.i18n.getMessage("line", (i + 1).toString()) + ": " + error}; |
if (filter) |
filters.push(filter); |
} |
- return filters; |
+ return {filters: filters}; |
}; |