export const MANUAL_EDIT_DISCOVERY_SELECTOR = 'main, nav, section, article, header, footer, div, h1, h2, h3, p, a, button, img, strong, span'; export const MANUAL_EDIT_SOURCE_PATH_ATTR = 'data-od-source-path'; export const MANUAL_EDIT_HOST_NODE_SELECTOR = [ '[data-od-sandbox-shim]', '[data-od-deck-bridge]', '[data-od-comment-bridge]', '[data-od-edit-bridge]', '[data-od-comment-bridge-style]', '[data-od-edit-bridge-style]', '[data-od-deck-fix]', ].join(','); export function manualEditDomPathForElement(el: Element): string { const parts: number[] = []; let node: Element | null = el; while (node && node !== node.ownerDocument.body) { const parentEl: Element | null = node.parentElement; if (!parentEl) break; const children = Array.from(parentEl.children).filter((child) => !isManualEditHostNode(child)); parts.unshift(children.indexOf(node)); node = parentEl; } return parts.length ? `path-${parts.join('-')}` : ''; } export function isManualEditHostNode(el: Element): boolean { return el.matches(MANUAL_EDIT_HOST_NODE_SELECTOR); } export function manualEditStableIdForElement(el: Element): string { const explicit = el.getAttribute('data-od-id'); if (explicit) return explicit; const generated = el.getAttribute(MANUAL_EDIT_SOURCE_PATH_ATTR) || el.getAttribute('data-od-runtime-id') || manualEditDomPathForElement(el); if (generated) el.setAttribute('data-od-runtime-id', generated); return generated || 'unknown'; } export function isMeaningfulManualEditElement(el: Element, rect: Pick): boolean { return isSourceMappableManualEditElement(el) && el.matches(MANUAL_EDIT_DISCOVERY_SELECTOR) && rect.width >= 4 && rect.height >= 4; } export function isSourceMappableManualEditElement(el: Element): boolean { return el.hasAttribute('data-od-id') || el.hasAttribute(MANUAL_EDIT_SOURCE_PATH_ATTR); } export function buildManualEditBridge(enabled: boolean): string { return ``; } export function buildManualEditBridgeStyle(): string { return ``; }