Additive enrichment after the list renders: never blocks the list, and a
scraping failure leaves it intact without badge. The 'Créer' button is
removed for published events (anti-duplicate).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pure matching (date locale Cugnaux + titre normalisé) and paginated
transport, both fully tested. HTML extraction via DOMParser stays impure
and untested (absent from Bun), like formulaire-mairie.js.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wire the seam end to end: the background mirrors config.local.json into
storage (a content script would need web_accessible_resources, which would
expose the email to the mairie page), and the content script lays the computed
values into the form.
The layer is deliberately thin and untested: all the logic lives in
formulaire-valeurs.js. It never writes an empty value, never touches the image,
the honeypots or the CSRF tokens, and never submits: a human reads and sends.
A banner states what is left to do, and warns when a field could not be filled,
so that a silent failure stays diagnosable.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pure, testable core of the prefill: payload + config -> flat values ready to
lay down. What the machine does not know stays empty and is listed in
aCompleter, never invented (no fake 00:00, no made-up coordinates).
DTEND is exclusive (RFC 5545): a festival on the 18th-20th carries DTEND=21,
so the end date must step back one day, in local components for all-day
events. Without it, a wrong date reaches a moderated form.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The mairie form needs an organiser, an email and the café defaults. Ship the
defaults in the repo and let each volunteer override the personal bits in
config.local.json (gitignored, optional: a fresh clone still works).
config.js carries neither import nor export on purpose, so that it loads both
as a classic script (content script, background) and as an ESM module. That is
what lets presentation.js drop its duplicated café address.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Firefox re-reads page scripts on every open but the manifest only at
install time. A "Reload" leaves the newest code running with the old
permission set, surfacing as `browser.<api> is undefined` despite a
correct manifest. This trap cost two test passes on T1; T2 adds a
CalDAV permission and would hit it next.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pierre reported the button doing nothing. The click handler dropped the
async promise, so any failure became an unhandled rejection: no tab, no
message, nothing to diagnose from — whatever the underlying cause.
T1 deliberately shipped no error UI, but the field showed that choice
makes the anomaly both invisible and undiagnosable. The failure is now
caught, logged, and named on screen, and the advice to reload covers the
orphaned page case (extension reloaded while the list stayed open).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pierre's field test: the agenda announces "10:30 → 12:30", the list only
said "à 10:30". The end date was already parsed and already in the
payload; it was purely missing from the display.
Naively rendering start → end would have been wrong four ways, all
measured against the real parser:
- no DTEND: the parser sets fin === debut, so "de 10:30 à 10:30"
- crossing midnight: "samedi de 22:00 à 02:00" hides the end date
- all-day: DTEND is EXCLUSIVE (RFC 5545), so a one-day event carries
the next day, and a 18→20 festival carries the 21st
The last one is the dangerous one: it yields a wrong date, not just an
ugly one. The end day is therefore fin minus one day, computed from
local components since a floating date has no timezone.
DECISIONS.md records the exclusive DTEND for the sibling task, which
fills the town hall's end date field straight from DTEND.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Documents the single storage key (revising the sibling task's "key =
uid" seam, which had no way to transport the uid), the explicit ISO
serialisation, and why the café fallback is display-only.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
It existed as T1's proof of life; the rendered list proves it better.
liste.js was its only caller and no longer counts VEVENTs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The list page now parses the calendar feed and renders each upcoming
event (title, date, place) in chronological order, with a button that
hands the event over to the town hall form.
Sorting, date formatting and the café fallback live in a pure
presentation module rather than in liste.js, which touches the DOM and
cannot be imported under bun test. The seam to the sibling task's
content script lives in transfert.js: a single storage slot, since a
content script running on the town hall site has no way to learn a uid.
The deposit is awaited before opening the tab, otherwise the content
script could read before the write lands.
Test timezone is pinned to Europe/Paris: date formatting is the core
logic here and would otherwise pass only on machines set to Paris.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a pure parser parserEvenements(flux, aujourdhui) backed by vendored
ical.js v2.2.1 (ESM, no build). Returns events at the frozen Event contract
{ uid, titre, description, lieu, debut, fin, categories, journeeEntiere }:
- register embedded VTIMEZONE before toJSDate (correct offset, e.g. Africa/Lagos)
- dedupe by UID, keep the master (RECURRENCE-ID exceptions ignored)
- filter to today and future (local start of day)
- coerce missing text fields to ""
Edge cases deferred to T3 (RRULE expansion, all-day hour) are documented.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Orchestrate the feed retrieval from the list page: loading / success
(event count) / actionable French error states with a Réessayer button
and an Ouvrir Nextcloud link when the session is missing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Isolated CalDAV transport module that reuses the browser's Nextcloud
session (cookies, no stored password). Returns a discriminated result
and detects the HTTP-200 login-page redirect by sniffing the body for
BEGIN:VCALENDAR. compterEvenements counts real VEVENT line starts as the
T1 proof of life.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Load via about:debugging as a temporary add-on (extension/manifest.json),
note its volatility across restarts, and add the web-ext lint command.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Manifest V3 (Firefox keys: background.scripts, host_permissions), a
background event page that opens a standalone list page on toolbar
click, and the placeholder list page (HTML/CSS/JS vanilla). No build
step. extension.test.ts validates manifest shape and referenced files.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extension Firefox pour publier une sélection d'événements du calendrier
Nextcloud de L'Atelier du Huit vers l'agenda de la mairie de Cugnaux.
- README : vue d'ensemble et installation
- CLAUDE.md : guide agent et contraintes structurantes
- docs/RECHERCHE.md : faits techniques vérifiés (CalDAV, formulaire, agenda, ICS)
- docs/DECISIONS.md : choix d'architecture et leur pourquoi
- package.json : Bun comme outil de dev minimaliste (pas de build au runtime)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>