HimeraSearchDB
Carding_EbayThief
triada
CrackerTuch
JustinSun

НОВОСТИ Конвертируем TeX в SVG: опенсорс-решение в помощь образовательным проектам

NewsBot
Оффлайн

NewsBot

.
.
Регистрация
21.07.20
Сообщения
40.408
Реакции
1
Репутация
0
5496d871b662cea721f6dc654d015154.png


Привет! Меня зовут Костя Мамаев, я занимаюсь фронтенд-разработкой в поиске Яндекса. Некоторое время назад мы вместе с другими ребятами из команды помогали образовательным проектам компании. Среди прочего пришлось решить, казалось бы, простую задачку: отображать на экране и распечатывать на бумаге формулы, закодированные в популярном формате TeX. Звучит, как дело пяти минут, но в результате трёх подходов к снаряду появился полноценный микросервис для серверного рендеринга формул в svg и png. В статье расскажу, зачем мы пошли этим путём и почему ни один из существующих проектов не подошёл «из коробки».

Результаты нашей работы могут быть полезны и другим разработчикам, помогающим школьникам и учителям, поэтому готовый микросервис ждёт вас на гитхабе Яндекса. По весь джентльменский набор: Docker-контейнер, документация, открытый код.


В математических, физических и химических задачах (например, в материалах для подготовки к ЕГЭ и ОГЭ) много формул. Мы хотели, чтобы работать с ними было удобно. Качество отображения должно быть высоким, а формат — универсальным: мог выразить любую формулу, был простым в хранении и понятным за пределами Яндекса. Ещё важно, чтобы формулы выглядели одинаково и не «ехали» на разных экранах, а их обработка не перегружала CPU и расходовала энергию экономично — это особенно актуально для мобильных устройств.

Подход первый: фронтендерский. KaTeX


Показывать сырую TeX-разметку опрометчиво — вряд ли её сможет прочесть пользователь без кандидатской степени, поэтому сначала нужно её приготовить. Первое решение, которое приходит на ум — конвертировать на стороне клиента, будь то что-то встроенное или библиотека для рендеринга TeX.

Немногие вспомнят, что в браузерах уже есть поддержка математических формул — . Но, как показало беглое исследование, формат давно забыт и пользователями, и . Пришлось двигаться дальше. Оказалось, выбор инструментов не так уж велик: монструозный, но всеядный и расширяемый или относительно молодой и быстрый . Как говорится, из двух зол — выбирай меньшее. Решили попробовать KaTeX.

Плюсы:


  • Realtime-отрисовка формул. Пользователь пишет формулу и сразу видит, что будет на выходе.


  • Формирование разметки на клиентской стороне — не нужно ничего хранить.

Минусы:


  • Каким бы легковесным ни был KaTeX по сравнению MathJaX, он всё равно оставался слишком большим по стандартам Яндекса.


  • Артефакты realtime-генерации: мигание на странице и долгий рендеринг, особенно на мобильных устройствах.


  • Проблемы при печати (о них поговорим чуть позже).


  • KaTeX отдаёт html-разметку, так что скопировать формулу как формулу не получится.


  • Двойная работа при использовании SSR. Сначала генерируем html на сервере, а потом на клиенте.
Подход второй: браузерный. Puppeteer


Результат, полученный с KaTeX, не устроил — хотелось избавиться от недостатков первой реализации. Пришла идея сделать всё на сервере без realtime-генерации формул. В этом случае можно выбрать более мощную библиотеку — MathJaX. Она умеет «из коробки» превращать TeX в разметку, MathML и svg. Здорово, не правда ли? Оставалось написать обвязку в виде сервера, парочки web-хуков для добавления заданий на обработку и сложить всё в s3. Это оказалось не так просто. Возникли проблемы с печатью:


  • выяснилось, что svg не копируется через ctrl+c ctrl+v в Microsoft Word,


  • ломалось выравнивание формул в тексте.

Мы много общались с учителями, репетиторами, готовящими школьников к ЕГЭ и ОГЭ, и преподавателями вузов. Большинство из них распечатывает на бумаге материалы к занятиям. Это подтверждали интервью, проведённые коллегами: все респонденты-репетиторы рассказывали, что печатают задания для учеников. Значит, закрывать глаза на эти проблемы нельзя.

Здесь пригодился . Мы добавили конвертацию из svg в png, чтобы реализовать копирование в Word. А это, стоит заметить, один из самых востребованных сценариев среди преподавателей. Но, как только появился браузер, сервис стал тормозить: генерация одной формулы занимала секунды, а пересоздание всех формул (у нас их было 110 469) — дни или даже недели.

Подход третий: серверный. MathJax, sharp и немного смекалки


Чтобы получить решение, которое работает быстро, не нагружает даже слабенькие устройства и даёт приемлемое качество изображения, оставалось решить две проблемы:


  • ускорить генерацию png,


  • починить выравнивание формул.

Первая проблема решалась просто, хотя пришлось перепробовать множество вариантов, чтобы получить нужный результат. Puppeteer был безжалостно выпилен, а вместо него — добавлена маленькая и быстрая библиотека . Да, решение породило внешнюю зависимость, но сервис запускается в Docker-контейнере, так что это было приемлемо. Скорость генерации заметно выросла.

А вот с «поехавшими» формулами в тексте пришлось побороться. Было предположение, что выравнивание по центру или базовой линии поможет, но оно работало хорошо только для однострочных или идеально симметричных формул. MathJax сам генерирует правильные отступы в svg-файлах (правда, в , но это не беда), но для оптимизации отрисовки выносит одинаковые символы в defs. Они конфликтуют между вставленными svg, и выглядит это, будто сломалась головка струйного принтера. Дополнительный минус — раздутая разметка и невозможность повторного использования одинаковых svg на странице. Обращение к png выглядело жестом отчаяния: проблемы примерно те же, а качество графики хуже.

Решение оказалось достаточно простым:


  1. генерируем svg-файл,


  2. получаем из него атрибуты со стилями (это же обычный xml, не так ли?),


  3. удаляем атрибуты,


  4. генерируем png из svg,


  5. сохраняем в метаинформации файла данные о стилях, нужных для корректного отображения картинки.

Готово!

Результаты и выводы


Теперь формулы копируются, масштабируются, лениво загружаются, идеально выровнены, а CPU пользователя не нагревается до состояния сковородки. Удалось добиться скоростных улучшений. Размер десктопных и тачевых бандлов уменьшился на 64.5кб (37%).

Обработка страницы варианта ЕГЭ, на которой нужно было отрендерить 94 формулы:


  • с использованием Katex: 7594 ms


  • без Katex: 6584 ms


  • финальный вариант: 1010 ms

Эта же страница, но на слабом CPU и с медленным 3G:


  • с использованием Katex: 40229 ms


  • без Katex: 37524 ms


  • финальный вариант: 2705 ms
Чему я научился?


  • Даже самая тривиальная задача может оказаться сложнее, чем представлялось вначале.


  • Svg не копируется через буфер обмена.


  • Конвертировать svg в png с помощью браузера — это долго.


  • Не стоит забывать о метаинформации.

Надеюсь, этот проект принесёт пользу и другим разработчикам, помогающим школьникам, студентам и учителям. Если вы один из них — встретимся на .
 
Сверху Снизу