notation: !!! als Fokusmarke — ein geteilter Zeigefinger im Text

Beim gemeinsamen Arbeiten an einem Pad (D31) fehlte das Naheliegendste: „schau
mal hier". Etherpad zeigt die Cursor der anderen im Pad, aber Werkbaum kommt
nicht an sie heran — ein fremdstämmiger Rahmen gibt keinen DOM-Zugriff, der
Klartext-Export überträgt nur Text. Eine Marke IM Text ist damit nicht der
Notbehelf, sondern der einzige Weg. Und sie hat etwas, das ein Cursor nicht hat:
alle sehen dieselbe Stelle.

Erkannt wird `!!!` nur ALLEINSTEHEND (`(^|\s)!!!(?=\s|$)`), sonst verlöre jedes
„Achtung!!!" seine Ausrufezeichen und niemand fände den Grund. Bewusst ohne
Lookbehind — Safari kennt es erst ab 16.4, und die Notation soll nicht an einer
Browserversion hängen. Position in der Extraktion (SPEC §1): nach den Tags; der
Kommentar fällt vorher weg, eine Marke hinter `%%` wirkt also nicht.

Darstellung ist DIESELBE wie die der Cursor-Zeile (D25), nicht eine vierte:
neben Fokusrahmen, Strahlenkranz (D28) und Cursor-Ring wäre ein weiterer Ring
ein Zeichen zu viel — es gibt nur einen Begriff „hier schauen". Preis: Im Bild
ist nicht zu unterscheiden, ob die eigene Cursor-Zeile oder eine fremde Marke
leuchtet; für Screenreader benennt `a11yFocusMark` es ausdrücklich.

Ins Bild geholt wird nur bei ÄNDERUNG der Marke, Schlüssel ist der Label-Text
statt der Zeilennummer (Umsortieren im Pad soll nicht neu scrollen). Ohne diese
Bedingung zöge jeder Neubau den Blick zurück und man käme nicht weg. Beides
geprüft: gleiche Marke -> Scrollstand bleibt 0, Marke gewandert -> springt auf
242 und markiert den neuen Knoten.

Beim Hinsehen gefunden: Die Pfad-Inversion verschluckte den Zeigefinger. Der
erste markierte Knoten im Test war eine nicht gewählte any-of-Alternative
(„Headless CMS") — `opacity:.32; saturate(.4)`, der Ring praktisch unsichtbar.
Der Zeiger zeigte auf nichts. Dieselbe Ausnahme wie für D28 behebt es, und hier
ist sie zwingender: „Sollten wir diese verworfene Alternative noch einmal
ansehen?" ist einer der wahrscheinlichsten Gründe, überhaupt zu zeigen. Anders
als beim optionalen Knoten (D29), wo das Zurücktreten die Aussage IST.

Nicht im Druck und nicht im Grafikexport (wie die Cursor-Zeile): Die Marke sagt
„schau jetzt hierhin", nicht „so ist der Plan". Nicht ins kanonische Beispiel
(SPEC §10) aufgenommen — das ist zugleich Test-Fixture, ein dauerhafter
Zeigefinger darin wäre eine Aussage, die niemand gemacht hat.

Verworfen war `%%!` (Kommentar-Variante, bliebe harmlos liegen und könnte die
Begründung tragen) — der Nutzer wählte `!!!`, weil es im Moment des Zeigens
schnell zu tippen ist, und genau dann will man nicht über Syntax nachdenken.
Der Preis steht in D32: die Marke bleibt sichtbar stehen, bis jemand sie löscht;
Werkbaum kann sie nicht entfernen (kein Schreibzugriff auf das Pad).

SPEC §1/§9 zuerst, dann D32, dann Code. 15 neue Tests (86 -> 101), Legende und
i18n in allen 9 Sprachen.
This commit is contained in:
mhoennig
2026-07-30 13:30:50 +02:00
parent 0a08706877
commit 816a77d9e7
12 changed files with 334 additions and 19 deletions
+74
View File
@@ -1164,3 +1164,77 @@ Name und Farbe halten nicht. Reparieren lässt sich das nur **serverseitig**
Auf kleinem Bildschirm wurde „beide" nachgemessen statt geschätzt: bei 375 × 812
bleiben Pad 317 px und Spiegel 180 px, per Splitter verschiebbar — knapp, aber
brauchbar. Eine Sonderregel für Mobil braucht es deshalb nicht.
## D32 — `!!!` als Fokusmarke: ein geteilter Zeigefinger im Text
Beim gemeinsamen Arbeiten an einem Pad (D31) fehlt das Naheliegendste: „schau
mal hier". Etherpad zeigt die Cursor der anderen im **Pad**, aber Werkbaum
kommt nicht an sie heran — ein fremdstämmiger Rahmen gibt keinen DOM-Zugriff,
und der Klartext-Export überträgt ohnehin nur Text. Eine Marke **im Text** ist
damit nicht der Notbehelf, sondern der einzige Weg.
Sie hat sogar etwas, das ein Cursor nicht hat: **alle sehen dieselbe Stelle.**
Ein Cursor ist privat, `!!!` ist eine Aussage im gemeinsamen Dokument.
**Syntax `!!!`.** Vorgeschlagen und **verworfen** war `%%!` — eine
Kommentar-Variante (`- [ ] Backend %%! schau mal hier`). Deren Vorzug: Bleibt die
Marke liegen, ist sie harmlos, denn `%%` ist längst ein Kommentar (SPEC §8);
jedes andere Werkzeug und jeder Leser überliest sie, und der Resttext hätte die
Begründung tragen können. Der Nutzer hat `!!!` gewählt, „am einfachsten schnell
mal zu tippen" — und das ist das entscheidende Kriterium, weil der Moment des
Zeigens genau der Moment ist, in dem man **nicht** über Syntax nachdenken will.
Bewusst in Kauf genommen: Die Marke bleibt sichtbar im Plan stehen, bis jemand
sie löscht (Werkbaum kann sie nicht entfernen — auf das Pad gibt es keinen
Schreibzugriff), und in einer committeten Datei sieht sie nach einer Aussage über
den Knoten aus. Ebenfalls verworfen: `@@` als Pseudo-Tag — `@` bedeutet in dieser
Notation „zuständig" (SPEC §7), ein `@@` daneben lädt zur Verwechslung ein.
**Nur alleinstehend.** Erkannt wird `!!!` am Zeilenanfang/-ende oder von Leerraum
umgeben. Ohne diese Einschränkung verlöre jedes `Achtung!!!` seine
Ausrufezeichen — und niemand fände den Grund, weil die Zeile im Diagramm nur
stumm anders aussieht. `!!` und `!!!!` zählen nicht, `!!!` innerhalb einer URL
bleibt Teil der URL. Regex bewusst **ohne Lookbehind** (`(^|\s)!!!(?=\s|$)`,
führender Leerraum wird mitgefangen und wieder eingesetzt): Safari kennt
Lookbehind erst ab 16.4, und die Notation soll nicht an einer Browserversion
hängen.
Position in der Extraktionsreihenfolge (SPEC §1): **nach** den Tags, vor dem
Label. Kollisionsfrei, weil `!!!` weder `@` noch Klammern noch `:` enthält. Der
Kommentar fällt als Erstes weg — eine Marke **im** Kommentar wirkt deshalb nicht,
was richtig ist: Was hinter `%%` steht, ist Beiwerk.
**Darstellung: dieselbe wie die Cursor-Zeile** (weißer Halo + Ring in Tinte,
D25), plus Scrollen ins Bild. Erwogen war ein eigenes Aussehen (Petrol-Ring mit
Sprechblasen-Spitze); der Nutzer entschied für die vorhandene Hervorhebung. Das
ist die sparsamere Wahl: Es gibt nur **einen** Begriff „hier schauen", und neben
Fokusrahmen (Petrol), Strahlenkranz (gelb, D28) und Cursor-Ring wäre ein vierter
Ring ein Zeichen zu viel. **Preis:** Im Bild ist nicht zu unterscheiden, ob ein
Knoten wegen der eigenen Cursor-Zeile oder wegen einer fremden Marke leuchtet.
Für Screenreader wird der Unterschied benannt (`a11yFocusMark`, „hierhin
schauen"), weil ein `box-shadow` dort ohnehin nicht ankommt.
**Ins Bild geholt wird nur bei Änderung.** Schlüssel ist der **Label-Text** des
markierten Knotens, nicht die Zeilennummer: Umsortieren im Pad soll nicht als
neue Marke gelten. Ohne diese Bedingung zöge jeder Neubau des Baums den Blick
zurück — man könnte nicht wegscrollen, und bei einem Pad-Dokument wird oft neu
gebaut.
**Beim Hinsehen gefunden: die Pfad-Inversion verschluckte den Zeigefinger.**
`.cheap-on .node:not(.cheap)` setzt `opacity:.32; filter:saturate(.4)` — und die
erste markierte Alternative im Test war genau ein nicht gewählter any-of-Zweig
(„Headless CMS"). Gemessen: Deckkraft 0,32, der Ring praktisch unsichtbar. Der
Zeiger zeigte auf nichts. Dieselbe Ausnahme wie für „neu in Produktion" (D28)
behebt es, und hier ist sie noch zwingender: „Sollten wir diese verworfene
Alternative noch einmal ansehen?" ist einer der wahrscheinlichsten Gründe,
überhaupt zu zeigen. Anders als beim optionalen Knoten (D29), wo das
Zurücktreten die Aussage **ist** — dort bleibt die Schwäche bewusst stehen.
**Nicht im Druck, nicht im Grafikexport** — wie die Cursor-Zeile. Die Marke sagt
„schau jetzt hierhin", nicht „so ist der Plan"; ein Export wäre für jeden
Betrachter etwas anderes. Der Export erbt das ohnehin, weil `diagramToSvg()` nie
`box-shadow` ausliest (D25).
**Dritte, unabhängige Achse.** Die Marke sagt nichts über Fortschritt (§4) oder
Notwendigkeit (§3) — test-abgedeckt, damit niemand später Status oder `optional`
daran koppelt. **Nicht** in das kanonische Beispiel (SPEC §10) aufgenommen: Das
ist zugleich Test-Fixture, und ein dauerhafter Zeigefinger darin wäre eine
Aussage, die niemand gemacht hat.
+41 -2
View File
@@ -7,7 +7,7 @@ Syntaxänderungen werden zuerst hier dokumentiert, dann implementiert.
## 1. Zeilenformat
```
[Einrückung][Zeichen] [Statusbox] Label (Größe) URL @tag … %% Kommentar
[Einrückung][Zeichen] [Statusbox] Label (Größe) URL @tag … !!! %% Kommentar
```
Alle Bestandteile außer dem Label sind optional. Die Extraktion erfolgt in
@@ -18,7 +18,25 @@ dieser Reihenfolge (wichtig für Kollisionsfreiheit):
3. URL: erstes Token, das auf `https?://\S+` passt (dadurch stören `@` in URLs nicht).
4. Größe: erstes `(XS|S|M|L|XL|XXL)`, Groß-/Kleinschreibung egal.
5. Tags: alle `@name`-Vorkommen.
6. Rest, whitespace-normalisiert = Label. Leeres Label ⇒ Zeile ignorieren.
6. Fokusmarke: `!!!` als **alleinstehendes** Token (siehe unten).
7. Rest, whitespace-normalisiert = Label. Leeres Label ⇒ Zeile ignorieren.
**Fokusmarke `!!!`** — „schau hier hin": Der Knoten wird im Diagramm
hervorgehoben und ins Bild geholt (§9). Gedacht für das gemeinsame Arbeiten an
einem Pad (§9, `?etherpad=`): Weil dort niemand den Cursor der anderen sieht,
ist eine Marke **im Text** der einzige Weg, auf eine Stelle zu zeigen — und sie
hat etwas, das ein Cursor nicht hat: **alle** sehen dieselbe Stelle.
- Erkannt nur **alleinstehend**, also am Zeilenanfang/-ende oder von Leerraum
umgeben. `Achtung!!!` bleibt damit ein gewöhnliches Label; auch `!!!`
innerhalb einer URL bleibt Teil der URL.
- Die Marke gehört **nicht** zum Label und ist an jeder Position der Zeile
zulässig. Mehrere Marken sind erlaubt: alle markierten Knoten werden
hervorgehoben, ins Bild geholt wird der **erste**.
- Sie sagt nichts über Fortschritt (§4) oder Notwendigkeit (§3) — eine dritte,
unabhängige Achse.
- Sie bleibt im Text stehen, bis jemand sie löscht; ein Werkzeug entfernt sie
nicht von selbst.
Referenz-Regex der Implementierung:
@@ -26,6 +44,12 @@ Referenz-Regex der Implementierung:
^([ \t]*)([-|+])?\s*(?:\[([ ?~xX^/-])\]\s*)?(.*)$
```
Für die Fokusmarke (Schritt 6):
```
(^|\s)!!!(?=\s|$)
```
## 2. Hierarchie
- Die Einrückung bestimmt die Ebene. Es gibt keine feste Schrittweite:
@@ -372,6 +396,21 @@ verknüpft (siehe D25):
- Die Hervorhebung ist eine reine Editierhilfe: nicht im Grafikexport, nicht im
Druck.
### Fokusmarke im Diagramm (`!!!`, §1)
Ein mit `!!!` markierter Knoten trägt **dieselbe Hervorhebung wie die
Cursor-Zeile** (weißer Halo + Ring in Tinte) und wird ins Bild geholt — bewusst
kein eigenes Aussehen: Es gibt nur einen Begriff „hier schauen", und ein
dritter Ring neben Fokusrahmen, Strahlenkranz (§9) und Cursor-Ring wäre ein
Zeichen zu viel.
- Ins Bild geholt wird nur, wenn sich die Marke **ändert** — sonst zöge das
Diagramm bei jedem Neubau den Blick zurück und man könnte nicht wegscrollen.
- Weil `!!!` im Text steht, sehen **alle** dieselbe Stelle. Der Unterschied zur
eigenen Cursor-Zeile ist im Bild nicht zu erkennen; für Screenreader benennt
das `aria-label` die Marke ausdrücklich.
- Wie die Cursor-Zeile erscheint sie **nicht** im Druck und **nicht** im
Grafikexport: Sie sagt „schau jetzt hierhin", nicht „so ist der Plan".
### Grafikexport des Diagramms
Das Diagramm wird aus der Live-Geometrie in ein eigenständiges SVG (nur Formen
+ Text, keine externen Ressourcen) nachgezeichnet. Zwei Icon-Schaltflächen:
+1
View File
@@ -68,6 +68,7 @@
- [x] Embed the pad, keep the text mirror beside it (M)
- [x] Three views: pad and text, pad only, text only (S)
- [x] Splitter between pad and mirror (XS)
- [x] A shared pointer: !!! focuses a node for everyone (XS)
- [ ] Git as the shared store (L)
| [ ] A file in a repository, changed by pull request (S) %% works today, no code
| [?] The backend commits every change (L)