ether-code 0.1.6 → 0.1.7
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/css-generator.js +42 -55
- package/generators/graphql-generator.js +19 -22
- package/generators/html-generator.js +51 -220
- package/generators/js-generator.js +76 -157
- package/generators/node-generator.js +49 -93
- package/generators/php-generator.js +46 -68
- package/generators/python-generator.js +35 -54
- package/generators/react-generator.js +37 -47
- package/generators/ruby-generator.js +59 -119
- package/generators/sql-generator.js +42 -63
- package/generators/ts-generator.js +59 -133
- package/i18n/i18n-css.json +147 -147
- package/i18n/i18n-graphql.json +6 -6
- package/i18n/i18n-html.json +135 -135
- package/i18n/i18n-js.json +107 -107
- package/i18n/i18n-node.json +14 -14
- package/i18n/i18n-php.json +177 -177
- package/i18n/i18n-python.json +16 -16
- package/i18n/i18n-react.json +97 -97
- package/i18n/i18n-ruby.json +22 -22
- package/i18n/i18n-sql.json +153 -153
- package/i18n/i18n-ts.json +10 -10
- package/lexer/ether-lexer.js +175 -34
- package/lexer/tokens.js +6 -6
- package/package.json +1 -1
- package/parsers/ast-css.js +0 -545
- package/parsers/ast-graphql.js +0 -424
- package/parsers/ast-html.js +0 -886
- package/parsers/ast-js.js +0 -750
- package/parsers/ast-node.js +0 -2440
- package/parsers/ast-php.js +0 -957
- package/parsers/ast-react.js +0 -580
- package/parsers/ast-ruby.js +0 -895
- package/parsers/ast-ts.js +0 -1352
- package/parsers/css-parser.js +0 -1981
- package/parsers/graphql-parser.js +0 -2011
- package/parsers/html-parser.js +0 -1182
- package/parsers/js-parser.js +0 -2564
- package/parsers/node-parser.js +0 -2644
- package/parsers/php-parser.js +0 -3037
- package/parsers/react-parser.js +0 -1035
- package/parsers/ruby-parser.js +0 -2680
- package/parsers/ts-parser.js +0 -3881
|
@@ -5,54 +5,12 @@ class JSGenerator {
|
|
|
5
5
|
this.i18n = null
|
|
6
6
|
this.indent = 0
|
|
7
7
|
this.output = ''
|
|
8
|
-
this.keywordMap = {}
|
|
9
|
-
this.methodMap = {}
|
|
10
|
-
this.operatorMap = {}
|
|
11
|
-
|
|
12
|
-
this.buildGenericMaps()
|
|
13
8
|
|
|
14
9
|
if (i18nPath) {
|
|
15
10
|
this.loadI18n(i18nPath)
|
|
16
11
|
}
|
|
17
12
|
}
|
|
18
13
|
|
|
19
|
-
buildGenericMaps() {
|
|
20
|
-
this.keywordMap = {
|
|
21
|
-
'variable': 'let', 'constante': 'const', 'var': 'var',
|
|
22
|
-
'fonction': 'function', 'retourner': 'return',
|
|
23
|
-
'si': 'if', 'sinon': 'else', 'sinon si': 'else if',
|
|
24
|
-
'pour': 'for', 'tant que': 'while', 'faire': 'do',
|
|
25
|
-
'selon': 'switch', 'cas': 'case', 'défaut': 'default',
|
|
26
|
-
'sortir': 'break', 'continuer': 'continue',
|
|
27
|
-
'essayer': 'try', 'attraper': 'catch', 'finalement': 'finally',
|
|
28
|
-
'lancer': 'throw', 'nouveau': 'new',
|
|
29
|
-
'classe': 'class', 'étend': 'extends', 'super': 'super',
|
|
30
|
-
'statique': 'static', 'obtenir': 'get', 'définir': 'set',
|
|
31
|
-
'importer': 'import', 'exporter': 'export', 'depuis': 'from',
|
|
32
|
-
'asynchrone': 'asynchrone', 'attendre': 'await',
|
|
33
|
-
'vrai': 'true', 'faux': 'false', 'nul': 'null', 'indefini': 'undefined',
|
|
34
|
-
'typeof': 'typeof', 'instanceof': 'instanceof', 'dans': 'in', 'de': 'of'
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
this.methodMap = {
|
|
38
|
-
'afficher': 'console.log',
|
|
39
|
-
'ajouter': 'push', 'retirer': 'pop', 'insérer': 'unshift',
|
|
40
|
-
'filtrer': 'filter', 'mapper': 'map', 'réduire': 'reduce',
|
|
41
|
-
'trouver': 'find', 'certains': 'some', 'tous': 'every',
|
|
42
|
-
'joindre': 'join', 'diviser': 'split',
|
|
43
|
-
'longueur': 'length', 'taille': 'length',
|
|
44
|
-
'majuscules': 'toUpperCase', 'minuscules': 'toLowerCase',
|
|
45
|
-
'inclut': 'includes', 'indice de': 'indexOf',
|
|
46
|
-
'tableau': 'Array', 'objet': 'Object', 'chaîne': 'String', 'nombre': 'Number'
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
this.operatorMap = {
|
|
50
|
-
'et': '&&', 'ou': '||', 'non': '!',
|
|
51
|
-
'egal': '===', 'different': '!==',
|
|
52
|
-
'plus': '+', 'moins': '-', 'fois': '*', 'divise': '/'
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
14
|
loadI18n(filePath) {
|
|
57
15
|
const content = fs.readFileSync(filePath, 'utf-8')
|
|
58
16
|
this.i18n = JSON.parse(content)
|
|
@@ -122,7 +80,7 @@ class JSGenerator {
|
|
|
122
80
|
'faire': 'do',
|
|
123
81
|
'selon': 'switch',
|
|
124
82
|
'cas': 'case',
|
|
125
|
-
'
|
|
83
|
+
'defaut': 'default',
|
|
126
84
|
'sortir': 'break',
|
|
127
85
|
'continuer': 'continue',
|
|
128
86
|
'essayer': 'try',
|
|
@@ -143,20 +101,20 @@ class JSGenerator {
|
|
|
143
101
|
'indefini': 'undefined',
|
|
144
102
|
'ceci': 'this',
|
|
145
103
|
'classe': 'class',
|
|
146
|
-
'
|
|
104
|
+
'etend': 'extends',
|
|
147
105
|
'super': 'super',
|
|
148
106
|
'constructeur': 'constructor',
|
|
149
107
|
'statique': 'static',
|
|
150
108
|
'obtenir': 'get',
|
|
151
|
-
'
|
|
152
|
-
'asynchrone': '
|
|
109
|
+
'definir': 'set',
|
|
110
|
+
'asynchrone': 'async',
|
|
153
111
|
'attendre': 'await',
|
|
154
112
|
'produire': 'yield',
|
|
155
113
|
'importer': 'import',
|
|
156
114
|
'exporter': 'export',
|
|
157
115
|
'depuis': 'from',
|
|
158
116
|
'comme': 'as',
|
|
159
|
-
'par
|
|
117
|
+
'par defaut': 'default',
|
|
160
118
|
'et': '&&',
|
|
161
119
|
'ou': '||',
|
|
162
120
|
'non': '!',
|
|
@@ -176,7 +134,7 @@ class JSGenerator {
|
|
|
176
134
|
'ajouter': 'push',
|
|
177
135
|
'retirer': 'pop',
|
|
178
136
|
'decaler': 'shift',
|
|
179
|
-
'
|
|
137
|
+
'inserer debut': 'unshift',
|
|
180
138
|
'trancher': 'slice',
|
|
181
139
|
'epiisser': 'splice',
|
|
182
140
|
'concatener': 'concat',
|
|
@@ -185,7 +143,7 @@ class JSGenerator {
|
|
|
185
143
|
'trier': 'sort',
|
|
186
144
|
'filtrer': 'filter',
|
|
187
145
|
'mapper': 'map',
|
|
188
|
-
'
|
|
146
|
+
'reduire': 'reduce',
|
|
189
147
|
'trouver': 'find',
|
|
190
148
|
'trouver index': 'findIndex',
|
|
191
149
|
'chaque': 'forEach',
|
|
@@ -200,31 +158,31 @@ class JSGenerator {
|
|
|
200
158
|
'supprimer espaces': 'trim',
|
|
201
159
|
'commence par': 'startsWith',
|
|
202
160
|
'finit par': 'endsWith',
|
|
203
|
-
'sous
|
|
161
|
+
'sous chaine': 'substring',
|
|
204
162
|
'afficher': 'console.log',
|
|
205
163
|
'alerte': 'alert',
|
|
206
164
|
'confirmer': 'confirm',
|
|
207
165
|
'demander': 'prompt',
|
|
208
166
|
'document': 'document',
|
|
209
167
|
'fenetre': 'window',
|
|
210
|
-
'
|
|
211
|
-
'
|
|
212
|
-
'
|
|
213
|
-
'
|
|
168
|
+
'element par id': 'getElementById',
|
|
169
|
+
'elements par classe': 'getElementsByClassName',
|
|
170
|
+
'elements par tag': 'getElementsByTagName',
|
|
171
|
+
'selecteur': 'querySelector',
|
|
214
172
|
'selecteurs': 'querySelectorAll',
|
|
215
|
-
'
|
|
173
|
+
'creer element': 'createElement',
|
|
216
174
|
'ajouter enfant': 'appendChild',
|
|
217
175
|
'supprimer enfant': 'removeChild',
|
|
218
176
|
'attribut': 'getAttribute',
|
|
219
|
-
'
|
|
220
|
-
'
|
|
177
|
+
'definir attribut': 'setAttribute',
|
|
178
|
+
'ecouter': 'addEventListener',
|
|
221
179
|
'stopper ecoute': 'removeEventListener',
|
|
222
|
-
'
|
|
180
|
+
'empecher defaut': 'preventDefault',
|
|
223
181
|
'stopper propagation': 'stopPropagation',
|
|
224
182
|
'stockage local': 'localStorage',
|
|
225
183
|
'stockage session': 'sessionStorage',
|
|
226
184
|
'obtenir item': 'getItem',
|
|
227
|
-
'
|
|
185
|
+
'definir item': 'setItem',
|
|
228
186
|
'supprimer item': 'removeItem',
|
|
229
187
|
'vider': 'clear',
|
|
230
188
|
'temporisation': 'setTimeout',
|
|
@@ -232,25 +190,25 @@ class JSGenerator {
|
|
|
232
190
|
'annuler temporisation': 'clearTimeout',
|
|
233
191
|
'annuler intervalle': 'clearInterval',
|
|
234
192
|
'promesse': 'Promise',
|
|
235
|
-
'
|
|
193
|
+
'resoudre': 'resolve',
|
|
236
194
|
'rejeter': 'reject',
|
|
237
195
|
'alors': 'then',
|
|
238
196
|
'capturer': 'catch',
|
|
239
197
|
'tout': 'all',
|
|
240
198
|
'course': 'race',
|
|
241
|
-
'
|
|
199
|
+
'recuperer': 'fetch',
|
|
242
200
|
'json': 'json',
|
|
243
201
|
'texte': 'text',
|
|
244
|
-
'
|
|
245
|
-
'
|
|
246
|
-
'
|
|
202
|
+
'reponse': 'response',
|
|
203
|
+
'requete': 'request',
|
|
204
|
+
'entetes': 'headers',
|
|
247
205
|
'corps': 'body',
|
|
248
|
-
'
|
|
206
|
+
'methode': 'method',
|
|
249
207
|
'analyser': 'JSON.parse',
|
|
250
208
|
'convertir': 'JSON.stringify',
|
|
251
209
|
'nombre': 'Number',
|
|
252
|
-
'
|
|
253
|
-
'
|
|
210
|
+
'chaine': 'String',
|
|
211
|
+
'booleen': 'Boolean',
|
|
254
212
|
'tableau': 'Array',
|
|
255
213
|
'objet': 'Object',
|
|
256
214
|
'date': 'Date',
|
|
@@ -258,11 +216,11 @@ class JSGenerator {
|
|
|
258
216
|
'expression reguliere': 'RegExp',
|
|
259
217
|
'erreur': 'Error',
|
|
260
218
|
'erreur type': 'TypeError',
|
|
261
|
-
'erreur
|
|
219
|
+
'erreur reference': 'ReferenceError',
|
|
262
220
|
'erreur syntaxe': 'SyntaxError',
|
|
263
221
|
'erreur plage': 'RangeError',
|
|
264
222
|
'math': 'Math',
|
|
265
|
-
'
|
|
223
|
+
'aleatoire': 'random',
|
|
266
224
|
'plancher': 'floor',
|
|
267
225
|
'plafond': 'ceil',
|
|
268
226
|
'arrondi': 'round',
|
|
@@ -289,22 +247,13 @@ class JSGenerator {
|
|
|
289
247
|
|
|
290
248
|
if (Array.isArray(ast)) {
|
|
291
249
|
for (const node of ast) {
|
|
292
|
-
|
|
293
|
-
if (result !== undefined && this.output === '') {
|
|
294
|
-
this.output = result
|
|
295
|
-
}
|
|
250
|
+
this.generateNode(node)
|
|
296
251
|
}
|
|
297
252
|
} else if (ast && ast.type) {
|
|
298
|
-
|
|
299
|
-
if (result !== undefined && this.output === '') {
|
|
300
|
-
this.output = result
|
|
301
|
-
}
|
|
253
|
+
this.generateNode(ast)
|
|
302
254
|
} else if (ast && ast.body) {
|
|
303
255
|
for (const node of ast.body) {
|
|
304
|
-
|
|
305
|
-
if (result !== undefined && this.output === '') {
|
|
306
|
-
this.output = result
|
|
307
|
-
}
|
|
256
|
+
this.generateNode(node)
|
|
308
257
|
}
|
|
309
258
|
}
|
|
310
259
|
|
|
@@ -396,6 +345,8 @@ class JSGenerator {
|
|
|
396
345
|
return this.generateArrayExpression(node)
|
|
397
346
|
case 'Identifier':
|
|
398
347
|
return this.translate(node.name)
|
|
348
|
+
case 'Parameter':
|
|
349
|
+
return this.generateParameter(node)
|
|
399
350
|
case 'Literal':
|
|
400
351
|
return this.generateLiteral(node)
|
|
401
352
|
case 'TemplateLiteral':
|
|
@@ -404,8 +355,6 @@ class JSGenerator {
|
|
|
404
355
|
return this.generateNewExpression(node)
|
|
405
356
|
case 'AwaitExpression':
|
|
406
357
|
return this.generateAwaitExpression(node)
|
|
407
|
-
case 'UpdateExpression':
|
|
408
|
-
return this.generateUpdateExpression(node)
|
|
409
358
|
default:
|
|
410
359
|
if (node.expression) {
|
|
411
360
|
return this.generateNode(node.expression)
|
|
@@ -414,15 +363,6 @@ class JSGenerator {
|
|
|
414
363
|
}
|
|
415
364
|
}
|
|
416
365
|
|
|
417
|
-
generateUpdateExpression(node) {
|
|
418
|
-
const arg = this.generateNode(node.argument)
|
|
419
|
-
const op = node.operator
|
|
420
|
-
if (node.prefix) {
|
|
421
|
-
return `${op}${arg}`
|
|
422
|
-
}
|
|
423
|
-
return `${arg}${op}`
|
|
424
|
-
}
|
|
425
|
-
|
|
426
366
|
generateProgram(node) {
|
|
427
367
|
for (const statement of node.body || []) {
|
|
428
368
|
this.generateNode(statement)
|
|
@@ -431,24 +371,21 @@ class JSGenerator {
|
|
|
431
371
|
|
|
432
372
|
generateVariableDeclaration(node) {
|
|
433
373
|
const kind = this.translate(node.kind || 'let')
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
name =
|
|
441
|
-
} else if (decl.id.name) {
|
|
442
|
-
name = this.translate(decl.id.name)
|
|
374
|
+
|
|
375
|
+
if (node.declarations && Array.isArray(node.declarations)) {
|
|
376
|
+
for (const decl of node.declarations) {
|
|
377
|
+
const name = this.generateNode(decl.id || decl.name)
|
|
378
|
+
if (decl.init) {
|
|
379
|
+
const init = this.generateNode(decl.init)
|
|
380
|
+
this.writeLine(`${kind} ${name} = ${init};`)
|
|
443
381
|
} else {
|
|
444
|
-
|
|
382
|
+
this.writeLine(`${kind} ${name};`)
|
|
445
383
|
}
|
|
446
|
-
} else if (decl.name) {
|
|
447
|
-
name = this.translate(typeof decl.name === 'string' ? decl.name : decl.name.name)
|
|
448
384
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
385
|
+
} else {
|
|
386
|
+
const name = typeof node.name === 'string' ? node.name : this.generateNode(node.name)
|
|
387
|
+
if (node.init) {
|
|
388
|
+
const init = this.generateNode(node.init)
|
|
452
389
|
this.writeLine(`${kind} ${name} = ${init};`)
|
|
453
390
|
} else {
|
|
454
391
|
this.writeLine(`${kind} ${name};`)
|
|
@@ -460,7 +397,7 @@ class JSGenerator {
|
|
|
460
397
|
const async = node.async ? 'async ' : ''
|
|
461
398
|
const generator = node.generator ? '*' : ''
|
|
462
399
|
const name = this.translate(node.id?.name || node.name || '')
|
|
463
|
-
const params = (node.params || []).map(p => this.
|
|
400
|
+
const params = (node.params || []).map(p => this.generateParameter(p)).join(', ')
|
|
464
401
|
|
|
465
402
|
this.writeLine(`${async}function${generator} ${name}(${params}) {`)
|
|
466
403
|
this.indent++
|
|
@@ -470,6 +407,24 @@ class JSGenerator {
|
|
|
470
407
|
this.writeLine('')
|
|
471
408
|
}
|
|
472
409
|
|
|
410
|
+
generateParameter(node) {
|
|
411
|
+
if (!node) return ''
|
|
412
|
+
if (typeof node === 'string') return node
|
|
413
|
+
if (node.type === 'Identifier') return this.translate(node.name)
|
|
414
|
+
|
|
415
|
+
let result = this.translate(node.name || '')
|
|
416
|
+
|
|
417
|
+
if (node.typeAnnotation) {
|
|
418
|
+
result += `: ${this.generateNode(node.typeAnnotation)}`
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
if (node.default) {
|
|
422
|
+
result += ` = ${this.generateNode(node.default)}`
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
return result
|
|
426
|
+
}
|
|
427
|
+
|
|
473
428
|
generateClassDeclaration(node) {
|
|
474
429
|
const name = this.translate(node.id?.name || node.name || '')
|
|
475
430
|
const extend = node.superClass ? ` extends ${this.generateNode(node.superClass)}` : ''
|
|
@@ -520,25 +475,8 @@ class JSGenerator {
|
|
|
520
475
|
|
|
521
476
|
if (node.alternate) {
|
|
522
477
|
if (node.alternate.type === 'IfStatement') {
|
|
523
|
-
this.output = this.output.trimEnd() + '
|
|
524
|
-
|
|
525
|
-
this.output += `if (${altTest}) {\n`
|
|
526
|
-
this.indent++
|
|
527
|
-
this.generateNode(node.alternate.consequent)
|
|
528
|
-
this.indent--
|
|
529
|
-
if (node.alternate.alternate) {
|
|
530
|
-
if (node.alternate.alternate.type === 'IfStatement') {
|
|
531
|
-
this.generateIfStatement({ ...node.alternate, test: node.alternate.alternate.test, consequent: node.alternate.alternate.consequent, alternate: node.alternate.alternate.alternate })
|
|
532
|
-
} else {
|
|
533
|
-
this.writeLine('} else {')
|
|
534
|
-
this.indent++
|
|
535
|
-
this.generateNode(node.alternate.alternate)
|
|
536
|
-
this.indent--
|
|
537
|
-
this.writeLine('}')
|
|
538
|
-
}
|
|
539
|
-
} else {
|
|
540
|
-
this.writeLine('}')
|
|
541
|
-
}
|
|
478
|
+
this.output = this.output.trimEnd() + ' else '
|
|
479
|
+
this.generateIfStatement(node.alternate)
|
|
542
480
|
} else {
|
|
543
481
|
this.writeLine('} else {')
|
|
544
482
|
this.indent++
|
|
@@ -552,16 +490,9 @@ class JSGenerator {
|
|
|
552
490
|
}
|
|
553
491
|
|
|
554
492
|
generateForStatement(node) {
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
this.output = ''
|
|
559
|
-
this.generateNode(node.init)
|
|
560
|
-
init = this.output.trim().replace(/;$/, '')
|
|
561
|
-
this.output = saved
|
|
562
|
-
}
|
|
563
|
-
const test = node.test ? (this.generateNode(node.test) || '') : ''
|
|
564
|
-
const update = node.update ? (this.generateNode(node.update) || '') : ''
|
|
493
|
+
const init = node.init ? this.generateNode(node.init).replace(/;$/, '') : ''
|
|
494
|
+
const test = node.test ? this.generateNode(node.test) : ''
|
|
495
|
+
const update = node.update ? this.generateNode(node.update) : ''
|
|
565
496
|
|
|
566
497
|
this.writeLine(`for (${init}; ${test}; ${update}) {`)
|
|
567
498
|
this.indent++
|
|
@@ -571,21 +502,8 @@ class JSGenerator {
|
|
|
571
502
|
}
|
|
572
503
|
|
|
573
504
|
generateForOfStatement(node) {
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
const kind = this.translate(node.left.kind || 'const')
|
|
577
|
-
const decl = node.left.declarations?.[0]
|
|
578
|
-
let name = ''
|
|
579
|
-
if (decl?.id?.name) {
|
|
580
|
-
name = this.translate(decl.id.name)
|
|
581
|
-
} else if (decl?.name) {
|
|
582
|
-
name = this.translate(typeof decl.name === 'string' ? decl.name : decl.name.name)
|
|
583
|
-
}
|
|
584
|
-
left = `${kind} ${name}`
|
|
585
|
-
} else {
|
|
586
|
-
left = this.generateNode(node.left) || ''
|
|
587
|
-
}
|
|
588
|
-
const right = this.generateNode(node.right) || ''
|
|
505
|
+
const left = this.generateNode(node.left)
|
|
506
|
+
const right = this.generateNode(node.right)
|
|
589
507
|
const keyword = node.type === 'ForInStatement' ? 'in' : 'of'
|
|
590
508
|
|
|
591
509
|
this.writeLine(`for (${left} ${keyword} ${right}) {`)
|
|
@@ -661,8 +579,9 @@ class JSGenerator {
|
|
|
661
579
|
}
|
|
662
580
|
|
|
663
581
|
generateReturnStatement(node) {
|
|
664
|
-
|
|
665
|
-
|
|
582
|
+
const value = node.argument || node.value
|
|
583
|
+
if (value) {
|
|
584
|
+
const arg = this.generateNode(value)
|
|
666
585
|
this.writeLine(`return ${arg};`)
|
|
667
586
|
} else {
|
|
668
587
|
this.writeLine('return;')
|
|
@@ -841,14 +760,14 @@ class JSGenerator {
|
|
|
841
760
|
|
|
842
761
|
generateLiteral(node) {
|
|
843
762
|
if (node.raw) return node.raw
|
|
844
|
-
if (node.regex) {
|
|
845
|
-
return `/${node.regex.pattern}/${node.regex.flags || ''}`
|
|
846
|
-
}
|
|
847
763
|
if (typeof node.value === 'string') {
|
|
848
764
|
return `"${node.value.replace(/"/g, '\\"')}"`
|
|
849
765
|
}
|
|
850
766
|
if (node.value === null) return 'null'
|
|
851
767
|
if (node.value === undefined) return 'undefined'
|
|
768
|
+
if (node.regex) {
|
|
769
|
+
return `/${node.regex.pattern}/${node.regex.flags}`
|
|
770
|
+
}
|
|
852
771
|
return String(node.value)
|
|
853
772
|
}
|
|
854
773
|
|