From 9bbe7d78cc110e66181153dacbc36d5dfdb4be39 Mon Sep 17 00:00:00 2001 From: mhoennig Date: Sun, 23 Aug 2026 10:31:04 +0200 Subject: [PATCH] feat: Falt-Voreinstellungen im Diagramm-Kopf (D44) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ein Menü mit zwei Einträgen: alle aufklappen, unter Größe M zuklappen. Das Kriterium ist die Größe, nicht die Tiefe. Die Ebene ist eine Eigenschaft der Schreibweise — ein fein zerlegter Zweig verschwände bei derselben Zahl früher als ein grob notierter. Die T-Shirt-Größe sagt etwas über die Arbeit, und ab M muss ohnehin zerlegt sein (SPEC §5): „unter M" ist genau die Menge, die keine Zerlegung mehr braucht. Ohne Größenangabe wird nicht zugeklappt. Der günstigste Pfad wertet fehlende Größen als M (D18), aber das ist eine Kostenannahme, keine Aussage des Autors. Beide Einträge beschreiben einen vollständigen Zustand — sonst hinge die Wirkung vom Vorzustand ab. Rückgängig nimmt den ganzen Vorgang in einem Schritt zurück. Umgesetzt über denselben Weg wie das einzelne Umklappen; der Voll-Rewrite ist dafür aus writeFoldToText() in writeAllFoldMarks() gewandert. Die Rückfall-Kette gilt unverändert: Im Werkbaum-Plan ist der Zustand wegen einer Fokusmarke nicht in Marken ausdrückbar, dort trägt die Sitzungs-Überlagerung. Co-Authored-By: Claude Fable 5 --- docs/DECISIONS.md | 60 +++++++++++++++++++++ docs/SPEC.md | 9 ++++ frontend/CLAUDE.md | 7 ++- frontend/index.html | 17 ++++++ frontend/src/app.js | 103 ++++++++++++++++++++++++++++++------ frontend/src/model.js | 7 +++ frontend/src/style.css | 14 +++++ frontend/tests/fold.test.js | 32 ++++++++++- 8 files changed, 232 insertions(+), 17 deletions(-) diff --git a/docs/DECISIONS.md b/docs/DECISIONS.md index c72cabd..693f3c3 100644 --- a/docs/DECISIONS.md +++ b/docs/DECISIONS.md @@ -2717,3 +2717,63 @@ Markdown; die Konvention nutzt `.txt` nur als kleinsten gemeinsamen Nenner), und der Footer-Link rückt zwischen Versionsnummer und Copyright — zur Werkzeug-Ecke des Footers statt ans Ende hinter die Rechtstexte. Der Dateiname bleibt als Linktext (übersetzungsfrei), die Wurzel-Lage bleibt. + +## D44 — Falt-Voreinstellungen: ein Menü, „unter M“ statt einer Tiefenzahl +Einzeln zu falten (D38) reicht für einen Plan mit 167 Knoten nicht — man will +den Baum am Stück auf eine Arbeitshöhe bringen. Der Diagramm-Kopf bekommt +deshalb ein Menü mit zwei Einträgen: **alle aufklappen** und **unter Größe M +zuklappen**. + +**Das Kriterium ist die Größe, nicht die Tiefe.** Die naheliegende Alternative +wäre „bis Ebene n aufklappen“ gewesen. Die Ebene ist aber eine Eigenschaft der +Schreibweise, nicht der Sache: Wie tief etwas steht, hängt davon ab, wie fein +der Autor zerlegt hat, und ein sorgfältig aufgeschlüsselter Zweig verschwände +bei derselben Zahl früher als ein grob notierter. Die T-Shirt-Größe sagt +dagegen etwas über die **Arbeit**, und die Notation hat dafür bereits eine +Schwelle: Ab `M` **muss** ein Element zerlegt sein (§5/D8). „Unter M“ ist also +genau die Menge, die keine Zerlegung mehr braucht — was darunter hängt, ist +Detail. Die Voreinstellung zeigt damit den Plan auf der Höhe, auf der noch +Entscheidungen anstehen. + +**Ohne Größenangabe wird nicht zugeklappt.** Der günstigste Pfad wertet eine +fehlende Größe als `M` (D18) — das wäre hier der falsche Präzedenzfall: Dort +ist es eine bewusst konservative **Kostenannahme** („mindestens M“), hier wäre +es eine Aussage über den Willen des Autors. Wer keine Größe angegeben hat, hat +nichts gesagt; einen Zweig deswegen zu verbergen, behandelte eine Vermutung +wie eine Angabe. Ein Knoten ohne Größe bleibt also offen — und fällt dadurch +angenehmerweise auf. + +**Beide Einträge beschreiben einen vollständigen Zustand.** „Unter M +zuklappen“ klappt nicht nur zu, es klappt alles **andere auf**. Sonst wäre die +Wirkung vom Vorzustand abhängig und zweimal Drücken ergäbe zweierlei — für +eine Voreinstellung die falsche Eigenschaft. Der Preis: Ein von Hand gesetztes +`>` an einem großen Knoten wird dabei aufgelöst. Das ist vertretbar, weil der +Nutzer gerade ausdrücklich eine Gesamtansicht angefordert hat, und weil +**Rückgängig** den ganzen Vorgang in einem Schritt zurücknimmt (nachgemessen: +`replaceTextUndoable` schreibt genau einmal, Strg+Z stellt Text und Diagramm +wieder her). + +**Umgesetzt über denselben Weg wie das einzelne Umklappen** — die +Sitzungs-Überlagerungen setzen, dann in den Text schreiben (D38-Nachtrag 2). +Dafür wanderte der Voll-Rewrite aus `writeFoldToText()` in ein eigenes +`writeAllFoldMarks(roots, want)`: Für eine Voreinstellung gibt es keinen +minimalen Patch, sie fasst den ganzen Baum an. Damit gilt auch hier die +Rückfall-Kette unverändert — ist der Zustand in Marken **nicht ausdrückbar**, +wird nicht geschrieben und die Überlagerung trägt ihn für die Sitzung. + +Genau der Fall tritt im mitgelieferten Werkbaum-Plan auf und ist beim Bauen +nachgemessen worden: Zwei Knoten sind kleiner als `M` und haben Kinder +(Zeile 94 und 100), aber in Zeile 103 steht eine Fokusmarke `!!!` unterhalb +von 94 — die holt ihren Knoten immer wieder hervor, „94 eingeklappt“ ist als +Markensatz also nicht schreibbar. Das Bild stimmt trotzdem (die Überlagerung +gewinnt in `render()`), der Text bleibt unangetastet. In einem Plan ohne `!!!` +werden die Marken geschrieben: `- [ ] > Klein (S)` und `- [ ] > Teil 3 (S)`, +während `(L)`, `(XL)` und der Knoten ohne Größe offen bleiben. + +**Ein Menü, nicht zwei Knöpfe.** Der Diagramm-Kopf trägt schon acht +Bedienelemente und bricht auf dem Telefon knapp nicht um (D17). Zwei weitere +Icon-Knöpfe hätten das gekostet — und die beiden Einträge brauchen **Text**: +„unter Größe M zuklappen“ ist als Piktogramm nicht zu sagen. Dasselbe Idiom +wie das Download-Menü (D17), nur auf **allen** Bildschirmgrößen aufklappend +statt nur auf schmalen. Nachgemessen bei 375 px: Das Menü steht mit 159 px +vollständig im Bild, die Kopfzeile bleibt einzeilig. diff --git a/docs/SPEC.md b/docs/SPEC.md index a32e877..614ac0f 100644 --- a/docs/SPEC.md +++ b/docs/SPEC.md @@ -699,6 +699,15 @@ fokussierten Knoten (WAI-ARIA-Baum-Idiom). weil eine Fokusmarke `!!!` ihren Knoten immer wieder hervorholt): Dann wird lieber nichts geschrieben, als einen Text zu hinterlassen, der etwas anderes sagt als das Bild. +- **Für den ganzen Baum** gibt es im Diagramm-Kopf ein Menü mit zwei + Voreinstellungen: **alle aufklappen** und **unter Größe M zuklappen**. Beide + beschreiben einen **vollständigen** Faltzustand — was die Voreinstellung + nicht zuklappt, ist danach offen; „unter Größe M“ meint jeden Knoten mit + Kindern, dessen **angegebene** Größe (§5) kleiner als `M` ist. Ein Knoten + **ohne** Größenangabe wird nicht zugeklappt: Der günstigste Pfad rechnet + fehlende Größen zwar als `M` (§9), das ist aber eine Kostenannahme und keine + Aussage des Autors. Geschrieben wird wie beim einzelnen Umklappen — ein + einziger Rückgängig-Schritt für den ganzen Vorgang. Siehe D44. - Faltung ist **reine Ansicht**: Warnungen aus eingeklappten Teilbäumen werden weiter gemeldet (sie gelten dem Text), und der günstigste Pfad rechnet unverändert über den ganzen Baum. diff --git a/frontend/CLAUDE.md b/frontend/CLAUDE.md index a9f4aa4..e8d9b9f 100644 --- a/frontend/CLAUDE.md +++ b/frontend/CLAUDE.md @@ -340,7 +340,12 @@ verworfene Elemente. Quelle sind ES-Module unter `src/`; `index.html` ist der Mobil die Tastatur hoch (`keyboardOnJump(true)`). Bei `src.readOnly` (Pad, D31) wird nicht geschrieben, dort trägt weiter `foldOverrides` — die Überlagerungen werden nach erfolgreichem Schreiben geleert, sonst maskieren - sie den Text. **`replaceTextUndoable()` meldet bei unveränderten Text + sie den Text. **Voreinstellungen** im Diagramm-Kopf (`applyFoldPreset`, D44) + gehen denselben Weg: Überlagerungen für ALLE faltbaren Knoten setzen + (`belowM(n)` bzw. `false`), dann `writeAllFoldMarks()` — der aus + `writeFoldToText()` herausgelöste Voll-Rewrite; einen minimalen Patch gibt es + hier nicht. Ein Knoten **ohne** Größe zählt nicht als „unter M" (anders als + bei den Pfadkosten, D18). **`replaceTextUndoable()` meldet bei unveränderten Text `false`** (D38-Nachtrag 3): Ohne Textänderung feuert kein `input`, also läuft kein `render()` — der Aufrufer muss dann selbst zeichnen. Sonst bleibt das Bild stehen (aufgefallen beim Aufklappen eines nur per Überlagerung diff --git a/frontend/index.html b/frontend/index.html index 2a3dce5..cb00ed2 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -159,6 +159,23 @@ + +
+ +
+ + +
+