Gå til innholdet

Kommandolinjen

Pakken har en kommandolinje med sju kommandoer. Den har ingen avhengigheter, og du trenger ikke installere noe ekstra:

Terminal window
npx @fristil/designsystem <kommando>

Står pakken i package.json, heter kommandoen fristil, så npx fristil sjekk og et skript med fristil sjekk gjør det samme. npx @fristil/designsystem uten kommando, eller med --hjelp, viser hele oversikten.

KommandoGjør
sjekksjekker markup mot Fristil, i filer, fra standard inn eller fra en adresse
agentskriver regelboka for kodeagenter for miljøet ditt
overtakopierer kildekoden til én komponent inn i prosjektet
temalager et fargetema av merkefargene dine
sjekk-temakontrollerer at et tema holder kontrastkravene
manifestskriver manifestet sjekken bruker, med fragmentene fra overta
lspspråkserveren for editorer, se Editoren

Kommandoene er skrevet én gang, i Rust, og bygget som en WebAssembly-modul for WASI. npx kjører den med Node, men den samme modulen kjører også uten, og svarer det samme, byte for byte. Velg det som allerede finnes på maskinen:

Har duKjør
Java 17 eller nyerejava -jar fristil.jar sjekk skjema.html
wasmtimewasmtime run --dir=. --env FRISTIL_PACKAGE=package fristil.wasm sjekk skjema.html
Rustcargo install --git https://github.com/MarkusAugust/fristil fristil, og så fristil sjekk skjema.html

fristil.jar og fristil.wasm ligger ved hver utgivelse på GitHub, med samme versjon som npm-pakken. Ingen av dem er signert med et sertifikat. GitHub attesterer i stedet hvilken commit og hvilken arbeidsflyt hver fil ble bygd av, og det kan du kontrollere selv:

Terminal window
gh attestation verify fristil.jar --repo MarkusAugust/fristil

Jar-en har alt i seg og trenger ingen avhengigheter. Den kjørbare fila og fristil.wasm har ingen data: de leser manifestet, fargekontrakten, regelbøkene og komponentene fra @fristil/designsystem i node_modules, eller fra mappa FRISTIL_PACKAGE peker på. Uten Node henter du pakken fra npm-registeret og pakker den ut, så ligger den i package/:

Terminal window
curl -sL https://registry.npmjs.org/@fristil/designsystem/-/designsystem-0.35.0.tgz | tar xz
FRISTIL_PACKAGE=package fristil sjekk skjema.html

Bytt ut versjonen med den du vil sjekke mot. Uten pakken stopper kommandoen og sier hva den mangler.

En adresse hentes av verten, siden WASI ikke har nettverk. npx og java -jar henter både http:// og https://. Den kjørbare fila fra cargo install henter http://, som er det en lokal server svarer på. For https:// fra cargo install sender du siden inn selv: curl -s https://… | fristil sjekk --rendret.

wasmtime er med for den som har det fra før, eller ikke har Node, Java eller Rust. Det er den svakeste av vertene, og det bør du vite før du velger den:

  • Du må stole på en tredjepart. wasmtime installeres fra wasmtime.dev, utenfor npm, Maven og cargo, og er laget av Bytecode Alliance, ikke av Fristil.
  • Ingen adresser. wasmtime har ikke nettverk, og ingen vert henter siden for modulen. fristil sjekk http://… sier at den ikke fikk kontakt. Send siden inn selv: curl -s http://localhost:8080/skjema | wasmtime run --dir=. --env FRISTIL_PACKAGE=package fristil.wasm sjekk --rendret.
  • Bare mappene du åpner. wasmtime ser bare det du gir den med --dir. Med --dir=. virker stier under arbeidsmappa, og en fil utenfor gir «Fant ikke fila», selv om den finnes. Pakken må også ligge under en mappe du åpner, og FRISTIL_PACKAGE gis med --env, siden wasmtime ikke gir modulen miljøet ditt. Språkserveren trenger --dir=/::/, som gir den hele filsystemet.
  • Ingen beskjed om standard inn. De andre vertene sier «Leser markup fra standard inn» når du kjører sjekk uten filer i en terminal. wasmtime kan ikke se det, så kommandoen venter stille til du avslutter med Ctrl-D.
  • Windows er ikke prøvd. De andre vertene oversetter C:\… til det modulen forstår. I wasmtime må du åpne stasjonen selv med --dir.
  • Ikke prøvd i CI. npx, java -jar og den kjørbare fila prøves på hver endring, med de samme kjøringene. wasmtime er prøvd for hånd.

sjekk er den samme kontrollen som editoren kjører mens du skriver. Den kjenner hver klasse, hvert element, hvert attributt og hver lovlige verdi i pakken du har installert.

Terminal window
npx @fristil/designsystem sjekk maler/*.html
npx @fristil/designsystem sjekk http://localhost:8080/skjema
curl -s http://localhost:8080/skjema | npx @fristil/designsystem sjekk --rendret

Den leser tre slags inndata:

  • filer, oppgitt som argumenter;
  • standard inn, når ingen filer er oppgitt;
  • en adresse som begynner med http:// eller https://. Den hentes av kommandolinja, se Uten Node. En side som svarer noe annet enn 2xx, eller med noe annet enn HTML, gir feilkode i stedet for å bli sjekket.

Hvert funn skrives som en kompilator skriver det, med fil, linje og kolonne:

skjema.html:4:27: advarsel: data-variant kan ikke være «outline» på button. Lovlige verdier: secondary, ghost, danger, og primary uten attributt.
skjema.html:5:13: advarsel: Klassen «fs-modal» finnes ikke i Fristil.
2 funn i 1 fil.
FlaggBetydning
--rendretsjekk filer og standard inn som hele sider, med koblingen
--css=<fil>sjekk også at stilarkene styler markupen. Se Med stilarkene
--manifest=<fil>sjekk også en komponent du har tatt over. Se overta

Exit-koden er 0 når det ikke er noen funn, og 1 ellers, også når alle funnene er advarsler. En advarsel i en mal er en feil ingen kompilator ser. Tom standard inn, filer som alle er tomme, en fil som ikke finnes, og en adresse som ikke svarer eller svarer med en tom side, gir også 1. Én tom fil blant flere, som en tom partial i et glob, er ikke en feil.

En mal er ofte delt i biter. En ledetekst kan stå i én fil og feltet i en annen, og malsyntaks som {{ }}, {% %}, <?= ?>, @variabel og <%= %> står der verdien kommer senere. Uten flagg sjekker sjekk derfor bare det som kan avgjøres i én fil: elementer, klasser, attributter, verdier, at hvert <fs-field> har en ledetekst, og at en del som skal stå én gang, ikke står flere ganger. Et <fs-field> med to kontroller kobler bare den første, og en fs-table med to <caption> får navnet sitt fra den første. Hvilke deler det gjelder, står i manifestet som unique. Andre deler kan stå flere ganger, som knappene i panelet til <fs-popover>. Står det malsyntaks i komponenten, også v-if eller et uttrykk i {…}, sier regelen ingenting, siden et vilkår kan gi to deler i malen og én på siden.

En side slik serveren sender den, er hel. Da kan sjekk også kreve at koblingen stemmer:

  • hver id i for, aria-describedby, aria-labelledby og aria-controls finnes på siden, og for peker på et felt eller en knapp;
  • ingen id står mer enn én gang;
  • hvert felt med en fs--klasse har en ledetekst: en <label for>, en <label> rundt, aria-label eller aria-labelledby;
  • hver synlige hjelpetekst og feilmelding er pekt på fra aria-describedby. En tekst er ikke synlig når den selv eller en forelder har hidden, eller står i en lukket <dialog> eller <details>. Et statusfelt, med role="status", role="alert" eller aria-live, leses opp av seg selv og trenger ingen kobling;
  • hver lenke i <fs-error-summary> går til en id som finnes.

En adresse sjekkes alltid slik. Filer og standard inn sjekkes slik med --rendret. Bar markup inni <fs-field> gir ingen funn, siden web-komponenten setter koblingen i nettleseren. Det samme gjelder et felt inni <fs-suggestion>. En id som er skrevet og peker feil, meldes uansett hvor den står.

To ting leses ikke som en del av siden. Innholdet i en <template> er ikke i dokumentet, og i en shadow root, <template shadowrootmode>, har id-ene sitt eget rom. Markup som står i en attributtverdi, som et kodeeksempel bak en kopieringsknapp, eller inni en <textarea>, er tekst. Ingen av dem sjekkes.

http://localhost:8080/skjema:12:30: feil: for="epost" peker på id-en «epost», som ikke finnes på siden. Skjermleseren mister ledeteksten. Skriv for på ledeteksten og id på feltet i malen, eller legg ledeteksten rundt feltet. Lages markupen med JavaScript, gjør fs.field({ id }) det.

Det er denne sjekken som virker likt i alle språk. HTML-en serveren sender, ser lik ut enten den kommer fra Kotlin, Go, PHP eller Node, og det er den som sjekkes, ikke koden som lager den.

Markupen kan være riktig og likevel se feil ut: stilarket til komponenten er ikke lastet, eller en variant har ingen regel. Med --css leser sjekk stilarkene siden laster, med det de importerer, og sier fra om begge deler:

Terminal window
npx @fristil/designsystem sjekk --css=public/app.css --manifest=src/ui/button/fristil-manifest.json maler/*.html
maler/knapp.html:1:28: advarsel: data-variant="glass" på button har ingen regel i stilarkene, så den gjør ingenting synlig. Style verdien, eller ta den bort.
maler/kort.html:1:13: advarsel: Klassen «fs-card» står i markupen, men ingen av stilarkene styler den. Er fristil.css, eller stilarket til card, lastet?
2 funn i 2 filer.

Den første meldingen kommer for en verdi manifestet kjenner, men som ingen av stilarkene styler. En verdi Fristil ikke har, som data-variant="glass" på fs-button, avvises før stilarkene leses, med beskjed om de lovlige verdiene. Meldingen er nyttigst for en komponent du har tatt over: legger du til en variant i fragmentet, men ikke i CSS-en, er markupen gyldig og ser ut som standard. Utdataene over er fra en slik kopi: knapp.html er <button class="app-button" data-variant="glass">, med glass lagt til i fragmentet. @import følges til filer ved siden av og til pakker i node_modules, som @fristil/designsystem/fristil.css. --css kan gis flere ganger. Stilarkene leses med en ekte CSS-leser, så nesting, :is(), :where(), @layer og @media forstås som nettleseren forstår dem.

Det serveren sender, er ikke alltid det brukeren ser. Web-komponentene legger til markup, et skript kan sette en klasse, og stilarkene er de nettleseren faktisk lastet. diagnoseRendered sjekker siden slik nettleseren har rendret den, med Playwright:

import { diagnoseRendered } from "@fristil/designsystem/diagnostics"
test("skjemaet er riktig slik det vises", async ({ page }) => {
await page.goto("http://localhost:8080/skjema")
expect(await diagnoseRendered(page)).toEqual([])
})

Den gir det diagnosePage gir, og det stilarkene ikke styler. Et stilark fra et CDN leses også, når det svarer med Access-Control-Allow-Origin, som jsDelivr og unpkg gjør. Med Fristil for Kotlin heter det assertFristilRendered.

Med en server som kjører, er én linje nok:

Terminal window
npx @fristil/designsystem sjekk http://localhost:8080/ http://localhost:8080/skjema

Den samme sjekken finnes som funksjoner, for tester skrevet i JavaScript eller TypeScript:

import { diagnoseMarkup, diagnosePage } from "@fristil/designsystem/diagnostics"
expect(diagnoseMarkup(mal)).toEqual([]) // en mal eller en bit av en side
expect(diagnosePage(html)).toEqual([]) // en hel side, med koblingen

Hvert funn har start, end, line, column, severity, rule og message, og noen har en fix editoren kan tilby. Sjekken er den samme Rust-kjernen som editorene bruker, bygget til WebAssembly og med i pakken.

Er appen skrevet i et annet språk, kjører testen kommandoen over HTML-en den rendrer. I Kotlin:

@Test
fun `skjemaet er koblet riktig`() {
val html = app.render("/skjema")
val sjekk = ProcessBuilder("npx", "@fristil/designsystem", "sjekk", "--rendret")
.redirectErrorStream(true)
.start()
sjekk.outputStream.use { it.write(html.toByteArray()) }
val utdata = sjekk.inputStream.bufferedReader().readText()
assertEquals(0, sjekk.waitFor(), utdata)
}

Testen feiler med funnene som melding, og det er meldingen en kodeagent leser og retter etter.

Uten Node i CI bytter du npx @fristil/designsystem med java -jar fristil.jar. Med Fristil for Kotlin blir det assertFristil(html), med den samme sjekken kjørt i JVM-en.

Skriver regelboka for kodeagenter til standard ut. Ingen fil skrives noe sted.

Terminal window
npx @fristil/designsystem agent
npx @fristil/designsystem agent --rammeverk=datastar

Uten flagg leses miljøet av avhengighetene i package.json: Astro, React, Datastar, eller et byggesteg som Vite. Finnes det ingen package.json, som i en Kotlin- eller Go-app, er det regelboka for maler. Hvilken det ble, og hvorfor, står på standard feil.

--rammeverkRegelboka for
htmlhåndskrevet HTML uten byggesteg, der nettleseren laster filene direkte
malerserverskrevet HTML: Go-maler, Razor, PHP, Jinja, ERB og andre, og HTML skrevet i kode
bundleset byggesteg der markupen er vanlig HTML: Vue, Svelte, Solid, Lit og Vite
reactReact
astroAstro
datastarHTML med Datastar

Hvordan agenten finner regelboka, står på Kodeagenter.

Kopierer kildekoden til én komponent inn i prosjektet: TypeScript-fila og stilarket. Kopien er din fra det øyeblikket den er skrevet, og kommandoen gjør tre ting for at den skal kunne være det:

  • Kopien får nytt navn. fs-button blir app-button i klassene, taggene, customElements.define og selektorene. Kopien kan dermed stå ved siden av originalen, og du bytter navnet i markupen der kopien skal brukes. Variablene fra temaet, --fs-*, er de samme, så kopien følger temaet ditt som før.
  • Henvisningene ut av komponenten skrives om til pakken, så resten av systemet fortsatt kommer fra @fristil/designsystem og kan oppgraderes.
  • Et fragment av manifestet skrives ved siden av, fristil-manifest.json, med klassene, elementene og verdiene til kopien under det nye navnet. Med det sjekker sjekk markupen for kopien også:
Terminal window
npx @fristil/designsystem overta button --ut=src/ui
npx @fristil/designsystem sjekk --manifest=src/ui/button/fristil-manifest.json maler/*.html

Uten --manifest lar sjekk alt som ikke begynner med fs- være. Med det sjekkes bare kopiens egne navn, app-button med varianter og elementer, ikke resten av prosjektets klasser. Endrer du kopien, for eksempel med en ny variant, skriver du den inn i fragmentet også. --manifest kan gis flere ganger, én gang for hver kopi.

FlaggBetydning
--ut=<mappe>hvor kopien skal ligge. Standard: src/fristil
--overskriv=jaskriv over en kopi som finnes fra før

Uten navn lister kommandoen komponentene. Når du bør ta over en komponent, og hva du bør prøve først, står på Tilpasning.

Skriver manifestet sjekk bruker: Fristils klasser, elementer og lovlige verdier, med fragmentene fra overta lagt til. Det er det en editor eller et annet verktøy trenger for å kjenne ordforrådet prosjektet faktisk har.

Terminal window
npx @fristil/designsystem manifest --manifest=src/ui/button/fristil-manifest.json --ut=build/fristil/manifest.json
FlaggBetydning
--manifest=<fil>et fragment fra overta. Kan gis flere ganger
--ut=<fil>skriv til fil i stedet for til standard ut

Gradle-pluginen skriver den samme fila til build/fristil/manifest.json når manifests har fragmenter.

Lager et fargetema av merkefargene dine, med lyst og mørkt utseende og kontrastkravene oppfylt. Temaet skrives til standard ut, eller til en fil.

Terminal window
npx @fristil/designsystem tema --aksent=#7c3aed --fare=#b3261e \
--suksess=#2b6940 --advarsel=#8a5a00 --ut=tema.css
npx @fristil/designsystem tema fristil.tema.json --ut=tema.css
FlaggBetydning
--aksent, --fare, --suksess, --advarsel, --noytral, --besoktfargene for rollene, heksadesimalt
--merke1, --merke2, --merke3merkefarger for flater og kategorier
--skriftskriftstakken temaet skal bruke
--knapp-hjorner, --felt-hjorner, --flate-hjornerhjørnene på knapper, felt og flater
--knapp-ramme, --knapp-vektrammetykkelsen og vekten på knappeteksten
--ut=<fil>skriv til fil i stedet for til standard ut

Hva hver rolle styrer, og hvordan temaet tas i bruk, står på Eget tema.

Kontrollerer et tema du har skrevet selv. Kommandoen leser --fs-color-*-verdiene i hver blokk og sier hvilken celle som ryker, og hvorfor.

Terminal window
npx @fristil/designsystem sjekk-tema tema.css

Ett brudd gir feilkode. Et tema laget med tema holder kravene fra før.

Et tema uten farger, med bare skrift og form, har ingen kontrast å kontrollere. Kommandoen sier det og avslutter uten feilkode. En fil uten noen --fs-*-verdier gir feilkode, for da har sjekken ikke sett på noe.