/**
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
/**
* @module engine/view/matcher
*/
import { type ViewElement } from "./element.js";
import { type Consumables } from "../conversion/viewconsumable.js";
/**
* View matcher class.
* Instance of this class can be used to find {@link module:engine/view/element~ViewElement elements} that match given pattern.
*/
export declare class Matcher {
	private readonly _patterns;
	/**
	* Creates new instance of Matcher.
	*
	* @param pattern Match patterns. See {@link module:engine/view/matcher~Matcher#add add method} for more information.
	*/
	constructor(...pattern: Array<MatcherPattern>);
	/**
	* Adds pattern or patterns to matcher instance.
	*
	* ```ts
	* // String.
	* matcher.add( 'div' );
	*
	* // Regular expression.
	* matcher.add( /^\w/ );
	*
	* // Single class.
	* matcher.add( {
	* 	classes: 'foobar'
	* } );
	* ```
	*
	* See {@link module:engine/view/matcher~MatcherPattern} for more examples.
	*
	* Multiple patterns can be added in one call:
	*
	* ```ts
	* matcher.add( 'div', { classes: 'foobar' } );
	* ```
	*
	* @param pattern Object describing pattern details. If string or regular expression
	* is provided it will be used to match element's name. Pattern can be also provided in a form
	* of a function - then this function will be called with each {@link module:engine/view/element~ViewElement element} as a parameter.
	* Function's return value will be stored under `match` key of the object returned from
	* {@link module:engine/view/matcher~Matcher#match match} or {@link module:engine/view/matcher~Matcher#matchAll matchAll} methods.
	*/
	add(...pattern: Array<MatcherPattern>): void;
	/**
	* Matches elements for currently stored patterns. Returns match information about first found
	* {@link module:engine/view/element~ViewElement element}, otherwise returns `null`.
	*
	* Example of returned object:
	*
	* ```ts
	* {
	* 	element: <instance of found element>,
	* 	pattern: <pattern used to match found element>,
	* 	match: {
	* 		name: true,
	* 		attributes: [
	* 			[ 'title' ],
	* 			[ 'href' ],
	* 			[ 'class', 'foo' ],
	* 			[ 'style', 'color' ],
	* 			[ 'style', 'position' ]
	* 		]
	* 	}
	* }
	* ```
	*
	* You could use the `match` field from the above returned object as an input for the
	* {@link module:engine/conversion/viewconsumable~ViewConsumable#test `ViewConsumable#test()`} and
	* {@link module:engine/conversion/viewconsumable~ViewConsumable#consume `ViewConsumable#consume()`} methods.
	*
	* @see module:engine/view/matcher~Matcher#add
	* @see module:engine/view/matcher~Matcher#matchAll
	* @param element View element to match against stored patterns.
	* @returns The match information about found element or `null`.
	*/
	match(...element: Array<ViewElement>): MatchResult | null;
	/**
	* Matches elements for currently stored patterns. Returns array of match information with all found
	* {@link module:engine/view/element~ViewElement elements}. If no element is found - returns `null`.
	*
	* @see module:engine/view/matcher~Matcher#add
	* @see module:engine/view/matcher~Matcher#match
	* @param element View element to match against stored patterns.
	* @returns Array with match information about found elements or `null`. For more information
	* see {@link module:engine/view/matcher~Matcher#match match method} description.
	*/
	matchAll(...element: Array<ViewElement>): Array<MatchResult> | null;
	/**
	* Returns the name of the element to match if there is exactly one pattern added to the matcher instance
	* and it matches element name defined by `string` (not `RegExp`). Otherwise, returns `null`.
	*
	* @returns Element name trying to match.
	*/
	getElementName(): string | null;
	/**
	* Returns match information if {@link module:engine/view/element~ViewElement element} is matching provided pattern.
	* If element cannot be matched to provided pattern - returns `null`.
	*
	* @returns Returns object with match information or null if element is not matching.
	*/
	private _isElementMatching;
}
/**
* Returns true if the given `item` matches the pattern.
*
* @internal
* @param pattern A pattern representing a key/value we want to match.
* @param item An actual item key/value (e.g. `'src'`, `'background-color'`, `'ck-widget'`) we're testing against pattern.
*/
export declare function isPatternMatched(pattern: true | string | RegExp, item: string): unknown;
/**
* An entity that is a valid pattern recognized by a matcher. `MatcherPattern` is used by {@link ~Matcher} to recognize
* if a view element fits in a group of view elements described by the pattern.
*
* `MatcherPattern` can be given as a `String`, a `RegExp`, an `Object` or a `Function`.
*
* If `MatcherPattern` is given as a `String` or `RegExp`, it will match any view element that has a matching name:
*
* ```ts
* // Match any element with name equal to 'div'.
* const pattern = 'div';
*
* // Match any element which name starts on 'p'.
* const pattern = /^p/;
* ```
*
* If `MatcherPattern` is given as an `Object`, all the object's properties will be matched with view element properties.
* If the view element does not meet all of the object's pattern properties, the match will not happen.
* Available `Object` matching properties:
*
* Matching view element:
*
* ```ts
* // Match view element's name using String:
* const pattern = { name: 'p' };
*
* // or by providing RegExp:
* const pattern = { name: /^(ul|ol)$/ };
*
* // The name can also be skipped to match any view element with matching attributes:
* const pattern = {
* 	attributes: {
* 		'title': true
* 	}
* };
* ```
*
* Matching view element attributes:
*
* ```ts
* // Match view element with any attribute value.
* const pattern = {
* 	name: 'p',
* 	attributes: true
* };
*
* // Match view element which has matching attributes (String).
* const pattern = {
* 	name: 'figure',
* 	attributes: 'title' // Match title attribute (can be empty).
* };
*
* // Match view element which has matching attributes (RegExp).
* const pattern = {
* 	name: 'figure',
* 	attributes: /^data-.*$/ // Match attributes starting with `data-` e.g. `data-foo` with any value (can be empty).
* };
*
* // Match view element which has matching attributes (Object).
* const pattern = {
* 	name: 'figure',
* 	attributes: {
* 		title: 'foobar',           // Match `title` attribute with 'foobar' value.
* 		alt: true,                 // Match `alt` attribute with any value (can be empty).
* 		'data-type': /^(jpg|png)$/ // Match `data-type` attribute with `jpg` or `png` value.
* 	}
* };
*
* // Match view element which has matching attributes (Array).
* const pattern = {
* 	name: 'figure',
* 	attributes: [
* 		'title',    // Match `title` attribute (can be empty).
* 		/^data-*$/ // Match attributes starting with `data-` e.g. `data-foo` with any value (can be empty).
* 	]
* };
*
* // Match view element which has matching attributes (key-value pairs).
* const pattern = {
* 	name: 'input',
* 	attributes: [
* 		{
* 			key: 'type',                     // Match `type` as an attribute key.
* 			value: /^(text|number|date)$/	 // Match `text`, `number` or `date` values.
* 		},
* 		{
* 			key: /^data-.*$/,                // Match attributes starting with `data-` e.g. `data-foo`.
* 			value: true                      // Match any value (can be empty).
* 		}
* 	]
* };
* ```
*
* Matching view element styles:
*
* ```ts
* // Match view element with any style.
* const pattern = {
* 	name: 'p',
* 	styles: true
* };
*
* // Match view element which has matching styles (String).
* const pattern = {
* 	name: 'p',
* 	styles: 'color' // Match attributes with `color` style.
* };
*
* // Match view element which has matching styles (RegExp).
* const pattern = {
* 	name: 'p',
* 	styles: /^border.*$/ // Match view element with any border style.
* };
*
* // Match view element which has matching styles (Object).
* const pattern = {
* 	name: 'p',
* 	styles: {
* 		color: /rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)/, // Match `color` in RGB format only.
* 		'font-weight': 600,                              // Match `font-weight` only if it's `600`.
* 		'text-decoration': true                          // Match any text decoration.
* 	}
* };
*
* // Match view element which has matching styles (Array).
* const pattern = {
* 	name: 'p',
* 	styles: [
* 		'color',      // Match `color` with any value.
* 		/^border.*$/ // Match all border properties.
* 	]
* };
*
* // Match view element which has matching styles (key-value pairs).
* const pattern = {
* 	name: 'p',
* 	styles: [
* 		{
* 			key: 'color',                                  		// Match `color` as an property key.
* 			value: /rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)/		// Match RGB format only.
* 		},
* 		{
* 			key: /^border.*$/, // Match any border style.
* 			value: true        // Match any value.
* 		}
* 	]
* };
* ```
*
* Matching view element classes:
*
* ```ts
* // Match view element with any class.
* const pattern = {
* 	name: 'p',
* 	classes: true
* };
*
* // Match view element which has matching class (String).
* const pattern = {
* 	name: 'p',
* 	classes: 'highlighted' // Match `highlighted` class.
* };
*
* // Match view element which has matching classes (RegExp).
* const pattern = {
* 	name: 'figure',
* 	classes: /^image-side-(left|right)$/ // Match `image-side-left` or `image-side-right` class.
* };
*
* // Match view element which has matching classes (Object).
* const pattern = {
* 	name: 'p',
* 	classes: {
* 		highlighted: true, // Match `highlighted` class.
* 		marker: true       // Match `marker` class.
* 	}
* };
*
* // Match view element which has matching classes (Array).
* const pattern = {
* 	name: 'figure',
* 	classes: [
* 		'image',                    // Match `image` class.
* 		/^image-side-(left|right)$/ // Match `image-side-left` or `image-side-right` class.
* 	]
* };
*
* // Match view element which has matching classes (key-value pairs).
* const pattern = {
* 	name: 'figure',
* 	classes: [
* 		{
* 			key: 'image', // Match `image` class.
* 			value: true
* 		},
* 		{
* 			key: /^image-side-(left|right)$/, // Match `image-side-left` or `image-side-right` class.
* 			value: true
* 		}
* 	]
* };
* ```
*
* Pattern can combine multiple properties allowing for more complex view element matching:
*
* ```ts
* const pattern = {
* 	name: 'span',
* 	attributes: [ 'title' ],
* 	styles: {
* 		'font-weight': 'bold'
* 	},
* 	classes: 'highlighted'
* };
* ```
*
* If `MatcherPattern` is given as a `Function`, the function takes a view element as a first and only parameter and
* the function should decide whether that element matches. If so, it should return what part of the view element has been matched.
* Otherwise, the function should return `null`. The returned result will be included in `match` property of the object
* returned by {@link ~Matcher#match} call.
*
* ```ts
* // Match an empty <div> element.
* const pattern = element => {
* 	if ( element.name == 'div' && element.childCount > 0 ) {
* 		// Return which part of the element was matched.
* 		return { name: true };
* 	}
*
* 	return null;
* };
*
* // Match a <p> element with big font ("heading-like" element).
* const pattern = element => {
* 	if ( element.name == 'p' ) {
* 		const fontSize = element.getStyle( 'font-size' );
* 		const size = fontSize.match( /(\d+)/px );
*
* 		if ( size && Number( size[ 1 ] ) > 26 ) {
* 			return { name: true, styles: [ 'font-size' ] };
* 		}
* 	}
*
* 	return null;
* };
* ```
*
* `MatcherPattern` is defined in a way that it is a superset of {@link module:engine/view/elementdefinition~ViewElementDefinition},
* that is, every `ElementDefinition` also can be used as a `MatcherPattern`.
*/
export type MatcherPattern = string | RegExp | MatcherFunctionPattern | MatcherObjectPattern;
/**
* A function describing `MatcherPattern`. See {@link ~MatcherPattern} for examples and other options.
*/
export type MatcherFunctionPattern = (element: ViewElement) => Match | Consumables | null;
/**
* An object describing `MatcherPattern`. See {@link ~MatcherPattern} for examples and other options.
*/
export interface MatcherObjectPattern {
	/**
	* View element name to match.
	*/
	name?: string | RegExp;
	/**
	* View element's classes to match.
	*/
	classes?: MatchClassPatterns;
	/**
	* View element's styles to match.
	*/
	styles?: MatchStylePatterns;
	/**
	* View element's attributes to match.
	*/
	attributes?: MatchAttributePatterns;
}
/**
* An object representing matched element parts.
*/
export interface Match {
	/**
	* True if name of the element was matched.
	*/
	name?: boolean;
	/**
	* Array of matching tuples: attribute name, and optional token for tokenized attributes.
	* Note that there could be multiple entries for the same attribute with different tokens (class names or style properties).
	*/
	attributes?: Array<[string, string?]>;
}
/**
* The result of {@link ~Matcher#match}.
*/
export interface MatchResult {
	/**
	* Matched view element.
	*/
	element: ViewElement;
	/**
	* Pattern that was used to find matched element.
	*/
	pattern: MatcherFunctionPattern | MatcherObjectPattern;
	/**
	* An object representing matched element parts.
	*/
	match: Match;
}
export type MatchPropertyPatterns<ValuePattern = string | RegExp> = true | string | RegExp | Record<string, true | ValuePattern> | Array<string | RegExp | {
	key: string | RegExp;
	value: true | ValuePattern;
}>;
export type MatchAttributePatterns = MatchPropertyPatterns;
export type MatchStylePatterns = MatchPropertyPatterns;
export type MatchClassPatterns = MatchPropertyPatterns<never>;
/**
* @internal
*/
export type NormalizedPropertyPattern = [true | string | RegExp, true | string | RegExp, (true | string | RegExp)?];
