You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 75d663f
Browse filesBrowse the repository at this point in the historyBrowse files
Rework the a11y inspector to track violations per route, present them through a
Dashboard + grouped Violations tab, and highlight with a preview ring plus
pinned, numbered badges (root-element targets get a corner notice). The agent
detects routes framework-neutrally (History-API patch + popstate/hashchange),
persists its route→report map in sessionStorage, broadens the axe tag set to
WCAG 2.0–2.2 + best-practice (tagged and filterable), adds interaction-driven
auto-scan, and logs newly-appeared violations to the console.
Author options (auto-scan, logging, default-highlight, axe tags/options) flow
through `get-config` to the panel, which forwards the runtime slice to the agent
over the BroadcastChannel. Each mirrored messages-feed entry carries a
navigation action back to the deep-linked rule/route, and the panel honours dock
activations from other docks.
Co-authored-with an agent.
|**Node** (`src/index.ts`, `src/node`, `src/rpc`) | the devframe backend |`get-config` RPC (impact taxonomy + runtime config) — live in dev, baked in a static build |
24
40
25
41
The agent and panel talk over a same-origin
26
42
[`BroadcastChannel`](src/shared/protocol.ts), not the devframe RPC backend. That
27
43
is what keeps the live loop working in **both modes**: neither half needs a
28
44
server to reach the other, only a shared browser origin (host page + panel
29
-
iframe). devframe RPC carries the data model on top — `get-config` is a `static`
30
-
function, so it resolves over WebSocket in dev and from the baked dump in a
31
-
static build.
45
+
iframe). The agent owns the authoritative route → report map and broadcasts the
46
+
whole aggregate on every change, so the panel stays a pure render of it. devframe
47
+
RPC carries the data model on top — `get-config` is a `static` function, so it
48
+
resolves over WebSocket in dev and from the baked dump in a static build; the
49
+
panel forwards its runtime-config slice to the agent over the channel, keeping the
50
+
agent itself free of any RPC dependency.
32
51
33
52
devframe deliberately provides no access to the host application's DOM, so the
34
53
agent is the author-provided bridge into the page being checked. In a hub, the
@@ -37,14 +56,34 @@ dock's `clientScript` (resolved to an importable URL — `/@fs/…` under Vite,
37
56
statically-served path) and the hub's client runtime (`createDevframeClientHost`
38
57
from `@devframes/hub/client`) imports it into the host page and calls its
39
58
default export with the client-script context. Booted that way, the agent also
40
-
mirrors each scan into the hub's **messages feed** — a summary entry driven
41
-
through the loading → idle lifecycle plus one entry per violated rule, carrying
42
-
the impact-mapped level, WCAG tags as labels, and the first offending element's
43
-
selector and bounding box (rendered by `@devframes/plugin-messages` when the
44
-
hub mounts it). Both minimal hub examples do exactly this. Outside a hub, one
59
+
mirrors the active route's scan into the hub's **messages feed** — a summary entry
60
+
driven through the loading → idle lifecycle plus one entry per violated rule,
61
+
carrying the impact-mapped level, WCAG tags as labels, and the first offending
62
+
element's selector and bounding box (rendered by `@devframes/plugin-messages` when
63
+
the hub mounts it). Each entry also carries a **navigation action**: clicking it
64
+
in the messages panel activates the a11y dock (`hub:docks:activate`) deep-linked
65
+
to the rule + route (or the Dashboard, for the summary). Both minimal hub examples
66
+
do exactly this. Outside a hub, one
45
67
`<script type="module">` for the same bundle does the job — the demo below
46
68
shows it (no hub context, so the feed mirror simply stays off).
47
69
70
+
## Configuration
71
+
72
+
Pass options to `createA11yDevframe()` (surfaced through `get-config`, so they
73
+
reach both the panel and the agent):
74
+
75
+
```ts
76
+
createA11yDevframe({
77
+
autoScan: true, // rescan on debounced interaction (default true)
78
+
logIssues: true, // log new violations to the console (default true)
79
+
defaultHighlight: false, // auto-pin a route's violations on first scan (default false)
runOptions: {}, // extra axe `run` options merged over the defaults
83
+
},
84
+
})
85
+
```
86
+
48
87
## Run the demo
49
88
50
89
The demo serves an intentionally-broken host page and the panel from **one
@@ -74,7 +113,7 @@ pnpm -C plugins/a11y dev # from source: same, at /__devframes_plugin_a11
74
113
| Path | Export | Purpose |
75
114
|------|--------|---------|
76
115
|`src/index.ts`|`.`|`createA11yDevframe()` + the default `DevframeDefinition`; `a11yAgentBundlePath` — the agent module a hub attaches as this dock's client script |
77
-
|`src/node/index.ts`|`/node`|`setupA11y(ctx)` — registers the RPC functions |
116
+
|`src/node/index.ts`|`/node`|`setupA11y(ctx, options?)` — registers the RPC functions with the runtime config|
78
117
|`src/cli.ts`|`/cli`|`createA11yCli()` — backs the `devframes_plugin_a11y` bin |
79
118
|`src/vite.ts`|`/vite`|`a11yVitePlugin()` — mounts the panel into a Vite host |
0 commit comments