Kontrole
Zielony build nie znaczy, że strony są w porządku. Ten zestaw narzędzi stawia po jednej kontroli na każdej warstwie; każda łapie klasę cichych awarii „build zielony, strona zepsuta” — a dwie z nich patrzą na strony tak, jak patrzy czytelnik: w prawdziwej przeglądarce.
§1Pięć bram, pięć warstw
| Kontrola | Pochodzi z | Patrzy na | Kiedy uruchamiać |
|---|---|---|---|
| check-content | silnik, scripts/check-content.mjs | każdy plik źródłowy md/mdx | CI repozytorium treści albo po pisaniu |
| check-wikilinks | silnik, scripts/check-wikilinks.mjs | graf [[wikilinków]] | CI repozytorium treści albo po zmianie nazwy notatki |
| check-dist | silnik, scripts/check-dist.mjs | wynik astro build | po każdym buildzie (postbuild) |
| ui_probe | ten pakiet, scripts/ui_probe.mjs | strony wyrenderowane w prawdziwej przeglądarce | po zmianach stylów i layoutu |
| contrast_probe | ten pakiet, scripts/contrast_probe.mjs | kontrast każdego węzła tekstu, oba motywy | po każdej zmianie tokenów |
§2check-content: warstwa źródeł
Kompiluje każdy plik md/mdx zmierzający na stronę dokładnie tym samym dialektem co witryna — błędy składni i ciche zniekształcenia (znaki wyróżnień bez pary, klamry połknięte przez wyliczanie MDX, znaczniki list zrodzone z zawijania wierszy, jednoliniowe $$, wzory nie do wyrenderowania przez KaTeX — ten sam zestaw, którym zamyka się Wszystko naraz) wszystkie zapalają CI na czerwono.
Dlaczego ten skrypt musi pochodzić z silnika: walidator, którego zestaw wtyczek różni się od zestawu witryny, jest gorszy niż brak walidatora — bez wtyczki matematycznej odczytuje klamry wzorów jako wyrażenia JSX, a bez GFM przepuszcza tabele bez słowa. Dialekt jest napisany raz, w silniku; renderowanie witryny, walidacja zapisu w CMS i ten skrypt konsumują zawsze ten sam.
node <silnik>/scripts/check-content.mjs . --glob '**/index.{md,mdx}' --mathPoza kompilacją łapie dwie frontmatterowe klasy cichej utraty danych: niecytowany # w wartości (YAML czyta go jako komentarz i po cichu ucina resztę) oraz YAML, który w ogóle się nie parsuje, raportowany z numerem linii.
§3check-wikilinks: graf linków
Martwe [[wikilinki]] celowo nie wywracają builda — ogrodowi wolno linkować do notatek, które jeszcze nie wyrosły. Gnicie linków należy jednak do CI, więc silnik dostarcza lint, który rozwiązuje każdy wikilink parserem i regułami rozwiązywania samej biblioteki (alias, brand, tytuł, lustrzane wersje językowe) i raportuje brakujące, wieloznaczne oraz podejrzane kotwice. --strict zamienia martwe linki w niezerowy kod wyjścia — tak uruchamia go CI tego repozytorium:
node scripts/check-links.mjs§4check-dist: warstwa wyniku
W zbudowanym dist/ każde wewnętrzne odwołanie, które czytelnik może kliknąć, musi naprawdę istnieć. Ta kontrola łapie ciche dziury pod zielonym buildem:
- wewnętrzne linki i zasoby wskazujące na nieistniejące pliki (ten gatunek, który po przemeblowaniu tras pojawia się tuzinami);
- kotwice w obrębie strony wskazujące na nieistniejące id;
- zdublowane segmenty języka w ścieżkach (
/en/en/— klasyczny owoc i18n-owych fallbacków doklejających prefiks do tras już oprefiksowanych); <a>zagnieżdżone w<a>(parser HTML domyka zewnętrzny przedwcześnie i przyciski wypadają z kart);- resztki błędów KaTeX-a (wzór jest na stronie czerwonym tekstem, a build pozostaje zielony).
To demo wpina ją w postbuild: zielone npm run build znaczy, że kontrola wyniku też przeszła.
node vendor/astro-inkbrush/scripts/check-dist.mjs dist --base ${DEMO_BASE:-/}§5Sonda warstwy renderowania
Źródło i wynik mogą być oba w porządku, a strona wciąż zepsuta — klasyczny przypadek to karty strony głównej, do których nie pasuje żadna reguła arkusza stylów i które renderują się jako jedna stłoczona linia gołego tekstu: kontrole linków i kotwic pozostają zielone, bo nigdy nie patrzą na wyrenderowaną stronę. ui_probe przejeżdża prawdziwą przeglądarką po każdej stronie w dist w czterech szerokościach okna (1440/1024/768/430) i mierzy: poziomy przelew strony, elementy szersze niż ich kontener bez pudełka przewijania, w którym mogłyby mieszkać, tekst, który SVG rysuje poza własnym polem, etykiety linii FlowDiagram, których nie ma ani przy linii, ani w legendzie, etykiety i numery leżące na ramce, nagłówku albo na sobie nawzajem, linie przecinające ramkę, której nie łączą, albo nagłówek, klasy, których nie styluje żadna reguła arkusza, przeskoczone poziomy nagłówków, zdublowane id, obrazy bez atrybutu alt, kotwice w obrębie strony i aria-controls wskazujące donikąd. Raportuje tylko to, co maszyna umie udowodnić — bez sądów estetycznych.
npm run build
node ../scripts/ui_probe.mjs dist # sam serwuje dist; przekaż baseUrl, by sondować działający serwerOgląda cały dokument — chrome, sidebar i dialogi włącznie.
Zielono jest wtedy, gdy ostatnia linia raportu brzmi SAMPLES WITH FINDINGS: 0
(próbka to jedna trasa w jednej szerokości).
§6Sonda kontrastu
Tokeny deklarują AA, więc deklarację się mierzy, a nie powtarza na wiarę. contrast_probe ładuje każdą stronę dist w prawdziwej przeglądarce — motyw jasny i ciemny, szerokość biurkowa i telefoniczna — i mierzy każdy przebieg tekstu wyrenderowany w stanie domyślnym: tekst HTML, tekst SVG i tekst generowany przez ::before / ::after, przy czym każda nakładka <dialog data-probe-open> jest sondowana otwarta (a w znalezionym tam polu wyszukiwania wpisywane jest zapytanie) na stronie reprezentatywnej — ten znacznik to deklaracja witryny, że dialog jest kompletny w takiej formie, w jakiej go napisano. Podłoża nie czyta się z arkusza stylów; strona jest renderowana z każdym glifem uczynionym przezroczystym, zrzucana do obrazu, a piksel pod każdym przebiegiem jest jego podłożem — więc gradienty, tinty color-mix(), półprzezroczyste warstwy i paleta nocna są mierzone tak, jak się renderują. Kolor przebiegu niesie skumulowane opacity elementu i przodków, więc przygaszony tekst jest mierzony w sile, w jakiej naprawdę widzi go czytelnik. Stany hover i focus są przeglądane okiem, nie sondowane. Drobny tekst trzymany jest na 4,5:1, duży (24px albo 18,66px pogrubiony) na 3:1; przebieg, którego koloru nie da się sparsować albo którego podłoża nie da się spróbkować, liczy się jako znalezisko. Raport wymienia stronę, motyw, szerokość, selektor, oba kolory i współczynnik każdego przebiegu poniżej poprzeczki:
node ../scripts/contrast_probe.mjs dist # PROBE_THEMES / PROBE_WIDTHS zawężają macierzui_probe i contrast_probe nad wynikiem — wszystko zielone przed commitem. Demo jest zarazem poligonem testowym pakietu.