@twardoch/namzy 1.0.21 → 1.0.23
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/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/mangle.d.ts +3 -4
- package/dist/mangle.js +55 -24
- package/dist/web.d.ts +1 -1
- package/dist/web.js +1 -1
- package/dist/wordlist.d.ts +1 -0
- package/dist/wordlist.js +270 -184
- package/package.json +1 -1
- package/src/index.ts +2 -2
- package/src/mangle.ts +54 -22
- package/src/web.ts +1 -1
- package/src/wordlist.ts +271 -184
package/src/mangle.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// this_file: src/mangle.ts
|
|
2
2
|
|
|
3
|
-
import { ROTATIONS, STEMS } from "./wordlist.js";
|
|
3
|
+
import { BAD_SEAMS, ROTATIONS, STEMS } from "./wordlist.js";
|
|
4
|
+
|
|
5
|
+
const MAX_LEN = 12;
|
|
6
|
+
const MAX_TRIES = 8;
|
|
4
7
|
|
|
5
|
-
/** Seeded mulberry32 RNG — yields [0,1) floats. */
|
|
6
8
|
export function mulberry32(seed: number): () => number {
|
|
7
9
|
let s = seed >>> 0;
|
|
8
10
|
return () => {
|
|
@@ -17,35 +19,65 @@ function pick<T>(arr: readonly T[], rng: () => number): T {
|
|
|
17
19
|
return arr[Math.floor(rng() * arr.length)];
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
function hasTripleLetter(s: string): boolean {
|
|
23
|
+
for (let i = 2; i < s.length; i++) {
|
|
24
|
+
if (s[i] === s[i - 1] && s[i] === s[i - 2]) return true;
|
|
25
|
+
}
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
21
28
|
|
|
22
|
-
function
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
+
function junctionUgly(compound: string, junction: number): boolean {
|
|
30
|
+
// Inspect the 4-char window centered on the junction.
|
|
31
|
+
const start = Math.max(0, junction - 2);
|
|
32
|
+
const end = Math.min(compound.length, junction + 2);
|
|
33
|
+
const win = compound.slice(start, end);
|
|
34
|
+
for (const seam of BAD_SEAMS) {
|
|
35
|
+
if (win.includes(seam)) return true;
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
29
38
|
}
|
|
30
39
|
|
|
31
|
-
/** Apply
|
|
32
|
-
export function
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
let
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
/** Apply one rotation at a randomly chosen matching position. */
|
|
41
|
+
export function applyRotation(s: string, rng: () => number): string {
|
|
42
|
+
type Match = { i: number; src: string; dst: string };
|
|
43
|
+
const matches: Match[] = [];
|
|
44
|
+
for (let i = 0; i < s.length; i++) {
|
|
45
|
+
for (const [src, dst] of ROTATIONS) {
|
|
46
|
+
if (s.slice(i, i + src.length) === src) {
|
|
47
|
+
matches.push({ i, src, dst });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
38
50
|
}
|
|
39
|
-
return
|
|
51
|
+
if (matches.length === 0) return s;
|
|
52
|
+
const m = matches[Math.floor(rng() * matches.length)];
|
|
53
|
+
return s.slice(0, m.i) + m.dst + s.slice(m.i + m.src.length);
|
|
40
54
|
}
|
|
41
55
|
|
|
42
56
|
function capitalize(s: string): string {
|
|
43
57
|
return s.length === 0 ? s : s[0].toUpperCase() + s.slice(1);
|
|
44
58
|
}
|
|
45
59
|
|
|
46
|
-
/** Build one name
|
|
60
|
+
/** Build one name with junction validation + one rotation. */
|
|
47
61
|
export function buildName(rng: () => number): string {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
62
|
+
let best = "";
|
|
63
|
+
for (let attempt = 0; attempt < MAX_TRIES; attempt++) {
|
|
64
|
+
const a = pick(STEMS, rng);
|
|
65
|
+
const b = pick(STEMS, rng);
|
|
66
|
+
const compound = a + b;
|
|
67
|
+
if (compound.length > MAX_LEN) {
|
|
68
|
+
best = best || compound;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (hasTripleLetter(compound)) {
|
|
72
|
+
best = best || compound;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (junctionUgly(compound, a.length)) {
|
|
76
|
+
best = best || compound;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
return capitalize(applyRotation(compound, rng));
|
|
80
|
+
}
|
|
81
|
+
// All attempts had some flaw; rotate and ship the first candidate anyway.
|
|
82
|
+
return capitalize(applyRotation(best, rng));
|
|
51
83
|
}
|
package/src/web.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// this_file: src/web.ts
|
|
2
2
|
// Browser entry point — exposes namzy.generate() on window.namzy.
|
|
3
3
|
|
|
4
|
-
export { generate, generateMany,
|
|
4
|
+
export { generate, generateMany, applyRotation, buildName, mulberry32, STEMS, ROTATIONS } from "./index.js";
|
|
5
5
|
export type { NamzyOptions } from "./index.js";
|