diff --git a/README.de.md b/README.de.md
index a261b99..38e5b2f 100644
--- a/README.de.md
+++ b/README.de.md
@@ -121,8 +121,25 @@ Getestet gegen Etherpad: Der Klartext-Export sendet
zurück — führende Leerzeichen, `-`/`+`/`|`, Statusboxen und `%%` überleben
Etherpads Speichermodell, das `-` wird nicht zur Aufzählung umgedeutet.
+Das Pad lässt sich auch **im Editor-Panel einbetten**: Ein Wähler in der
+Titelzeile schaltet reihum zwischen *Pad und Text* (durch einen Splitter frei
+geteilt), *nur Pad* und *nur Text*. Der schmal gezogene Textspiegel behält seinen
+Zweck — der Sprung zwischen Diagramm und Text arbeitet auf ihm, und in *nur Pad*
+holt ein Sprung ihn selbst zurück. Der Rahmen wird nur geladen, solange er
+sichtbar ist, denn ein geladenes Pad verbindet sich und zeigt dich in dessen
+Anwesenden-Liste.
+
+**Der gemeinsame Zeigefinger:** Schreib `!!!` in eine Zeile, und dieser Knoten
+wird hervorgehoben und ins Bild geholt — bei **allen**, die auf das Pad schauen.
+Das kann ein Cursor nicht. Erkannt nur als alleinstehendes Token, `Achtung!!!`
+bleibt also ein gewöhnliches Label. Die Marke bleibt stehen, bis jemand sie
+löscht.
+
**Bedenke:** Der Plantext liegt damit auf fremder Infrastruktur, und ein Pad ist
-für jeden lesbar, der die Adresse kennt. Siehe `docs/DECISIONS.md` D31.
+für jeden lesbar, der die Adresse kennt. Im eingebetteten Rahmen wird Etherpads
+Autoren-Cookie (`SameSite=Lax`) nicht mitgesendet — man gilt bei jedem Laden als
+neuer Autor, was nur serverseitig zu beheben ist (`cookie.sameSite: "None"`).
+Siehe `docs/DECISIONS.md` D31 und D32.
### Lokal ausführen
diff --git a/README.md b/README.md
index e636d86..30c7294 100644
--- a/README.md
+++ b/README.md
@@ -116,8 +116,23 @@ Verified against Etherpad: the plain-text export sends
leading spaces, `-`/`+`/`|`, status boxes and `%%` survive Etherpad's storage
model, and `-` is not turned into a bullet list.
+The pad can also be **embedded** in the editor panel: a selector in the title bar
+cycles through *pad and text* (split by a draggable divider), *pad only* and *text
+only*. The narrow text mirror keeps its purpose — the jump between diagram and
+text works on it, and in *pad only* a jump brings it back by itself. The frame is
+only loaded while it is visible, because a loaded pad connects and shows you in
+the pad's list of people.
+
+**A shared pointer:** write `!!!` on a line and that node is highlighted and
+scrolled into view — for **everyone** looking at the pad, which is something a
+cursor cannot do. Recognised only as a standalone token, so `Careful!!!` stays an
+ordinary label. It stays in the text until someone deletes it.
+
**Be aware:** your plan text then lives on third-party infrastructure, and a pad
-is readable by anyone who knows its address. See `docs/DECISIONS.md` D31.
+is readable by anyone who knows its address. In an embedded frame Etherpad's
+author cookie (`SameSite=Lax`) is not sent, so you count as a new author on every
+load — fixable only on the server (`cookie.sameSite: "None"`). See
+`docs/DECISIONS.md` D31 and D32.
### Running it locally
diff --git a/docs/DECISIONS.md b/docs/DECISIONS.md
index f6c9fe4..df02f78 100644
--- a/docs/DECISIONS.md
+++ b/docs/DECISIONS.md
@@ -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.
diff --git a/docs/SPEC.md b/docs/SPEC.md
index 09cb52a..31b0bbc 100644
--- a/docs/SPEC.md
+++ b/docs/SPEC.md
@@ -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:
diff --git a/docs/examples/example-werkbaum.werkbaum b/docs/examples/example-werkbaum.werkbaum
index 1c2dcfa..d481a5e 100644
--- a/docs/examples/example-werkbaum.werkbaum
+++ b/docs/examples/example-werkbaum.werkbaum
@@ -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)
diff --git a/frontend/CLAUDE.md b/frontend/CLAUDE.md
index 13caacd..bd4f5b9 100644
--- a/frontend/CLAUDE.md
+++ b/frontend/CLAUDE.md
@@ -170,6 +170,19 @@ verworfene Elemente. Quelle sind ES-Module unter `src/`; `index.html` ist der
Nichts. Das Markup: `#srcArea` umschließt Rahmen + Splitter + `#src`, damit die
Legenden-Aufteilung unberührt bleibt — `.editor-body textarea` ist ein
Nachfahren-Selektor und greift weiter.
+- Fokusmarke `!!!` (D32, SPEC §1): Parser setzt `focus`, Renderer die Klasse
+ `focusmark`, CSS teilt die Regel mit `.node.current` (ein Begriff „hier
+ schauen"). Erkannt **nur alleinstehend** — `(^|\s)!!!(?=\s|$)`, bewusst ohne
+ Lookbehind (Safari erst ab 16.4), sonst verlöre `Achtung!!!` seine
+ Ausrufezeichen. Extraktion **nach** den Tags; der Kommentar fällt vorher weg,
+ eine Marke hinter `%%` wirkt also nicht. `revealFocusMark()` scrollt **nur bei
+ Änderung** (Schlüssel = Label-Text, nicht Zeilennummer — Umsortieren im Pad soll
+ nicht neu scrollen), sonst zöge jeder Neubau den Blick zurück. Die Regel braucht
+ den `#out`-Präfix wie `.current` (`ul.or .node{box-shadow:none}` ist
+ spezifischer) **und** die Ausnahme
+ `.cheap-on .node:not(.cheap).focusmark{opacity:1;filter:none}` — sonst blasst die
+ Pfad-Inversion genau den Knoten aus, auf den gezeigt wird (bei einer nicht
+ gewählten Alternative gemessen: Deckkraft 0,32).
- Sprung Diagramm ↔ Text (D25): `render.js` schreibt die Parser-Zeilennummer als
`data-line` an jeden Knoten (Geister-Knoten bekommen keine). `jumpToLine()` in
`app.js` klappt bei Bedarf das Editor-Panel auf (`revealEditor()`), markiert die
diff --git a/frontend/index.html b/frontend/index.html
index ed5a7b5..8c92511 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -96,6 +96,7 @@
Einrückung (2 Leerzeichen oder Tab) definiert die Hierarchie.
- Teilpaket, alle erforderlich (all of)
+ Zugabe, nicht erforderlich (optional)
+ !!! hierhin schauen (gemeinsamer Zeigefinger)
| Alternative, eine wählen (any of)
Zeile ohne Zeichen = Wurzelknoten. | nicht mit -/+ mischen.
Status als Kästchen nach dem Zeichen, z. B. - [~] Frontend:
diff --git a/frontend/src/app.js b/frontend/src/app.js
index 7b93113..1e20e21 100644
--- a/frontend/src/app.js
+++ b/frontend/src/app.js
@@ -96,9 +96,26 @@ function render(){
/* Der Baum ist neu gebaut — die Markierung der Cursor-Zeile neu setzen (D25).
Ohne Scrollen: beim Tippen soll das Diagramm stehen bleiben. */
highlightCurrentNode(false);
+ revealFocusMark(); /* `!!!` ins Bild holen, wenn die Marke neu ist (SPEC §1) */
updateFreshBtn(); /* Zähler folgt der gerade gerenderten Menge (D28) */
}
+/* Fokusmarke `!!!` (SPEC §1): Der erste markierte Knoten wird ins Bild geholt —
+ aber nur, wenn sich die Marke **geändert** hat. Sonst zöge jeder Neubau des
+ Baums den Blick zurück und man käme nicht weg. Verglichen wird das Label des
+ Knotens, nicht die Zeilennummer: Umsortieren im Pad soll nicht als neue Marke
+ gelten. Die Hervorhebung selbst macht die Klasse `focusmark` aus dem Renderer,
+ hier geht es nur ums Scrollen. */
+let lastFocusMark = null;
+function revealFocusMark(){
+ const el = out.querySelector('.node.focusmark');
+ const key = el ? el.textContent : null;
+ if(key && key !== lastFocusMark){
+ el.scrollIntoView({block:'center', inline:'center', behavior:'smooth'});
+ }
+ lastFocusMark = key;
+}
+
/* ---------- Günstigster-Pfad-Linie ----------
Eine gestrichelte, geschwungene Petrol-Linie fädelt durch die Endknoten
(Blätter) des günstigen Pfads. Das Overlay-SVG liegt in #out und erbt damit
@@ -948,10 +965,11 @@ const I18N = {
unknownStatusWarn:"Zeile {line}: unbekanntes Statuszeichen „{code}“ — als neutral dargestellt.",
sourceLoadWarn:"„{url}“ konnte nicht geladen werden ({error}). Die Datei muss per http(s) erreichbar sein und CORS erlauben (Access-Control-Allow-Origin).",
sourceTimeoutWarn:"„{url}“ hat innerhalb von {seconds} s nicht geantwortet — der Abruf wurde abgebrochen. Etherpad begrenzt, wie oft der Export geholt werden darf (serienmäßig 10-mal pro 90 s); warte einen Moment und lade dann erneut.",
- a11yStatus:"Status: {status}", a11ySize:"Aufwand: {size}", a11ySizeImplicit:"Aufwand: M (angenommen)", a11yTags:"Zuständig: {names}", a11yOptional:"optional", a11yLink:"verlinkt",
+ a11yStatus:"Status: {status}", a11ySize:"Aufwand: {size}", a11ySizeImplicit:"Aufwand: M (angenommen)", a11yTags:"Zuständig: {names}", a11yOptional:"optional", a11yFocusMark:"hierhin schauen", a11yLink:"verlinkt",
hint_indent:"Einrückung (2 Leerzeichen oder Tab) definiert die Hierarchie.",
hint_all:"Teilpaket, alle erforderlich", hint_any:"Alternative, eine wählen",
hint_opt:"Zugabe, nicht erforderlich",
+ hint_focus:"hierhin schauen (gemeinsamer Zeigefinger)",
hint_root:"Zeile ohne Zeichen = Wurzelknoten. | nicht mit - / + mischen.",
hint_status:"Status als Kästchen nach dem Zeichen, z. B.",
hint_size:"Aufwand als T-Shirt-Größe in Klammern, Link einfach als URL anhängen:",
@@ -1011,10 +1029,11 @@ const I18N = {
unknownStatusWarn:"Line {line}: unknown status code “{code}” — shown as neutral.",
sourceLoadWarn:"Could not load “{url}” ({error}). The file must be reachable via http(s) and allow CORS (Access-Control-Allow-Origin).",
sourceTimeoutWarn:"“{url}” did not answer within {seconds} s — the request was aborted. Etherpad limits how often the export may be fetched (10 times per 90 s by default); wait a moment, then reload.",
- a11yStatus:"Status: {status}", a11ySize:"Effort: {size}", a11ySizeImplicit:"Effort: M (assumed)", a11yTags:"Assigned: {names}", a11yOptional:"optional", a11yLink:"has link",
+ a11yStatus:"Status: {status}", a11ySize:"Effort: {size}", a11ySizeImplicit:"Effort: M (assumed)", a11yTags:"Assigned: {names}", a11yOptional:"optional", a11yFocusMark:"look here", a11yLink:"has link",
hint_indent:"Indentation (2 spaces or a tab) defines the hierarchy.",
hint_all:"sub-task, all required", hint_any:"alternative, choose one",
hint_opt:"extra, not required",
+ hint_focus:"look here (a shared pointer)",
hint_root:"Line without a marker = root node. Do not mix | with - / +.",
hint_status:"Status as a checkbox after the marker, e.g.",
hint_size:"Effort as a T-shirt size in parentheses; add a link simply as a URL:",
@@ -1074,10 +1093,11 @@ const I18N = {
unknownStatusWarn:"Línea {line}: código de estado desconocido «{code}» — mostrado como neutral.",
sourceLoadWarn:"No se pudo cargar «{url}» ({error}). El archivo debe ser accesible por http(s) y permitir CORS (Access-Control-Allow-Origin).",
sourceTimeoutWarn:"«{url}» no respondió en {seconds} s — se canceló la petición. Etherpad limita la frecuencia de descarga del export (10 veces por 90 s de forma predeterminada); espera un momento y vuelve a cargar.",
- a11yStatus:"Estado: {status}", a11ySize:"Esfuerzo: {size}", a11ySizeImplicit:"Esfuerzo: M (asumido)", a11yTags:"Responsable: {names}", a11yOptional:"opcional", a11yLink:"con enlace",
+ a11yStatus:"Estado: {status}", a11ySize:"Esfuerzo: {size}", a11ySizeImplicit:"Esfuerzo: M (asumido)", a11yTags:"Responsable: {names}", a11yOptional:"opcional", a11yFocusMark:"mirar aquí", a11yLink:"con enlace",
hint_indent:"La sangría (2 espacios o un tabulador) define la jerarquía.",
hint_all:"subtarea, todas obligatorias", hint_any:"alternativa, elige una",
hint_opt:"extra, no obligatorio",
+ hint_focus:"mirar aquí (un puntero compartido)",
hint_root:"Línea sin marcador = nodo raíz. No mezcles | con - / +.",
hint_status:"Estado como casilla tras el marcador, p. ej.",
hint_size:"Esfuerzo como talla de camiseta entre paréntesis; añade un enlace simplemente como URL:",
@@ -1137,10 +1157,11 @@ const I18N = {
unknownStatusWarn:"Ligne {line} : code de statut inconnu « {code} » — affiché comme neutre.",
sourceLoadWarn:"Impossible de charger « {url} » ({error}). Le fichier doit être accessible en http(s) et autoriser CORS (Access-Control-Allow-Origin).",
sourceTimeoutWarn:"« {url} » n’a pas répondu en {seconds} s — la requête a été interrompue. Etherpad limite la fréquence de récupération de l’export (10 fois par 90 s par défaut) ; attends un instant, puis recharge.",
- a11yStatus:"Statut : {status}", a11ySize:"Effort : {size}", a11ySizeImplicit:"Effort : M (supposé)", a11yTags:"Responsable : {names}", a11yOptional:"facultatif", a11yLink:"avec lien",
+ a11yStatus:"Statut : {status}", a11ySize:"Effort : {size}", a11ySizeImplicit:"Effort : M (supposé)", a11yTags:"Responsable : {names}", a11yOptional:"facultatif", a11yFocusMark:"regarder ici", a11yLink:"avec lien",
hint_indent:"L'indentation (2 espaces ou une tabulation) définit la hiérarchie.",
hint_all:"sous-tâche, toutes requises", hint_any:"alternative, en choisir une",
hint_opt:"supplément, non requis",
+ hint_focus:"regarder ici (un pointeur partagé)",
hint_root:"Ligne sans marqueur = nœud racine. Ne mélangez pas | avec - / +.",
hint_status:"Statut sous forme de case après le marqueur, p. ex.",
hint_size:"Effort en taille de T-shirt entre parenthèses ; ajoutez un lien simplement comme URL :",
@@ -1200,10 +1221,11 @@ const I18N = {
unknownStatusWarn:"Wiersz {line}: nieznany znak statusu „{code}” — pokazany jako neutralny.",
sourceLoadWarn:"Nie udało się wczytać „{url}” ({error}). Plik musi być dostępny przez http(s) i zezwalać na CORS (Access-Control-Allow-Origin).",
sourceTimeoutWarn:"„{url}” nie odpowiedział w ciągu {seconds} s — żądanie przerwano. Etherpad ogranicza częstość pobierania eksportu (domyślnie 10 razy na 90 s); odczekaj chwilę i wczytaj ponownie.",
- a11yStatus:"Status: {status}", a11ySize:"Nakład: {size}", a11ySizeImplicit:"Nakład: M (założony)", a11yTags:"Przypisano: {names}", a11yOptional:"opcjonalny", a11yLink:"z linkiem",
+ a11yStatus:"Status: {status}", a11ySize:"Nakład: {size}", a11ySizeImplicit:"Nakład: M (założony)", a11yTags:"Przypisano: {names}", a11yOptional:"opcjonalny", a11yFocusMark:"spójrz tutaj", a11yLink:"z linkiem",
hint_indent:"Wcięcie (2 spacje lub tabulator) definiuje hierarchię.",
hint_all:"podzadanie, wszystkie wymagane", hint_any:"alternatywa, wybierz jedną",
hint_opt:"dodatek, niewymagany",
+ hint_focus:"spójrz tutaj (wspólny wskaźnik)",
hint_root:"Wiersz bez znacznika = węzeł główny. Nie mieszaj | z - / +.",
hint_status:"Status jako pole wyboru po znaczniku, np.",
hint_size:"Nakład jako rozmiar koszulki w nawiasach; link dodaj po prostu jako URL:",
@@ -1263,10 +1285,11 @@ const I18N = {
unknownStatusWarn:"Строка {line}: неизвестный код статуса «{code}» — показан как нейтральный.",
sourceLoadWarn:"Не удалось загрузить «{url}» ({error}). Файл должен быть доступен по http(s) и разрешать CORS (Access-Control-Allow-Origin).",
sourceTimeoutWarn:"«{url}» не ответил за {seconds} с — запрос прерван. Etherpad ограничивает частоту загрузки экспорта (по умолчанию 10 раз за 90 с); подождите немного и обновите снова.",
- a11yStatus:"Статус: {status}", a11ySize:"Оценка: {size}", a11ySizeImplicit:"Оценка: M (предполагается)", a11yTags:"Ответственные: {names}", a11yOptional:"необязательно", a11yLink:"со ссылкой",
+ a11yStatus:"Статус: {status}", a11ySize:"Оценка: {size}", a11ySizeImplicit:"Оценка: M (предполагается)", a11yTags:"Ответственные: {names}", a11yOptional:"необязательно", a11yFocusMark:"смотрите здесь", a11yLink:"со ссылкой",
hint_indent:"Отступ (2 пробела или табуляция) задаёт иерархию.",
hint_all:"подзадача, все обязательны", hint_any:"альтернатива, выберите одну",
hint_opt:"дополнение, не обязательно",
+ hint_focus:"смотрите здесь (общая указка)",
hint_root:"Строка без маркера = корневой узел. Не смешивайте | с - / +.",
hint_status:"Статус в виде флажка после маркера, напр.",
hint_size:"Трудоёмкость как размер футболки в скобках; ссылку добавьте просто как URL:",
@@ -1326,10 +1349,11 @@ const I18N = {
unknownStatusWarn:"पंक्ति {line}: अज्ञात स्थिति कोड „{code}“ — तटस्थ रूप में दिखाया गया।",
sourceLoadWarn:"„{url}“ लोड नहीं हो सका ({error})। फ़ाइल http(s) से उपलब्ध होनी चाहिए और CORS की अनुमति देनी चाहिए (Access-Control-Allow-Origin)।",
sourceTimeoutWarn:"„{url}“ ने {seconds} स॰ में उत्तर नहीं दिया — अनुरोध रद्द कर दिया गया। Etherpad सीमित करता है कि एक्सपोर्ट कितनी बार लिया जा सके (डिफ़ॉल्ट रूप से 90 स॰ में 10 बार); कुछ क्षण रुकें, फिर दोबारा लोड करें।",
- a11yStatus:"स्थिति: {status}", a11ySize:"आकार: {size}", a11ySizeImplicit:"आकार: M (अनुमानित)", a11yTags:"जिम्मेदार: {names}", a11yOptional:"वैकल्पिक", a11yLink:"लिंक सहित",
+ a11yStatus:"स्थिति: {status}", a11ySize:"आकार: {size}", a11ySizeImplicit:"आकार: M (अनुमानित)", a11yTags:"जिम्मेदार: {names}", a11yOptional:"वैकल्पिक", a11yFocusMark:"यहाँ देखें", a11yLink:"लिंक सहित",
hint_indent:"इंडेंट (2 स्पेस या टैब) पदानुक्रम तय करता है।",
hint_all:"उप-कार्य, सभी आवश्यक", hint_any:"विकल्प, एक चुनें",
hint_opt:"अतिरिक्त, आवश्यक नहीं",
+ hint_focus:"यहाँ देखें (साझा संकेतक)",
hint_root:"बिना मार्कर वाली पंक्ति = मूल नोड। | को - / + के साथ न मिलाएँ।",
hint_status:"मार्कर के बाद चेकबॉक्स के रूप में स्थिति, जैसे",
hint_size:"प्रयास कोष्ठक में टी-शर्ट आकार के रूप में; लिंक बस URL के रूप में जोड़ें:",
@@ -1389,10 +1413,11 @@ const I18N = {
unknownStatusWarn:"第 {line} 行:未知状态代码“{code}”——显示为中性。",
sourceLoadWarn:"无法加载“{url}”({error})。该文件必须可通过 http(s) 访问并允许 CORS(Access-Control-Allow-Origin)。",
sourceTimeoutWarn:"“{url}” 在 {seconds} 秒内没有响应 — 请求已中止。Etherpad 会限制导出的获取频率(默认每 90 秒 10 次);请稍候再重新加载。",
- a11yStatus:"状态:{status}", a11ySize:"工作量:{size}", a11ySizeImplicit:"工作量:M(假定)", a11yTags:"负责人:{names}", a11yOptional:"可选", a11yLink:"含链接",
+ a11yStatus:"状态:{status}", a11ySize:"工作量:{size}", a11ySizeImplicit:"工作量:M(假定)", a11yTags:"负责人:{names}", a11yOptional:"可选", a11yFocusMark:"看这里", a11yLink:"含链接",
hint_indent:"缩进(2 个空格或制表符)定义层级。",
hint_all:"子任务,全部必需", hint_any:"备选项,择其一",
hint_opt:"附加项,非必需",
+ hint_focus:"看这里(共享的指针)",
hint_root:"无标记的行 = 根节点。请勿将 | 与 - / + 混用。",
hint_status:"在标记后用方框表示状态,例如",
hint_size:"用括号中的 T 恤尺码表示工作量;链接直接作为 URL 附加:",
@@ -1452,10 +1477,11 @@ const I18N = {
unknownStatusWarn:"{line} 行目: 不明なステータス記号「{code}」— 中立として表示。",
sourceLoadWarn:"「{url}」を読み込めませんでした({error})。ファイルは http(s) でアクセス可能で、CORS(Access-Control-Allow-Origin)を許可する必要があります。",
sourceTimeoutWarn:"「{url}」が {seconds} 秒以内に応答しませんでした — 要求を中止しました。Etherpad はエクスポートの取得回数を制限します(既定で 90 秒あたり 10 回)。少し待ってから再読み込みしてください。",
- a11yStatus:"ステータス: {status}", a11ySize:"規模: {size}", a11ySizeImplicit:"規模: M(想定)", a11yTags:"担当: {names}", a11yOptional:"任意", a11yLink:"リンクあり",
+ a11yStatus:"ステータス: {status}", a11ySize:"規模: {size}", a11ySizeImplicit:"規模: M(想定)", a11yTags:"担当: {names}", a11yOptional:"任意", a11yFocusMark:"ここを見る", a11yLink:"リンクあり",
hint_indent:"インデント(スペース2つまたはタブ)で階層を定義します。",
hint_all:"サブタスク、すべて必須", hint_any:"選択肢、1つを選ぶ",
hint_opt:"追加、必須ではない",
+ hint_focus:"ここを見る(共有の指さし)",
hint_root:"マーカーのない行 = ルートノード。| を - / + と混在させないでください。",
hint_status:"マーカーの後にチェックボックスで状態、例:",
hint_size:"工数は括弧内の T シャツサイズで;リンクは URL としてそのまま追加:",
@@ -1493,6 +1519,7 @@ function buildHint(){
${esc(t('hint_break'))}
${esc(t('hint_comment'))}
${esc(t('hint_people'))}
+ !!! ${esc(t('hint_focus'))}