w3c-keyname
Normalizes any KeyboardEvent into a consistent, W3C-compliant key name string across browsers.
Repository Health
Technical Analysis
w3c-keyname is a tiny JavaScript utility that produces a consistent, W3C-standard KeyboardEvent.key string from any keyboard event, even in older or inconsistent browsers. It prefers the native event.key property when trustworthy, and falls back to hard-coded keyCode-to-name lookup tables (base and shift) when the browser’s key data is missing, non-standard, or known to be wrong (Safari on macOS with Cmd+Shift held, older IE/Edge quirks).
It’s used as a low-level building block inside larger editor and UI libraries, most notably ProseMirror’s keymap plugin, wherever code needs to interpret which key was pressed without hand-rolling cross-browser branching logic around the native key event API.
What You Get
- A single keyName(event) function that returns a normalized W3C key-name string from any KeyboardEvent
- Exported base and shift keyCode-to-name lookup tables usable directly, without going through keyName
- Automatic detection and correction of known macOS Safari and legacy IE/Edge key-naming bugs
- Zero runtime dependencies, shipped as both ESM (index.js) and CJS (index.cjs) builds with TypeScript declarations
Common Use Cases
- Building a custom keymap or keyboard-shortcut system for a text editor or rich-text component
- Normalizing keyboard input handling across browsers without duplicating keyCode lookup tables
- Detecting arrow keys, function keys, or punctuation consistently in legacy-browser support code
- Powering editor keybinding matching inside ProseMirror-based editors via prosemirror-keymap
Under The Hood
Architecture w3c-keyname is architected as a single-file utility module (index.js, roughly 140 lines) rather than a layered system: two plain-object lookup tables (base and shift) are built once at module-load time via simple loops that fill in digit keys, function keys, and alphabetic keys, layered on top of a hard-coded table of punctuation and control-key codes. The one exported function, keyName(event), is a small decision tree that first checks environment flags computed at load time (a macOS check via navigator.platform, an IE check via a User-Agent regex) to decide whether the browser’s own event.key value can be trusted, falls back to indexing into shift or base by event.keyCode when it can’t, and finally patches a handful of known-bad key names before returning. There is no internal layering, dependency injection, or state beyond the two static tables — the entire architecture is data plus one branch-heavy pure function, appropriate for a single correctness-focused normalization utility with nothing else for a consumer to break by changing.
Tech Stack The package is plain, dependency-free JavaScript authored as an ES module, with hand-written ambient TypeScript declarations rather than being written in TypeScript and compiled. The only devDependency is Rollup, driven by a minimal config that bundles the ESM source down to a CommonJS build for dual-format consumption via package.json’s exports map. There is no test runner, linter, or CI configuration checked into the repository, and no bundler-specific integrations beyond the plain Rollup CJS output — the package is meant to be consumed directly by downstream bundlers rather than shipping its own build pipeline for consumers.
Code Quality No test files, test directories, or test-framework dependencies exist anywhere in the repository, and the author does not claim test coverage in the README — correctness here relies on the small, reviewable size of the lookup tables and the function itself. There is likewise no linter/formatter config or CI workflow file checked in, so style and behavior are enforced only through the author’s own review discipline, visible in the terse but consistent naming shared with his other well-known projects. Type safety is retrofitted via hand-maintained declaration files rather than the source itself being written in TypeScript, so a change to the exported shape would not be caught by a type checker unless the declarations are updated in lockstep. Error handling is essentially absent, which is reasonable for a pure, side-effect-free normalization function operating on well-formed event objects.
API Design The public API is deliberately tiny: a single keyName(event) function plus two plain-object lookup tables that can be used directly if a consumer wants the raw keyCode maps instead of the normalized function. There are no configuration options, no classes to instantiate, and no setup step — a consumer imports keyName and calls it with a native KeyboardEvent, and the TypeScript declarations make the contract explicit at the type level. This zero-ceremony surface trades flexibility for extremely low adoption friction, fitting its role as a dependency other libraries pull in internally rather than a general end-user-facing tool with its own configuration surface.
Used by 3 apps in this directory
AFFiNE
Productivity · Project Management · Note Taking
Write, draw, and plan in one infinite canvas — the open-source alternative to Notion and Miro that keeps your data yours.
Notesnook
Note Taking · File Storage · Security
End-to-end encrypted, open-source note-taking where your data stays yours — even from the server.
overleaf
Collaboration · Productivity
Open-source, real-time collaborative LaTeX editor with sandboxed compilation and full TeXLive support for self-hosted academic and research teams.