СправочникИнструментыРастётобновлено 2026.084 мин чтения
Справочник · инструменты

Проверки

Зелёная сборка ещё не значит, что со страницами всё в порядке. Этот набор инструментов ставит по одной проверке на каждый слой — каждая ловит свой класс тихих поломок вида «сборка зелёная, страница сломана», — и две из них смотрят на страницы так, как смотрит читатель: в настоящем браузере.

пять проверок · три от движка, две из этого пакета · всё зелёное до коммита

§1Пять рубежей — пять слоёв

ПроверкаЕдет сСмотрит наКогда запускать
check-contentдвижок, scripts/check-content.mjsкаждый исходный md/mdxCI репозитория контента, или после письма
check-wikilinksдвижок, scripts/check-wikilinks.mjsграф [[вики-ссылок]]CI репозитория контента, или после переименования заметки
check-distдвижок, scripts/check-dist.mjsвывод astro buildпосле каждой сборки (postbuild)
ui_probeэтот пакет, scripts/ui_probe.mjsстраницы, отрисованные в настоящем браузерепосле правок стилей и макета
contrast_probeэтот пакет, scripts/contrast_probe.mjsконтраст каждого текстового узла, обе темыпосле любой правки токенов

§2check-content: слой исходников

Компилирует каждый md/mdx, которому предстоит стать страницей, ровно тем же диалектом, что и сайт, — синтаксические ошибки и тихие деформации (непарные маркеры выделения, скобки, проглоченные вычислением MDX, маркеры списков, рождённые переносом строки, однострочный $$, формулы, которые KaTeX не осилит, — тот самый список, которым закрывается «Всё и сразу») окрашивают CI в красный.

Почему этот скрипт обязан приходить из движка: проверка, чей набор плагинов отличается от сайтового, хуже, чем никакой проверки — без плагина математики она читает скобки формул как выражения JSX, без GFM пропускает таблицы. Диалект написан в движке однажды; отрисовка сайта, валидация сохранений CMS и этот скрипт потребляют один и тот же — всегда.

корень репозитория контента
node <engine>/scripts/check-content.mjs . --glob '**/index.{md,mdx}' --math

Помимо компиляции он ловит два класса тихих потерь во frontmatter: неэкранированный # в значении (YAML считает его комментарием и молча отрезает хвост) и YAML, который вовсе не парсится, — с указанием строки.

Мёртвые [[вики-ссылки]] нарочно не роняют сборку: саду положено ссылаться на заметки, которые ещё не выросли. Но гнили ссылок место в CI, поэтому движок поставляет линт, который разрешает каждую вики-ссылку парсером и правилами разрешения самой библиотеки (псевдоним, брендовое имя, заголовок, локальные зеркала) и докладывает о пропавших целях, неоднозначностях и сомнительных якорях. --strict превращает мёртвые ссылки в ненулевой код выхода — именно так его запускает CI этого репозитория:

проверка ссылок этого сада — так её запускает CI
node scripts/check-links.mjs

§4check-dist: слой сборки

В собранном dist/ каждая внутренняя ссылка, по которой читатель может щёлкнуть, обязана существовать. Проверка ловит тихие дыры под зелёной сборкой:

  • внутренние ссылки и ассеты, указывающие на несуществующие файлы (после перекройки маршрутов такие появляются дюжинами);
  • внутристраничные якоря, указывающие на несуществующие id;
  • удвоенные сегменты локали в путях (/en/en/ — классический результат i18n-фолбэков, наслаивающих префикс на уже префиксованные маршруты);
  • <a>, вложенный в <a> (HTML-парсер рано закрывает внешний, и кнопки вываливаются из карточек);
  • осадок ошибок KaTeX (формула стоит на странице красным текстом, а сборка остаётся зелёной).

Это демо включает его в postbuild: зелёный npm run build означает, что проверка вывода тоже пройдена.

корень сайта, после сборки (--base — если сайт живёт на подпути)
node vendor/astro-inkbrush/scripts/check-dist.mjs dist --base ${DEMO_BASE:-/}

§5Зонд слоя отрисовки

Исходники и вывод могут быть правы одновременно, а страница всё равно сломана; классика жанра — карточки главной, до которых не дотягивается ни одно правило стилей и которые отрисовываются одной сплющенной строкой голого текста: проверки ссылок и якорей остаются зелёными, ведь на отрисованную страницу они не смотрят вовсе. ui_probe прогоняет настоящий браузер по каждой странице dist на четырёх ширинах вьюпорта (1440/1024/768/430) и меряет: горизонтальное переполнение страницы, элементы шире контейнера без скролл-бокса, где им жить, классы, которые не стилизует ни одно правило, пропущенные уровни заголовков, повторяющиеся id, изображения без атрибута alt, внутристраничные якоря и aria-controls, указывающие в пустоту. Он докладывает только то, что машина может доказать, — без эстетических суждений.

нужен локальный Chrome/Chromium
npm run build
node ../scripts/ui_probe.mjs dist   # сам раздаёт dist; передайте baseUrl, чтобы проверить живой сервер

Он осматривает документ целиком — вместе с обвязкой, сайдбаром и диалогами. Зелёный итог — это когда последняя строка отчёта гласит SAMPLES WITH FINDINGS: 0 (замер — один маршрут на одной ширине).

§6Зонд контраста

Токены заявляют AA — значит, заявление измеряется, а не постулируется. contrast_probe открывает каждую страницу dist в настоящем браузере — светлая и тёмная тема, десктопная и телефонная ширина — и меряет каждый текстовый фрагмент, отрисованный в состоянии по умолчанию: текст HTML, текст SVG и генерируемый текст ::before / ::after; каждый оверлей <dialog data-probe-open> прощупывается открытым (а в найденное там поле поиска вводится запрос) на представительной странице — этот маркер и есть заявление сайта, что диалог в авторском виде полон. Фон не вычитывается из таблицы стилей: страница отрисовывается со всеми глифами, сделанными прозрачными, снимается скриншот, и пиксель под фрагментом — его фон; так градиенты, примеси color-mix(), полупрозрачные слои и ночная палитра меряются такими, какими они рендерятся. Передний план фрагмента несёт накопленную opacity элемента и его предков — приглушённый текст меряется той силой, какой его действительно видит читатель. Состояния hover и focus рецензируются глазами, не зондом. Мелкий текст держит планку 4.5:1, крупный (24px, или 18.66px жирным) — 3:1; фрагмент, чей цвет не разобрать или чей фон не снять, сам считается находкой. Отчёт называет страницу, тему, ширину, селектор, оба цвета и коэффициент каждого фрагмента, не добравшего до планки:

после сборки, обе темы
node ../scripts/contrast_probe.mjs dist   # PROBE_THEMES / PROBE_WIDTHS сужают матрицу

Порядок при смене стилей
Любое изменение таблиц стилей или компонентов пакета сперва проходит через сборку этого демо, затем через ui_probe и contrast_probe по её выводу — всё зелёное до коммита. Демо по совместительству — испытательный стенд пакета.

Заголовки, разделы и текст заметок — на этом языке.
    ↑↓ · Enter · Escastro-inkstone