onelaraveljs 1.0.0 → 1.1.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/README.md +1 -1
- package/bin/onejs-build.js +32 -0
- package/index.js +3 -1
- package/package.json +11 -3
- package/scripts/README-template-compiler.md +133 -0
- package/scripts/README.md +61 -0
- package/scripts/__pycache__/build.cpython-314.pyc +0 -0
- package/scripts/__pycache__/compile.cpython-313.pyc +0 -0
- package/scripts/__pycache__/compile.cpython-314.pyc +0 -0
- package/scripts/build.py +574 -0
- package/scripts/check-system-errors.php +214 -0
- package/scripts/compile.py +101 -0
- package/scripts/compiler/README_CONFIG.md +196 -0
- package/scripts/compiler/__init__.py +18 -0
- package/scripts/compiler/__pycache__/__init__.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/__init__.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/binding_directive_service.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/class_binding_handler.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/compiler_utils.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/compiler_utils.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/conditional_handlers.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/conditional_handlers.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/config.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/config.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/declaration_tracker.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/directive_processors.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/directive_processors.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/echo_processor.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/event_directive_processor.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/event_directive_processor.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/function_generators.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/function_generators.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/loop_handlers.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/loop_handlers.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/main_compiler.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/main_compiler.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/parsers.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/parsers.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/php_converter.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/php_converter.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/php_js_converter.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/php_js_converter.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/register_parser.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/register_parser.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/section_handlers.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/section_handlers.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/show_directive_handler.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/style_directive_handler.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/template_analyzer.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/template_analyzer.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/template_processor.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/template_processor.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/template_processors.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/template_processors.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/utils.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/utils.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/wrapper_parser.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/wrapper_parser.cpython-314.pyc +0 -0
- package/scripts/compiler/binding_directive_service.py +103 -0
- package/scripts/compiler/class_binding_handler.py +347 -0
- package/scripts/compiler/cli.py +34 -0
- package/scripts/compiler/code_generator.py +141 -0
- package/scripts/compiler/compiler.config.json +36 -0
- package/scripts/compiler/compiler_utils.py +55 -0
- package/scripts/compiler/conditional_handlers.py +252 -0
- package/scripts/compiler/config.py +107 -0
- package/scripts/compiler/declaration_tracker.py +420 -0
- package/scripts/compiler/directive_processors.py +603 -0
- package/scripts/compiler/echo_processor.py +667 -0
- package/scripts/compiler/event_directive_processor.py +1099 -0
- package/scripts/compiler/fetch_parser.py +49 -0
- package/scripts/compiler/function_generators.py +310 -0
- package/scripts/compiler/loop_handlers.py +224 -0
- package/scripts/compiler/main_compiler.py +1763 -0
- package/scripts/compiler/parsers.py +1418 -0
- package/scripts/compiler/php_converter.py +470 -0
- package/scripts/compiler/php_js_converter.py +603 -0
- package/scripts/compiler/register_parser.py +480 -0
- package/scripts/compiler/section_handlers.py +122 -0
- package/scripts/compiler/show_directive_handler.py +85 -0
- package/scripts/compiler/style_directive_handler.py +169 -0
- package/scripts/compiler/template_analyzer.py +162 -0
- package/scripts/compiler/template_processor.py +1167 -0
- package/scripts/compiler/template_processors.py +1557 -0
- package/scripts/compiler/test_compiler.py +69 -0
- package/scripts/compiler/utils.py +54 -0
- package/scripts/compiler/variables_analyzer.py +135 -0
- package/scripts/compiler/view_identifier_generator.py +278 -0
- package/scripts/compiler/wrapper_parser.py +78 -0
- package/scripts/dev-context.js +311 -0
- package/scripts/dev.js +109 -0
- package/scripts/generate-assets-order.js +208 -0
- package/scripts/migrate-namespace.php +146 -0
- package/scripts/node/MIGRATION.md +190 -0
- package/scripts/node/README.md +269 -0
- package/scripts/node/build.js +208 -0
- package/scripts/node/compiler/compiler-utils.js +38 -0
- package/scripts/node/compiler/conditional-handlers.js +45 -0
- package/scripts/node/compiler/config.js +178 -0
- package/scripts/node/compiler/directive-processors.js +51 -0
- package/scripts/node/compiler/event-directive-processor.js +182 -0
- package/scripts/node/compiler/function-generators.js +239 -0
- package/scripts/node/compiler/loop-handlers.js +45 -0
- package/scripts/node/compiler/main-compiler.js +236 -0
- package/scripts/node/compiler/parsers.js +358 -0
- package/scripts/node/compiler/php-converter.js +227 -0
- package/scripts/node/compiler/register-parser.js +32 -0
- package/scripts/node/compiler/section-handlers.js +46 -0
- package/scripts/node/compiler/template-analyzer.js +50 -0
- package/scripts/node/compiler/template-processor.js +371 -0
- package/scripts/node/compiler/template-processors.js +219 -0
- package/scripts/node/compiler/utils.js +203 -0
- package/scripts/node/compiler/wrapper-parser.js +25 -0
- package/scripts/node/package.json +24 -0
- package/scripts/node/test-compiler.js +52 -0
- package/scripts/node-run.cjs +28 -0
- package/scripts/standardize-directories.php +92 -0
- package/src/core/ViewManager.js +4 -4
- package/templates/view.module.js +2 -0
- package/templates/view.tpl-raw.js +13 -0
- package/templates/wraper.js +71 -0
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Chuyển đổi các biểu thức PHP sang JavaScript
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from config import JS_FUNCTION_PREFIX
|
|
6
|
+
from utils import normalize_quotes
|
|
7
|
+
from php_js_converter import php_to_js_advanced
|
|
8
|
+
import re
|
|
9
|
+
import subprocess
|
|
10
|
+
|
|
11
|
+
def convert_php_array_with_php_r(php_array_expr):
|
|
12
|
+
"""Convert PHP array to JSON using php -r command"""
|
|
13
|
+
try:
|
|
14
|
+
# Tạo PHP code để convert array sang JSON
|
|
15
|
+
php_code = f"try {{ echo json_encode({php_array_expr}); }} catch (Exception $e) {{ echo '[]'; }}"
|
|
16
|
+
|
|
17
|
+
# Chạy php -r command
|
|
18
|
+
result = subprocess.run(
|
|
19
|
+
['php', '-r', php_code],
|
|
20
|
+
capture_output=True,
|
|
21
|
+
text=True,
|
|
22
|
+
timeout=5, # 5 giây timeout
|
|
23
|
+
check=False # Không raise exception khi return code != 0
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
if result.returncode == 0:
|
|
27
|
+
# Parse JSON output
|
|
28
|
+
json_output = result.stdout.strip()
|
|
29
|
+
return json_output
|
|
30
|
+
else:
|
|
31
|
+
print(f"PHP error: {result.stderr}")
|
|
32
|
+
return None
|
|
33
|
+
|
|
34
|
+
except (subprocess.TimeoutExpired, subprocess.SubprocessError, OSError) as e:
|
|
35
|
+
print(f"Error running php -r: {e}")
|
|
36
|
+
return None
|
|
37
|
+
|
|
38
|
+
def convert_php_array_to_json(expr):
|
|
39
|
+
"""Convert PHP array syntax to JSON object/array syntax using php -r"""
|
|
40
|
+
if not expr or '[' not in expr:
|
|
41
|
+
return expr
|
|
42
|
+
|
|
43
|
+
# Tìm tất cả các mảng PHP và convert chúng
|
|
44
|
+
def replace_array(match):
|
|
45
|
+
full_array = match.group(0) # Toàn bộ array expression
|
|
46
|
+
inner = match.group(1).strip()
|
|
47
|
+
|
|
48
|
+
if not inner:
|
|
49
|
+
return '[]'
|
|
50
|
+
|
|
51
|
+
# Check if this is array access vs array literal
|
|
52
|
+
if (("'" in inner and inner.count("'") == 2 and not '=>' in inner) or
|
|
53
|
+
('"' in inner and inner.count('"') == 2 and not '=>' in inner) or
|
|
54
|
+
(inner.replace('_', '').replace('.', '').isalnum() and not '=>' in inner)):
|
|
55
|
+
return '[' + inner + ']' # Keep as array access
|
|
56
|
+
|
|
57
|
+
# Sử dụng php -r để convert array
|
|
58
|
+
json_result = convert_php_array_with_php_r(full_array)
|
|
59
|
+
if json_result is not None:
|
|
60
|
+
return json_result
|
|
61
|
+
|
|
62
|
+
# Fallback to old method if php -r fails
|
|
63
|
+
return _convert_php_array_legacy(full_array)
|
|
64
|
+
|
|
65
|
+
# Thử sử dụng php -r cho toàn bộ expression trước
|
|
66
|
+
json_result = convert_php_array_with_php_r(expr)
|
|
67
|
+
if json_result is not None and 'PHP error' not in str(json_result):
|
|
68
|
+
return json_result
|
|
69
|
+
|
|
70
|
+
# Fallback: chỉ xử lý quotes đơn giản
|
|
71
|
+
expr = re.sub(r"'([^']*)'", r'"\1"', expr)
|
|
72
|
+
return expr
|
|
73
|
+
|
|
74
|
+
def _process_array_content(inner_content):
|
|
75
|
+
"""Process array content directly without recursion"""
|
|
76
|
+
if not inner_content:
|
|
77
|
+
return '[]'
|
|
78
|
+
|
|
79
|
+
# Process array elements
|
|
80
|
+
elements = []
|
|
81
|
+
current_element = ''
|
|
82
|
+
paren_count = 0
|
|
83
|
+
bracket_count = 0
|
|
84
|
+
in_quotes = False
|
|
85
|
+
quote_char = ''
|
|
86
|
+
|
|
87
|
+
i = 0
|
|
88
|
+
while i < len(inner_content):
|
|
89
|
+
char = inner_content[i]
|
|
90
|
+
|
|
91
|
+
if not in_quotes:
|
|
92
|
+
if char in ['"', "'"]:
|
|
93
|
+
in_quotes = True
|
|
94
|
+
quote_char = char
|
|
95
|
+
current_element += char
|
|
96
|
+
elif char == '(':
|
|
97
|
+
paren_count += 1
|
|
98
|
+
current_element += char
|
|
99
|
+
elif char == ')':
|
|
100
|
+
paren_count -= 1
|
|
101
|
+
current_element += char
|
|
102
|
+
elif char == '[':
|
|
103
|
+
bracket_count += 1
|
|
104
|
+
current_element += char
|
|
105
|
+
elif char == ']':
|
|
106
|
+
bracket_count -= 1
|
|
107
|
+
current_element += char
|
|
108
|
+
elif char == ',' and paren_count == 0 and bracket_count == 0:
|
|
109
|
+
# End of element
|
|
110
|
+
elements.append(current_element.strip())
|
|
111
|
+
current_element = ''
|
|
112
|
+
else:
|
|
113
|
+
current_element += char
|
|
114
|
+
else:
|
|
115
|
+
if char == quote_char:
|
|
116
|
+
# Check if it's escaped
|
|
117
|
+
escape_count = 0
|
|
118
|
+
j = i - 1
|
|
119
|
+
while j >= 0 and inner_content[j] == '\\':
|
|
120
|
+
escape_count += 1
|
|
121
|
+
j -= 1
|
|
122
|
+
|
|
123
|
+
# If even number of backslashes, quote is not escaped
|
|
124
|
+
if escape_count % 2 == 0:
|
|
125
|
+
in_quotes = False
|
|
126
|
+
|
|
127
|
+
current_element += char
|
|
128
|
+
|
|
129
|
+
i += 1
|
|
130
|
+
|
|
131
|
+
# Add last element
|
|
132
|
+
if current_element.strip():
|
|
133
|
+
elements.append(current_element.strip())
|
|
134
|
+
|
|
135
|
+
# Process elements
|
|
136
|
+
processed_elements = []
|
|
137
|
+
for element in elements:
|
|
138
|
+
element = element.strip()
|
|
139
|
+
if not element:
|
|
140
|
+
continue
|
|
141
|
+
|
|
142
|
+
# Check if it's a key => value pair
|
|
143
|
+
if '=>' in element:
|
|
144
|
+
key, value = element.split('=>', 1)
|
|
145
|
+
key = key.strip()
|
|
146
|
+
value = value.strip()
|
|
147
|
+
|
|
148
|
+
# Convert key
|
|
149
|
+
if key.startswith("'") and key.endswith("'"):
|
|
150
|
+
key_js = '"' + key[1:-1] + '"'
|
|
151
|
+
elif key.startswith('"') and key.endswith('"'):
|
|
152
|
+
key_js = key
|
|
153
|
+
elif key.replace('_', '').replace('.', '').isalnum():
|
|
154
|
+
key_js = '"' + key + '"'
|
|
155
|
+
else:
|
|
156
|
+
key_js = key
|
|
157
|
+
|
|
158
|
+
# Convert value
|
|
159
|
+
if value.startswith("'") and value.endswith("'"):
|
|
160
|
+
value_js = '"' + value[1:-1] + '"'
|
|
161
|
+
elif value.startswith('"') and value.endswith('"'):
|
|
162
|
+
value_js = value
|
|
163
|
+
elif value in ['true', 'false', 'null']:
|
|
164
|
+
value_js = value
|
|
165
|
+
elif value.replace('.', '').replace('-', '').isdigit():
|
|
166
|
+
value_js = value
|
|
167
|
+
else:
|
|
168
|
+
# Try to convert nested arrays using php -r
|
|
169
|
+
try:
|
|
170
|
+
value_js = convert_php_array_with_php_r(value)
|
|
171
|
+
except:
|
|
172
|
+
value_js = value
|
|
173
|
+
|
|
174
|
+
processed_elements.append(key_js + ': ' + value_js)
|
|
175
|
+
else:
|
|
176
|
+
# Simple value
|
|
177
|
+
if element.startswith("'") and element.endswith("'"):
|
|
178
|
+
element_js = '"' + element[1:-1] + '"'
|
|
179
|
+
elif element.startswith('"') and element.endswith('"'):
|
|
180
|
+
element_js = element
|
|
181
|
+
elif element in ['true', 'false', 'null']:
|
|
182
|
+
element_js = element
|
|
183
|
+
elif element.replace('.', '').replace('-', '').isdigit():
|
|
184
|
+
element_js = element
|
|
185
|
+
else:
|
|
186
|
+
# Try to convert nested arrays using php -r
|
|
187
|
+
try:
|
|
188
|
+
element_js = convert_php_array_with_php_r(element)
|
|
189
|
+
except:
|
|
190
|
+
element_js = element
|
|
191
|
+
|
|
192
|
+
processed_elements.append(element_js)
|
|
193
|
+
|
|
194
|
+
if not processed_elements:
|
|
195
|
+
return '[]'
|
|
196
|
+
elif any(':' in elem for elem in processed_elements):
|
|
197
|
+
# This is a mixed array, treat as object
|
|
198
|
+
return '{' + ', '.join(processed_elements) + '}'
|
|
199
|
+
else:
|
|
200
|
+
return '[' + ', '.join(processed_elements) + ']'
|
|
201
|
+
|
|
202
|
+
def _convert_php_array_legacy(expr):
|
|
203
|
+
"""Legacy method for converting PHP arrays (fallback)"""
|
|
204
|
+
# Find all array patterns and convert them
|
|
205
|
+
def replace_array(match):
|
|
206
|
+
inner = match.group(1).strip()
|
|
207
|
+
if not inner:
|
|
208
|
+
return '[]'
|
|
209
|
+
|
|
210
|
+
# Check if this is array access vs array literal (không phải nested array)
|
|
211
|
+
if (("'" in inner and inner.count("'") == 2 and not '=>' in inner and inner.count('[') == 0) or
|
|
212
|
+
('"' in inner and inner.count('"') == 2 and not '=>' in inner and inner.count('[') == 0) or
|
|
213
|
+
(inner.replace('_', '').replace('.', '').isalnum() and not '=>' in inner and inner.count('[') == 0)):
|
|
214
|
+
return '[' + inner + ']' # Keep as array access
|
|
215
|
+
|
|
216
|
+
# Process array elements
|
|
217
|
+
elements = []
|
|
218
|
+
current_element = ''
|
|
219
|
+
paren_count = 0
|
|
220
|
+
bracket_count = 0
|
|
221
|
+
in_quotes = False
|
|
222
|
+
quote_char = ''
|
|
223
|
+
i = 0
|
|
224
|
+
|
|
225
|
+
while i < len(inner):
|
|
226
|
+
char = inner[i]
|
|
227
|
+
|
|
228
|
+
if (char == '"' or char == "'") and not in_quotes:
|
|
229
|
+
in_quotes = True
|
|
230
|
+
quote_char = char
|
|
231
|
+
elif char == quote_char and in_quotes:
|
|
232
|
+
in_quotes = False
|
|
233
|
+
quote_char = ''
|
|
234
|
+
elif not in_quotes:
|
|
235
|
+
if char == '(':
|
|
236
|
+
paren_count += 1
|
|
237
|
+
elif char == ')':
|
|
238
|
+
paren_count -= 1
|
|
239
|
+
elif char == '[':
|
|
240
|
+
bracket_count += 1
|
|
241
|
+
elif char == ']':
|
|
242
|
+
bracket_count -= 1
|
|
243
|
+
elif char == ',' and paren_count == 0 and bracket_count == 0:
|
|
244
|
+
elements.append(current_element.strip())
|
|
245
|
+
current_element = ''
|
|
246
|
+
i += 1
|
|
247
|
+
continue
|
|
248
|
+
|
|
249
|
+
current_element += char
|
|
250
|
+
i += 1
|
|
251
|
+
|
|
252
|
+
if current_element.strip():
|
|
253
|
+
elements.append(current_element.strip())
|
|
254
|
+
|
|
255
|
+
# Process each element
|
|
256
|
+
processed_elements = []
|
|
257
|
+
has_key_value_pairs = False
|
|
258
|
+
|
|
259
|
+
for element in elements:
|
|
260
|
+
element = element.strip()
|
|
261
|
+
if '=>' in element:
|
|
262
|
+
# This is a key => value pair
|
|
263
|
+
has_key_value_pairs = True
|
|
264
|
+
key_value = element.split('=>', 1)
|
|
265
|
+
key = key_value[0].strip().strip('\'"')
|
|
266
|
+
value = key_value[1].strip()
|
|
267
|
+
|
|
268
|
+
# Convert value to JS (recursively)
|
|
269
|
+
value_js = _convert_php_array_legacy(value)
|
|
270
|
+
|
|
271
|
+
# Normalize quotes in value_js
|
|
272
|
+
value_js = normalize_quotes(value_js)
|
|
273
|
+
|
|
274
|
+
# Handle key (add quotes if not already quoted)
|
|
275
|
+
if not (key.startswith('"') and key.endswith('"')) and not (key.startswith("'") and key.endswith("'")):
|
|
276
|
+
key = f'"{key}"'
|
|
277
|
+
|
|
278
|
+
processed_elements.append(f'{key}: {value_js}')
|
|
279
|
+
else:
|
|
280
|
+
# This is a simple value - check if it's a nested array
|
|
281
|
+
if '[' in element and ']' in element:
|
|
282
|
+
# It's a nested array, try php -r first
|
|
283
|
+
json_result = convert_php_array_with_php_r(element)
|
|
284
|
+
if json_result is not None:
|
|
285
|
+
value_js = json_result
|
|
286
|
+
else:
|
|
287
|
+
# Fallback to recursive conversion
|
|
288
|
+
value_js = _convert_php_array_legacy(element)
|
|
289
|
+
else:
|
|
290
|
+
# Simple value
|
|
291
|
+
value_js = element
|
|
292
|
+
|
|
293
|
+
value_js = normalize_quotes(value_js)
|
|
294
|
+
processed_elements.append(value_js)
|
|
295
|
+
|
|
296
|
+
# If contains key-value pairs, it's an object
|
|
297
|
+
if has_key_value_pairs:
|
|
298
|
+
return '{' + ', '.join(processed_elements) + '}'
|
|
299
|
+
else:
|
|
300
|
+
# Check if this is a numeric array
|
|
301
|
+
is_numeric_array = True
|
|
302
|
+
for element in elements:
|
|
303
|
+
if '=>' in element:
|
|
304
|
+
is_numeric_array = False
|
|
305
|
+
break
|
|
306
|
+
|
|
307
|
+
if is_numeric_array:
|
|
308
|
+
return '[' + ', '.join(processed_elements) + ']'
|
|
309
|
+
else:
|
|
310
|
+
# This is a mixed array, treat as object
|
|
311
|
+
return '{' + ', '.join(processed_elements) + '}'
|
|
312
|
+
|
|
313
|
+
# Apply array conversion recursively với balanced bracket matching
|
|
314
|
+
def find_and_replace_arrays(text):
|
|
315
|
+
result = text
|
|
316
|
+
while '[' in result:
|
|
317
|
+
# Tìm mảng đầu tiên
|
|
318
|
+
start = result.find('[')
|
|
319
|
+
if start == -1:
|
|
320
|
+
break
|
|
321
|
+
|
|
322
|
+
# Tìm closing bracket tương ứng với balanced matching
|
|
323
|
+
bracket_count = 0
|
|
324
|
+
end = start
|
|
325
|
+
in_quotes = False
|
|
326
|
+
quote_char = ''
|
|
327
|
+
|
|
328
|
+
for i in range(start, len(result)):
|
|
329
|
+
char = result[i]
|
|
330
|
+
|
|
331
|
+
if not in_quotes:
|
|
332
|
+
if char in ['"', "'"]:
|
|
333
|
+
in_quotes = True
|
|
334
|
+
quote_char = char
|
|
335
|
+
elif char == '[':
|
|
336
|
+
bracket_count += 1
|
|
337
|
+
elif char == ']':
|
|
338
|
+
bracket_count -= 1
|
|
339
|
+
if bracket_count == 0:
|
|
340
|
+
end = i
|
|
341
|
+
break
|
|
342
|
+
else:
|
|
343
|
+
if char == quote_char:
|
|
344
|
+
# Check if it's escaped
|
|
345
|
+
escape_count = 0
|
|
346
|
+
j = i - 1
|
|
347
|
+
while j >= 0 and result[j] == '\\':
|
|
348
|
+
escape_count += 1
|
|
349
|
+
j -= 1
|
|
350
|
+
|
|
351
|
+
# If even number of backslashes, quote is not escaped
|
|
352
|
+
if escape_count % 2 == 0:
|
|
353
|
+
in_quotes = False
|
|
354
|
+
|
|
355
|
+
if bracket_count == 0:
|
|
356
|
+
# Tìm thấy mảng hoàn chỉnh
|
|
357
|
+
array_expr = result[start:end+1]
|
|
358
|
+
inner_content = array_expr[1:-1].strip()
|
|
359
|
+
|
|
360
|
+
if not inner_content:
|
|
361
|
+
replacement = '[]'
|
|
362
|
+
else:
|
|
363
|
+
# Check if this is array access vs array literal
|
|
364
|
+
if (("'" in inner_content and inner_content.count("'") == 2 and not '=>' in inner_content and inner_content.count('[') == 0) or
|
|
365
|
+
('"' in inner_content and inner_content.count('"') == 2 and not '=>' in inner_content and inner_content.count('[') == 0) or
|
|
366
|
+
(inner_content.replace('_', '').replace('.', '').isalnum() and not '=>' in inner_content and inner_content.count('[') == 0)):
|
|
367
|
+
replacement = array_expr # Keep as array access
|
|
368
|
+
else:
|
|
369
|
+
# Process as array literal - xử lý trực tiếp để tránh vòng lặp
|
|
370
|
+
replacement = _process_array_content(inner_content)
|
|
371
|
+
|
|
372
|
+
result = result[:start] + replacement + result[end+1:]
|
|
373
|
+
else:
|
|
374
|
+
break
|
|
375
|
+
|
|
376
|
+
return result
|
|
377
|
+
|
|
378
|
+
expr = find_and_replace_arrays(expr)
|
|
379
|
+
|
|
380
|
+
return expr
|
|
381
|
+
|
|
382
|
+
def php_to_js(expr):
|
|
383
|
+
"""Convert PHP expression to JavaScript using advanced converter"""
|
|
384
|
+
if expr is None:
|
|
385
|
+
return "''"
|
|
386
|
+
|
|
387
|
+
# Remove PHP closure use(...) syntax
|
|
388
|
+
expr = re.sub(r'\s+use\s*\([^)]*\)', '', expr)
|
|
389
|
+
|
|
390
|
+
# Handle foreach BEFORE converting => to :
|
|
391
|
+
foreach_pattern = r'\bforeach\s*\(\s*(.*?)\s*as\s*\$?(\w+)(\s*=>\s*\$?(\w+))?\s*\)(\s*)\{'
|
|
392
|
+
|
|
393
|
+
def replace_foreach(match):
|
|
394
|
+
array_expr = match.group(1).strip()
|
|
395
|
+
first_var = match.group(2)
|
|
396
|
+
space_before_brace = match.group(5) if len(match.groups()) >= 5 else ' '
|
|
397
|
+
|
|
398
|
+
if match.group(3): # Has key => value
|
|
399
|
+
key_var = first_var # first var is key
|
|
400
|
+
value_var = match.group(4) # second var is value
|
|
401
|
+
return f'{JS_FUNCTION_PREFIX}.foreach({array_expr}, ({value_var}, {key_var}, __loopIndex, loop) =>{space_before_brace}{{'
|
|
402
|
+
else: # Only value
|
|
403
|
+
value_var = first_var
|
|
404
|
+
return f'{JS_FUNCTION_PREFIX}.foreach({array_expr}, ({value_var}, __loopKey, __loopIndex, loop) =>{space_before_brace}{{'
|
|
405
|
+
|
|
406
|
+
expr = re.sub(foreach_pattern, replace_foreach, expr)
|
|
407
|
+
|
|
408
|
+
# Use advanced converter for complex structures
|
|
409
|
+
expr = php_to_js_advanced(expr)
|
|
410
|
+
|
|
411
|
+
return expr
|
|
412
|
+
|
|
413
|
+
def convert_php_to_js(php_expr):
|
|
414
|
+
"""Convert PHP expressions to JavaScript equivalents"""
|
|
415
|
+
php_expr = php_expr.strip()
|
|
416
|
+
|
|
417
|
+
# Convert PHP operators to JavaScript with correct precedence order:
|
|
418
|
+
# (1) String concatenation "." -> "+"
|
|
419
|
+
# (2) Object accessor "->" -> "."
|
|
420
|
+
# (3) Static accessor "::" -> "."
|
|
421
|
+
|
|
422
|
+
# Step 1: Convert string concatenation (.) to (+) but be careful with object access and floats
|
|
423
|
+
# Don't convert dots that are part of numbers or already converted object access
|
|
424
|
+
php_expr = convert_string_concatenation(php_expr)
|
|
425
|
+
|
|
426
|
+
# Step 2: Convert object accessor (->) to (.)
|
|
427
|
+
php_expr = re.sub(r'->', '.', php_expr)
|
|
428
|
+
|
|
429
|
+
# Step 3: Convert static accessor (::) to (.)
|
|
430
|
+
# Handle $Class::$property and Class::method patterns
|
|
431
|
+
php_expr = re.sub(r'::', '.', php_expr)
|
|
432
|
+
|
|
433
|
+
# Remove $ prefix from variables (but keep it in template strings)
|
|
434
|
+
php_expr = convert_php_variables(php_expr)
|
|
435
|
+
|
|
436
|
+
return php_expr
|
|
437
|
+
|
|
438
|
+
def convert_string_concatenation(php_expr):
|
|
439
|
+
"""Convert PHP string concatenation (.) to JavaScript (+) with proper precedence"""
|
|
440
|
+
# Protect string literals first
|
|
441
|
+
string_literals = []
|
|
442
|
+
def protect_string_literal(match):
|
|
443
|
+
pattern = match.group(0)
|
|
444
|
+
placeholder = f"__STR_LIT_{len(string_literals)}__"
|
|
445
|
+
string_literals.append(pattern)
|
|
446
|
+
return placeholder
|
|
447
|
+
|
|
448
|
+
# Protect single-quoted strings
|
|
449
|
+
php_expr = re.sub(r"'[^']*'", protect_string_literal, php_expr)
|
|
450
|
+
# Protect double-quoted strings
|
|
451
|
+
php_expr = re.sub(r'"[^"]*"', protect_string_literal, php_expr)
|
|
452
|
+
|
|
453
|
+
# Pattern to match string concatenation dots (not in numbers, not in decimals)
|
|
454
|
+
# Look for dots that are surrounded by non-digit characters or are at word boundaries
|
|
455
|
+
pattern = r'(\w|\]|\))\s*\.\s*(?=\w|\$|\'|"|\()'
|
|
456
|
+
|
|
457
|
+
result = re.sub(pattern, r'\1+', php_expr)
|
|
458
|
+
|
|
459
|
+
# Restore string literals
|
|
460
|
+
for i, literal in enumerate(string_literals):
|
|
461
|
+
result = result.replace(f"__STR_LIT_{i}__", literal)
|
|
462
|
+
|
|
463
|
+
return result
|
|
464
|
+
|
|
465
|
+
def convert_php_variables(php_expr):
|
|
466
|
+
"""Convert $variable to variable (remove $ prefix)"""
|
|
467
|
+
# Don't convert $ in template strings (between backticks)
|
|
468
|
+
# Simple approach: convert $word patterns that are not in template strings
|
|
469
|
+
result = re.sub(r'\$([a-zA-Z_][a-zA-Z0-9_]*)', r'\1', php_expr)
|
|
470
|
+
return result
|