Index: lib/filterValidation.js |
=================================================================== |
--- a/lib/filterValidation.js |
+++ b/lib/filterValidation.js |
@@ -19,6 +19,63 @@ |
let {Filter, InvalidFilter, ElemHideBase} = require("filterClasses"); |
+/** |
+ * An error returned by |
+ * {@link module:filterValidation.parseFilter parseFilter()} or |
+ * {@link module:filterValidation.parseFilters parseFilters()} |
+ * indicating that a given filter cannot be parsed, |
+ * contains an invalid CSS selector or is a filter list header. |
+ * |
+ * @constructor |
+ */ |
+function FilterParsingError(type, details) |
+{ |
+ /** |
+ * Indicates why the filter is rejected. Possible choices: |
+ * "invalid-filter", "invalid-css-selector", "unexpected-filter-list-header" |
+ * |
+ * @type {string} |
+ */ |
+ this.type = type; |
+ |
+ if (details) |
+ { |
+ if ("reason" in details) |
+ this.reason = details.reason; |
+ if ("selector" in details) |
+ this.selector = details.selector; |
+ } |
+} |
+FilterParsingError.prototype = { |
+ /** |
+ * The line number the error occurred on if |
+ * {@link module:filterValidation.parseFilters parseFilters()} |
+ * were used. Or null if the error was returned by |
+ * {@link module:filterValidation.parseFilter parseFilter()}. |
+ * |
+ * @type {?number} |
+ */ |
+ lineno: null, |
+ |
+ /** |
+ * Returns a detailed translated error message. |
+ * |
+ * @return {string} |
+ */ |
+ toString: function() |
+ { |
+ let message = this.reason || ext.i18n.getMessage( |
+ this.type.replace(/-/g, "_"), |
+ "selector" in this ? "'" + this.selector + "'" : null |
+ ); |
+ |
+ if (this.lineno) |
+ message = ext.i18n.getMessage("line", this.lineno.toLocaleString()) + ": " + message; |
+ |
+ return message; |
+ } |
+}; |
+ |
function isValidCSSSelector(selector) |
{ |
let style = document.createElement("style"); |
@@ -40,10 +97,10 @@ |
/** |
* @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. |
+ * @property {?Filter} [filter] The parsed filter if it is valid. |
+ * Or null if the given string is empty. |
+ * @property {FilterParsingError} [error] See {@link module:filterValidation~FilterParsingError FilterParsingError} |
+ * |
*/ |
let parseFilter = |
@@ -51,32 +108,25 @@ |
* Parses and validates a filter given by the user. |
* |
* @param {string} text |
- * @param {Boolean} [ignoreHeaders=false] If true, {filter: null} is |
- returned instead an error |
- for filter list headers. |
* @return {ParsedFilter} |
*/ |
-exports.parseFilter = function(text, ignoreHeaders) |
+exports.parseFilter = function(text) |
{ |
let filter = null; |
text = Filter.normalize(text); |
if (text) |
{ |
- if (text[0] != "[") |
- { |
- filter = Filter.fromText(text); |
+ if (text[0] == "[") |
+ return {error: new FilterParsingError("unexpected-filter-list-header")}; |
- if (filter instanceof InvalidFilter) |
- return {error: filter.reason}; |
+ filter = Filter.fromText(text); |
- if (filter instanceof ElemHideBase && !isValidCSSSelector(filter.selector)) |
- return {error: ext.i18n.getMessage("invalid_css_selector", "'" + filter.selector + "'")}; |
- } |
- else if (!ignoreHeaders) |
- { |
- return {error: ext.i18n.getMessage("unexpected_filter_list_header")}; |
- } |
+ if (filter instanceof InvalidFilter) |
+ return {error: new FilterParsingError("invalid-filter", {reason: filter.reason})}; |
+ |
+ if (filter instanceof ElemHideBase && !isValidCSSSelector(filter.selector)) |
+ return {error: new FilterParsingError("invalid-css-selector", {selector: filter.selector})}; |
} |
return {filter: filter}; |
@@ -84,35 +134,35 @@ |
/** |
* @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. |
+ * @property {Filter[]} filters The parsed result without invalid filters. |
+ * @property {FilterParsingError[]} errors See {@link module:filterValidation~FilterParsingError FilterParsingError} |
*/ |
/** |
* Parses and validates a newline-separated list of filters given by the user. |
* |
* @param {string} text |
- * @param {Boolean} [ignoreHeaders=false] If true, filter list headers |
- * will be stripped instead of |
- * returning an error. |
* @return {ParsedFilters} |
*/ |
-exports.parseFilters = function(text, ignoreHeaders) |
+exports.parseFilters = function(text) |
{ |
let lines = text.split("\n"); |
let filters = []; |
+ let errors = []; |
for (let i = 0; i < lines.length; i++) |
{ |
- let {filter, error} = parseFilter(lines[i], ignoreHeaders); |
- |
- if (error) |
- return {error: ext.i18n.getMessage("line", (i + 1).toString()) + ": " + error}; |
+ let {filter, error} = parseFilter(lines[i]); |
if (filter) |
filters.push(filter); |
+ |
+ if (error) |
+ { |
+ error.lineno = i + 1; |
+ errors.push(error); |
+ } |
} |
- return {filters: filters}; |
+ return {filters: filters, errors: errors}; |
}; |