first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,62 @@
# `keyboard` — keyboard adjacency matcher
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Detects spatial walks across a physical keyboard layout (QWERTY, DVORAK,
AZERTY, or any caller-supplied adjacency graph) per Wheeler 2016 section
3.5. A password like `qwerty` traces a straight horizontal walk along the
top row; the matcher reports its length, the number of times the walker
changed direction, and how many shift-required presses it contained — all
inputs to the keyboard guess estimate in section 4.5.
## Features
- Pluggable graph map via the `graphs` option
- Counts both `turns` (direction changes) and `shiftedCount` (capital /
symbol presses)
- Default graph is QWERTY; alternative layouts ship under
`graphs/{dvorak,azerty}` subpaths
- Rejects malformed graphs (self-adjacency or asymmetric edges) via
`validateGraph` → `PWSTRENGTH.GRAPH_INVALID`
## Usage: Basic Example
```ts
import { keyboardMatch } from "@suaveplan/password-strength/matchers/keyboard";
const matches = keyboardMatch("qwerty");
console.log(matches[0]); // { graph: "qwerty", turns: 0, shiftedCount: 0, … }
```
## Usage: Advanced Example
```ts
import { keyboardMatch } from "@suaveplan/password-strength/matchers/keyboard";
import { DVORAK_GRAPH } from "@suaveplan/password-strength/graphs/dvorak";
const matches = keyboardMatch("aoeuhtns", { graphs: { dvorak: DVORAK_GRAPH } });
for (const m of matches) {
console.log(m.token, m.graph, m.turns, m.shiftedCount);
}
```
## API Reference
- `keyboardMatch(password: string, opts?: KeyboardMatchOptions): KeyboardMatch[]`
- `opts.graphs`: `Record<string, KeyboardGraph>` — override the default
QWERTY-only graph set. Each graph is validated before use.
- `KeyboardMatchOptions`: `{ graphs?: KeyboardGraphMap }`
## Implementation Notes
Each walk advances character by character; a transition is accepted iff the
target character appears in the current key's adjacency slots (six slots
per key, encoding the six surrounding keys on a staggered layout). A
direction change increments `turns`; a press whose target matches the
shifted half of the slot increments `shiftedCount`. The walk continues
greedily until the chain breaks; the matcher then restarts at the
following index. Graph validation rejects malformed graphs upfront so the
matcher never produces self-loops or asymmetric walks.