import * as Common from "../../core/common/common.js";
import * as Host from "../../core/host/host.js";
import * as i18n from "../../core/i18n/i18n.js";
import * as Platform from "../../core/platform/platform.js";
import * as SDK from "../../core/sdk/sdk.js";
import * as TextUtils from "../../models/text_utils/text_utils.js";
import * as CodeMirror from "../../third_party/codemirror.next/codemirror.next.js";
import * as Adorners from "../../ui/components/adorners/adorners.js";
import * as CodeHighlighter from "../../ui/components/code_highlighter/code_highlighter.js";
import * as TextEditor from "../../ui/components/text_editor/text_editor.js";
import * as Components from "../../ui/legacy/components/utils/utils.js";
import * as UI from "../../ui/legacy/legacy.js";
import * as Emulation from "../emulation/emulation.js";
import * as ElementsComponents from "./components/components.js";
import { canGetJSPath, cssPath, jsPath, xPath } from "./DOMPath.js";
import { ElementsPanel } from "./ElementsPanel.js";
import { MappedCharToEntity } from "./ElementsTreeOutline.js";
import { ImagePreviewPopover } from "./ImagePreviewPopover.js";
import { getRegisteredDecorators } from "./MarkerDecorator.js";
const UIStrings = {
  thisFrameWasIdentifiedAsAnAd: "This frame was identified as an ad frame",
  forceState: "Force state",
  useSInTheConsoleToReferToThis: "Use {PH1} in the console to refer to this element.",
  addAttribute: "Add attribute",
  editAttribute: "Edit attribute",
  focus: "Focus",
  scrollIntoView: "Scroll into view",
  enterIsolationMode: "Enter Isolation Mode",
  exitIsolationMode: "Exit Isolation Mode",
  editText: "Edit text",
  editAsHtml: "Edit as HTML",
  cut: "Cut",
  copy: "Copy",
  paste: "Paste",
  copyOuterhtml: "Copy outerHTML",
  copySelector: "Copy `selector`",
  copyJsPath: "Copy JS path",
  copyStyles: "Copy styles",
  copyXpath: "Copy XPath",
  copyFullXpath: "Copy full XPath",
  copyElement: "Copy element",
  duplicateElement: "Duplicate element",
  hideElement: "Hide element",
  deleteElement: "Delete element",
  expandRecursively: "Expand recursively",
  collapseChildren: "Collapse children",
  captureNodeScreenshot: "Capture node screenshot",
  showFrameDetails: "Show `iframe` details",
  valueIsTooLargeToEdit: "<value is too large to edit>",
  children: "Children:",
  enableGridMode: "Enable grid mode",
  disableGridMode: "Disable grid mode",
  enableFlexMode: "Enable flex mode",
  disableFlexMode: "Disable flex mode",
  enableScrollSnap: "Enable scroll-snap overlay",
  disableScrollSnap: "Disable scroll-snap overlay"
};
const str_ = i18n.i18n.registerUIStrings("panels/elements/ElementsTreeElement.ts", UIStrings);
const i18nString = i18n.i18n.getLocalizedString.bind(void 0, str_);
export class ElementsTreeElement extends UI.TreeOutline.TreeElement {
  nodeInternal;
  treeOutline;
  gutterContainer;
  decorationsElement;
  isClosingTagInternal;
  canAddAttributes;
  searchQuery;
  expandedChildrenLimitInternal;
  decorationsThrottler;
  inClipboard;
  hoveredInternal;
  editing;
  highlightResult;
  adornerContainer;
  adorners;
  styleAdorners;
  adornersThrottler;
  htmlEditElement;
  expandAllButtonElement;
  searchHighlightsVisible;
  selectionElement;
  hintElement;
  contentElement;
  constructor(node, isClosingTag) {
    super();
    this.nodeInternal = node;
    this.treeOutline = null;
    this.contentElement = this.listItemElement.createChild("div");
    this.gutterContainer = this.contentElement.createChild("div", "gutter-container");
    this.gutterContainer.addEventListener("click", this.showContextMenu.bind(this));
    const gutterMenuIcon = UI.Icon.Icon.create("largeicon-menu", "gutter-menu-icon");
    this.gutterContainer.append(gutterMenuIcon);
    this.decorationsElement = this.gutterContainer.createChild("div", "hidden");
    this.isClosingTagInternal = isClosingTag;
    if (this.nodeInternal.nodeType() === Node.ELEMENT_NODE && !isClosingTag) {
      this.canAddAttributes = true;
    }
    this.searchQuery = null;
    this.expandedChildrenLimitInternal = InitialChildrenLimit;
    this.decorationsThrottler = new Common.Throttler.Throttler(100);
    this.inClipboard = false;
    this.hoveredInternal = false;
    this.editing = null;
    this.highlightResult = [];
    if (!isClosingTag) {
      this.adornerContainer = this.contentElement.createChild("div", "adorner-container hidden");
      this.adorners = [];
      this.styleAdorners = [];
      this.adornersThrottler = new Common.Throttler.Throttler(100);
      void this.updateStyleAdorners();
      if (node.isAdFrameNode()) {
        const config = ElementsComponents.AdornerManager.getRegisteredAdorner(ElementsComponents.AdornerManager.RegisteredAdorners.AD);
        const adorner = this.adorn(config);
        UI.Tooltip.Tooltip.install(adorner, i18nString(UIStrings.thisFrameWasIdentifiedAsAnAd));
      }
    }
    this.expandAllButtonElement = null;
  }
  static animateOnDOMUpdate(treeElement) {
    const tagName = treeElement.listItemElement.querySelector(".webkit-html-tag-name");
    UI.UIUtils.runCSSAnimationOnce(tagName || treeElement.listItemElement, "dom-update-highlight");
  }
  static visibleShadowRoots(node) {
    let roots = node.shadowRoots();
    if (roots.length && !Common.Settings.Settings.instance().moduleSetting("showUAShadowDOM").get()) {
      roots = roots.filter(filter);
    }
    function filter(root) {
      return root.shadowRootType() !== SDK.DOMModel.DOMNode.ShadowRootTypes.UserAgent;
    }
    return roots;
  }
  static canShowInlineText(node) {
    if (node.contentDocument() || node.templateContent() || ElementsTreeElement.visibleShadowRoots(node).length || node.hasPseudoElements()) {
      return false;
    }
    if (node.nodeType() !== Node.ELEMENT_NODE) {
      return false;
    }
    if (!node.firstChild || node.firstChild !== node.lastChild || node.firstChild.nodeType() !== Node.TEXT_NODE) {
      return false;
    }
    const textChild = node.firstChild;
    const maxInlineTextChildLength = 80;
    if (textChild.nodeValue().length < maxInlineTextChildLength) {
      return true;
    }
    return false;
  }
  static populateForcedPseudoStateItems(contextMenu, node) {
    const pseudoClasses = ["active", "hover", "focus", "visited", "focus-within", "focus-visible"];
    const forcedPseudoState = node.domModel().cssModel().pseudoState(node);
    const stateMenu = contextMenu.debugSection().appendSubMenuItem(i18nString(UIStrings.forceState));
    for (const pseudoClass of pseudoClasses) {
      const pseudoClassForced = forcedPseudoState ? forcedPseudoState.indexOf(pseudoClass) >= 0 : false;
      stateMenu.defaultSection().appendCheckboxItem(":" + pseudoClass, setPseudoStateCallback.bind(null, pseudoClass, !pseudoClassForced), pseudoClassForced, false);
    }
    function setPseudoStateCallback(pseudoState, enabled) {
      node.domModel().cssModel().forcePseudoState(node, pseudoState, enabled);
    }
  }
  isClosingTag() {
    return Boolean(this.isClosingTagInternal);
  }
  node() {
    return this.nodeInternal;
  }
  isEditing() {
    return Boolean(this.editing);
  }
  highlightSearchResults(searchQuery) {
    if (this.searchQuery !== searchQuery) {
      this.hideSearchHighlight();
    }
    this.searchQuery = searchQuery;
    this.searchHighlightsVisible = true;
    this.updateTitle(null, true);
  }
  hideSearchHighlights() {
    delete this.searchHighlightsVisible;
    this.hideSearchHighlight();
  }
  hideSearchHighlight() {
    if (this.highlightResult.length === 0) {
      return;
    }
    for (let i = this.highlightResult.length - 1; i >= 0; --i) {
      const entry = this.highlightResult[i];
      switch (entry.type) {
        case "added":
          entry.node.remove();
          break;
        case "changed":
          entry.node.textContent = entry.oldText || null;
          break;
      }
    }
    this.highlightResult = [];
  }
  setInClipboard(inClipboard) {
    if (this.inClipboard === inClipboard) {
      return;
    }
    this.inClipboard = inClipboard;
    this.listItemElement.classList.toggle("in-clipboard", inClipboard);
  }
  get hovered() {
    return this.hoveredInternal;
  }
  set hovered(isHovered) {
    if (this.hoveredInternal === isHovered) {
      return;
    }
    this.hoveredInternal = isHovered;
    if (this.listItemElement) {
      if (isHovered) {
        this.createSelection();
        this.listItemElement.classList.add("hovered");
      } else {
        this.listItemElement.classList.remove("hovered");
      }
    }
  }
  expandedChildrenLimit() {
    return this.expandedChildrenLimitInternal;
  }
  setExpandedChildrenLimit(expandedChildrenLimit) {
    this.expandedChildrenLimitInternal = expandedChildrenLimit;
  }
  createSelection() {
    const contentElement = this.contentElement;
    if (!contentElement) {
      return;
    }
    if (!this.selectionElement) {
      this.selectionElement = document.createElement("div");
      this.selectionElement.className = "selection fill";
      this.selectionElement.style.setProperty("margin-left", -this.computeLeftIndent() + "px");
      contentElement.prepend(this.selectionElement);
    }
  }
  createHint() {
    if (this.contentElement && !this.hintElement) {
      this.hintElement = this.contentElement.createChild("span", "selected-hint");
      const selectedElementCommand = "$0";
      UI.Tooltip.Tooltip.install(this.hintElement, i18nString(UIStrings.useSInTheConsoleToReferToThis, { PH1: selectedElementCommand }));
      UI.ARIAUtils.markAsHidden(this.hintElement);
    }
  }
  onbind() {
    if (this.treeOutline && !this.isClosingTagInternal) {
      this.treeOutline.treeElementByNode.set(this.nodeInternal, this);
    }
  }
  onunbind() {
    if (this.editing) {
      this.editing.cancel();
    }
    if (this.treeOutline && this.treeOutline.treeElementByNode.get(this.nodeInternal) === this) {
      this.treeOutline.treeElementByNode.delete(this.nodeInternal);
    }
  }
  onattach() {
    if (this.hoveredInternal) {
      this.createSelection();
      this.listItemElement.classList.add("hovered");
    }
    this.updateTitle();
    this.listItemElement.draggable = true;
  }
  async onpopulate() {
    if (this.treeOutline) {
      return this.treeOutline.populateTreeElement(this);
    }
  }
  async expandRecursively() {
    await this.nodeInternal.getSubtree(-1, true);
    await super.expandRecursively(Number.MAX_VALUE);
  }
  onexpand() {
    if (this.isClosingTagInternal) {
      return;
    }
    this.updateTitle();
  }
  oncollapse() {
    if (this.isClosingTagInternal) {
      return;
    }
    this.updateTitle();
  }
  select(omitFocus, selectedByUser) {
    if (this.editing) {
      return false;
    }
    return super.select(omitFocus, selectedByUser);
  }
  onselect(selectedByUser) {
    if (!this.treeOutline) {
      return false;
    }
    this.treeOutline.suppressRevealAndSelect = true;
    this.treeOutline.selectDOMNode(this.nodeInternal, selectedByUser);
    if (selectedByUser) {
      this.nodeInternal.highlight();
      Host.userMetrics.actionTaken(Host.UserMetrics.Action.ChangeInspectedNodeInElementsPanel);
    }
    this.createSelection();
    this.createHint();
    this.treeOutline.suppressRevealAndSelect = false;
    return true;
  }
  ondelete() {
    if (!this.treeOutline) {
      return false;
    }
    const startTagTreeElement = this.treeOutline.findTreeElement(this.nodeInternal);
    startTagTreeElement ? startTagTreeElement.remove() : this.remove();
    return true;
  }
  onenter() {
    if (this.editing) {
      return false;
    }
    this.startEditing();
    return true;
  }
  selectOnMouseDown(event) {
    super.selectOnMouseDown(event);
    if (this.editing) {
      return;
    }
    if (event.detail >= 2) {
      event.preventDefault();
    }
  }
  ondblclick(event) {
    if (this.editing || this.isClosingTagInternal) {
      return false;
    }
    if (this.startEditingTarget(event.target)) {
      return false;
    }
    if (this.isExpandable() && !this.expanded) {
      this.expand();
    }
    return false;
  }
  hasEditableNode() {
    return !this.nodeInternal.isShadowRoot() && !this.nodeInternal.ancestorUserAgentShadowRoot();
  }
  insertInLastAttributePosition(tag, node) {
    if (tag.getElementsByClassName("webkit-html-attribute").length > 0) {
      tag.insertBefore(node, tag.lastChild);
    } else if (tag.textContent !== null) {
      const matchResult = tag.textContent.match(/^<(.*?)>$/);
      if (!matchResult) {
        return;
      }
      const nodeName = matchResult[1];
      tag.textContent = "";
      UI.UIUtils.createTextChild(tag, "<" + nodeName);
      tag.appendChild(node);
      UI.UIUtils.createTextChild(tag, ">");
    }
  }
  startEditingTarget(eventTarget) {
    if (!this.treeOutline || this.treeOutline.selectedDOMNode() !== this.nodeInternal) {
      return false;
    }
    if (this.nodeInternal.nodeType() !== Node.ELEMENT_NODE && this.nodeInternal.nodeType() !== Node.TEXT_NODE) {
      return false;
    }
    const textNode = eventTarget.enclosingNodeOrSelfWithClass("webkit-html-text-node");
    if (textNode) {
      return this.startEditingTextNode(textNode);
    }
    const attribute = eventTarget.enclosingNodeOrSelfWithClass("webkit-html-attribute");
    if (attribute) {
      return this.startEditingAttribute(attribute, eventTarget);
    }
    const tagName = eventTarget.enclosingNodeOrSelfWithClass("webkit-html-tag-name");
    if (tagName) {
      return this.startEditingTagName(tagName);
    }
    const newAttribute = eventTarget.enclosingNodeOrSelfWithClass("add-attribute");
    if (newAttribute) {
      return this.addNewAttribute();
    }
    return false;
  }
  showContextMenu(event) {
    this.treeOutline && this.treeOutline.showContextMenu(this, event);
  }
  populateTagContextMenu(contextMenu, event) {
    const treeElement = this.isClosingTagInternal && this.treeOutline ? this.treeOutline.findTreeElement(this.nodeInternal) : this;
    if (!treeElement) {
      return;
    }
    contextMenu.editSection().appendItem(i18nString(UIStrings.addAttribute), treeElement.addNewAttribute.bind(treeElement));
    const target = event.target;
    const attribute = target.enclosingNodeOrSelfWithClass("webkit-html-attribute");
    const newAttribute = target.enclosingNodeOrSelfWithClass("add-attribute");
    if (attribute && !newAttribute) {
      contextMenu.editSection().appendItem(i18nString(UIStrings.editAttribute), this.startEditingAttribute.bind(this, attribute, target));
    }
    this.populateNodeContextMenu(contextMenu);
    ElementsTreeElement.populateForcedPseudoStateItems(contextMenu, treeElement.node());
    this.populateScrollIntoView(contextMenu);
    contextMenu.viewSection().appendItem(i18nString(UIStrings.focus), async () => {
      await this.nodeInternal.focus();
    });
    const overlayModel = this.nodeInternal.domModel().overlayModel();
    if (overlayModel.isHighlightedIsolatedElementInPersistentOverlay(this.nodeInternal.id)) {
      contextMenu.viewSection().appendItem(i18nString(UIStrings.exitIsolationMode), () => {
        overlayModel.hideIsolatedElementInPersistentOverlay(this.nodeInternal.id);
      });
    } else {
      contextMenu.viewSection().appendItem(i18nString(UIStrings.enterIsolationMode), () => {
        overlayModel.highlightIsolatedElementInPersistentOverlay(this.nodeInternal.id);
      });
    }
  }
  populateScrollIntoView(contextMenu) {
    contextMenu.viewSection().appendItem(i18nString(UIStrings.scrollIntoView), () => this.nodeInternal.scrollIntoView());
  }
  populateTextContextMenu(contextMenu, textNode) {
    if (!this.editing) {
      contextMenu.editSection().appendItem(i18nString(UIStrings.editText), this.startEditingTextNode.bind(this, textNode));
    }
    this.populateNodeContextMenu(contextMenu);
  }
  populateNodeContextMenu(contextMenu) {
    const isEditable = this.hasEditableNode();
    if (isEditable && !this.editing) {
      contextMenu.editSection().appendItem(i18nString(UIStrings.editAsHtml), this.editAsHTML.bind(this));
    }
    const isShadowRoot = this.nodeInternal.isShadowRoot();
    const createShortcut = UI.KeyboardShortcut.KeyboardShortcut.shortcutToString.bind(null);
    const modifier = UI.KeyboardShortcut.Modifiers.CtrlOrMeta;
    const treeOutline = this.treeOutline;
    if (!treeOutline) {
      return;
    }
    let menuItem;
    menuItem = contextMenu.clipboardSection().appendItem(i18nString(UIStrings.cut), treeOutline.performCopyOrCut.bind(treeOutline, true, this.nodeInternal), !this.hasEditableNode());
    menuItem.setShortcut(createShortcut("X", modifier));
    const copyMenu = contextMenu.clipboardSection().appendSubMenuItem(i18nString(UIStrings.copy));
    const section = copyMenu.section();
    if (!isShadowRoot) {
      menuItem = section.appendItem(i18nString(UIStrings.copyOuterhtml), treeOutline.performCopyOrCut.bind(treeOutline, false, this.nodeInternal));
      menuItem.setShortcut(createShortcut("V", modifier));
    }
    if (this.nodeInternal.nodeType() === Node.ELEMENT_NODE) {
      section.appendItem(i18nString(UIStrings.copySelector), this.copyCSSPath.bind(this));
      section.appendItem(i18nString(UIStrings.copyJsPath), this.copyJSPath.bind(this), !canGetJSPath(this.nodeInternal));
      section.appendItem(i18nString(UIStrings.copyStyles), this.copyStyles.bind(this));
    }
    if (!isShadowRoot) {
      section.appendItem(i18nString(UIStrings.copyXpath), this.copyXPath.bind(this));
      section.appendItem(i18nString(UIStrings.copyFullXpath), this.copyFullXPath.bind(this));
    }
    if (!isShadowRoot) {
      menuItem = copyMenu.clipboardSection().appendItem(i18nString(UIStrings.copyElement), treeOutline.performCopyOrCut.bind(treeOutline, false, this.nodeInternal));
      menuItem.setShortcut(createShortcut("C", modifier));
      const isRootElement = !this.nodeInternal.parentNode || this.nodeInternal.parentNode.nodeName() === "#document";
      menuItem = contextMenu.editSection().appendItem(i18nString(UIStrings.duplicateElement), treeOutline.duplicateNode.bind(treeOutline, this.nodeInternal), this.nodeInternal.isInShadowTree() || isRootElement);
    }
    menuItem = contextMenu.clipboardSection().appendItem(i18nString(UIStrings.paste), treeOutline.pasteNode.bind(treeOutline, this.nodeInternal), !treeOutline.canPaste(this.nodeInternal));
    menuItem.setShortcut(createShortcut("V", modifier));
    menuItem = contextMenu.debugSection().appendCheckboxItem(i18nString(UIStrings.hideElement), treeOutline.toggleHideElement.bind(treeOutline, this.nodeInternal), treeOutline.isToggledToHidden(this.nodeInternal));
    menuItem.setShortcut(UI.ShortcutRegistry.ShortcutRegistry.instance().shortcutTitleForAction("elements.hide-element") || "");
    if (isEditable) {
      contextMenu.editSection().appendItem(i18nString(UIStrings.deleteElement), this.remove.bind(this));
    }
    contextMenu.viewSection().appendItem(i18nString(UIStrings.expandRecursively), this.expandRecursively.bind(this));
    contextMenu.viewSection().appendItem(i18nString(UIStrings.collapseChildren), this.collapseChildren.bind(this));
    const deviceModeWrapperAction = new Emulation.DeviceModeWrapper.ActionDelegate();
    contextMenu.viewSection().appendItem(i18nString(UIStrings.captureNodeScreenshot), deviceModeWrapperAction.handleAction.bind(null, UI.Context.Context.instance(), "emulation.capture-node-screenshot"));
    if (this.nodeInternal.frameOwnerFrameId()) {
      contextMenu.viewSection().appendItem(i18nString(UIStrings.showFrameDetails), () => {
        const frameOwnerFrameId = this.nodeInternal.frameOwnerFrameId();
        if (frameOwnerFrameId) {
          const frame = SDK.FrameManager.FrameManager.instance().getFrame(frameOwnerFrameId);
          void Common.Revealer.reveal(frame);
        }
      });
    }
  }
  startEditing() {
    if (!this.treeOutline || this.treeOutline.selectedDOMNode() !== this.nodeInternal) {
      return;
    }
    const listItem = this.listItemElement;
    if (this.canAddAttributes) {
      const attribute = listItem.getElementsByClassName("webkit-html-attribute")[0];
      if (attribute) {
        return this.startEditingAttribute(attribute, attribute.getElementsByClassName("webkit-html-attribute-value")[0]);
      }
      return this.addNewAttribute();
    }
    if (this.nodeInternal.nodeType() === Node.TEXT_NODE) {
      const textNode = listItem.getElementsByClassName("webkit-html-text-node")[0];
      if (textNode) {
        return this.startEditingTextNode(textNode);
      }
    }
    return;
  }
  addNewAttribute() {
    const container = document.createElement("span");
    const attr = this.buildAttributeDOM(container, " ", "", null);
    attr.style.marginLeft = "2px";
    attr.style.marginRight = "2px";
    const tag = this.listItemElement.getElementsByClassName("webkit-html-tag")[0];
    this.insertInLastAttributePosition(tag, attr);
    attr.scrollIntoViewIfNeeded(true);
    return this.startEditingAttribute(attr, attr);
  }
  triggerEditAttribute(attributeName) {
    const attributeElements = this.listItemElement.getElementsByClassName("webkit-html-attribute-name");
    for (let i = 0, len = attributeElements.length; i < len; ++i) {
      if (attributeElements[i].textContent === attributeName) {
        for (let elem = attributeElements[i].nextSibling; elem; elem = elem.nextSibling) {
          if (elem.nodeType !== Node.ELEMENT_NODE) {
            continue;
          }
          if (elem.classList.contains("webkit-html-attribute-value")) {
            return this.startEditingAttribute(elem.parentElement, elem);
          }
        }
      }
    }
    return;
  }
  startEditingAttribute(attribute, elementForSelection) {
    console.assert(this.listItemElement.isAncestor(attribute));
    if (UI.UIUtils.isBeingEdited(attribute)) {
      return true;
    }
    const attributeNameElement = attribute.getElementsByClassName("webkit-html-attribute-name")[0];
    if (!attributeNameElement) {
      return false;
    }
    const attributeName = attributeNameElement.textContent;
    const attributeValueElement = attribute.getElementsByClassName("webkit-html-attribute-value")[0];
    elementForSelection = attributeValueElement.isAncestor(elementForSelection) ? attributeValueElement : elementForSelection;
    function removeZeroWidthSpaceRecursive(node) {
      if (node.nodeType === Node.TEXT_NODE) {
        node.nodeValue = node.nodeValue ? node.nodeValue.replace(/\u200B/g, "") : "";
        return;
      }
      if (node.nodeType !== Node.ELEMENT_NODE) {
        return;
      }
      for (let child = node.firstChild; child; child = child.nextSibling) {
        removeZeroWidthSpaceRecursive(child);
      }
    }
    const attributeValue = attributeName && attributeValueElement ? this.nodeInternal.getAttribute(attributeName) : void 0;
    if (attributeValue !== void 0) {
      attributeValueElement.setTextContentTruncatedIfNeeded(attributeValue, i18nString(UIStrings.valueIsTooLargeToEdit));
    }
    removeZeroWidthSpaceRecursive(attribute);
    const config = new UI.InplaceEditor.Config(this.attributeEditingCommitted.bind(this), this.editingCancelled.bind(this), attributeName || void 0);
    function postKeyDownFinishHandler(event) {
      UI.UIUtils.handleElementValueModifications(event, attribute);
      return "";
    }
    if (!Common.ParsedURL.ParsedURL.fromString(attributeValueElement.textContent || "")) {
      config.setPostKeydownFinishHandler(postKeyDownFinishHandler);
    }
    this.updateEditorHandles(attribute, config);
    const componentSelection = this.listItemElement.getComponentSelection();
    componentSelection && componentSelection.selectAllChildren(elementForSelection);
    return true;
  }
  startEditingTextNode(textNodeElement) {
    if (UI.UIUtils.isBeingEdited(textNodeElement)) {
      return true;
    }
    let textNode = this.nodeInternal;
    if (textNode.nodeType() === Node.ELEMENT_NODE && textNode.firstChild) {
      textNode = textNode.firstChild;
    }
    const container = textNodeElement.enclosingNodeOrSelfWithClass("webkit-html-text-node");
    if (container) {
      container.textContent = textNode.nodeValue();
    }
    const config = new UI.InplaceEditor.Config(this.textNodeEditingCommitted.bind(this, textNode), this.editingCancelled.bind(this));
    this.updateEditorHandles(textNodeElement, config);
    const componentSelection = this.listItemElement.getComponentSelection();
    componentSelection && componentSelection.selectAllChildren(textNodeElement);
    return true;
  }
  startEditingTagName(tagNameElement) {
    if (!tagNameElement) {
      tagNameElement = this.listItemElement.getElementsByClassName("webkit-html-tag-name")[0];
      if (!tagNameElement) {
        return false;
      }
    }
    const tagName = tagNameElement.textContent;
    if (tagName !== null && EditTagBlocklist.has(tagName.toLowerCase())) {
      return false;
    }
    if (UI.UIUtils.isBeingEdited(tagNameElement)) {
      return true;
    }
    const closingTagElement = this.distinctClosingTagElement();
    function keyupListener() {
      if (closingTagElement && tagNameElement) {
        closingTagElement.textContent = "</" + tagNameElement.textContent + ">";
      }
    }
    const keydownListener = (event) => {
      if (event.key !== " ") {
        return;
      }
      this.editing && this.editing.commit();
      event.consume(true);
    };
    function editingCommitted(element, newTagName, oldText, tagName2, moveDirection) {
      if (!tagNameElement) {
        return;
      }
      tagNameElement.removeEventListener("keyup", keyupListener, false);
      tagNameElement.removeEventListener("keydown", keydownListener, false);
      this.tagNameEditingCommitted(element, newTagName, oldText, tagName2, moveDirection);
    }
    function editingCancelled(element, context) {
      if (!tagNameElement) {
        return;
      }
      tagNameElement.removeEventListener("keyup", keyupListener, false);
      tagNameElement.removeEventListener("keydown", keydownListener, false);
      this.editingCancelled(element, context);
    }
    tagNameElement.addEventListener("keyup", keyupListener, false);
    tagNameElement.addEventListener("keydown", keydownListener, false);
    const config = new UI.InplaceEditor.Config(editingCommitted.bind(this), editingCancelled.bind(this), tagName);
    this.updateEditorHandles(tagNameElement, config);
    const componentSelection = this.listItemElement.getComponentSelection();
    componentSelection && componentSelection.selectAllChildren(tagNameElement);
    return true;
  }
  updateEditorHandles(element, config) {
    const editorHandles = UI.InplaceEditor.InplaceEditor.startEditing(element, config);
    if (!editorHandles) {
      this.editing = null;
    } else {
      this.editing = {
        commit: editorHandles.commit,
        cancel: editorHandles.cancel,
        editor: void 0,
        resize: () => {
        }
      };
    }
  }
  async startEditingAsHTML(commitCallback, disposeCallback, maybeInitialValue) {
    if (maybeInitialValue === null) {
      return;
    }
    if (this.editing) {
      return;
    }
    const initialValue = this.convertWhitespaceToEntities(maybeInitialValue).text;
    this.htmlEditElement = document.createElement("div");
    this.htmlEditElement.className = "source-code elements-tree-editor";
    let child = this.listItemElement.firstChild;
    while (child) {
      child.style.display = "none";
      child = child.nextSibling;
    }
    if (this.childrenListElement) {
      this.childrenListElement.style.display = "none";
    }
    this.listItemElement.append(this.htmlEditElement);
    this.htmlEditElement.addEventListener("keydown", (event) => {
      if (event.key === "Escape") {
        event.consume(true);
      }
    });
    const editor = new TextEditor.TextEditor.TextEditor(CodeMirror.EditorState.create({
      doc: initialValue,
      extensions: [
        CodeMirror.keymap.of([
          {
            key: "Mod-Enter",
            run: () => {
              this.editing?.commit();
              return true;
            }
          },
          {
            key: "Escape",
            run: () => {
              this.editing?.cancel();
              return true;
            }
          }
        ]),
        TextEditor.Config.baseConfiguration(initialValue),
        TextEditor.Config.closeBrackets,
        TextEditor.Config.autocompletion,
        CodeMirror.html.html(),
        TextEditor.Config.domWordWrap.instance(),
        CodeMirror.EditorView.theme({
          "&.cm-editor": { maxHeight: "300px" },
          ".cm-scroller": { overflowY: "auto" }
        }),
        CodeMirror.EditorView.domEventHandlers({
          focusout: (event) => {
            const relatedTarget = event.relatedTarget;
            if (relatedTarget && !relatedTarget.isSelfOrDescendant(editor)) {
              this.editing && this.editing.commit();
            }
          }
        })
      ]
    }));
    this.editing = { commit: commit.bind(this), cancel: dispose.bind(this), editor, resize: resize.bind(this) };
    resize.call(this);
    this.htmlEditElement.appendChild(editor);
    editor.editor.focus();
    this.treeOutline && this.treeOutline.setMultilineEditing(this.editing);
    function resize() {
      if (this.treeOutline && this.htmlEditElement) {
        this.htmlEditElement.style.width = this.treeOutline.visibleWidth() - this.computeLeftIndent() - 30 + "px";
      }
    }
    function commit() {
      if (this.editing && this.editing.editor) {
        commitCallback(initialValue, this.editing.editor.state.doc.toString());
      }
      dispose.call(this);
    }
    function dispose() {
      if (!this.editing || !this.editing.editor) {
        return;
      }
      this.editing = null;
      if (this.htmlEditElement) {
        this.listItemElement.removeChild(this.htmlEditElement);
      }
      this.htmlEditElement = void 0;
      if (this.childrenListElement) {
        this.childrenListElement.style.removeProperty("display");
      }
      let child2 = this.listItemElement.firstChild;
      while (child2) {
        child2.style.removeProperty("display");
        child2 = child2.nextSibling;
      }
      if (this.treeOutline) {
        this.treeOutline.setMultilineEditing(null);
        this.treeOutline.focus();
      }
      disposeCallback();
    }
  }
  attributeEditingCommitted(element, newText, oldText, attributeName, moveDirection) {
    this.editing = null;
    const treeOutline = this.treeOutline;
    function moveToNextAttributeIfNeeded(error) {
      if (error) {
        this.editingCancelled(element, attributeName);
      }
      if (!moveDirection) {
        return;
      }
      if (treeOutline) {
        treeOutline.runPendingUpdates();
        treeOutline.focus();
      }
      const attributes = this.nodeInternal.attributes();
      for (let i = 0; i < attributes.length; ++i) {
        if (attributes[i].name !== attributeName) {
          continue;
        }
        if (moveDirection === "backward") {
          if (i === 0) {
            this.startEditingTagName();
          } else {
            this.triggerEditAttribute(attributes[i - 1].name);
          }
        } else {
          if (i === attributes.length - 1) {
            this.addNewAttribute();
          } else {
            this.triggerEditAttribute(attributes[i + 1].name);
          }
        }
        return;
      }
      if (moveDirection === "backward") {
        if (newText === " ") {
          if (attributes.length > 0) {
            this.triggerEditAttribute(attributes[attributes.length - 1].name);
          }
        } else {
          if (attributes.length > 1) {
            this.triggerEditAttribute(attributes[attributes.length - 2].name);
          }
        }
      } else if (moveDirection === "forward") {
        if (!Platform.StringUtilities.isWhitespace(newText)) {
          this.addNewAttribute();
        } else {
          this.startEditingTagName();
        }
      }
    }
    if ((attributeName.trim() || newText.trim()) && oldText !== newText) {
      this.nodeInternal.setAttribute(attributeName, newText, moveToNextAttributeIfNeeded.bind(this));
      return;
    }
    this.updateTitle();
    moveToNextAttributeIfNeeded.call(this);
  }
  tagNameEditingCommitted(element, newText, oldText, tagName, moveDirection) {
    this.editing = null;
    const self = this;
    function cancel() {
      const closingTagElement = self.distinctClosingTagElement();
      if (closingTagElement) {
        closingTagElement.textContent = "</" + tagName + ">";
      }
      self.editingCancelled(element, tagName);
      moveToNextAttributeIfNeeded.call(self);
    }
    function moveToNextAttributeIfNeeded() {
      if (moveDirection !== "forward") {
        this.addNewAttribute();
        return;
      }
      const attributes = this.nodeInternal.attributes();
      if (attributes.length > 0) {
        this.triggerEditAttribute(attributes[0].name);
      } else {
        this.addNewAttribute();
      }
    }
    newText = newText.trim();
    if (newText === oldText) {
      cancel();
      return;
    }
    const treeOutline = this.treeOutline;
    const wasExpanded = this.expanded;
    this.nodeInternal.setNodeName(newText, (error, newNode) => {
      if (error || !newNode) {
        cancel();
        return;
      }
      if (!treeOutline) {
        return;
      }
      const newTreeItem = treeOutline.selectNodeAfterEdit(wasExpanded, error, newNode);
      moveToNextAttributeIfNeeded.call(newTreeItem);
    });
  }
  textNodeEditingCommitted(textNode, element, newText) {
    this.editing = null;
    function callback() {
      this.updateTitle();
    }
    textNode.setNodeValue(newText, callback.bind(this));
  }
  editingCancelled(_element, _context) {
    this.editing = null;
    this.updateTitle();
  }
  distinctClosingTagElement() {
    if (this.expanded) {
      const closers = this.childrenListElement.querySelectorAll(".close");
      return closers[closers.length - 1];
    }
    const tags = this.listItemElement.getElementsByClassName("webkit-html-tag");
    return tags.length === 1 ? null : tags[tags.length - 1];
  }
  updateTitle(updateRecord, onlySearchQueryChanged) {
    if (this.editing) {
      return;
    }
    if (onlySearchQueryChanged) {
      this.hideSearchHighlight();
    } else {
      const nodeInfo = this.nodeTitleInfo(updateRecord || null);
      if (this.nodeInternal.nodeType() === Node.DOCUMENT_FRAGMENT_NODE && this.nodeInternal.isInShadowTree() && this.nodeInternal.shadowRootType()) {
        this.childrenListElement.classList.add("shadow-root");
        let depth = 4;
        for (let node = this.nodeInternal; depth && node; node = node.parentNode) {
          if (node.nodeType() === Node.DOCUMENT_FRAGMENT_NODE) {
            depth--;
          }
        }
        if (!depth) {
          this.childrenListElement.classList.add("shadow-root-deep");
        } else {
          this.childrenListElement.classList.add("shadow-root-depth-" + depth);
        }
      }
      this.contentElement.removeChildren();
      const highlightElement = this.contentElement.createChild("span", "highlight");
      highlightElement.append(nodeInfo);
      this.title = this.contentElement;
      this.updateDecorations();
      this.contentElement.prepend(this.gutterContainer);
      if (!this.isClosingTagInternal && this.adornerContainer) {
        this.contentElement.append(this.adornerContainer);
      }
      this.highlightResult = [];
      delete this.selectionElement;
      delete this.hintElement;
      if (this.selected) {
        this.createSelection();
        this.createHint();
      }
    }
    this.highlightSearchResultsInternal();
  }
  computeLeftIndent() {
    let treeElement = this.parent;
    let depth = 0;
    while (treeElement !== null) {
      depth++;
      treeElement = treeElement.parent;
    }
    return 12 * (depth - 2) + (this.isExpandable() && this.isCollapsible() ? 1 : 12);
  }
  updateDecorations() {
    this.gutterContainer.style.left = -this.computeLeftIndent() + "px";
    if (this.isClosingTag()) {
      return;
    }
    if (this.nodeInternal.nodeType() !== Node.ELEMENT_NODE) {
      return;
    }
    void this.decorationsThrottler.schedule(this.updateDecorationsInternal.bind(this));
  }
  updateDecorationsInternal() {
    if (!this.treeOutline) {
      return Promise.resolve();
    }
    const node = this.nodeInternal;
    if (!this.treeOutline.decoratorExtensions) {
      this.treeOutline.decoratorExtensions = getRegisteredDecorators();
    }
    const markerToExtension = /* @__PURE__ */ new Map();
    for (const decoratorExtension of this.treeOutline.decoratorExtensions) {
      markerToExtension.set(decoratorExtension.marker, decoratorExtension);
    }
    const promises = [];
    const decorations = [];
    const descendantDecorations = [];
    node.traverseMarkers(visitor);
    function visitor(n, marker) {
      const extension = markerToExtension.get(marker);
      if (!extension) {
        return;
      }
      promises.push(Promise.resolve(extension.decorator()).then(collectDecoration.bind(null, n)));
    }
    function collectDecoration(n, decorator) {
      const decoration = decorator.decorate(n);
      if (!decoration) {
        return;
      }
      (n === node ? decorations : descendantDecorations).push(decoration);
    }
    return Promise.all(promises).then(updateDecorationsUI.bind(this));
    function updateDecorationsUI() {
      this.decorationsElement.removeChildren();
      this.decorationsElement.classList.add("hidden");
      this.gutterContainer.classList.toggle("has-decorations", Boolean(decorations.length || descendantDecorations.length));
      UI.ARIAUtils.setAccessibleName(this.decorationsElement, "");
      if (!decorations.length && !descendantDecorations.length) {
        return;
      }
      const colors = /* @__PURE__ */ new Set();
      const titles = document.createElement("div");
      for (const decoration of decorations) {
        const titleElement = titles.createChild("div");
        titleElement.textContent = decoration.title;
        colors.add(decoration.color);
      }
      if (this.expanded && !decorations.length) {
        return;
      }
      const descendantColors = /* @__PURE__ */ new Set();
      if (descendantDecorations.length) {
        let element = titles.createChild("div");
        element.textContent = i18nString(UIStrings.children);
        for (const decoration of descendantDecorations) {
          element = titles.createChild("div");
          element.style.marginLeft = "15px";
          element.textContent = decoration.title;
          descendantColors.add(decoration.color);
        }
      }
      let offset = 0;
      processColors.call(this, colors, "elements-gutter-decoration");
      if (!this.expanded) {
        processColors.call(this, descendantColors, "elements-gutter-decoration elements-has-decorated-children");
      }
      UI.Tooltip.Tooltip.install(this.decorationsElement, titles.textContent);
      UI.ARIAUtils.setAccessibleName(this.decorationsElement, titles.textContent || "");
      function processColors(colors2, className) {
        for (const color of colors2) {
          const child = this.decorationsElement.createChild("div", className);
          this.decorationsElement.classList.remove("hidden");
          child.style.backgroundColor = color;
          child.style.borderColor = color;
          if (offset) {
            child.style.marginLeft = offset + "px";
          }
          offset += 3;
        }
      }
    }
  }
  buildAttributeDOM(parentElement, name, value, updateRecord, forceValue, node) {
    const closingPunctuationRegex = /[\/;:\)\]\}]/g;
    let highlightIndex = 0;
    let highlightCount = 0;
    let additionalHighlightOffset = 0;
    function setValueWithEntities(element, value2) {
      const result = this.convertWhitespaceToEntities(value2);
      highlightCount = result.entityRanges.length;
      value2 = result.text.replace(closingPunctuationRegex, (match, replaceOffset) => {
        while (highlightIndex < highlightCount && result.entityRanges[highlightIndex].offset < replaceOffset) {
          result.entityRanges[highlightIndex].offset += additionalHighlightOffset;
          ++highlightIndex;
        }
        additionalHighlightOffset += 1;
        return match + "\u200B";
      });
      while (highlightIndex < highlightCount) {
        result.entityRanges[highlightIndex].offset += additionalHighlightOffset;
        ++highlightIndex;
      }
      element.setTextContentTruncatedIfNeeded(value2);
      UI.UIUtils.highlightRangesWithStyleClass(element, result.entityRanges, "webkit-html-entity-value");
    }
    const hasText = forceValue || value.length > 0;
    const attrSpanElement = parentElement.createChild("span", "webkit-html-attribute");
    const attrNameElement = attrSpanElement.createChild("span", "webkit-html-attribute-name");
    attrNameElement.textContent = name;
    if (hasText) {
      UI.UIUtils.createTextChild(attrSpanElement, '=\u200B"');
    }
    const attrValueElement = attrSpanElement.createChild("span", "webkit-html-attribute-value");
    if (updateRecord && updateRecord.isAttributeModified(name)) {
      UI.UIUtils.runCSSAnimationOnce(hasText ? attrValueElement : attrNameElement, "dom-update-highlight");
    }
    function linkifyValue(value2) {
      const rewrittenHref = node ? node.resolveURL(value2) : null;
      if (rewrittenHref === null) {
        const span = document.createElement("span");
        setValueWithEntities.call(this, span, value2);
        return span;
      }
      value2 = value2.replace(closingPunctuationRegex, "$&\u200B");
      if (value2.startsWith("data:")) {
        value2 = Platform.StringUtilities.trimMiddle(value2, 60);
      }
      const link = node && node.nodeName().toLowerCase() === "a" ? UI.XLink.XLink.create(rewrittenHref, value2, "", true) : Components.Linkifier.Linkifier.linkifyURL(rewrittenHref, {
        text: value2,
        preventClick: true,
        showColumnNumber: false,
        inlineFrameIndex: 0
      });
      return ImagePreviewPopover.setImageUrl(link, rewrittenHref);
    }
    const nodeName = node ? node.nodeName().toLowerCase() : "";
    if (nodeName && (name === "src" || name === "href")) {
      attrValueElement.appendChild(linkifyValue.call(this, value));
    } else if ((nodeName === "img" || nodeName === "source") && name === "srcset") {
      attrValueElement.appendChild(linkifySrcset.call(this, value));
    } else if (nodeName === "image" && (name === "xlink:href" || name === "href")) {
      attrValueElement.appendChild(linkifySrcset.call(this, value));
    } else {
      setValueWithEntities.call(this, attrValueElement, value);
    }
    if (hasText) {
      UI.UIUtils.createTextChild(attrSpanElement, '"');
    }
    function linkifySrcset(value2) {
      const fragment = document.createDocumentFragment();
      let i = 0;
      while (value2.length) {
        if (i++ > 0) {
          UI.UIUtils.createTextChild(fragment, " ");
        }
        value2 = value2.trim();
        let url = "";
        let descriptor = "";
        const indexOfSpace = value2.search(/\s/);
        if (indexOfSpace === -1) {
          url = value2;
        } else if (indexOfSpace > 0 && value2[indexOfSpace - 1] === ",") {
          url = value2.substring(0, indexOfSpace);
        } else {
          url = value2.substring(0, indexOfSpace);
          const indexOfComma = value2.indexOf(",", indexOfSpace);
          if (indexOfComma !== -1) {
            descriptor = value2.substring(indexOfSpace, indexOfComma + 1);
          } else {
            descriptor = value2.substring(indexOfSpace);
          }
        }
        if (url) {
          if (url.endsWith(",")) {
            fragment.appendChild(linkifyValue.call(this, url.substring(0, url.length - 1)));
            UI.UIUtils.createTextChild(fragment, ",");
          } else {
            fragment.appendChild(linkifyValue.call(this, url));
          }
        }
        if (descriptor) {
          UI.UIUtils.createTextChild(fragment, descriptor);
        }
        value2 = value2.substring(url.length + descriptor.length);
      }
      return fragment;
    }
    return attrSpanElement;
  }
  buildPseudoElementDOM(parentElement, pseudoElementName) {
    const pseudoElement = parentElement.createChild("span", "webkit-html-pseudo-element");
    pseudoElement.textContent = "::" + pseudoElementName;
    UI.UIUtils.createTextChild(parentElement, "\u200B");
  }
  buildTagDOM(parentElement, tagName, isClosingTag, isDistinctTreeElement, updateRecord) {
    const node = this.nodeInternal;
    const classes = ["webkit-html-tag"];
    if (isClosingTag && isDistinctTreeElement) {
      classes.push("close");
    }
    const tagElement = parentElement.createChild("span", classes.join(" "));
    UI.UIUtils.createTextChild(tagElement, "<");
    const tagNameElement = tagElement.createChild("span", isClosingTag ? "webkit-html-close-tag-name" : "webkit-html-tag-name");
    tagNameElement.textContent = (isClosingTag ? "/" : "") + tagName;
    if (!isClosingTag) {
      if (node.hasAttributes()) {
        const attributes = node.attributes();
        for (let i = 0; i < attributes.length; ++i) {
          const attr = attributes[i];
          UI.UIUtils.createTextChild(tagElement, " ");
          this.buildAttributeDOM(tagElement, attr.name, attr.value, updateRecord, false, node);
        }
      }
      if (updateRecord) {
        let hasUpdates = updateRecord.hasRemovedAttributes() || updateRecord.hasRemovedChildren();
        hasUpdates = hasUpdates || !this.expanded && updateRecord.hasChangedChildren();
        if (hasUpdates) {
          UI.UIUtils.runCSSAnimationOnce(tagNameElement, "dom-update-highlight");
        }
      }
    }
    UI.UIUtils.createTextChild(tagElement, ">");
    UI.UIUtils.createTextChild(parentElement, "\u200B");
    if (tagElement.textContent) {
      UI.ARIAUtils.setAccessibleName(tagElement, tagElement.textContent);
    }
  }
  convertWhitespaceToEntities(text) {
    let result = "";
    let lastIndexAfterEntity = 0;
    const entityRanges = [];
    const charToEntity = MappedCharToEntity;
    for (let i = 0, size = text.length; i < size; ++i) {
      const char = text.charAt(i);
      if (charToEntity.has(char)) {
        result += text.substring(lastIndexAfterEntity, i);
        const entityValue = "&" + charToEntity.get(char) + ";";
        entityRanges.push({ offset: result.length, length: entityValue.length });
        result += entityValue;
        lastIndexAfterEntity = i + 1;
      }
    }
    if (result) {
      result += text.substring(lastIndexAfterEntity);
    }
    return { text: result || text, entityRanges };
  }
  nodeTitleInfo(updateRecord) {
    const node = this.nodeInternal;
    const titleDOM = document.createDocumentFragment();
    const updateSearchHighlight = () => {
      this.highlightResult = [];
      this.highlightSearchResultsInternal();
    };
    switch (node.nodeType()) {
      case Node.ATTRIBUTE_NODE:
        this.buildAttributeDOM(titleDOM, node.name, node.value, updateRecord, true);
        break;
      case Node.ELEMENT_NODE: {
        const pseudoType = node.pseudoType();
        if (pseudoType) {
          this.buildPseudoElementDOM(titleDOM, pseudoType);
          break;
        }
        const tagName = node.nodeNameInCorrectCase();
        if (this.isClosingTagInternal) {
          this.buildTagDOM(titleDOM, tagName, true, true, updateRecord);
          break;
        }
        this.buildTagDOM(titleDOM, tagName, false, false, updateRecord);
        if (this.isExpandable()) {
          if (!this.expanded) {
            const textNodeElement = titleDOM.createChild("span", "webkit-html-text-node bogus");
            textNodeElement.textContent = "\u2026";
            UI.UIUtils.createTextChild(titleDOM, "\u200B");
            this.buildTagDOM(titleDOM, tagName, true, false, updateRecord);
          }
          break;
        }
        if (ElementsTreeElement.canShowInlineText(node)) {
          const textNodeElement = titleDOM.createChild("span", "webkit-html-text-node");
          const firstChild = node.firstChild;
          if (!firstChild) {
            throw new Error("ElementsTreeElement._nodeTitleInfo expects node.firstChild to be defined.");
          }
          const result = this.convertWhitespaceToEntities(firstChild.nodeValue());
          textNodeElement.textContent = Platform.StringUtilities.collapseWhitespace(result.text);
          UI.UIUtils.highlightRangesWithStyleClass(textNodeElement, result.entityRanges, "webkit-html-entity-value");
          UI.UIUtils.createTextChild(titleDOM, "\u200B");
          this.buildTagDOM(titleDOM, tagName, true, false, updateRecord);
          if (updateRecord && updateRecord.hasChangedChildren()) {
            UI.UIUtils.runCSSAnimationOnce(textNodeElement, "dom-update-highlight");
          }
          if (updateRecord && updateRecord.isCharDataModified()) {
            UI.UIUtils.runCSSAnimationOnce(textNodeElement, "dom-update-highlight");
          }
          break;
        }
        if (this.treeOutline && this.treeOutline.isXMLMimeType || !ForbiddenClosingTagElements.has(tagName)) {
          this.buildTagDOM(titleDOM, tagName, true, false, updateRecord);
        }
        break;
      }
      case Node.TEXT_NODE:
        if (node.parentNode && node.parentNode.nodeName().toLowerCase() === "script") {
          const newNode = titleDOM.createChild("span", "webkit-html-text-node webkit-html-js-node");
          const text = node.nodeValue();
          newNode.textContent = text.replace(/^[\n\r]+|\s+$/g, "");
          void CodeHighlighter.CodeHighlighter.highlightNode(newNode, "text/javascript").then(updateSearchHighlight);
        } else if (node.parentNode && node.parentNode.nodeName().toLowerCase() === "style") {
          const newNode = titleDOM.createChild("span", "webkit-html-text-node webkit-html-css-node");
          const text = node.nodeValue();
          newNode.textContent = text.replace(/^[\n\r]+|\s+$/g, "");
          void CodeHighlighter.CodeHighlighter.highlightNode(newNode, "text/css").then(updateSearchHighlight);
        } else {
          UI.UIUtils.createTextChild(titleDOM, '"');
          const textNodeElement = titleDOM.createChild("span", "webkit-html-text-node");
          const result = this.convertWhitespaceToEntities(node.nodeValue());
          textNodeElement.textContent = Platform.StringUtilities.collapseWhitespace(result.text);
          UI.UIUtils.highlightRangesWithStyleClass(textNodeElement, result.entityRanges, "webkit-html-entity-value");
          UI.UIUtils.createTextChild(titleDOM, '"');
          if (updateRecord && updateRecord.isCharDataModified()) {
            UI.UIUtils.runCSSAnimationOnce(textNodeElement, "dom-update-highlight");
          }
        }
        break;
      case Node.COMMENT_NODE: {
        const commentElement = titleDOM.createChild("span", "webkit-html-comment");
        UI.UIUtils.createTextChild(commentElement, "<!--" + node.nodeValue() + "-->");
        break;
      }
      case Node.DOCUMENT_TYPE_NODE: {
        const docTypeElement = titleDOM.createChild("span", "webkit-html-doctype");
        UI.UIUtils.createTextChild(docTypeElement, "<!DOCTYPE " + node.nodeName());
        if (node.publicId) {
          UI.UIUtils.createTextChild(docTypeElement, ' PUBLIC "' + node.publicId + '"');
          if (node.systemId) {
            UI.UIUtils.createTextChild(docTypeElement, ' "' + node.systemId + '"');
          }
        } else if (node.systemId) {
          UI.UIUtils.createTextChild(docTypeElement, ' SYSTEM "' + node.systemId + '"');
        }
        if (node.internalSubset) {
          UI.UIUtils.createTextChild(docTypeElement, " [" + node.internalSubset + "]");
        }
        UI.UIUtils.createTextChild(docTypeElement, ">");
        break;
      }
      case Node.CDATA_SECTION_NODE: {
        const cdataElement = titleDOM.createChild("span", "webkit-html-text-node");
        UI.UIUtils.createTextChild(cdataElement, "<![CDATA[" + node.nodeValue() + "]]>");
        break;
      }
      case Node.DOCUMENT_FRAGMENT_NODE: {
        const fragmentElement = titleDOM.createChild("span", "webkit-html-fragment");
        fragmentElement.textContent = Platform.StringUtilities.collapseWhitespace(node.nodeNameInCorrectCase());
        break;
      }
      default: {
        const nameWithSpaceCollapsed = Platform.StringUtilities.collapseWhitespace(node.nodeNameInCorrectCase());
        UI.UIUtils.createTextChild(titleDOM, nameWithSpaceCollapsed);
      }
    }
    return titleDOM;
  }
  remove() {
    if (this.nodeInternal.pseudoType()) {
      return;
    }
    const parentElement = this.parent;
    if (!parentElement) {
      return;
    }
    if (!this.nodeInternal.parentNode || this.nodeInternal.parentNode.nodeType() === Node.DOCUMENT_NODE) {
      return;
    }
    void this.nodeInternal.removeNode();
  }
  toggleEditAsHTML(callback, startEditing) {
    if (this.editing && this.htmlEditElement) {
      this.editing.commit();
      return;
    }
    if (startEditing === false) {
      return;
    }
    function selectNode(error) {
      if (callback) {
        callback(!error);
      }
    }
    function commitChange(initialValue, value) {
      if (initialValue !== value) {
        node.setOuterHTML(value, selectNode);
      }
    }
    function disposeCallback() {
      if (callback) {
        callback(false);
      }
    }
    const node = this.nodeInternal;
    void node.getOuterHTML().then(this.startEditingAsHTML.bind(this, commitChange, disposeCallback));
  }
  copyCSSPath() {
    Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(cssPath(this.nodeInternal, true));
  }
  copyJSPath() {
    Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(jsPath(this.nodeInternal, true));
  }
  copyXPath() {
    Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(xPath(this.nodeInternal, true));
  }
  copyFullXPath() {
    Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(xPath(this.nodeInternal, false));
  }
  async copyStyles() {
    const node = this.nodeInternal;
    const cssModel = node.domModel().cssModel();
    const cascade = await cssModel.cachedMatchedCascadeForNode(node);
    if (!cascade) {
      return;
    }
    const indent = Common.Settings.Settings.instance().moduleSetting("textEditorIndent").get();
    const lines = [];
    for (const style of cascade.nodeStyles().reverse()) {
      for (const property of style.leadingProperties()) {
        if (!property.parsedOk || property.disabled || !property.activeInStyle() || property.implicit) {
          continue;
        }
        if (cascade.isInherited(style) && !SDK.CSSMetadata.cssMetadata().isPropertyInherited(property.name)) {
          continue;
        }
        if (style.parentRule && style.parentRule.isUserAgent()) {
          continue;
        }
        if (cascade.propertyState(property) !== SDK.CSSMatchedStyles.PropertyState.Active) {
          continue;
        }
        lines.push(`${indent}${property.name}: ${property.value};`);
      }
    }
    Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(lines.join("\n"));
  }
  highlightSearchResultsInternal() {
    if (!this.searchQuery || !this.searchHighlightsVisible) {
      return;
    }
    this.hideSearchHighlight();
    const text = this.listItemElement.textContent || "";
    const regexObject = Platform.StringUtilities.createPlainTextSearchRegex(this.searchQuery, "gi");
    let match = regexObject.exec(text);
    const matchRanges = [];
    while (match) {
      matchRanges.push(new TextUtils.TextRange.SourceRange(match.index, match[0].length));
      match = regexObject.exec(text);
    }
    if (!matchRanges.length) {
      matchRanges.push(new TextUtils.TextRange.SourceRange(0, text.length));
    }
    this.highlightResult = [];
    UI.UIUtils.highlightSearchResults(this.listItemElement, matchRanges, this.highlightResult);
  }
  editAsHTML() {
    const promise = Common.Revealer.reveal(this.node());
    void promise.then(() => {
      const action = UI.ActionRegistry.ActionRegistry.instance().action("elements.edit-as-html");
      if (!action) {
        return;
      }
      return action.execute();
    });
  }
  adorn({ name }) {
    const adornerContent = document.createElement("span");
    adornerContent.textContent = name;
    const adorner = new Adorners.Adorner.Adorner();
    adorner.data = {
      name,
      content: adornerContent
    };
    this.adorners.push(adorner);
    ElementsPanel.instance().registerAdorner(adorner);
    this.updateAdorners();
    return adorner;
  }
  removeAdorner(adornerToRemove) {
    const adorners = this.adorners;
    ElementsPanel.instance().deregisterAdorner(adornerToRemove);
    adornerToRemove.remove();
    for (let i = 0; i < adorners.length; ++i) {
      if (adorners[i] === adornerToRemove) {
        adorners.splice(i, 1);
        this.updateAdorners();
        return;
      }
    }
  }
  removeAllAdorners() {
    for (const adorner of this.adorners) {
      ElementsPanel.instance().deregisterAdorner(adorner);
      adorner.remove();
    }
    this.adorners = [];
    this.updateAdorners();
  }
  updateAdorners() {
    void this.adornersThrottler.schedule(this.updateAdornersInternal.bind(this));
  }
  updateAdornersInternal() {
    const adornerContainer = this.adornerContainer;
    if (!adornerContainer) {
      return Promise.resolve();
    }
    const adorners = this.adorners;
    if (adorners.length === 0) {
      adornerContainer.classList.add("hidden");
      return Promise.resolve();
    }
    adorners.sort(adornerComparator);
    adornerContainer.removeChildren();
    for (const adorner of adorners) {
      adornerContainer.appendChild(adorner);
    }
    adornerContainer.classList.remove("hidden");
    return Promise.resolve();
  }
  async updateStyleAdorners() {
    if (this.isClosingTagInternal) {
      return;
    }
    const node = this.node();
    const nodeId = node.id;
    if (node.nodeType() === Node.COMMENT_NODE || node.nodeType() === Node.DOCUMENT_FRAGMENT_NODE || node.nodeType() === Node.TEXT_NODE || nodeId === void 0) {
      return;
    }
    const styles = await node.domModel().cssModel().getComputedStyle(nodeId);
    for (const styleAdorner of this.styleAdorners) {
      this.removeAdorner(styleAdorner);
    }
    this.styleAdorners = [];
    if (!styles) {
      return;
    }
    const display = styles.get("display");
    const isGrid = display === "grid" || display === "inline-grid";
    const isFlex = display === "flex" || display === "inline-flex";
    const containerType = styles.get("container-type");
    const contain = styles.get("contain");
    const isContainer = SDK.CSSContainerQuery.getQueryAxis(`${containerType} ${contain}`) !== SDK.CSSContainerQuery.QueryAxis.None;
    const appendAdorner = (adorner) => {
      if (adorner) {
        this.styleAdorners.push(adorner);
      }
    };
    if (isGrid) {
      appendAdorner(this.createGridAdorner());
    }
    if (isFlex) {
      appendAdorner(this.createFlexAdorner());
    }
    if (styles.get("scroll-snap-type") && styles.get("scroll-snap-type") !== "none") {
      appendAdorner(this.createScrollSnapAdorner());
    }
    if (isContainer) {
      appendAdorner(this.createContainerAdorner());
    }
  }
  createGridAdorner() {
    const node = this.node();
    const nodeId = node.id;
    if (!nodeId) {
      return null;
    }
    const config = ElementsComponents.AdornerManager.getRegisteredAdorner(ElementsComponents.AdornerManager.RegisteredAdorners.GRID);
    const adorner = this.adorn(config);
    adorner.classList.add("grid");
    const onClick = () => {
      if (adorner.isActive()) {
        node.domModel().overlayModel().highlightGridInPersistentOverlay(nodeId);
      } else {
        node.domModel().overlayModel().hideGridInPersistentOverlay(nodeId);
      }
    };
    adorner.addInteraction(onClick, {
      isToggle: true,
      shouldPropagateOnKeydown: false,
      ariaLabelDefault: i18nString(UIStrings.enableGridMode),
      ariaLabelActive: i18nString(UIStrings.disableGridMode)
    });
    node.domModel().overlayModel().addEventListener(SDK.OverlayModel.Events.PersistentGridOverlayStateChanged, (event) => {
      const { nodeId: eventNodeId, enabled } = event.data;
      if (eventNodeId !== nodeId) {
        return;
      }
      adorner.toggle(enabled);
    });
    return adorner;
  }
  createScrollSnapAdorner() {
    const node = this.node();
    const nodeId = node.id;
    if (!nodeId) {
      return null;
    }
    const config = ElementsComponents.AdornerManager.getRegisteredAdorner(ElementsComponents.AdornerManager.RegisteredAdorners.SCROLL_SNAP);
    const adorner = this.adorn(config);
    adorner.classList.add("scroll-snap");
    const onClick = () => {
      const model = node.domModel().overlayModel();
      if (adorner.isActive()) {
        model.highlightScrollSnapInPersistentOverlay(nodeId);
      } else {
        model.hideScrollSnapInPersistentOverlay(nodeId);
      }
    };
    adorner.addInteraction(onClick, {
      isToggle: true,
      shouldPropagateOnKeydown: false,
      ariaLabelDefault: i18nString(UIStrings.enableScrollSnap),
      ariaLabelActive: i18nString(UIStrings.disableScrollSnap)
    });
    node.domModel().overlayModel().addEventListener(SDK.OverlayModel.Events.PersistentScrollSnapOverlayStateChanged, (event) => {
      const { nodeId: eventNodeId, enabled } = event.data;
      if (eventNodeId !== nodeId) {
        return;
      }
      adorner.toggle(enabled);
    });
    return adorner;
  }
  createFlexAdorner() {
    const node = this.node();
    const nodeId = node.id;
    if (!nodeId) {
      return null;
    }
    const config = ElementsComponents.AdornerManager.getRegisteredAdorner(ElementsComponents.AdornerManager.RegisteredAdorners.FLEX);
    const adorner = this.adorn(config);
    adorner.classList.add("flex");
    const onClick = () => {
      const model = node.domModel().overlayModel();
      if (adorner.isActive()) {
        model.highlightFlexContainerInPersistentOverlay(nodeId);
      } else {
        model.hideFlexContainerInPersistentOverlay(nodeId);
      }
    };
    adorner.addInteraction(onClick, {
      isToggle: true,
      shouldPropagateOnKeydown: false,
      ariaLabelDefault: i18nString(UIStrings.enableFlexMode),
      ariaLabelActive: i18nString(UIStrings.disableFlexMode)
    });
    node.domModel().overlayModel().addEventListener(SDK.OverlayModel.Events.PersistentFlexContainerOverlayStateChanged, (event) => {
      const { nodeId: eventNodeId, enabled } = event.data;
      if (eventNodeId !== nodeId) {
        return;
      }
      adorner.toggle(enabled);
    });
    return adorner;
  }
  createContainerAdorner() {
    const node = this.node();
    const nodeId = node.id;
    if (!nodeId) {
      return null;
    }
    const config = ElementsComponents.AdornerManager.getRegisteredAdorner(ElementsComponents.AdornerManager.RegisteredAdorners.CONTAINER);
    const adorner = this.adorn(config);
    adorner.classList.add("container");
    const onClick = () => {
      const model = node.domModel().overlayModel();
      if (adorner.isActive()) {
        model.highlightContainerQueryInPersistentOverlay(nodeId);
      } else {
        model.hideContainerQueryInPersistentOverlay(nodeId);
      }
    };
    adorner.addInteraction(onClick, {
      isToggle: true,
      shouldPropagateOnKeydown: false,
      ariaLabelDefault: i18nString(UIStrings.enableScrollSnap),
      ariaLabelActive: i18nString(UIStrings.disableScrollSnap)
    });
    node.domModel().overlayModel().addEventListener(SDK.OverlayModel.Events.PersistentContainerQueryOverlayStateChanged, (event) => {
      const { nodeId: eventNodeId, enabled } = event.data;
      if (eventNodeId !== nodeId) {
        return;
      }
      adorner.toggle(enabled);
    });
    return adorner;
  }
}
export const InitialChildrenLimit = 500;
export const ForbiddenClosingTagElements = /* @__PURE__ */ new Set([
  "area",
  "base",
  "basefont",
  "br",
  "canvas",
  "col",
  "command",
  "embed",
  "frame",
  "hr",
  "img",
  "input",
  "keygen",
  "link",
  "menuitem",
  "meta",
  "param",
  "source",
  "track",
  "wbr"
]);
export const EditTagBlocklist = /* @__PURE__ */ new Set(["html", "head", "body"]);
export function adornerComparator(adornerA, adornerB) {
  const compareCategories = ElementsComponents.AdornerManager.compareAdornerNamesByCategory(adornerB.name, adornerB.name);
  if (compareCategories === 0) {
    return adornerA.name.localeCompare(adornerB.name);
  }
  return compareCategories;
}
//# sourceMappingURL=ElementsTreeElement.js.map
