Справочник API, которому можно верить

Таблица props, написанная руками, неверна через месяц. Вот что нужно, чтобы вывести её из кода, — и четыре вещи, которые ломаются после этого.

Таблица props, написанная руками, неверна через месяц, и хуже всего то, что об этом никто не узнаёт. На неверную фразу в прозе заводят баг. На пропавший проп в таблице не заводят ничего: читатель решает, что пропа нет, обходит его стороной и никому об обходе не рассказывает.

Значит, таблицу надо выводить. Это очевидно, и на этом обычно останавливаются, решив четверть задачи. Вот как выглядели остальные три четверти на каталоге из 108 компонентов из 8 пакетов.

Вывести — простая часть

vue-component-meta читает компонент и отдаёт props, слоты, события и методы с типами, значениями по умолчанию и JSDoc. Задача решённая, и первая версия порождённой таблицы делается за вечер.

Интересное решение — где запускается генератор. Запустить его на сайте документации кажется естественным и неверно: ему нужен весь тулчейн библиотеки, он работает минуты и — вот что важно — даёт результат, который может отличаться от опубликованного самой библиотекой. Правило, которое из этого выросло, стоит украсть:

Порождённое порождается один раз тем, кому оно принадлежит. Остальные читают артефакт.

Библиотека кладёт componentApi.generated.json в релиз. Портал его читает и никогда не пересчитывает. Потребитель, пересчитывающий чужие данные, тихо завёл второй источник правды.

Поломка первая: таблица честная и бесполезная

Первые порождённые таблицы были верны и нечитаемы, потому что показывали всё, что вернул инструмент. Пустые секции — «Events: 0», «Methods: 0» — появлялись у каждого компонента, у которого их нет.

Пустая секция не нейтральна. Она сообщает об отсутствии там, где читатель ищет присутствие, и делает это 108 раз. Секции без содержимого теперь не выводятся вовсе, и страница от этого стала короче и правдивее.

Поломка вторая: описание не на том языке

Эта специфична для проекта и общая по форме. Комментарии JSDoc в библиотеке написаны по-русски — правило репозитория, и для внутреннего объяснения разумное. Но vue-component-meta не отличает «внутренний комментарий» от «публичной документации». Он просто извлекает.

Результат: английская страница компонента показывала русскую таблицу props. 862 описания из 865 — больше половины всего, что на странице вообще написано.

Есть правильная починка и возможная. Правильная — английский JSDoc в самой библиотеке: он чинит заодно подсказки IDE, web-types и MCP-сервер, читающие те же комментарии. Она меняет правило репозитория, и это решение не сайта документации.

Возможная — та, что поехала: таблица перевода с ключом компонент.раздел.имя, где рядом с английским текстом лежит русский оригинал. Оригинал там не из сентиментальности — он и есть отпечаток. Изменилось описание в библиотеке — сохранённый оригинал перестал совпадать, и сборка падает с точным ключом. Без него устаревший перевод неотличим от свежего.

Поломка третья: гейт, проверяющий сам себя

Очевидный гейт сверяет таблицу перевода с библиотекой. Соблазнительное сокращение — собрать ожидаемый набор из того же модуля, который читает страница, — не доказывает ровно ничего: обе стороны приходят из одного места.

Правило, которое выжило: гейт читает источник независимо. Он обходит сам артефакт API и пересобирает ожидаемый набор ключей, а от таблицы требует четырёх вещей: строка есть, оригинал не уехал, перевод не пуст, кириллицы в английской колонке нет. Плюс обратное направление: строка, описания которой в библиотеке больше нет, — тоже ошибка, потому что таблица, пережившая свой предмет, выглядит поддерживаемой.

Второй гейт читает собранные страницы, а не исходники, и ищет чужой язык в оболочке. Он намеренно несимметричен: на русской странице ищется связка из трёх английских слов, потому что отдельные английские слова в техническом тексте законны везде; на английской — любая кириллица, потому что кириллица в английской прозе не бывает законной никогда.

Поломка четвёртая: playground и таблица разошлись

Таблица API и интерактивный playground строились из одних данных и разойтись не могли — пока не приехал перевод и локализована оказалась только таблица. Одну сборку страница компонента показывала английские описания в таблице и русские в контролах playground.

Починка структурная, а не внимательная: страница разрешает API один раз, на языке страницы, и всё, что ниже, — таблица, playground, Markdown-версия для агентов — берёт готовое. Два языка в двух местах одной страницы читаются не как перевод в процессе. Они читаются как сломанная страница.

Во что это обходится

Четыре гейта и одна таблица. Купленное этим уже, чем «правильная документация», и стоит сформулировать точно: таблица props не может молча разойтись с пакетом, который читатель ставит. Она может быть неполной, может быть плохо сформулирована, а проза вокруг неё может устареть. Она не может врать про API.

Это обещание меньше, чем даёт большинство документаций, и, в отличие от них, его можно проверить на каждом коммите.

Компоненты в статье