Upgrade auf Mathjax Version 4

@sam und alle, die daran interessiert sind, Mathematik in Discourse einzutippen. Ich habe das Plugin discourse-math so aktualisiert, dass es MathJax V3 anstelle des viel langsameren und sehr veralteten V2 verwendet. Wie erwartet, führt dies zu einer viel schnelleren Benutzererfahrung, während die funktionsreiche Umgebung im Vergleich zu KaTeX beibehalten wird.

Ich würde gerne einen Pull-Request stellen, wenn Ihnen die Ergebnisse gut gefallen.


Sie können es auf der Discourse-Seite meiner Klasse in Aktion sehen:

Die meisten Inhalte auf dieser Seite sind privat oder nicht gelistet. Es sollten sich oben einige Themen in der Kategorie MathJax V3 befinden, die die Ideen veranschaulichen, obwohl

Sie können den Code für das Plugin im diesem eigenständigen discourse-mathjax-Plugin-Repository einsehen. Die Datei mit den mit Abstand meisten Änderungen ist der Initialisierer.

Sie können dieses Repository auch verwenden, um es sofort auf einer eigenständigen Seite zu installieren. Stellen Sie einfach sicher, dass Sie das alte Repository während der Installation entfernen. Sie würden also die Standard-Plugin-Installationstechnik wie folgt ändern:

hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - rm -r discourse-math
          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/mcmcclur/discourse-math.git

Kommentare

Die neueste Version von MathJax ist eigentlich 4.0.0. Ich habe mich aus mehreren Gründen für V3.2.2 entschieden:

  • Obwohl V4 sicherlich viel schneller als V2 ist, ist es nicht ganz so schnell wie V3.
  • Die Benutzererfahrung ist in V4 etwas anders, besonders wenn der Benutzer auf die Ausgabe klickt.
  • Der Status 4.0.0 lässt mich vermuten, wie viele Fehler es geben könnte.

Nichtsdestotrotz ist die API für V4 identisch mit der von V3. Es sollte möglich sein, später ein Upgrade durchzuführen, indem man einfach das neueste MathJax-Repository einfügt.

Ich musste eine kleine Änderung in der Datei locales/server.en.yml vornehmen. Natürlich gibt es noch unzählige weitere solcher Dateien für verschiedene Sprachen. Mein Verständnis ist, dass diese anderen Dateien später automatisch übersetzt werden?

Ich nutze Chat überhaupt nicht und habe es in diesem Kontext nicht getestet.

4 „Gefällt mir“

Pull Request zum Upgrade auf MathJax V3 mit bestandenen Tests erstellt!

2 „Gefällt mir“

Bezüglich:

Das ist fantastisch :hugs: , aber ich frage mich, ob wir dies als Gelegenheit nutzen können, unser Repository etwas zu verkleinern.

Nachdem wir MathJax in den Kern verschoben haben, können wir uns auf pnpm verlassen, um das Paket zu ziehen, und vermeiden, den gesamten Quellcode zu bündeln, wie wir es zum Beispiel für FullCalendar tun.

Insbesondere ist das Ziel, nur noch „Links“ in unserem Repository zu haben, und dann können wir den Build-Prozess nutzen, um die korrekten Abhängigkeiten zu ziehen.

Geben Sie uns ein paar Tage, ich möchte mich hier mit dem Dev-XP-Team beraten. Vielen Dank für Ihre Bemühungen hier!

4 „Gefällt mir“

Ja, ich denke, das ist mit Sicherheit das Richtige. Ich habe mich immer gefragt, warum Sie das ganze Ding verpackt haben!

Also, ich nehme an, Sie werden eine loadMathJax-Funktion für Ihre Bibliothek erstellen, die zum Laden von MathJax verwendet wird?

Ich muss sagen, dass das Zusammenfassen aller Plugins im Core es etwas schwieriger gemacht hat, damit herumzuspielen. Die Abhängigkeiten an den Build-Prozess zu binden, würde es nur noch schwieriger machen, obwohl ich sicher bin, dass ich MathJax oder FullCalendar von einem CDN ziehen könnte.

Ich spreche hauptsächlich davon, wenn ich mit Plugins für die Verwendung in meinen eigenen Foren herumspiele, und ich denke absolut, dass Sie MathJax während des Builds ziehen sollten.

Absolut! Ich benutze Discourse seit Jahren und freue mich sehr, dass Sie das fantastisch finden! :rocket:

3 „Gefällt mir“

Ja, genau. Ein gutes Beispiel zum Kopieren ist morphlex:

1 „Gefällt mir“

Ich frage mich, ob Sie schon mit Ihren Developer Experience-Leuten sprechen konnten? Ich helfe gerne, wenn ich kann. Mein Eindruck ist jedoch, dass ich ohne Ihr Feedback dazu wirklich nichts tun kann.

Ich habe einige zusätzliche Änderungen in einem separaten Branch vorgenommen, über die ich bald berichten werde. Mir ist bewusst, dass Sie viel zu tun haben, daher möchte ich nicht lästig sein!

Ich habe das discourse-math-Plugin so modifiziert, dass es viel mehr mathematische Eingaben parsen kann.

@sam Als ich 2017 zum ersten Mal zu diesem Plugin beigetragen habe, erinnere ich mich, dass du sehr darauf bestanden hast, dass das Parsen sehr streng sein sollte. Ich möchte gleich zu Beginn sagen, dass meine Hauptmotivation, das Parsen zu lockern und zu erweitern, darin bestand, dass es mit KI besser funktioniert. Insbesondere wenn man mit einem KI-Bot über Mathematik chattet, wird man oft feststellen, dass er mit LaTeX antwortet, und es gibt viele Möglichkeiten, wie er diese LaTeX-Eingabe abgrenzen könnte. Obwohl ich also deine Motivation für strenges Parsen verstehe, sind die von mir vorgenommenen Änderungen für diesen Anwendungsfall eher unerlässlich.

Natürlich kann es dir trotzdem egal sein, daher habe ich die Änderungen in einem separaten Branch von meinem V3-Pull-Request abgelegt. Wenn du entscheidest, dass sie dir gefallen, stelle ich gerne einen weiteren Pull-Request.

Die spezifischen Änderungen am Pull-Request sind:

Es akzeptiert schrägstrich-klammer-begrenzten Inline-Math wie \\(a^2+b^2=c^2\\).

Es akzeptiert einzeiligen doppelt-dollar-begrenzten Display-Math wie
$$a^2+b^2=c^2.$$

Es akzeptiert einzeiligen schrägstrich-eckige-klammer-begrenzten Display-Math wie
\\[a^2+b^2=c^2.\\]

Es akzeptiert mehrzeiligen schrägstrich-eckige-klammer-begrenzten Display-Math wie
\\[
a^2+b^2=c^2.
\\]

Natürlich akzeptiert es immer noch die Eingaben des Originals:

Dollar-begrenzter Inline-Math: $a^2+b^2=c^2$.

Mehrzeiliger, doppelt-dollar-begrenzter Display-Math:
$$
a^2+b^2=c^2.
$$

Du findest den relevanten Branch hier.

Der Code existiert auch als eigenständiges Plugin.

Oh, du kannst es auch in Aktion sehen!

2 „Gefällt mir“

@mcmcclur Vielen Dank für Ihre Arbeit. Es wäre großartig, diese Funktionen im Kern zu sehen.

1 „Gefällt mir“

Vielen Dank, Mark.

Mein größtes Hindernis hier ist, dass ich unbedingt zu den neuen Mustern für die Abhängigkeitsverteilung wechseln möchte, siehe:

Könntest du dir das ansehen?

Bezüglich der gelockerten Syntax, das fühlt sich für mich wie eine Site-Einstellung an, vielleicht sogar standardmäßig aktiviert, angesichts all der LLMs, die es gibt?

3 „Gefällt mir“

@mcmcclur Ich habe heute damit herumgespielt:

Noch lange nicht fertig … aber die Dinge starten mit 4.1, was schön ist.

2 „Gefällt mir“

Ja, das ist definitiv ein Fortschritt!
Das erste wichtige Problem, das angegangen werden muss, wie ich vermute, Sie wissen, ist, dass die Schriftarten nicht gefunden werden. Tatsächlich habe ich mit dieser Zeile in discourse-math-mathjax.js herumgespielt:

fontURL: getURLWithCDN("/assets/mathjax/woff-v2"),

Als Test habe ich die URL so eingestellt, dass sie einfach auf ein temporäres Verzeichnis auf meinem eigenen Webserver zeigt, und die ersten Ergebnisse sehen sehr gut aus. Es geht also darum, diese Schriftarten korrekt in Discourse zu installieren.
In einem einfachen pnpm-Projekt auf meiner Maschine installiert der folgende Befehl die Schriftarten:

pnpm install @mathjax/mathjax-newcm-font@4

Wenn ich diesen Befehl in discourse/frontend/discourse ausführe, erscheinen die Schriftarten unter

/discourse/frontend/discourse/npm_modules/@mathjax/mathjax-newcm-font/chtml/woff2/

Diese Schriftarten scheinen jedoch nach dem Build nicht unter /assets/mathjax/woff-v2 zu landen. Ich habe eine Reihe von Variationen des Verzeichnisses ausprobiert, aber es hat nicht funktioniert. Ich gehe davon aus, dass dies eine Art Routing-Magie ist, von der ich kein Experte bin. Ich bin mir ziemlich sicher, dass ich gute Fortschritte bei der Bereinigung machen könnte, sobald dieses Pfadproblem geklärt ist.

1 „Gefällt mir“

@sam Ich glaube, ich habe hier ziemlich signifikante Fortschritte gemacht, allerdings mit einem wichtigen Vorbehalt. Ich bin mir nicht sicher, woher die gewünschten Komponenten geladen werden sollen. In Code ausgedrückt:

window.MathJax = {
    loader: {
      // Das funktioniert nicht:
      // paths: { mathjax: getURLWithCDN("/assets/mathjax") },
      // Aber das funktioniert einwandfrei:
      paths: { mathjax: "https://cdn.jsdelivr.net/npm/mathjax@4.1.0" },
      load: ["core", "input/tex", "input/mml", "output/chtml", "output/svg"],
    },
    // Weitere Konfiguration ...
  };

Wenn ich sage, dass die auskommentierte Version nicht funktioniert, meine ich, dass ich die explizite Meldung erhalte:
MathJax(core): Kann „/assets/mathjax/core.js“ nicht laden

Beachten Sie, dass in beiden Fällen die Funktion loadMathJax den MathJax-Start von der lokalen Kopie zieht. Das heißt, ich habe Folgendes in
/discourse/frontend/discourse/app/static/mathjax-bundle.js

export * from "mathjax/startup.js";

Dann ruft loadMathJax, definiert in
/discourse/frontend/discourse/app/lib/load-mathjax.js
auf:

const bundle = await import("discourse/static/mathjax-bundle");

Das deutet auf ein paar Möglichkeiten hin:

  1. Vielleicht ist /assets/mathjax nicht der richtige Ort oder
  2. Vielleicht müssen diese Assets auf irgendeine Weise registriert werden, damit sie im „dist“ erscheinen?

Wenn ich von der CDN-Version ausgehe, kann ich signifikante Fortschritte erzielen, aber ich nehme an, dass dies für Sie ein großes Hindernis darstellt.

Ich könnte meinen Code mit Ihnen teilen, wenn Sie möchten, aber vielleicht sind das genügend Informationen für eine Diagnose?

1 „Gefällt mir“

Absolut, Code wäre hier sehr hilfreich. Vielleicht forken Sie Discourse und pushen dann Ihre Änderungen in einen Branch, dann kann ich die Änderungen von Ihrem Branch in den PR übernehmen.

Ich freue mich sehr, dass Sie Fortschritte machen und versuchen, dieses Problem zu diagnostizieren.

Können Sie auch den neuesten Stand ziehen? Ich habe eine Runde Bereinigung durchgeführt.

1 „Gefällt mir“

OK, hier ist der Code:

Seien Sie jedoch gewarnt, ich habe nicht direkt von Ihrem letzten Commit aus gearbeitet. Ich habe direkt von Discourse main begonnen und von dort aus Änderungen vorgenommen. Daher habe ich viel von Ihrer Arbeit gelernt, aber die Gesamtstruktur ist anders.

Ich denke, Sie könnten den Hauptunterschied wie folgt zusammenfassen: Während Sie (natürlich) Discourse-Funktionen verwenden, die von Ember geerbt wurden, um die Zeitpunkte im Zusammenhang mit dem Laden und Setzen zu koordinieren, verwende ich MathJax-Funktionen. Daher sind meine load-mathjax und mathjax-Bundles (eines für SVG und eines für CHTML) viel einfacher als Ihre. Das Laden wird vollständig über das window.MathJax-Objekt in discourse-math-mathjax koordiniert.

Ich habe immer noch dasselbe Problem, das ich zuvor beschrieben habe, nämlich dass dieser auskommentierte Loader nicht funktioniert; ich muss stattdessen diese CDN-Version verwenden. Ich weiß wirklich nicht warum.

Ich denke, Ihr Code leidet unter demselben Problem. Deshalb scheint AsciiMath nicht zu funktionieren.

1 „Gefällt mir“

Können Sie meinen letzten Commit noch einmal überprüfen? Ich glaube, ich habe einen Funnel für Ember hinzugefügt, sodass der Ember-Build jetzt alle Dateien an die richtige Stelle legt.

2 „Gefällt mir“

OK, ich habe sehr gute Nachrichten und einige frustrierende Nachrichten.

Erstens, du hast absolut recht, dass das Hinzufügen des Funnels diese Dateien an die richtige Stelle legt. Ich habe den Funnel zu meinem Branch hinzugefügt und es funktioniert jetzt großartig ohne die CDN-Abhängigkeit. :tada:

Leider kann ich deinen Code im Moment nicht ausführen. Immer wenn ich zu einer Seite mit Mathematik navigiere, wird die Mathematik nicht gesetzt und ich sehe die folgende Fehlermeldung in der Konsole:
Uncaught (in promise) Error: State EXPLORER already exists

Ich bin mir sicher, dass dein Code vorher funktioniert hat, also nehme ich an, es liegt an etwas, das ich getan habe. Um es klarzustellen: Ich habe buchstäblich ein komplett neues Verzeichnis mit den in Install Discourse on macOS for development beschriebenen Techniken erstellt.

git clone https://github.com/discourse/discourse.git ./discourse
cd ./discourse
bundle install
pnpm install
bundle exec rake db:create
bundle exec rake db:migrate
RAILS_ENV=test bundle exec rake db:create db:migrate

# In einem Terminal
bundle exec rails server

# In einem anderen Terminal
bin/ember-cli

Dann habe ich deinen Code mit

git checkout 71ad0305f812311f2a4570edf7c33f97de46c457
git switch -c mathjax-sam

geholt. Selbst mit dieser frischen Einrichtung erhalte ich den Fehler.


An diesem Punkt bin ich mit meiner Version des Codes ziemlich zufrieden, aber immer noch neugierig, was bei deiner Version vor sich geht. Ich muss das für die Feiertage pausieren. Ich schaue aber gerne in ein paar Tagen noch einmal darauf.

Ein letzter Punkt noch: Soweit ich weiß,

await import("tex-mml-chtml.js") // gefolgt von
await import("input/asciimath.js")

sollte nicht funktionieren, was effektiv das ist, was dein Code tut, glaube ich.

Ich bin bei den Pfaden ungenau, aber mein Punkt ist, dass ich nicht weiß, ob aufeinanderfolgende dynamische Aufrufe von import zur korrekten MathJax-Struktur führen. Ich denke, das Laden von MathJax-Komponenten ist ziemlich kompliziert, und deshalb haben sie diesen detaillierten Ladevorgang mit dem MathJax-Objekt und allem.

Vielen Dank für deine Hilfe und Geduld @sam!

2 „Gefällt mir“

Ich habe hier Fortschritte gemacht:

Ich habe die riesigen JavaScript-Payloads in ein dediziertes Gem verschoben

Dies wird es erheblich einfacher machen, auf dem neuesten Stand zu bleiben, außerdem wird MathJax nicht mehr im Repository eingecheckt.

3 „Gefällt mir“

Hallo Sam – Ich habe heute eine ganze Menge damit herumgespielt. Es sieht großartig aus! Ich denke aber, es gibt noch eine ganze Menge zu tun. Bei manchen Dingen kann ich definitiv helfen. Manche Dinge liegen möglicherweise außerhalb meiner Möglichkeiten, insbesondere da die Universität wieder anfängt.

Jedenfalls hier ein paar meiner Gedanken.

Zoom

Zoom beim Darüberfahren ist in MathJax V4 nicht mehr verfügbar. Es ist jedoch einfach, es so einzustellen, dass es bei Alt-Klick zoomt. Das habe ich hier getan:

Beachten Sie, dass es einen bekannten MathJax-Fehler gibt, der mit etwas CSS behoben werden muss, wie in diesem GitHub-Issue beschrieben. Ich habe diese Korrektur ebenfalls in diesen Code aufgenommen.

Ladeoptionen

Derzeit kann AsciiMath nicht aktiviert und Barrierefreiheit nicht deaktiviert werden. Ich denke, das liegt daran, wie Untermodule in load-mathjax.js sequenziell geladen werden.

Wie ich in meiner letzten Nachricht erwähnt habe, ist es üblicher, ein window.MathJax-Objekt vorab zu definieren, das angibt, welche Komponenten Sie wünschen. Das MathJax-Objekt wird neu definiert, wenn das Hauptskript geladen wird. So konnte ich dies in meiner V3-Version zum Laufen bringen. Ich denke, ich könnte diesen Ansatz Anfang nächster Woche in Ihren Code einbauen, wenn Sie möchten, dass ich es versuche?

Sobald wir die Optionen geklärt haben, könnte es sich auch lohnen zu prüfen, ob es in V4 neue Optionen gibt, die einbezogen werden sollten.

Der Rich-Editor

Das ist einfach großartig – ich freue mich sehr, das zu sehen!

Ich frage mich, ob es möglich wäre, ein schickes KI-Kontextmenü innerhalb des Modals verfügbar zu machen? Ich frage, weil Studenten (und Professoren :confused:) manchmal Schwierigkeiten haben, LaTeX einzugeben. Ein kleiner KI-Korrektor kann das so viel reibungsloser gestalten. Ich habe das in meinem Klassenraum-Discourse integriert und freue mich darauf, es im kommenden Semester zu nutzen.


OK, ich bin sicher, da gibt es noch viel mehr, aber ich bin für heute fertig.

Vielen Dank!!! :rocket: :fire: :tada:

3 „Gefällt mir“

Ich verstehe, dass das discourse-math Plugin auf das separate MathJax/KaTeX Asset Gem angewiesen ist, anstatt diese Bibliotheken direkt einzubinden, was das Plugin schlank hält und es ermöglicht, die Mathematikbibliotheken unabhängig voneinander zu aktualisieren.

Ich möchte dies vor der ersten Produktionsfreigabe validieren, indem ich einige Tests in der Praxis durchführe. Mein erster Gedanke war, eine separate, temporäre Instanz aufzusetzen und das Plugin dort zu aktivieren, um inhaltsreiche mathematische Inhalte, das Laden von Assets über die Standard-Pipeline, das CSP-Verhalten und die Leistung zu testen.

Bevor ich dies tue, wollte ich fragen, welche Umgebung in dieser Phase empfohlen wird – ob frühe Tests in einer produktionsähnlichen Umgebung angemessen sind oder ob Sie bevorzugen, dass dies bis zur ersten Produktionsfreigabe in einer Entwicklungsumgebung durchgeführt wird.

Ich helfe sehr gerne beim Testen in der nützlichsten Weise und melde alle Probleme oder Randfälle, auf die ich stoße, nach oben. Aufgrund meiner universitären Verpflichtungen kann ich mich nicht auf einen festen Testzeitplan festlegen, aber ich bin bereit, nach besten Kräften zu testen, wenn es die Zeit erlaubt, und ich werde wahrscheinlich nach dem 6. Juni deutlich mehr Zeit haben.

Ich habe die Optionen jetzt gut zum Laufen gebracht; Sie können den Code hier einsehen:

Hier sind ein paar Anmerkungen:

  • Die gesamte Konfiguration und das Laden werden vom MathJaxInitConfig-Objekt gehandhabt, das in math-renderer.js definiert ist.
  • Ich habe eine ganze Menge inaktiven Code aus load-mathjax.js entfernt.
  • Die Erweiterung „ui/safe“ wird immer geladen.
  • Ich habe eine Option „Discourse math enable menu“ hinzugefügt, die standardmäßig auf „true“ gesetzt ist. Wenn sie auf „false“ gesetzt ist, wird das Menü vollständig entfernt, was MathJax noch schneller macht.
  • Die nächsten beiden Menüpunkte sind
    • „Discourse math zoom on click“ (Discourse-Mathematik-Zoom beim Klicken) und
    • „Discourse math enable accessibility“ (Discourse-Mathematik Barrierefreiheit aktivieren).
      Diese haben keine Auswirkung, wenn das Menü deaktiviert ist, sind aber voneinander unabhängig, wenn es aktiviert ist.

Das gesamte Menü sieht wie folgt aus:

Ich habe noch keine Tests hinzugefügt, könnte es aber versuchen, falls Sie einen Pull-Request wünschen.