diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 9c64a34..72ee12f 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -19,6 +19,7 @@ reverse. ## 2026-08-24 +- When the caret's node is folded away, the nearest visible ancestor takes the highlight — also on Alt+click from the text - A size that cannot hold its sub-packages turns its badge amber and gets a warning — sizes are read as ranges, so only sure conflicts are reported - Fix: the exported SVG drew the assumed-M badge filled like a real size instead of inverted - Dependency links now run behind every node, highlighted ones included — no more lines struck through node titles diff --git a/docs/DECISIONS.md b/docs/DECISIONS.md index 4de3d42..5b1ad13 100644 --- a/docs/DECISIONS.md +++ b/docs/DECISIONS.md @@ -2619,6 +2619,41 @@ dasselbe. Jetzt meldet die Funktion „nichts geschrieben“, und der Aufrufer zeichnet selbst neu. Nachgemessen: 144 Knoten/69 Punkte → 1/1 → 144/69 → 1/1 über mehrere Klicks. +**Nachtrag 4 — der eingeklappte Knoten vertritt seine Zeilen auch für den +Cursor.** Gemeldet als Wunsch: Steht der Cursor im Text auf einer Zeile, deren +Knoten im Diagramm eingeklappt ist, soll der nächste sichtbare Elternknoten +fokussiert werden — auch beim Alt+Klick. Bisher hob so eine Zeile schlicht +**nichts** hervor: `nodeOfLine()` sucht per `data-line` im DOM, und der +Renderer lässt eingeklappte Kinder weg (oben) — die Zeile lief ins Leere, +ausgerechnet dort, wo man ohne Hervorhebung am wenigsten sieht. + +Die Regel gibt es schon, sie galt nur noch nicht hier: **Der eingeklappte +Knoten vertritt seinen Teilbaum** — für die Pfad-Station (Nachtrag oben) wie +für den „▸ n"-Zähler. Jetzt auch für die Zeilenauflösung: Liegt die Zeile in +einem eingeklappten Teilbaum, ist ihr Vertreter der **nächste sichtbare +Vorfahr** (bei verschachtelter Faltung der äußerste eingeklappte — nur der +steht im DOM). Beschreibungs- und Fortsetzungszeilen wandern mit ihrem Knoten +mit (D40-Nachtrag 2/D59). Beide Richtungen bekommen es über die **eine** +Auflösungsstelle `nodeOfLine()` (D25-Regel: wer eine neue Zeilensuche +schreibt, nimmt sie) — Cursor-Mitlaufen, Alt+Klick, Alt+Enter und der +Mobil-Umschalter sind damit automatisch abgedeckt. + +**Die Grenze bleibt gezogen: ausgeblendete verworfene Elemente heben weiter +nichts hervor.** SPEC §9 nennt sie ausdrücklich neben Kommentar und +Leerzeile — Faltung ist Ansicht („hier, aber zusammengelegt"), der +Verworfen-Filter ist Aussage („nicht Teil des Plans"). Umgesetzt fällt die +Unterscheidung von selbst: Die Zeilen-Map (`lineTargets()` in model.js, +headless getestet) läuft über `visibleChildren()` — ausgefilterte Teilbäume +stehen gar nicht erst darin. Die Map wird in `render()` aus **denselben** +Mengen gebildet wie das DOM (`collapsedSet`, `showDiscarded`) — dieselbe +Identitäts-Regel wie bei `freshSet` (D28). + +**Nachgemessen** im Browser: Cursor auf einem verborgenen Kind → der +eingeklappte Elternknoten trägt Ring und Puls; Alt+Klick fokussiert ihn +(`document.activeElement` ist der „▸ 2"-Knoten); Cursor auf einer +ausgeblendeten verworfenen Zeile und ihrem Kind → weiterhin keine +Hervorhebung. 377 Tests, davon 5 neue in `tests/fold.test.js`. + ## D39 — Effektiver Status: die Farbe sagt die Wahrheit, die Marke die Box Mit den Abhängigkeiten (D37) gibt es zwei Aussagen je Knoten: was in der Statusbox steht (intrinsisch) und wie weit er wirklich ist (effektiv, §4). diff --git a/docs/SPEC.md b/docs/SPEC.md index 22a332f..bdf119b 100644 --- a/docs/SPEC.md +++ b/docs/SPEC.md @@ -804,7 +804,11 @@ verknüpft (siehe D25): Knoten, gehören aber zu einem, und wer darin schreibt, arbeitet an genau diesem Knoten. Das gilt für beide Richtungen der Geste (also auch für den ausdrücklichen Alt+Klick unten) und für die Hervorhebung der - Abhängigkeits-Kanten (§9). Zeilen ohne Knoten (Kommentar, Leerzeile, der + Abhängigkeits-Kanten (§9). **Liegt der Knoten der Cursor-Zeile in einem + eingeklappten Teilbaum** (§9, Falten), wird stattdessen sein **nächster + sichtbarer Vorfahr** hervorgehoben — der eingeklappte Knoten vertritt seinen + Teilbaum (D38), auch hier; das gilt ebenso für den ausdrücklichen Alt+Klick + unten. Zeilen ohne Knoten (Kommentar, Leerzeile, der `---`-Trenner selbst, ausgeblendetes verworfenes Element) heben nichts hervor. Die Hervorhebung arbeitet auf einer **eigenen Achse — Tiefe**: weißer Halo + Ring in Tinte, dazu ein Schlagschatten und eine leichte Vergrößerung, diff --git a/frontend/src/app.js b/frontend/src/app.js index 6254d28..0844f11 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -1,6 +1,6 @@ import './style.css'; import { parse, setFoldMark, expandShortIds, shortIdClosed } from './parser.js'; -import { computeCheapPlan, freshProdSet, initialCollapsed, nodeKeys, effectiveStatus, atMostM } from './model.js'; +import { computeCheapPlan, freshProdSet, initialCollapsed, nodeKeys, effectiveStatus, atMostM, lineTargets } from './model.js'; import { esc, renderTreeHtml, TIP_RULE } from './render.js'; import { formatWarning, warningText } from './warnings.js'; import { padUrls } from './remote.js'; @@ -92,6 +92,10 @@ let newsDay = null, newsKeySet = null; Textmarken, gelten nur für die Sitzung und fallen beim Dokumentwechsel weg. `foldByLine` ist der Zustand des letzten Renders für Klick/Tastatur. */ let foldOverrides = new Map(), foldByLine = new Map(); +/* Zeile -> Zeile des sichtbaren Vertreters (D38-Nachtrag 4): Für Zeilen in + eingeklappten Teilbäumen zeigt sie auf den nächsten sichtbaren Vorfahren; + `nodeOfLine()` greift darauf zurück, wenn die Zeile keinen DOM-Knoten hat. */ +let lineTargetMap = new Map(); /* ---------- Renderer (Anbindung an den DOM) ---------- parse -> Wurzeln filtern (verworfene) -> günstigen Pfad markieren -> @@ -117,6 +121,7 @@ function render(){ out.innerHTML = `