@getvitops/utils 8.2.0 → 8.3.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +83 -0
- package/dist/audit/index.d.mts +204 -0
- package/dist/audit/index.d.mts.map +1 -0
- package/dist/audit/index.mjs +572 -0
- package/dist/audit/index.mjs.map +1 -0
- package/dist/color/index.d.mts +6 -1
- package/dist/color/index.d.mts.map +1 -1
- package/dist/color/index.mjs +8 -1
- package/dist/color/index.mjs.map +1 -1
- package/dist/plan-CddqsmJJ.d.mts +82 -0
- package/dist/plan-CddqsmJJ.d.mts.map +1 -0
- package/dist/plan-DpHv6NO8.mjs +93 -0
- package/dist/plan-DpHv6NO8.mjs.map +1 -0
- package/dist/reviews/index.d.mts +2 -81
- package/dist/reviews/index.d.mts.map +1 -1
- package/dist/reviews/index.mjs +1 -91
- package/dist/reviews/index.mjs.map +1 -1
- package/dist/reviews/select.d.mts +2 -0
- package/dist/reviews/select.mjs +3 -0
- package/dist/turnstile/index.d.mts +105 -0
- package/dist/turnstile/index.d.mts.map +1 -0
- package/dist/turnstile/index.mjs +281 -0
- package/dist/turnstile/index.mjs.map +1 -0
- package/package.json +35 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,88 @@
|
|
|
1
1
|
# @getvitops/utils
|
|
2
2
|
|
|
3
|
+
## 8.3.0-alpha.1
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 24c568b: Escape hatches on every block, a section theme, widget areas, a badges block, Tailwind scanning of package renderers, and a sturdier `vitops audit`.
|
|
8
|
+
|
|
9
|
+
**@getvitops/emdash**
|
|
10
|
+
|
|
11
|
+
- Every `vitops.*` block and `vitops_section` gains three fields: `anchor` (rendered as the `id`, so `#contact` works), `className` (`class_name` on the section type: block-type slugs are lowercase) and `style`. `style` takes CSS custom properties only (`--p-card: 2rem`); any other declaration, and any value containing `url(`, `@`, `{`, `}` or a backslash, is dropped. With the `tailwind` format a class typed in the CMS only works if the site already uses it. They are applied to the block's own outermost element (the grid `<ul>` for `vitops.cards`), never an extra wrapper, so a block's markup is the same whether or not an editor fills them in.
|
|
12
|
+
- `vitops_section` gains a `theme` select: a role, or `<role>:solid`, with readable text chosen by the generator's contrast rules. It overrides `tone`/`color`/`solid`, which stay for existing content. Other site roles still go through `tone`.
|
|
13
|
+
- New `vitops.badges` block (a row of `.badge` or `.tag` labels, each with an optional tone, icon and link) and `vitops.widgetArea` block, plus `<VitopsWidgetArea name level />` from `@getvitops/emdash/astro`. A widget area is content defined once under Widgets and shown wherever it is placed. An area cannot hold another area, and an area containing a `core:*` component widget is rendered by EmDash's own renderer.
|
|
14
|
+
- Existing sites: re-run the block-type seed only on a new database; on an existing one add the `theme`, `anchor`, `className` and `style` fields to the `vitops_section` block type in the admin.
|
|
15
|
+
|
|
16
|
+
**@getvitops/create**: the emdash template seeds `announcement` and `pre-footer` widget areas, renders them in `Layout.astro`, and documents when to use a Section, a block or a widget area. Sites scaffolded earlier add the two `<VitopsWidgetArea>` lines and the `widgetAreas` seed entries by hand.
|
|
17
|
+
|
|
18
|
+
**@getvitops/generator / astro / vite** (`tailwind` format only): the Astro integration now adds `@source` lines for `@getvitops/astro` and `@getvitops/emdash`, because Tailwind v4 does not scan `node_modules`; utilities used only by their renderers (`font-display`, `font-caption`, `font-footnote`) were never emitted and the page silently rendered at body size. New `sources` option on `generate()` and the Vite plugin. A site's `src/package-classes.txt` workaround can be deleted. css and bricks: no change.
|
|
19
|
+
|
|
20
|
+
**@getvitops/cli**: `vitops emdash check-prerender` now also warns when a page uses a type-role class (`font-display`, …) the built CSS has no rule for; `--strict` makes it fail. `vitops audit` checks for its optional packages and a Chromium binary before starting the preview server (so a failed run no longer leaves port 4398 busy), stops the server on Ctrl+C and termination, and takes its page list from the built sitemap, then the menus; the guessed defaults (`/privacy`, `/contact`, …) are used only when neither exists.
|
|
21
|
+
|
|
22
|
+
**@getvitops/utils**: the audit helpers behind the above (`preflight`, `fetchSitemapPaths`, `sitemapLocs`, `pathsFromSitemapLocs`).
|
|
23
|
+
|
|
24
|
+
**@getvitops/core** (all formats): new `.block-anchor` rule gives an anchored block `scroll-margin-top: var(--header-offset, 5rem)`; set `--header-offset` to a sticky header's height. New `widget-area.css` partial. No other consumer-facing change.
|
|
25
|
+
|
|
26
|
+
The other fixed-group packages: no consumer-facing change beyond the above.
|
|
27
|
+
|
|
28
|
+
**Also fixed in the emdash template** (`site.json`): it defined only the `display`, `heading` and `body` type roles while the blocks use `title`, `eyebrow`, `lead`, `caption` and `footnote`, so those rendered at body size with no rule behind them. The roles are added with the reference design system's specs. A site scaffolded earlier adds the same five entries under `designSystem.themes.default.typography.roles`; `vitops emdash check-prerender` now names any that are missing.
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- @getvitops/config@8.3.0-alpha.1
|
|
33
|
+
|
|
34
|
+
## 8.3.0-alpha.0
|
|
35
|
+
|
|
36
|
+
### Minor Changes
|
|
37
|
+
|
|
38
|
+
- 161c7f3: A contact form that works end to end: `vitops setup turnstile`, `<wc-turnstile>`, the `vitops.form` EmDash block, and the route the emdash template ships to receive it.
|
|
39
|
+
|
|
40
|
+
**CSS, all formats** (no existing class changes): `forms.css` gains `.form-notice--target:not(:target)` (a message revealed only when the URL fragment names it, which is how a prerendered page shows a no-JS form's result) and `:where(wc-turnstile) { display: block }`.
|
|
41
|
+
|
|
42
|
+
**`@getvitops/core`:** new `<wc-turnstile sitekey="…">` in `elements.js`. It loads Cloudflare Turnstile on the first interaction with its form (no request to `challenges.cloudflare.com` for a visitor who only reads the page), holds an early submit until the token arrives, and leaves its slotted no-JS explanation in place until JS takes over. Turnstile is category `necessary`, so it is not behind the consent banner.
|
|
43
|
+
|
|
44
|
+
**`@getvitops/utils` / `@getvitops/cli`:** new `@getvitops/utils/turnstile` and `vitops setup turnstile [--dry] [--check] [--no-write] [--no-secret]`. It plans from the site's hostnames, creates a managed widget unless one already covers them (an existing widget is adopted, never edited, rotated or deleted), writes the public key to `site.security.turnstile.siteKey`, and pipes the one-time secret to `wrangler secret put VITOPS_TURNSTILE_SECRET` without writing it to any file. Needs `CLOUDFLARE_API_TOKEN` with **Account > Turnstile > Edit** and `CLOUDFLARE_ACCOUNT_ID`.
|
|
45
|
+
|
|
46
|
+
**`@getvitops/astro`:** `virtual:getvitops/head` gains `turnstileSiteKey` (read from `site.security.turnstile.siteKey`) so blocks can render the widget. No other change.
|
|
47
|
+
|
|
48
|
+
**`@getvitops/generator`:** `TIERS` gains a `turnstile` entry (wc-turnstile, claimed by `vitops.form`); `wc-multi-field`'s `emdashExempt` reason is reworded now the form block exists.
|
|
49
|
+
|
|
50
|
+
**`@getvitops/emdash`:** new `vitops.form` block: a field repeater (text, email, phone, long text, choose one, tick box), required flags, help text, success/error messages, optional Turnstile. It renders a semantic `<form method="post">` that works with no JavaScript, with a honeypot named per `createConversionRoute`'s defaults. A field named `phone` submits as `tel`, because the route reserves `phone` and `event`.
|
|
51
|
+
|
|
52
|
+
**`@getvitops/create`:** the emdash template ships `src/pages/api/track.ts` (`prerender = false`, `createConversionRoute()`), a seeded contact form, and `challenges.cloudflare.com` in both templates' Report-Only CSP (`script-src`, `frame-src`). The route refuses a post with nowhere to deliver and fails closed when a site key exists without `VITOPS_TURNSTILE_SECRET`. SETUP.html gains the Turnstile step. Existing sites: copy the route and the CSP change, then run `vitops setup turnstile`.
|
|
53
|
+
|
|
54
|
+
- 175d16e: **Added: `vitops.reviews` and `vitops.nav` EmDash blocks.** Non-breaking.
|
|
55
|
+
|
|
56
|
+
- **`vitops.reviews`** renders Google reviews from the committed `.vitops/reviews.json` cache (`vitops reviews`) as a grid, carousel or marquee of `<ReviewCard>`. Fields: location key, layout, columns, limit, lowest rating, order, featured ids, reviewer photos (off by default), tone/colour. Which reviews show is `selectReviews()`, the one shared decision. Review JSON-LD is not offered (Google treats self-marked-up reviews as ineligible for rich results). A new review reaches the page after `vitops reviews` is re-run, committed and the site rebuilt, not when an editor saves; with no cache file the block renders nothing (a note in `astro dev`).
|
|
57
|
+
- **`vitops.nav`** renders a named EmDash menu inside page content (site map, section links, footer-style columns), never the header. Fields: menu (picked from the site's menus via a new `menus/list` plugin route, with `footer-sitemap`/`footer-legal`/`primary` as the static fallback), accessible name, visible heading and level, layout `list | inline | columns | sitenav`, depth 1-3, tone/colour. It is a `<nav>` with a name that is never `Primary`, `Site map` or `Legal` (the layout's landmarks), `aria-current="page"`, no runtime JS; a missing or empty menu renders nothing.
|
|
58
|
+
- `@getvitops/astro`: **`virtual:getvitops/reviews`**, served by `vitops()`, is `.vitops/reviews.json` as a build-time import (an empty cache when absent or unreadable), because a Worker cannot read the file. `<ReviewCard>` now renders the review's source link (`.review__source`, `rel="nofollow noopener noreferrer"`), which the pattern already styled. **Fix:** `src/json-ld.ts` was missing from the published `files`, so any consumer importing `<ReviewCard>` (which composes `schemas/Review.astro`) failed to build with an unresolved import. `@getvitops/emdash` now needs this version of `@getvitops/astro` for the `vitops.reviews` block.
|
|
59
|
+
- `@getvitops/utils`: new Worker-safe subpath **`@getvitops/utils/reviews/select`** (`selectReviews` and the review types, no `node:fs`). `selectReviews` now takes only the display fields (`featured`, `minRating`, `limit`, `sort`), so a caller with no configured `locationId` can use it; existing calls are unchanged.
|
|
60
|
+
- `@getvitops/core`: new `.navlist` pattern in `patterns/sitenav.css` (`.navlist`, `__item`, `__link`, `__label`, `__sub`, `--inline`, `--columns`). **All formats** (css, bricks, tailwind). No existing class changes.
|
|
61
|
+
- `@getvitops/generator`: `TIERS.review` lists `vitops.reviews` and `TIERS.sitenav` lists `vitops.nav` (and `.navlist`), so `vitops docs components` and the docsite show them.
|
|
62
|
+
|
|
63
|
+
- 83d6f3c: Theming escape hatches, so a real palette builds without raw ramp steps. All additive; existing configs build unchanged.
|
|
64
|
+
|
|
65
|
+
- **Dark-only sites.** `designSystem.defaultColorScheme: "dark"` (accepted by the schema before, but ignored) now makes the dark tokens the `:root` appearance with `color-scheme: dark`, emits no light block or `data-theme` flip, and skips light-mode contrast checks. Reaches css, bricks and tailwind formats. Do not ship `<wc-color-scheme-toggle>` on such a site.
|
|
66
|
+
- **Role solid step and foreground.** `colors.roles.<role>` may be `{ hue, kind?, solid?, foreground? }`. `solid: 400` starts the solid family at step 400 (bold and x-bold walk one and two rungs darker); `foreground: "dark" | "light"` pins `text-on-<role>`. The APCA check (Lc 60) still runs on the pair emitted. The string shorthand is unchanged. All formats. The live editor's `roleTokens` still assume the default 600 family when re-pointing a role.
|
|
67
|
+
- **Split shadows.** `shadows.<name>` may be `{ box?, drop? }`: `box` (spread, inset, layers) is `--shadow-<name>`; `drop` is `--shadow-<name>-drop` and feeds `.drop-shadow-<name>` and the `shadow:` state shortcut. The string form is unchanged. css/bricks emit `.drop-shadow-*`; tailwind emits the `-drop` token only.
|
|
68
|
+
- **Layout tokens.** New optional `layout` block (`widths.{measure,breakout,spotlight,nav}`, `regionSpace.{min,preferred,max}`) emitted as `--width-*` / `--region-space*` on `:root` in css, bricks and tailwind formats, and exposed in `design-manifest.json` (`layout`, `reverseIndex`). Keys you omit keep the framework defaults.
|
|
69
|
+
- **`acknowledgeOffLadder: true`** on a palette hue silences that hue's off-ladder anchor warnings.
|
|
70
|
+
- **Typography:** `transform` and `decoration` are now accepted as aliases of `text-transform` and `text-decoration` (canonical wins when both are present) instead of warning and being dropped.
|
|
71
|
+
- **Docs strings** (`authoring.md`, JSON Schema hovers) state the Lc 60 muted-text requirement against the page plane and give a type-scale recipe for marketing headings.
|
|
72
|
+
- `@getvitops/utils`: `pickOn` takes an optional `prefer: 'light' | 'dark'`.
|
|
73
|
+
|
|
74
|
+
- b47df4d: **Added: `vitops audit` — Lighthouse + axe budgets over a built site.** Non-breaking, opt-in.
|
|
75
|
+
|
|
76
|
+
`vitops audit [--build] [--url <base>] [--pages /a,/b] [--warn] [--out <dir>]` serves the existing build with `astro preview` on a dedicated port (4398; it aborts rather than attach to something else already there), audits `/` plus `/privacy`, `/terms`, `/cookies`, `/contact` and every link in `seed/seed.json`'s `primary*`/`footer*` menus, and skips any route that 404s (a 404 on `/` fails the run). Per page it runs axe (tags wcag2a, wcag2aa, wcag21a, wcag21aa) and Lighthouse on the same Chromium. Default budgets: LCP < 2500 ms, CLS < 0.1, TBT < 200 ms (the INP proxy), no serious or critical axe violations; override with `--lcp`, `--cls`, `--tbt`, `--impact`. Writes `report.json`, `report.md` and `pages/<page>.{json,md}` to `.vitops/audit/`; exits non-zero on failure unless `--warn`. Every report states that a pass is **not** AODA certification and lists the manual checks.
|
|
77
|
+
|
|
78
|
+
`playwright`, `@axe-core/playwright` and `lighthouse` are **optional peer dependencies** of `@getvitops/utils`, loaded lazily — nothing is installed or loaded unless you run the command, and a missing one fails with the install command. Pure planner and report rendering are `@getvitops/utils/audit` (new subpath).
|
|
79
|
+
|
|
80
|
+
CI: the reusable `site-ci.yml` gains opt-in `run-audit` (default `false`) and `audit-args` inputs; callers pinned to `@v1` that pass neither are unaffected.
|
|
81
|
+
|
|
82
|
+
### Patch Changes
|
|
83
|
+
|
|
84
|
+
- @getvitops/config@8.3.0-alpha.0
|
|
85
|
+
|
|
3
86
|
## 8.2.0
|
|
4
87
|
|
|
5
88
|
### Minor Changes
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/** Shapes shared by the audit planner, the executor and the report renderers. */
|
|
2
|
+
type AxeImpact = 'minor' | 'moderate' | 'serious' | 'critical';
|
|
3
|
+
interface AuditBudgets {
|
|
4
|
+
/** Largest Contentful Paint ceiling, ms. */
|
|
5
|
+
lcpMs: number;
|
|
6
|
+
/** Cumulative Layout Shift ceiling (unitless). */
|
|
7
|
+
cls: number;
|
|
8
|
+
/** Total Blocking Time ceiling, ms — the lab proxy for INP. */
|
|
9
|
+
tbtMs: number;
|
|
10
|
+
/** axe impacts that fail the page. Default: serious + critical. */
|
|
11
|
+
blockingImpacts: AxeImpact[];
|
|
12
|
+
}
|
|
13
|
+
interface AxeViolation {
|
|
14
|
+
id: string;
|
|
15
|
+
/** axe reports `null` impact for some incomplete rules; normalised to `moderate`. */
|
|
16
|
+
impact: AxeImpact;
|
|
17
|
+
help: string;
|
|
18
|
+
helpUrl: string;
|
|
19
|
+
/** Total nodes the rule failed on. */
|
|
20
|
+
nodeCount: number;
|
|
21
|
+
/** First few CSS selectors, for the report. */
|
|
22
|
+
targets: string[];
|
|
23
|
+
}
|
|
24
|
+
interface PageMetrics {
|
|
25
|
+
/** `undefined` when Lighthouse could not compute it — which fails the page, not passes it. */
|
|
26
|
+
lcpMs?: number | undefined;
|
|
27
|
+
cls?: number | undefined;
|
|
28
|
+
tbtMs?: number | undefined;
|
|
29
|
+
/** Lighthouse category scores, 0-100. */
|
|
30
|
+
scores: {
|
|
31
|
+
performance?: number | undefined;
|
|
32
|
+
seo?: number | undefined;
|
|
33
|
+
bestPractices?: number | undefined;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
interface BudgetFailure {
|
|
37
|
+
kind: 'lcp' | 'cls' | 'tbt' | 'axe' | 'metric-missing' | 'page-error' | 'required-page-missing';
|
|
38
|
+
message: string;
|
|
39
|
+
}
|
|
40
|
+
type PageStatus = 'audited' | 'skipped' | 'error';
|
|
41
|
+
interface PageResult {
|
|
42
|
+
path: string;
|
|
43
|
+
url: string;
|
|
44
|
+
status: PageStatus;
|
|
45
|
+
httpStatus?: number;
|
|
46
|
+
/** Why a page was skipped or errored. */
|
|
47
|
+
reason?: string;
|
|
48
|
+
metrics?: PageMetrics;
|
|
49
|
+
violations?: AxeViolation[];
|
|
50
|
+
failures: BudgetFailure[];
|
|
51
|
+
}
|
|
52
|
+
type FormFactor = 'mobile' | 'desktop';
|
|
53
|
+
interface AuditReport {
|
|
54
|
+
generatedAt: string;
|
|
55
|
+
baseUrl: string;
|
|
56
|
+
formFactor: FormFactor;
|
|
57
|
+
budgets: AuditBudgets;
|
|
58
|
+
axeTags: string[];
|
|
59
|
+
pages: PageResult[];
|
|
60
|
+
/** True when no page has a failure. */
|
|
61
|
+
passed: boolean;
|
|
62
|
+
/** Always present: what a pass does and does not mean. */
|
|
63
|
+
disclaimer: string;
|
|
64
|
+
manualChecks: string[];
|
|
65
|
+
}
|
|
66
|
+
export declare const DEFAULT_BUDGETS: AuditBudgets;
|
|
67
|
+
/**
|
|
68
|
+
* `wcag2a`/`wcag2aa` are what AODA (WCAG 2.0 AA) asks for; `wcag21a`/`wcag21aa` add the
|
|
69
|
+
* 2.1 criteria we target. `wcag21aa` alone covers only the *new AA* criteria, not the
|
|
70
|
+
* new level-A ones, so both 2.1 tags are listed.
|
|
71
|
+
*/
|
|
72
|
+
export declare const AXE_TAGS: string[];
|
|
73
|
+
/** Pages tried on every run. `/` is required; the rest are skipped when they 404. */
|
|
74
|
+
export declare const DEFAULT_PAGES: string[];
|
|
75
|
+
export declare const DISCLAIMER: string;
|
|
76
|
+
export declare const MANUAL_CHECKS: string[];
|
|
77
|
+
/**
|
|
78
|
+
* A menu-ish thing: EmDash seed (`items`), `getMenu()` (`items`, items with `children`),
|
|
79
|
+
* or either shape nested. Only `name`, `url` and children are read.
|
|
80
|
+
*/
|
|
81
|
+
interface MenuLike {
|
|
82
|
+
name?: string;
|
|
83
|
+
items?: MenuItemLike[];
|
|
84
|
+
}
|
|
85
|
+
interface MenuItemLike {
|
|
86
|
+
url?: string | null;
|
|
87
|
+
children?: MenuItemLike[];
|
|
88
|
+
items?: MenuItemLike[];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Normalise to a site-relative path, or `undefined` for anything that is not an
|
|
92
|
+
* auditable page of this site: external URLs, hash-only links, `mailto:`/`tel:`,
|
|
93
|
+
* protocol-relative URLs, file downloads (anything with an extension) and the CMS
|
|
94
|
+
* admin. Query and hash are dropped; a trailing slash is too (except the root).
|
|
95
|
+
*/
|
|
96
|
+
export declare function normalizePath(url: string | null | undefined): string | undefined;
|
|
97
|
+
/** Is this one of the menus whose links are pages worth auditing? */
|
|
98
|
+
export declare function isAuditMenu(name: string | undefined): boolean;
|
|
99
|
+
/** Paths from the `primary*` / `footer*` menus (`footer-legal`, `primary-mobile`, …). */
|
|
100
|
+
export declare function pathsFromMenus(menus: MenuLike[]): string[];
|
|
101
|
+
/** Same, from an EmDash seed file's parsed JSON (`{ menus: [...] }`). */
|
|
102
|
+
export declare function pathsFromSeed(seed: unknown): string[];
|
|
103
|
+
/** `<loc>` values in a sitemap or sitemap index, in document order. */
|
|
104
|
+
export declare function sitemapLocs(xml: string): string[];
|
|
105
|
+
/**
|
|
106
|
+
* The page paths in a sitemap's `<loc>`s. The origin is dropped: a built sitemap names the
|
|
107
|
+
* production host, and the audit reads the same paths from whatever server it was pointed at.
|
|
108
|
+
*/
|
|
109
|
+
export declare function pathsFromSitemapLocs(locs: string[]): string[];
|
|
110
|
+
interface PagePlanInput {
|
|
111
|
+
/** Paths from the built sitemap. */
|
|
112
|
+
sitemapPaths?: string[];
|
|
113
|
+
/** Paths found in menus. */
|
|
114
|
+
menuPaths?: string[];
|
|
115
|
+
/** Paths from `--pages`. */
|
|
116
|
+
extra?: string[];
|
|
117
|
+
/**
|
|
118
|
+
* Default true, but only used when the sitemap and the menus found nothing: guessing
|
|
119
|
+
* `/privacy`, `/contact`… is the fallback, not an addition to a list the site already gave.
|
|
120
|
+
* `--no-defaults` for a site that wants an exact list.
|
|
121
|
+
*/
|
|
122
|
+
includeDefaults?: boolean;
|
|
123
|
+
}
|
|
124
|
+
/** The pages to try, `/` always first, unique, in a stable order. */
|
|
125
|
+
export declare function planPages(input?: PagePlanInput): string[];
|
|
126
|
+
/**
|
|
127
|
+
* What an HTTP status means for a candidate page. 404/410 → skipped (a single-page
|
|
128
|
+
* site has no `/contact`, and that is fine) — except `/`, which must exist. Any other
|
|
129
|
+
* non-2xx is an error: a 500 on `/privacy` is a defect, not an absent page.
|
|
130
|
+
*/
|
|
131
|
+
export declare function classifyStatus(path: string, httpStatus: number | undefined): {
|
|
132
|
+
status: 'audited' | 'skipped' | 'error';
|
|
133
|
+
reason?: string;
|
|
134
|
+
};
|
|
135
|
+
/** axe can report a null impact; treat it as `moderate`, never silently drop it. */
|
|
136
|
+
export declare function normalizeImpact(impact: string | null | undefined): AxeImpact;
|
|
137
|
+
/** `serious,critical` → impacts, rejecting typos so a budget cannot silently be empty. */
|
|
138
|
+
export declare function parseImpacts(list: string): AxeImpact[];
|
|
139
|
+
/** Everything that makes one audited page fail. Empty = the page passes. */
|
|
140
|
+
export declare function evaluatePage(metrics: PageMetrics | undefined, violations: AxeViolation[] | undefined, budgets: AuditBudgets): BudgetFailure[];
|
|
141
|
+
/** Build a `PageResult` for a page that was not audited (skipped or error). */
|
|
142
|
+
export declare function unauditedPage(path: string, url: string, httpStatus: number | undefined, verdict: {
|
|
143
|
+
status: 'skipped' | 'error';
|
|
144
|
+
reason?: string;
|
|
145
|
+
}): PageResult;
|
|
146
|
+
export declare function auditedPage(path: string, url: string, httpStatus: number, metrics: PageMetrics, violations: AxeViolation[], budgets: AuditBudgets): PageResult;
|
|
147
|
+
export declare function buildReport(input: {
|
|
148
|
+
generatedAt: string;
|
|
149
|
+
baseUrl: string;
|
|
150
|
+
formFactor: FormFactor;
|
|
151
|
+
budgets: AuditBudgets;
|
|
152
|
+
pages: PageResult[];
|
|
153
|
+
}): AuditReport;
|
|
154
|
+
/** `/` → `home`, `/a/b` → `a-b`: a safe per-page filename. */
|
|
155
|
+
export declare function pageSlug(path: string): string;
|
|
156
|
+
export declare function renderPageMarkdown(page: PageResult, budgets: AuditBudgets): string;
|
|
157
|
+
export declare function renderMarkdown(report: AuditReport): string;
|
|
158
|
+
/** Files to write, relative to the output dir: JSON + markdown overall and per page. */
|
|
159
|
+
export declare function reportFiles(report: AuditReport): Record<string, string>;
|
|
160
|
+
/** One-line-per-failure console summary. */
|
|
161
|
+
export declare function formatSummary(report: AuditReport): string;
|
|
162
|
+
/**
|
|
163
|
+
* Check, before any server starts, that everything the audit needs is there: the three optional
|
|
164
|
+
* packages and a Chromium binary. A missing browser used to surface only after the preview
|
|
165
|
+
* server was up, and the failed launch left it running.
|
|
166
|
+
*/
|
|
167
|
+
export declare function preflight(): Promise<void>;
|
|
168
|
+
/**
|
|
169
|
+
* Page paths from the served site's sitemap (`/sitemap-index.xml`, then `/sitemap.xml`), following
|
|
170
|
+
* an index one level to its child sitemaps. Empty when the site serves none.
|
|
171
|
+
*/
|
|
172
|
+
export declare function fetchSitemapPaths(baseUrl: string): Promise<string[]>;
|
|
173
|
+
/** A free TCP port, or `true` for "this specific one is free". */
|
|
174
|
+
export declare function isPortFree(port: number): Promise<boolean>;
|
|
175
|
+
/** Run a command to completion, inheriting stdio. Rejects on a non-zero exit. */
|
|
176
|
+
export declare function runCommand(cmd: string, args: string[], cwd: string): Promise<void>;
|
|
177
|
+
interface PreviewServer {
|
|
178
|
+
baseUrl: string;
|
|
179
|
+
stop(): void;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* `astro preview` on a dedicated port.
|
|
183
|
+
*
|
|
184
|
+
* Astro's preview server silently moves to the next port when its own is taken, and
|
|
185
|
+
* a readiness probe would then happily attach to whatever owns the original one — the
|
|
186
|
+
* failure `site/playwright.config.ts` documents. So the port is checked free first and
|
|
187
|
+
* the run aborts if it is not.
|
|
188
|
+
*/
|
|
189
|
+
export declare function startPreview(opts: {
|
|
190
|
+
cwd: string;
|
|
191
|
+
port: number;
|
|
192
|
+
timeoutMs?: number;
|
|
193
|
+
}): Promise<PreviewServer>;
|
|
194
|
+
interface RunOptions {
|
|
195
|
+
baseUrl: string;
|
|
196
|
+
paths: string[];
|
|
197
|
+
budgets: AuditBudgets;
|
|
198
|
+
formFactor: FormFactor;
|
|
199
|
+
onProgress?: (message: string) => void;
|
|
200
|
+
}
|
|
201
|
+
/** Audit each path. Never throws for a bad PAGE — only for missing tooling/browser. */
|
|
202
|
+
export declare function runAudit(opts: RunOptions): Promise<PageResult[]>;
|
|
203
|
+
export type { AuditBudgets, AuditReport, AxeImpact, AxeViolation, BudgetFailure, FormFactor, MenuItemLike, MenuLike, PageMetrics, PagePlanInput, PageResult, PageStatus, PreviewServer, RunOptions };
|
|
204
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/audit/types.ts","../../src/audit/plan.ts","../../src/audit/run.ts"],"mappings":";KAEY;UAEK;;EAEf;;EAEA;;EAEA;;EAEA,iBAAiB;;UAGF;EACf;;EAEA,QAAQ;EACR;EACA;;EAEA;;EAEA;;UAGe;;EAEf;EACA;EACA;;EAEA;IACE;IACA;IACA;;;UAIa;EACf;EACA;;KAGU;UAEK;EACf;EACA;EACA,QAAQ;EACR;;EAEA;EACA,UAAU;EACV,aAAa;EACb,UAAU;;KAGA;UAEK;EACf;EACA;EACA,YAAY;EACZ,SAAS;EACT;EACA,OAAO;;EAEP;;EAEA;EACA;;qBCrDW,iBAAiB;;;;;;qBAYjB;;qBAGA;qBAEA;qBAKA;;;;;UAgBI;EACf;EACA,QAAQ;;UAEO;EACf;EACA,WAAW;EACX,QAAQ;;;;;;;;wBASM,cAAc;;wBAsBd,YAAY;;wBAKZ,eAAe,OAAO;;wBAOtB,cAAc;;wBAMd,YAAY;;;;;wBAaZ,qBAAqB;UAcpB;;EAEf;;EAEA;;EAEA;;;;;;EAMA;;;wBAIc,UAAU,QAAO;;;;;;wBAuBjB,eACd,cACA;EACG;EAAyC;;;wBAgB9B,gBAAgB,oCAAoC;;wBAKpD,aAAa,eAAe;;wBAe5B,aACd,SAAS,yBACT,YAAY,4BACZ,SAAS,eACR;;wBAyCa,cACd,cACA,aACA,gCACA;EAAW;EAA6B;IACvC;wBAmBa,YACd,cACA,aACA,oBACA,SAAS,aACT,YAAY,gBACZ,SAAS,eACR;wBAYa,YAAY;EAC1B;EACA;EACA,YAAY;EACZ,SAAS;EACT,OAAO;IACL;;wBAiBY,SAAS;wBAOT,mBAAmB,MAAM,YAAY,SAAS;wBAyC9C,eAAe,QAAQ;;wBAiCvB,YAAY,QAAQ,cAAc;;wBAgBlC,cAAc,QAAQ;;;;;;wBCjXhB,aAAa;;;;;wBAoBb,kBAAkB,kBAAkB;;wBAyB1C,WAAW,eAAe;;wBAoB1B,WAAW,aAAa,gBAAgB,cAAc;UAUrD;EACf;EACA;;;;;;;;;;wBAWoB,aAAa;EACjC;EACA;EACA;IACE,QAAQ;UA+FK;EACf;EACA;EACA,SAAS;EACT,YAAY;EACZ,cAAc;;;wBAIM,SAAS,MAAM,aAAa,QAAQ"}
|