diff --git a/docs/DECISIONS.md b/docs/DECISIONS.md index b726d07..a4e6a9c 100644 --- a/docs/DECISIONS.md +++ b/docs/DECISIONS.md @@ -1843,6 +1843,58 @@ will. Der Streifen ist so schmal wie die Ziffern es verlangen gar nicht. `scrollEditorToOffset()` zieht die Zahlen deshalb selbst gleich mit, statt sich auf das Ereignis zu verlassen. +**Nachtrag — die Warn-Zahl trägt ihre Meldung als Tooltip.** Der Streifen sagte +bisher nur *dass* eine Zeile eine Warnung hat; *welche*, stand allein unter dem +Diagramm. Das ist der halbe Weg: Man sieht die orange Zahl, sucht dann in der +Liste die passende Zeilennummer und liest dort. Der Tooltip schließt genau +diese Lücke, und er kostet nichts Neues — die Meldung existiert schon, sie wird +nur ein zweites Mal ausgegeben. + +**Wörtlich dieselbe Meldung, aus derselben Quelle.** `formatWarning()` ist seit +jeher die eine Stelle, die die Warnungstypen kennt; sie bleibt es. Nur der +**Ausgang** ist ein anderer: Der Warnungsbereich ist HTML, ein `title` ist +Klartext. Deshalb gibt es jetzt `warningText()` daneben, gebaut aus demselben +`switch` mit einem anderen Escaper. Ohne die Trennung stünde im Tooltip +wörtlich `Drag & Drop` — und Labels mit `&`, `<` oder `"` sind keine +Ausnahme, sondern der Alltag (der Prüf-Plan trug „Plan mit "Drag & Drop"“ +genau deswegen). Ein zweiter, handgeschriebener Formatierer wäre die +naheliegende Alternative gewesen und die schlechtere: zwei Stellen, die +dieselben elf Typen kennen müssen, und die eine veraltet. + +**Mehrere Warnungen einer Zeile stehen untereinander.** Sie sind ohnehin je +eine eigene Meldung (D35 begründet das für `xorConflict`: die Warnung zeigt auf +die Zeile, die man ansehen muss); im Tooltip getrennt durch `\n`, was ein +`title` als einzige Auszeichnung kann. Der Präfix „Zeile 12: “ bleibt darin +stehen, obwohl er neben der Zahl redundant ist: Ihn zu entfernen hieße, eine +lokalisierte Vorlage in neun Sprachen zu zerschneiden — für ein paar +gesparte Zeichen an einer Stelle, an der die Wortgleichheit mit dem +Warnungsbereich mehr wert ist. + +**Der Kasten der Warn-Zahl reicht über die ganze Streifenbreite.** Die Zahlen +stehen `position:absolute; right:6px` und sind damit nur so breit wie ihre +Ziffern — auf dem Telefon rund 7 px. Ein Tooltip an einem so kleinen Ziel ist +praktisch nicht zu treffen. Warn-Zahlen bekommen deshalb `left:0;right:0` plus +`padding-right:6px`: Die **Ziffern bleiben punktgenau stehen** (nachgemessen: +rechte Kante 21,14 px, gleichauf mit einer gewöhnlichen Zahl), nur die +unsichtbare Fläche wächst. `cursor:help` sagt, dass es dort etwas zu lesen +gibt — die einzige Auffindbarkeit, die ein Tooltip haben kann (die Lehre aus +D25). + +**Kein Ersatz für den Warnungsbereich, und kein Zweitweg für Screenreader.** +Der Streifen ist `aria-hidden` (D33: reine Lesehilfe) — ein `title` darin ist +für einen Screenreader ohnehin nicht da, und das soll so bleiben: Die +Live-Region meldet neue Warnungen von selbst (§9), ein zweiter Kanal läse sie +doppelt vor. Auf Touch gibt es keinen Tooltip; anders als bei den +Knotenbeschreibungen (D52) fehlt dort aber nichts, denn die vollständige +Meldung steht sichtbar unter dem Diagramm. + +**Nachgemessen** an einem Plan mit vier Warnungen in drei Zeilen: Die drei +Zahlen tragen genau die vier Meldungen des Warnungsbereichs, Zeile 2 beide +untereinander, `&` und `"` unverfälscht; keine Zahl ohne Warnung trägt einen +`title`. Nach dem Beheben zweier Warnungen verschwinden Klasse **und** Titel +mit (Zeile 3 ganz, Zeile 2 von zwei Meldungen auf eine). Im mitgelieferten +Werkbaum-Plan (941 Zeilen, 155 Knoten, 0 Warnungen): 0 Tooltips. + ## D34 — Abhängigkeiten, IDs, XOR, Falten, Beschreibungen: erst reserviert, dann gebaut Fünf Erweiterungen auf einmal — Knoten-**IDs** (`#auth`), **Abhängigkeiten** (`:#auth,#api`) samt effektivem Status, **XOR** (`x`), ein- und ausklappbare diff --git a/docs/SPEC.md b/docs/SPEC.md index de3387c..ded8db8 100644 --- a/docs/SPEC.md +++ b/docs/SPEC.md @@ -718,6 +718,12 @@ im Text abzählen. waagerechte Verschiebung zurück — er zeigt auf eine Zeile, nicht auf ihr Ende. - Die **Cursor-Zeile** und Zeilen mit einer **Warnung** heben sich ab (Warnung in `--warn`, `#B45309`) — genau die beiden Fälle, für die man hinsieht. +- Die Zahl einer Warn-Zeile trägt die **Meldung als Tooltip** — wörtlich + dieselbe, die unter dem Diagramm im Warnungsbereich steht; mehrere Warnungen + einer Zeile stehen darin untereinander. Der Streifen bleibt `aria-hidden`: + Für Screenreader ist die Live-Region des Warnungsbereichs die Quelle, der + Tooltip erspart nur den Weg dorthin. Ohne Zeiger gibt es ihn nicht (wie + überall) — die Meldung steht dort ohnehin vollständig. Siehe D33-Nachtrag. - Reine Lesehilfe: kein Bestandteil des Notationstexts, nicht im Grafikexport und nicht im Druck (dort ist ohnehin nur das Diagramm zu sehen). diff --git a/docs/examples/werkbaum.werkbaum b/docs/examples/werkbaum.werkbaum index 8760f29..9bae3bd 100644 --- a/docs/examples/werkbaum.werkbaum +++ b/docs/examples/werkbaum.werkbaum @@ -66,6 +66,7 @@ - [^] #ed.docs.restore: Restore a shipped document from the menu (XS) - [^] #ed.jump: Jump between diagram and text (S) - [^] #ed.lineno: Line numbers in the text editor (XS) %% the warnings name them + - [x] #ed.lineno.tip: The warning is the tooltip of its number (XS) %% no hunting in the list - [^] #ed.fold: Collapsible subtrees (M) - [^] #ed.fold.marks: Initial state from the text: > collapses, < re-opens (S) - [^] #ed.fold.click: Fold and unfold in the diagram (S) @@ -479,6 +480,11 @@ same ones the warnings name. Measured rather than calculated: a wrapped line keeps exactly one number. +#ed.lineno.tip + An amber number says that a line has a warning; its tooltip says which one, + word for word as it stands below the diagram. Otherwise you read the number, + then hunt for it in the list. + #ed.fold A large plan is unreadable unless parts of it can be put away. Folding is view only — warnings from folded subtrees are still reported, because they diff --git a/frontend/CLAUDE.md b/frontend/CLAUDE.md index 98c3ec0..c43a392 100644 --- a/frontend/CLAUDE.md +++ b/frontend/CLAUDE.md @@ -55,6 +55,10 @@ verworfene Elemente. Quelle sind ES-Module unter `src/`; `index.html` ist der neutral. `render()` in app.js führt Parser- und Renderer-Warnungen zusammen (nach Zeile sortiert) und zeigt sie via `formatWarning` (warnings.js). Neue Warnungstypen dort + i18n-Key in allen 9 Sprachen ergänzen. +- **Zwei Senken, ein `switch`:** `formatWarning()` liefert HTML (Warnungsbereich), + `warningText()` Klartext (der `title` der Zeilennummer, D33-Nachtrag); beide + bauen auf `build(w, t, esc)` auf. Einen neuen Typ **nur dort** eintragen — + einen zweiten Formatierer danebenzustellen heißt, dass einer veraltet. - Modulteilung (D19): `parser.js` (Text→Baum, headless), `model.js` (Baum-/ Kostenlogik: `gateOf`, `needsBreakdown`, `visibleChildren(n, showDiscarded)`, `computeCheapSet`, `cheapCls`), `render.js` (HTML-String via diff --git a/frontend/src/app.js b/frontend/src/app.js index d1d3a76..b999118 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -2,7 +2,7 @@ import './style.css'; import { parse, setFoldMark } from './parser.js'; import { computeCheapPlan, freshProdSet, initialCollapsed, nodeKeys, effectiveStatus, atMostM } from './model.js'; import { esc, renderTreeHtml, TIP_RULE } from './render.js'; -import { formatWarning } from './warnings.js'; +import { formatWarning, warningText } from './warnings.js'; import { padUrls } from './remote.js'; /* Werkbaum, mit Werkbaum geplant — als mitgeliefertes Dokument „Werkbank" (D27). Dieselbe Datei, die auch per ?sourceUrl= geladen werden kann; `?raw` bettet @@ -156,8 +156,16 @@ function render(){ warnings = warnings.slice().sort((a, b) => (a.line || 0) - (b.line || 0)); warnBox.innerHTML = warnings.map(w => `
⚠ ${formatWarning(w, t)}
`).join(''); /* Der Zeilennummern-Streifen zeigt genau die Zeilen an, die hier genannt - werden — deshalb hängt er an derselben Warnungsliste (D33). */ - lineNoWarn = new Set(warnings.map(w => w.line).filter(Boolean)); + werden — deshalb hängt er an derselben Warnungsliste (D33). Der Text + wandert gleich mit in den `title` der Zahl (D33-Nachtrag); mehrere + Warnungen einer Zeile stehen dort untereinander. */ + lineNoWarn = new Map(); + for(const w of warnings){ + if(!w.line) continue; + const vorher = lineNoWarn.get(w.line); + const text = warningText(w, t); + lineNoWarn.set(w.line, vorher ? vorher + '\n' + text : text); + } renderLineNos(); applyOptStairs(); /* muss vor dem Messen laufen — es verschiebt Knoten */ alignStems(); @@ -832,7 +840,7 @@ function lineTops(){ in den Textfluss lässt sich nichts einfügen, ein `