Да, я думаю, что резюме Сэма точное: если мы хотим, чтобы в письмах и печатных версиях отображалась отрендеренная математика, нам необходим серверный рендеринг формул (или хотя бы серверное «предварительное рендерирование»), поскольку почтовые клиенты не запускают MathJax.
Реалистичный подход был бы следующим:
- Во время обработки (или в фоновой задаче после неё) найти все теги с математикой (строчные и блочные).
- Отрендерить каждое выражение в SVG (или MathML в качестве запасного варианта), используя MathJax в среде Node.
- Заменить математику в обработанном HTML, используемом для электронной почты и печати, на:
- встроенный тег
<svg ...>(наилучшее качество, отсутствие внешних запросов), или <img src="data:image/svg+xml;base64,...">(более совместимо с некоторыми клиентами, но может занимать много места).
- встроенный тег
- Кэшировать результат по стабильному ключу (например,
sha256(latex + display_mode + macros + font_config)), чтобы рендерить каждую уникальную формулу только один раз.
Сложные моменты (но управляемые при тщательном планировании):
- Эмуляция DOM: вывод MathJax для «браузера» требует наличия DOM; поэтому, скорее всего, потребуется
mathjax-full+jsdom(или использование чистого адаптера). - Производительность и таймауты: выполнять асинхронно через очередь задач и предусмотреть плавное ухудшение (оставлять LaTeX без изменений, если рендеринг не удался).
- Особенности почтовых клиентов: некоторые клиенты блокируют SVG; поэтому важно иметь план на случай неудачи (например, простой текст/LaTeX или MathML там, где он поддерживается).
Если кто-то хочет быстро провести эксперимент, первое, что я бы попробовал:
- Написать крошечный скрипт на Node с использованием
mathjax-fullдля рендеринга$begin:math:text$E\=mc\^2$end:math:text$в SVG, - Проверить, какие допущения он делает (DOM или адаптер),
- Затем решить, является ли MiniRacer тупиковым вариантом, и нужно ли нам требовать наличия Node (или создать небольшой сервис).
Если эксперимент увенчается успехом, мы обсудим, куда именно это интегрировать (пайплайн писем, обработка или печатная версия), и что будем кэшировать/хранить.