/** * Content script Momento — sélection live, surlignage, communication avec le side panel. * Injecté automatiquement sur http(s) ; ré-injecté à la demande si l’onglet était déjà ouvert. */ ;(function initMementoClipperContent() { if (globalThis.__mementoClipperContent) return globalThis.__mementoClipperContent = true const HIGHLIGHT_ID = 'memento-clipper-highlight-root' const BANNER_ID = 'memento-clipper-banner-root' const STYLE_ID = 'memento-clipper-styles' let pickMode = false let debounceTimer = null function getSelectionText() { return window.getSelection()?.toString().trim() || '' } function getPageMeta() { const dir = document.documentElement.getAttribute('dir') || document.body?.getAttribute('dir') || '' const lang = ( document.documentElement.getAttribute('lang') || document.body?.getAttribute('lang') || '' ).split('-')[0] return { text: getSelectionText(), dir, lang, url: location.href, title: document.title, } } function broadcastSelection() { clearTimeout(debounceTimer) debounceTimer = setTimeout(() => { const payload = { type: 'SELECTION_CHANGED', ...getPageMeta() } try { chrome.runtime.sendMessage(payload).catch(() => {}) } catch { /* ignore */ } if (pickMode) paintHighlight() }, 80) } function removeHighlight() { document.getElementById(HIGHLIGHT_ID)?.remove() } function paintHighlight() { removeHighlight() const sel = window.getSelection() if (!sel || sel.isCollapsed || !sel.rangeCount) return let range try { range = sel.getRangeAt(0) } catch { return } const host = document.createElement('div') host.id = HIGHLIGHT_ID host.setAttribute('aria-hidden', 'true') host.style.cssText = 'position:fixed;inset:0;pointer-events:none;z-index:2147483644;overflow:hidden;' for (const rect of range.getClientRects()) { if (rect.width < 2 || rect.height < 2) continue const box = document.createElement('div') box.style.cssText = [ 'position:fixed', `left:${rect.left - 2}px`, `top:${rect.top - 1}px`, `width:${rect.width + 4}px`, `height:${rect.height + 2}px`, 'background:rgba(164,113,72,0.28)', 'border-radius:3px', 'box-shadow:0 0 0 1px rgba(164,113,72,0.35)', 'transition:opacity 0.15s ease', ].join(';') host.appendChild(box) } if (host.childNodes.length) document.documentElement.appendChild(host) } function ensureStyles() { if (document.getElementById(STYLE_ID)) return const style = document.createElement('style') style.id = STYLE_ID style.textContent = ` html.memento-clipper-pick ::selection { background: rgba(164, 113, 72, 0.45) !important; color: inherit !important; } html.memento-clipper-pick { scroll-behavior: auto; } ` document.documentElement.appendChild(style) } function removeBanner() { document.getElementById(BANNER_ID)?.remove() } function ensureBanner() { if (document.getElementById(BANNER_ID)) return const host = document.createElement('div') host.id = BANNER_ID host.style.cssText = 'all:initial;position:fixed;top:16px;left:50%;transform:translateX(-50%);z-index:2147483647;pointer-events:none;font-family:Inter,system-ui,sans-serif;' const shadow = host.attachShadow({ mode: 'open' }) shadow.innerHTML = `