ether-code 0.1.8 → 0.2.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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Steve
3
+ Copyright (c) 2025 Steve
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,130 +1,68 @@
1
1
  # Ether
2
2
 
3
- **Le langage intentionnel** - Programmez dans votre langue naturelle.
4
-
5
- Ether est un compilateur qui transforme du code écrit en langage naturel (français, anglais, espagnol, russe, chinois, japonais) en code exécutable dans les langages cibles : JavaScript, TypeScript, HTML, CSS, PHP, Python, Ruby, SQL, Node.js, React, GraphQL.
3
+ **Le langage intentionnel** - Écrivez du code comme vous pensez.
6
4
 
7
5
  ## Installation
8
6
 
9
7
  ```bash
10
- npm install -g ether-lang
8
+ npm install -g ether-code
11
9
  ```
12
10
 
13
11
  ## Utilisation
14
12
 
15
- ### Compiler un projet
13
+ ### Initialiser un projet
16
14
 
17
15
  ```bash
18
- ether build
16
+ ether init
19
17
  ```
20
18
 
21
- ### Mode développement (watch)
19
+ ### Compiler
22
20
 
23
21
  ```bash
24
- ether dev
22
+ ether build
25
23
  ```
26
24
 
27
- ### Compiler un fichier spécifique
25
+ ### Mode développement (watch)
28
26
 
29
27
  ```bash
30
- ether build fichier.eth
31
- ```
32
-
33
- ## Configuration
34
-
35
- Créez un fichier `ether.config.json` à la racine de votre projet :
36
-
37
- ```json
38
- {
39
- "lang": "fr",
40
- "src": "./src",
41
- "out": "./dist",
42
- "targets": ["js", "css", "html"]
43
- }
28
+ ether dev
44
29
  ```
45
30
 
46
- ### Options
47
-
48
- | Option | Description | Défaut |
49
- |--------|-------------|--------|
50
- | `lang` | Langue source (fr, en, es, ru, zh, ja) | `fr` |
51
- | `src` | Dossier source | `./src` |
52
- | `out` | Dossier de sortie | `./dist` |
53
- | `targets` | Langages cibles | tous |
54
-
55
31
  ## Exemple
56
32
 
57
- ### Code Ether (français)
33
+ Créez un fichier `src/index.eth`:
58
34
 
59
- ```ether
60
- // style.eth
61
- sélecteur ".bouton"
62
- couleur fond: bleu
63
- couleur texte: blanc
64
- marge: 1rem
65
- bordure arrondie: 0.5rem
66
35
  ```
67
-
68
- ### Résultat CSS
69
-
70
- ```css
71
- .bouton {
72
- background-color: blue;
73
- color: white;
74
- margin: 1rem;
75
- border-radius: 0.5rem;
76
- }
36
+ // cible: html
37
+
38
+ document
39
+ tete
40
+ titre "Ma page"
41
+ corps
42
+ titre1 "Bienvenue"
43
+ paragraphe "Ether permet d'écrire du code naturellement."
77
44
  ```
78
45
 
79
- ### Code Ether (JavaScript)
80
-
81
- ```ether
82
- // app.eth
83
- fonction saluer avec nom
84
- retourner "Bonjour, " + nom + "!"
85
-
86
- afficher saluer("Monde")
87
- ```
88
-
89
- ### Résultat JavaScript
90
-
91
- ```javascript
92
- function saluer(nom) {
93
- return "Bonjour, " + nom + "!";
94
- }
95
-
96
- console.log(saluer("Monde"));
97
- ```
46
+ Compilez avec `ether build` pour générer `dist/index.html`.
98
47
 
99
48
  ## Langages supportés
100
49
 
101
- ### Langues source
102
- - 🇫🇷 Français
103
- - 🇬🇧 English
104
- - 🇪🇸 Español
105
- - 🇷🇺 Русский
106
- - 🇨🇳 中文
107
- - 🇯🇵 日本語
108
-
109
- ### Langages cibles
110
- - JavaScript / TypeScript
111
- - HTML / CSS
50
+ - HTML
51
+ - CSS
52
+ - JavaScript
53
+ - TypeScript
112
54
  - PHP
113
55
  - Python
114
56
  - Ruby
115
57
  - SQL
116
58
  - Node.js
117
- - React / JSX
59
+ - React
118
60
  - GraphQL
119
61
 
120
- ## Philosophie
121
-
122
- Ether est un **langage intentionnel** : au lieu de forcer les humains à parler comme des machines, Ether permet aux machines de comprendre l'intention humaine.
62
+ ## Documentation
123
63
 
124
- - **Naturel** : Écrivez du code comme vous pensez
125
- - **Multilingue** : Programmez dans votre langue maternelle
126
- - **Universel** : Un seul langage, tous les frameworks
64
+ https://ether-code.com/docs
127
65
 
128
- ## Licence
66
+ ## License
129
67
 
130
- MIT © Steve
68
+ MIT
package/cli/compiler.js CHANGED
@@ -66,7 +66,6 @@ class EtherCompiler {
66
66
  ...config
67
67
  }
68
68
 
69
- this.lexer = new EtherLexer()
70
69
  this.generators = {}
71
70
  this.parser = null
72
71
 
@@ -111,12 +110,9 @@ class EtherCompiler {
111
110
  async compileFile(filePath) {
112
111
  const content = fs.readFileSync(filePath, 'utf-8')
113
112
  const fileName = path.basename(filePath, '.eth')
114
- const dirName = path.dirname(filePath)
115
113
 
116
114
  const target = this.detectTarget(content, filePath)
117
-
118
115
  const ast = this.parse(content, target)
119
-
120
116
  const code = this.generate(ast, target)
121
117
 
122
118
  const extension = this.getExtension(target)
@@ -179,38 +175,34 @@ class EtherCompiler {
179
175
  inferTargetFromContent(content) {
180
176
  const patterns = {
181
177
  html: [
178
+ /^document\b/im,
182
179
  /^html\b/im,
183
- /\b(html|page|document|entête|entete|corps|section|div|paragraphe|titre|lien|image|formulaire|bouton)\b/i,
184
- /\b(balise|élément|element|attribut)\b/i
180
+ /\b(page|entête|entete|corps|section|paragraphe|titre|lien|image|formulaire|bouton)\b/i
185
181
  ],
186
182
  css: [
187
- /\b(style|couleur|taille|marge|bordure|fond|police|largeur|hauteur)\s*[:=]/i,
188
- /\.([\w-]+)\s*\{/,
189
- /#([\w-]+)\s*\{/
183
+ /\b(fond|couleur|marge|bordure|police|largeur|hauteur)\s*:/i,
184
+ /^\s*\./m,
185
+ /^\s*#[\w-]+\s*$/m
190
186
  ],
191
187
  js: [
192
188
  /\b(fonction|variable|constante|si|sinon|pour|tant que|retourner)\b/i,
193
- /\b(classe|méthode|constructeur)\b/i,
194
- /=>\s*\{/
189
+ /\b(classe|méthode|constructeur)\b/i
195
190
  ],
196
191
  php: [
197
- /\b(<?php|echo|namespace|use)\b/i,
192
+ /\b(<\?php|echo|namespace|utiliser)\b/i,
198
193
  /\$\w+/
199
194
  ],
200
195
  sql: [
201
- /\b(sélectionner|insérer|mettre à jour|supprimer|créer table|depuis|où)\b/i,
202
- /\b(SELECT|INSERT|UPDATE|DELETE|CREATE|FROM|WHERE)\b/i
196
+ /\b(sélectionner|selectionner|insérer|mettre à jour|supprimer|créer|depuis|où)\b/i
203
197
  ],
204
198
  python: [
205
- /\b(def|class|import|from|if|elif|else|for|while|return)\b/,
206
- /:\s*$/m
199
+ /\b(définir|def|classe|importer)\b/i
207
200
  ],
208
201
  react: [
209
- /\b(composant|état|effet|props|rendu)\b/i,
210
- /<[\w]+[^>]*\/>/
202
+ /\b(composant|état|effet|props|rendu)\b/i
211
203
  ],
212
204
  graphql: [
213
- /\b(type|query|mutation|subscription|schema|input)\b/i
205
+ /\b(type|requête|mutation|subscription|schema|entrée)\b/i
214
206
  ]
215
207
  }
216
208
 
@@ -239,12 +231,6 @@ class EtherCompiler {
239
231
  const content = fs.readFileSync(filePath, 'utf-8')
240
232
  const target = this.detectTarget(content, filePath)
241
233
 
242
- try {
243
- this.lexer.tokenize(content)
244
- } catch (err) {
245
- throw new Error(`Erreur de lexer: ${err.message}`)
246
- }
247
-
248
234
  try {
249
235
  this.parse(content, target)
250
236
  } catch (err) {
package/cli/ether.js CHANGED
@@ -2,11 +2,10 @@
2
2
 
3
3
  const fs = require('fs')
4
4
  const path = require('path')
5
- const http = require('http')
6
5
  const { EtherCompiler } = require('./compiler')
7
6
  const { Watcher } = require('./watcher')
8
7
 
9
- const VERSION = '0.1.8'
8
+ const VERSION = '0.2.0'
10
9
 
11
10
  const COLORS = {
12
11
  reset: '\x1b[0m',
@@ -63,7 +62,7 @@ ${COLORS.bright}UTILISATION${COLORS.reset}
63
62
  ${COLORS.bright}COMMANDES${COLORS.reset}
64
63
  ${COLORS.cyan}init${COLORS.reset} Initialiser un nouveau projet Ether
65
64
  ${COLORS.cyan}build${COLORS.reset} Compiler les fichiers .eth
66
- ${COLORS.cyan}dev${COLORS.reset} Mode développement (serveur + watch + live reload)
65
+ ${COLORS.cyan}dev${COLORS.reset} Mode développement (watch + compilation auto)
67
66
  ${COLORS.cyan}check${COLORS.reset} Vérifier la syntaxe sans compiler
68
67
  ${COLORS.cyan}help${COLORS.reset} Afficher cette aide
69
68
  ${COLORS.cyan}version${COLORS.reset} Afficher la version
@@ -71,7 +70,6 @@ ${COLORS.bright}COMMANDES${COLORS.reset}
71
70
  ${COLORS.bright}OPTIONS${COLORS.reset}
72
71
  -c, --config Chemin vers le fichier de configuration
73
72
  -o, --output Dossier de sortie
74
- -p, --port Port du serveur de développement (défaut: 3000)
75
73
  -w, --watch Surveiller les changements (alias de dev)
76
74
  -v, --verbose Mode verbeux
77
75
  -q, --quiet Mode silencieux
@@ -84,11 +82,11 @@ ${COLORS.bright}EXEMPLES${COLORS.reset}
84
82
  ${COLORS.dim}# Compiler le projet${COLORS.reset}
85
83
  ether build
86
84
 
87
- ${COLORS.dim}# Mode développement sur localhost:3000${COLORS.reset}
85
+ ${COLORS.dim}# Mode développement${COLORS.reset}
88
86
  ether dev
89
87
 
90
- ${COLORS.dim}# Mode développement sur un autre port${COLORS.reset}
91
- ether dev -p 8080
88
+ ${COLORS.dim}# Compiler avec config personnalisée${COLORS.reset}
89
+ ether build -c ./mon-config.js
92
90
 
93
91
  ${COLORS.bright}DOCUMENTATION${COLORS.reset}
94
92
  https://ether-code.com/docs
@@ -148,23 +146,11 @@ async function cmdInit() {
148
146
  fs.mkdirSync(srcDir, { recursive: true })
149
147
  logSuccess('Dossier src/ créé')
150
148
  }
151
-
152
- const publicDir = path.join(cwd, 'public')
153
- if (!fs.existsSync(publicDir)) {
154
- fs.mkdirSync(publicDir, { recursive: true })
155
- logSuccess('Dossier public/ créé')
156
- }
157
-
158
- const imagesDir = path.join(publicDir, 'images')
159
- if (!fs.existsSync(imagesDir)) {
160
- fs.mkdirSync(imagesDir, { recursive: true })
161
- logSuccess('Dossier public/images/ créé')
162
- }
163
-
164
- const videosDir = path.join(publicDir, 'videos')
165
- if (!fs.existsSync(videosDir)) {
166
- fs.mkdirSync(videosDir, { recursive: true })
167
- logSuccess('Dossier public/videos/ créé')
149
+
150
+ const distDir = path.join(cwd, 'dist')
151
+ if (!fs.existsSync(distDir)) {
152
+ fs.mkdirSync(distDir, { recursive: true })
153
+ logSuccess('Dossier dist/ créé')
168
154
  }
169
155
 
170
156
  const configContent = `module.exports = {
@@ -202,42 +188,23 @@ async function cmdInit() {
202
188
  logWarning('ether.config.js existe déjà')
203
189
  }
204
190
 
205
- const projectName = path.basename(cwd)
206
- const packageJson = {
207
- name: projectName,
208
- version: "1.0.0",
209
- description: "Projet Ether",
210
- scripts: {
211
- dev: "ether dev",
212
- build: "ether build",
213
- check: "ether check"
214
- },
215
- keywords: ["ether"],
216
- license: "MIT"
217
- }
218
-
219
- const packagePath = path.join(cwd, 'package.json')
220
- if (!fs.existsSync(packagePath)) {
221
- fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 2))
222
- logSuccess('Fichier package.json créé')
223
- } else {
224
- logWarning('package.json existe déjà')
225
- }
191
+ const exampleEth = `// cible: html
226
192
 
227
- const exampleEth = `html
228
- tête
193
+ document
194
+ tete
229
195
  titre "Ma première page Ether"
196
+
230
197
  corps
231
198
  entete
232
199
  titre1 "Bienvenue sur Ether"
233
- paragraphe "Le langage intentionnel"
200
+
234
201
  principal
235
- section #hero
236
- titre2 "Commencez maintenant"
237
- paragraphe "Programmez dans votre langue naturelle."
238
- bouton .primary "Démarrer"
202
+ section
203
+ titre2 "Le langage intentionnel"
204
+ paragraphe "Ether permet d'écrire du code comme on pense."
205
+
239
206
  pied
240
- paragraphe "© 2025 Créé avec Ether"
207
+ paragraphe "Créé avec Ether"
241
208
  `
242
209
 
243
210
  const examplePath = path.join(srcDir, 'index.eth')
@@ -268,7 +235,6 @@ async function cmdBuild(options) {
268
235
  const config = loadConfig(options.config)
269
236
  const srcDir = path.resolve(process.cwd(), config.src)
270
237
  const outDir = path.resolve(process.cwd(), options.output || config.out)
271
- const publicDir = path.resolve(process.cwd(), config.public || 'public')
272
238
 
273
239
  if (!fs.existsSync(srcDir)) {
274
240
  logError(`Dossier source introuvable: ${srcDir}`)
@@ -279,13 +245,6 @@ async function cmdBuild(options) {
279
245
  fs.mkdirSync(outDir, { recursive: true })
280
246
  }
281
247
 
282
- if (fs.existsSync(publicDir)) {
283
- copyDir(publicDir, outDir)
284
- if (!options.quiet) {
285
- logSuccess('Dossier public/ copié vers dist/')
286
- }
287
- }
288
-
289
248
  const compiler = new EtherCompiler(config)
290
249
 
291
250
  const files = findEthFiles(srcDir)
@@ -345,7 +304,6 @@ async function cmdDev(options) {
345
304
  const config = loadConfig(options.config)
346
305
  const srcDir = path.resolve(process.cwd(), config.src)
347
306
  const outDir = path.resolve(process.cwd(), options.output || config.out)
348
- const port = options.port || config.port || 3000
349
307
 
350
308
  if (!fs.existsSync(srcDir)) {
351
309
  logError(`Dossier source introuvable: ${srcDir}`)
@@ -354,106 +312,9 @@ async function cmdDev(options) {
354
312
 
355
313
  logInfo(`Surveillance de ${srcDir}`)
356
314
  logInfo(`Sortie vers ${outDir}`)
357
- console.log('')
358
315
 
359
316
  await cmdBuild({ ...options, quiet: true })
360
317
 
361
- const clients = []
362
-
363
- const MIME_TYPES = {
364
- '.html': 'text/html',
365
- '.css': 'text/css',
366
- '.js': 'application/javascript',
367
- '.json': 'application/json',
368
- '.png': 'image/png',
369
- '.jpg': 'image/jpeg',
370
- '.jpeg': 'image/jpeg',
371
- '.gif': 'image/gif',
372
- '.svg': 'image/svg+xml',
373
- '.ico': 'image/x-icon',
374
- '.webp': 'image/webp',
375
- '.mp4': 'video/mp4',
376
- '.webm': 'video/webm',
377
- '.woff': 'font/woff',
378
- '.woff2': 'font/woff2',
379
- '.ttf': 'font/ttf'
380
- }
381
-
382
- const LIVE_RELOAD_SCRIPT = `
383
- <script>
384
- (function() {
385
- const es = new EventSource('/__ether_reload');
386
- es.onmessage = function(e) {
387
- if (e.data === 'reload') {
388
- window.location.reload();
389
- }
390
- };
391
- es.onerror = function() {
392
- es.close();
393
- setTimeout(function() { window.location.reload(); }, 1000);
394
- };
395
- })();
396
- </script>
397
- </body>`
398
-
399
- const server = http.createServer((req, res) => {
400
- if (req.url === '/__ether_reload') {
401
- res.writeHead(200, {
402
- 'Content-Type': 'text/event-stream',
403
- 'Cache-Control': 'no-cache',
404
- 'Connection': 'keep-alive',
405
- 'Access-Control-Allow-Origin': '*'
406
- })
407
- res.write('data: connected\n\n')
408
- clients.push(res)
409
- req.on('close', () => {
410
- const index = clients.indexOf(res)
411
- if (index > -1) clients.splice(index, 1)
412
- })
413
- return
414
- }
415
-
416
- let filePath = req.url === '/' ? '/index.html' : req.url
417
- filePath = filePath.split('?')[0]
418
- filePath = path.join(outDir, filePath)
419
-
420
- const ext = path.extname(filePath).toLowerCase()
421
- const contentType = MIME_TYPES[ext] || 'application/octet-stream'
422
-
423
- fs.readFile(filePath, (err, content) => {
424
- if (err) {
425
- if (err.code === 'ENOENT') {
426
- res.writeHead(404)
427
- res.end('404 - Fichier non trouvé')
428
- } else {
429
- res.writeHead(500)
430
- res.end('Erreur serveur')
431
- }
432
- return
433
- }
434
-
435
- if (ext === '.html') {
436
- content = content.toString().replace('</body>', LIVE_RELOAD_SCRIPT)
437
- }
438
-
439
- res.writeHead(200, { 'Content-Type': contentType })
440
- res.end(content)
441
- })
442
- })
443
-
444
- server.listen(port, () => {
445
- logSuccess(`Serveur démarré sur http://localhost:${port}`)
446
- console.log('')
447
- logInfo('En attente de modifications... (Ctrl+C pour arrêter)')
448
- console.log('')
449
- })
450
-
451
- function notifyClients() {
452
- clients.forEach(client => {
453
- client.write('data: reload\n\n')
454
- })
455
- }
456
-
457
318
  const watcher = new Watcher(srcDir, config.watch)
458
319
  const compiler = new EtherCompiler(config)
459
320
 
@@ -477,8 +338,6 @@ async function cmdDev(options) {
477
338
  fs.writeFileSync(outPath, output.content)
478
339
  logSuccess(`→ ${output.path}`)
479
340
  }
480
-
481
- notifyClients()
482
341
  } catch (err) {
483
342
  logError(err.message)
484
343
  }
@@ -504,8 +363,6 @@ async function cmdDev(options) {
504
363
  fs.writeFileSync(outPath, output.content)
505
364
  logSuccess(`→ ${output.path}`)
506
365
  }
507
-
508
- notifyClients()
509
366
  } catch (err) {
510
367
  logError(err.message)
511
368
  }
@@ -520,8 +377,7 @@ async function cmdDev(options) {
520
377
 
521
378
  process.on('SIGINT', () => {
522
379
  console.log('')
523
- logInfo('Arrêt du serveur de développement')
524
- server.close()
380
+ logInfo('Arrêt du mode développement')
525
381
  watcher.stop()
526
382
  process.exit(0)
527
383
  })
@@ -596,31 +452,11 @@ function findEthFiles(dir) {
596
452
  return files
597
453
  }
598
454
 
599
- function copyDir(src, dest) {
600
- if (!fs.existsSync(dest)) {
601
- fs.mkdirSync(dest, { recursive: true })
602
- }
603
-
604
- const entries = fs.readdirSync(src, { withFileTypes: true })
605
-
606
- for (const entry of entries) {
607
- const srcPath = path.join(src, entry.name)
608
- const destPath = path.join(dest, entry.name)
609
-
610
- if (entry.isDirectory()) {
611
- copyDir(srcPath, destPath)
612
- } else {
613
- fs.copyFileSync(srcPath, destPath)
614
- }
615
- }
616
- }
617
-
618
455
  function parseArgs(args) {
619
456
  const options = {
620
457
  command: null,
621
458
  config: null,
622
459
  output: null,
623
- port: null,
624
460
  verbose: false,
625
461
  quiet: false,
626
462
  watch: false
@@ -634,8 +470,6 @@ function parseArgs(args) {
634
470
  options.config = args[++i]
635
471
  } else if (arg === '-o' || arg === '--output') {
636
472
  options.output = args[++i]
637
- } else if (arg === '-p' || arg === '--port') {
638
- options.port = parseInt(args[++i], 10)
639
473
  } else if (arg === '-v' || arg === '--verbose') {
640
474
  options.verbose = true
641
475
  } else if (arg === '-q' || arg === '--quiet') {