docs: capitalize Firefox extension skeleton solution
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
5aa8ea2b0b
commit
ade15c5635
@@ -0,0 +1,92 @@
|
||||
# Solution : Squelette de l'extension Firefox
|
||||
|
||||
## Problème résolu
|
||||
Poser la structure minimale d'une extension Firefox (Manifest V3, **sans build
|
||||
step**, vanilla JS) chargeable en module temporaire via `about:debugging` sur
|
||||
NixOS (pas de signature requise en dev). Le clic sur l'icône doit ouvrir une
|
||||
**page dédiée autonome** — la future liste agrégeant l'Atelier du Huit et la
|
||||
ville de Cugnaux. Ce squelette ne récupère aucune donnée : il câble la chaîne
|
||||
icône → page.
|
||||
|
||||
## Approche choisie
|
||||
Entre les deux options du corps de tâche (`action.default_popup` **ou** page
|
||||
dédiée), on retient la **page dédiée** ouverte dans un onglet via
|
||||
`background.js` :
|
||||
|
||||
- « liste autonome » = vraie page plein écran, lisible, rechargeable, non
|
||||
contrainte aux ~600 px d'un popup qui se ferme à la perte de focus.
|
||||
- Cela donne un rôle concret à `background.scripts` (clé Firefox explicitement
|
||||
demandée) : écouter `action.onClicked` et faire `tabs.create`.
|
||||
- Contrainte MDN confirmée : `action.onClicked` **ne se déclenche pas** si
|
||||
`default_popup` est défini → on **n'ajoute pas** `default_popup`.
|
||||
|
||||
Pas de dépendance runtime. Tests de forme avec `bun test` à la racine,
|
||||
`web-ext lint` en contrôle dev optionnel via `bunx` (zéro dépendance ajoutée).
|
||||
|
||||
## Décisions clés
|
||||
- **Sous-dossier `extension/`** : isole l'extension chargeable (ce que voit
|
||||
`about:debugging`) du tooling bun resté à la racine (tests, `package.json`).
|
||||
Séparation des concerns nette.
|
||||
- **`strict_min_version: "127.0"`** : avant Firefox 127, les `host_permissions`
|
||||
étaient optionnelles (non accordées à l'install). Le seuil 127 garantit
|
||||
qu'elles sont accordées dès l'installation.
|
||||
- **Namespace `browser.*`** (API Firefox native, basée promesses) — jamais
|
||||
`chrome.*`. Cohérent dans tout le code.
|
||||
- **Permission `tabs` volontairement omise** : `tabs.create` ne la requiert
|
||||
pas. Principe du moindre privilège.
|
||||
- **Icône SVG unique** mappée sur les tailles `48`/`96` : accepté par Firefox,
|
||||
low-tech.
|
||||
- **`browser_specific_settings.gecko.id`** présent : identité stable de
|
||||
l'extension.
|
||||
|
||||
## Patterns à réutiliser
|
||||
**Listener `onClicked` au niveau racine (synchrone)** — l'event page MV3 peut
|
||||
être déchargée ; enregistrer le listener à la racine de `background.js` (jamais
|
||||
dans un callback async) garantit qu'il est rattaché au réveil :
|
||||
```js
|
||||
// extension/background.js
|
||||
browser.action.onClicked.addListener(() => {
|
||||
browser.tabs.create({ url: browser.runtime.getURL("liste.html") });
|
||||
});
|
||||
```
|
||||
`browser.runtime.getURL(...)` plutôt qu'une URL concaténée : robuste et sûr.
|
||||
|
||||
**Test de forme du manifeste (garde-fous structurels)** — `bun test` valide la
|
||||
structure sans navigateur, dont le garde-fou anti-régression `default_popup`
|
||||
absent :
|
||||
```ts
|
||||
const manifest = await Bun.file(join(extensionDir, "manifest.json")).json();
|
||||
test("ne définit PAS default_popup (sinon onClicked devient muet)", () => {
|
||||
expect(manifest.action.default_popup).toBeUndefined();
|
||||
});
|
||||
test("demande les host_permissions des deux sources", () => {
|
||||
expect(manifest.host_permissions).toEqual([/* URLs exactes, ordre vérifié */]);
|
||||
});
|
||||
```
|
||||
Vérifier aussi l'existence des ressources référencées (`existsSync`).
|
||||
|
||||
## Pièges à éviter
|
||||
- **`default_popup` + `onClicked` incompatibles** : ajouter `default_popup` rend
|
||||
`onClicked` muet → la page ne s'ouvre plus. Protégé par un test dédié.
|
||||
- **`host_permissions` < FF127** : sans `strict_min_version: "127.0"`, elles ne
|
||||
sont pas accordées à l'install.
|
||||
- **Listener dans un callback async** : peut être manqué au réveil de l'event
|
||||
page. Toujours au niveau racine.
|
||||
- **Module temporaire volatil** : un add-on chargé via `about:debugging`
|
||||
disparaît au redémarrage de Firefox → à recharger (nature dev, documentée
|
||||
dans le README).
|
||||
- **Ressource d'icône manquante** : si l'icône SVG n'est pas fournie, retirer
|
||||
les clés `icons`/`action.default_icon` sinon erreur de ressource au lint.
|
||||
- **Worktree sans baseline** : le worktree n'héritait pas du README/`docs/`
|
||||
canoniques. Résolu par rebase sur `main` une fois la baseline réelle commitée
|
||||
(`328df2d`). Penser à vérifier la baseline avant de dupliquer des fichiers.
|
||||
- **Warning `MISSING_DATA_COLLECTION_PERMISSIONS`** (web-ext) : non bloquant
|
||||
ici, mais Firefox recommande désormais
|
||||
`gecko.data_collection_permissions: { "required": ["none"] }` pour une
|
||||
extension sans collecte — à prévoir pour les prochaines.
|
||||
- **Diagnostics IDE `bun:test`** : `bun test` tourne sans `tsconfig`, mais
|
||||
l'éditeur signale `Cannot find module 'bun:test'` faute de `bun-types`.
|
||||
Purement cosmétique (aucun impact runtime).
|
||||
|
||||
## Tags
|
||||
tags: [firefox-extension, manifest-v3, webextension, vanilla-js, bun-test, web-ext, low-tech, nixos]
|
||||
Reference in New Issue
Block a user