Как не надо строить документацию: история одного парсера HTML
· 3 min read
Мы сели писать собственный движок документации от безысходности. Изначально никто не планировал разрабатывать масштабный UDE. У нас была простая утилитарная задача — задокументировать свежую обёртку на Python. Как обычно, самые монструозные костыли начинаются с безобидных скриптов на пару строк.
Внезапный Python
Наш основной SDK написан на C++. Чтобы им можно было пользоваться из других языков, создаются обертки. Дошла очередь до Python. Разработчики выдали готовый API, который теперь нужно было публиковать на портале документации.
Мы давно сидели на Doc-o-Matic. Старый, тяжелый, проверенный временем генератор. Одно плохо: код на Python он категорически не понимал. Программа годами не обновлялась, техподдержка давно умерла, поэтому рассчитывать на патчи не приходилось. У нас есть жесткие корпоративные требования к дизайну портала. Ни один из стандартных генераторов им не соответствовал, а задокументировать код было необходимо.
Мы посмотрели в сторону Doxygen. Утилита вытаскивает структуру из чего угодно. Правда стандартный HTML на выходе выглядит как привет из девяностых. Тут-то нам в голову и пришла гениальная мысль.
«Мы просто немного причешем стили»
«Doxygen генерирует готовые страницы. Давайте натравим скрипт, подменим пару CSS, и всё будет готово за пару дней».

Оказалось, мы катастрофически недооценили масштаб проблемы. План был прост: перехватить выдачу, подсунуть в свою структуру и пойти пить кофе. Но чем глубже мы лезли в сгенерированный DOM, тем хуже становилось. Doxygen абсолютно игнорировал современные подходы к верстке (вместо понятных тегов мы разгребали завалы таблиц и инлайн-стилей).
Отступать было поздно. Прототип требовался уже вчера, поэтому пришлось стиснуть зубы и дописывать скрипт. Постепенно он обрастал десятками регулярных выражений, становясь всё более хрупким.
Боковое меню и JS-некромантия
Самое дикое началось на этапе навигации. У нас в компании строгое правило UI: абсолютно все страницы должны лежать в левом боковом меню (чтобы разработчик видел всю картину). Doxygen с этим подходом не согласен. Он строит меню динамически из глубоко вложенных массивов, размазанных по нескольким сгенерированным файлам JavaScript.
Нам с ИИ пришлось физически вычитывать эти JS-файлы как обычный текст. Мы парсили массивы, вытаскивали оттуда иерархию классов и руками перестраивали HTML-дерево страницы. Это уже походило на цифровую некромантию.
Семь раз отмерь, один раз распарси
Прототип в итоге завелся. Снаружи всё выглядело прилично и по стандартам. Но внутри же наш скрипт представлял собой карточный домик на изоленте. Выходит минорный апдейт Doxygen — и весь портал рассыпается с ошибками.

Мы потратили уйму времени на попытку срезать угол. Вместо этого можно было спокойно продумать нормальную архитектуру и реализовать ее. Нам стоило сразу вытаскивать абстрактное синтаксическое дерево, или хотя бы просто парсить чистый XML от Doxygen.
Стало очевидно: нужен свой независимый движок. Мы снова подключили ИИ, чтобы он по-быстрому накидал нормальный парсер для чтения XML от Doxygen. Но и тут всё пошло не так. О том, что бывает, когда оставляешь ИИ без присмотра, расскажу в следующей части.