2 Punkte von GN⁺ 4 시간 전 | 1 Kommentare | Auf WhatsApp teilen
  • Wordgard 0.1 ist eine neu entwickelte JavaScript-Bibliothek für Rich-Text-Editoren, die 9 Jahre Erfahrung seit der Stabilisierung von ProseMirror sowie das Design von CodeMirror 6 einfließen lässt
  • Anstatt das bestehende ProseMirror auf 2.0 umzustellen oder 1.x zu erweitern, wurde es mit einem neuen API ohne Kompatibilitätslast und unter einem separaten Namen neu entworfen
  • Das Kerndesign verwendet statt Steps ein Modell auf Basis von Änderungsabschnitten und kombiniert unabhängige Node- und Mark-Typen mit einem Facet-Erweiterungssystem nach Art von CodeMirror
  • Die Abhängigkeit vom Auswahlverhalten des Browsers wird reduziert, indem Pointer- und Tastaturauswahl direkt verarbeitet werden, aber die Touch-Auswahl bleibt wegen Problemen mit nativen Kontextmenüs bei der Browser-Implementierung
  • Die Bibliothek kann über npm als wordgard installiert werden, und Dokumentation sowie Referenzhandbuch wurden veröffentlicht, soll aber wegen Feedback und Fehlerbehebungen vorerst noch eine Weile bei Version 0.x bleiben

Charakter und Veröffentlichungsstatus von Wordgard

  • Wordgard ist ein Projekt, das ein Rich-Text-Editor-System im Stil von ProseMirror neu auflegt
  • Es wurde stark von den Erkenntnissen aus 9 Jahren seit der Stabilisierung von ProseMirror und vom Redesign von CodeMirror Version 6 beeinflusst
  • Es ist eine JavaScript-Bibliothek, die die Editor-Oberfläche über das Browser-DOM darstellt, und steht unter der MIT-Lizenz
  • Der Code ist auf einem Forgejo-Server öffentlich verfügbar
  • Es kann im npm-Register als wordgard installiert werden, Nutzungshinweise gibt es auf der Website

Warum ein neues System statt ProseMirror zu verändern

  • ProseMirror wird weiter gepflegt, aber einige Designentscheidungen sind aus heutiger Sicht Bereiche, die man anders hätte gestalten sollen
  • Würde man ein inkompatibles ProseMirror 2.0 veröffentlichen, könnte unklar werden, was genau gemeint ist, wenn Leute von „ProseMirror“ sprechen
  • Wenn man neue Ideen mit Abwärtskompatibilität an ProseMirror 1.x anfügt, kann die Struktur zu stark von Kompromissen geprägt werden
  • Wordgard übernimmt viele Ideen von ProseMirror, entwirft die Programmierschnittstelle aber von Grund auf neu, ohne Rücksicht auf Kompatibilität

Änderungsdarstellung: abschnittsbasiertes Modell statt Steps

  • Die Steps von ProseMirror teilen Änderungen in mehrere atomare Operationen auf, wobei jeder Step auf das durch den vorherigen Step erzeugte Dokument angewendet wird
  • Dieser Ansatz funktioniert, ist aber wegen Positionsanpassungen über mehrere Steps hinweg und der Nachverfolgung von Änderungsbereichen kompliziert und unhandlich
  • Wordgard verwendet auf Basis der Änderungsdarstellung von CodeMirror und des „Delta“-Formats von ShareJS ein einfacheres Modell
    • Wenn ein Dokument die Länge 10 hat und an Position 4 L eingefügt wird, wird das als [keep 4] [replace 0 with "L"] [keep 6] dargestellt
    • Werden die ersten beiden Zeichen gelöscht, lautet die Darstellung [replace 2 with ""] [keep 8]
  • Für Rich-Text-Verarbeitung werden Änderungsabschnitte ergänzt, mit denen sich Markierungen wie Hervorhebungen, Link-Stile oder Bild-Alternativtexte hinzufügen oder entfernen lassen, ohne die Struktur zu verändern
    • Wenn das Wort von 3 bis 6 fett gemacht wird, lautet die Darstellung [keep 3] [update 3 +bold] [keep 4]
  • Wordgard verwendet wie ProseMirror tokenzählende Indizes, um Dokumentpositionen als flache Sequenz aus öffnenden/schließenden Node-Tokens und Leaf-Tokens zu behandeln
  • Eine einzelne Transaktion enthält immer genau eine Änderung, wodurch Zusammensetzung, Prüfung und Ableitung von Änderungen einfacher werden
  • Es unterstützt eingeschränkte Operational Transformation, um mehrere Änderungen zusammenzuführen, die vom gleichen Ausgangsdokument ausgehen
    • Damit lassen sich Transaktionen mit mehreren Änderungen bequemer ausdrücken
    • Das kann für kollaboratives Editieren und für Undo-Historien genutzt werden, in denen nur ein Teil der Änderungen zurückgenommen wird

Wie eine gültige Dokumentstruktur erhalten bleibt

  • Wordgard-Dokumente sind keine bloßen Token-Sequenzen, sondern müssen eine balancierte Baumstruktur bilden
  • Wenn zum Beispiel ein schließendes Node-Token gelöscht wird, kann das ein Ungleichgewicht erzeugen und eine nicht anwendbare Änderung verursachen
  • Code, der Änderungsmengen erzeugt, muss Änderungen prüfen und korrigieren, sodass das Ergebnis eine gültige Dokumentstruktur bleibt
  • Auch bei Operational Transformation darf die transformierte Änderung das Dokument nicht ungültig machen
  • Das Änderungsmodell von Wordgard leitet dabei eine Fix-up-Änderung ab, die kombinierte Ergebnisse während der Transformation korrigiert
    • Dabei werden die Eingaben so verwendet, dass für A-over-B und B-over-A dieselbe Korrektur entsteht
    • Ohne diese Korrektur könnten beide Reihenfolgen dasselbe, aber ungültige Dokument erzeugen
    • Durch Komposition derselben Korrektur konvergieren beide Reihenfolgen auf dasselbe gültige Dokument
  • Die meisten Änderungen brauchen keine Korrektur, aber wenn sie nötig ist, bleibt die Konvergenz erhalten

Schema-Kombination und Verallgemeinerung von Marks

  • Im Dokumentschema von ProseMirror werden Beziehungen zwischen Nodes direkt festgelegt, weshalb es in der Regel von Hand konfiguriert werden muss
  • Node- und Mark-Typen in ProseMirror existieren nur innerhalb eines bestimmten Schemas; es gibt keine gemeinsam nutzbare Node-Identität zwischen Schemata
  • In Wordgard sind Node- und Mark-Typen unabhängige Objekte und können in mehrere Dokumentschemata aufgenommen werden
  • Diese Objekte funktionieren wie Handles mit Typisierung und Autovervollständigung, sodass sich Schemata durch Kombination der benötigten Elemente leichter erstellen lassen
  • Schemata können Beziehungen bestehender Elemente überschreiben
    • Node- oder Mark-Definitionen geben Standardinhalte oder Zieltypen vor
    • Wenn dasselbe Element anders verwendet werden soll, kann das Schema diese Beziehung ändern
  • Dadurch lassen sich reichhaltigere eingebaute Nodes bereitstellen, und Systemintegrationen wie Editor-Support-Erweiterungen oder Menü-Buttons können leichter direkt an diese Nodes gebunden werden
  • Funktionen, die bisher an bestimmte Node-Attribute gebunden waren, etwa Textausrichtung oder Alternativtext, lassen sich durch Verallgemeinerung von Marks modularer ergänzen
  • Ein Node-Typ muss selbst nicht wissen, welche Marks auf ihn angewendet werden können

Warum Inhaltsbeschränkungen gelockert wurden

  • Die charakteristische regex-basierte Beschreibung zulässiger Inhalte aus ProseMirror wird in Wordgard nicht unterstützt
  • Die Inhaltsbeschreibung von Nodes in Wordgard beschränkt nur, welche Kindtypen unterstützt werden, nicht aber deren Reihenfolge
  • Regex-basierte Beschränkungen erschweren das Schreiben allgemeiner Codepfade zur Dokumentmanipulation
    • Code, der nicht für ein bestimmtes Schema geschrieben wurde, kann kaum annehmen, welche Transformationen gültig sind
    • Jede Operation muss gegen Inhaltsbeschränkungen geprüft werden, was subtil und aufwendig ist
  • Beschränkungen, die die Dokumentform stark festschreiben, können Bearbeitungsschritte verhindern, die für den Weg zum gewünschten Ergebnis nötig sind, und damit die User Experience verschlechtern
  • Wordgard fördert einen lockereren Ansatz bei der Dokumentform
  • Wenn Invarianten benötigt werden, die über Schemaregeln hinausgehen, gibt es die Abstraktion correction
    • Unerwünschte Dokumentformen werden programmatisch korrigiert
    • Dadurch sind intelligentere, kontextbezogene Korrekturen möglich als bei erzwungenen Inhaltsausdrücken
    • Das eignet sich auch für Bedingungen wie die Sicherstellung rechteckiger Tabellen, die sich mit ProseMirror-Beschränkungen gar nicht ausdrücken ließen

Erweiterungssystem: Facets nach Art von CodeMirror 6

  • Das Erweiterungssystem von ProseMirror überträgt Plugins viele Aufgaben, und die Reihenfolge im Array beeinflusst die Priorität
  • Dabei kann es Situationen geben, in denen ein Plugin bei einem Hook niedrige, bei einem anderen aber hohe Priorität braucht
  • Das auf Facets basierende System von CodeMirror macht Erweiterungen feingranularer und erlaubt es jedem Erweiterungswert, eine eigene Prioritätskategorie festzulegen
  • Ein Facet ist ein typisierter Erweiterungspunkt, der nicht nur von der Bibliothek selbst, sondern von beliebigem Code definiert werden kann
  • Wordgard übernimmt diesen Teil des CodeMirror-Systems fast unverändert, einschließlich Mechanismen für State-Updates und Rekonfiguration
  • Konfiguration ist kein Plugin-Array, sondern ein Erweiterungsbaum
    • Definition von Event-Handlern
    • Setzen von Editor-Eigenschaften
    • Hinzufügen neuer Editor-States
  • Feature-Implementierungen bestehen in der Regel aus Bündeln von Erweiterungen, die zusammenarbeiten
  • Die primitiven Bausteine sind so gestaltet, dass sich Erweiterungs-Bundles meist gut kombinieren lassen, indem man sie einfach in die Konfiguration aufnimmt

Weniger Browser-Abhängigkeit und Auswahlverarbeitung

  • Viele Probleme in ProseMirror hängen mit der Abhängigkeit vom nativen Auswahlverhalten des Browsers zusammen
  • Der bisherige Ansatz ließ den Browser Cursorbewegungen etwa in bidirektionalem Text oder bei ungewöhnlich gestylten Inhalten verarbeiten und übernahm das Ergebnis dann in das eigene Auswahlmodell
  • Reale Browser können den Cursor aber an manchen Inhalten nicht vorbeibewegen, ihn gar nicht zeichnen, an falscher Stelle zeichnen oder sich beim Ziehen einer Mausauswahl merkwürdig verhalten
  • Wordgard verarbeitet die Auswahl per Pointer und Tastatur fast vollständig selbst
    • Es implementiert die Behandlung bidirektionaler Texte
    • Es baut ein Modell für das Content-Layout
    • Es zeichnet den Cursor selbst
  • Eine Ausnahme ist die Touch-Auswahl, die weiterhin die native Implementierung nutzt
    • Eine Neuimplementierung scheint das native Kontextmenü zu zerstören
    • Auf Smartphones und Tablets ist das Kontextmenü nur schwer zu ersetzen
    • Touch-Auswahl zeigt zudem weniger seltsames Verhalten als Tastaturauswahl

Verarbeitung von Eingabe-Events und Wegfall der DOM-Änderungsbeobachtung

  • In den vergangenen 9 Jahren ist die Browser-Unterstützung für Bearbeitungs-Events, insbesondere für beforeinput, konsistenter geworden
  • Zwar sind noch Tests unter realen Einsatzbedingungen nötig, aber Wordgard scheint ohne die DOM-Änderungsbeobachtung und Parsing-Tricks für geänderte Inhalte auszukommen, auf die ProseMirror angewiesen war
  • Wordgard verarbeitet für alles außer zusammengesetzter Texteingabe das beforeinput-Event
  • Dieser Ansatz vermeidet eine ganze Klasse von Problemen, die sonst schmutzige Workarounds erfordern

Stabilität, Versionsplan und Lizenz

  • Wordgard ist bei seiner Veröffentlichung etwas weiter fortgeschritten als frühere Projekte zum Zeitpunkt ihrer Ankündigung
  • Die Kernschnittstellen unterstützen fast alle gewünschten Funktionen, und es wurden bereits mehrere Erweiterungen geschrieben, um die Praxistauglichkeit des Designs zu prüfen
  • Die Dokumentation ist noch etwas roh, aber das Referenzhandbuch ist vollständig und nutzbar
  • Viele Probleme könnten erst sichtbar werden, wenn Menschen es in echter Arbeit einsetzen
  • Es gibt weitere Funktionen, die künftig ergänzt werden sollen, und man hofft, dass nach der Veröffentlichung auch andere einen Blick darauf werfen
  • Teile der öffentlichen Schnittstelle müssen möglicherweise mit weiteren Erkenntnissen noch einmal überdacht werden
  • Die erste Version ist 0.1; um Feedback zu sammeln, Fehler zu beheben und raue Stellen zu glätten, soll es noch eine Weile bei 0.x bleiben
    • Erwartet wird ein Zeitraum von mindestens etwa einem Jahr
  • Wie die früheren Projekte steht es unter der MIT-Lizenz
  • Es wurde auch eine restriktivere Lizenz erwogen, aber das Interesse an breiter Nutzung war größer, daher fiel die Wahl auf eine permissive Lizenz

KI-Modelle, Codegenerierung und Pull-Request-Politik

  • Für die Entwicklung dieser Software wurden Sprachmodelle nicht verwendet
  • Da JavaScript-Code im Web und Dokumentation öffentlich verfügbar sein müssen, wird davon ausgegangen, dass es keinen verlässlichen Weg gibt, öffentlich zugänglichen Code und Ideen aus großen Sprachmodellen herauszuhalten
  • Bei Wordgard wird entgegen üblicher Open-Source-Praxis experimentell darauf verzichtet, Pull Requests anzunehmen
  • Große Änderungen zu prüfen und so anzupassen, dass sie den Erwartungen entsprechen, ist oft mehr Arbeit als sie direkt selbst zu implementieren
  • Da die Kosten für Codegenerierung stark gesunken sind, wirkt ein Modell, bei dem andere Leute Code einreichen und Maintainer ihn prüfen, pflegen oder Ablehnungsgründe erklären müssen, zunehmend weniger attraktiv

1 Kommentare

 
GN⁺ 4 시간 전
Kommentare auf Lobste.rs
  • Als Autor werde ich diesen Thread gelegentlich auf Fragen oder Feedback prüfen.

    • Sieht ziemlich beeindruckend aus. Ich habe es in der FAQ nicht gesehen, aber ich frage mich, wie man es für Markdown-Bearbeitung verwenden oder einrichten könnte.
      Man könnte wohl mit einem Markdown-Renderer HTML erzeugen und es in Wordgard bearbeiten lassen, aber wie ließe sich anschließend aus dem Editor-Inhalt wieder Markdown extrahieren?
    • Ich frage mich, welchen Migrationspfad Nutzer von ProseMirror einschlagen werden.
      Werden sie am Ende zu Wordgard wechseln? Wenn jemand ProseMirror für ein neues Projekt einsetzen möchte: Wann sollte man Wordgard wählen?
  • Contains 0% AI

    Not having PRs is an effective way to nip the problem of people submitting LLM-generated slop code in the bud.

    Und es gibt auch schöne Kunst von einem echten, menschlichen Künstler.
    Gefällt mir.

  • Herzlichen Glückwunsch an Marijn zu dem Projekt und der Ankündigung. Sieht großartig aus, und mir gefällt auch die Kunst von Kamila Stankiewicz.

  • Die Haupt-Homepage des Projekts ist https://wordgard.net/

  • As a deviation from standard open-source practice, I'm doing an experiment where I don't take pull requests for Wordgard.

    Dieser Teil, insbesondere der gesamte letzte Absatz, ist wirklich interessant.
    Ich frage mich, ob dieser Ansatz eine Zeit lang häufiger werden könnte, bis wir ein besseres Verhältnis zu KI-Codegenerierung gefunden haben — oder uns vielleicht dafür entscheiden, gar keines einzugehen.
    Zur Einordnung: Der Code steht unter der MIT-Lizenz.