ether-code 0.1.1 → 0.1.3

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/cli/ether.js CHANGED
@@ -2,10 +2,11 @@
2
2
 
3
3
  const fs = require('fs')
4
4
  const path = require('path')
5
+ const http = require('http')
5
6
  const { EtherCompiler } = require('./compiler')
6
7
  const { Watcher } = require('./watcher')
7
8
 
8
- const VERSION = '0.1.0'
9
+ const VERSION = '0.1.3'
9
10
 
10
11
  const COLORS = {
11
12
  reset: '\x1b[0m',
@@ -62,7 +63,7 @@ ${COLORS.bright}UTILISATION${COLORS.reset}
62
63
  ${COLORS.bright}COMMANDES${COLORS.reset}
63
64
  ${COLORS.cyan}init${COLORS.reset} Initialiser un nouveau projet Ether
64
65
  ${COLORS.cyan}build${COLORS.reset} Compiler les fichiers .eth
65
- ${COLORS.cyan}dev${COLORS.reset} Mode développement (watch + compilation auto)
66
+ ${COLORS.cyan}dev${COLORS.reset} Mode développement (serveur + watch + live reload)
66
67
  ${COLORS.cyan}check${COLORS.reset} Vérifier la syntaxe sans compiler
67
68
  ${COLORS.cyan}help${COLORS.reset} Afficher cette aide
68
69
  ${COLORS.cyan}version${COLORS.reset} Afficher la version
@@ -70,6 +71,7 @@ ${COLORS.bright}COMMANDES${COLORS.reset}
70
71
  ${COLORS.bright}OPTIONS${COLORS.reset}
71
72
  -c, --config Chemin vers le fichier de configuration
72
73
  -o, --output Dossier de sortie
74
+ -p, --port Port du serveur de développement (défaut: 3000)
73
75
  -w, --watch Surveiller les changements (alias de dev)
74
76
  -v, --verbose Mode verbeux
75
77
  -q, --quiet Mode silencieux
@@ -82,14 +84,14 @@ ${COLORS.bright}EXEMPLES${COLORS.reset}
82
84
  ${COLORS.dim}# Compiler le projet${COLORS.reset}
83
85
  ether build
84
86
 
85
- ${COLORS.dim}# Mode développement${COLORS.reset}
87
+ ${COLORS.dim}# Mode développement sur localhost:3000${COLORS.reset}
86
88
  ether dev
87
89
 
88
- ${COLORS.dim}# Compiler avec config personnalisée${COLORS.reset}
89
- ether build -c ./mon-config.js
90
+ ${COLORS.dim}# Mode développement sur un autre port${COLORS.reset}
91
+ ether dev -p 8080
90
92
 
91
93
  ${COLORS.bright}DOCUMENTATION${COLORS.reset}
92
- https://ether-code.com/docs
94
+ https://docs.ether-code.com
93
95
  `)
94
96
  }
95
97
 
@@ -234,6 +236,21 @@ page "Ma première page Ether"
234
236
  titre "Ether"
235
237
  paragraphe "Le langage intentionnel"
236
238
  bouton .primary "Commencer"
239
+ section #features
240
+ article
241
+ icône "🚀"
242
+ titre "Rapide"
243
+ paragraphe "Compilez votre code en un clin d'œil."
244
+ article
245
+ icône "🔒"
246
+ titre "Sécurisé"
247
+ paragraphe "Vos données sont protégées par défaut."
248
+ article
249
+ icône "🌐"
250
+ titre "Évolutif"
251
+ paragraphe "Adaptez votre application à vos besoins."
252
+ piedDePage
253
+ paragraphe "© 2025 Site créé avec Ether. Tous droits réservés."
237
254
  `
238
255
 
239
256
  const examplePath = path.join(srcDir, 'index.eth')
@@ -341,6 +358,7 @@ async function cmdDev(options) {
341
358
  const config = loadConfig(options.config)
342
359
  const srcDir = path.resolve(process.cwd(), config.src)
343
360
  const outDir = path.resolve(process.cwd(), options.output || config.out)
361
+ const port = options.port || config.port || 3000
344
362
 
345
363
  if (!fs.existsSync(srcDir)) {
346
364
  logError(`Dossier source introuvable: ${srcDir}`)
@@ -350,11 +368,105 @@ async function cmdDev(options) {
350
368
  logInfo(`Surveillance de ${srcDir}`)
351
369
  logInfo(`Sortie vers ${outDir}`)
352
370
  console.log('')
353
- logInfo('En attente de modifications... (Ctrl+C pour arrêter)')
354
- console.log('')
355
371
 
356
372
  await cmdBuild({ ...options, quiet: true })
357
373
 
374
+ const clients = []
375
+
376
+ const MIME_TYPES = {
377
+ '.html': 'text/html',
378
+ '.css': 'text/css',
379
+ '.js': 'application/javascript',
380
+ '.json': 'application/json',
381
+ '.png': 'image/png',
382
+ '.jpg': 'image/jpeg',
383
+ '.jpeg': 'image/jpeg',
384
+ '.gif': 'image/gif',
385
+ '.svg': 'image/svg+xml',
386
+ '.ico': 'image/x-icon',
387
+ '.webp': 'image/webp',
388
+ '.mp4': 'video/mp4',
389
+ '.webm': 'video/webm',
390
+ '.woff': 'font/woff',
391
+ '.woff2': 'font/woff2',
392
+ '.ttf': 'font/ttf'
393
+ }
394
+
395
+ const LIVE_RELOAD_SCRIPT = `
396
+ <script>
397
+ (function() {
398
+ const es = new EventSource('/__ether_reload');
399
+ es.onmessage = function(e) {
400
+ if (e.data === 'reload') {
401
+ window.location.reload();
402
+ }
403
+ };
404
+ es.onerror = function() {
405
+ es.close();
406
+ setTimeout(function() { window.location.reload(); }, 1000);
407
+ };
408
+ })();
409
+ </script>
410
+ </body>`
411
+
412
+ const server = http.createServer((req, res) => {
413
+ if (req.url === '/__ether_reload') {
414
+ res.writeHead(200, {
415
+ 'Content-Type': 'text/event-stream',
416
+ 'Cache-Control': 'no-cache',
417
+ 'Connection': 'keep-alive',
418
+ 'Access-Control-Allow-Origin': '*'
419
+ })
420
+ res.write('data: connected\n\n')
421
+ clients.push(res)
422
+ req.on('close', () => {
423
+ const index = clients.indexOf(res)
424
+ if (index > -1) clients.splice(index, 1)
425
+ })
426
+ return
427
+ }
428
+
429
+ let filePath = req.url === '/' ? '/index.html' : req.url
430
+ filePath = filePath.split('?')[0]
431
+ filePath = path.join(outDir, filePath)
432
+
433
+ const ext = path.extname(filePath).toLowerCase()
434
+ const contentType = MIME_TYPES[ext] || 'application/octet-stream'
435
+
436
+ fs.readFile(filePath, (err, content) => {
437
+ if (err) {
438
+ if (err.code === 'ENOENT') {
439
+ res.writeHead(404)
440
+ res.end('404 - Fichier non trouvé')
441
+ } else {
442
+ res.writeHead(500)
443
+ res.end('Erreur serveur')
444
+ }
445
+ return
446
+ }
447
+
448
+ if (ext === '.html') {
449
+ content = content.toString().replace('</body>', LIVE_RELOAD_SCRIPT)
450
+ }
451
+
452
+ res.writeHead(200, { 'Content-Type': contentType })
453
+ res.end(content)
454
+ })
455
+ })
456
+
457
+ server.listen(port, () => {
458
+ logSuccess(`Serveur démarré sur http://localhost:${port}`)
459
+ console.log('')
460
+ logInfo('En attente de modifications... (Ctrl+C pour arrêter)')
461
+ console.log('')
462
+ })
463
+
464
+ function notifyClients() {
465
+ clients.forEach(client => {
466
+ client.write('data: reload\n\n')
467
+ })
468
+ }
469
+
358
470
  const watcher = new Watcher(srcDir, config.watch)
359
471
  const compiler = new EtherCompiler(config)
360
472
 
@@ -378,6 +490,8 @@ async function cmdDev(options) {
378
490
  fs.writeFileSync(outPath, output.content)
379
491
  logSuccess(`→ ${output.path}`)
380
492
  }
493
+
494
+ notifyClients()
381
495
  } catch (err) {
382
496
  logError(err.message)
383
497
  }
@@ -403,6 +517,8 @@ async function cmdDev(options) {
403
517
  fs.writeFileSync(outPath, output.content)
404
518
  logSuccess(`→ ${output.path}`)
405
519
  }
520
+
521
+ notifyClients()
406
522
  } catch (err) {
407
523
  logError(err.message)
408
524
  }
@@ -417,7 +533,8 @@ async function cmdDev(options) {
417
533
 
418
534
  process.on('SIGINT', () => {
419
535
  console.log('')
420
- logInfo('Arrêt du mode développement')
536
+ logInfo('Arrêt du serveur de développement')
537
+ server.close()
421
538
  watcher.stop()
422
539
  process.exit(0)
423
540
  })
@@ -516,6 +633,7 @@ function parseArgs(args) {
516
633
  command: null,
517
634
  config: null,
518
635
  output: null,
636
+ port: null,
519
637
  verbose: false,
520
638
  quiet: false,
521
639
  watch: false
@@ -529,6 +647,8 @@ function parseArgs(args) {
529
647
  options.config = args[++i]
530
648
  } else if (arg === '-o' || arg === '--output') {
531
649
  options.output = args[++i]
650
+ } else if (arg === '-p' || arg === '--port') {
651
+ options.port = parseInt(args[++i], 10)
532
652
  } else if (arg === '-v' || arg === '--verbose') {
533
653
  options.verbose = true
534
654
  } else if (arg === '-q' || arg === '--quiet') {
@@ -557,7 +557,7 @@
557
557
  "comparators": {
558
558
  "plusGrandQue": { "fr": "plus grand que", "en": "greater than", "es": "mayor que", "ru": "больше чем", "zh": "大于", "ja": "より大きい" },
559
559
  "plusPetitQue": { "fr": "plus petit que", "en": "less than", "es": "menor que", "ru": "меньше чем", "zh": "小于", "ja": "より小さい" },
560
- "egalA": { "fr": "égal Ô, "en": "equal to", "es": "igual a", "ru": "равно", "zh": "等于", "ja": "等しい" },
560
+ "egalA": { "fr": "égal à", "en": "equal to", "es": "igual a", "ru": "равно", "zh": "等于", "ja": "等しい" },
561
561
  "auMoins": { "fr": "au moins", "en": "at least", "es": "al menos", "ru": "не менее", "zh": "至少", "ja": "以上" },
562
562
  "auPlus": { "fr": "au plus", "en": "at most", "es": "como mucho", "ru": "не более", "zh": "至多", "ja": "以下" }
563
563
  },
@@ -538,8 +538,8 @@
538
538
 
539
539
  "entities": {
540
540
  "espaceInsecable": { "fr": "espace insécable", "en": "non-breaking space", "es": "espacio irrompible", "ru": "неразрывный пробел", "zh": "不换行空格", "ja": "ノーブレークスペース", "html": "&nbsp;" },
541
- "inferieurA": { "fr": "inférieur Ô, "en": "less than", "es": "menor que", "ru": "меньше", "zh": "小于", "ja": "小なり", "html": "&lt;" },
542
- "superieurA": { "fr": "supérieur Ô, "en": "greater than", "es": "mayor que", "ru": "больше", "zh": "大于", "ja": "大なり", "html": "&gt;" },
541
+ "inferieurA": { "fr": "inférieur à", "en": "less than", "es": "menor que", "ru": "меньше", "zh": "小于", "ja": "小なり", "html": "&lt;" },
542
+ "superieurA": { "fr": "supérieur à", "en": "greater than", "es": "mayor que", "ru": "больше", "zh": "大于", "ja": "大なり", "html": "&gt;" },
543
543
  "esperluette": { "fr": "esperluette", "en": "ampersand", "es": "ampersand", "ru": "амперсанд", "zh": "和号", "ja": "アンパサンド", "html": "&amp;" },
544
544
  "guillemet": { "fr": "guillemet", "en": "quotation mark", "es": "comillas", "ru": "кавычка", "zh": "引号", "ja": "引用符", "html": "&quot;" },
545
545
  "apostrophe": { "fr": "apostrophe", "en": "apostrophe", "es": "apóstrofo", "ru": "апостроф", "zh": "撇号", "ja": "アポストロフィ", "html": "&apos;" },
package/i18n/i18n-js.json CHANGED
@@ -1331,7 +1331,7 @@
1331
1331
  "ja": "イズアレイ"
1332
1332
  },
1333
1333
  "a": {
1334
- "fr": "Ô,
1334
+ "fr": "à",
1335
1335
  "en": "at",
1336
1336
  "es": "en",
1337
1337
  "ru": "по",
@@ -1381,7 +1381,7 @@
1381
1381
  "ja": "レングス"
1382
1382
  },
1383
1383
  "caractereA": {
1384
- "fr": "caractère Ô,
1384
+ "fr": "caractère à",
1385
1385
  "en": "char at",
1386
1386
  "es": "carácter en",
1387
1387
  "ru": "символ по",
@@ -1389,7 +1389,7 @@
1389
1389
  "ja": "キャラアット"
1390
1390
  },
1391
1391
  "codeCaractereA": {
1392
- "fr": "code caractère Ô,
1392
+ "fr": "code caractère à",
1393
1393
  "en": "char code at",
1394
1394
  "es": "código carácter en",
1395
1395
  "ru": "код символа по",
@@ -1581,7 +1581,7 @@
1581
1581
  "ja": "トリムエンド"
1582
1582
  },
1583
1583
  "a": {
1584
- "fr": "Ô,
1584
+ "fr": "à",
1585
1585
  "en": "at",
1586
1586
  "es": "en",
1587
1587
  "ru": "по",
@@ -2624,7 +2624,7 @@
2624
2624
  "ja": "使用"
2625
2625
  },
2626
2626
  "aSql": {
2627
- "fr": "Ô,
2627
+ "fr": "à",
2628
2628
  "en": "to",
2629
2629
  "es": "a",
2630
2630
  "ru": "к",
@@ -2760,7 +2760,7 @@
2760
2760
  "ja": "ロール内"
2761
2761
  },
2762
2762
  "appartientA": {
2763
- "fr": "appartient Ô,
2763
+ "fr": "appartient à",
2764
2764
  "en": "member of",
2765
2765
  "es": "miembro de",
2766
2766
  "ru": "член",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ether-code",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Ether - Le langage intentionnel",
5
5
  "main": "cli/compiler.js",
6
6
  "bin": {
@@ -42,4 +42,4 @@
42
42
  "README.md",
43
43
  "LICENSE"
44
44
  ]
45
- }
45
+ }