Werkbaum hat kein Backend, und das eigentlich Schwere an gemeinsamem Bearbeiten ist das Zusammenführen gleichzeitiger Änderungen — im Plan als `[!] Merging simultaneous edits` markiert. Etherpad hat das gelöst. Also geliehen statt nachgebaut: das Pad ist die Schreibfläche, Werkbaum die Ansicht. Nachgemessen an pad.hostsharing.net, bevor irgendwas gebaut wurde: - der Klartext-Export sendet `Access-Control-Allow-Origin: *`, - das kanonische Beispiel (SPEC §10) kommt byte-identisch zurück, - der HTML-Export zeigt kein Listen-Markup — Etherpad deutet `-` nicht zur Aufzählung um und behält die führenden Leerzeichen. Das war das Risiko, das die Idee hätte erledigen können. Nicht geprüft ist das Tippen im Etherpad-Editor selbst (Tab-Einrückung, mögliches Auto-Bullet); dafür braucht es einen echten Browser. Eigener Parameter statt `?sourceUrl=`: Die URL, die ein Mensch in der Hand hat, ist die Pad-URL — `/export/txt` hängt Werkbaum selbst an. Vor allem aber lizenziert der eigene Parameter das andere Verhalten, sodass D23 unangetastet bleibt: `sourceUrl` heißt weiter „statische Datei, einmal pro Laden geholt", bestehende Links bekommen kein Polling. Name und id sind die vollständige Pad-URL (Pad-Namen sind nur pro Instanz eindeutig). Textfeld schreibgeschützt, Knopf öffnet das Pad: ohne das verschwände getippter Text beim nächsten Abruf. Schrift bleibt Tinte statt grau — hier wird gelesen, der Plantext ist der Hauptinhalt. Drei Riegel im Takt, jeder aus einem echten Fehler: - `padBusy` — im Netzwerk-Mitschnitt stapelten sich die Abrufe, weil die Gegenseite langsamer war als der Takt; eine spät eintreffende alte Antwort hätte neueren Text überschrieben, - Abbruch nach 10 s — sonst bliebe der Riegel bei hängender Gegenseite für immer zu, - `visibilityState` + `visibilitychange` — nicht im Hintergrund abrufen, aber bei Rückkehr sofort. Der Stabilitätstakt übernimmt erst beim zweiten gleichen Abruf, sonst sieht man die anderen mitten im Tippen. Die Normalisierung der Pad-Adresse liegt headless in `remote.js`, damit sie testbar ist (23 neue Tests, 60 -> 83). Im Vorschau-Browser meldet `visibilityState` „hidden" und HMR lädt bei jeder Quelländerung neu — ein Reload sieht wie eine geglückte Übernahme aus; nachgewiesen wurde die Übernahme deshalb mit einem Marker auf `window`, der einen Reload nicht überlebt. SPEC §9 zuerst, dann D31, dann Code. Der Plan bekommt den Knoten nach D30 mit `[x]`, nicht `[^]`.
29 lines
1.5 KiB
JavaScript
29 lines
1.5 KiB
JavaScript
/* Werkbaum — Adressen für Dokumente von außen (headless, D31).
|
|
Hier steht nur reine Logik, damit sie testbar ist; das Holen selbst und der
|
|
ganze DOM-Kram bleiben in app.js. */
|
|
|
|
/* Pad-Adresse normalisieren (D31). Eingabe ist die Adresse aus der Browser-
|
|
Adresszeile — ohne Export-Pfad, den hängt Werkbaum selbst an. Abgeschnitten
|
|
werden ein versehentlich mitgegebener Export- oder /timeslider-Pfad, Query,
|
|
Fragment und Schrägstriche am Ende: derselbe Pad soll genau ein Dokument
|
|
ergeben, gleich in welcher Schreibweise der Link kam.
|
|
|
|
Verlangt wird `/p/<name>` am Ende (auch unter einem Unterpfad montiert) — das
|
|
ist die Prüfung, ob überhaupt eine Pad-Adresse vorliegt. Erlaubt sind nur
|
|
http(s), wie bei ?sourceUrl= (D23).
|
|
|
|
Rückgabe {pad, text} oder null. `pad` ist zugleich Name und Identität des
|
|
Dokuments — die **vollständige** URL, nicht der bloße Pad-Name: Pad-Namen sind
|
|
nur pro Instanz eindeutig, zwei Hosts mit je einem Pad `plan` wären sonst im
|
|
Wähler nicht zu unterscheiden. */
|
|
export function padUrls(raw, base){
|
|
let u;
|
|
try{ u = base ? new URL(raw, base) : new URL(raw); }catch(_){ return null; }
|
|
if(u.protocol !== 'http:' && u.protocol !== 'https:') return null;
|
|
const path = u.pathname.replace(/\/+$/, '').replace(/\/(export\/[^/]+|timeslider)$/, '');
|
|
if(!/\/p\/[^/]+$/.test(path)) return null;
|
|
u.pathname = path; u.search = ''; u.hash = '';
|
|
const pad = u.href;
|
|
return {pad, text: pad + '/export/txt'};
|
|
}
|