mcmcclur
(Mark McClure)
1
@sam 以及所有对在 Discourse 中输入数学内容感兴趣的人。我已经更新了 discourse-math 插件,使其使用 MathJax V3,而不是速度慢得多且非常过时的 V2。正如预期的那样,结果是用户体验更加灵敏,同时与 KaTeX 相比仍保持功能丰富的环境。
如果结果看起来不错,我很乐意提交一个拉取请求(pull request)。
您可以在我的课堂 Discourse 网站上看到它的实际效果:
该网站上的大多数内容都是私密或未列出的。在顶部的 MathJax V3 类别中应该有几个主题来说明这些想法,不过
您可以在这个独立的 discourse-mathjax 插件仓库中检查插件的代码。修改最多的文件是初始化文件。
您也可以立即使用该仓库将其安装在独立站点上。只需确保在安装过程中删除旧的仓库。因此,您需要修改标准的插件安装技术使其如下所示:
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 的 API 相同。稍后可以通过简单地放入最新的 MathJax 仓库来升级。
我不得不在 locales/server.en.yml 文件中进行了一个小的更改。当然,对于各种语言还有很多这样的文件。我的理解是,那些其他文件稍后会自动翻译?
我完全不使用聊天,也没有在那种情况下进行测试。
4 个赞
mcmcclur
(Mark McClure)
2
升级 MathJax 到 V3 的拉取请求已提交,所有测试均已通过!
2 个赞
sam
(Sam Saffron)
3
关于:
这太棒了
,但我不知道我们是否可以借此机会精简一下我们的仓库。
既然我们已经将 mathjax 移至核心,我们可以依赖 pnpm 来拉取包,并避免像对 FullCalendar 那样打包所有源代码。
特别是,目标是我们的仓库中只保留“链接”,然后我们可以使用构建过程来拉取正确的依赖项。
请给我们几天时间,我想在这里与开发体验 (dev xp) 团队咨询一下。非常感谢您的努力!
4 个赞
mcmcclur
(Mark McClure)
5
是的,我认为这绝对是正确的做法。我一直很奇怪你为什么要打包整个东西!
那么,我猜你会为你的库构建一个 loadMathJax 函数来加载 MathJax 吧?
我要说的是,将所有插件都集成到核心中使得摆弄它们变得更加棘手。将依赖项与构建过程绑定只会让情况更糟,尽管我确信我可以从 CDN 拉取 MathJax 或 FullCalendar。
我主要说的是当我为我自己的论坛修补插件时,我绝对认为你应该在构建过程中拉入 MathJax。
当然!我使用 Discourse 已经很多年了,很高兴你认为这很棒!
3 个赞
david
(David Taylor)
6
是的,完全正确。一个好的参考是 morphlex:
1 个赞
mcmcclur
(Mark McClure)
7
我想知道您是否已经和您的开发体验人员讨论过了?如果我能帮上忙,我很乐意提供帮助。不过,我的印象是,如果没有您那边的反馈,我确实无能为力。
我已经在另一个分支中做了一些额外的更改,我很快就会发布相关信息。我明白您手头有很多事情要做,我无意打扰!
mcmcclur
(Mark McClure)
8
我对 discourse-math 插件进行了修改,使其能够解析更多的数学输入。
@sam 我记得 2017 年我第一次向该插件贡献代码时,您非常坚持希望解析非常严格。我首先要说明的是,我放宽和扩展解析的主要动机是使其能更好地与人工智能(AI)配合使用。特别是,当您与 AI 机器人讨论数学问题时,您会发现它经常使用 LaTeX 回复,并且它可能会选择多种方式来分隔该 LaTeX 输入。因此,虽然我理解您对严格解析的动机,但我所做的更改对于该用例来说是相当必要的。
当然,您可能仍然不关心该用例,所以我将更改放在了我的 V3 拉取请求(pull request)的一个单独分支中。如果您决定喜欢这些更改,我很乐意再提交一个拉取请求。
对拉取请求的具体更改如下:
它接受斜杠-括号分隔的行内数学公式,例如 \\(a^2+b^2=c^2\\)。
它接受单行双美元符号分隔的显示数学公式,例如
$$a^2+b^2=c^2.$$
它接受单行斜杠-方括号分隔的显示数学公式,例如
\\[a^2+b^2=c^2.\\]
它接受多行斜杠-方括号分隔的显示数学公式,例如
\\[
a^2+b^2=c^2.
\\]
当然,它仍然接受原始版本的输入:
美元符号分隔的行内数学公式:$a^2+b^2=c^2$。
多行、双美元符号分隔的显示数学公式:
$$
a^2+b^2=c^2.
$$
您可以在此处找到相关的分支。
该代码也作为一个独立插件存在。
哦,您还可以在此处看到它的实际效果!
2 个赞
ozkn
(Mathx)
9
@mcmcclur 感谢您的工作。很高兴能在核心中看到这些功能。
1 个赞
sam
(Sam Saffron)
10
非常感谢马克。
我目前最大的阻碍是,我真的很想采用新的依赖项分发模式,参见:
您能看一下这个问题吗?
关于宽松的语法,我觉得这应该是一个站点设置,鉴于目前所有的大型语言模型(LLM)的普及,甚至可以默认开启?
3 个赞
sam
(Sam Saffron)
11
@mcmcclur 我今天摆弄了一下这个:
远未准备好……但东西在 4.1 上可以启动了,这很好。
2 个赞
mcmcclur
(Mark McClure)
12
是的,这绝对是进步!
我要解决的第一个关键问题是找不到字体,我怀疑您也知道。事实上,我摆弄了 discourse-math-mathjax.js 中的这一行:
fontURL: getURLWithCDN("/assets/mathjax/woff-v2"),
作为测试,我将 URL 设置为仅指向我自己的 Web 服务器上的一个临时目录,初步结果看起来非常好。所以,问题在于如何将这些字体正确地安装到 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 个赞
mcmcclur
(Mark McClure)
13
@sam 我认为我在这个问题上取得了相当大的进展,但有一个重要的注意事项。我不确定应该从哪里加载所需的组件。用代码表示如下:
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): 无法加载 “/assets/mathjax/core.js”
请注意,在这两种情况下,loadMathJax 函数都是从本地副本中获取 MathJax 启动代码的。也就是说,我在以下位置有以下内容:
/discourse/frontend/discourse/app/static/mathjax-bundle.js
export * from "mathjax/startup.js";
然后,在以下位置定义的 loadMathJax:
/discourse/frontend/discourse/app/lib/load-mathjax.js
调用
const bundle = await import("discourse/static/mathjax-bundle");
这暗示了几个可能性:
- 也许
/assets/mathjax 不是正确的位置,或者
- 也许需要以某种方式注册这些资产,以便它们出现在分发目录中?
基于 CDN 版本,我似乎可以取得重大进展,但我假设这对你来说是一个主要的障碍。
如果你愿意,我可以与你分享我的代码,但这是否提供了足够的信息来进行诊断?
1 个赞
sam
(Sam Saffron)
14
当然,代码在这里会非常有帮助,也许可以 fork discourse 然后将你的更改推送到一个分支,这样我就可以从你的分支拉取更改到 PR 中。
很高兴看到你取得了进展,正在努力诊断这个问题。
你也能拉取最新的代码吗,我做了一轮清理。
1 个赞
mcmcclur
(Mark McClure)
15
好的,这是代码:
不过请注意,我不是直接从你的最新提交开始的。我是直接从 Discourse 主分支开始并在其上进行更改的。因此,我从你的工作中学习了不少,但整体结构有所不同。
我认为你可以将主要区别总结如下:你在协调与加载和排版相关的时间安排方面(很自然地)使用了从 Ember 继承的 Discourse 功能,而我使用了 MathJax 的功能。因此,我的 load-mathjax 和 mathjax 捆绑包(一个用于 svg,一个用于 chtml)比你的要简单得多。加载完全是通过 discourse-math-mathjax 中的 window.MathJax 对象协调的。
我仍然存在我之前描述的同一个问题,即 这个被注释掉的加载器 不起作用;我必须使用 这个 CDN 版本 才能工作。我真的不知道为什么。
我认为你的代码也存在同样的问题。这就是 AsciiMath 似乎不起作用的原因。
1 个赞
sam
(Sam Saffron)
16
你能检查一下我最新的提交吗?我想我为 Ember 添加了一个漏斗(funnel),所以 Ember 构建现在会将所有文件放在正确的位置。
2 个赞
mcmcclur
(Mark McClure)
17
好的,我有一个非常好的消息和一个令人沮丧的消息。
首先,你说得完全正确,添加 funnel 将这些文件放在了正确的位置。我在我的分支中添加了 funnel,现在它在没有 CDN 依赖的情况下运行得非常好。
不幸的是,我目前无法运行你的代码。每当我导航到包含数学内容的页面时,数学内容都不会被排版,并且我在控制台中看到了以下错误消息:
Uncaught (in promise) Error: State EXPLORER already exists
我确信我之前让你的代码可以工作,所以我想这可能是我做错了什么。但话说清楚,我确实是使用在 macOS 上为开发安装 Discourse 中描述的技术,从一个全新的目录开始的。
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
# 在一个终端中
bundle exec rails server
# 在另一个终端中
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 个赞
sam
(Sam Saffron)
18
我在这里取得了一些进展:
我已将大型 JavaScript 有效载荷移至一个专用的 gem 中
这将使保持最新状态变得更加容易,而且 mathjax 不再提交到仓库中。
3 个赞
mcmcclur
(Mark McClure)
19
嗨,Sam——我今天花了很多时间研究这个。它看起来很棒!但我确实认为还有很多工作要做。其中一些我肯定可以帮忙。有些可能超出了我的能力范围,尤其是我大学快要开学了。
无论如何,以下是我的一些想法。
缩放 (Zoom)
MathJax V4 不再支持悬停缩放。不过,很容易将其设置为按住 Alt 键单击时缩放。我已经在以下位置进行了设置:
请注意,有一个已知的 MathJax 错误需要通过一些 CSS 来解决,如此 GitHub Issue 中所述。我也已将该修复包含在此代码中。
加载选项 (Loading options)
目前,AsciiMath 无法打开,而可访问性 (Accessibility) 无法关闭。我认为这是因为 load-mathjax.js 中子模块是按顺序加载的。
正如我在上一条消息中所说,更常见的是预先定义一个 window.MathJax 对象,其中指定了你想要的组件。MathJax 对象在主脚本加载时会被重新定义。这就是我能够在我的 V3 版本中实现此功能的方式。如果你愿意,我想我可以在下周初将该方法整合到你的代码库中,试试看?
一旦我们确定了选项,也值得考虑 V4 中是否有应该包含的新选项。
富文本编辑器 (The rich editor)
这太棒了——我很高兴看到它!
我想知道是否可以在模态框内获得一个闪亮的 AI 上下文菜单?我这样问是因为学生(和教授
)有时在输入 LaTeX 时会遇到困难。一个小的 AI 校对工具可以让这个过程顺畅得多。我已经将它集成到我的课堂 Discourse 中,并期待着在即将到来的学期中使用它。
好的,我确信还有很多,但我今天就到此为止了。
非常感谢!!!

4 个赞
Ethsim2
(Ethan )
20
我理解 discourse-math 插件依赖于单独的 MathJax/KaTeX 资源 gem,而不是直接捆绑这些库,这使插件保持轻量级,并允许数学库独立更新。
我想通过进行一些实际测试来帮助在首次生产发布之前验证这一点。我的初步想法是启动一个单独的、一次性的实例并在那里启用该插件,以测试大量数学内容、通过标准管道进行的资源加载、内容安全策略 (CSP) 行为和性能。
在这样做之前,我想询问一下现阶段推荐的环境是什么——是在类似生产的设置中进行早期测试是否合适,还是您更希望在首次生产发布之前使用开发环境进行测试。
我非常乐意以最有用的方式进行测试,并向上游报告我遇到的任何问题或边缘情况。由于大学事务,我无法承诺固定的测试时间表,但我乐意在时间允许的情况下尽力进行测试,并且我可能在 6 月 6 日之后有更多的时间。
mcmcclur
(Mark McClure)
21
我的选项现在运行良好;你可以在这里看到代码:
这里有几点评论:
- 所有配置和加载都由
math-renderer.js 中定义的 MathJaxInitConfig 对象处理。
- 我从
load-mathjax.js 中移除了相当多的无效代码。
ui/safe 扩展总是被加载。
- 我添加了一个“Discourse 数学启用菜单”选项,默认值为 true。当设置为 false 时,它会完全移除菜单,使 MathJax 速度更快。
- 接下来的两个菜单项是
- 点击时放大 Discourse 数学公式
- 启用 Discourse 数学辅助功能
如果菜单被禁用,这些将不起作用,但在启用时它们是相互独立的。
整个菜单如下所示:
我还没有添加任何测试,但如果你想要一个拉取请求(pull request),我可以尝试添加。