Mathjaxをバージョン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

MathJaxをV3にアップグレードするためのプルリクエストが、すべてのテストに合格しました!

「いいね!」 2

Regarding:

これは素晴らしいですね :hugs: 。しかし、これを機会にリポジトリを少しスリム化できないかと思っています。

MathJaxをコアに移行したので、pnpmに依存してパッケージを取得し、例えばFullCalendarのようにすべてのソースをバンドルするのを避けることができます。

特に、リポジトリには「リンク」だけを持たせ、ビルドプロセスで正しい依存関係を取得できるようにすることを目指します。

数日いただければ、ここで開発エクスペリエンスチームと相談したいです。ご尽力に大変感謝します!

「いいね!」 4

はい、それは確かに正しいことだと思います。なぜ全体をパッケージ化していたのか、いつも不思議に思っていました!

それで、あなたのライブラリ用にMathJaxをロードするためのloadMathJax関数を構築するつもりですか?

すべてのプラグインをコアに統合したことで、それらをいじるのが少し難しくなったと言わざるを得ません。依存関係をビルドプロセスに結びつけると、さらに難しくなるでしょうが、MathJaxやFullCalendarをCDNから取得することはできると思います。

主に、自分のフォーラムで使用するプラグインをいじっている場合の話ですが、ビルド時にMathJaxを取得すべきだと強く思います。

もちろんです!私は何年もDiscourseを使用していて、あなたがこれを素晴らしいと思ってくれていることを非常に嬉しく思います!:rocket:

「いいね!」 3

はい、その通りです。良い例としてmorphlexがあります。

「いいね!」 1

開発者エクスペリエンスの担当者と話し合うことはできましたか?もし私がお手伝いできることがあれば喜んで協力させていただきます。ただし、あなたのフィードバックなしには私にできることは何もないという印象です。

別のブランチでいくつかの追加の変更を行いましたので、近いうちに投稿する予定です。あなたが非常に多忙であることは承知しておりますので、ご迷惑をおかけするつもりはありません!

discourse-math プラグインを変更し、より多くの数学的な入力を解析できるようにしました。

@sam 2017年にこのプラグインに初めて貢献したとき、あなたは非常に厳格な解析を望んでいたと記憶しています。まず最初に言っておきたいのは、解析を緩和し拡張した主な動機は、AIとの連携を改善するためだということです。特に、AIボットと数学についてチャットすると、ボットがLaTeXを使用して応答することがよくありますが、そのLaTeX入力を区切る方法はたくさんあります。したがって、厳格な解析の動機は理解していますが、私が加えた変更はそのユースケースにとって非常に重要です。

もちろん、あなたはまだそのユースケースを気にしないかもしれませんが、V3プルリクエストとは別のブランチに変更を入れました。もし気に入っていただけるようでしたら、別のプルリクエストを出すことも可能です。

プルリクエストに対する具体的な変更点は以下の通りです。

スラッシュ括弧で区切られたインライン数式、例えば \\(a^2+b^2=c^2\\) を受け付けます。

単一行の二重ドル記号で区切られたディスプレイ数式、例えば
$$a^2+b^2=c^2.$$
を受け付けます。

単一行のスラッシュ角括弧で区切られたディスプレイ数式、例えば
\\[a^2+b^2=c^2.\\]
を受け付けます。

複数行のスラッシュ角括弧で区切られたディスプレイ数式、例えば
\\[\na^2+b^2=c^2.\n\\]
を受け付けます。

もちろん、元の入力も引き続き受け付けます。

ドル記号で区切られたインライン数式: $a^2+b^2=c^2$.

複数行の二重ドル記号で区切られたディスプレイ数式:
$$\na^2+b^2=c^2.\n$$

関連するブランチはこちらで見つけることができます。

このコードはスタンドアロンのプラグインとしても存在します。

ああ、実際に動作している様子も見ることができます!

「いいね!」 2

@mcmcclur ご協力ありがとうございます。これらの機能をコアに組み込んでいただけると幸いです。

「いいね!」 1

マークさん、本当にありがとうございます。

私の大きな障害は、依存関係の配布に関する新しいパターンに移行したいことです。参照先はこちらです:

これを確認していただけますか?

構文の緩和については、サイト設定のように感じます。現在のLLMの状況を考えると、デフォルトでオンにするべきかもしれませんね。

「いいね!」 3

@mcmcclur 今日これをいじっていました:

まだ準備はできていませんが、4.1で何とか起動するのはいいですね。

「いいね!」 2

はい、これは間違いなく進歩です!

ご存知のように、最初に対処すべき重要な問題は、フォントが見つからないことです。実際、discourse-math-mathjax.js のこの行をいじってみました。

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

テストとして、URLを自分のウェブサーバー上のテンポラリディレクトリを指すように単純に変更したところ、最初の結果は非常に良好に見えました。したがって、問題はそれらのフォントをDiscourseに正しくインストールすることです。

私のマシン上の単純な pnpm プロジェクトでは、次のコマンドでフォントがインストールされます。

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

discourse/frontend/discourse 内でそのコマンドを実行すると、フォントは次の場所に表示されます。

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

しかし、ビルド後、それらのフォントは /assets/mathjax/woff-v2 には配置されないようです。ディレクトリのさまざまなバリエーションを試しましたが、うまくいきませんでした。これは、私が専門としていない何らかのルーティングの魔法だと思います。そのパスの問題が解決すれば、クリーンアップに向けて大きく前進できると確信しています。

「いいね!」 1

@sam これについてかなりの進展があったと思いますが、1つ大きな注意点があります。必要なコンポーネントをどこからロードすればよいのかわかりません。コードで表現すると、

window.MathJax = {
    loader: {
      // これは動作しません:
      // paths: { mathjax: getURLWithCDN("/assets/mathjax") },
      // しかし、これはうまく動作します:
      paths: { mathjax: "https://cdn.jsdelivr.net/npm/mathjax@4.1.0" },
      load: ["core", "input/tex", "input/mml", "output/chtml", "output/svg"],
    },
    // その他の設定 ...
  };

コメントアウトされたバージョンが動作しないというのは、明示的なメッセージ「MathJax(core): Can’t load “/assets/mathjax/core.js”」が表示されることを意味します。

どちらの場合も、loadMathJax 関数はローカルコピーから MathJax の起動を読み込んでいることに注意してください。つまり、/discourse/frontend/discourse/app/static/mathjax-bundle.js に以下があるということです。

export * from "mathjax/startup.js";

次に、/discourse/frontend/discourse/app/lib/load-mathjax.js で定義されている loadMathJax は以下を呼び出します。

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

これは、次のようないくつかの可能性を示唆しています。

  1. おそらく /assets/mathjax が正しい場所ではないか、または
  2. おそらく、これらのアセットを何らかの方法で登録して、dist に表示されるようにする必要があるか

CDN バージョンを基に作業すると、かなりの進展が見込めますが、それがあなたにとって大きな障害になると想定しています。

よろしければ私のコードを共有できますが、診断するにはこれで十分な情報でしょうか?

「いいね!」 1

もちろんです、コードがあれば非常に役立ちます。おそらくDiscourseをフォークして、変更をブランチにプッシュしてもらい、それから私があなたのブランチからPRに変更を取り込むことができます。

この問題の診断に取り組んでいて、進捗があったことを大変嬉しく思います。

最新版もプルしていただけますか?クリーンアップを行いました。

「いいね!」 1

OK、こちらがコードです。

ただし、最新のコミットから直接作業したわけではないことに注意してください。Discourseのメインから直接開始し、そこから変更を加えました。したがって、あなたの作業からかなりのことを学びましたが、全体的な構造は異なります。

主な違いは次のように要約できると思います。あなたが(当然ながら)読み込みや組版に関連するタイミングを調整するためにEmberから継承したDiscourseの機能を使用しているのに対し、私はMathJaxの機能を使用しています。そのため、私のload-mathjaxmathjaxバンドル(SVG用とchtml用)はあなたのものよりもはるかに単純です。読み込みはすべてdiscourse-math-mathjax内のwindow.MathJaxオブジェクトを介して調整されます。

以前説明したのと同じ問題がまだあります。つまり、このコメントアウトされたローダーが機能せず、代わりにこのCDNバージョンを使用しなければならないということです。なぜなのか本当にわかりません。

あなたのコードも同じ問題を抱えていると思います。それがAsciiMathが機能しない理由でしょう。

「いいね!」 1

最新のコミットを確認してもらえますか?Ember用のファネルを追加したので、Emberビルドがすべてのファイルを正しい場所に配置するはずだと思います。

「いいね!」 2

OK、非常に良いニュースと、少々厄介なニュースがあります。

まず、funnelを追加することで、それらのファイルが正しい場所に配置されるというのは、全くその通りです。私のブランチにfunnelを追加したところ、CDNへの依存なしで素晴らしい動作をするようになりました。 :tada:

残念ながら、現時点ではあなたのコードを実行することができません。数式のあるページに移動するたびに、数式が組版されず、コンソールに次のエラーメッセージが表示されます。
Uncaught (in promise) Error: State EXPLORER already exists

以前はあなたのコードが動作していたことは確かですので、何か私がしたことなのだろうと思います。はっきりさせておきますが、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

# 1つ目のターミナルで
bundle exec rails server

# 2つ目のターミナルで
bin/ember-cli

その後、次のようにあなたのコードを取得しました。

git checkout 71ad0305f812311f2a4570edf7c33f97de46c457
git switch -c mathjax-sam

そのクリーンなセットアップからでさえ、エラーが発生します。


この時点で、自分のバージョンのコードにはかなり満足していますが、あなたのコードで何が起こっているのかについてはまだ興味があります。しかし、休暇のためにこれからは休憩する必要があります。数日後にまた確認できれば幸いです。

最後に一点だけ:私の知る限りでは、

await import("tex-mml-chtml.js") // その後に
await import("input/asciimath.js")

は動作しないはずですが、これはあなたのコードがやっていることと実質的に同じだと私は思っています。

パスについては不正確かもしれませんが、私の言いたいのは、importへの連続した動的な呼び出しが正しいMathJax構造につながるかどうかはわからないということです。MathJaxコンポーネントの読み込みは非常に複雑で、だからこそMathJaxオブジェクトなどを使った非常に詳細な読み込みプロセスがあるのだと思います。

手伝ってくれて、そして辛抱強く付き合ってくれて本当にありがとう、@sam!

「いいね!」 2

こちらで進捗がありました。

巨大なJavaScriptペイロードを専用のgemに移動しました。

これにより、最新の状態を維持することが大幅に容易になり、また、mathjaxがリポジトリにチェックインされなくなります。

「いいね!」 3

サムさん、こんにちは。今日はこれをかなり試してみました。素晴らしい出来栄えですね!ただし、まだやるべきことはかなりあると思います。そのうちのいくつかは、特に大学が再開するので、私の能力を超えるかもしれませんが、手伝えることは間違いなくあります。

とにかく、いくつか思いついたことを挙げます。

ズーム

MathJax V4では、ホバー時のズームは利用できなくなりました。ただし、altキーを押しながらクリックするとズームするように設定するのは簡単です。私はここでその設定を行いました。

少しCSSで対処する必要がある既知のMathJaxのバグがあることに注意してください。これはこのGitHub Issueで説明されています。私もその修正をこのコードに含めました。

ロードオプション

現状では、AsciiMathをオンにして、アクセシビリティをオフにすることができません。これは、load-mathjax.jsでサブモジュールが順番にロードされる方法によるものだと思います。

前回のメッセージで述べたように、どのコンポーネントが必要かを指定するwindow.MathJaxオブジェクトを事前に定義する方がはるかに一般的です。MathJaxオブジェクトは、メインスクリプトがロードされるときに再定義されます。これが、私のV3バージョンでこれを機能させることができた方法です。よろしければ、来週前半にあなたのコードベースにそのアプローチを組み込むことができると思いますか?

オプションが解決したら、V4で利用可能で含めるべき新しいオプションがあるかどうかを検討する価値があるかもしれません。

リッチエディタ

これは素晴らしいです。これを見られてとても嬉しいです!

モーダル内でキラキラしたAIコンテキストメニューを利用することは可能でしょうか?学生(そして教授も :confused:)がLaTeXの入力に苦労することがあるため、尋ねています。ちょっとしたAI校正ツールがあれば、それがずっとスムーズになります。私は自分の教室のDiscourseにそれを組み込んでおり、この次の学期に使うのを楽しみにしています。


さて、もっとたくさんあると思いますが、今日はこれで終わりにします。

本当にありがとうございます!!! :rocket: :fire: :tada:

「いいね!」 3

discourse-math プラグインは、プラグイン自体に MathJax/KaTeX ライブラリをバンドルするのではなく、個別の MathJax/KaTeX アセット gem に依存していると理解しています。これにより、プラグインを軽量に保ち、数学ライブラリを独立して更新できるようになります。

最初の本番リリースに先立ち、実環境でのテストを行うことでこれを検証したいと考えています。私の最初の考えは、分離可能で使い捨てのインスタンスを立ち上げ、そこでプラグインを有効にして、数式を多用するコンテンツ、標準パイプライン経由でのアセットの読み込み、CSP の動作、およびパフォーマンスをテストすることでした。

そうする前に、現段階で推奨される環境についてお尋ねしたかったのですが、本番環境に似たセットアップでの早期テストが適切なのか、それとも最初の本番リリースまで開発環境を使用してテストを行うことをご希望でしょうか。

最も役立つ方法でテストを行い、遭遇した問題やエッジケースを上流(upstream)に報告することに非常に前向きです。大学での予定があるため、固定されたテストスケジュールを約束することはできませんが、時間が許す限りベストエフォートでテストを行うつもりです。6月6日以降は、より多くの時間が取れる可能性が高いです。

オプションはうまく動作するようになりました。コードはこちらで確認できます。

いくつかのコメントです。

  • すべての設定と読み込みは、math-renderer.js で定義されている MathJaxInitConfig オブジェクトによって処理されます。
  • load-mathjax.js から不要なコードをかなり削除しました。
  • 「ui/safe」拡張機能は常に読み込まれます。
  • 「Discourse math enable menu」オプションを追加しました。これはデフォルトで true に設定されています。false にするとメニュー全体が削除され、MathJax がさらに高速になります。
  • 次の 2 つのメニュー項目は
    • Discourse math zoom on click (クリックで拡大) および
    • Discourse math enable accessibility (アクセシビリティを有効にする) です。
      これらはメニューが無効になっている場合は効果がありませんが、有効になっている場合は互いに独立しています。

メニュー全体は次のようになります。

まだテストは追加していませんが、プルリクエストをご希望でしたら試すことは可能です。