docs: record the prefill seam and the optional local config
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
2e60bd08d8
commit
23e58b17ee
@@ -50,6 +50,37 @@ runtime à installer) :
|
||||
> Pense aussi à **fermer les anciens onglets de la liste** avant de recharger :
|
||||
> une page orpheline rend les clics inertes.
|
||||
|
||||
### Configuration (optionnelle)
|
||||
|
||||
Le formulaire de la mairie demande un **organisateur** et un **email** : ils sont
|
||||
personnels, donc absents du dépôt. Pour qu'ils soient pré-remplis :
|
||||
|
||||
```sh
|
||||
cp extension/config.local.json.example extension/config.local.json
|
||||
```
|
||||
|
||||
puis édite le fichier (il est gitignoré, il ne partira jamais sur le dépôt) :
|
||||
|
||||
```json
|
||||
{
|
||||
"organisateur": "L'Atelier du Huit",
|
||||
"email": "contact@atelier-huit.fr"
|
||||
}
|
||||
```
|
||||
|
||||
Ce fichier est **facultatif**. Sans lui, tout le reste est pré-rempli (titre,
|
||||
dates, heures, lieu, thème, tarifs) : seuls l'organisateur et l'email restent
|
||||
vides, et le bandeau du formulaire te le dit.
|
||||
|
||||
> ⚠️ Ce fichier ne surcharge que `organisateur` et `email`. Les autres valeurs
|
||||
> par défaut (thème « Culture », tarifs « Gratuit », adresse **et coordonnées**
|
||||
> du café) vont ensemble et vivent dans `extension/config.js` : c'est là qu'on
|
||||
> les change. Y mettre un `cafe` partiel produirait des coordonnées invalides.
|
||||
|
||||
> **Après avoir créé ou modifié `config.local.json`** : recharge le module dans
|
||||
> `about:debugging`. L'extension lit le fichier au réveil de son arrière-plan,
|
||||
> pas à chaque ouverture du formulaire.
|
||||
|
||||
### Vérifier l'extension
|
||||
|
||||
```sh
|
||||
|
||||
@@ -126,3 +126,58 @@ deux avals du parseur ont chacun le leur : la liste affiche l'adresse pour ne pa
|
||||
montrer une ligne vide (cas majoritaire), le content script décide s'il pose
|
||||
**aussi** les coordonnées (`input_18`). Écrire l'adresse dans le payload
|
||||
détruirait le signal « pas de lieu » dont il a besoin.
|
||||
|
||||
## 2026-07-17 — [T1] Pré-remplissage : content scripts classiques + `globalThis`
|
||||
|
||||
Le formulaire mairie est pré-rempli par deux content scripts (`config.js`,
|
||||
`formulaire-valeurs.js`, `formulaire-mairie.js`), **classiques — pas des modules
|
||||
ESM** — qui communiquent par des namespaces `globalThis` (`EchoConfig`,
|
||||
`EchoFormulaire`).
|
||||
|
||||
**Pourquoi pas ESM :** un content script n'est pas un module (`import` y lève une
|
||||
`SyntaxError`), et le `import()` dynamique y est cassé côté Firefox (bugs ouverts
|
||||
1803950 / 1536094). Restait à convertir la couture `transfert.js`, figée le
|
||||
2026-07-14 : non.
|
||||
|
||||
⚠️ **`config.js` et `formulaire-valeurs.js` n'ont NI `import` NI `export`, et
|
||||
c'est délibéré — ne pas « corriger ».** Un fichier sans les deux est valide **à la
|
||||
fois** comme script classique (content script, background) et comme module ESM
|
||||
(`import "./config.js"` depuis `presentation.js` et depuis `bun test`). C'est ce
|
||||
qui permet à `presentation.js` de partager l'adresse du café **sans build**. Le
|
||||
jour où quelqu'un y ajoute un `export`, les content scripts cassent
|
||||
silencieusement.
|
||||
|
||||
**Corollaire : l'ordre des tableaux `js` du manifest EST la dépendance**
|
||||
(`config` → `valeurs` → `mairie`), testé dans `extension.test.ts`.
|
||||
|
||||
**`CLE_EVENEMENT_EN_ATTENTE` est dupliquée** dans `formulaire-valeurs.js`
|
||||
(l'original vit dans `transfert.js`, en ESM, inatteignable depuis un content
|
||||
script classique). Un **test de dérive** garantit l'égalité des deux.
|
||||
|
||||
**Config (a) : défauts committés + `config.local.json` optionnel.** Les défauts
|
||||
(thème, tarifs, café) sont dans `config.js` ; seuls organisateur et email sont
|
||||
personnels et vivent dans `config.local.json` (gitignoré). Le fichier n'est
|
||||
**pas requis** : un clone frais doit marcher, il laisserait sinon l'extension
|
||||
cassée par défaut. Absent ou invalide → défauts nus, manque **signalé** dans le
|
||||
bandeau, jamais d'exception.
|
||||
|
||||
**C'est le background qui lit `config.local.json`**, puis le passe par le
|
||||
storage. Un content script ne pourrait le `fetch(runtime.getURL(...))` que si le
|
||||
fichier était en `web_accessible_resources` — ce qui **exposerait l'email à la
|
||||
page de la mairie**. Le fichier étant optionnel, il ne peut pas non plus être
|
||||
listé dans un tableau `js` (Firefox refuse d'installer si un fichier déclaré
|
||||
manque) : `fetch` + repli est la seule voie.
|
||||
|
||||
**On ne remplit que ce qu'on sait ; le reste est dit, jamais inventé.** Pas
|
||||
d'heure « 00:00 » pour une journée entière, pas de `lat|lng` deviné pour un lieu
|
||||
hors café, pas d'organisateur par défaut. Ce qui manque part dans le bandeau
|
||||
(`aCompleter`). En particulier, **`input_6_35` (accessibilité) est laissé
|
||||
intact** : `RECHERCHE.md` le dit « fixe », mais la machine ne sait pas si le lieu
|
||||
est accessible — cocher au hasard sur un formulaire **modéré** serait exactement
|
||||
le « champ rempli faux » qu'on veut éviter.
|
||||
|
||||
**Séparation calcul / DOM** : `formulaire-valeurs.js` est pur et testé (les dates
|
||||
sont le vrai risque, invisible sous `TZ=Europe/Paris`) ; `formulaire-mairie.js`
|
||||
est fin, impur et **non testé unitairement** — aucun harnais DOM dans le repo, et
|
||||
happy-dom n'émulerait de toute façon pas Gravity Forms. C'est le test humain qui
|
||||
tranche.
|
||||
|
||||
+28
-18
@@ -45,24 +45,34 @@ Content script qui **remplit le DOM par id**, puis **l'utilisateur soumet à la
|
||||
|
||||
### Mapping des champs (ids confirmés présents dans le HTML)
|
||||
|
||||
| id DOM | name | Contenu | Source |
|
||||
|---|---|---|---|
|
||||
| `#input_6_42` | `input_42` | Organisateur | config (« L'Atelier du Huit ») |
|
||||
| `#input_6_41` | `input_41` | Email | config |
|
||||
| `#input_6_1` | `input_1` | Titre | SUMMARY |
|
||||
| `#input_6_3` | `input_3` | Description (textarea) | DESCRIPTION |
|
||||
| `#input_6_20` | `input_20` | Thème (select) | mapping (voir §3) |
|
||||
| `#input_6_31` | `input_31` | Date début `jj/mm/aaaa` | DTSTART |
|
||||
| `#input_6_32` | `input_32` | Date fin `jj/mm/aaaa` | DTEND |
|
||||
| `#input_6_38_1` / `#input_6_38_2` | `input_38[]` | Heure début [HH, MM] | DTSTART |
|
||||
| `#input_6_39_1` / `#input_6_39_2` | `input_39[]` | Heure fin [HH, MM] | DTEND |
|
||||
| `#input_6_35` (`_1`) | `input_35.1` | Accessibilité (case) | fixe |
|
||||
| `#input_6_36` | `input_36` | Public ciblé | optionnel |
|
||||
| `#input_6_40` | `input_40` | Tarifs | défaut « Gratuit » |
|
||||
| `#nova_address` | `nova_address` | Adresse texte | défaut café |
|
||||
| `#input_6_18` | `input_18` | `lat\|lng\|adresse` (hidden) | défaut café |
|
||||
| `#input_6_34` | `input_34` | **Image (file)** | ⚠️ non remplissable par script (sécurité) → manuel |
|
||||
| `#input_6_23`, `#input_6_43` | | Honeypot | laisser vide |
|
||||
> ⚠️ **La colonne « balise réelle » a été payée par un bug** (2026-07-17). Le
|
||||
> corps de la tâche T1 affirmait « Heures = 2 **selects** » : c'est **faux**, ce
|
||||
> sont des `<input type="number">`. Le code l'a suivi et les 4 champs d'heures
|
||||
> ont échoué (`champ.options` undefined → TypeError). **Ne pas déduire le type
|
||||
> d'un champ de son intitulé : le HTML est la seule source de vérité.** Types
|
||||
> ci-dessous vérifiés sur la page réelle le 2026-07-17.
|
||||
|
||||
| id DOM | name | Balise réelle | Contenu | Source |
|
||||
|---|---|---|---|---|
|
||||
| `#input_6_42` | `input_42` | `input[type=text]` | Organisateur | config (« L'Atelier du Huit ») |
|
||||
| `#input_6_41` | `input_41` | `input[type=email]` | Email | config |
|
||||
| `#input_6_1` | `input_1` | `input[type=text]` | Titre | SUMMARY |
|
||||
| `#input_6_3` | `input_3` | `textarea` | Description | DESCRIPTION |
|
||||
| `#input_6_20` | `input_20` | **`select`** | Thème | mapping (voir §3) |
|
||||
| `#input_6_31` | `input_31` | `input[type=text]` (datepicker) | Date début `jj/mm/aaaa` | DTSTART |
|
||||
| `#input_6_32` | `input_32` | `input[type=text]` (datepicker) | Date fin `jj/mm/aaaa` | DTEND |
|
||||
| `#input_6_38_1` / `#input_6_38_2` | `input_38[]` | **`input[type=number]`** (`min/max`, placeholder `HH`/`MM`) | Heure début [HH, MM] | DTSTART |
|
||||
| `#input_6_39_1` / `#input_6_39_2` | `input_39[]` | **`input[type=number]`** | Heure fin [HH, MM] | DTEND |
|
||||
| `#input_6_35` (`_1`) | `input_35.1` | `input[type=checkbox]` | Accessibilité | ⚠️ laissé **intact** : la machine ne sait pas si le lieu est accessible |
|
||||
| `#input_6_36` | `input_36` | | Public ciblé | optionnel |
|
||||
| `#input_6_40` | `input_40` | **`textarea`** | Tarifs | défaut « Gratuit » |
|
||||
| `#nova_address` | `nova_address` | `input[type=text]` | Adresse texte | défaut café |
|
||||
| `#input_6_18` | `input_18` | `input[type=hidden]` | `lat\|lng\|adresse` | défaut café |
|
||||
| `#input_6_34` | `input_34` | `input[type=file]` | **Image** | ⚠️ non remplissable par script (sécurité) → manuel |
|
||||
| `#input_6_23`, `#input_6_43` | | | Honeypot | laisser vide |
|
||||
|
||||
Les 4 champs d'heures acceptent le **zéro-padding** (`"09"`, `"00"`) : une suite
|
||||
de chiffres est un *valid floating-point number* au sens HTML.
|
||||
|
||||
**Défaut café** : `8 Rue du Pré Vicinal 31270 Cugnaux`
|
||||
`input_18` = `43.53753132806989|1.342981890597508|8 Rue du Pré Vicinal 31270 Cugnaux`
|
||||
|
||||
Reference in New Issue
Block a user