fix(extension): sync robuste content/sidepanel, diagnostic panel, preview propre v0.4.4
Some checks failed
CI / Deploy production (on server) (push) Has been cancelled
CI / Lint, Unit Tests & Build (push) Has been cancelled

- content.js : écrit la sélection dans chrome.storage.session/local en plus du message runtime
- sidepanel.js : lit le storage en fallback, loggue chaque étape, affiche un diagnostic panel
- sidepanel.js : avertissement explicite si le content script n'est pas détecté
- sidepanel.js : sépare le rendu Markdown du résumé et l'affichage texte brut de l'extrait
- sidepanel.css : agrandit la zone de prévisualisation
- i18n : nouvelles clés contentScriptMissing, diagnosticsTitle, copyDiagnostics
- locales : correction FR (Retour, Enregistrement, Note, etc.) + version 0.4.4 partout
- extract-article.ts : nettoie textContent des métadonnées (dates, temps de lecture, sources)
- analyze/route.ts : excerpt propre via makeExcerpt
- builds Chrome Store et Firefox regénérés en 0.4.4
This commit is contained in:
Antigravity
2026-07-18 16:56:51 +00:00
parent bff060ad20
commit 0ee2afbd62
67 changed files with 1794 additions and 640 deletions

View File

@@ -1,6 +1,12 @@
/**
* Content script Momento — sélection live, surlignage, communication avec le side panel.
* Injecté automatiquement sur http(s) ; ré-injecté à la demande si longlet était déjà ouvert.
*
* Architecture v0.4.4 :
* - La sélection courante est écrite dans chrome.storage.session/local comme source de vérité
* (filet de sécurité si le runtime.sendMessage est perdu).
* - Les messages runtime servent de notification rapide au side panel.
* - SET_PICK_MODE répond toujours avec létat pickMode + la sélection courante.
*/
;(function initMementoClipperContent() {
if (globalThis.__mementoClipperContent) return
@@ -9,10 +15,16 @@
const HIGHLIGHT_ID = 'memento-clipper-highlight-root'
const BANNER_ID = 'memento-clipper-banner-root'
const STYLE_ID = 'memento-clipper-styles'
const SESSION_KEY = 'memento_clipper_session'
let pickMode = false
let debounceTimer = null
function storageArea() {
// Firefox < 128 na pas storage.session en MV3 ; on fallback sur local.
return chrome.storage.session || chrome.storage.local
}
function getSelectionText() {
return window.getSelection()?.toString().trim() || ''
}
@@ -36,10 +48,25 @@
}
}
async function writeSession(extra = {}) {
try {
await storageArea().set({
[SESSION_KEY]: {
...getPageMeta(),
...extra,
updatedAt: Date.now(),
},
})
} catch (err) {
console.debug('[memento] storage session write failed', err)
}
}
function broadcastSelection() {
clearTimeout(debounceTimer)
debounceTimer = setTimeout(() => {
debounceTimer = setTimeout(async () => {
const payload = { type: 'SELECTION_CHANGED', ...getPageMeta() }
writeSession({ source: 'selection' })
try {
chrome.runtime.sendMessage(payload).catch(() => {})
} catch {
@@ -189,7 +216,7 @@
chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
if (message?.type === 'PING') {
sendResponse({ ok: true })
sendResponse({ ok: true, pickMode, selection: getPageMeta() })
return true
}
if (message?.type === 'GET_CONTEXT') {
@@ -201,11 +228,13 @@
}
if (message?.type === 'SET_PICK_MODE') {
setPickMode(!!message.enabled)
sendResponse({ ok: true, pickMode })
sendResponse({ ok: true, pickMode, selection: getPageMeta() })
return true
}
return false
})
// Amorcer le storage dès l'injection (utile si une sélection existait avant l'ouverture du side panel).
writeSession({ source: 'init' })
broadcastSelection()
})()