← Gesamte Dokumentation
Zusammenarbeit & Review

Plugins für Zusammenarbeit & Review

Sechs Plugins, die den Editor zu einem praxistauglichen Dokument-Workflow machen: Slash-Befehle, @-Erwähnungen, Änderungsverfolgung, Kommentare mit Threads, Versionsverlauf und Präsenz auf Basis von Yjs. Alle sind in der Standardlizenz enthalten – keine Premium-Edition nötig.

Slash-Befehle

Tippen Sie / in einer leeren Zeile (oder nach Leerraum), um eine Befehlsauswahl direkt im Text zu öffnen. 15 eingebaute Blöcke (H1–H3, Aufzählungs- / nummerierte Listen, Zitat, Code, Trennlinie, Tabelle, Bild, Link, Emoji, heutiges Datum) plus jede registrierte Aktion des AI Toolkit.

Konfiguration

{
    slashCommandEnabled: true,          // default when this plugin is loaded
    slashCommandIncludeAi: true         // pull aiToolkitActions into the menu
}

API

editor.slashCommands.register({ id, label, keywords, run });
editor.slashCommands.remove(id);
editor.slashCommands.list();
editor.slashCommands.open(); / .close();

@-Erwähnungen

Framework für Auslösezeichen wie @, #, [[wiki]] oder ein beliebiges eigenes Präfix. Asynchrone Datenquellen (per Debounce verzögert, mit Ladezustand). Atomare, nicht bearbeitbare Pills – die Rücktaste entfernt den ganzen Chip.

Einen Auslöser registrieren

editor.mentions.register({
    trigger: "@",
    insertClass: "rte-mention-person",
    search: function (query, done) {
        fetch("/api/users?q=" + encodeURIComponent(query))
            .then(r => r.json())
            .then(done);                // Array<{ id, name, color? }>
    },
    renderItem: function (user) { return user.name; },
    renderInsert: function (user) { return "@" + user.name; }
});

Änderungsverfolgung (Vorschlagsmodus für Menschen)

Vorschläge wie in Word. Einfügungen erscheinen unterstrichen in der Farbe des aktuellen Benutzers; Löschungen werden durchgestrichen (und erst bei Annahme entfernt). Aufeinanderfolgende Löschungen werden zu einem Bereich zusammengefasst; die Rücktaste innerhalb einer gerade selbst getippten Einfügung verkürzt diese.

Konfiguration

{
    trackChangesEnabled: true,
    currentUser: { id: "maya", name: "Maya Patel", color: "#9333ea" },
    reviewCanDecide: (entry, action, user) => user.role === "editor"
}

Annehmen / Ablehnen pro Autor in der Review-Seitenleiste. Mit reviewCanDecide setzen Sie die Prüferrichtlinie Ihrer Anwendung durch; verweigerte Entscheidungen lassen den Vorschlag offen und lösen review_decision_denied aus. Angenommene und abgelehnte Vorschläge speichern decidedBy für einen Audit-Trail. Funktioniert zusammen mit KI-Vorschlägen – beide landen im selben Speicher editor.reviewLedger.

Kommentare mit Threads

Kommentare sind an Auswahlbereiche verankert und erscheinen als Hervorhebung plus Thread in der Seitenleiste. Eingabefeld, Antworten, Erledigen, Löschen.

Konfiguration

{
    commentsEnabled: true,
    currentUser: { id: "alice", name: "Alice Lee", color: "#2563eb" }
}

API

editor.comments.add(range, text);
editor.comments.reply(threadId, text);
editor.comments.resolve(threadId);
editor.comments.delete(threadId);
editor.comments.list();

Versionsverlauf

Browser für Snapshots mit einem Vorschau-iframe in einer Sandbox und einem zeilenbasierten Diff auf LCS-Basis. Manuelle oder per Debounce verzögerte automatische Snapshots. Standardmäßig localStorage, alternativ POST an einen Server-Endpoint.

Konfiguration

{
    revisionHistoryEnabled: true,
    revisionHistoryMaxEntries: 50,
    revisionHistoryAutoSnapshotMs: 10000,
    revisionHistoryUrl: "/api/revisions",       // optional
    revisionHistoryRequestHeaders: () => ({
        "X-CSRF-Token": readCsrfToken()
    }),
    onRevisionHistorySyncError: ({ reason, status }) => {
        reportSyncProblem(reason, status);
    }
}

Verwenden Sie einen Endpoint am selben Origin mit Ihrer bestehenden Session und Ihrem CSRF-Schutz. Header-Werte können von einer Funktion geliefert werden, sodass ein kurzlebiges Antiforgery-Token zum Zeitpunkt des Requests gelesen werden kann. Legen Sie keine langlebigen API-Schlüssel in die Konfiguration des Editors.

API

editor.revisionHistory.snapshot(label?, metadata?);
editor.revisionHistory.promptAndSnapshot(defaultLabel?);   // native prompt + snapshot
editor.revisionHistory.rename(id, label);
editor.revisionHistory.list();                             // all snapshots
editor.revisionHistory.listNamed();                        // user-labeled only
editor.revisionHistory.diff(idA, idB);                     // { lines, oldText, newText }
editor.revisionHistory.restore(id);
editor.revisionHistory.delete(id);
editor.revisionHistory.openBrowser();

Yjs-Präsenz & gleichzeitiges Tippen

Live-Cursor, Präsenz-Avatare, gemeinsames Review-Ledger. Yjs ist eine Peer Dependency – das Plugin liefert es nie mit. Sie laden Yjs + einen Provider (WebSocket / WebRTC / Hocuspocus) und übergeben sie.

Anbinden

import * as Y from "yjs";
import { WebsocketProvider } from "y-websocket";

const ydoc = new Y.Doc();
const provider = new WebsocketProvider("wss://collab.example.com", docId, ydoc);

editor.collab.attach({
    doc: ydoc,
    provider: provider,
    user: { id: "alice", name: "Alice", color: "#2563eb" },
    textSync: "crdt",      // per-node Yjs CRDT; load crdt-engine.min.js first
    requireCrdt: true       // do not silently fall back to legacy snapshots
});

textSync: "crdt". Die Bindung pro Knoten spiegelt das bearbeitbare DOM in ein Y.XmlFragment und erhält gleichzeitige Text- und Formatierungsänderungen ohne das frühere Zurücksetzen des gesamten Bodys. Rufen Sie nach dem Anbinden editor.collab.getStatus() auf, um den aktiven Modus und einen etwaigen Grund für einen Fallback festzuhalten.

WebSocket-Edge für die Produktion

Der mitgelieferte Server für Zusammenarbeit unterstützt signierte, auf einen Raum beschränkte Tokens, dauerhaften Zustand in LevelDB, eine Allowlist für Browser-Origins und eine Obergrenze für Verbindungen pro Raum. Verwenden Sie in der Produktion alle vier Mechanismen; terminieren Sie TLS an Ihrem Proxy und stellen Sie keinen offenen WebSocket-Endpoint bereit.

RTE_COLLAB_SECRET="use-a-long-random-secret"
RTE_COLLAB_PERSIST="/var/lib/rte-collab"
RTE_COLLAB_ALLOWED_ORIGINS="https://app.example.com,https://admin.example.com"
RTE_COLLAB_MAX_CONNECTIONS_PER_ROOM="100"
RTE_COLLAB_REDIS_URL="redis://redis:6379"
node server.js

Der Token-Endpoint in der Cloud prüft die Eigentümerschaft am Dokument, bevor er eine kurzlebige Berechtigung für einen Raum ausstellt. Der Server lehnt fehlende oder nicht gelistete Browser-Origins mit HTTP 403 ab und überzählige Peers in einem stark genutzten Raum mit HTTP 429. Setzen Sie auf jeder Replika dieselbe Redis-URL, um Dokument- und Awareness-Updates ohne Sticky Sessions weiterzuleiten; eine Replika, die einem aktiven Raum beitritt, fordert einen vollständigen Snapshot des CRDT-Zustands an, bevor sie ihren ersten Client synchronisiert. Ist das konfigurierte Redis nicht erreichbar, gibt /healthz HTTP 503 und status: "degraded" zurück. Nach dem erneuten Verbinden bleibt die Bereitschaft eingeschränkt, bis ein interner Pub/Sub-Roundtrip beweist, dass das Abonnement wieder empfängt.

Jeder Peer ist eine nicht vertrauenswürdige Eingabe

Ein CRDT wendet entfernte Änderungen an, indem es Knoten direkt in das laufende Dokument schreibt. Das geht weder durch die Behandlung beim Einfügen noch durch setHTMLCode, und ein Editor, der nur diese beiden Eingänge filtert, führt ein <iframe srcdoc> eines Mitwirkenden bereitwillig im Browser jedes anderen Teilnehmers aus – und repliziert es weiter. Behandeln Sie einen Mitautor eines gemeinsamen Dokuments genau so wie eingefügtes HTML.

sanitizer.js schließt diesen Weg: Es beobachtet den bearbeitbaren Bereich auf eingefügte Knoten und Attribute und filtert alles Ausführbare, bevor es laufen kann, ganz gleich, woher es stammt. Normales Tippen kostet nichts, weil Textknoten übersprungen werden und der Filter erst eingreift, wenn etwas Gefährliches auftaucht. Schalten Sie ihn mit sanitizerGuardLiveDom: false ab, wenn Ihre Synchronisationsschicht schon vorher bereinigt. Diese Prüfung können Sie selbst auf der Live-Verifizierungsseite ausführen.

Die Release-Testsuite startet zwei unabhängige WebSocket-Serverprozesse gegen einen isolierten, echten Redis-kompatiblen Prozess und prüft spätes Beitreten, Inhalt und Präsenz in beide Richtungen, Isolation von Räumen und Tokens, den Ausfall des Backends, die Wiederherstellung der Bereitschaft und die erste Änderung nach der Wiederherstellung. Das ist ein vom Hersteller durchgeführter Integrationsnachweis, kein SLA eines verwalteten Dienstes und keine externe Zuverlässigkeitszertifizierung.

Gemeinsames Review-Ledger

KI-Vorschläge, Vorschläge aus der Änderungsverfolgung von Menschen und Kommentare laufen alle durch einen einzigen Speicher: editor.reviewLedger. Deshalb kann die Review-Seitenleiste sie gemischt anzeigen, und Annehmen / Ablehnen funktioniert unabhängig von der Quelle gleich.

API

editor.reviewLedger.add(entry);            // { id, changeType, author, text, replies[], ... }
editor.reviewLedger.update(id, patch);
editor.reviewLedger.remove(id);
editor.reviewLedger.get(id);
editor.reviewLedger.list();
editor.reviewLedger.refreshPanel();