naider 1.17.2 → 1.18.0

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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Node AI Development Environment** — A programming language simpler than Python, designed for AI-speed code generation, that transpiles to **15 languages**.
4
4
 
5
- NAIDE is built on four principles: simpler than Python (built-in functions, syntax sugar, zero boilerplate), one way to write everything (zero ambiguity), keyword-driven intent (the first token decides meaning), and minimal token count (fewer tokens = faster AI generation). Write once, compile to any target. 35+ built-in functions, syntax sugar (`unless`, `until`, `repeat`, `swap`, `is`/`isnt`, one-line functions), and 47 built-in features including servers, databases, authentication, bots, GraphQL, gRPC, WebRTC, blockchain, and more.
5
+ NAIDE is built on four principles: simpler than Python (built-in functions, syntax sugar, zero boilerplate), one way to write everything (zero ambiguity), keyword-driven intent (the first token decides meaning), and minimal token count (fewer tokens = faster AI generation). Write once, compile to any target. 40+ built-in functions, syntax sugar (`unless`, `until`, `repeat`, `swap`, `is`/`isnt`, one-line functions, `auto` type inference, destructuring, pipe operator), and 55+ built-in features including servers, databases, authentication, bots, GraphQL, gRPC, WebRTC, blockchain, and more.
6
6
 
7
7
  ### Compilation Targets
8
8
 
@@ -136,9 +136,29 @@ any data = null
136
136
 
137
137
  mut int counter = 0 # mutable (let)
138
138
  mut str label = "init"
139
+
140
+ auto x = 42 # type inferred (const)
141
+ auto msg = "hello" # compiler infers str
142
+ mut auto counter2 = 0 # type inferred (let)
139
143
  ```
140
144
 
141
- Types: `str`, `int`, `num`, `bool`, `list`, `map`, `any`, `json`, `void`
145
+ Types: `str`, `int`, `num`, `bool`, `list`, `map`, `any`, `json`, `void`, `auto` (inferred)
146
+
147
+ ### Destructuring
148
+
149
+ ```python
150
+ # Object destructuring
151
+ auto {name, age} = user
152
+ auto {name, age = 0} = user # with defaults
153
+ auto {name, ...rest} = user # with rest
154
+ mut {score, level} = gameState # mutable
155
+
156
+ # Array destructuring
157
+ auto [first, second] = items
158
+ auto [head, ...tail] = items # with rest
159
+ auto [x, y = 0] = coords # with defaults
160
+ mut [a, b] = pair # mutable
161
+ ```
142
162
 
143
163
  ### String Interpolation
144
164
 
@@ -257,6 +277,28 @@ model Admin extends User:
257
277
  ret ["read", "write", "delete"]
258
278
  ```
259
279
 
280
+ Schema inheritance with constructors and methods:
281
+
282
+ ```python
283
+ schema Animal:
284
+ id auto
285
+ name str required
286
+ species str required
287
+
288
+ schema Dog extends Animal:
289
+ breed str optional
290
+ trained bool default(false)
291
+
292
+ init(str name, str breed):
293
+ self.name = name
294
+ self.breed = breed
295
+
296
+ fn bark() -> str:
297
+ ret "Woof! I'm {self.name}"
298
+ ```
299
+
300
+ `init(params):` defines a constructor. `fn method():` defines methods. `extends` inherits all fields and methods from the parent.
301
+
260
302
  ### Pipe Operator
261
303
 
262
304
  ```python
@@ -264,8 +306,37 @@ list result = data
264
306
  |> filter((x) => x.active)
265
307
  |> map((x) => x.name)
266
308
  |> sort()
309
+
310
+ int total = items
311
+ |> filter((x) => x > 0)
312
+ |> map((x) => x * 2)
313
+ |> reduce((a, b) => a + b, 0)
267
314
  ```
268
315
 
316
+ Chain operations left to right for readable data transformations.
317
+
318
+ ### Optional Chaining & Null Coalescing
319
+
320
+ ```python
321
+ str name = user?.name # safe property access
322
+ any val = data?.nested?.value # deep safe access
323
+ str display = user?.name ?? "Anonymous" # fallback on null/undefined
324
+ int port = config?.port ?? 3000
325
+ ```
326
+
327
+ `?.` safely accesses properties (returns `undefined` if the left side is `null`/`undefined`). `??` provides a fallback value when the left side is `null` or `undefined`.
328
+
329
+ ### Spread Operator
330
+
331
+ ```python
332
+ list combined = [...listA, ...listB]
333
+ map merged = {...defaults, ...overrides}
334
+ list withExtra = [...items, 4, 5, 6]
335
+ map withDebug = {...config, debug: true}
336
+ ```
337
+
338
+ Spread arrays and objects with `...`. Works in list literals, map literals, and function arguments.
339
+
269
340
  ### Imports / Exports
270
341
 
271
342
  ```python
@@ -888,6 +959,15 @@ Variables become constants. Missing `required` vars exit with an error.
888
959
  ## Syntax Sugar (Simpler than Python)
889
960
 
890
961
  ```python
962
+ # auto — type inference
963
+ auto x = 42
964
+ auto msg = "hello"
965
+ mut auto counter = 0
966
+
967
+ # destructuring
968
+ auto {name, age} = user
969
+ auto [first, ...rest] = items
970
+
891
971
  # unless — negated if
892
972
  unless x > 10:
893
973
  log "small"
@@ -918,6 +998,16 @@ if y isnt null: log "exists"
918
998
  # one-line functions
919
999
  fn double(int x) -> int = x * 2
920
1000
 
1001
+ # pipe operator
1002
+ list result = items |> filter((x) => x > 0) |> map((x) => x * 2)
1003
+
1004
+ # optional chaining + null coalescing
1005
+ str name = user?.name ?? "Anonymous"
1006
+
1007
+ # spread
1008
+ list all = [...a, ...b]
1009
+ map merged = {...defaults, ...overrides}
1010
+
921
1011
  # print alias
922
1012
  print "hello world"
923
1013
  ```
@@ -955,6 +1045,15 @@ list flat_list = flat(nested)
955
1045
  list zipped = zip(a, b)
956
1046
  list chunks = chunk(items, 3)
957
1047
 
1048
+ # Functional ops (map/filter/reduce)
1049
+ list doubled = map(items, (x) => x * 2)
1050
+ list big = filter(items, (x) => x > 5)
1051
+ int total = reduce(items, (a, b) => a + b, 0)
1052
+ any found = find(items, (x) => x > 3)
1053
+ bool allPos = every(items, (x) => x > 0)
1054
+ bool hasNeg = some(items, (x) => x < 0)
1055
+ foreach(items, (x) => log x)
1056
+
958
1057
  # Math
959
1058
  num a = abs(-5)
960
1059
  num r = round(3.7)
package/SPEC.naide CHANGED
@@ -27,6 +27,26 @@ any data = null
27
27
  mut int counter = 0
28
28
  mut str label = "initial"
29
29
 
30
+ # auto 型推論 (コンパイラが型を推論)
31
+ auto x = 42 # const x = 42
32
+ auto msg = "hello" # const msg = "hello"
33
+ auto items = [1, 2, 3] # const items = [1, 2, 3]
34
+ mut auto counter2 = 0 # let counter2 = 0
35
+
36
+
37
+ # ---- 分割代入 (Destructuring) ----
38
+ # オブジェクト分割代入
39
+ auto {name2, age} = user
40
+ auto {name3, age2 = 0} = user # デフォルト値
41
+ auto {name4, ...rest} = user # レスト
42
+ mut {score, level} = gameState # 可変
43
+
44
+ # 配列分割代入
45
+ auto [first, second] = items
46
+ auto [head, ...tail] = items # レスト
47
+ auto [x2, y = 0] = coords # デフォルト値
48
+ mut [a3, b3] = pair # 可変
49
+
30
50
 
31
51
  # ---- 文字列補間 ----
32
52
  # ダブルクォートで {式} が自動展開
@@ -132,12 +152,29 @@ if err instanceof TypeError:
132
152
  log "type error occurred"
133
153
 
134
154
 
155
+ # ---- map/filter/reduce ビルトイン ----
156
+ # コレクション操作の組み込み関数
157
+ list doubled = map(items, (x) => x * 2)
158
+ list big = filter(items, (x) => x > 5)
159
+ int total2 = reduce(items, (a, b) => a + b, 0)
160
+ any found = find(items, (x) => x > 3)
161
+ bool allBig = every(items, (x) => x > 0)
162
+ bool hasBig = some(items, (x) => x > 10)
163
+ foreach(items, (x) => log x)
164
+
165
+
135
166
  # ---- パイプ演算子 ----
136
167
  # データ変換チェーンが読みやすい
137
168
  list result = [1, 2, 3, 4, 5]
138
169
  |> filter((x) => x > 2)
139
170
  |> map((x) => x * 10)
140
171
 
172
+ # パイプ + map/filter/reduce の組み合わせ
173
+ list names = users
174
+ |> filter((u) => u.active)
175
+ |> map((u) => u.name)
176
+ |> sort()
177
+
141
178
 
142
179
  # ---- クラス (model) ----
143
180
  model User:
@@ -159,6 +196,25 @@ model Admin extends User:
159
196
  ret ["read", "write", "delete"]
160
197
 
161
198
 
199
+ # ---- スキーマ継承 (schema extends) ----
200
+ # schema も extends で継承可能
201
+ schema Animal:
202
+ id auto
203
+ name str required
204
+ species str required
205
+
206
+ schema Dog extends Animal:
207
+ breed str optional
208
+ trained bool default(false)
209
+
210
+ init(str name, str breed):
211
+ self.name = name
212
+ self.breed = breed
213
+
214
+ fn bark() -> str:
215
+ ret "Woof! I'm {self.name}"
216
+
217
+
162
218
  # ---- データベース永続化 ----
163
219
  # db ディレクトリパス → スキーマストアがJSONファイルに自動保存
164
220
  db "data/"
@@ -436,7 +492,15 @@ pub str VERSION = "1.0.0"
436
492
 
437
493
 
438
494
  # ---- null安全 ----
495
+ # オプショナルチェーニング (?.)
439
496
  any val = data?.nested?.value ?? "default"
497
+ str userName = user?.name
498
+ any first = items?.[0]
499
+ any result2 = obj?.method?.()
500
+
501
+ # Null合体演算子 (??)
502
+ str displayName = user?.name ?? "Anonymous"
503
+ int port = config?.port ?? 3000
440
504
 
441
505
 
442
506
  # ---- await.all (Promise.all) ----
@@ -446,6 +510,8 @@ any val = data?.nested?.value ?? "default"
446
510
  # ---- スプレッド ----
447
511
  list combined = [...items, 4, 5, 6]
448
512
  map merged = {...config, debug: true}
513
+ list all = [...listA, ...listB]
514
+ map full = {...defaults, ...overrides}
449
515
 
450
516
 
451
517
  # ---- ページ生成 (HTML) ----
package/assets/naide.ico CHANGED
Binary file
Binary file
package/assets/nx.ico CHANGED
Binary file
Binary file
@@ -1,13 +1,62 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { writeFileSync } from 'fs';
3
+ import { writeFileSync, mkdirSync } from 'fs';
4
4
  import { resolve, dirname } from 'path';
5
5
  import { fileURLToPath } from 'url';
6
+ import zlib from 'zlib';
6
7
 
7
8
  const __dirname = dirname(fileURLToPath(import.meta.url));
8
9
 
10
+ function createPNG(width, height, pixels) {
11
+ const signature = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
12
+
13
+ function makeChunk(type, data) {
14
+ const buf = Buffer.alloc(4 + type.length + data.length + 4);
15
+ buf.writeUInt32BE(data.length, 0);
16
+ buf.write(type, 4);
17
+ data.copy(buf, 4 + type.length);
18
+ const crc = crc32(buf.slice(4, 4 + type.length + data.length));
19
+ buf.writeUInt32BE(crc, buf.length - 4);
20
+ return buf;
21
+ }
22
+
23
+ const ihdr = Buffer.alloc(13);
24
+ ihdr.writeUInt32BE(width, 0);
25
+ ihdr.writeUInt32BE(height, 4);
26
+ ihdr[8] = 8;
27
+ ihdr[9] = 6;
28
+ ihdr[10] = 0;
29
+ ihdr[11] = 0;
30
+ ihdr[12] = 0;
31
+
32
+ const rawData = Buffer.alloc(height * (1 + width * 4));
33
+ for (let y = 0; y < height; y++) {
34
+ rawData[y * (1 + width * 4)] = 0;
35
+ for (let x = 0; x < width; x++) {
36
+ const si = (y * width + x) * 4;
37
+ const di = y * (1 + width * 4) + 1 + x * 4;
38
+ rawData[di + 0] = pixels[si + 0];
39
+ rawData[di + 1] = pixels[si + 1];
40
+ rawData[di + 2] = pixels[si + 2];
41
+ rawData[di + 3] = pixels[si + 3];
42
+ }
43
+ }
44
+ const compressed = zlib.deflateSync(rawData);
45
+
46
+ const ihdrChunk = makeChunk('IHDR', ihdr);
47
+ const idatChunk = makeChunk('IDAT', compressed);
48
+ const iendChunk = makeChunk('IEND', Buffer.alloc(0));
49
+
50
+ return Buffer.concat([signature, ihdrChunk, idatChunk, iendChunk]);
51
+ }
52
+
9
53
  function createICO(sizes, renderFn) {
10
- const images = sizes.map(s => createBMPImage(s, renderFn));
54
+ const images = sizes.map(s => {
55
+ const pixels = new Uint8Array(s * s * 4);
56
+ renderFn(pixels, s);
57
+ return { size: s, data: createPNG(s, s, pixels) };
58
+ });
59
+
11
60
  const headerSize = 6 + images.length * 16;
12
61
  let offset = headerSize;
13
62
 
@@ -34,175 +83,155 @@ function createICO(sizes, renderFn) {
34
83
  return Buffer.concat([header, ...entries, ...images.map(i => i.data)]);
35
84
  }
36
85
 
37
- function createBMPImage(size, renderFn) {
38
- const pixels = new Uint8Array(size * size * 4);
39
- renderFn(pixels, size);
40
-
41
- const rowSize = size * 4;
42
- const andRowSize = Math.ceil(size / 32) * 4;
43
- const bmpInfoSize = 40;
44
- const pixelDataSize = rowSize * size;
45
- const andMaskSize = andRowSize * size;
46
- const totalSize = bmpInfoSize + pixelDataSize + andMaskSize;
47
-
48
- const buf = Buffer.alloc(totalSize);
49
-
50
- buf.writeUInt32LE(40, 0);
51
- buf.writeInt32LE(size, 4);
52
- buf.writeInt32LE(size * 2, 8);
53
- buf.writeUInt16LE(1, 12);
54
- buf.writeUInt16LE(32, 14);
55
- buf.writeUInt32LE(0, 16);
56
- buf.writeUInt32LE(pixelDataSize + andMaskSize, 20);
57
- buf.writeInt32LE(0, 24);
58
- buf.writeInt32LE(0, 28);
59
- buf.writeUInt32LE(0, 32);
60
- buf.writeUInt32LE(0, 36);
61
-
62
- for (let y = 0; y < size; y++) {
63
- const srcRow = (size - 1 - y) * size * 4;
64
- const dstRow = bmpInfoSize + y * rowSize;
65
- for (let x = 0; x < size; x++) {
66
- const si = srcRow + x * 4;
67
- const di = dstRow + x * 4;
68
- buf[di + 0] = pixels[si + 2];
69
- buf[di + 1] = pixels[si + 1];
70
- buf[di + 2] = pixels[si + 0];
71
- buf[di + 3] = pixels[si + 3];
72
- }
73
- }
74
-
75
- const andOffset = bmpInfoSize + pixelDataSize;
76
- for (let y = 0; y < size; y++) {
77
- const srcRow = (size - 1 - y) * size * 4;
78
- for (let x = 0; x < size; x++) {
79
- const alpha = pixels[srcRow + x * 4 + 3];
80
- if (alpha < 128) {
81
- const byteIdx = andOffset + y * andRowSize + Math.floor(x / 8);
82
- buf[byteIdx] |= (0x80 >> (x % 8));
83
- }
84
- }
85
- }
86
-
87
- return { size, data: buf };
86
+ const crcTable = new Uint32Array(256);
87
+ for (let n = 0; n < 256; n++) {
88
+ let c = n;
89
+ for (let k = 0; k < 8; k++) c = (c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1);
90
+ crcTable[n] = c;
91
+ }
92
+ function crc32(buf) {
93
+ let crc = 0xFFFFFFFF;
94
+ for (let i = 0; i < buf.length; i++) crc = crcTable[(crc ^ buf[i]) & 0xFF] ^ (crc >>> 8);
95
+ return (crc ^ 0xFFFFFFFF) >>> 0;
88
96
  }
89
97
 
90
98
  function setPixel(pixels, size, x, y, r, g, b, a = 255) {
91
99
  if (x < 0 || x >= size || y < 0 || y >= size) return;
92
100
  const i = (y * size + x) * 4;
93
- if (a < 255 && pixels[i + 3] > 0) {
94
- const sa = a / 255;
95
- const da = 1 - sa;
96
- pixels[i + 0] = Math.round(r * sa + pixels[i + 0] * da);
97
- pixels[i + 1] = Math.round(g * sa + pixels[i + 1] * da);
98
- pixels[i + 2] = Math.round(b * sa + pixels[i + 2] * da);
99
- pixels[i + 3] = 255;
100
- } else {
101
- pixels[i + 0] = r;
102
- pixels[i + 1] = g;
103
- pixels[i + 2] = b;
104
- pixels[i + 3] = a;
101
+ const sa = a / 255;
102
+ const da = (pixels[i + 3] / 255) * (1 - sa);
103
+ const oa = sa + da;
104
+ if (oa > 0) {
105
+ pixels[i + 0] = Math.round((r * sa + pixels[i + 0] * da) / oa);
106
+ pixels[i + 1] = Math.round((g * sa + pixels[i + 1] * da) / oa);
107
+ pixels[i + 2] = Math.round((b * sa + pixels[i + 2] * da) / oa);
108
+ pixels[i + 3] = Math.round(oa * 255);
105
109
  }
106
110
  }
107
111
 
108
- function fillRect(pixels, size, x0, y0, w, h, r, g, b, a = 255) {
109
- for (let y = y0; y < y0 + h; y++)
110
- for (let x = x0; x < x0 + w; x++)
111
- setPixel(pixels, size, x, y, r, g, b, a);
112
+ function fillRect(p, s, x0, y0, w, h, r, g, b, a = 255) {
113
+ for (let y = y0; y < y0 + h && y < s; y++)
114
+ for (let x = x0; x < x0 + w && x < s; x++)
115
+ setPixel(p, s, x, y, r, g, b, a);
112
116
  }
113
117
 
114
- function fillRoundRect(pixels, size, x0, y0, w, h, radius, r, g, b, a = 255) {
118
+ function fillCircle(p, s, cx, cy, radius, r, g, b, a = 255) {
119
+ const r2 = radius * radius;
120
+ for (let y = Math.floor(cy - radius); y <= Math.ceil(cy + radius); y++) {
121
+ for (let x = Math.floor(cx - radius); x <= Math.ceil(cx + radius); x++) {
122
+ const dx = x - cx + 0.5, dy = y - cy + 0.5;
123
+ const d2 = dx * dx + dy * dy;
124
+ if (d2 <= r2) {
125
+ const edge = Math.max(0, Math.min(1, (radius - Math.sqrt(d2)) * 1.5));
126
+ setPixel(p, s, x, y, r, g, b, Math.round(a * edge));
127
+ }
128
+ }
129
+ }
130
+ }
131
+
132
+ function fillRoundRect(p, s, x0, y0, w, h, rad, r, g, b, a = 255) {
115
133
  for (let y = y0; y < y0 + h; y++) {
116
134
  for (let x = x0; x < x0 + w; x++) {
117
- let inside = true;
118
- const corners = [
119
- [x0 + radius, y0 + radius],
120
- [x0 + w - radius - 1, y0 + radius],
121
- [x0 + radius, y0 + h - radius - 1],
122
- [x0 + w - radius - 1, y0 + h - radius - 1],
123
- ];
124
- for (const [cx, cy] of corners) {
125
- const inCornerX = (x < x0 + radius && cx === corners[0][0]) || (x > x0 + w - radius - 1 && cx === corners[1][0]);
126
- const inCornerY = (y < y0 + radius && cy === corners[0][1]) || (y > y0 + h - radius - 1 && cy === corners[2][1]);
127
- if (inCornerX && inCornerY) {
128
- const dx = x - cx;
129
- const dy = y - cy;
130
- if (dx * dx + dy * dy > radius * radius) {
131
- inside = false;
132
- break;
133
- }
134
- }
135
+ let draw = true;
136
+ if (x < x0 + rad && y < y0 + rad) {
137
+ const dx = x - (x0 + rad), dy = y - (y0 + rad);
138
+ if (dx * dx + dy * dy > rad * rad) draw = false;
139
+ } else if (x >= x0 + w - rad && y < y0 + rad) {
140
+ const dx = x - (x0 + w - rad - 1), dy = y - (y0 + rad);
141
+ if (dx * dx + dy * dy > rad * rad) draw = false;
142
+ } else if (x < x0 + rad && y >= y0 + h - rad) {
143
+ const dx = x - (x0 + rad), dy = y - (y0 + h - rad - 1);
144
+ if (dx * dx + dy * dy > rad * rad) draw = false;
145
+ } else if (x >= x0 + w - rad && y >= y0 + h - rad) {
146
+ const dx = x - (x0 + w - rad - 1), dy = y - (y0 + h - rad - 1);
147
+ if (dx * dx + dy * dy > rad * rad) draw = false;
135
148
  }
136
- if (inside) setPixel(pixels, size, x, y, r, g, b, a);
149
+ if (draw) setPixel(p, s, x, y, r, g, b, a);
137
150
  }
138
151
  }
139
152
  }
140
153
 
141
- const GLYPH_N = [
142
- [1,0,0,0,1],
143
- [1,1,0,0,1],
144
- [1,0,1,0,1],
145
- [1,0,0,1,1],
146
- [1,0,0,0,1],
147
- ];
148
-
149
- const GLYPH_X = [
150
- [1,0,0,0,1],
151
- [0,1,0,1,0],
152
- [0,0,1,0,0],
153
- [0,1,0,1,0],
154
- [1,0,0,0,1],
155
- ];
156
-
157
- function drawGlyph(pixels, size, glyph, ox, oy, scale, r, g, b) {
158
- for (let gy = 0; gy < glyph.length; gy++) {
159
- for (let gx = 0; gx < glyph[gy].length; gx++) {
160
- if (glyph[gy][gx]) {
161
- fillRect(pixels, size, ox + gx * scale, oy + gy * scale, scale, scale, r, g, b);
154
+ function distToSegment(px, py, ax, ay, bx, by) {
155
+ const dx = bx - ax, dy = by - ay;
156
+ const len2 = dx * dx + dy * dy;
157
+ if (len2 === 0) return Math.hypot(px - ax, py - ay);
158
+ const t = Math.max(0, Math.min(1, ((px - ax) * dx + (py - ay) * dy) / len2));
159
+ return Math.hypot(px - (ax + t * dx), py - (ay + t * dy));
160
+ }
161
+
162
+ function drawSmooth(p, s, segments, ox, oy, scale, r, g, b) {
163
+ const thick = scale * 0.22;
164
+ const x0 = Math.floor(ox - thick - 1), y0 = Math.floor(oy - thick - 1);
165
+ const x1 = Math.ceil(ox + scale + thick + 1), y1 = Math.ceil(oy + scale + thick + 1);
166
+ for (let y = Math.max(0, y0); y < Math.min(s, y1); y++) {
167
+ for (let x = Math.max(0, x0); x < Math.min(s, x1); x++) {
168
+ let minD = Infinity;
169
+ for (const seg of segments) {
170
+ const d = distToSegment(x + 0.5, y + 0.5,
171
+ ox + seg[0] * scale, oy + seg[1] * scale,
172
+ ox + seg[2] * scale, oy + seg[3] * scale);
173
+ if (d < minD) minD = d;
174
+ }
175
+ if (minD < thick + 1) {
176
+ const alpha = Math.max(0, Math.min(1, (thick + 0.8 - minD) / 1.2));
177
+ setPixel(p, s, x, y, r, g, b, Math.round(255 * alpha));
162
178
  }
163
179
  }
164
180
  }
165
181
  }
166
182
 
183
+ function drawLetterN(p, s, cx, cy, h, r, g, b) {
184
+ const w = h * 0.7;
185
+ const x0 = cx - w / 2, y0 = cy - h / 2;
186
+ const segments = [
187
+ [0, 0, 0, 1],
188
+ [1, 0, 1, 1],
189
+ [0, 0, 1, 1],
190
+ ];
191
+ drawSmooth(p, s, segments, x0, y0, h, r, g, b);
192
+ const extra = h * 0.22;
193
+ drawSmooth(p, s, [[0, 0, 0, 1], [1, 0, 1, 1], [0, 0, 1, 1]], x0, y0, h, r, g, b);
194
+ }
195
+
196
+ function drawLetterX(p, s, cx, cy, h, r, g, b) {
197
+ const segments = [
198
+ [0, 0, 1, 1],
199
+ [1, 0, 0, 1],
200
+ ];
201
+ const x0 = cx - h * 0.35, y0 = cy - h / 2;
202
+ drawSmooth(p, s, segments, x0, y0, h, r, g, b);
203
+ }
204
+
167
205
  function renderNaideIcon(pixels, size) {
168
206
  const s = size;
169
- const r = Math.max(2, Math.round(s * 0.15));
170
- fillRoundRect(pixels, s, 0, 0, s, s, r, 30, 110, 230);
171
- fillRoundRect(pixels, s, 1, 1, s - 2, s - 2, r, 40, 130, 255);
172
-
173
- const glyphScale = Math.max(1, Math.round(s / 10));
174
- const gw = 5 * glyphScale;
175
- const gh = 5 * glyphScale;
176
- const ox = Math.round((s - gw) / 2);
177
- const oy = Math.round((s - gh) / 2);
178
- drawGlyph(pixels, s, GLYPH_N, ox, oy, glyphScale, 255, 255, 255);
207
+ const pad = Math.max(1, Math.round(s * 0.08));
208
+ const rad = Math.max(3, Math.round(s * 0.22));
209
+
210
+ fillRoundRect(pixels, s, 0, 0, s, s, rad, 35, 70, 150);
211
+ fillRoundRect(pixels, s, pad, pad, s - pad * 2, s - pad * 2, Math.max(2, rad - 2), 55, 110, 210);
212
+
213
+ const letterH = Math.round(s * 0.5);
214
+ drawLetterN(pixels, s, Math.round(s / 2), Math.round(s * 0.46), letterH, 255, 255, 255);
179
215
  }
180
216
 
181
217
  function renderNxIcon(pixels, size) {
182
218
  const s = size;
183
- const r = Math.max(2, Math.round(s * 0.15));
184
- fillRoundRect(pixels, s, 0, 0, s, s, r, 20, 170, 80);
185
- fillRoundRect(pixels, s, 1, 1, s - 2, s - 2, r, 30, 200, 100);
186
-
187
- const glyphScale = Math.max(1, Math.round(s / 10));
188
- const gw = 5 * glyphScale;
189
- const gh = 5 * glyphScale;
190
- const ox = Math.round((s - gw) / 2);
191
- const oy = Math.round((s - gh) / 2);
192
- drawGlyph(pixels, s, GLYPH_X, ox, oy, glyphScale, 255, 255, 255);
193
- }
219
+ const pad = Math.max(1, Math.round(s * 0.08));
220
+ const rad = Math.max(3, Math.round(s * 0.22));
194
221
 
195
- const naideIco = createICO([16, 32, 48, 64], renderNaideIcon);
196
- const nxIco = createICO([16, 32, 48, 64], renderNxIcon);
222
+ fillRoundRect(pixels, s, 0, 0, s, s, rad, 25, 110, 60);
223
+ fillRoundRect(pixels, s, pad, pad, s - pad * 2, s - pad * 2, Math.max(2, rad - 2), 45, 160, 90);
197
224
 
198
- const naideOut = resolve(__dirname, '..', 'assets', 'naide.ico');
199
- const nxOut = resolve(__dirname, '..', 'assets', 'nx.ico');
225
+ const letterH = Math.round(s * 0.5);
226
+ drawLetterX(pixels, s, Math.round(s / 2), Math.round(s * 0.46), letterH, 255, 255, 255);
227
+ }
200
228
 
201
- import { mkdirSync } from 'fs';
202
229
  mkdirSync(resolve(__dirname, '..', 'assets'), { recursive: true });
203
230
 
204
- writeFileSync(naideOut, naideIco);
205
- writeFileSync(nxOut, nxIco);
231
+ const naideIco = createICO([16, 32, 48, 256], renderNaideIcon);
232
+ const nxIco = createICO([16, 32, 48, 256], renderNxIcon);
233
+
234
+ writeFileSync(resolve(__dirname, '..', 'assets', 'naide.ico'), naideIco);
235
+ writeFileSync(resolve(__dirname, '..', 'assets', 'nx.ico'), nxIco);
206
236
 
207
- console.log(`Generated: ${naideOut}`);
208
- console.log(`Generated: ${nxOut}`);
237
+ console.log('Icons generated successfully.');
@@ -39,10 +39,10 @@ function registerWindows() {
39
39
  regAdd('HKCU\\Software\\Classes\\NAIDEXFile\\shell\\open\\command', cmd);
40
40
 
41
41
  const assetsDir = resolve(__dirname, '..', 'assets');
42
- const naideIco = resolve(assetsDir, 'naide.ico').replace(/\\/g, '\\\\');
43
- const nxIco = resolve(assetsDir, 'nx.ico').replace(/\\/g, '\\\\');
44
- run(`reg add "HKCU\\Software\\Classes\\NAIDEFile\\DefaultIcon" /ve /d "${naideIco}" /f`);
45
- run(`reg add "HKCU\\Software\\Classes\\NAIDEXFile\\DefaultIcon" /ve /d "${nxIco}" /f`);
42
+ const naideIco = resolve(assetsDir, 'naide.ico');
43
+ const nxIco = resolve(assetsDir, 'nx.ico');
44
+ regAdd('HKCU\\Software\\Classes\\NAIDEFile\\DefaultIcon', naideIco);
45
+ regAdd('HKCU\\Software\\Classes\\NAIDEXFile\\DefaultIcon', nxIco);
46
46
 
47
47
  console.log(' .naide and .nx file associations registered (Windows)');
48
48
  }