ether-code 0.1.3 → 0.1.4

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/compiler.js CHANGED
@@ -212,8 +212,8 @@ class EtherCompiler {
212
212
  inferTargetFromContent(content) {
213
213
  const patterns = {
214
214
  html: [
215
- /\b(page|document|entête|entete|corps|section|div|paragraphe|titre|lien|image|formulaire|bouton)\b/i,
216
- /\b(balise|élément|element|attribut)\b/i
215
+ /\b(page|document|entête|corps|section|div|paragraphe|titre|lien|image|formulaire|bouton)\b/i,
216
+ /\b(balise|élément|attribut)\b/i
217
217
  ],
218
218
  css: [
219
219
  /\b(style|couleur|taille|marge|bordure|fond|police|largeur|hauteur)\s*[:=]/i,
@@ -222,7 +222,7 @@ class EtherCompiler {
222
222
  ],
223
223
  js: [
224
224
  /\b(fonction|variable|constante|si|sinon|pour|tant que|retourner)\b/i,
225
- /\b(classe|méthode|methode|constructeur)\b/i,
225
+ /\b(classe|méthode|constructeur)\b/i,
226
226
  /=>\s*\{/
227
227
  ],
228
228
  php: [
@@ -230,7 +230,7 @@ class EtherCompiler {
230
230
  /\$\w+/
231
231
  ],
232
232
  sql: [
233
- /\b(sélectionner|selectionner|insérer|inserer|mettre à jour|mettre a jour|supprimer|créer table|creer table|depuis|où|ou)\b/i,
233
+ /\b(sélectionner|insérer|mettre à jour|supprimer|créer table|depuis|)\b/i,
234
234
  /\b(SELECT|INSERT|UPDATE|DELETE|CREATE|FROM|WHERE)\b/i
235
235
  ],
236
236
  python: [
@@ -238,7 +238,7 @@ class EtherCompiler {
238
238
  /:\s*$/m
239
239
  ],
240
240
  react: [
241
- /\b(composant|état|etat|effet|props|rendu)\b/i,
241
+ /\b(composant|état|effet|props|rendu)\b/i,
242
242
  /<[\w]+[^>]*\/>/
243
243
  ],
244
244
  graphql: [
@@ -295,4 +295,4 @@ class EtherCompiler {
295
295
  }
296
296
  }
297
297
 
298
- module.exports = { EtherCompiler, GENERATORS, TARGET_EXTENSIONS }
298
+ module.exports = { EtherCompiler, GENERATORS, TARGET_EXTENSIONS }
package/cli/ether.js CHANGED
@@ -6,7 +6,7 @@ const http = require('http')
6
6
  const { EtherCompiler } = require('./compiler')
7
7
  const { Watcher } = require('./watcher')
8
8
 
9
- const VERSION = '0.1.3'
9
+ const VERSION = '0.1.4'
10
10
 
11
11
  const COLORS = {
12
12
  reset: '\x1b[0m',
@@ -91,7 +91,7 @@ ${COLORS.bright}EXEMPLES${COLORS.reset}
91
91
  ether dev -p 8080
92
92
 
93
93
  ${COLORS.bright}DOCUMENTATION${COLORS.reset}
94
- https://docs.ether-code.com
94
+ https://ether-code.com/docs
95
95
  `)
96
96
  }
97
97
 
@@ -224,33 +224,20 @@ async function cmdInit() {
224
224
  logWarning('package.json existe déjà')
225
225
  }
226
226
 
227
- const exampleEth = `// Exemple de fichier Ether
228
- // Cible: html
229
-
230
- page "Ma première page Ether"
231
- entête
232
- titre "Bienvenue"
233
-
227
+ const exampleEth = `html
228
+ tête
229
+ titre "Ma première page Ether"
234
230
  corps
235
- section #hero
236
- titre "Ether"
231
+ entete
232
+ titre1 "Bienvenue sur Ether"
237
233
  paragraphe "Le langage intentionnel"
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."
234
+ principal
235
+ section #hero
236
+ titre2 "Commencez maintenant"
237
+ paragraphe "Programmez dans votre langue naturelle."
238
+ bouton .primary "Démarrer"
239
+ pied
240
+ paragraphe "© 2025 Créé avec Ether"
254
241
  `
255
242
 
256
243
  const examplePath = path.join(srcDir, 'index.eth')
@@ -710,4 +697,4 @@ async function main() {
710
697
  main().catch(err => {
711
698
  logError(err.message)
712
699
  process.exit(1)
713
- })
700
+ })
@@ -455,10 +455,16 @@ class HTMLGenerator {
455
455
  if (!node) return
456
456
 
457
457
  switch (node.type) {
458
+ case 'Document':
459
+ this.generateDocument(node)
460
+ break
458
461
  case 'Element':
459
462
  case 'élément':
460
463
  this.generateElement(node)
461
464
  break
465
+ case 'TextNode':
466
+ this.generateTextNode(node)
467
+ break
462
468
  case 'Text':
463
469
  case 'text':
464
470
  this.generateText(node)
@@ -474,14 +480,34 @@ class HTMLGenerator {
474
480
  default:
475
481
  if (node.tag || node.tagName) {
476
482
  this.generateElement(node)
477
- } else if (node.text || node.content) {
483
+ } else if (node.text || node.content || node.value) {
478
484
  this.generateText(node)
479
485
  }
480
486
  }
481
487
  }
482
488
 
489
+ generateDocument(node) {
490
+ this.writeLine('<!DOCTYPE html>')
491
+ if (node.html) {
492
+ this.generateNode(node.html)
493
+ }
494
+ }
495
+
496
+ generateTextNode(node) {
497
+ if (node.value || node.content) {
498
+ this.writeLine(this.escapeHtml(node.value || node.content))
499
+ }
500
+ }
501
+
483
502
  generateElement(node) {
484
- const tag = this.translateTag(node.tag || node.tagName || node.name)
503
+ let tag
504
+ if (node.htmlTag && !node.htmlTag.startsWith('<')) {
505
+ tag = node.htmlTag
506
+ } else {
507
+ const rawTag = node.tag || node.tagName || node.name
508
+ tag = this.translateTag(rawTag)
509
+ }
510
+
485
511
  const attributes = this.generateAttributes(node.attributes || node.attrs || {})
486
512
  const isVoid = this.voidElements.includes(tag.toLowerCase())
487
513
 
@@ -521,30 +547,46 @@ class HTMLGenerator {
521
547
  }
522
548
 
523
549
  generateAttributes(attrs) {
524
- if (!attrs || Object.keys(attrs).length === 0) {
550
+ if (!attrs || (Array.isArray(attrs) && attrs.length === 0) || Object.keys(attrs).length === 0) {
525
551
  return ''
526
552
  }
527
553
 
528
554
  const parts = []
529
- for (const [key, value] of Object.entries(attrs)) {
530
- let attrName = this.translateAttribute(key)
531
-
532
- if (attrName.startsWith('au ') || attrName.startsWith('a la ')) {
533
- attrName = this.translateEvent(key)
534
- }
535
-
536
- if (value === true || value === '') {
537
- parts.push(attrName)
538
- } else if (value === false || value === null || value === undefined) {
539
- continue
540
- } else {
541
- let attrValue = this.translateAttrValue(value)
555
+
556
+ if (Array.isArray(attrs)) {
557
+ for (const attr of attrs) {
558
+ const attrName = attr.htmlName || this.translateAttribute(attr.name)
559
+ const value = attr.value
542
560
 
543
- if (attrName === 'type' && this.isInputType(value)) {
544
- attrValue = this.translateInputType(value)
561
+ if (value === true || value === '') {
562
+ parts.push(attrName)
563
+ } else if (value === false || value === null || value === undefined) {
564
+ continue
565
+ } else {
566
+ parts.push(`${attrName}="${this.escapeAttr(value)}"`)
545
567
  }
568
+ }
569
+ } else {
570
+ for (const [key, value] of Object.entries(attrs)) {
571
+ let attrName = this.translateAttribute(key)
546
572
 
547
- parts.push(`${attrName}="${this.escapeAttr(attrValue)}"`)
573
+ if (attrName.startsWith('au ') || attrName.startsWith('a la ')) {
574
+ attrName = this.translateEvent(key)
575
+ }
576
+
577
+ if (value === true || value === '') {
578
+ parts.push(attrName)
579
+ } else if (value === false || value === null || value === undefined) {
580
+ continue
581
+ } else {
582
+ let attrValue = this.translateAttrValue(value)
583
+
584
+ if (attrName === 'type' && this.isInputType(value)) {
585
+ attrValue = this.translateInputType(value)
586
+ }
587
+
588
+ parts.push(`${attrName}="${this.escapeAttr(attrValue)}"`)
589
+ }
548
590
  }
549
591
  }
550
592
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ether-code",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Ether - Le langage intentionnel",
5
5
  "main": "cli/compiler.js",
6
6
  "bin": {
@@ -20,15 +20,15 @@
20
20
  "french",
21
21
  "multilingual"
22
22
  ],
23
- "author": "Stéphane LEGRAND",
23
+ "author": "Steve",
24
24
  "license": "MIT",
25
25
  "repository": {
26
26
  "type": "git",
27
- "url": "https://github.com/ether-code/ether"
27
+ "url": "https://github.com/ether-lang/ether"
28
28
  },
29
29
  "homepage": "https://ether-code.com",
30
30
  "bugs": {
31
- "url": "https://github.com/ether-code/ether/issues"
31
+ "url": "https://github.com/ether-lang/ether/issues"
32
32
  },
33
33
  "engines": {
34
34
  "node": ">=14.0.0"
@@ -42,4 +42,4 @@
42
42
  "README.md",
43
43
  "LICENSE"
44
44
  ]
45
- }
45
+ }
@@ -551,6 +551,7 @@ class HTMLParser {
551
551
  const tagName = elemToken.value
552
552
  const htmlTag = this.translateElement(tagName)
553
553
  const loc = elemToken.loc
554
+ const elemIndent = loc.column - 1
554
555
 
555
556
  const attributes = this.parseAttributes()
556
557
 
@@ -567,7 +568,7 @@ class HTMLParser {
567
568
  children.push(new AST.TextNode(textContent))
568
569
  }
569
570
 
570
- const childElements = this.parseChildren()
571
+ const childElements = this.parseChildren(elemIndent)
571
572
  children = children.concat(childElements)
572
573
  }
573
574
 
@@ -575,6 +576,9 @@ class HTMLParser {
575
576
  }
576
577
 
577
578
  parseShorthandElement() {
579
+ const firstToken = this.peek()
580
+ const elemIndent = firstToken.loc ? firstToken.loc.column - 1 : 0
581
+
578
582
  const attributes = []
579
583
  let tagName = 'div'
580
584
  let htmlTag = 'div'
@@ -607,7 +611,7 @@ class HTMLParser {
607
611
  children.push(new AST.TextNode(textContent))
608
612
  }
609
613
 
610
- const childElements = this.parseChildren()
614
+ const childElements = this.parseChildren(elemIndent)
611
615
  children.push(...childElements)
612
616
 
613
617
  return new AST.Element(tagName, htmlTag, attributes, children, false)
@@ -664,16 +668,13 @@ class HTMLParser {
664
668
  return attributes
665
669
  }
666
670
 
667
- parseChildren() {
671
+ parseChildren(parentIndent = -1) {
668
672
  const children = []
669
673
 
670
- this.skipNewlines()
671
- const baseIndent = this.currentIndent
672
-
673
674
  while (!this.match('EOF')) {
674
675
  this.skipNewlines()
675
676
 
676
- if (this.currentIndent <= baseIndent && children.length > 0) {
677
+ if (this.currentIndent <= parentIndent) {
677
678
  break
678
679
  }
679
680
 
@@ -807,12 +808,12 @@ class HTMLParser {
807
808
  'tete': 'head', 'tête': 'head', 'head': 'head', 'cabeza': 'head', 'голова': 'head', '头部': 'head', 'ヘッド': 'head',
808
809
  'corps': 'body', 'body': 'body', 'cuerpo': 'body', 'тело': 'body', '主体': 'body', 'ボディ': 'body',
809
810
  'titre': 'title', 'title': 'title', 'título': 'title', 'titulo': 'title', 'заголовок': 'title', '标题': 'title', 'タイトル': 'title',
810
- 'titre 1': 'h1', 'heading 1': 'h1', 'título 1': 'h1', 'titulo 1': 'h1', 'заголовок 1': 'h1', '标题 1': 'h1', '見出し 1': 'h1',
811
- 'titre 2': 'h2', 'heading 2': 'h2', 'título 2': 'h2', 'titulo 2': 'h2', 'заголовок 2': 'h2', '标题 2': 'h2', '見出し 2': 'h2',
812
- 'titre 3': 'h3', 'heading 3': 'h3', 'título 3': 'h3', 'titulo 3': 'h3', 'заголовок 3': 'h3', '标题 3': 'h3', '見出し 3': 'h3',
813
- 'titre 4': 'h4', 'heading 4': 'h4', 'título 4': 'h4', 'titulo 4': 'h4', 'заголовок 4': 'h4', '标题 4': 'h4', '見出し 4': 'h4',
814
- 'titre 5': 'h5', 'heading 5': 'h5', 'título 5': 'h5', 'titulo 5': 'h5', 'заголовок 5': 'h5', '标题 5': 'h5', '見出し 5': 'h5',
815
- 'titre 6': 'h6', 'heading 6': 'h6', 'título 6': 'h6', 'titulo 6': 'h6', 'заголовок 6': 'h6', '标题 6': 'h6', '見出し 6': 'h6',
811
+ 'titre 1': 'h1', 'titre1': 'h1', 'heading 1': 'h1', 'título 1': 'h1', 'titulo 1': 'h1', 'заголовок 1': 'h1', '标题 1': 'h1', '見出し 1': 'h1',
812
+ 'titre 2': 'h2', 'titre2': 'h2', 'heading 2': 'h2', 'título 2': 'h2', 'titulo 2': 'h2', 'заголовок 2': 'h2', '标题 2': 'h2', '見出し 2': 'h2',
813
+ 'titre 3': 'h3', 'titre3': 'h3', 'heading 3': 'h3', 'título 3': 'h3', 'titulo 3': 'h3', 'заголовок 3': 'h3', '标题 3': 'h3', '見出し 3': 'h3',
814
+ 'titre 4': 'h4', 'titre4': 'h4', 'heading 4': 'h4', 'título 4': 'h4', 'titulo 4': 'h4', 'заголовок 4': 'h4', '标题 4': 'h4', '見出し 4': 'h4',
815
+ 'titre 5': 'h5', 'titre5': 'h5', 'heading 5': 'h5', 'título 5': 'h5', 'titulo 5': 'h5', 'заголовок 5': 'h5', '标题 5': 'h5', '見出し 5': 'h5',
816
+ 'titre 6': 'h6', 'titre6': 'h6', 'heading 6': 'h6', 'título 6': 'h6', 'titulo 6': 'h6', 'заголовок 6': 'h6', '标题 6': 'h6', '見出し 6': 'h6',
816
817
  'paragraphe': 'p', 'paragraph': 'p', 'párrafo': 'p', 'parrafo': 'p', 'параграф': 'p', '段落': 'p',
817
818
  'division': 'div', 'div': 'div', 'bloque': 'div', 'блок': 'div', '块': 'div', 'ディブ': 'div',
818
819
  'etendue': 'span', 'étendue': 'span', 'span': 'span', 'extensión': 'span', 'extension': 'span', 'спан': 'span', '跨度': 'span', 'スパン': 'span',