(*--------------------------------------------------------------------------- Copyright (c) 2025 Anil Madhavapeddy . All rights reserved. SPDX-License-Identifier: MIT ---------------------------------------------------------------------------*) (** Browser DOM utilities for mapping validation results to live elements. This module bridges the gap between HTML string validation (which produces line/column locations) and live DOM manipulation (which needs element references). It builds mappings between source positions and DOM elements by walking both the serialized HTML and the DOM tree in parallel. *) (** {1 Element Mapping} When we validate [element.outerHTML], we get messages with line/column positions. To annotate the original DOM, we need to map those positions back to the live elements. *) (** An element map associates source locations with DOM elements. *) type t (** Build an element map by walking a DOM element and its serialization. This function: 1. Serializes the element to HTML via [outerHTML] 2. Parses that HTML with Html5rw to get the parse tree with locations 3. Walks both trees in parallel to build a bidirectional mapping @param root The DOM element to map. @return The element map and the HTML source string. *) val create : Brr.El.t -> t * string (** Find the DOM element corresponding to a source location. @param line 1-indexed line number @param column 1-indexed column number @return The element at or containing that position, or [None]. *) val find_by_location : t -> line:int -> column:int -> Brr.El.t option (** Find the DOM element corresponding to an element name at a location. More precise than {!find_by_location} when the validator provides the element name along with the location. @param line 1-indexed line number @param column 1-indexed column number @param tag Element tag name (lowercase) @return The matching element, or [None]. *) val find_by_location_and_tag : t -> line:int -> column:int -> tag:string -> Brr.El.t option (** Find the DOM element for a validation message. Uses the message's location and element fields to find the best match. This is the primary function used by the annotation system. *) val find_for_message : t -> Htmlrw_check.message -> Brr.El.t option (** The HTML source string that was used to build this map. *) val html_source : t -> string (** The root element this map was built from. *) val root_element : t -> Brr.El.t (** {1 CSS Selector Generation} *) (** Build a CSS selector path that uniquely identifies an element. The selector uses child combinators and [:nth-child] to be specific: ["body > div.main:nth-child(2) > p > img:nth-child(1)"] @param root Optional root element; selector will be relative to this. Defaults to [document.body]. @param el The element to build a selector for. @return A CSS selector string. *) val selector_path : ?root:Brr.El.t -> Brr.El.t -> string (** Build a shorter selector using IDs and classes when available. Tries to find the shortest unique selector: 1. If element has an ID: ["#myId"] 2. If parent has ID: ["#parentId > .myClass"] 3. Falls back to full path from {!selector_path} @param root Optional root element. @param el The element to build a selector for. *) val short_selector : ?root:Brr.El.t -> Brr.El.t -> string (** {1 DOM Iteration} *) (** Iterate over all elements in document order (depth-first pre-order). *) val iter_elements : (Brr.El.t -> unit) -> Brr.El.t -> unit (** Fold over all elements in document order. *) val fold_elements : ('a -> Brr.El.t -> 'a) -> 'a -> Brr.El.t -> 'a (** Find all elements matching a predicate. *) val filter_elements : (Brr.El.t -> bool) -> Brr.El.t -> Brr.El.t list (** {1 Serialization} *) (** Get the outer HTML of an element. This is a wrapper around the browser's [outerHTML] property. *) val outer_html : Brr.El.t -> string (** Get the inner HTML of an element. *) val inner_html : Brr.El.t -> string