@half-built/tooling
v0.16.1
Published
Lint presets and the test kit for half-built sites.
Readme
@half-built/tooling
Lint presets and the test kit for half-built sites.
Presets
@half-built/tooling/eslint: flat config for JS, TS (type-checked strict tier), and Astro, plus the vertical-whitespace policy: a blank line after imports and around interfaces, types, classes, functions, exports, and any statement that spans several lines, and braces on any control-statement body that drops to its own line (curly: multi-line). Autofixable witheslint --fix.@half-built/tooling/stylelint: stylelint-config-standard tuned for the house CSS (no hex outside tokens, nochwidths), with the empty-line rules on so rules and comment groups get their own air. Autofixable withstylelint --fix.@half-built/tooling/prettier: Prettier's defaults plus the Astro plugin. Prettier is a peer dependency; consumers import the preset fromprettier.config.mjsand add*.mdto.prettierignoreif their prose should stay as written.astroCompressHTMLis set to match Astro's owncompressHTMLdefault (true); a consumer that turnscompressHTMLoff inastro.config.mjsmust overrideastroCompressHTMLto match, or the plugin reformats around whitespace the build no longer collapses.@half-built/tooling/htmlvalidate: html-validate cannotextendsa package's JSON preset yet, so consumers keep a local copy of this file. Needs the optionalhtml-validatepeer.
Prettier keeps blank lines but never adds them, so run it first, then
the two linters' fixers, then Prettier once more to tidy what the
fixers rewrote. The workspace's lint:fix script is that sequence.
Test kit
From test-kit/browser-server.ts:
findChrome(): returns the absolute path to a local Chrome or Chromium install; throws naming every path it checked.CHROME_PATHoverrides the search when set. The built-in candidates cover Windows, the ubuntu-latest CI runner, and macOS (Chrome and Chromium).startPreview(port, readyPath): spawnsastro previewonportand resolves oncereadyPathanswers 200. Refuses to run against a port something else already answers. If the wait fails (a 404, a crashed server, or a timeout) it stops the server it just spawned before rethrowing, so a failed run never leaks a process holding the port.stopPreview(server): kills the server and, on POSIX, its whole detached process group; safe to call on a server that never started.launchChrome(): launches headless Chrome with a stated desktop pointer (hover, finepointer) so hover-gated code does not silently decline to mount on a CI runner with no input devices.desktopPage(browser, width?, height?): opens a desktop-viewport page.phonePage(browser, width?, height?): opens a touch, phone-viewport page, which flips(hover: none)and(pointer: coarse)on for that page over the launch setting.
From test-kit/helpers.ts:
stubRafOnFakeTimers(): stubsrequestAnimationFrameandcancelAnimationFrameon a self-advancing frame clock, for suites undervi.useFakeTimers(). Undo withvi.unstubAllGlobals().polyfillDialog(): fills inHTMLDialogElement.prototype.showModaland.closewhere jsdom has not implemented them, so a suite exercises the component's logic rather than jsdom's gaps.recordingContext(): returns aRecordingContextwhosectxis a fake 2D canvas context recording every draw call (with the style fields in effect at call time) intocalls, and whoseops(op)filterscallsdown to one operation.CanvasCall: the shape of one recorded canvas call (op,args, and the style snapshot).RecordingContext: the shaperecordingContext()returns (calls,ops,ctx).
Requirements
Node ^22.13.0 || >=24. Required peers: eslint, stylelint,
prettier. Optional peers: html-validate (the htmlvalidate
preset) and vitest (the test kit). The test kit's browser helpers
also need puppeteer-core, installed by the consumer and tested with
25.x. It is not declared as a peer: npm walks optional peers when it
resolves, and html-validate's chain (vitest, @vitest/browser,
webdriverio) caps puppeteer-core at 24.x, so declaring 25.x made a
fresh install fail with ERESOLVE.
Provenance
Extracted from the private half-built-robots-blog repository, where
this configuration was built and used in production. The decisions
behind it are in the design record.
