ether-code 0.8.1 → 0.8.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
@@ -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.8.1'
9
+ const VERSION = '0.8.3'
10
10
 
11
11
  const COLORS = {
12
12
  reset: '\x1b[0m',
@@ -46,7 +46,8 @@ class PHPGenerator {
46
46
  }
47
47
 
48
48
  translate(word) {
49
- if (!word || typeof word !== 'string') return word
49
+ if (!word) return word
50
+ if (typeof word !== 'string') return String(word)
50
51
 
51
52
  const normalized = word.toLowerCase().trim()
52
53
 
@@ -63,6 +64,7 @@ class PHPGenerator {
63
64
  }
64
65
 
65
66
  removeAccents(str) {
67
+ if (typeof str !== 'string') return String(str)
66
68
  return str.normalize('NFD').replace(/[\u0300-\u036f]/g, '')
67
69
  }
68
70
 
@@ -140,12 +142,19 @@ class PHPGenerator {
140
142
  'ArrayExpression': () => this.generateArrayExpression(node),
141
143
  'ObjectExpression': () => this.generateObjectExpression(node),
142
144
  'ArrowFunction': () => this.generateArrowFunction(node),
145
+ 'ArrowFunctionExpression': () => this.generateArrowFunction(node),
143
146
  'Closure': () => this.generateClosure(node),
147
+ 'FunctionExpression': () => this.generateClosure(node),
144
148
  'Identifier': () => this.generateIdentifier(node),
149
+ 'Variable': () => this.generateVariable(node),
145
150
  'Literal': () => this.generateLiteral(node),
151
+ 'StringLiteral': () => this.generateStringLiteral(node),
146
152
  'NewExpression': () => this.generateNewExpression(node),
147
153
  'InstanceOf': () => this.generateInstanceOf(node),
148
154
  'BlockStatement': () => this.generateBlockStatement(node),
155
+ 'ThisExpression': () => '$this',
156
+ 'StaticMemberExpression': () => this.generateStaticMemberExpression(node),
157
+ 'IndexExpression': () => this.generateIndexExpression(node),
149
158
  'EmptyStatement': () => '',
150
159
  'Comment': () => ''
151
160
  }
@@ -168,11 +177,12 @@ class PHPGenerator {
168
177
  }
169
178
 
170
179
  generateFunctionDeclaration(node) {
171
- const name = this.translate(node.name || node.id?.name || 'anonymous')
180
+ const name = this.safeString(node.name || node.id?.name || 'anonymous')
181
+ const translatedName = this.translate(name)
172
182
  const params = this.generateParams(node.params || [])
173
183
  const returnType = node.returnType ? ': ' + this.translateType(node.returnType) : ''
174
184
 
175
- this.writeLine(`function ${name}(${params})${returnType} {`)
185
+ this.writeLine(`function ${translatedName}(${params})${returnType} {`)
176
186
  this.indent++
177
187
  this.generateNode(node.body)
178
188
  this.indent--
@@ -200,8 +210,8 @@ class PHPGenerator {
200
210
  result += '&'
201
211
  }
202
212
 
203
- const name = p.name || p.id?.name || p
204
- result += '$' + this.translate(typeof name === 'string' ? name : name.name || 'param')
213
+ const name = this.safeString(p.name || p.id?.name || p)
214
+ result += '$' + this.translate(name)
205
215
 
206
216
  if (p.default !== undefined) {
207
217
  result += ' = ' + this.generateNode(p.default)
@@ -211,6 +221,14 @@ class PHPGenerator {
211
221
  }).join(', ')
212
222
  }
213
223
 
224
+ safeString(value) {
225
+ if (typeof value === 'string') return value
226
+ if (value && typeof value === 'object') {
227
+ return value.name || value.value || 'unknown'
228
+ }
229
+ return String(value || 'unknown')
230
+ }
231
+
214
232
  translateType(type) {
215
233
  if (!type) return ''
216
234
 
@@ -230,7 +248,8 @@ class PHPGenerator {
230
248
  'itérable': 'iterable', 'iterable': 'iterable',
231
249
  'jamais': 'never', 'never': 'never'
232
250
  }
233
- return typeMap[translated.toLowerCase()] || typeMap[type.toLowerCase()] || type
251
+ const lower = translated.toLowerCase()
252
+ return typeMap[lower] || typeMap[type.toLowerCase()] || type
234
253
  }
235
254
 
236
255
  if (type.union) {
@@ -245,7 +264,11 @@ class PHPGenerator {
245
264
  return '?' + this.translateType(type.type)
246
265
  }
247
266
 
248
- return type.name || type
267
+ if (type.name) {
268
+ return this.translateType(type.name)
269
+ }
270
+
271
+ return String(type)
249
272
  }
250
273
 
251
274
  generateClassDeclaration(node) {
@@ -255,14 +278,15 @@ class PHPGenerator {
255
278
  if (node.final) declaration += 'final '
256
279
  if (node.readonly) declaration += 'readonly '
257
280
 
258
- declaration += 'class ' + this.translate(node.name || node.id?.name)
281
+ const className = this.safeString(node.name || node.id?.name)
282
+ declaration += 'class ' + this.translate(className)
259
283
 
260
284
  if (node.extends) {
261
- declaration += ' extends ' + this.translate(node.extends)
285
+ declaration += ' extends ' + this.translate(this.safeString(node.extends))
262
286
  }
263
287
 
264
288
  if (node.implements && node.implements.length > 0) {
265
- declaration += ' implements ' + node.implements.map(i => this.translate(i)).join(', ')
289
+ declaration += ' implements ' + node.implements.map(i => this.translate(this.safeString(i))).join(', ')
266
290
  }
267
291
 
268
292
  this.writeLine(declaration + ' {')
@@ -278,10 +302,11 @@ class PHPGenerator {
278
302
  }
279
303
 
280
304
  generateInterfaceDeclaration(node) {
281
- let declaration = 'interface ' + this.translate(node.name || node.id?.name)
305
+ const name = this.safeString(node.name || node.id?.name)
306
+ let declaration = 'interface ' + this.translate(name)
282
307
 
283
308
  if (node.extends && node.extends.length > 0) {
284
- declaration += ' extends ' + node.extends.map(e => this.translate(e)).join(', ')
309
+ declaration += ' extends ' + node.extends.map(e => this.translate(this.safeString(e))).join(', ')
285
310
  }
286
311
 
287
312
  this.writeLine(declaration + ' {')
@@ -297,7 +322,8 @@ class PHPGenerator {
297
322
  }
298
323
 
299
324
  generateTraitDeclaration(node) {
300
- this.writeLine('trait ' + this.translate(node.name || node.id?.name) + ' {')
325
+ const name = this.safeString(node.name || node.id?.name)
326
+ this.writeLine('trait ' + this.translate(name) + ' {')
301
327
  this.indent++
302
328
 
303
329
  for (const member of node.body || node.members || []) {
@@ -310,7 +336,8 @@ class PHPGenerator {
310
336
  }
311
337
 
312
338
  generateEnumDeclaration(node) {
313
- let declaration = 'enum ' + this.translate(node.name || node.id?.name)
339
+ const name = this.safeString(node.name || node.id?.name)
340
+ let declaration = 'enum ' + this.translate(name)
314
341
 
315
342
  if (node.backingType) {
316
343
  declaration += ': ' + this.translateType(node.backingType)
@@ -346,7 +373,7 @@ class PHPGenerator {
346
373
  if (node.final) declaration += 'final '
347
374
  if (node.abstract) declaration += 'abstract '
348
375
 
349
- const name = this.translateMethodName(node.name || node.key?.name)
376
+ const name = this.translateMethodName(this.safeString(node.name || node.key?.name))
350
377
  const params = this.generateParams(node.params || node.value?.params || [])
351
378
  const returnType = node.returnType ? ': ' + this.translateType(node.returnType) : ''
352
379
 
@@ -425,8 +452,8 @@ class PHPGenerator {
425
452
  declaration += this.translateType(node.type) + ' '
426
453
  }
427
454
 
428
- const name = this.translate(node.name || node.key?.name)
429
- declaration += '$' + name
455
+ const name = this.safeString(node.name || node.key?.name)
456
+ declaration += '$' + this.translate(name)
430
457
 
431
458
  if (node.value !== undefined) {
432
459
  declaration += ' = ' + this.generateNode(node.value)
@@ -437,8 +464,8 @@ class PHPGenerator {
437
464
 
438
465
  generateVariableDeclaration(node) {
439
466
  for (const decl of node.declarations || [node]) {
440
- const name = decl.name || decl.id?.name || decl.id
441
- const varName = '$' + this.translate(typeof name === 'string' ? name : name.name || 'var')
467
+ const name = this.safeString(decl.name || decl.id?.name || decl.id)
468
+ const varName = '$' + this.translate(name)
442
469
 
443
470
  if (decl.init !== undefined) {
444
471
  const value = this.generateNode(decl.init)
@@ -450,7 +477,7 @@ class PHPGenerator {
450
477
  }
451
478
 
452
479
  generateConstantDeclaration(node) {
453
- const name = node.name || node.id?.name
480
+ const name = this.safeString(node.name || node.id?.name)
454
481
  const value = this.generateNode(node.value || node.init)
455
482
 
456
483
  if (node.classLevel) {
@@ -498,8 +525,8 @@ class PHPGenerator {
498
525
 
499
526
  generateForEachStatement(node) {
500
527
  const array = this.generateNode(node.array || node.right || node.iterable)
501
- const value = this.generateIdentifier(node.value || node.left || node.valueVar)
502
- const key = node.key || node.keyVar ? this.generateIdentifier(node.key || node.keyVar) + ' => ' : ''
528
+ const value = this.generateVariable(node.value || node.left || node.valueVar)
529
+ const key = node.key || node.keyVar ? this.generateVariable(node.key || node.keyVar) + ' => ' : ''
503
530
 
504
531
  this.writeLine(`foreach (${array} as ${key}${value}) {`)
505
532
  this.indent++
@@ -576,7 +603,7 @@ class PHPGenerator {
576
603
 
577
604
  for (const handler of node.handlers || (node.handler ? [node.handler] : [])) {
578
605
  const exceptionType = handler.type || handler.param?.type || 'Exception'
579
- const param = handler.param ? this.generateIdentifier(handler.param) : '$e'
606
+ const param = handler.param ? this.generateVariable(handler.param) : '$e'
580
607
  this.writeLine(`} catch (${exceptionType} ${param}) {`)
581
608
  this.indent++
582
609
  this.generateNode(handler.body)
@@ -623,12 +650,13 @@ class PHPGenerator {
623
650
  }
624
651
 
625
652
  generateNamespace(node) {
626
- this.writeLine(`namespace ${node.name};`)
653
+ const name = this.safeString(node.name)
654
+ this.writeLine(`namespace ${name};`)
627
655
  this.writeLine('')
628
656
  }
629
657
 
630
658
  generateUseStatement(node) {
631
- const name = node.name || node.source
659
+ const name = this.safeString(node.name || node.source)
632
660
  const alias = node.alias ? ' as ' + node.alias : ''
633
661
  const type = node.type === 'function' ? 'function ' : (node.type === 'const' ? 'const ' : '')
634
662
  this.writeLine(`use ${type}${name}${alias};`)
@@ -655,17 +683,19 @@ class PHPGenerator {
655
683
 
656
684
  if (typeof node.callee === 'string') {
657
685
  callee = this.translate(node.callee)
658
- } else if (node.callee.type === 'MemberExpression') {
686
+ } else if (node.callee && node.callee.type === 'MemberExpression') {
659
687
  callee = this.generateMemberExpression(node.callee)
688
+ } else if (node.callee && node.callee.type === 'StaticMemberExpression') {
689
+ callee = this.generateStaticMemberExpression(node.callee)
660
690
  } else {
661
691
  callee = this.generateNode(node.callee)
662
692
  }
663
693
 
664
694
  const args = (node.arguments || []).map(a => {
665
- if (a.spread) {
695
+ if (a && a.type === 'SpreadElement') {
666
696
  return '...' + this.generateNode(a.argument || a)
667
697
  }
668
- if (a.name && a.value) {
698
+ if (a && a.type === 'NamedArgument') {
669
699
  return `${a.name}: ${this.generateNode(a.value)}`
670
700
  }
671
701
  return this.generateNode(a)
@@ -676,9 +706,15 @@ class PHPGenerator {
676
706
 
677
707
  generateMemberExpression(node) {
678
708
  const object = this.generateNode(node.object)
679
- const property = typeof node.property === 'string'
680
- ? node.property
681
- : this.generateNode(node.property)
709
+ let property
710
+
711
+ if (typeof node.property === 'string') {
712
+ property = node.property
713
+ } else if (node.property && node.property.name) {
714
+ property = node.property.name
715
+ } else {
716
+ property = this.generateNode(node.property)
717
+ }
682
718
 
683
719
  if (node.static) {
684
720
  return `${object}::${property}`
@@ -686,12 +722,33 @@ class PHPGenerator {
686
722
  if (node.computed) {
687
723
  return `${object}[${property}]`
688
724
  }
689
- if (node.nullSafe) {
725
+ if (node.nullsafe || node.operator === '?->') {
690
726
  return `${object}?->${property}`
691
727
  }
692
728
  return `${object}->${property}`
693
729
  }
694
730
 
731
+ generateStaticMemberExpression(node) {
732
+ const cls = this.generateNode(node.class)
733
+ let member
734
+
735
+ if (typeof node.member === 'string') {
736
+ member = node.member
737
+ } else if (node.member && node.member.name) {
738
+ member = node.member.name
739
+ } else {
740
+ member = this.generateNode(node.member)
741
+ }
742
+
743
+ return `${cls}::${member}`
744
+ }
745
+
746
+ generateIndexExpression(node) {
747
+ const object = this.generateNode(node.object)
748
+ const index = node.index ? this.generateNode(node.index) : ''
749
+ return `${object}[${index}]`
750
+ }
751
+
695
752
  generateBinaryExpression(node) {
696
753
  const left = this.generateNode(node.left)
697
754
  const right = this.generateNode(node.right)
@@ -708,14 +765,16 @@ class PHPGenerator {
708
765
  'fusion null': '??', 'null coalescing': '??'
709
766
  }
710
767
 
711
- op = opMap[op?.toLowerCase()] || op
768
+ const opLower = op ? op.toLowerCase() : op
769
+ op = opMap[opLower] || op
712
770
 
713
771
  return `${left} ${op} ${right}`
714
772
  }
715
773
 
716
774
  generateUnaryExpression(node) {
717
775
  const argument = this.generateNode(node.argument)
718
- const op = node.operator === 'non' || node.operator === 'not' ? '!' : node.operator
776
+ let op = node.operator
777
+ if (op === 'non' || op === 'not') op = '!'
719
778
 
720
779
  if (node.prefix) {
721
780
  return `${op}${argument}`
@@ -756,14 +815,22 @@ class PHPGenerator {
756
815
  generateArrayExpression(node) {
757
816
  const elements = (node.elements || []).map(e => {
758
817
  if (!e) return 'null'
759
- if (e.key !== undefined) {
818
+ if (e.type === 'SpreadElement') {
819
+ return '...' + this.generateNode(e.argument || e)
820
+ }
821
+ if (e.type === 'ArrayElement') {
822
+ if (e.key !== null && e.key !== undefined) {
823
+ const key = this.generateNode(e.key)
824
+ const value = this.generateNode(e.value)
825
+ return `${key} => ${value}`
826
+ }
827
+ return this.generateNode(e.value)
828
+ }
829
+ if (e.key !== undefined && e.key !== null) {
760
830
  const key = this.generateNode(e.key)
761
831
  const value = this.generateNode(e.value || e)
762
832
  return `${key} => ${value}`
763
833
  }
764
- if (e.spread) {
765
- return '...' + this.generateNode(e.argument || e)
766
- }
767
834
  return this.generateNode(e)
768
835
  })
769
836
 
@@ -786,19 +853,19 @@ class PHPGenerator {
786
853
 
787
854
  generateClosure(node) {
788
855
  const params = this.generateParams(node.params || [])
789
- const useVars = node.use && node.use.length > 0
790
- ? ` use (${node.use.map(u => (u.byRef ? '&' : '') + '$' + this.translate(u.name || u)).join(', ')})`
856
+ const useVars = node.uses && node.uses.length > 0
857
+ ? ` use (${node.uses.map(u => (u.byRef ? '&' : '') + '$' + this.translate(this.safeString(u.name || u))).join(', ')})`
791
858
  : ''
792
859
  const returnType = node.returnType ? ': ' + this.translateType(node.returnType) : ''
793
860
 
794
861
  let result = `function(${params})${useVars}${returnType} {\n`
795
862
  this.indent++
796
863
 
797
- if (Array.isArray(node.body)) {
798
- for (const stmt of node.body) {
864
+ if (node.body && Array.isArray(node.body.body)) {
865
+ for (const stmt of node.body.body) {
799
866
  result += this.getIndent() + this.generateNode(stmt)
800
867
  }
801
- } else {
868
+ } else if (node.body) {
802
869
  result += this.getIndent() + 'return ' + this.generateNode(node.body) + ';\n'
803
870
  }
804
871
 
@@ -807,34 +874,47 @@ class PHPGenerator {
807
874
  return result
808
875
  }
809
876
 
877
+ generateVariable(node) {
878
+ if (!node) return '$var'
879
+
880
+ const name = this.safeString(node.name || node.id?.name || node)
881
+ const translated = this.translate(name)
882
+ const translatedStr = String(translated)
883
+
884
+ if (translatedStr.startsWith('$')) return translatedStr
885
+ return '$' + translatedStr
886
+ }
887
+
810
888
  generateIdentifier(node) {
811
- const name = node.name || node.id?.name || node
812
- if (typeof name !== 'string') return '$var'
889
+ if (!node) return '$var'
813
890
 
891
+ const name = this.safeString(node.name || node.id?.name || node)
814
892
  const translated = this.translate(name)
893
+ const translatedStr = String(translated)
815
894
 
816
- if (translated.startsWith('$')) return translated
895
+ if (translatedStr.startsWith('$')) return translatedStr
817
896
 
818
897
  const keywords = [
819
898
  'true', 'false', 'null',
820
899
  'self', 'parent', 'static',
821
900
  'this', '$this'
822
901
  ]
823
- if (keywords.includes(translated.toLowerCase())) {
824
- if (translated.toLowerCase() === 'this') return '$this'
825
- return translated
902
+ if (keywords.includes(translatedStr.toLowerCase())) {
903
+ if (translatedStr.toLowerCase() === 'this') return '$this'
904
+ return translatedStr
826
905
  }
827
906
 
828
- if (/^[A-Z]/.test(translated)) return translated
907
+ if (/^[A-Z]/.test(translatedStr)) return translatedStr
829
908
 
830
- if (translated.includes('(') || translated.includes('::')) return translated
909
+ if (translatedStr.includes('(') || translatedStr.includes('::')) return translatedStr
831
910
 
832
911
  const superglobals = ['_GET', '_POST', '_SERVER', '_SESSION', '_COOKIE', '_FILES', '_REQUEST', '_ENV', 'GLOBALS']
833
- if (superglobals.includes(translated) || superglobals.includes(translated.toUpperCase())) {
834
- return '$' + translated.toUpperCase()
912
+ const upper = translatedStr.toUpperCase()
913
+ if (superglobals.includes(translatedStr) || superglobals.includes(upper)) {
914
+ return '$' + upper
835
915
  }
836
916
 
837
- return '$' + translated
917
+ return '$' + translatedStr
838
918
  }
839
919
 
840
920
  generateLiteral(node) {
@@ -854,10 +934,26 @@ class PHPGenerator {
854
934
  return String(node.value)
855
935
  }
856
936
 
937
+ generateStringLiteral(node) {
938
+ const value = node.value || ''
939
+ const escaped = value
940
+ .replace(/\\/g, '\\\\')
941
+ .replace(/"/g, '\\"')
942
+ .replace(/\n/g, '\\n')
943
+ .replace(/\r/g, '\\r')
944
+ .replace(/\t/g, '\\t')
945
+ return node.doubleQuoted !== false ? `"${escaped}"` : `'${escaped}'`
946
+ }
947
+
857
948
  generateNewExpression(node) {
858
- const callee = typeof node.callee === 'string'
859
- ? this.translate(node.callee)
860
- : this.generateNode(node.callee)
949
+ let callee
950
+ if (typeof node.callee === 'string') {
951
+ callee = this.translate(node.callee)
952
+ } else if (node.callee && node.callee.name) {
953
+ callee = this.translate(node.callee.name)
954
+ } else {
955
+ callee = this.generateNode(node.callee)
956
+ }
861
957
  const args = (node.arguments || []).map(a => this.generateNode(a)).join(', ')
862
958
  return `new ${callee}(${args})`
863
959
  }
@@ -887,6 +983,4 @@ class PHPGenerator {
887
983
  }
888
984
  }
889
985
 
890
- module.exports = {
891
- PHPGenerator
892
- }
986
+ module.exports = { PHPGenerator }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ether-code",
3
- "version": "0.8.1",
3
+ "version": "0.8.3",
4
4
  "description": "Ether - Le langage intentionnel",
5
5
  "main": "cli/compiler.js",
6
6
  "bin": {
@@ -226,6 +226,12 @@ class EtherParserPHP extends EtherParserBase {
226
226
  this.phpModifiers = ['statique', 'static', 'final', 'finale', 'abstrait', 'abstraite', 'abstract', 'readonly', 'lecture seule']
227
227
  }
228
228
 
229
+ safeStr(val) {
230
+ if (typeof val === 'string') return val
231
+ if (val && typeof val === 'object') return String(val.name || val.value || '')
232
+ return String(val || '')
233
+ }
234
+
229
235
  translatePHP(word) {
230
236
  if (!word) return word
231
237
  const lower = this.normalizeAccents(String(word))
@@ -736,7 +742,7 @@ class EtherParserPHP extends EtherParserBase {
736
742
  }
737
743
 
738
744
  const nameToken = this.current()
739
- let name = nameToken ? nameToken.value : 'property'
745
+ let name = this.safeStr(nameToken ? nameToken.value : 'property')
740
746
 
741
747
  if (name.startsWith('$')) {
742
748
  name = name.substring(1)
@@ -1047,7 +1053,7 @@ class EtherParserPHP extends EtherParserBase {
1047
1053
  }
1048
1054
 
1049
1055
  const varToken = this.current()
1050
- let varName = varToken ? varToken.value : ''
1056
+ let varName = this.safeStr(varToken ? varToken.value : '')
1051
1057
  if (varName.startsWith('$')) {
1052
1058
  varName = varName.substring(1)
1053
1059
  }
@@ -1126,7 +1132,7 @@ class EtherParserPHP extends EtherParserBase {
1126
1132
  const nameToken = this.current()
1127
1133
  if (!nameToken) return null
1128
1134
 
1129
- let name = nameToken.value
1135
+ let name = this.safeStr(nameToken.value)
1130
1136
  if (name.startsWith('$')) {
1131
1137
  name = name.substring(1)
1132
1138
  }
@@ -1218,7 +1224,7 @@ class EtherParserPHP extends EtherParserBase {
1218
1224
  }
1219
1225
 
1220
1226
  const nameToken = this.current()
1221
- let name = nameToken ? nameToken.value : 'variable'
1227
+ let name = this.safeStr(nameToken ? nameToken.value : 'variable')
1222
1228
  if (name.startsWith('$')) {
1223
1229
  name = name.substring(1)
1224
1230
  }
@@ -1372,7 +1378,7 @@ class EtherParserPHP extends EtherParserBase {
1372
1378
  }
1373
1379
 
1374
1380
  const firstVar = this.current()
1375
- let firstName = firstVar ? firstVar.value : 'item'
1381
+ let firstName = this.safeStr(firstVar ? firstVar.value : 'item')
1376
1382
  if (firstName.startsWith('$')) firstName = firstName.substring(1)
1377
1383
  this.advance()
1378
1384
 
@@ -1384,7 +1390,7 @@ class EtherParserPHP extends EtherParserBase {
1384
1390
  }
1385
1391
 
1386
1392
  const valueVar = this.current()
1387
- value = valueVar ? valueVar.value : 'value'
1393
+ let value = this.safeStr(valueVar ? valueVar.value : 'value')
1388
1394
  if (value.startsWith('$')) value = value.substring(1)
1389
1395
  this.advance()
1390
1396
  } else {
@@ -1632,7 +1638,7 @@ class EtherParserPHP extends EtherParserBase {
1632
1638
  do {
1633
1639
  const typeToken = this.current()
1634
1640
  if (typeToken && typeToken.type === TokenType.IDENTIFIER) {
1635
- const typeName = typeToken.value
1641
+ const typeName = this.safeStr(typeToken.value)
1636
1642
  if (typeName.startsWith('$')) {
1637
1643
  param = typeName.substring(1)
1638
1644
  } else {
@@ -1645,7 +1651,7 @@ class EtherParserPHP extends EtherParserBase {
1645
1651
  if (!param) {
1646
1652
  const paramToken = this.current()
1647
1653
  if (paramToken && paramToken.type === TokenType.IDENTIFIER) {
1648
- param = paramToken.value
1654
+ param = this.safeStr(paramToken.value)
1649
1655
  if (param.startsWith('$')) param = param.substring(1)
1650
1656
  this.advance()
1651
1657
  }
@@ -1759,7 +1765,7 @@ class EtherParserPHP extends EtherParserBase {
1759
1765
  const variables = []
1760
1766
  do {
1761
1767
  const varToken = this.current()
1762
- let varName = varToken ? varToken.value : ''
1768
+ let varName = this.safeStr(varToken ? varToken.value : '')
1763
1769
  if (varName.startsWith('$')) varName = varName.substring(1)
1764
1770
  this.advance()
1765
1771
  variables.push(varName)
@@ -2209,11 +2215,11 @@ class EtherParserPHP extends EtherParserBase {
2209
2215
 
2210
2216
  if (token.type === TokenType.STRING) {
2211
2217
  this.advance()
2212
- let value = token.value
2218
+ let value = this.safeStr(token.value)
2213
2219
  if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
2214
2220
  value = value.slice(1, -1)
2215
2221
  }
2216
- const isDouble = token.value.startsWith('"')
2222
+ const isDouble = value.startsWith('"') || this.safeStr(token.value).startsWith('"')
2217
2223
  return { type: 'StringLiteral', value, doubleQuoted: isDouble }
2218
2224
  }
2219
2225
 
@@ -2223,7 +2229,7 @@ class EtherParserPHP extends EtherParserBase {
2223
2229
  }
2224
2230
 
2225
2231
  if (token.type === TokenType.IDENTIFIER) {
2226
- const value = token.value
2232
+ const value = this.safeStr(token.value)
2227
2233
  const valueLower = this.normalizeAccents(value.toLowerCase())
2228
2234
 
2229
2235
  if (valueLower === 'vrai' || valueLower === 'true') {
@@ -2285,7 +2291,7 @@ class EtherParserPHP extends EtherParserBase {
2285
2291
 
2286
2292
  if (token.type === TokenType.VARIABLE) {
2287
2293
  this.advance()
2288
- let name = token.value
2294
+ let name = this.safeStr(token.value)
2289
2295
  if (name.startsWith('$')) name = name.substring(1)
2290
2296
  return { type: 'Variable', name }
2291
2297
  }
@@ -30,13 +30,23 @@ class EtherParser {
30
30
  if (!this.parsers[lang]) {
31
31
  switch (lang) {
32
32
  case 'js':
33
+ this.parsers[lang] = new EtherParserJS(this.options)
34
+ break
33
35
  case 'ts':
36
+ this.parsers[lang] = new EtherParserJS(this.options)
37
+ break
34
38
  case 'react':
39
+ this.parsers[lang] = new EtherParserJS(this.options)
40
+ break
35
41
  case 'node':
42
+ this.parsers[lang] = new EtherParserJS(this.options)
43
+ break
36
44
  case 'php':
37
45
  this.parsers[lang] = new EtherParserPHP(this.options)
38
46
  break
39
47
  case 'python':
48
+ this.parsers[lang] = new EtherParserJS(this.options)
49
+ break
40
50
  case 'ruby':
41
51
  this.parsers[lang] = new EtherParserJS(this.options)
42
52
  break
@@ -53,15 +63,13 @@ class EtherParser {
53
63
  this.parsers[lang] = new EtherParserGraphQL(this.options)
54
64
  break
55
65
  default:
56
- this.parsers[lang] = new EtherParserJS(this.options)
66
+ this.parsers[lang] = new EtherParserHTML(this.options)
57
67
  }
58
68
  }
59
69
  return this.parsers[lang]
60
70
  }
61
71
 
62
72
  detectTargetLanguage(source) {
63
- const lower = source.toLowerCase()
64
-
65
73
  const targetMatch = source.match(/\/\/\s*cible\s*:\s*(\w+)/i)
66
74
  if (targetMatch) {
67
75
  const target = targetMatch[1].toLowerCase()
@@ -83,6 +91,8 @@ class EtherParser {
83
91
  }
84
92
  }
85
93
 
94
+ const lower = source.toLowerCase()
95
+
86
96
  if (/^\s*(document|page|<!doctype|<html|tete|corps|entete|navigation|section|article)/m.test(lower)) {
87
97
  return 'html'
88
98
  }
@@ -133,7 +143,7 @@ class EtherParser {
133
143
  return 'js'
134
144
  }
135
145
 
136
- return 'js'
146
+ return 'html'
137
147
  }
138
148
 
139
149
  parse(source, targetLang = null) {
@@ -145,4 +155,4 @@ class EtherParser {
145
155
  }
146
156
  }
147
157
 
148
- module.exports = { EtherParser, TokenType }
158
+ module.exports = { EtherParser, TokenType }