Mise à niveau de Mathjax vers la version 4

@sam および Discourse で数式を入力することに関心のあるすべての方へ。discourse-math プラグインを更新し、はるかに遅く時代遅れの V2 ではなく MathJax V3 を使用するようにしました。ご想像の通り、KaTeX と比較して機能豊富な環境を維持しつつ、はるかに軽快なユーザーエクスペリエンスが得られました。

もし結果が良ければ、プルリクエストを発行したいと思います。


私のクラスの Discourse サイトで動作を確認できます。

そのサイトのコンテンツのほとんどは非公開または未掲載です。アイデアを示すために、MathJax V3 カテゴリのトップにいくつかのトピックがあるはずですが、

プラグインのコードはこのスタンドアロンの discourse-mathjax プラグインリポジトリで確認できます。最も多くの変更が加えられているファイルはinitializerです。

また、そのリポジトリを使用して、スタンドアロンサイトにすぐにインストールすることもできます。インストール時には、古いリポジトリを削除するようにしてください。したがって、標準のプラグインインストール手順を次のように変更する必要があります。

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

コメント

MathJax の最新バージョンは実際には 4.0.0 です。いくつかの理由で V3.2.2 を選択しました。

  • V4 は V2 よりも間違いなく高速ですが、V3 ほど高速ではありません。
  • V4 ではユーザーエクスペリエンスが少し異なり、特にユーザーが出力をクリックした場合に顕著です。
  • 4.0.0 というステータスは、バグがどれくらいあるのか疑問に思わせます。

とはいえ、V4 の API は V3 と同一です。後で最新の MathJax リポジトリをドロップインするだけでアップグレードできるはずです。

locales/server.en.yml ファイルで 1 つの小さな変更を加える必要がありました。もちろん、さまざまな言語に対応するファイルは他にもたくさんあります。私の理解では、これらの他のファイルは後で自動的に翻訳されるということでしょうか?

チャットはまったく利用しておらず、そのコンテキストではテストしていません。

4 « J'aime »

Pull request pour mettre à niveau MathJax vers la V3 effectuée avec tous les tests réussis !

2 « J'aime »

Concernant :

C’est fantastique :hugs: , mais je me demande si nous pouvons profiter de cette occasion pour alléger un peu notre dépôt.

Maintenant que nous avons déplacé MathJax dans le cœur, nous pouvons nous appuyer sur pnpm pour récupérer le paquet et éviter d’inclure toutes les sources comme nous le faisons pour FullCalendar par exemple.

L’objectif particulier est de n’avoir que des « liens » dans notre dépôt, et nous pourrons ensuite utiliser le processus de construction pour récupérer les dépendances correctes.

Donnez-nous quelques jours, je veux consulter l’équipe de l’expérience développeur ici. Merci beaucoup pour vos efforts !

4 « J'aime »

Oui, je pense que c’est certainement la bonne chose à faire. Je me suis toujours demandé pourquoi vous empaquetiez le tout !

Donc, je suppose que vous allez créer une fonction loadMathJax pour votre bibliothèque qui est utilisée pour charger MathJax ?

Je dois dire que regrouper tous les plugins dans le cœur a rendu un peu plus difficile de jouer avec eux. Lier les dépendances au processus de construction ne ferait que rendre les choses encore plus difficiles, bien que je sois sûr que je pourrais récupérer MathJax ou FullCalendar depuis un CDN.

Je parle surtout de lorsque je bricole avec des plugins pour les utiliser dans mes propres forums, et je pense absolument que vous devriez intégrer MathJax pendant la construction.

Absolument ! J’utilise Discourse depuis des années et je suis ravi que vous pensiez que c’est fantastique ! :rocket:

3 « J'aime »

Oui, exactement. Un bon exemple à copier est morphlex :

1 « J'aime »

Je me demande si vous avez pu en discuter avec vos collègues de l’expérience développeur ? Je serais heureux d’aider, si je le peux. Mon impression, cependant, est qu’il n’y a vraiment rien que je puisse faire sans vos commentaires à ce sujet.

J’ai apporté quelques changements supplémentaires dans une branche séparée, que je publierai bientôt. Je suis conscient que vous avez beaucoup de choses à faire, donc je ne veux pas vous déranger !

J’ai modifié le plugin discourse-math pour qu’il puisse analyser beaucoup plus d’entrées mathématiques.

@sam Quand j’ai contribué pour la première fois à ce plugin en 2017, je me souviens que vous étiez très ferme sur le fait de vouloir une analyse très stricte. Je tiens à dire d’emblée que ma principale motivation pour assouplir et étendre l’analyse était de le faire mieux fonctionner avec l’IA. En particulier, lorsque vous discutez de mathématiques avec un robot IA, vous constaterez souvent qu’il répond en utilisant LaTeX et qu’il existe de nombreuses façons dont il pourrait choisir de délimiter cette entrée LaTeX. Ainsi, bien que je comprenne votre motivation pour une analyse stricte, les modifications que j’ai apportées sont plutôt essentielles pour ce cas d’utilisation.

Bien sûr, ce cas d’utilisation pourrait toujours ne pas vous intéresser, j’ai donc placé les modifications dans une branche séparée de ma pull request V3. Si vous décidez qu’elles vous plaisent, je serai heureux de soumettre une autre pull request.

Les modifications spécifiques apportées à la pull request sont les suivantes :

Il accepte les maths en ligne délimitées par des parenthèses obliques comme \\(a^2+b^2=c^2\\).

Il accepte les maths en mode affichage délimitées par des doubles dollars sur une seule ligne comme
$$a^2+b^2=c^2.$$

Il accepte les maths en mode affichage délimitées par des crochets obliques sur une seule ligne comme
\\[a^2+b^2=c^2.\\]

Il accepte les maths en mode affichage délimitées par des crochets obliques sur plusieurs lignes comme
\\[
a^2+b^2=c^2.
\\]

Bien sûr, il accepte toujours les entrées de l'original :

Maths en ligne délimitées par des dollars : $a^2+b^2=c^2$.

Maths en mode affichage délimitées par des doubles dollars sur plusieurs lignes :
$$
a^2+b^2=c^2.
$$

Vous pouvez trouver la branche pertinente ici.

Le code existe également en tant que plugin autonome.

Oh, vous pouvez aussi le voir en action !

2 « J'aime »

@mcmcclur Merci pour votre travail. Ce serait formidable de voir ces fonctionnalités dans le cœur.

1 « J'aime »

Merci beaucoup Mark.

Mon principal obstacle ici est que je souhaite vraiment adopter les nouvelles méthodes de distribution des dépendances, voir :

Pourriez-vous examiner cela ?

Concernant la syntaxe assouplie, j’ai l’impression que c’est un paramètre de site, peut-être même activé par défaut étant donné tous les LLM disponibles ?

3 « J'aime »

@mcmcclur J’étais en train de jouer avec ceci aujourd’hui :

Loin d’être prêt… mais les choses démarrent un peu avec la 4.1, ce qui est bien.

2 « J'aime »

Oui, c’est certainement un progrès !
Le premier problème clé à résoudre, comme je le soupçonne, est que les polices ne sont pas trouvées. En fait, j’ai tripoté cette ligne dans discourse-math-mathjax.js :

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

À titre de test, j’ai configuré l’URL pour pointer simplement vers un répertoire temporaire sur mon propre serveur web, et les premiers résultats semblent très bons. C’est donc une question d’installation correcte de ces polices dans Discourse.
Dans un projet pnpm simple sur ma machine, la commande suivante installe les polices :

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

Lorsque j’exécute cette commande dans discourse/frontend/discourse, les polices apparaissent dans

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

Cependant, ces polices ne semblent pas arriver dans /assets/mathjax/woff-v2 après la compilation. J’ai essayé un certain nombre de variations du répertoire mais je n’ai pas réussi à le faire fonctionner. Je suppose que c’est une sorte de magie de routage dont je ne suis pas expert. Je suis presque sûr que je pourrais faire de bons progrès pour nettoyer cela une fois que ce problème de chemin sera réglé.

1 « J'aime »

@sam Je pense avoir fait des progrès assez significatifs là-dessus, avec une mise en garde importante. Je ne suis pas sûr d’où charger les composants souhaités. Exprimé en code,

window.MathJax = {
    loader: {
      // Ceci ne fonctionne pas :
      // paths: { mathjax: getURLWithCDN("/assets/mathjax") },
      // Mais ceci fonctionne très bien :
      paths: { mathjax: "https://cdn.jsdelivr.net/npm/mathjax@4.1.0" },
      load: ["core", "input/tex", "input/mml", "output/chtml", "output/svg"],
    },
    // Plus de configuration ...
  };

Quand je dis que la version commentée ne fonctionne pas, je veux dire que j’obtiens le message explicite :
MathJax(core): Impossible de charger « /assets/mathjax/core.js »

Notez que, dans les deux cas, la fonction loadMathJax récupère le démarrage de MathJax à partir de la copie locale. C’est-à-dire que j’ai ce qui suit dans
/discourse/frontend/discourse/app/static/mathjax-bundle.js

export * from "mathjax/startup.js";

Ensuite, loadMathJax défini dans
/discourse/frontend/discourse/app/lib/load-mathjax.js
appelle

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

Cela suggère quelques possibilités :

  1. Peut-être que /assets/mathjax n’est pas l’emplacement correct ou
  2. Peut-être que ces actifs doivent être enregistrés d’une manière ou d’une autre pour apparaître dans la distribution ?

En travaillant à partir de la version CDN, il semble que je puisse faire des progrès significatifs, mais je suppose que c’est un obstacle majeur pour vous.

Je peux partager mon code avec vous, si vous le souhaitez, mais peut-être que ces informations sont suffisantes pour un diagnostic ?

1 « J'aime »

Absolument, le code sera très utile ici, peut-être créer une fourche (fork) de Discourse et ensuite pousser vos modifications vers une branche, puis je pourrai récupérer les modifications de votre branche dans la PR.

Tellement heureux que vous progressiez, en essayant de diagnostiquer ce problème.

Pouvez-vous également récupérer les dernières modifications (pull latest), j’ai fait une série de nettoyages.

1 « J'aime »

OK, voici le code :

Attention cependant, je n’ai pas travaillé directement à partir de votre dernier commit. J’ai commencé directement à partir de Discourse main et j’ai fait des modifications à partir de là. Ainsi, j’ai beaucoup appris de votre travail mais la structure globale est différente.

Je pense que vous pourriez résumer la principale différence comme suit : Là où vous utilisez (naturellement) les fonctionnalités de Discourse héritées d’Ember pour coordonner les timings associés au chargement et à la composition, j’utilise les fonctionnalités de MathJax. Ainsi, mes bundles load-mathjax et mathjax (un pour svg et un pour chtml) sont beaucoup plus simples que les vôtres. Le chargement est entièrement coordonné via l’objet window.MathJax dans discourse-math-mathjax.

J’ai toujours le même problème que celui que j’ai décrit auparavant, à savoir que ce chargeur commenté ne fonctionne pas ; je dois utiliser cette version CDN à la place. Je ne sais vraiment pas pourquoi.

Je pense que votre code souffre du même problème. C’est pourquoi AsciiMath ne semble pas fonctionner.

1 « J'aime »

pouvez-vous vérifier ma dernière validation (commit), je pense avoir ajouté un entonnoir (funnel) pour ember, donc la construction (build) ember place maintenant tous les fichiers au bon endroit.

2 « J'aime »

OK, j’ai de très bonnes nouvelles et des nouvelles frustrantes.

Premièrement, vous avez absolument raison, l’ajout de l’entonnoir place ces fichiers au bon endroit. J’ai ajouté l’entonnoir à ma branche et cela fonctionne maintenant très bien sans la dépendance CDN. :tada:

Malheureusement, je suis incapable d’exécuter votre code pour le moment. Chaque fois que je navigue vers une page contenant des mathématiques, les mathématiques ne sont pas typographiées et je vois le message d’erreur suivant dans la console :
Uncaught (in promise) Error: State EXPLORER already exists

Je suis certain que votre code fonctionnait avant, donc je suppose que c’est quelque chose que j’ai fait. Pour être clair, j’ai littéralement commencé avec un répertoire entièrement neuf en utilisant les techniques décrites dans Install Discourse on macOS for development.

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

# Dans un terminal
bundle exec rails server

# Dans un autre terminal
bin/ember-cli

J’ai ensuite récupéré votre code avec

git checkout 71ad0305f812311f2a4570edf7c33f97de46c457
git switch -c mathjax-sam

Même à partir de cette nouvelle configuration, j’obtiens l’erreur.


À ce stade, je suis assez satisfait de ma version du code mais toujours curieux de ce qui se passe avec le vôtre. Je dois faire une pause là-dessus pour les vacances, cependant. Je serai ravi d’y jeter un autre coup d’œil dans quelques jours.

Un dernier point, cependant : pour autant que je sache,

await import("tex-mml-chtml.js") // suivi de
await import("input/asciimath.js")

ne devrait pas fonctionner, ce qui est effectivement ce que fait votre code, je crois.

Je suis imprécis avec les chemins là-bas, mais mon point est que je ne sais pas si des appels dynamiques consécutifs à import mènent à la structure MathJax correcte. Je pense que le chargement des composants MathJax est assez compliqué et c’est pourquoi ils ont un processus de chargement aussi détaillé avec l’objet MathJax et tout.

Merci beaucoup pour votre aide et votre patience @sam !

2 « J'aime »

J’ai fait des progrès ici :

J’ai déplacé les énormes charges utiles JavaScript dans une gemme dédiée

Cela facilitera grandement la mise à jour, et mathjax n’est plus intégré au dépôt.

3 « J'aime »

Salut Sam - J’ai beaucoup joué avec ça aujourd’hui. Ça a l’air super ! Je pense cependant qu’il reste encore beaucoup à faire. Je peux certainement aider pour une partie. Une autre partie est peut-être au-delà de mes capacités, surtout avec le début de mon université.

Quoi qu’il en soit, voici quelques-unes de mes réflexions.

Zoom

Le zoom au survol n’est plus disponible dans MathJax V4. Il est cependant facile de le configurer pour zoomer avec alt-clic. Je l’ai fait ici :

Notez qu’il y a un bug connu de MathJax qui doit être corrigé avec un peu de CSS, comme décrit dans ce problème GitHub. J’ai également inclus cette correction dans ce code.

Options de chargement

En l’état actuel, AsciiMath ne peut pas être activé et l’accessibilité ne peut pas être désactivée. Je pense que cela est dû à la façon dont les sous-modules sont chargés séquentiellement dans load-mathjax.js.

Comme je l’ai dit dans mon dernier message, il est beaucoup plus courant de pré-définir un objet window.MathJax qui spécifie les composants que vous souhaitez. L’objet MathJax est redéfini lorsque le script principal est chargé. C’est ainsi que j’ai réussi à faire fonctionner cela dans ma version V3. Pensez-vous que je pourrais intégrer cette approche dans votre base de code au cours de la première partie de la semaine prochaine, si vous voulez que j’essaie ?

Une fois que nous aurons réglé les options, il pourrait également être utile de considérer s’il existe de nouvelles options disponibles dans V4 qui devraient être incluses.

L’éditeur riche

C’est tout simplement génial - je suis super content de le voir !

Je me demande s’il serait possible d’avoir un menu contextuel IA étincelant disponible dans la modale ? Je demande cela parce que les étudiants (et les professeurs :confused:) ont parfois des difficultés à taper du LaTeX. Un petit correcteur IA peut rendre cela beaucoup plus fluide. Je l’ai intégré dans mon Discourse de classe et j’ai hâte de l’utiliser ce semestre à venir.


OK, je suis sûr qu’il y a beaucoup plus, mais j’ai terminé pour aujourd’hui.

Merci beaucoup !!! :rocket: :fire: :tada:

3 « J'aime »

Je comprends que le plugin discourse-math s’appuie sur le gem d’asset MathJax/KaTeX séparé plutôt que d’intégrer ces bibliothèques directement, ce qui maintient le plugin léger et permet aux bibliothèques mathématiques d’être mises à jour indépendamment.

J’aimerais aider à valider cela avant la première version de production en effectuant des tests concrets. Ma première idée était de lancer une instance séparée et jetable et d’y activer le plugin pour tester le contenu riche en mathématiques, le chargement des assets via le pipeline standard, le comportement de la CSP et les performances.

Avant de le faire, je voulais demander quel est l’environnement recommandé à ce stade : si des tests précoces dans une configuration proche de la production sont appropriés, ou si vous préférez que cela soit fait en utilisant un environnement de développement jusqu’à la première version de production.

Je suis tout à fait disposé à tester de la manière qui sera la plus utile et à signaler tout problème ou cas limite que je rencontre en amont. Je ne peux pas m’engager à un calendrier de test fixe en raison de mes engagements universitaires, mais je suis heureux de faire des tests au mieux de mes capacités lorsque le temps le permet, et je serai probablement beaucoup plus disponible après le 6 juin.

J’ai bien fait fonctionner les options maintenant ; vous pouvez voir le code ici :

Voici quelques commentaires :

  • Toute la configuration et le chargement sont gérés par l’objet MathJaxInitConfig défini dans math-renderer.js.
  • J’ai supprimé pas mal de code inerte de load-mathjax.js.
  • L’extension 'ui/safe' est toujours chargée.
  • J’ai ajouté une option « Menu d’activation des maths Discourse », qui est vraie par défaut. Lorsqu’elle est fausse, cela supprime entièrement le menu, ce qui rend MathJax encore plus rapide.
  • Les deux éléments de menu suivants sont
    • Zoom sur clic des maths Discourse et
    • Activation de l’accessibilité des maths Discourse.
      Ceux-ci n’ont aucun effet si le menu est désactivé, mais sont indépendants l’un de l’autre lorsqu’il est activé.

L’ensemble du menu ressemble à ceci :

Je n’ai pas encore ajouté de tests mais je peux essayer si vous souhaitez une pull request.