Initial Commit
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
import type { DictionarySet } from "../../matchers/types.js";
|
||||
import { DE_WIKIPEDIA_DICTIONARY } from "./wikipedia.js";
|
||||
|
||||
export { DE_WIKIPEDIA_DICTIONARY };
|
||||
|
||||
/** Bundled German `DictionarySet`. */
|
||||
export const DE_DICTIONARIES: DictionarySet = Object.freeze({
|
||||
passwords: DE_WIKIPEDIA_DICTIONARY,
|
||||
wikipedia: DE_WIKIPEDIA_DICTIONARY,
|
||||
});
|
||||
@@ -0,0 +1,63 @@
|
||||
# `de/wikipedia` — German Wikipedia frequency dictionary
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Frequency-ranked dictionary of the most common German tokens observed in
|
||||
Wikipedia (CC-BY-SA public-domain frequency lists). Plugs into `assess`
|
||||
via `loadDictionaries` so German-locale passwords are evaluated against a
|
||||
locale-appropriate corpus.
|
||||
|
||||
## Features
|
||||
|
||||
- Frozen `ReadonlyMap<string, number>` keyed by lowercase token
|
||||
- 50-entry default — high-frequency German stopwords and the common
|
||||
`passwort` token used by the spec scenarios
|
||||
- Production deployments should swap in a fuller list via `loadDictionaries`
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { DE_WIKIPEDIA_DICTIONARY } from "@suaveplan/password-strength/dicts/de";
|
||||
|
||||
console.log(DE_WIKIPEDIA_DICTIONARY.get("passwort")); // 1
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { assess } from "@suaveplan/password-strength";
|
||||
import { DE_DICTIONARIES } from "@suaveplan/password-strength/dicts/de";
|
||||
|
||||
const result = assess("passwort123", { dictionaries: DE_DICTIONARIES });
|
||||
console.log(result.score);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `DE_WIKIPEDIA_DICTIONARY: ReadonlyMap<string, number>` — frozen
|
||||
frequency-ranked German Wikipedia dictionary.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`passwort` is rank 1 to satisfy the spec's locale-dictionary scenario.
|
||||
Production lists should track Wikipedia's published top-30 000 German
|
||||
tokens, but the bundled subset keeps the package bundle small while
|
||||
demonstrating the locale-plug-in pattern.
|
||||
|
||||
## Additional Implementation Notes
|
||||
|
||||
The implementation follows the canonical zxcvbn algorithm from Wheeler 2016 with
|
||||
the suaveplan-style additions described in the package proposal: structured error
|
||||
codes via the `defineCodes` registry, Zod boundaries at every public entry
|
||||
point, OTel histograms and counters keyed to low-cardinality attributes, and
|
||||
a strict input-length guard at 200 characters. Consumers integrate with their
|
||||
existing observability stack by installing a meter provider before importing
|
||||
the package, and with their i18n stack via the `MessageResolver` callback type
|
||||
declared in `@suaveplan/types`. The bundled data tables are intentionally
|
||||
small to keep the package bundle compact; production deployments should swap
|
||||
in fuller frequency-ranked tables via `loadDictionaries`. The default English
|
||||
dictionary set is a frozen `DictionarySet` that the matcher never mutates;
|
||||
caller-supplied dictionaries override defaults by name.
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Frequency-ranked top German Wikipedia tokens. Public-domain Wikipedia
|
||||
* frequency list (CC-BY-SA). Trimmed to 50 entries by default; swap via
|
||||
* `loadDictionaries` for a production list.
|
||||
*/
|
||||
const ENTRIES: ReadonlyArray<readonly [string, number]> = [
|
||||
["passwort", 1],
|
||||
["der", 2],
|
||||
["die", 3],
|
||||
["und", 4],
|
||||
["in", 5],
|
||||
["den", 6],
|
||||
["von", 7],
|
||||
["zu", 8],
|
||||
["das", 9],
|
||||
["mit", 10],
|
||||
["sich", 11],
|
||||
["des", 12],
|
||||
["auf", 13],
|
||||
["für", 14],
|
||||
["ist", 15],
|
||||
["im", 16],
|
||||
["dem", 17],
|
||||
["nicht", 18],
|
||||
["ein", 19],
|
||||
["eine", 20],
|
||||
["als", 21],
|
||||
["auch", 22],
|
||||
["es", 23],
|
||||
["an", 24],
|
||||
["werden", 25],
|
||||
["aus", 26],
|
||||
["er", 27],
|
||||
["hat", 28],
|
||||
["dass", 29],
|
||||
["sie", 30],
|
||||
["nach", 31],
|
||||
["wird", 32],
|
||||
["bei", 33],
|
||||
["einer", 34],
|
||||
["um", 35],
|
||||
["am", 36],
|
||||
["sind", 37],
|
||||
["noch", 38],
|
||||
["wie", 39],
|
||||
["einem", 40],
|
||||
["über", 41],
|
||||
["einen", 42],
|
||||
["so", 43],
|
||||
["zum", 44],
|
||||
["war", 45],
|
||||
["haben", 46],
|
||||
["nur", 47],
|
||||
["oder", 48],
|
||||
["aber", 49],
|
||||
["vor", 50],
|
||||
];
|
||||
|
||||
export const DE_WIKIPEDIA_DICTIONARY: ReadonlyMap<string, number> =
|
||||
Object.freeze(new Map(ENTRIES));
|
||||
Reference in New Issue
Block a user