Il motore scrive i percorsi relativi alla radice del progetto (es. la wiki cyber-tesi con l'exe in una sottocartella): ora si cercano nella cartella dell'exe e poi in quelle superiori, vince la più vicina. Il catalogo JSON delle figure resta del motore; l'app mostra solo le immagini citate. Test MD-28…MD-30, ADR-0006, README, MVP e AGENT.md aggiornati. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
5.2 KiB
ADR-0006 — Immagini nel markdown: solo file locali
Contesto
Il renderer markdown (Gui/MarkdownView.cs) trasforma  nel solo testo alternativo [alt]: non carica nulla. Un motore (Claude Code, Codex) può però produrre o citare un'immagine su disco (un grafico, uno screenshot) e rispondere con . Se il percorso è noto e il file esiste, l'utente si aspetta di vederla nella chat. Oggi l'app contatta la rete solo per il controllo delle versioni (AGENT.md, "Vincoli non ovvi"); aprire le immagini remote cambierebbe questo vincolo.
Criteri di decisione
- Mostrare l'immagine quando il percorso è locale e il file è leggibile.
- Nessun accesso alla rete oltre a quello già previsto.
- Nessun crash e nessun blocco della chat per file mancanti, enormi o corrotti: ripiego sul testo alternativo di oggi.
- Coerenza con il resto del renderer: colori dal tema, testo selezionabile, accessibilità.
Opzioni considerate
| Opzione | Esito | Motivo |
|---|---|---|
Lasciare il testo [alt] |
Scartata | Il percorso noto resta inutilizzato. |
| Solo percorsi locali | Scelta | Soddisfa il caso d'uso, nessuna rete, sola lettura. |
Locali + URL http(s) |
Rimandata | Una risposta del modello farebbe partire richieste di rete verso indirizzi scelti dal modello (tracciamento, indirizzo IP dell'utente esposto). Si può riprendere con un nuovo ADR e un consenso esplicito. |
Decisione
mostra l'immagine se la destinazione è un percorso locale: assoluto, relativo oppure un URIfile://.- Percorsi relativi: radice del progetto. Il motore gira nella cartella dell'exe, ma le istruzioni che segue (il
CLAUDE.mddi una wiki) stanno di solito in una cartella superiore e scrivono i percorsi relativi a quella radice (esempio: la wikicyber-tesi, con l'exe incyber-tesi/agent-wiki-ui/e le istruzioni «, percorso relativo alla radice del repo»). Un percorso relativo si cerca quindi nella cartella dell'exe e poi in ciascuna cartella superiore, fino alla radice del filesystem; vince la prima in cui il file esiste (la più vicina all'exe). - Cataloghi e metadati restano del motore. Struttura tipo
cyber-tesi: un catalogo JSON con i metadati delle figure (raw/immagini.json: file, didascalia stampata e generata, posizione, avvertenze) e una cartella delle immagini (raw/immagini/). Chi legge il catalogo e sceglie le figure è il motore, guidato dalle istruzioni della wiki; l'app non legge né interpreta il catalogo: mostra le immagini che la risposta cita in markdown, e la didascalia, la posizione e le avvertenze che il motore scrive sotto l'immagine sono testo markdown normale. - Formati: png, jpg/jpeg, gif (primo fotogramma), webp, bmp. Altre estensioni ⇒ ripiego.
- Limiti: file fino a 20 MB; se l'immagine è più larga di 1600 px si decodifica a 1600 px di larghezza, per non occupare memoria inutile. In visualizzazione l'immagine non supera la larghezza della colonna dei messaggi (proporzioni mantenute) e non è mai ingrandita oltre l'originale.
- Un paragrafo fatto solo di immagini le mostra come blocchi; un'immagine dentro una riga di testo (o dentro un link) è inline, con larghezza massima di 480 px.
- Ripiego sul testo
[alt](come oggi) quando: la destinazione èhttp(s)o altro schema, il file manca o non è leggibile, il formato non è ammesso, il file supera il limite, la decodifica fallisce. Nessun errore a schermo, nessuna eccezione. - Caricamento in background: al rendering un controllo di controllo rapido e sincrono (percorso, estensione, esistenza, dimensione) decide se l'immagine è plausibile; se no, compare subito
[alt]. Se sì, compare[alt]come segnaposto e la decodifica avviene su un altro thread; a fine decodifica il segnaposto diventa l'immagine, se la decodifica fallisce resta[alt]. Così la GUI non si blocca con file grandi o dischi lenti. - Accessibilità: l'immagine espone
altcome nome per le tecnologie assistive e come suggerimento al passaggio del mouse. - Nessuna azione al clic (non si apre il file). Il pulsante Copia della risposta continua a copiare il markdown originale.
Conseguenze
Positive: le immagini prodotte dai motori si vedono nella chat; nessuna richiesta di rete in più; ripiego sicuro. Negative: una risposta può far leggere e mostrare un file immagine qualsiasi dell'utente (sola lettura, solo a schermo, nessun invio altrove); le immagini remote restano non supportate e si vedono come testo.
Da verificare
- Quali formati decodifica davvero Avalonia 12 con Skia su Windows e Linux (in particolare webp e gif) e se il limite di 20 MB è adeguato.
- Il comportamento dei percorsi Windows (
C:\…, UNC) e di quelli WSL (/mnt/c/…). - Se la ricerca nelle cartelle superiori debba fermarsi alla prima cartella con un marcatore di progetto (
CLAUDE.md,.git) invece di salire fino alla radice del filesystem.
Riferimenti
- MVP.md → "GUI (chat)"; matrice MD-14, MD-19…MD-30 in TESTING.md.