Ce tutoriel construit le plus petit prototype utile sous Chrome Manifest V3 : une zone de texte privée intégrée aux pages d’Épingle Pinterest, indexée par l’identifiant numérique de l’Épingle et enregistrée dans chrome.storage.local. Il s’agit volontairement d’un prototype, pas d’une réplique des anciennes notes Pinterest prête pour la production.
Le DOM de Pinterest peut changer sans préavis. Isolez vos sélecteurs, n’imitez pas les éléments de marque protégés de Pinterest et testez tous les types de pages et toutes les langues que vous annoncez prendre en charge.
1. Créez l’extension Manifest V3
Créez un dossier contenant manifest.json et content.js. La documentation de référence du manifeste Chrome fait autorité pour les clés disponibles.
{ "manifest_version": 3, "name": "Prototype de contexte d’Épingle", "version": "0.1.0", "description": "Enregistre une note privée locale pour une Épingle Pinterest.", "permissions": ["storage"], "content_scripts": [{ "matches": ["https://*.pinterest.com/*"], "js": ["content.js"], "run_at": "document_idle" }] }
Le motif d’hôte est large, car Pinterest utilise une navigation côté client. Si votre fonctionnalité ne prend en charge qu’un nombre limité de routes ou de domaines nationaux, réduisez ce périmètre et documentez-le.
2. Dérivez une clé stable de l’URL de l’Épingle
N’utilisez ni la position d’une carte ni son titre visible comme clé de note. Extrayez l’identifiant numérique d’un chemin canonique /pin/…/ et renvoyez null dans tous les autres cas.
function getPinId(url = location.href) { try { const { pathname } = new URL(url); const match = pathname.match(/\/pin\/(\d+)\/?/); return match ? match[1] : null; } catch { return null; } }
Testez les URL de détail valides, les chaînes de requête, les pages sans Épingle, les URL mal formées et toutes les variantes locales que vous annoncez prendre en charge. N’associez jamais silencieusement une note lorsque l’identifiant est incertain.
3. Stockez un enregistrement versionné
Définissez explicitement le schéma afin de permettre les futures migrations :
async function readNote(pinId) { const key = 'pin-note:' + pinId; const result = await chrome.storage.local.get(key); return result[key] ?? { version: 1, pinId, text: '', updatedAt: null }; } async function writeNote(pinId, text) { const key = 'pin-note:' + pinId; const record = { version: 1, pinId, text, updatedAt: new Date().toISOString() }; await chrome.storage.local.set({ [key]: record }); return record; }
Chrome documente une limite par défaut de 10 Mo pour storage.local, ainsi qu’une autorisation distincte, unlimitedStorage , qui permet d’augmenter cette capacité. Chrome précise également que le stockage local de l’extension est effacé lors de sa désinstallation. Consultez la version actuelle de la documentation de l’API Storage et concevez l’export avant d’encourager les utilisateurs à confier des données importantes à l’extension.
4. Intégrez un éditeur isolé et accessible
Un Shadow DOM limite les collisions de styles accidentelles. L’exemple ajoute le composant au corps de la page afin de ne pas dépendre d’un nom de classe Pinterest fragile :
async function mountEditor(pinId) { if (document.querySelector('[data-pin-context-root]')) return; const host = document.createElement('aside'); host.dataset.pinContextRoot = ''; host.setAttribute('aria-label', 'Note privée pour une Épingle'); document.body.append(host); const root = host.attachShadow({ mode: 'open' }); const label = document.createElement('label'); label.textContent = 'Note privée'; const editor = document.createElement('textarea'); editor.id = 'pin-note-editor'; label.htmlFor = editor.id; editor.setAttribute('aria-label', 'Note privée pour cette Épingle'); const status = document.createElement('span'); status.setAttribute('role', 'status'); const saved = await readNote(pinId); editor.value = saved.text; root.append(label, editor, status); bindAutosave(editor, status, pinId); }
Créez le texte de l’interface avec textContent, jamais avec du contenu non fiable injecté dans innerHTML. Ajoutez un indicateur de focus visible, un contraste suffisant, un véritable libellé, un accès complet au clavier et un texte d’état qui ne déplace pas le focus.
5. Enregistrez sans écrire à chaque frappe
function bindAutosave(editor, status, pinId) { let saveTimer; editor.addEventListener('input', () => { status.textContent = 'Non enregistré'; clearTimeout(saveTimer); saveTimer = setTimeout(async () => { try { await writeNote(pinId, editor.value); status.textContent = 'Enregistré localement'; } catch (error) { console.error('Échec de l’enregistrement de la note', error); status.textContent = 'Enregistrement impossible'; } }, 400); }); }
En production, forcez également l’enregistrement des saisies en attente lors d’un changement de page, empêchez deux onglets de s’écraser mutuellement, fixez une taille maximale pour les notes et affichez clairement les erreurs de quota.
6. Gérez la navigation côté client de Pinterest
Un gestionnaire exécuté uniquement au chargement ne détecte pas la navigation entre le fil et les pages de détail. Utilisez une fonction de réconciliation idempotente et observez les changements sans recréer le composant à chaque mutation :
let scheduled = false; async function reconcile() { scheduled = false; const pinId = getPinId(); const existing = document.querySelector('[data-pin-context-root]'); if (!pinId) { existing?.remove(); return; } if (existing?.dataset.pinId === pinId) return; existing?.remove(); await mountEditor(pinId); const mounted = document.querySelector('[data-pin-context-root]'); if (mounted) mounted.dataset.pinId = pinId; } new MutationObserver(() => { if (scheduled) return; scheduled = true; requestAnimationFrame(reconcile); }).observe(document.documentElement, { childList: true, subtree: true }); reconcile();
Une version de production doit aussi surveiller directement l’état de navigation lorsque c’est possible et déconnecter les observateurs devenus inutiles. Mesurez les performances du code sur de longs fils : une fonction correcte qui ralentit la page reste une mauvaise extension.
7. Respectez les contraintes de sécurité de Manifest V3
Manifest V3 interdit le code exécutable hébergé à distance. Intégrez tout le JavaScript exécutable à l’extension, conservez la politique de sécurité du contenu par défaut sauf raison justifiée de la modifier, évitez l’exécution dynamique de code et ne demandez que les autorisations indispensables. La présentation de Manifest V3 par Chrome explique le modèle de la plateforme.
8. Ajoutez les fonctions nécessaires à un véritable produit
- export et import JSON avec validation du schéma et gestion des conflits ;
- export lisible par un humain pour la récupération ;
- recherche et tags optionnels ;
- indication de l’espace utilisé et du quota ;
- suppression d’une note précise ou de toutes les données ;
- politique de confidentialité conforme au comportement observable ;
- tests de migration entre les versions du schéma ;
- avertissements clairs sur la suppression à la désinstallation et sur l’absence de synchronisation ;
- télémétrie d’erreur uniquement avec une collecte minimale et une information transparente.
9. Testez les scénarios d’échec
- Chargez l’extension non empaquetée depuis
chrome://extensions. - Ouvrez un fil, un tableau, une page de détail d’Épingle et une route qui ne correspond pas à une Épingle.
- Passez d’une Épingle à une autre sans recharger la page et vérifiez que leurs notes restent isolées.
- Ouvrez la même Épingle dans deux onglets et testez la gestion des conflits.
- Désactivez le stockage ou simulez un dépassement de quota, puis vérifiez l’avertissement.
- Exportez un enregistrement de test, supprimez-le, puis restaurez-le.
- Testez la navigation au clavier, le zoom, les libellés pour lecteurs d’écran ainsi que les thèmes clair et sombre de la page.
La leçon d’ingénierie
La zone de texte est la partie facile. Une extension Pinterest digne de confiance repose sur un identifiant stable, une gestion robuste du cycle de vie, une interface accessible, des autorisations limitées, un stockage documenté et une procédure de sortie testée. Construisez ces fondations avant d’allonger la liste des fonctions.
Continuez à améliorer votre organisation sur Pinterest
Poursuivez avec le guide qui correspond à votre prochaine étape :
Essayez l'extension Notestopin pour Chrome
Ajoutez des notes privées à chaque épingle, classez-les avec des tags et retrouvez facilement vos contenus enregistrés.
Ajouter à Chrome