Перевірки
Зелена збірка ще не означає, що сторінки в порядку. Цей інструментарій ставить по одній перевірці на кожен шар, і кожна ловить свій клас тихих відмов «збірка зелена — сторінка зламана», а дві з них дивляться на сторінки так, як читач: у справжньому браузері.
§1П’ять заслон, п’ять шарів
| Перевірка | Постачається з | Дивиться на | Коли запускати |
|---|---|---|---|
| check-content | рушій, scripts/check-content.mjs | кожне джерело md/mdx | CI репозиторію вмісту або одразу після написання |
| 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, який узагалі не парситься, — обидва зі згадкою рядка у звіті.
§3check-wikilinks: граф посилань
Мертві [[вікіпосилання]] навмисно не валять збірку: сад мусить мати право посилатися на нотатки, які ще не виросли. Але гниття посилань усе одно має жити в CI, тож рушій постачає лінт, який розв’язує кожне вікіпосилання парсером і правилами самої бібліотеки (псевдонім, бренд, заголовок, мовні дзеркала) і звітує про відсутні цілі, неоднозначності та сумнівні якорі. --strict перетворює мертві посилання на ненульовий код виходу — саме так це запускає CI цього репозиторію:
node scripts/check-links.mjs§4check-dist: шар виводу
У зібраному dist/ кожне внутрішнє посилання, на яке читач може клацнути, мусить справді існувати. Перевірка ловить тихі провали під зеленою збіркою:
- внутрішні посилання й ресурси, що вказують на неіснуючі файли (після перекроювання маршрутів такі з’являються десятками);
- якорі в межах сторінки, що вказують на неіснуючі id;
- подвоєні мовні сегменти в шляхах (
/en/en/— класичний наслідок того, що i18n-фолбеки нашаровують префікс на вже префіксовані маршрути); <a>, вкладений в<a>(HTML-парсер закриває зовнішній передчасно, і кнопки випадають зі своїх карток);- рештки помилок KaTeX (формула стоїть на сторінці червоним текстом, а збірка тим часом зелена).
Це демо вмикає його у postbuild: зелений npm run build означає, що перевірка виводу теж пройшла.
node vendor/astro-inkbrush/scripts/check-dist.mjs dist --base ${DEMO_BASE:-/}§5Зонд шару рендерингу
Джерело й вивід можуть бути бездоганними, а сторінка — все одно зламаною; класичний випадок — картки головної, до яких не дотягується жодне правило стилів, тож вони рендеряться одним затиснутим рядком голого тексту: перевірки посилань і якорів лишаються зеленими, бо на відрендерену сторінку вони не дивляться взагалі. ui_probe проганяє справжній браузер по кожній сторінці dist на чотирьох ширинах вікна (1440/1024/768/430) і вимірює: горизонтальне переповнення сторінки, елементи ширші за контейнер без прокручуваної рамки, текст, який SVG малює поза власною рамкою, підписи ліній FlowDiagram, яких немає ні біля лінії, ні в легенді, підписи й номери поверх блока, заголовка чи одне одного, лінії крізь блок, який вони не з’єднують, чи крізь заголовок, класи, які не стилізує жодне правило, пропущені рівні заголовків, повторені id, зображення без атрибута alt, якорі в межах сторінки й aria-controls, що вказують у порожнечу. Він звітує лише те, що машина може довести, — без естетичних суджень.
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 елемента і предків, тож пригашений текст виміряно на тій силі, яку читач бачить насправді. Стани наведення й фокуса переглядають очима, а не зондом. Дрібний текст тримають на 4.5:1, великий (24px або 18.66px жирним) — на 3:1; фрагмент, чий колір не вдалося розібрати або чиє тло не вдалося зняти, рахується знахідкою. Звіт називає сторінку, тему, ширину, селектор, обидва кольори та коефіцієнт кожного фрагмента нижче планки:
node ../scripts/contrast_probe.mjs dist # PROBE_THEMES / PROBE_WIDTHS звужують матрицюui_probe і contrast_probe по виводу — все зелене до коміту. Демо водночас слугує пакетові випробувальним стендом.