ether-code 0.9.6 → 0.9.8
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 +1 -1
- package/generators/html-generator.js +58 -0
- package/generators/php-generator.js +29 -0
- package/lexer/ether-lexer.js +3 -3
- package/package.json +1 -1
- package/parsers/ether-parser-html.js +99 -12
package/cli/ether.js
CHANGED
|
@@ -589,6 +589,12 @@ class HTMLGenerator {
|
|
|
589
589
|
case 'include':
|
|
590
590
|
this.generateInclude(node)
|
|
591
591
|
break
|
|
592
|
+
case 'EtherCSS':
|
|
593
|
+
this.generateEtherCSS(node)
|
|
594
|
+
break
|
|
595
|
+
case 'EtherJS':
|
|
596
|
+
this.generateEtherJS(node)
|
|
597
|
+
break
|
|
592
598
|
default:
|
|
593
599
|
if (node.tag || node.tagName || node.name) {
|
|
594
600
|
this.generateElement(node)
|
|
@@ -1069,6 +1075,58 @@ class HTMLGenerator {
|
|
|
1069
1075
|
})
|
|
1070
1076
|
return result.join('\n')
|
|
1071
1077
|
}
|
|
1078
|
+
|
|
1079
|
+
generateEtherCSS(node) {
|
|
1080
|
+
if (!node.source) return
|
|
1081
|
+
|
|
1082
|
+
try {
|
|
1083
|
+
const { EtherParserCSS } = require('./ether-parser-css')
|
|
1084
|
+
const { CSSGenerator } = require('./css-generator')
|
|
1085
|
+
|
|
1086
|
+
const cssParser = new EtherParserCSS()
|
|
1087
|
+
const cssAst = cssParser.parse(node.source)
|
|
1088
|
+
|
|
1089
|
+
const cssGenerator = new CSSGenerator()
|
|
1090
|
+
cssGenerator.loadI18n('./i18n-css.json')
|
|
1091
|
+
const cssOutput = cssGenerator.generate(cssAst)
|
|
1092
|
+
|
|
1093
|
+
if (cssOutput) {
|
|
1094
|
+
const lines = cssOutput.split('\n')
|
|
1095
|
+
for (const line of lines) {
|
|
1096
|
+
this.writeLine(line)
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
} catch (e) {
|
|
1100
|
+
this.writeLine('/* Erreur de compilation CSS: ' + e.message + ' */')
|
|
1101
|
+
this.writeLine(node.source)
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
generateEtherJS(node) {
|
|
1106
|
+
if (!node.source) return
|
|
1107
|
+
|
|
1108
|
+
try {
|
|
1109
|
+
const { EtherParserJS } = require('./ether-parser-js')
|
|
1110
|
+
const { JSGenerator } = require('./js-generator')
|
|
1111
|
+
|
|
1112
|
+
const jsParser = new EtherParserJS()
|
|
1113
|
+
const jsAst = jsParser.parse(node.source)
|
|
1114
|
+
|
|
1115
|
+
const jsGenerator = new JSGenerator()
|
|
1116
|
+
jsGenerator.loadI18n('./i18n-js.json')
|
|
1117
|
+
const jsOutput = jsGenerator.generate(jsAst)
|
|
1118
|
+
|
|
1119
|
+
if (jsOutput) {
|
|
1120
|
+
const lines = jsOutput.split('\n')
|
|
1121
|
+
for (const line of lines) {
|
|
1122
|
+
this.writeLine(line)
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
} catch (e) {
|
|
1126
|
+
this.writeLine('// Erreur de compilation JS: ' + e.message)
|
|
1127
|
+
this.writeLine(node.source)
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1072
1130
|
}
|
|
1073
1131
|
|
|
1074
1132
|
module.exports = {
|
|
@@ -356,8 +356,10 @@ class PHPGenerator {
|
|
|
356
356
|
this.output = ''
|
|
357
357
|
this.indent = 0
|
|
358
358
|
this.closureVariables = new Set()
|
|
359
|
+
this.importedClasses = new Set()
|
|
359
360
|
|
|
360
361
|
this.collectClosureVariables(ast)
|
|
362
|
+
this.collectImportedClasses(ast)
|
|
361
363
|
|
|
362
364
|
if (ast.phpTag !== false) {
|
|
363
365
|
this.output = '<?php\n'
|
|
@@ -382,6 +384,27 @@ class PHPGenerator {
|
|
|
382
384
|
return this.output.trim()
|
|
383
385
|
}
|
|
384
386
|
|
|
387
|
+
collectImportedClasses(ast) {
|
|
388
|
+
const nodes = Array.isArray(ast) ? ast : (ast?.body || [ast])
|
|
389
|
+
|
|
390
|
+
for (const node of nodes) {
|
|
391
|
+
if (!node) continue
|
|
392
|
+
|
|
393
|
+
if (node.type === 'UseStatement') {
|
|
394
|
+
if (node.imports && node.imports.length > 0) {
|
|
395
|
+
for (const imp of node.imports) {
|
|
396
|
+
const path = imp.path || imp.name || ''
|
|
397
|
+
const className = path.split('\\').pop()
|
|
398
|
+
if (className) this.importedClasses.add(className)
|
|
399
|
+
}
|
|
400
|
+
} else if (node.name) {
|
|
401
|
+
const className = node.name.split('\\').pop()
|
|
402
|
+
if (className) this.importedClasses.add(className)
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
385
408
|
collectClosureVariables(ast) {
|
|
386
409
|
const nodes = Array.isArray(ast) ? ast : (ast?.body || [ast])
|
|
387
410
|
|
|
@@ -963,6 +986,12 @@ class PHPGenerator {
|
|
|
963
986
|
}
|
|
964
987
|
|
|
965
988
|
prefixGlobalClass(name) {
|
|
989
|
+
if (!name) return name
|
|
990
|
+
|
|
991
|
+
if (this.importedClasses && this.importedClasses.has(name)) {
|
|
992
|
+
return name
|
|
993
|
+
}
|
|
994
|
+
|
|
966
995
|
const phpGlobalClasses = [
|
|
967
996
|
'Exception', 'Error', 'TypeError', 'ValueError', 'ArgumentCountError',
|
|
968
997
|
'ArithmeticError', 'DivisionByZeroError', 'ParseError', 'AssertionError',
|
package/lexer/ether-lexer.js
CHANGED
|
@@ -419,7 +419,7 @@ class EtherLexer {
|
|
|
419
419
|
break
|
|
420
420
|
}
|
|
421
421
|
if (this.peek() === '\n') {
|
|
422
|
-
this.tokens.push(new Token(TokenType.ERROR, '
|
|
422
|
+
this.tokens.push(new Token(TokenType.ERROR, 'Chaîne non terminée', startLine, startCol, this.currentIndent))
|
|
423
423
|
return
|
|
424
424
|
}
|
|
425
425
|
}
|
|
@@ -458,7 +458,7 @@ class EtherLexer {
|
|
|
458
458
|
value += String.fromCodePoint(parseInt(unicode, 16))
|
|
459
459
|
break
|
|
460
460
|
default:
|
|
461
|
-
value += escaped
|
|
461
|
+
value += '\\' + escaped
|
|
462
462
|
}
|
|
463
463
|
} else {
|
|
464
464
|
value += this.advance()
|
|
@@ -1001,7 +1001,7 @@ class EtherLexer {
|
|
|
1001
1001
|
break
|
|
1002
1002
|
|
|
1003
1003
|
default:
|
|
1004
|
-
this.tokens.push(new Token(TokenType.ERROR, `
|
|
1004
|
+
this.tokens.push(new Token(TokenType.ERROR, `Caractère inattendu: ${char}`, startLine, startCol, this.currentIndent))
|
|
1005
1005
|
}
|
|
1006
1006
|
}
|
|
1007
1007
|
|
package/package.json
CHANGED
|
@@ -118,14 +118,14 @@ class EtherParserHTML extends EtherParserBase {
|
|
|
118
118
|
'lecture': ['seule', 'auto'],
|
|
119
119
|
'nouvelle': ['fenetre'],
|
|
120
120
|
'a': ['popup'],
|
|
121
|
-
'jeu': ['caracteres', '
|
|
121
|
+
'jeu': ['caracteres', 'caractères'],
|
|
122
122
|
'equivalent': ['http'],
|
|
123
|
-
'
|
|
123
|
+
'équivalent': ['http'],
|
|
124
124
|
'fusion': ['colonnes', 'lignes'],
|
|
125
|
-
'plein': ['ecran', '
|
|
125
|
+
'plein': ['ecran', 'écran'],
|
|
126
126
|
'bac': ['sable'],
|
|
127
|
-
'origine': ['croisee', '
|
|
128
|
-
'sources': ['reactives', '
|
|
127
|
+
'origine': ['croisee', 'croisée'],
|
|
128
|
+
'sources': ['reactives', 'réactives']
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
while (!this.isAtEnd()) {
|
|
@@ -203,9 +203,22 @@ class EtherParserHTML extends EtherParserBase {
|
|
|
203
203
|
const rawContentTags = ['script', 'style']
|
|
204
204
|
const isRawContent = rawContentTags.includes(tag)
|
|
205
205
|
const isScript = tag === 'script'
|
|
206
|
+
const isStyle = tag === 'style'
|
|
206
207
|
|
|
207
208
|
if (this.match(TokenType.INDENT)) {
|
|
208
|
-
if (
|
|
209
|
+
if (isStyle) {
|
|
210
|
+
const etherSource = this.collectEtherBlock()
|
|
211
|
+
children.push({
|
|
212
|
+
type: 'EtherCSS',
|
|
213
|
+
source: etherSource
|
|
214
|
+
})
|
|
215
|
+
} else if (isScript) {
|
|
216
|
+
const etherSource = this.collectEtherBlock()
|
|
217
|
+
children.push({
|
|
218
|
+
type: 'EtherJS',
|
|
219
|
+
source: etherSource
|
|
220
|
+
})
|
|
221
|
+
} else if (isRawContent) {
|
|
209
222
|
let rawText = []
|
|
210
223
|
while (!this.isAtEnd()) {
|
|
211
224
|
const current = this.current()
|
|
@@ -227,11 +240,7 @@ class EtherParserHTML extends EtherParserBase {
|
|
|
227
240
|
}
|
|
228
241
|
|
|
229
242
|
if (current && current.type === TokenType.STRING) {
|
|
230
|
-
|
|
231
|
-
rawText.push("'" + current.value.replace(/'/g, "\\'") + "'")
|
|
232
|
-
} else {
|
|
233
|
-
rawText.push(current.value)
|
|
234
|
-
}
|
|
243
|
+
rawText.push(current.value)
|
|
235
244
|
this.advance()
|
|
236
245
|
continue
|
|
237
246
|
}
|
|
@@ -321,6 +330,84 @@ class EtherParserHTML extends EtherParserBase {
|
|
|
321
330
|
return String(token.value)
|
|
322
331
|
}
|
|
323
332
|
|
|
333
|
+
collectEtherBlock() {
|
|
334
|
+
const lines = []
|
|
335
|
+
let currentLine = []
|
|
336
|
+
let indentDepth = 1
|
|
337
|
+
|
|
338
|
+
while (!this.isAtEnd()) {
|
|
339
|
+
const current = this.current()
|
|
340
|
+
|
|
341
|
+
if (current && current.type === TokenType.DEDENT) {
|
|
342
|
+
if (currentLine.length > 0) {
|
|
343
|
+
lines.push(' '.repeat(Math.max(0, indentDepth - 1)) + this.joinTokens(currentLine))
|
|
344
|
+
currentLine = []
|
|
345
|
+
}
|
|
346
|
+
indentDepth--
|
|
347
|
+
this.advance()
|
|
348
|
+
if (indentDepth <= 0) {
|
|
349
|
+
break
|
|
350
|
+
}
|
|
351
|
+
continue
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if (current && current.type === TokenType.INDENT) {
|
|
355
|
+
if (currentLine.length > 0) {
|
|
356
|
+
lines.push(' '.repeat(Math.max(0, indentDepth - 1)) + this.joinTokens(currentLine))
|
|
357
|
+
currentLine = []
|
|
358
|
+
}
|
|
359
|
+
indentDepth++
|
|
360
|
+
this.advance()
|
|
361
|
+
continue
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (current && current.type === TokenType.NEWLINE) {
|
|
365
|
+
if (currentLine.length > 0) {
|
|
366
|
+
lines.push(' '.repeat(Math.max(0, indentDepth - 1)) + this.joinTokens(currentLine))
|
|
367
|
+
currentLine = []
|
|
368
|
+
}
|
|
369
|
+
this.advance()
|
|
370
|
+
continue
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (!current || current.type === TokenType.EOF) break
|
|
374
|
+
|
|
375
|
+
if (current.type === TokenType.STRING) {
|
|
376
|
+
currentLine.push('"' + current.value + '"')
|
|
377
|
+
} else {
|
|
378
|
+
currentLine.push(this.tokenToString(current))
|
|
379
|
+
}
|
|
380
|
+
this.advance()
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (currentLine.length > 0) {
|
|
384
|
+
lines.push(' '.repeat(Math.max(0, indentDepth - 1)) + this.joinTokens(currentLine))
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return lines.join('\n')
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
joinTokens(tokens) {
|
|
391
|
+
let result = ''
|
|
392
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
393
|
+
const token = tokens[i]
|
|
394
|
+
const prevToken = i > 0 ? tokens[i - 1] : null
|
|
395
|
+
|
|
396
|
+
const noSpaceBefore = [':', ',', ')', ']']
|
|
397
|
+
const noSpaceAfter = ['.', '#', '(', '[', '::', '-']
|
|
398
|
+
|
|
399
|
+
if (i > 0) {
|
|
400
|
+
const needSpace = !noSpaceBefore.includes(token) && !noSpaceAfter.includes(prevToken)
|
|
401
|
+
if (needSpace) {
|
|
402
|
+
result += ' '
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
result += token
|
|
407
|
+
}
|
|
408
|
+
return result
|
|
409
|
+
}
|
|
410
|
+
|
|
324
411
|
processCompoundTags(tagName) {
|
|
325
412
|
const nextToken = this.current()
|
|
326
413
|
if (!nextToken || nextToken.type !== TokenType.IDENTIFIER) {
|
|
@@ -585,4 +672,4 @@ class EtherParserHTML extends EtherParserBase {
|
|
|
585
672
|
}
|
|
586
673
|
}
|
|
587
674
|
|
|
588
|
-
module.exports = { EtherParserHTML }
|
|
675
|
+
module.exports = { EtherParserHTML }
|