novac 2.2.0 → 2.2.2

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.
Files changed (122) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +0 -0
  3. package/bin/novac +6 -3
  4. package/bin/nvc +0 -0
  5. package/bin/nvml +0 -0
  6. package/demo.nv +0 -0
  7. package/demo_builtins.nv +0 -0
  8. package/demo_http.nv +0 -0
  9. package/examples/bf.nv +5 -13
  10. package/examples/math.nv +2 -2
  11. package/kits/kitffmpeg/kitdef.js +1174 -0
  12. package/kits/libos/kitdef.js +3135 -0
  13. package/kits/libtasker/kitdef.js +125 -0
  14. package/package.json +1 -1
  15. package/scripts/update-bin.js +0 -0
  16. package/src/core/executor.js +7 -4
  17. package/src/core/lexer.js +2 -2
  18. package/src/index.js +0 -0
  19. package/novac/LICENSE +0 -21
  20. package/novac/README.md +0 -1823
  21. package/novac/bin/novac +0 -950
  22. package/novac/bin/nvc +0 -522
  23. package/novac/bin/nvml +0 -542
  24. package/novac/demo.nv +0 -245
  25. package/novac/demo_builtins.nv +0 -209
  26. package/novac/demo_http.nv +0 -62
  27. package/novac/examples/bf.nv +0 -69
  28. package/novac/examples/math.nv +0 -21
  29. package/novac/kits/kitai/kitdef.js +0 -2185
  30. package/novac/kits/kitansi/kitdef.js +0 -1402
  31. package/novac/kits/kitformat/kitdef.js +0 -1485
  32. package/novac/kits/kitgps/kitdef.js +0 -1862
  33. package/novac/kits/kitlibfs/kitdef.js +0 -231
  34. package/novac/kits/kitlibproc/kitdef.js +0 -78
  35. package/novac/kits/kitmatrix/ex.js +0 -19
  36. package/novac/kits/kitmatrix/kitdef.js +0 -960
  37. package/novac/kits/kitmpatch/kitdef.js +0 -906
  38. package/novac/kits/kitnovacweb/README.md +0 -1572
  39. package/novac/kits/kitnovacweb/demo.nv +0 -12
  40. package/novac/kits/kitnovacweb/demo.nvml +0 -71
  41. package/novac/kits/kitnovacweb/index.nova +0 -12
  42. package/novac/kits/kitnovacweb/kitdef.js +0 -692
  43. package/novac/kits/kitnovacweb/nova.kit.json +0 -8
  44. package/novac/kits/kitnovacweb/nvml/executor.js +0 -739
  45. package/novac/kits/kitnovacweb/nvml/index.js +0 -67
  46. package/novac/kits/kitnovacweb/nvml/lexer.js +0 -263
  47. package/novac/kits/kitnovacweb/nvml/parser.js +0 -508
  48. package/novac/kits/kitnovacweb/nvml/renderer.js +0 -924
  49. package/novac/kits/kitparse/kitdef.js +0 -1688
  50. package/novac/kits/kitregex++/kitdef.js +0 -1353
  51. package/novac/kits/kitrequire/kitdef.js +0 -1599
  52. package/novac/kits/kitx11/kitdef.js +0 -1
  53. package/novac/kits/kitx11/kitx11.js +0 -2472
  54. package/novac/kits/kitx11/kitx11_conn.js +0 -948
  55. package/novac/kits/kitx11/kitx11_worker.js +0 -121
  56. package/novac/kits/libtea/tf.js +0 -2691
  57. package/novac/kits/libterm/ex.js +0 -285
  58. package/novac/kits/libterm/kitdef.js +0 -1927
  59. package/novac/node_modules/chalk/license +0 -9
  60. package/novac/node_modules/chalk/package.json +0 -83
  61. package/novac/node_modules/chalk/readme.md +0 -297
  62. package/novac/node_modules/chalk/source/index.d.ts +0 -325
  63. package/novac/node_modules/chalk/source/index.js +0 -225
  64. package/novac/node_modules/chalk/source/utilities.js +0 -33
  65. package/novac/node_modules/chalk/source/vendor/ansi-styles/index.d.ts +0 -236
  66. package/novac/node_modules/chalk/source/vendor/ansi-styles/index.js +0 -223
  67. package/novac/node_modules/chalk/source/vendor/supports-color/browser.d.ts +0 -1
  68. package/novac/node_modules/chalk/source/vendor/supports-color/browser.js +0 -34
  69. package/novac/node_modules/chalk/source/vendor/supports-color/index.d.ts +0 -55
  70. package/novac/node_modules/chalk/source/vendor/supports-color/index.js +0 -190
  71. package/novac/node_modules/commander/LICENSE +0 -22
  72. package/novac/node_modules/commander/Readme.md +0 -1176
  73. package/novac/node_modules/commander/esm.mjs +0 -16
  74. package/novac/node_modules/commander/index.js +0 -24
  75. package/novac/node_modules/commander/lib/argument.js +0 -150
  76. package/novac/node_modules/commander/lib/command.js +0 -2777
  77. package/novac/node_modules/commander/lib/error.js +0 -39
  78. package/novac/node_modules/commander/lib/help.js +0 -747
  79. package/novac/node_modules/commander/lib/option.js +0 -380
  80. package/novac/node_modules/commander/lib/suggestSimilar.js +0 -101
  81. package/novac/node_modules/commander/package-support.json +0 -19
  82. package/novac/node_modules/commander/package.json +0 -82
  83. package/novac/node_modules/commander/typings/esm.d.mts +0 -3
  84. package/novac/node_modules/commander/typings/index.d.ts +0 -1113
  85. package/novac/node_modules/node-addon-api/LICENSE.md +0 -9
  86. package/novac/node_modules/node-addon-api/README.md +0 -95
  87. package/novac/node_modules/node-addon-api/common.gypi +0 -21
  88. package/novac/node_modules/node-addon-api/except.gypi +0 -25
  89. package/novac/node_modules/node-addon-api/index.js +0 -14
  90. package/novac/node_modules/node-addon-api/napi-inl.deprecated.h +0 -186
  91. package/novac/node_modules/node-addon-api/napi-inl.h +0 -7165
  92. package/novac/node_modules/node-addon-api/napi.h +0 -3364
  93. package/novac/node_modules/node-addon-api/node_addon_api.gyp +0 -42
  94. package/novac/node_modules/node-addon-api/node_api.gyp +0 -9
  95. package/novac/node_modules/node-addon-api/noexcept.gypi +0 -26
  96. package/novac/node_modules/node-addon-api/nothing.c +0 -0
  97. package/novac/node_modules/node-addon-api/package-support.json +0 -21
  98. package/novac/node_modules/node-addon-api/package.json +0 -480
  99. package/novac/node_modules/node-addon-api/tools/README.md +0 -73
  100. package/novac/node_modules/node-addon-api/tools/check-napi.js +0 -99
  101. package/novac/node_modules/node-addon-api/tools/clang-format.js +0 -71
  102. package/novac/node_modules/node-addon-api/tools/conversion.js +0 -301
  103. package/novac/node_modules/serialize-javascript/LICENSE +0 -27
  104. package/novac/node_modules/serialize-javascript/README.md +0 -149
  105. package/novac/node_modules/serialize-javascript/index.js +0 -297
  106. package/novac/node_modules/serialize-javascript/package.json +0 -33
  107. package/novac/package.json +0 -27
  108. package/novac/scripts/update-bin.js +0 -24
  109. package/novac/src/core/bstd.js +0 -1035
  110. package/novac/src/core/config.js +0 -155
  111. package/novac/src/core/describe.js +0 -187
  112. package/novac/src/core/emitter.js +0 -499
  113. package/novac/src/core/error.js +0 -86
  114. package/novac/src/core/executor.js +0 -5606
  115. package/novac/src/core/formatter.js +0 -686
  116. package/novac/src/core/lexer.js +0 -1026
  117. package/novac/src/core/nova_builtins.js +0 -717
  118. package/novac/src/core/nova_thread_worker.js +0 -166
  119. package/novac/src/core/parser.js +0 -2181
  120. package/novac/src/core/types.js +0 -112
  121. package/novac/src/index.js +0 -28
  122. package/novac/src/runtime/stdlib.js +0 -244
@@ -1,112 +0,0 @@
1
- class NovaValue {
2
- constructor(inner) { this.inner = inner; }
3
- get type() { return this.constructor.name; }
4
- valueOf() { return this.inner?.valueOf?.() ?? this.inner; }
5
- toString() { return String(this.valueOf()); }
6
- }
7
- class NovaNumber extends NovaValue { constructor(n) { super(Number(n)); } }
8
- class NovaString extends NovaValue { constructor(s) { super(String(s)); } }
9
- class NovaBool extends NovaValue { constructor(b) { super(!!b); } }
10
- class NovaNull extends NovaValue { constructor() { super(null); } toString() { return 'null'; } valueOf() { return null; } }
11
- class NovaFunction extends NovaValue {
12
- constructor(fn, scope=null, args=[]) { super(fn); this.scope=scope; this.args=args; }
13
- call(thisArg, ...args) {
14
- if (typeof this.inner === 'function') return this.inner.apply(thisArg, args);
15
- }
16
- }
17
- class NovaTemplateString extends NovaValue {
18
- constructor(parts=[]) { super(parts.join('')); this.parts=parts; }
19
- }
20
- class NovaPointer extends NovaValue {
21
- constructor(value, readFn=null, writeFn=null, address=null) {
22
- super(value); this.readFn=readFn; this.writeFn=writeFn; this.address=address??Symbol('ptr');
23
- }
24
- read() { return this.readFn ? this.readFn(this.valueOf()) : this.valueOf(); }
25
- write(v) { if (this.writeFn) this.writeFn(v, this.address); this.inner=v; }
26
- toString(){ return '<Pointer@' + this.address.toString().slice(7,13) + '=' + this.inner + '>'; }
27
- }
28
- // Symbol used to attach a meta protocol to a NovaObject
29
- const NOVA_META = Symbol('NOVA_META');
30
-
31
- class NovaObject extends NovaValue {
32
- constructor(obj={}) { super(obj); }
33
-
34
- // Attach a meta descriptor: { get(k), set(k,v), missing(k) }
35
- attachMeta(meta) { this[NOVA_META] = meta; }
36
-
37
- get(k) {
38
- const m = this[NOVA_META];
39
- if (m) {
40
- // If key exists, use meta.get if defined
41
- if (k in this.inner) {
42
- if (m.get) return m.get(k, this.inner[k]);
43
- return this.inner[k];
44
- }
45
- // Key missing — use meta.missing
46
- if (m.missing) return m.missing(k);
47
- return undefined;
48
- }
49
- return this.inner[k];
50
- }
51
-
52
- set(k, v) {
53
- const m = this[NOVA_META];
54
- if (m && m.set) { m.set(k, v, this.inner); return; }
55
- this.inner[k] = v;
56
- }
57
-
58
- delete(k) { delete this.inner[k]; }
59
- keys() { return Object.keys(this.inner); }
60
- values() { return Object.values(this.inner); }
61
- entries() { return Object.entries(this.inner); }
62
- has(k) { return Object.hasOwnProperty(this.inner, k); }
63
- toCallable(){ return (vals) => new NovaObject(Object.fromEntries(vals.map((v,i)=>[i,v]))); }
64
- }
65
- class NovaArray extends NovaValue {
66
- constructor(arr=[]) { super(arr); }
67
- get(i) { return this.inner[i]; }
68
- set(i,v) { this.inner[i]=v; }
69
- delete(i) { this.inner.splice(Number(i),1); }
70
- push(v) { this.inner.push(v); }
71
- get length(){ return this.inner.length; }
72
- toCallable(){ return (vals) => new NovaArray(vals); }
73
- }
74
- class NovaRange extends NovaValue {
75
- constructor(start, end, step=1) { super({start,end,step}); this.start=start; this.end=end; this.step=step; }
76
- toArray() {
77
- const arr=[];
78
- if (this.step>0) { for (let i=this.start;i<=this.end;i+=this.step) arr.push(i); }
79
- else { for (let i=this.start;i>=this.end;i+=this.step) arr.push(i); }
80
- return arr;
81
- }
82
- includes(v) { return v>=Math.min(this.start,this.end)&&v<=Math.max(this.start,this.end); }
83
- get length(){ return Math.max(0,Math.floor(Math.abs(this.end-this.start)/Math.abs(this.step))+1); }
84
- toString() { return 'Range(' + this.start + '..' + this.end + ')'; }
85
- }
86
- /** Struct instance — typed object created by a struct declaration */
87
- class NovaStruct extends NovaValue {
88
- constructor(typeName, inner={}) { super(inner); this.typeName=typeName; }
89
- get(k) { return this.inner[k]; }
90
- set(k,v) { this.inner[k]=v; }
91
- delete(k) { delete this.inner[k]; }
92
- toString() {
93
- const fields = Object.entries(this.inner).map(([k,v])=>k+': '+String(v)).join(', ');
94
- return this.typeName + ' { ' + fields + ' }';
95
- }
96
- }
97
- /** Enum value — access via .variant, .enumType, .value, .typeName */
98
- class NovaEnum extends NovaValue {
99
- constructor(typeName, variant, value=null) {
100
- super(value);
101
- this.typeName = typeName;
102
- this.variant = variant;
103
- this.enumType = typeName; // .enumType instead of .type (avoids NovaValue getter clash)
104
- }
105
- toString() { return this.typeName + '::' + this.variant; }
106
- }
107
- module.exports = {
108
- NovaValue, NovaNumber, NovaString, NovaBool, NovaNull,
109
- NovaFunction, NovaTemplateString, NovaPointer,
110
- NovaObject, NovaArray, NovaRange, NovaStruct, NovaEnum,
111
- NOVA_META,
112
- };
@@ -1,28 +0,0 @@
1
- const { Lexer } = require('./core/lexer');
2
- const { Parser } = require('./core/parser');
3
- const { Formatter } = require('./core/formatter');
4
- const { Executor, Scope, TypeRegistry } = require('./core/executor');
5
- const stdlib = require('./runtime/stdlib');
6
-
7
- function run(source, builtins) {
8
- const fullstd = { ...stdlib, ...builtins };
9
- const parser = new Parser(source);
10
- const ast = parser.parse();
11
- const executor = new Executor(source, fullstd);
12
- // Inject caller-provided builtins (e.g. document, request) directly into
13
- // globalScope so Nova scripts can reference them as top-level variables.
14
- // Without this they only land at globalScope.variables.std (as std.document)
15
- // which is not how Nova scripts address them.
16
- if (builtins) {
17
- for (const [k, v] of Object.entries(builtins)) {
18
- executor.globalScope.set(k, v);
19
- }
20
- }
21
- return executor.run(ast);
22
- }
23
-
24
- function tokenize(source) { return new Lexer(source).tokenize(); }
25
- function parse(source) { return new Parser(source).parse(); }
26
- function format(source) { return new Formatter(source).format(); }
27
-
28
- module.exports = { run, tokenize, parse, format, Lexer, Parser, Formatter, Executor, Scope, TypeRegistry };
@@ -1,244 +0,0 @@
1
- const { NovaArray, NovaObject, NovaRange, NovaBool, NovaNull } = require("../core/types");
2
-
3
- module.exports = {
4
- print: (...args) => console.log(...args),
5
-
6
- // ── Math ──
7
- Math: {
8
- abs: Math.abs, ceil: Math.ceil, floor: Math.floor,
9
- round: Math.round, sqrt: Math.sqrt, pow: Math.pow,
10
- max: Math.max, min: Math.min, log: Math.log,
11
- log2: Math.log2, log10: Math.log10,
12
- sin: Math.sin, cos: Math.cos, tan: Math.tan,
13
- PI: Math.PI, E: Math.E,
14
- trunc: Math.trunc, sign: Math.sign,
15
- random: Math.random,
16
- clamp: (v, lo, hi) => Math.min(Math.max(v, lo), hi),
17
- floorTo(a, b) { return Math.floor(a / b) * b; },
18
- ceilTo(a, b) { return Math.ceil(a / b) * b; },
19
- factorial(n) {
20
- //memo to optimize for larger n
21
- const memo = [1];
22
- function fact(x) {
23
- if (x < 0) return NaN;
24
- if (x === 0) return 1;
25
- if (memo[x] !== undefined) return memo[x];
26
- return memo[x] = x * fact(x - 1);
27
- }
28
- return fact(n);
29
- },
30
- fibonacci(n) {
31
- //memo to optimize for larger n
32
- const memo = [0, 1];
33
- function fib(x) {
34
- if (x < 0) return NaN;
35
- if (memo[x] !== undefined) return memo[x];
36
- return memo[x] = fib(x - 1) + fib(x - 2);
37
- }
38
- return fib(n);
39
- },
40
- divmod(a, b) {
41
- if (b === 0) throw new Error("Division by zero");
42
- const q = Math.floor(a / b);
43
- const r = a - q * b;
44
- return [q, r];
45
- },
46
- },
47
-
48
- // ── Array utils ──
49
- Array: {
50
- from: (it) => new NovaArray(Array.from(it instanceof NovaArray ? it.inner : (it ?? []))),
51
- of: (...args) => new NovaArray(args),
52
- range: (start, end, step = 1) => new NovaRange(start, end, step),
53
- isArray: (v) => v instanceof NovaArray || Array.isArray(v),
54
- fill: (n, val) => new NovaArray(Array(n).fill(val)),
55
- zip: (...arrs) => {
56
- const inners = arrs.map(a => a instanceof NovaArray ? a.inner : a);
57
- const len = Math.min(...inners.map(a => a.length));
58
- return new NovaArray(Array.from({ length: len }, (_, i) => new NovaArray(inners.map(a => a[i]))));
59
- },
60
- },
61
-
62
- // ── Object utils ──
63
- Object: {
64
- keys: (o) => new NovaArray(o instanceof NovaObject ? Object.keys(o.inner) : Object.keys(o)),
65
- values: (o) => new NovaArray(o instanceof NovaObject ? Object.values(o.inner) : Object.values(o)),
66
- entries: (o) => new NovaArray((o instanceof NovaObject ? Object.entries(o.inner) : Object.entries(o)).map(([k,v]) => new NovaArray([k,v]))),
67
- assign: (target, ...sources) => {
68
- const t = target instanceof NovaObject ? target.inner : target;
69
- for (const s of sources) Object.assign(t, s instanceof NovaObject ? s.inner : s);
70
- return target;
71
- },
72
- freeze: (o) => { Object.freeze(o instanceof NovaObject ? o.inner : o); return o; },
73
- has: (o, k) => o instanceof NovaObject ? k in o.inner : (k in (o ?? {})),
74
- create: (proto) => new NovaObject(Object.create(proto instanceof NovaObject ? proto.inner : proto)),
75
- },
76
-
77
- // ── String utils ──
78
- String: {
79
- from: (v) => String(v),
80
- padStart: (s, n, ch = " ") => String(s).padStart(n, ch),
81
- padEnd: (s, n, ch = " ") => String(s).padEnd(n, ch),
82
- repeat: (s, n) => String(s).repeat(n),
83
- includes: (s, sub) => String(s).includes(sub),
84
- startsWith: (s, sub) => String(s).startsWith(sub),
85
- endsWith: (s, sub) => String(s).endsWith(sub),
86
- trim: (s) => String(s).trim(),
87
- split: (s, sep) => new NovaArray(String(s).split(sep)),
88
- replace: (s, from, to) => String(s).replace(from, to),
89
- replaceAll: (s, from, to) => String(s).replaceAll(from, to),
90
- toUpper: (s) => String(s).toUpperCase(),
91
- toLower: (s) => String(s).toLowerCase(),
92
- charAt: (s, i) => String(s).charAt(i),
93
- charCodeAt: (s, i) => String(s).charCodeAt(i),
94
- fromCharCode: (...codes) => String.fromCharCode(...codes),
95
- slice: (s, a, b) => String(s).slice(a, b),
96
- indexOf: (s, sub) => String(s).indexOf(sub),
97
- },
98
-
99
- // ── Type checks ──
100
- is: {
101
- number: (v) => typeof v === "number",
102
- string: (v) => typeof v === "string",
103
- bool: (v) => typeof v === "boolean" || v instanceof NovaBool,
104
- array: (v) => v instanceof NovaArray || Array.isArray(v),
105
- object: (v) => v instanceof NovaObject,
106
- null: (v) => v == null || v instanceof NovaNull,
107
- func: (v) => typeof v === "function" || (v?.args !== undefined && v?.body !== undefined),
108
- range: (v) => v instanceof NovaRange,
109
- integer: (v) => Number.isInteger(v),
110
- finite: (v) => Number.isFinite(v),
111
- NaN: (v) => Number.isNaN(v),
112
- },
113
-
114
- // ── Conversion ──
115
- num: (v) => Number(v),
116
- str: (v) => String(v),
117
- bool: (v) => Boolean(v),
118
- int: (v) => Math.trunc(Number(v)),
119
-
120
- // ── I/O ──
121
- console: {
122
- log: console.log,
123
- warn: console.warn,
124
- error: console.error,
125
- info: console.info,
126
- time: console.time,
127
- timeEnd: console.timeEnd,
128
- },
129
-
130
- // ── Time ──
131
- Date: {
132
- now: () => Date.now(),
133
- create: (...args) => new Date(...args),
134
- },
135
-
136
- // ── JSON ──
137
- json: {
138
- parse: (s) => JSON.parse(s),
139
- stringify: (v, sp) => JSON.stringify(v instanceof NovaObject ? v.inner : (v instanceof NovaArray ? v.inner : v), null, sp),
140
- },
141
-
142
- // ── Promise / async ──
143
- Promise: {
144
- resolve: (v) => Promise.resolve(v),
145
- reject: (v) => Promise.reject(v),
146
- all: (arr) => Promise.all(arr instanceof NovaArray ? arr.inner : arr),
147
- race: (arr) => Promise.race(arr instanceof NovaArray ? arr.inner : arr),
148
- allSettled: (arr) => Promise.allSettled(arr instanceof NovaArray ? arr.inner : arr),
149
- any: (arr) => Promise.any(arr instanceof NovaArray ? arr.inner : arr),
150
- },
151
-
152
- // ── Functional helpers ──
153
- fn: {
154
- identity: (x) => x,
155
- compose: (...fns) => (x) => fns.reduceRight((v, f) => f(v), x),
156
- pipe: (...fns) => (x) => fns.reduce((v, f) => f(v), x),
157
- memoize: (f) => { const c = new Map(); return (x) => { if (!c.has(x)) c.set(x, f(x)); return c.get(x); }; },
158
- once: (f) => { let called = false, result; return (...a) => { if (!called) { called = true; result = f(...a); } return result; }; },
159
- partial: (f, ...a) => (...b) => f(...a, ...b),
160
- curry: (f) => { const a = (args) => args.length >= f.length ? f(...args) : (...more) => a([...args, ...more]); return a([]); },
161
- noop: () => undefined,
162
- always: (x) => () => x,
163
- flip: (f) => (a, b) => f(b, a),
164
- not: (f) => (...a) => !f(...a),
165
- },
166
-
167
- // ── Errors ──
168
- error: (msg) => { throw new Error(msg); },
169
-
170
- // ── Range ──
171
- range: (start, end, step = 1) => new NovaRange(start, end, step),
172
-
173
- range: (start, end, step) => new NovaRange(start, end, step !== undefined ? step : 1),
174
-
175
- fnum: (min, max, initial) => {
176
- let v = Math.min(Math.max(initial !== undefined ? initial : min, min), max);
177
- return { get value(){ return v; }, set value(nv){ v = Math.min(Math.max(Number(nv),min),max); }, valueOf(){ return v; }, toString(){ return String(v); } };
178
- },
179
- fint: (min, max, initial) => {
180
- let v = Math.min(Math.max(Math.trunc(initial !== undefined ? initial : min), min), max);
181
- return { get value(){ return v; }, set value(nv){ v = Math.min(Math.max(Math.trunc(Number(nv)),min),max); }, valueOf(){ return v; }, toString(){ return String(v); } };
182
- },
183
- convertCase: (str, target) => {
184
- const words = String(str).replace(/([a-z])([A-Z])/g,'$1 $2').replace(/[-_]/g,' ').split(' ');
185
- const m = { snake: w=>w.join('_'), camel: w=>w.map((s,i)=>i?s[0].toUpperCase()+s.slice(1).toLowerCase():s.toLowerCase()).join(''), pascal: w=>w.map(s=>s[0].toUpperCase()+s.slice(1).toLowerCase()).join(''), kebab: w=>w.join('-'), upper: w=>str.toUpperCase(), lower: w=>str.toLowerCase() };
186
- return (m[target] || (()=>str))(words.map(s=>s.toLowerCase()));
187
- },
188
- randomWord: () => {
189
- const v = 'aeiou';
190
- const c = 'bcdfghjklmnpqrstvwxyz';
191
- const pick = a => a[Math.floor(Math.random() * a.length)];
192
- const patterns = ['CV','CVC','VC','CVV','CCV','VCC'];
193
- const makeSyllable = () => patterns[Math.floor(Math.random() * patterns.length)].split('').map(p => p === 'C' ? pick(c) : pick(v)).join('');
194
- const count = Math.floor(Math.random() * 3) + 1;
195
- return Array.from({ length: count }, () => makeSyllable()).join('');
196
- },
197
- randomName: (format, minLen = 4, maxLen = 9) => {
198
- const pick = a => a[Math.floor(Math.random() * a.length)];
199
- const consonants = ['b','c','d','f','g','h','j','k','l','m','n','p','r','s','t','v','w','z'];
200
- const consonantClusters = ['br','cr','dr','fr','gr','pr','tr','bl','cl','fl','gl','pl','sl','sc','sk','sm','sn','sp','st','str','ch','sh','th','wh','qu'];
201
- const vowels = ['a','e','i','o','u','ae','ai','au','ea','ee','ei','ie','io','oa','oe','oi','oo','ou','ui','y','ay','ey','oy'];
202
-
203
- const randomF = () => {
204
- if (Math.random() < 0.35) return pick(consonantClusters);
205
- return pick(consonants);
206
- };
207
- const randomL = () => {
208
- if (Math.random() < 0.6) return pick(vowels);
209
- return pick(['a','e','i','o','u']);
210
- };
211
- const parseFormat = str => {
212
- if (typeof str !== 'string' || !str) return null;
213
- const normalized = str.toLowerCase().trim();
214
- if (!/^[fl]+$/.test(normalized)) return null;
215
- return normalized.split('');
216
- };
217
- const makePieces = () => {
218
- const blocks = Math.floor(Math.random() * 3) + 2;
219
- const generated = [];
220
- for (let i = 0; i < blocks; i++) {
221
- const prev = generated[i - 1];
222
- generated.push(i === 0 ? 'f' : (prev === 'f' ? 'l' : 'f'));
223
- }
224
- return generated;
225
- };
226
- const buildName = pieces => pieces.map(chunk => chunk === 'f' ? randomF() : randomL()).join('');
227
- const normalizedMin = Math.max(1, Math.floor(minLen));
228
- const normalizedMax = Math.max(normalizedMin, Math.floor(maxLen));
229
- const pieces = parseFormat(format) || makePieces();
230
-
231
- let name = buildName(pieces);
232
- let attempts = 0;
233
- while ((name.length < normalizedMin || name.length > normalizedMax) && attempts < 10) {
234
- if (!parseFormat(format)) {
235
- name = buildName(makePieces());
236
- } else {
237
- name = buildName(pieces);
238
- }
239
- attempts += 1;
240
- }
241
-
242
- return name[0].toUpperCase() + name.slice(1);
243
- },
244
- };