/**
* @file HTML filtering rule converter.
*/
import { type HtmlFilteringRule } from '../../nodes/index.js';
import { type NodeConversionResult } from '../base-interfaces/conversion-result.js';
import { RuleConverterBase } from '../base-interfaces/rule-converter-base.js';
/**
* Error messages used in HTML filtering rule conversion.
*/
export declare const ERROR_MESSAGES: {
readonly ABP_NOT_SUPPORTED: "Invalid rule, ABP does not support HTML filtering rules";
readonly INVALID_RULE: "Invalid HTML filtering rule: %s";
readonly MIXED_SYNTAX_ADG_UBO: "Mixed AdGuard and uBlock syntax";
readonly EMPTY_SELECTOR_LIST: "Selector list of HTML filtering rule must not be empty";
readonly EMPTY_COMPLEX_SELECTOR: "Complex selector of selector list must not be empty";
readonly INVALID_SELECTOR_COMBINATOR: "Invalid selector combinator '%s' used between selectors";
readonly UNKNOWN_SELECTOR_TYPE: "Unknown selector type '%s' found during conversion";
readonly SPECIAL_ATTRIBUTE_SELECTOR_OPERATOR_INVALID: "Special attribute selector '%s' has invalid operator '%s'";
readonly SPECIAL_ATTRIBUTE_SELECTOR_FLAG_NOT_SUPPORTED: "Special attribute selector '%s' does not support flags";
readonly SPECIAL_ATTRIBUTE_SELECTOR_VALUE_REQUIRED: "Special attribute selector '%s' requires a value";
readonly SPECIAL_ATTRIBUTE_SELECTOR_VALUE_INT: "Value of special attribute selector '%s' must be an integer, got '%s'";
readonly SPECIAL_ATTRIBUTE_SELECTOR_VALUE_POSITIVE: "Value of special attribute selector '%s' must be a positive integer, got '%s'";
readonly SPECIAL_ATTRIBUTE_SELECTOR_NOT_SUPPORTED: "Special attribute selector '%s' is not supported in conversion";
readonly SPECIAL_PSEUDO_CLASS_SELECTOR_ARGUMENT_REQUIRED: "Special pseudo-class selector '%s' requires an argument";
readonly SPECIAL_PSEUDO_CLASS_SELECTOR_ARGUMENT_INT: "Argument of special pseudo-class selector '%s' must be an integer, got '%s'";
readonly SPECIAL_PSEUDO_CLASS_SELECTOR_ARGUMENT_POSITIVE: "Argument of special pseudo-class selector '%s' must be a positive integer, got '%s'";
readonly SPECIAL_PSEUDO_CLASS_SELECTOR_ARGUMENT_TOO_LARGE: "Argument of special pseudo-class selector '%s' must not exceed %s, got '%s'";
readonly SPECIAL_PSEUDO_CLASS_SELECTOR_NOT_SUPPORTED: "Special pseudo-class selector '%s' is not supported in conversion";
};
/**
* HTML filtering rule converter class.
*
* @todo Implement `convertToUbo` (ABP currently doesn't support HTML filtering rules).
*/
export declare class HtmlRuleConverter extends RuleConverterBase {
/**
* Converts a HTML rule to AdGuard syntax, if possible.
*
* Note: for AdGuard rules this is not a strict validation. AdGuard rule
* bodies with an unbalanced special pseudo-class argument, e.g.
* `:contains((function(...)`, are tolerated and parsed leniently by the
* parser itself (CoreLibs parity, see `AdgHtmlFilteringBodyParser`);
* other unparseable bodies with special selectors are kept as-is with
* `isConverted: false`, so callers must not treat a returned result as
* proof of rule validity.
*
* @param rule Rule node to convert.
*
* @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
* the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
* If the rule was not converted, the result array will contain the original node with the same object reference.
*
* @throws If the rule is genuinely invalid — an unparseable body without
* special selector markers, or a conversion error (e.g. mixed AdGuard and
* uBlock syntax, invalid length values) — or cannot be converted.
*/
static convertToAdg(rule: HtmlFilteringRule): NodeConversionResult;
/**
* Converts a HTML rule to uBlock syntax, if possible.
* Also can be used to convert uBlock rules to uBlock syntax to validate them.
*
* @param rule Rule node to convert.
*
* @returns An object which follows the {@link NodeConversionResult} interface. Its `result` property contains
* the array of converted rule nodes, and its `isConverted` flag indicates whether the original rule was converted.
* If the rule was not converted, the result array will contain the original node with the same object reference.
*
* @throws Error if the rule is invalid or cannot be converted.
*/
static convertToUbo(rule: HtmlFilteringRule): NodeConversionResult;
/**
* Handles special attribute selectors during AdGuard to AdGuard conversion:
* - `[tag-content="content"]` -> `:contains(content)`
* direct conversion, no changes to value. The value is emitted raw:
* any quotes in it are literal characters of the text to match, not
* a transport encoding to strip later. This mirrors CoreLibs, which
* never unquotes `:contains()` arguments.
* - `[wildcard="*content*"]` -> `:contains(/*.content*./s)`
* convert search pattern to regular expression
* - `[min-length="min"]` -> `:contains(/^(?=.{min,}$).*\/s)`
* converts to a length-matching regular expression.
* - `[max-length="max"]` -> `:contains(/^(?=.{0,max}$).*\/s)`
* converts to a length-matching regular expression.
*
* Note: This attribute selector to pseudo-class selector conversion
* is needed because AdGuard special attribute selectors are going
* to be deprecated and removed soon.
*
* @param name Name of the special attribute selector.
* @param value Value of the special attribute selector.
*
* @returns A {@link SimpleSelector} to add to the current complex selector.
*/
private static convertSpecialAttributeSelectorAdgToAdg;
/**
* Handles special pseudo-class selectors during AdGuard to AdGuard conversion:
* - `:contains(text)` -> kept as-is
* - `:-abp-contains(text)` -> kept as-is
* - `:has-text(text)` -> `:contains(text)`
* `:has-text()` is a documented synonym for `:contains()` in AdGuard products.
*
* @param name Name of the special pseudo-class selector.
* @param argument Argument of the special pseudo-class selector.
*
* @returns A {@link SimpleSelector} to add to the current complex selector,
* or `true` to keep the original pseudo-class selector as-is.
*
* @throws Rule conversion error for mixed syntax.
*/
private static convertSpecialPseudoClassSelectorAdgToAdg;
/**
* Since special attribute selectors only AdGuard-specific,
* we should never encounter them in uBlock rules.
*
* @throws Rule conversion error for mixed syntax.
*/
private static convertSpecialAttributeSelectorUboToAdg;
/**
* Handles special pseudo-class selectors during uBlock to AdGuard conversion:
* - `:has-text(text)` -> `:contains(text)`
* direct conversion, no changes to argument
* - `:min-text-length(min)` -> `:contains(/^(?=.{min,MAX_CONVERSION_DEFAULT}$).*\/s)`
* converts to a length-matching regular expression.
*
* @param name Name of the special pseudo-class selector.
* @param argument Argument of the special pseudo-class selector.
*
* @returns A {@link SimpleSelector} to add to the current complex selector.
*
* @throws If AdGuard-specific pseudo-class selector is found in uBlock rule.
*/
private static convertSpecialPseudoClassSelectorUboToAdg;
/**
* Handles special attribute selectors during AdGuard to uBlock conversion:
* - `[tag-content="content"]` -> `:has-text(content)`
* direct conversion, no changes to value
* - `[wildcard="*content*"]` -> `:has-text(/*.content*./s)`
* convert search pattern to regular expression
* - `[min-length="min"]` -> `:min-text-length(min)`
* direct conversion, no changes to value
* - `[max-length]` is skipped.
*
* @param name Name of the special attribute selector.
* @param value Value of the special attribute selector.
*
* @returns A {@link SimpleSelector} to add to the current complex selector, or `false` to skip it.
*/
private static convertSpecialAttributeSelectorAdgToUbo;
/**
* Handles special pseudo-class selectors during AdGuard to uBlock conversion:
* - `:contains(text)` -> `:has-text(text)`
* direct conversion, no changes to argument.
*
* @param name Name of the special pseudo-class selector.
* @param argument Argument of the special pseudo-class selector.
*
* @returns A {@link SimpleSelector} to add to the current complex selector.
*
* @throws If uBlock-specific pseudo-class selector is found in AdGuard rule.
*/
private static convertSpecialPseudoClassSelectorAdgToUbo;
/**
* Pre-scans a complex selector's child selectors
* for {@link AdgAttributeSelectors.MinLength}
* and {@link AdgAttributeSelectors.MaxLength} attribute selectors.
*
* Resolves duplicates to the most *restrictive* value:
* - for multiple `[min-length]` selectors, the largest value is selected;
* - for multiple `[max-length]` selectors, the smallest value is selected.
*
* Logs a warning when duplicate length selectors are found.
*
* @param selectors Child selectors of a complex selector to scan.
*
* @returns Resolved length constraints,
* or `null` if no length selectors were found.
*/
private static collectLengthConstraints;
/**
* Checks whether the raw HTML filtering rule body contains any special
* attribute selector or special pseudo-class selector outside of quoted
* text, where marker-like substrings may occur as plain text, e.g. the
* `:contains(` in `[data-x=":contains(foo"]`.
*
* Quote handling:
* - both single and double quotes toggle the quoted state;
* - a backslash-escaped quote (`\"`) does not toggle the quoted state;
* - a doubled quote (`""`) inside a quoted section is treated as an
* escaped quote (AdGuard escaping convention for `[tag-content]` values).
*
* Used by the tolerant fallback to distinguish rules with special
* selectors (which must be kept as-is if unparseable) from genuinely
* invalid rules (which must be rejected).
*
* @param raw Raw HTML filtering rule body.
*
* @returns `true` if the body contains special selectors, otherwise `false`.
*/
private static hasSpecialSimpleSelectors;
/**
* Converts a HTML filtering rule body by handling special simple selectors via callbacks.
* Special simple selectors are skipped in the converted selector list and should be handled from callee.
*
* @param body HTML filtering rule body to convert.
* @param parser HTML filtering rule body parser used for parsing raw value bodies.
* @param generator HTML filtering rule body generator used for generating raw value bodies.
* @param onSpecialAttributeSelector Callback invoked when a special attribute selector is found.
* @param onSpecialPseudoClassSelector Callback invoked when a special pseudo-class selector is found.
* @param shouldMergeLengthSelectors If true, `[min-length]` and `[max-length]` attribute
* selectors within the same complex selector are merged into a single `:contains()` pseudo-class.
* Defaults to `false`.
*
* @returns Converted selector list without special simple selectors.
*/
private static convertBody;
/**
* Checks whether a [tag-content] literal can be emitted as a standalone
* `:contains()` pseudo-class directly followed by another special
* pseudo-class ("chain-safe"):
*
* - it must not be empty and must not start with a slash — a leading `/`
* makes the argument look like a regular expression to CoreLibs;
* - it must not contain quotes, parentheses, brackets, braces,
* backslashes or colons — CoreLibs' special pseudo-class argument
* scanner splits a `:contains()` chain at the next free `:`, and any
* of those characters would swallow the separator, silently merging
* the two pseudo-classes into a single bogus literal argument.
*
* A literal that is not chain-safe is still valid as a *single*
* `:contains()` pseudo-class (CoreLibs takes the whole argument between
* `(` and the closing `)` of the sole pseudo-class in the rule), but it
* must be folded into a merged regular expression as soon as another
* regex-like constraint has to be emitted as well.
*
* @param value [tag-content] value to check.
*
* @returns `true` if the literal is chain-safe, otherwise `false`.
*/
private static isChainSafeLiteral;
/**
* Emits the pseudo-classes converted from the deferred special attribute
* selectors ([tag-content], [wildcard], [min-length], [max-length]) of a
* single complex selector, honoring the constraints of CoreLibs' HTML
* filter:
*
* - at most one "tag-content" constraint (a literal `:contains()`) and one
* "wildcard" constraint (a regex `:contains()`) are allowed per selector,
* so e.g. `[wildcard="..."]` cannot be chained with
* `[max-length="..."]` as two regex `:contains()` pseudo-classes;
* - a literal `:contains()` may be chained in front of a single regex
* `:contains()` only when it is chain-safe, see
* {@link HtmlRuleConverter.isChainSafeLiteral}.
*
* Combinations which cannot be represented as such a chain — an unsafe
* literal plus any regex-like constraint, or several regex-like
* constraints (multiple [wildcard] values, `[wildcard]` combined with
* `[min/max-length]`, multiple [tag-content] values) — are merged into a
* single regular expression instead:
* `/^(?=.{min,max}$)(?=)(?=.*).*\/s`.
*
* @param convertedSelectors Converted selectors of the complex selector,
* the emitted pseudo-classes are appended to it.
* @param tagContentValues Deferred [tag-content] values.
* @param wildcardGlobValues Deferred [wildcard] glob values.
* @param lengthConstraints Deferred length constraints collected from
* [min-length] / [max-length], or `null` if absent.
*/
private static appendSpecialAttributePseudoClasses;
/**
* Clones a simple selector or selector combinator node.
*
* @param selector Simple selector or selector combinator node to clone.
*
* @returns Cloned simple selector or selector combinator node.
*/
private static cloneSelector;
/**
* Creates a CSS pseudo-class selector node.
*
* @param name The name of the pseudo-class selector.
* @param argument Optional argument of the pseudo-class selector.
*
* @returns CSS pseudo-class selector node.
*/
private static getPseudoClassSelectorNode;
/**
* Asserts that the given array is not empty.
*
* @param array Array to check.
* @param errorMessage Error message to use if the array is empty.
*
* @throws If the array is empty.
*/
private static assertNotEmpty;
/**
* Asserts that the given special attribute / pseudo-class length value is valid.
*
* @param name Name of the attribute or pseudo-class.
* @param value Value to parse.
* @param notIntErrorMessage Error message when the value is not an integer.
* @param notPositiveErrorMessage Error message when the value is not positive.
*
* @throws If the value is not a valid number or not positive.
*/
private static assertValidLengthValue;
}