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
package/parsers/react-parser.js
DELETED
|
@@ -1,1035 +0,0 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const { JSLexer, JSParser, JSCodeGenerator } = require('./js-parser')
|
|
3
|
-
const AST = require('./ast-react')
|
|
4
|
-
|
|
5
|
-
const SELF_CLOSING_TAGS = new Set([
|
|
6
|
-
'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',
|
|
7
|
-
'link', 'meta', 'param', 'source', 'track', 'wbr'
|
|
8
|
-
])
|
|
9
|
-
|
|
10
|
-
const REACT_HOOKS = {
|
|
11
|
-
'useState': 'useState', 'utiliser etat': 'useState', 'utiliser état': 'useState', 'usar estado': 'useState',
|
|
12
|
-
'использовать состояние': 'useState', '使用状态': 'useState', 'ステート使用': 'useState',
|
|
13
|
-
|
|
14
|
-
'useEffect': 'useEffect', 'utiliser effet': 'useEffect', 'usar efecto': 'useEffect',
|
|
15
|
-
'использовать эффект': 'useEffect', '使用副作用': 'useEffect', 'エフェクト使用': 'useEffect',
|
|
16
|
-
|
|
17
|
-
'useContext': 'useContext', 'utiliser contexte': 'useContext', 'usar contexto': 'useContext',
|
|
18
|
-
'использовать контекст': 'useContext', '使用上下文': 'useContext', 'コンテキスト使用': 'useContext',
|
|
19
|
-
|
|
20
|
-
'useReducer': 'useReducer', 'utiliser reducteur': 'useReducer', 'utiliser réducteur': 'useReducer', 'usar reductor': 'useReducer',
|
|
21
|
-
'использовать редьюсер': 'useReducer', '使用归约器': 'useReducer', 'リデューサー使用': 'useReducer',
|
|
22
|
-
|
|
23
|
-
'useCallback': 'useCallback', 'utiliser rappel': 'useCallback', 'usar callback': 'useCallback',
|
|
24
|
-
'использовать колбэк': 'useCallback', '使用回调': 'useCallback', 'コールバック使用': 'useCallback',
|
|
25
|
-
|
|
26
|
-
'useMemo': 'useMemo', 'utiliser memo': 'useMemo', 'utiliser mémo': 'useMemo', 'usar memo': 'useMemo',
|
|
27
|
-
'использовать мемо': 'useMemo', '使用记忆': 'useMemo', 'メモ使用': 'useMemo',
|
|
28
|
-
|
|
29
|
-
'useRef': 'useRef', 'utiliser reference': 'useRef', 'utiliser référence': 'useRef', 'usar referencia': 'useRef',
|
|
30
|
-
'использовать ссылку': 'useRef', '使用引用': 'useRef', 'リファレンス使用': 'useRef',
|
|
31
|
-
|
|
32
|
-
'useImperativeHandle': 'useImperativeHandle', 'utiliser handle imperatif': 'useImperativeHandle', 'utiliser handle impératif': 'useImperativeHandle',
|
|
33
|
-
'usar handle imperativo': 'useImperativeHandle', 'использовать императивный хэндл': 'useImperativeHandle',
|
|
34
|
-
'使用命令式句柄': 'useImperativeHandle', '命令型ハンドル使用': 'useImperativeHandle',
|
|
35
|
-
|
|
36
|
-
'useLayoutEffect': 'useLayoutEffect', 'utiliser effet mise en page': 'useLayoutEffect',
|
|
37
|
-
'usar efecto diseño': 'useLayoutEffect', 'usar efecto diseno': 'useLayoutEffect',
|
|
38
|
-
'использовать эффект макета': 'useLayoutEffect', '使用布局副作用': 'useLayoutEffect', 'レイアウトエフェクト使用': 'useLayoutEffect',
|
|
39
|
-
|
|
40
|
-
'useInsertionEffect': 'useInsertionEffect', 'utiliser effet insertion': 'useInsertionEffect',
|
|
41
|
-
'usar efecto insercion': 'useInsertionEffect', 'usar efecto inserción': 'useInsertionEffect',
|
|
42
|
-
'использовать эффект вставки': 'useInsertionEffect', '使用插入副作用': 'useInsertionEffect', '挿入エフェクト使用': 'useInsertionEffect',
|
|
43
|
-
|
|
44
|
-
'useDebugValue': 'useDebugValue', 'utiliser valeur debug': 'useDebugValue',
|
|
45
|
-
'usar valor debug': 'useDebugValue', 'использовать значение отладки': 'useDebugValue',
|
|
46
|
-
'使用调试值': 'useDebugValue', 'デバッグ値使用': 'useDebugValue',
|
|
47
|
-
|
|
48
|
-
'useTransition': 'useTransition', 'utiliser transition': 'useTransition',
|
|
49
|
-
'usar transicion': 'useTransition', 'usar transición': 'useTransition',
|
|
50
|
-
'использовать переход': 'useTransition', '使用过渡': 'useTransition', 'トランジション使用': 'useTransition',
|
|
51
|
-
|
|
52
|
-
'useDeferredValue': 'useDeferredValue', 'utiliser valeur differee': 'useDeferredValue', 'utiliser valeur différée': 'useDeferredValue',
|
|
53
|
-
'usar valor diferido': 'useDeferredValue', 'использовать отложенное значение': 'useDeferredValue',
|
|
54
|
-
'使用延迟值': 'useDeferredValue', '遅延値使用': 'useDeferredValue',
|
|
55
|
-
|
|
56
|
-
'useId': 'useId', 'utiliser identifiant': 'useId', 'usar id': 'useId', 'usar identificador': 'useId',
|
|
57
|
-
'использовать идентификатор': 'useId', '使用ID': 'useId', 'ID使用': 'useId',
|
|
58
|
-
|
|
59
|
-
'useSyncExternalStore': 'useSyncExternalStore', 'utiliser etat synchronise': 'useSyncExternalStore', 'utiliser état synchronisé': 'useSyncExternalStore',
|
|
60
|
-
'usar almacen externo sincronizado': 'useSyncExternalStore', 'usar almacén externo sincronizado': 'useSyncExternalStore',
|
|
61
|
-
'использовать синхронизированное внешнее хранилище': 'useSyncExternalStore',
|
|
62
|
-
'使用同步外部存储': 'useSyncExternalStore', '外部ストア同期使用': 'useSyncExternalStore',
|
|
63
|
-
|
|
64
|
-
'useActionState': 'useActionState', 'utiliser etat action': 'useActionState', 'utiliser état action': 'useActionState',
|
|
65
|
-
'usar estado accion': 'useActionState', 'usar estado acción': 'useActionState',
|
|
66
|
-
'использовать состояние действия': 'useActionState', '使用动作状态': 'useActionState', 'アクション状態使用': 'useActionState',
|
|
67
|
-
|
|
68
|
-
'useFormStatus': 'useFormStatus', 'utiliser statut formulaire': 'useFormStatus',
|
|
69
|
-
'usar estado formulario': 'useFormStatus', 'использовать статус формы': 'useFormStatus',
|
|
70
|
-
'使用表单状态': 'useFormStatus', 'フォームステータス使用': 'useFormStatus',
|
|
71
|
-
|
|
72
|
-
'useOptimistic': 'useOptimistic', 'utiliser optimiste': 'useOptimistic',
|
|
73
|
-
'usar optimista': 'useOptimistic', 'использовать оптимистичный': 'useOptimistic',
|
|
74
|
-
'使用乐观': 'useOptimistic', 'オプティミスティック使用': 'useOptimistic',
|
|
75
|
-
|
|
76
|
-
'use': 'use', 'utiliser': 'use', 'usar': 'use', 'использовать': 'use', '使用': 'use', '使う': 'use'
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const REACT_COMPONENTS = {
|
|
80
|
-
'Fragment': 'Fragment', 'fragment': 'Fragment', 'fragmento': 'Fragment',
|
|
81
|
-
'фрагмент': 'Fragment', '片段': 'Fragment', 'フラグメント': 'Fragment',
|
|
82
|
-
|
|
83
|
-
'Suspense': 'Suspense', 'suspense': 'Suspense', 'suspenso': 'Suspense',
|
|
84
|
-
'ожидание': 'Suspense', '悬念': 'Suspense', 'サスペンス': 'Suspense',
|
|
85
|
-
|
|
86
|
-
'StrictMode': 'StrictMode', 'strict mode': 'StrictMode', 'mode strict': 'StrictMode', 'modo estricto': 'StrictMode',
|
|
87
|
-
'строгий режим': 'StrictMode', '严格模式': 'StrictMode', 'ストリクトモード': 'StrictMode',
|
|
88
|
-
|
|
89
|
-
'Profiler': 'Profiler', 'profileur': 'Profiler', 'perfilador': 'Profiler',
|
|
90
|
-
'профайлер': 'Profiler', '性能分析器': 'Profiler', 'プロファイラー': 'Profiler',
|
|
91
|
-
|
|
92
|
-
'ErrorBoundary': 'ErrorBoundary', 'limite erreur': 'ErrorBoundary', 'límite error': 'ErrorBoundary', 'limite error': 'ErrorBoundary',
|
|
93
|
-
'граница ошибки': 'ErrorBoundary', '错误边界': 'ErrorBoundary', 'エラーバウンダリ': 'ErrorBoundary',
|
|
94
|
-
|
|
95
|
-
'Provider': 'Provider', 'fournisseur': 'Provider', 'proveedor': 'Provider',
|
|
96
|
-
'провайдер': 'Provider', '提供者': 'Provider', 'プロバイダー': 'Provider',
|
|
97
|
-
|
|
98
|
-
'Consumer': 'Consumer', 'consommateur': 'Consumer', 'consumidor': 'Consumer',
|
|
99
|
-
'потребитель': 'Consumer', '消费者': 'Consumer', 'コンシューマー': 'Consumer',
|
|
100
|
-
|
|
101
|
-
'Portal': 'Portal', 'portail': 'Portal', 'portal': 'Portal',
|
|
102
|
-
'портал': 'Portal', '传送门': 'Portal', 'ポータル': 'Portal',
|
|
103
|
-
|
|
104
|
-
'Lazy': 'Lazy', 'lazy': 'Lazy', 'paresseux': 'Lazy', 'perezoso': 'Lazy',
|
|
105
|
-
'ленивый': 'Lazy', '懒加载': 'Lazy', 'レイジー': 'Lazy',
|
|
106
|
-
|
|
107
|
-
'Memo': 'Memo', 'memo': 'Memo', 'мемо': 'Memo', '记忆': 'Memo', 'メモ': 'Memo',
|
|
108
|
-
|
|
109
|
-
'ForwardRef': 'ForwardRef', 'reference avancee': 'ForwardRef', 'référence avancée': 'ForwardRef',
|
|
110
|
-
'referencia adelantada': 'ForwardRef', 'перенаправленная ссылка': 'ForwardRef',
|
|
111
|
-
'转发引用': 'ForwardRef', 'フォワードリファレンス': 'ForwardRef'
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
class ReactLexer extends JSLexer {
|
|
115
|
-
constructor(source, i18n) {
|
|
116
|
-
super(source, i18n)
|
|
117
|
-
this.inJSX = false
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
tokenize() {
|
|
121
|
-
while (this.pos < this.source.length) {
|
|
122
|
-
this.skipWhitespace()
|
|
123
|
-
if (this.pos >= this.source.length) break
|
|
124
|
-
|
|
125
|
-
const loc = { line: this.line, column: this.column }
|
|
126
|
-
const char = this.peek()
|
|
127
|
-
|
|
128
|
-
if (char === '<') {
|
|
129
|
-
if (this.peek(1) === '/' || this.peek(1) === '>' || /[a-zA-Z_]/.test(this.peek(1))) {
|
|
130
|
-
this.tokens.push(this.readJSXToken())
|
|
131
|
-
continue
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (char === '"' || char === "'") {
|
|
136
|
-
this.tokens.push(this.readString(char))
|
|
137
|
-
continue
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (char === '`') {
|
|
141
|
-
this.tokens.push(this.readTemplateLiteral())
|
|
142
|
-
continue
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
if (/[0-9]/.test(char) || (char === '.' && /[0-9]/.test(this.peek(1)))) {
|
|
146
|
-
this.tokens.push(this.readNumber())
|
|
147
|
-
continue
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if (/[a-zA-ZÀ-ÿА-яぁ-ゟァ-ヿ一-龯_$]/.test(char)) {
|
|
151
|
-
const { word, loc: wordLoc } = this.readWord()
|
|
152
|
-
const tokenType = this.classifyReactWord(word)
|
|
153
|
-
this.tokens.push({ type: tokenType, value: word, loc: wordLoc })
|
|
154
|
-
continue
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
if (char === '{') {
|
|
158
|
-
this.tokens.push({ type: 'LBRACE', loc })
|
|
159
|
-
this.advance()
|
|
160
|
-
continue
|
|
161
|
-
}
|
|
162
|
-
if (char === '}') {
|
|
163
|
-
this.tokens.push({ type: 'RBRACE', loc })
|
|
164
|
-
this.advance()
|
|
165
|
-
continue
|
|
166
|
-
}
|
|
167
|
-
if (char === '(') {
|
|
168
|
-
this.tokens.push({ type: 'LPAREN', loc })
|
|
169
|
-
this.advance()
|
|
170
|
-
continue
|
|
171
|
-
}
|
|
172
|
-
if (char === ')') {
|
|
173
|
-
this.tokens.push({ type: 'RPAREN', loc })
|
|
174
|
-
this.advance()
|
|
175
|
-
continue
|
|
176
|
-
}
|
|
177
|
-
if (char === '[') {
|
|
178
|
-
this.tokens.push({ type: 'LBRACKET', loc })
|
|
179
|
-
this.advance()
|
|
180
|
-
continue
|
|
181
|
-
}
|
|
182
|
-
if (char === ']') {
|
|
183
|
-
this.tokens.push({ type: 'RBRACKET', loc })
|
|
184
|
-
this.advance()
|
|
185
|
-
continue
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
const threeChar = this.source.slice(this.pos, this.pos + 3)
|
|
189
|
-
const twoChar = this.source.slice(this.pos, this.pos + 2)
|
|
190
|
-
|
|
191
|
-
if (threeChar === '...') {
|
|
192
|
-
this.tokens.push({ type: 'SPREAD', value: '...', loc })
|
|
193
|
-
this.advance(); this.advance(); this.advance()
|
|
194
|
-
continue
|
|
195
|
-
}
|
|
196
|
-
if (twoChar === '=>') {
|
|
197
|
-
this.tokens.push({ type: 'ARROW', value: '=>', loc })
|
|
198
|
-
this.advance(); this.advance()
|
|
199
|
-
continue
|
|
200
|
-
}
|
|
201
|
-
if (twoChar === '?.') {
|
|
202
|
-
this.tokens.push({ type: 'OPTIONAL_CHAIN', value: '?.', loc })
|
|
203
|
-
this.advance(); this.advance()
|
|
204
|
-
continue
|
|
205
|
-
}
|
|
206
|
-
if (twoChar === '&&') {
|
|
207
|
-
this.tokens.push({ type: 'AND', value: '&&', loc })
|
|
208
|
-
this.advance(); this.advance()
|
|
209
|
-
continue
|
|
210
|
-
}
|
|
211
|
-
if (twoChar === '||') {
|
|
212
|
-
this.tokens.push({ type: 'OR', value: '||', loc })
|
|
213
|
-
this.advance(); this.advance()
|
|
214
|
-
continue
|
|
215
|
-
}
|
|
216
|
-
if (twoChar === '??') {
|
|
217
|
-
this.tokens.push({ type: 'NULLISH', value: '??', loc })
|
|
218
|
-
this.advance(); this.advance()
|
|
219
|
-
continue
|
|
220
|
-
}
|
|
221
|
-
if (twoChar === '===') {
|
|
222
|
-
this.tokens.push({ type: 'STRICT_EQUAL', value: '===', loc })
|
|
223
|
-
this.advance(); this.advance(); this.advance()
|
|
224
|
-
continue
|
|
225
|
-
}
|
|
226
|
-
if (twoChar === '==') {
|
|
227
|
-
this.tokens.push({ type: 'EQUAL', value: '==', loc })
|
|
228
|
-
this.advance(); this.advance()
|
|
229
|
-
continue
|
|
230
|
-
}
|
|
231
|
-
if (twoChar === '!==') {
|
|
232
|
-
this.tokens.push({ type: 'STRICT_NOT_EQUAL', value: '!==', loc })
|
|
233
|
-
this.advance(); this.advance(); this.advance()
|
|
234
|
-
continue
|
|
235
|
-
}
|
|
236
|
-
if (twoChar === '!=') {
|
|
237
|
-
this.tokens.push({ type: 'NOT_EQUAL', value: '!=', loc })
|
|
238
|
-
this.advance(); this.advance()
|
|
239
|
-
continue
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
if (char === '=') {
|
|
243
|
-
this.tokens.push({ type: 'ASSIGN', value: '=', loc })
|
|
244
|
-
this.advance()
|
|
245
|
-
continue
|
|
246
|
-
}
|
|
247
|
-
if (char === '+') {
|
|
248
|
-
this.tokens.push({ type: 'PLUS', value: '+', loc })
|
|
249
|
-
this.advance()
|
|
250
|
-
continue
|
|
251
|
-
}
|
|
252
|
-
if (char === '-') {
|
|
253
|
-
this.tokens.push({ type: 'MINUS', value: '-', loc })
|
|
254
|
-
this.advance()
|
|
255
|
-
continue
|
|
256
|
-
}
|
|
257
|
-
if (char === '*') {
|
|
258
|
-
this.tokens.push({ type: 'STAR', value: '*', loc })
|
|
259
|
-
this.advance()
|
|
260
|
-
continue
|
|
261
|
-
}
|
|
262
|
-
if (char === '/') {
|
|
263
|
-
this.tokens.push({ type: 'SLASH', value: '/', loc })
|
|
264
|
-
this.advance()
|
|
265
|
-
continue
|
|
266
|
-
}
|
|
267
|
-
if (char === '%') {
|
|
268
|
-
this.tokens.push({ type: 'PERCENT', value: '%', loc })
|
|
269
|
-
this.advance()
|
|
270
|
-
continue
|
|
271
|
-
}
|
|
272
|
-
if (char === '<') {
|
|
273
|
-
this.tokens.push({ type: 'LT', value: '<', loc })
|
|
274
|
-
this.advance()
|
|
275
|
-
continue
|
|
276
|
-
}
|
|
277
|
-
if (char === '>') {
|
|
278
|
-
this.tokens.push({ type: 'GT', value: '>', loc })
|
|
279
|
-
this.advance()
|
|
280
|
-
continue
|
|
281
|
-
}
|
|
282
|
-
if (char === '!') {
|
|
283
|
-
this.tokens.push({ type: 'NOT', value: '!', loc })
|
|
284
|
-
this.advance()
|
|
285
|
-
continue
|
|
286
|
-
}
|
|
287
|
-
if (char === '?') {
|
|
288
|
-
this.tokens.push({ type: 'QUESTION', value: '?', loc })
|
|
289
|
-
this.advance()
|
|
290
|
-
continue
|
|
291
|
-
}
|
|
292
|
-
if (char === ':') {
|
|
293
|
-
this.tokens.push({ type: 'COLON', value: ':', loc })
|
|
294
|
-
this.advance()
|
|
295
|
-
continue
|
|
296
|
-
}
|
|
297
|
-
if (char === '.') {
|
|
298
|
-
this.tokens.push({ type: 'DOT', value: '.', loc })
|
|
299
|
-
this.advance()
|
|
300
|
-
continue
|
|
301
|
-
}
|
|
302
|
-
if (char === ',') {
|
|
303
|
-
this.tokens.push({ type: 'COMMA', value: ',', loc })
|
|
304
|
-
this.advance()
|
|
305
|
-
continue
|
|
306
|
-
}
|
|
307
|
-
if (char === ';') {
|
|
308
|
-
this.tokens.push({ type: 'SEMICOLON', value: ';', loc })
|
|
309
|
-
this.advance()
|
|
310
|
-
continue
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
this.advance()
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
this.tokens.push({ type: 'EOF', loc: { line: this.line, column: this.column } })
|
|
317
|
-
return this.tokens
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
readJSXToken() {
|
|
321
|
-
const loc = { line: this.line, column: this.column }
|
|
322
|
-
this.advance()
|
|
323
|
-
|
|
324
|
-
if (this.peek() === '/') {
|
|
325
|
-
this.advance()
|
|
326
|
-
if (this.peek() === '>') {
|
|
327
|
-
this.advance()
|
|
328
|
-
return { type: 'JSX_FRAGMENT_CLOSE', loc }
|
|
329
|
-
}
|
|
330
|
-
const name = this.readJSXName()
|
|
331
|
-
this.skipWhitespace()
|
|
332
|
-
if (this.peek() === '>') this.advance()
|
|
333
|
-
return { type: 'JSX_CLOSE', name, loc }
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
if (this.peek() === '>') {
|
|
337
|
-
this.advance()
|
|
338
|
-
return { type: 'JSX_FRAGMENT_OPEN', loc }
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
const name = this.readJSXName()
|
|
342
|
-
const attributes = []
|
|
343
|
-
let selfClosing = false
|
|
344
|
-
|
|
345
|
-
while (this.pos < this.source.length) {
|
|
346
|
-
this.skipWhitespace()
|
|
347
|
-
const char = this.peek()
|
|
348
|
-
|
|
349
|
-
if (char === '>') {
|
|
350
|
-
this.advance()
|
|
351
|
-
break
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
if (char === '/' && this.peek(1) === '>') {
|
|
355
|
-
selfClosing = true
|
|
356
|
-
this.advance()
|
|
357
|
-
this.advance()
|
|
358
|
-
break
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
if (char === '{') {
|
|
362
|
-
this.advance()
|
|
363
|
-
if (this.peek() === '.') {
|
|
364
|
-
this.advance()
|
|
365
|
-
this.advance()
|
|
366
|
-
this.advance()
|
|
367
|
-
let expr = ''
|
|
368
|
-
let braceCount = 1
|
|
369
|
-
while (braceCount > 0 && this.pos < this.source.length) {
|
|
370
|
-
const c = this.peek()
|
|
371
|
-
if (c === '{') braceCount++
|
|
372
|
-
if (c === '}') braceCount--
|
|
373
|
-
if (braceCount > 0) expr += this.advance()
|
|
374
|
-
else this.advance()
|
|
375
|
-
}
|
|
376
|
-
attributes.push({ type: 'spread', value: expr.trim() })
|
|
377
|
-
}
|
|
378
|
-
continue
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
if (/[a-zA-Z_\-]/.test(char)) {
|
|
382
|
-
const attrName = this.readJSXAttributeName()
|
|
383
|
-
let attrValue = true
|
|
384
|
-
|
|
385
|
-
this.skipWhitespace()
|
|
386
|
-
if (this.peek() === '=') {
|
|
387
|
-
this.advance()
|
|
388
|
-
this.skipWhitespace()
|
|
389
|
-
|
|
390
|
-
if (this.peek() === '"' || this.peek() === "'") {
|
|
391
|
-
const quote = this.advance()
|
|
392
|
-
attrValue = ''
|
|
393
|
-
while (this.pos < this.source.length && this.peek() !== quote) {
|
|
394
|
-
attrValue += this.advance()
|
|
395
|
-
}
|
|
396
|
-
if (this.peek() === quote) this.advance()
|
|
397
|
-
} else if (this.peek() === '{') {
|
|
398
|
-
this.advance()
|
|
399
|
-
attrValue = { type: 'expression', value: '' }
|
|
400
|
-
let braceCount = 1
|
|
401
|
-
while (braceCount > 0 && this.pos < this.source.length) {
|
|
402
|
-
const c = this.peek()
|
|
403
|
-
if (c === '{') braceCount++
|
|
404
|
-
if (c === '}') braceCount--
|
|
405
|
-
if (braceCount > 0) attrValue.value += this.advance()
|
|
406
|
-
else this.advance()
|
|
407
|
-
}
|
|
408
|
-
attrValue.value = attrValue.value.trim()
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
attributes.push({ name: attrName, value: attrValue })
|
|
413
|
-
continue
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
this.advance()
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
return { type: 'JSX_OPEN', name, attributes, selfClosing, loc }
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
readJSXName() {
|
|
423
|
-
let name = ''
|
|
424
|
-
while (this.pos < this.source.length) {
|
|
425
|
-
const char = this.peek()
|
|
426
|
-
if (/[a-zA-Z0-9_\-:.]/.test(char)) {
|
|
427
|
-
name += this.advance()
|
|
428
|
-
} else {
|
|
429
|
-
break
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
return name
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
readJSXAttributeName() {
|
|
436
|
-
let name = ''
|
|
437
|
-
while (this.pos < this.source.length) {
|
|
438
|
-
const char = this.peek()
|
|
439
|
-
if (/[a-zA-Z0-9_\-:]/.test(char)) {
|
|
440
|
-
name += this.advance()
|
|
441
|
-
} else {
|
|
442
|
-
break
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
return name
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
classifyReactWord(word) {
|
|
449
|
-
const lowerWord = word.toLowerCase()
|
|
450
|
-
|
|
451
|
-
if (REACT_HOOKS[lowerWord] || REACT_HOOKS[word]) {
|
|
452
|
-
return 'REACT_HOOK'
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
if (REACT_COMPONENTS[lowerWord] || REACT_COMPONENTS[word]) {
|
|
456
|
-
return 'REACT_COMPONENT'
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
return this.classifyWord(word)
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
class ReactParser extends JSParser {
|
|
464
|
-
constructor(i18nPath = null, jsI18nPath = null) {
|
|
465
|
-
super(jsI18nPath)
|
|
466
|
-
this.reactI18n = {}
|
|
467
|
-
|
|
468
|
-
if (i18nPath) {
|
|
469
|
-
this.loadReactI18n(i18nPath)
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
loadReactI18n(filePath) {
|
|
474
|
-
try {
|
|
475
|
-
const content = fs.readFileSync(filePath, 'utf-8')
|
|
476
|
-
this.reactI18n = JSON.parse(content)
|
|
477
|
-
} catch (e) {
|
|
478
|
-
console.error(`Erreur chargement i18n React: ${e.message}`)
|
|
479
|
-
this.reactI18n = {}
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
setReactI18n(i18nData) {
|
|
484
|
-
this.reactI18n = i18nData
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
parse(source) {
|
|
488
|
-
const lexer = new ReactLexer(source, this.i18n)
|
|
489
|
-
this.tokens = lexer.tokenize()
|
|
490
|
-
this.pos = 0
|
|
491
|
-
return this.parseProgram()
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
parsePrimaryExpression() {
|
|
495
|
-
const token = this.peek()
|
|
496
|
-
|
|
497
|
-
if (token.type === 'JSX_OPEN' || token.type === 'JSX_FRAGMENT_OPEN') {
|
|
498
|
-
return this.parseJSXElement()
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
if (token.type === 'REACT_HOOK') {
|
|
502
|
-
return this.parseHookCall()
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
return super.parsePrimaryExpression()
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
parseJSXElement() {
|
|
509
|
-
const token = this.peek()
|
|
510
|
-
|
|
511
|
-
if (token.type === 'JSX_FRAGMENT_OPEN') {
|
|
512
|
-
return this.parseJSXFragment()
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
const openingToken = this.advance()
|
|
516
|
-
const name = this.parseJSXElementName(openingToken.name)
|
|
517
|
-
const attributes = this.parseJSXAttributes(openingToken.attributes)
|
|
518
|
-
|
|
519
|
-
const openingElement = new AST.JSXOpeningElement(
|
|
520
|
-
name,
|
|
521
|
-
attributes,
|
|
522
|
-
openingToken.selfClosing,
|
|
523
|
-
openingToken.loc
|
|
524
|
-
)
|
|
525
|
-
|
|
526
|
-
if (openingToken.selfClosing) {
|
|
527
|
-
return new AST.JSXElement(openingElement, null, [], openingToken.loc)
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
const children = this.parseJSXChildren(openingToken.name)
|
|
531
|
-
|
|
532
|
-
let closingElement = null
|
|
533
|
-
if (this.match('JSX_CLOSE')) {
|
|
534
|
-
const closeToken = this.advance()
|
|
535
|
-
closingElement = new AST.JSXClosingElement(
|
|
536
|
-
this.parseJSXElementName(closeToken.name),
|
|
537
|
-
closeToken.loc
|
|
538
|
-
)
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
return new AST.JSXElement(openingElement, closingElement, children, openingToken.loc)
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
parseJSXFragment() {
|
|
545
|
-
const openToken = this.advance()
|
|
546
|
-
const openingFragment = new AST.JSXOpeningFragment(openToken.loc)
|
|
547
|
-
|
|
548
|
-
const children = this.parseJSXChildren(null)
|
|
549
|
-
|
|
550
|
-
let closingFragment = null
|
|
551
|
-
if (this.match('JSX_FRAGMENT_CLOSE')) {
|
|
552
|
-
const closeToken = this.advance()
|
|
553
|
-
closingFragment = new AST.JSXClosingFragment(closeToken.loc)
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
return new AST.JSXFragment(openingFragment, closingFragment, children, openToken.loc)
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
parseJSXElementName(name) {
|
|
560
|
-
if (!name) return new AST.JSXIdentifier('', null)
|
|
561
|
-
|
|
562
|
-
if (name.includes(':')) {
|
|
563
|
-
const [ns, local] = name.split(':')
|
|
564
|
-
return new AST.JSXNamespacedName(
|
|
565
|
-
new AST.JSXIdentifier(ns, null),
|
|
566
|
-
new AST.JSXIdentifier(local, null),
|
|
567
|
-
null
|
|
568
|
-
)
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
if (name.includes('.')) {
|
|
572
|
-
const parts = name.split('.')
|
|
573
|
-
let result = new AST.JSXIdentifier(parts[0], null)
|
|
574
|
-
for (let i = 1; i < parts.length; i++) {
|
|
575
|
-
result = new AST.JSXMemberExpression(
|
|
576
|
-
result,
|
|
577
|
-
new AST.JSXIdentifier(parts[i], null),
|
|
578
|
-
null
|
|
579
|
-
)
|
|
580
|
-
}
|
|
581
|
-
return result
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
return new AST.JSXIdentifier(name, null)
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
parseJSXAttributes(attrs) {
|
|
588
|
-
const attributes = []
|
|
589
|
-
|
|
590
|
-
for (const attr of attrs) {
|
|
591
|
-
if (attr.type === 'spread') {
|
|
592
|
-
const parser = new ReactParser()
|
|
593
|
-
parser.setI18n(this.i18n)
|
|
594
|
-
parser.setReactI18n(this.reactI18n)
|
|
595
|
-
const ast = parser.parse(attr.value)
|
|
596
|
-
const expr = ast.body[0]?.expression || new AST.Identifier(attr.value, null)
|
|
597
|
-
attributes.push(new AST.JSXSpreadAttribute(expr, null))
|
|
598
|
-
} else {
|
|
599
|
-
const attrName = this.parseJSXAttributeName(attr.name)
|
|
600
|
-
let attrValue = null
|
|
601
|
-
|
|
602
|
-
if (attr.value !== true) {
|
|
603
|
-
if (typeof attr.value === 'string') {
|
|
604
|
-
attrValue = new AST.StringLiteral(attr.value, `"${attr.value}"`, null)
|
|
605
|
-
} else if (attr.value?.type === 'expression') {
|
|
606
|
-
const parser = new ReactParser()
|
|
607
|
-
parser.setI18n(this.i18n)
|
|
608
|
-
parser.setReactI18n(this.reactI18n)
|
|
609
|
-
const ast = parser.parse(attr.value.value)
|
|
610
|
-
const expr = ast.body[0]?.expression || new AST.Identifier(attr.value.value, null)
|
|
611
|
-
attrValue = new AST.JSXExpressionContainer(expr, null)
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
attributes.push(new AST.JSXAttribute(attrName, attrValue, null))
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
return attributes
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
parseJSXAttributeName(name) {
|
|
623
|
-
if (name.includes(':')) {
|
|
624
|
-
const [ns, local] = name.split(':')
|
|
625
|
-
return new AST.JSXNamespacedName(
|
|
626
|
-
new AST.JSXIdentifier(ns, null),
|
|
627
|
-
new AST.JSXIdentifier(local, null),
|
|
628
|
-
null
|
|
629
|
-
)
|
|
630
|
-
}
|
|
631
|
-
return new AST.JSXIdentifier(name, null)
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
parseJSXChildren(parentName) {
|
|
635
|
-
const children = []
|
|
636
|
-
|
|
637
|
-
while (this.pos < this.tokens.length) {
|
|
638
|
-
const token = this.peek()
|
|
639
|
-
|
|
640
|
-
if (token.type === 'JSX_CLOSE') {
|
|
641
|
-
if (token.name === parentName || parentName === null) break
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
if (token.type === 'JSX_FRAGMENT_CLOSE') {
|
|
645
|
-
if (parentName === null) break
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
if (token.type === 'EOF') break
|
|
649
|
-
|
|
650
|
-
if (token.type === 'JSX_OPEN' || token.type === 'JSX_FRAGMENT_OPEN') {
|
|
651
|
-
children.push(this.parseJSXElement())
|
|
652
|
-
continue
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
if (token.type === 'LBRACE') {
|
|
656
|
-
children.push(this.parseJSXExpressionContainer())
|
|
657
|
-
continue
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
if (token.type === 'STRING') {
|
|
661
|
-
const strToken = this.advance()
|
|
662
|
-
children.push(new AST.JSXText(strToken.value, strToken.value, strToken.loc))
|
|
663
|
-
continue
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
if (token.type === 'IDENTIFIER' || token.type === 'KEYWORD') {
|
|
667
|
-
const textToken = this.advance()
|
|
668
|
-
children.push(new AST.JSXText(textToken.value, textToken.value, textToken.loc))
|
|
669
|
-
continue
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
this.advance()
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
return children
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
parseJSXExpressionContainer() {
|
|
679
|
-
const loc = this.peek().loc
|
|
680
|
-
this.expect('LBRACE')
|
|
681
|
-
|
|
682
|
-
if (this.match('RBRACE')) {
|
|
683
|
-
this.advance()
|
|
684
|
-
return new AST.JSXExpressionContainer(new AST.JSXEmptyExpression(loc), loc)
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
if (this.match('SPREAD')) {
|
|
688
|
-
this.advance()
|
|
689
|
-
const expr = this.parseAssignmentExpression()
|
|
690
|
-
this.expect('RBRACE')
|
|
691
|
-
return new AST.JSXSpreadChild(expr, loc)
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
const expression = this.parseExpression()
|
|
695
|
-
this.expect('RBRACE')
|
|
696
|
-
|
|
697
|
-
return new AST.JSXExpressionContainer(expression, loc)
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
parseHookCall() {
|
|
701
|
-
const token = this.advance()
|
|
702
|
-
const hookName = this.translateHook(token.value)
|
|
703
|
-
|
|
704
|
-
this.expect('LPAREN')
|
|
705
|
-
const args = []
|
|
706
|
-
|
|
707
|
-
while (!this.match('RPAREN', 'EOF')) {
|
|
708
|
-
args.push(this.parseAssignmentExpression())
|
|
709
|
-
if (!this.match('RPAREN')) {
|
|
710
|
-
this.expect('COMMA')
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
this.expect('RPAREN')
|
|
715
|
-
|
|
716
|
-
return new AST.ReactHookCall(hookName, args, token.loc)
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
translateHook(name) {
|
|
720
|
-
const lowerName = name.toLowerCase()
|
|
721
|
-
return REACT_HOOKS[lowerName] || REACT_HOOKS[name] || name
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
translateComponent(name) {
|
|
725
|
-
const lowerName = name.toLowerCase()
|
|
726
|
-
return REACT_COMPONENTS[lowerName] || REACT_COMPONENTS[name] || name
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
class ReactCodeGenerator extends JSCodeGenerator {
|
|
731
|
-
constructor(options = {}) {
|
|
732
|
-
super(options)
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
generate(ast) {
|
|
736
|
-
if (!ast) return ''
|
|
737
|
-
|
|
738
|
-
const method = `generate${ast.type}`
|
|
739
|
-
if (this[method]) {
|
|
740
|
-
return this[method](ast)
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
return super.generate(ast)
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
generateJSXElement(node) {
|
|
747
|
-
let result = this.generate(node.openingElement)
|
|
748
|
-
|
|
749
|
-
if (!node.openingElement.selfClosing) {
|
|
750
|
-
for (const child of node.children) {
|
|
751
|
-
result += this.generate(child)
|
|
752
|
-
}
|
|
753
|
-
if (node.closingElement) {
|
|
754
|
-
result += this.generate(node.closingElement)
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
return result
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
generateJSXOpeningElement(node) {
|
|
762
|
-
let result = '<' + this.generate(node.name)
|
|
763
|
-
|
|
764
|
-
for (const attr of node.attributes) {
|
|
765
|
-
result += ' ' + this.generate(attr)
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
if (node.selfClosing) {
|
|
769
|
-
result += ' />'
|
|
770
|
-
} else {
|
|
771
|
-
result += '>'
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
return result
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
generateJSXClosingElement(node) {
|
|
778
|
-
return '</' + this.generate(node.name) + '>'
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
generateJSXFragment(node) {
|
|
782
|
-
let result = '<>'
|
|
783
|
-
|
|
784
|
-
for (const child of node.children) {
|
|
785
|
-
result += this.generate(child)
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
result += '</>'
|
|
789
|
-
return result
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
generateJSXOpeningFragment() {
|
|
793
|
-
return '<>'
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
generateJSXClosingFragment() {
|
|
797
|
-
return '</>'
|
|
798
|
-
}
|
|
799
|
-
|
|
800
|
-
generateJSXIdentifier(node) {
|
|
801
|
-
return node.name
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
generateJSXMemberExpression(node) {
|
|
805
|
-
return this.generate(node.object) + '.' + this.generate(node.property)
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
generateJSXNamespacedName(node) {
|
|
809
|
-
return this.generate(node.namespace) + ':' + this.generate(node.name)
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
generateJSXAttribute(node) {
|
|
813
|
-
let result = this.generate(node.name)
|
|
814
|
-
|
|
815
|
-
if (node.value !== null) {
|
|
816
|
-
result += '='
|
|
817
|
-
if (node.value.type === 'StringLiteral') {
|
|
818
|
-
result += this.generate(node.value)
|
|
819
|
-
} else {
|
|
820
|
-
result += this.generate(node.value)
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
return result
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
generateJSXSpreadAttribute(node) {
|
|
828
|
-
return '{...' + this.generate(node.argument) + '}'
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
generateJSXText(node) {
|
|
832
|
-
return node.value
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
generateJSXExpressionContainer(node) {
|
|
836
|
-
return '{' + this.generate(node.expression) + '}'
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
generateJSXSpreadChild(node) {
|
|
840
|
-
return '{...' + this.generate(node.expression) + '}'
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
generateJSXEmptyExpression() {
|
|
844
|
-
return ''
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
generateReactHookCall(node) {
|
|
848
|
-
const args = node.arguments.map(a => this.generate(a)).join(', ')
|
|
849
|
-
return `${node.hookName}(${args})`
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
generateReactComponent(node) {
|
|
853
|
-
const props = node.props.length > 0 ? `{ ${node.props.join(', ')} }` : ''
|
|
854
|
-
|
|
855
|
-
if (node.componentType === 'function') {
|
|
856
|
-
return `function ${node.name}(${props}) ${this.generate(node.body)}`
|
|
857
|
-
} else {
|
|
858
|
-
return `class ${node.name} extends React.Component ${this.generate(node.body)}`
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
|
|
862
|
-
generateReactDirective(node) {
|
|
863
|
-
return `"${node.directive}";`
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
generateUseStateHook(node) {
|
|
867
|
-
const init = node.initialValue ? this.generate(node.initialValue) : ''
|
|
868
|
-
return `const [${node.stateName}, ${node.setterName}] = useState(${init})`
|
|
869
|
-
}
|
|
870
|
-
|
|
871
|
-
generateUseEffectHook(node) {
|
|
872
|
-
const callback = this.generate(node.callback)
|
|
873
|
-
const deps = node.dependencies ? this.generate(node.dependencies) : ''
|
|
874
|
-
return `useEffect(${callback}${deps ? ', ' + deps : ''})`
|
|
875
|
-
}
|
|
876
|
-
|
|
877
|
-
generateUseRefHook(node) {
|
|
878
|
-
const init = node.initialValue ? this.generate(node.initialValue) : 'null'
|
|
879
|
-
return `const ${node.refName} = useRef(${init})`
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
generateUseContextHook(node) {
|
|
883
|
-
return `useContext(${this.generate(node.context)})`
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
generateUseReducerHook(node) {
|
|
887
|
-
const reducer = this.generate(node.reducer)
|
|
888
|
-
const init = this.generate(node.initialState)
|
|
889
|
-
return `const [${node.stateName}, ${node.dispatchName}] = useReducer(${reducer}, ${init})`
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
generateUseMemoHook(node) {
|
|
893
|
-
const factory = this.generate(node.factory)
|
|
894
|
-
const deps = this.generate(new AST.ArrayExpression(node.dependencies, null))
|
|
895
|
-
return `useMemo(${factory}, ${deps})`
|
|
896
|
-
}
|
|
897
|
-
|
|
898
|
-
generateUseCallbackHook(node) {
|
|
899
|
-
const callback = this.generate(node.callback)
|
|
900
|
-
const deps = this.generate(new AST.ArrayExpression(node.dependencies, null))
|
|
901
|
-
return `useCallback(${callback}, ${deps})`
|
|
902
|
-
}
|
|
903
|
-
|
|
904
|
-
generateUseTransitionHook(node) {
|
|
905
|
-
return `const [${node.isPendingName}, ${node.startTransitionName}] = useTransition()`
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
generateUseDeferredValueHook(node) {
|
|
909
|
-
return `useDeferredValue(${this.generate(node.value)})`
|
|
910
|
-
}
|
|
911
|
-
|
|
912
|
-
generateUseIdHook(node) {
|
|
913
|
-
return `const ${node.idName} = useId()`
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
generateCreateContextCall(node) {
|
|
917
|
-
const defaultVal = node.defaultValue ? this.generate(node.defaultValue) : ''
|
|
918
|
-
return `createContext(${defaultVal})`
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
generateContextProvider(node) {
|
|
922
|
-
const value = this.generate(node.value)
|
|
923
|
-
const children = node.children.map(c => this.generate(c)).join('')
|
|
924
|
-
return `<${this.generate(node.context)}.Provider value={${value}}>${children}</${this.generate(node.context)}.Provider>`
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
generateForwardRefCall(node) {
|
|
928
|
-
return `forwardRef(${this.generate(node.render)})`
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
generateMemoCall(node) {
|
|
932
|
-
const component = this.generate(node.component)
|
|
933
|
-
const areEqual = node.areEqual ? ', ' + this.generate(node.areEqual) : ''
|
|
934
|
-
return `memo(${component}${areEqual})`
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
generateLazyCall(node) {
|
|
938
|
-
return `lazy(${this.generate(node.load)})`
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
generateSuspenseComponent(node) {
|
|
942
|
-
const fallback = this.generate(node.fallback)
|
|
943
|
-
const children = node.children.map(c => this.generate(c)).join('')
|
|
944
|
-
return `<Suspense fallback={${fallback}}>${children}</Suspense>`
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
generateStrictModeComponent(node) {
|
|
948
|
-
const children = node.children.map(c => this.generate(c)).join('')
|
|
949
|
-
return `<StrictMode>${children}</StrictMode>`
|
|
950
|
-
}
|
|
951
|
-
|
|
952
|
-
generateProfilerComponent(node) {
|
|
953
|
-
const id = this.generate(node.id)
|
|
954
|
-
const onRender = this.generate(node.onRender)
|
|
955
|
-
const children = node.children.map(c => this.generate(c)).join('')
|
|
956
|
-
return `<Profiler id=${id} onRender={${onRender}}>${children}</Profiler>`
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
generateCreatePortalCall(node) {
|
|
960
|
-
const children = this.generate(node.children)
|
|
961
|
-
const container = this.generate(node.container)
|
|
962
|
-
const key = node.key ? ', ' + this.generate(node.key) : ''
|
|
963
|
-
return `createPortal(${children}, ${container}${key})`
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
generateCreateRootCall(node) {
|
|
967
|
-
const container = this.generate(node.container)
|
|
968
|
-
const options = node.options ? ', ' + this.generate(node.options) : ''
|
|
969
|
-
return `createRoot(${container}${options})`
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
generateHydrateRootCall(node) {
|
|
973
|
-
const container = this.generate(node.container)
|
|
974
|
-
const children = this.generate(node.initialChildren)
|
|
975
|
-
const options = node.options ? ', ' + this.generate(node.options) : ''
|
|
976
|
-
return `hydrateRoot(${container}, ${children}${options})`
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
generateStartTransitionCall(node) {
|
|
980
|
-
return `startTransition(${this.generate(node.callback)})`
|
|
981
|
-
}
|
|
982
|
-
|
|
983
|
-
generateFlushSyncCall(node) {
|
|
984
|
-
return `flushSync(${this.generate(node.callback)})`
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
generateCreateElementCall(node) {
|
|
988
|
-
const type = typeof node.elementType === 'string' ? `"${node.elementType}"` : this.generate(node.elementType)
|
|
989
|
-
const props = node.props ? this.generate(node.props) : 'null'
|
|
990
|
-
const children = node.children.map(c => this.generate(c)).join(', ')
|
|
991
|
-
return `createElement(${type}, ${props}${children ? ', ' + children : ''})`
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
generateCloneElementCall(node) {
|
|
995
|
-
const element = this.generate(node.element)
|
|
996
|
-
const props = node.props ? this.generate(node.props) : 'null'
|
|
997
|
-
const children = node.children.map(c => this.generate(c)).join(', ')
|
|
998
|
-
return `cloneElement(${element}, ${props}${children ? ', ' + children : ''})`
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
|
-
generateServerActionFunction(node) {
|
|
1002
|
-
const params = node.params.map(p => this.generate(p)).join(', ')
|
|
1003
|
-
return `async function ${node.name}(${params}) {\n "use server";\n${this.generate(node.body)}\n}`
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
|
-
generateEtherReactComponent(node) {
|
|
1007
|
-
const props = node.props.length > 0 ? `{ ${node.props.join(', ')} }` : ''
|
|
1008
|
-
const hooks = node.hooks.map(h => ' ' + this.generate(h)).join('\n')
|
|
1009
|
-
const jsx = this.generate(node.returnJSX)
|
|
1010
|
-
|
|
1011
|
-
return `function ${node.name}(${props}) {\n${hooks}\n return (\n ${jsx}\n );\n}`
|
|
1012
|
-
}
|
|
1013
|
-
|
|
1014
|
-
generateEtherHookDeclaration(node) {
|
|
1015
|
-
const bindings = node.bindings.join(', ')
|
|
1016
|
-
const args = node.arguments.map(a => this.generate(a)).join(', ')
|
|
1017
|
-
|
|
1018
|
-
if (node.bindings.length === 1) {
|
|
1019
|
-
return `const ${bindings} = ${node.hookType}(${args});`
|
|
1020
|
-
} else if (node.bindings.length === 2) {
|
|
1021
|
-
return `const [${bindings}] = ${node.hookType}(${args});`
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
|
-
return `${node.hookType}(${args});`
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
module.exports = {
|
|
1029
|
-
ReactLexer,
|
|
1030
|
-
ReactParser,
|
|
1031
|
-
ReactCodeGenerator,
|
|
1032
|
-
REACT_HOOKS,
|
|
1033
|
-
REACT_COMPONENTS,
|
|
1034
|
-
SELF_CLOSING_TAGS
|
|
1035
|
-
}
|