onelaraveljs 1.21.21 ā 1.21.23
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/package.json +1 -1
- package/scripts/compiler/conditional_handlers.py +16 -26
- package/scripts/compiler/declaration_tracker.py +0 -16
- package/scripts/compiler/directive_processors.py +5 -9
- package/scripts/compiler/loop_handlers.py +18 -16
- package/scripts/compiler/main_compiler.py +10 -62
- package/scripts/compiler/template_processor.py +4 -4
- package/src/core/ViewManager.js +60 -60
- package/scripts/compiler/test_todo_template.py +0 -83
package/package.json
CHANGED
|
@@ -60,29 +60,29 @@ class ConditionalHandlers:
|
|
|
60
60
|
parent_is_loop = True
|
|
61
61
|
parent_concat_var = f"__{parent_type}OutputContent__"
|
|
62
62
|
|
|
63
|
-
# If inside a loop and has state vars, use concat += with
|
|
63
|
+
# If inside a loop and has state vars, use concat += with __watch
|
|
64
64
|
if parent_is_loop and watch_keys:
|
|
65
65
|
if self.processor:
|
|
66
66
|
self.processor.watch_counter += 1
|
|
67
67
|
watch_id = f"`${{__VIEW_ID__}}-watch-{self.processor.watch_counter}-${{__loop.index}}`"
|
|
68
68
|
else:
|
|
69
69
|
watch_id = "`${__VIEW_ID__}-watch-0-${__loop.index}`"
|
|
70
|
-
result = f"{parent_concat_var} += this.
|
|
70
|
+
result = f"{parent_concat_var} += this.__watch({watch_id}, {watch_keys}, () => {{ if({condition}){{ return `"
|
|
71
71
|
# If inside a loop but no state vars, use concat += with IIFE
|
|
72
72
|
elif parent_is_loop:
|
|
73
73
|
result = f"{parent_concat_var} += (() => {{ if({condition}){{ return `"
|
|
74
|
-
# Only wrap with
|
|
74
|
+
# Only wrap with __watch for block-level directives (not attributes, not in loops)
|
|
75
75
|
elif is_attribute_context or not watch_keys:
|
|
76
76
|
# Attribute directive or no state vars - no watch wrapping
|
|
77
77
|
result = f"${{this.__execute(() => {{ if({condition}){{ return `"
|
|
78
78
|
else:
|
|
79
|
-
# Block directive with state vars - wrap with
|
|
79
|
+
# Block directive with state vars - wrap with __watch
|
|
80
80
|
if self.processor:
|
|
81
81
|
self.processor.watch_counter += 1
|
|
82
82
|
watch_id = f"`${{__VIEW_ID__}}-watch-{self.processor.watch_counter}`"
|
|
83
83
|
else:
|
|
84
84
|
watch_id = "`${__VIEW_ID__}-watch-0`"
|
|
85
|
-
result = f"${{this.
|
|
85
|
+
result = f"${{this.__watch({watch_id}, {watch_keys}, () => {{ if({condition}){{ return `"
|
|
86
86
|
|
|
87
87
|
output.append(result)
|
|
88
88
|
stack.append(('if', len(output), watch_keys, is_attribute_context, parent_is_loop))
|
|
@@ -136,18 +136,15 @@ class ConditionalHandlers:
|
|
|
136
136
|
output.append("return '';")
|
|
137
137
|
|
|
138
138
|
if parent_is_loop and watch_keys:
|
|
139
|
-
# Inside loop with state vars - close
|
|
140
|
-
# Pattern: }
|
|
141
|
-
output.append(
|
|
139
|
+
# Inside loop with state vars - close watch without template wrapper
|
|
140
|
+
# Pattern: })); where } closes arrow func, )) closes watch call, ; ends statement
|
|
141
|
+
output.append('});')
|
|
142
142
|
elif parent_is_loop:
|
|
143
143
|
# Inside loop without state vars - close IIFE with immediate execution
|
|
144
144
|
output.append('})')
|
|
145
145
|
else:
|
|
146
|
-
# Normal block - close IIFE or
|
|
147
|
-
|
|
148
|
-
output.append("}, {type: 'watch'}})")
|
|
149
|
-
else:
|
|
150
|
-
output.append('})}')
|
|
146
|
+
# Normal block - close IIFE or watch
|
|
147
|
+
output.append('})}')
|
|
151
148
|
return True
|
|
152
149
|
|
|
153
150
|
def process_switch_directive(self, line, stack, output, is_attribute_context=False):
|
|
@@ -193,7 +190,7 @@ class ConditionalHandlers:
|
|
|
193
190
|
watch_id = f"`${{__VIEW_ID__}}-watch-{self.processor.watch_counter}`"
|
|
194
191
|
else:
|
|
195
192
|
watch_id = "`${__VIEW_ID__}-watch-0`"
|
|
196
|
-
result = f"{concat_var} += this.
|
|
193
|
+
result = f"{concat_var} += this.__watch({watch_id}, {watch_keys}, () => {{\n{switch_logic}"
|
|
197
194
|
else:
|
|
198
195
|
# Parent uses template literal, so output template expression
|
|
199
196
|
if is_attribute_context or not watch_keys:
|
|
@@ -204,7 +201,7 @@ class ConditionalHandlers:
|
|
|
204
201
|
watch_id = f"`${{__VIEW_ID__}}-watch-{self.processor.watch_counter}`"
|
|
205
202
|
else:
|
|
206
203
|
watch_id = "`${__VIEW_ID__}-watch-0`"
|
|
207
|
-
result = f"${{this.
|
|
204
|
+
result = f"${{this.__watch({watch_id}, {watch_keys}, () => {{\n{switch_logic}"
|
|
208
205
|
|
|
209
206
|
output.append(result)
|
|
210
207
|
stack.append(('switch', len(output), watch_keys, is_attribute_context, parent_is_concat))
|
|
@@ -242,20 +239,13 @@ class ConditionalHandlers:
|
|
|
242
239
|
if stack and stack[-1][0] == 'switch':
|
|
243
240
|
switch_info = stack.pop()
|
|
244
241
|
parent_is_concat = switch_info[4] if len(switch_info) > 4 else False
|
|
245
|
-
has_watch = switch_info[2] if len(switch_info) > 2 else []
|
|
246
242
|
|
|
247
243
|
if parent_is_concat:
|
|
248
|
-
# Parent uses concatenation
|
|
249
|
-
|
|
250
|
-
result = "`;\n}\nreturn __switchOutputContent__;\n}, {type: 'watch'})"
|
|
251
|
-
else:
|
|
252
|
-
result = "`;\n}\nreturn __switchOutputContent__;\n})"
|
|
244
|
+
# Parent uses concatenation, close with })
|
|
245
|
+
result = "`;\n}\nreturn __switchOutputContent__;\n})"
|
|
253
246
|
else:
|
|
254
|
-
# Parent uses template literal
|
|
255
|
-
|
|
256
|
-
result = "`;\n}\nreturn __switchOutputContent__;\n}, {type: 'watch'}})"
|
|
257
|
-
else:
|
|
258
|
-
result = "`;\n}\nreturn __switchOutputContent__;\n})}"
|
|
247
|
+
# Parent uses template literal, output template expression
|
|
248
|
+
result = "`;\n}\nreturn __switchOutputContent__;\n})}"
|
|
259
249
|
|
|
260
250
|
output.append(result)
|
|
261
251
|
return True
|
|
@@ -111,22 +111,6 @@ class DeclarationTracker:
|
|
|
111
111
|
"""Parse @vars content and extract variables"""
|
|
112
112
|
variables = []
|
|
113
113
|
|
|
114
|
-
# Handle array syntax: ['var1', 'var2'] or ["var1", "var2"]
|
|
115
|
-
if content.startswith('[') and content.endswith(']'):
|
|
116
|
-
# Extract array items
|
|
117
|
-
inner = content[1:-1].strip()
|
|
118
|
-
# Parse quoted strings
|
|
119
|
-
import re
|
|
120
|
-
# Find all quoted strings (single or double quotes)
|
|
121
|
-
matches = re.findall(r'''['"](.*?)['"]''', inner)
|
|
122
|
-
for var_name in matches:
|
|
123
|
-
variables.append({
|
|
124
|
-
'name': var_name.strip(),
|
|
125
|
-
'value': None,
|
|
126
|
-
'hasDefault': False
|
|
127
|
-
})
|
|
128
|
-
return variables
|
|
129
|
-
|
|
130
114
|
# Handle object destructuring {var1, var2}
|
|
131
115
|
if content.startswith('{') and content.endswith('}'):
|
|
132
116
|
inner = content[1:-1]
|
|
@@ -298,12 +298,10 @@ class DirectiveProcessor:
|
|
|
298
298
|
|
|
299
299
|
# Build the output
|
|
300
300
|
if vars_set:
|
|
301
|
-
# Has variables - use
|
|
301
|
+
# Has variables - use __output with subscription
|
|
302
302
|
subscribe = ','.join([f"'{v}'" for v in vars_set])
|
|
303
303
|
subscribe_js = f'[{subscribe}]'
|
|
304
|
-
|
|
305
|
-
reactive_id = f'`${{__VIEW_ID__}}-json-{len(vars_set)}`'
|
|
306
|
-
return '${' + f"this.__reactive({reactive_id}, {subscribe_js}, (__rc__) => JSON.stringify({js_expr}), {{type: 'output', escapeHTML: false}})" + '}'
|
|
304
|
+
return '${' + f"this.__output({subscribe_js}, () => JSON.stringify({js_expr}))" + '}'
|
|
307
305
|
else:
|
|
308
306
|
# No variables - direct JSON.stringify
|
|
309
307
|
return '${' + f"JSON.stringify({js_expr})" + '}'
|
|
@@ -453,11 +451,9 @@ class DirectiveProcessor:
|
|
|
453
451
|
else:
|
|
454
452
|
subscribe_js = '[]'
|
|
455
453
|
|
|
456
|
-
#
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
# Produce string like: ${this.__reactive(id, ['a','b'], (__rc__) => (expr), {type: 'output', escapeHTML: false})}
|
|
460
|
-
return '${' + "this.__reactive(" + reactive_id + ", " + subscribe_js + ", (__rc__) => (" + js_expr + "), {type: 'output', escapeHTML: false})" + '}'
|
|
454
|
+
# Return the output wrapper using this.__output
|
|
455
|
+
# Produce string like: ${this.__output(['a','b'], () => (expr))}
|
|
456
|
+
return '${' + "this.__output(" + subscribe_js + ", () => (" + js_expr + "))}"
|
|
461
457
|
|
|
462
458
|
def process_register_directive(self, line, stack, output):
|
|
463
459
|
"""Process @register directive - chį» Äį» ÄĆ”nh dįŗ„u, khĆ“ng tįŗ”o output"""
|
|
@@ -61,18 +61,18 @@ class LoopHandlers:
|
|
|
61
61
|
# Use this.__foreach for instance method
|
|
62
62
|
foreach_call = f"this.__foreach({array_expr}, {callback}"
|
|
63
63
|
|
|
64
|
-
# Only wrap with
|
|
64
|
+
# Only wrap with __watch for block-level directives (not attributes)
|
|
65
65
|
if is_attribute_context:
|
|
66
|
-
# Attribute directive - no
|
|
66
|
+
# Attribute directive - no watch wrapping
|
|
67
67
|
result = f"${{{foreach_call}"
|
|
68
68
|
else:
|
|
69
|
-
# Block directive - wrap with
|
|
69
|
+
# Block directive - wrap with __watch
|
|
70
70
|
if self.processor:
|
|
71
71
|
self.processor.watch_counter += 1
|
|
72
72
|
watch_id = f"`${{__VIEW_ID__}}-watch-{self.processor.watch_counter}`"
|
|
73
73
|
else:
|
|
74
74
|
watch_id = "`${__VIEW_ID__}-watch-0`"
|
|
75
|
-
result = f"${{this.
|
|
75
|
+
result = f"${{this.__watch({watch_id}, {watch_keys}, () => {foreach_call}"
|
|
76
76
|
|
|
77
77
|
output.append(result)
|
|
78
78
|
stack.append(('foreach', len(output), is_attribute_context))
|
|
@@ -85,11 +85,11 @@ class LoopHandlers:
|
|
|
85
85
|
is_attribute = stack[-1][2] if len(stack[-1]) > 2 else False
|
|
86
86
|
stack.pop()
|
|
87
87
|
if is_attribute:
|
|
88
|
-
# Attribute directive - no
|
|
88
|
+
# Attribute directive - no watch wrapper
|
|
89
89
|
output.append('`)}')
|
|
90
90
|
else:
|
|
91
|
-
# Block directive - close
|
|
92
|
-
output.append(
|
|
91
|
+
# Block directive - close watch wrapper
|
|
92
|
+
output.append('`))}')
|
|
93
93
|
return True
|
|
94
94
|
|
|
95
95
|
def process_for_directive(self, line, stack, output, is_attribute_context=False):
|
|
@@ -124,7 +124,7 @@ class LoopHandlers:
|
|
|
124
124
|
# Wrap in __for() with __loop parameter
|
|
125
125
|
for_call = f"this.__for('increment', {start_value}, {end_value}, (__loop) => {{\n{for_logic}"
|
|
126
126
|
|
|
127
|
-
# Only wrap with
|
|
127
|
+
# Only wrap with __watch for block-level directives (not attributes)
|
|
128
128
|
has_watch = not is_attribute_context and watch_keys
|
|
129
129
|
if is_attribute_context or not watch_keys:
|
|
130
130
|
result = f"${{{for_call}"
|
|
@@ -134,7 +134,7 @@ class LoopHandlers:
|
|
|
134
134
|
watch_id = f"`${{__VIEW_ID__}}-watch-{self.processor.watch_counter}`"
|
|
135
135
|
else:
|
|
136
136
|
watch_id = "`${__VIEW_ID__}-watch-0`"
|
|
137
|
-
result = f"${{this.
|
|
137
|
+
result = f"${{this.__watch({watch_id}, {watch_keys}, () => {{ return {for_call}"
|
|
138
138
|
|
|
139
139
|
output.append(result)
|
|
140
140
|
stack.append(('for', len(output), is_attribute_context, has_watch))
|
|
@@ -152,14 +152,16 @@ class LoopHandlers:
|
|
|
152
152
|
# Attribute directive - close __for
|
|
153
153
|
result = "\n}\nreturn __forOutputContent__;\n})\n}"
|
|
154
154
|
elif has_watch:
|
|
155
|
-
# Block directive with
|
|
155
|
+
# Block directive with watch - close __for, watch callback, and watch wrapper
|
|
156
156
|
# Pattern:
|
|
157
157
|
# } closes for loop body
|
|
158
158
|
# return __forOutputContent__;
|
|
159
159
|
# }) closes for arrow body and params
|
|
160
|
-
#
|
|
160
|
+
# ); closes __for call and ends return statement
|
|
161
|
+
# } closes watch callback arrow body
|
|
162
|
+
# ) closes __watch call
|
|
161
163
|
# } closes ${}
|
|
162
|
-
result = "\n}\nreturn __forOutputContent__;\n})\n}
|
|
164
|
+
result = "\n}\nreturn __forOutputContent__;\n})\n})}}"
|
|
163
165
|
else:
|
|
164
166
|
# Block directive without watch - close __for only
|
|
165
167
|
result = "\n}\nreturn __forOutputContent__;\n})\n}"
|
|
@@ -189,7 +191,7 @@ class LoopHandlers:
|
|
|
189
191
|
# Generate while loop
|
|
190
192
|
while_logic = f"let __whileOutputContent__ = ``;\nwhile({condition}) {{"
|
|
191
193
|
|
|
192
|
-
# Only wrap with
|
|
194
|
+
# Only wrap with __watch for block-level directives (not attributes)
|
|
193
195
|
if is_attribute_context or not watch_keys:
|
|
194
196
|
result = f"${{this.__execute(() => {{\n{while_logic}"
|
|
195
197
|
else:
|
|
@@ -198,7 +200,7 @@ class LoopHandlers:
|
|
|
198
200
|
watch_id = f"`${{__VIEW_ID__}}-watch-{self.processor.watch_counter}`"
|
|
199
201
|
else:
|
|
200
202
|
watch_id = "`${__VIEW_ID__}-watch-0`"
|
|
201
|
-
result = f"${{this.
|
|
203
|
+
result = f"${{this.__watch({watch_id}, {watch_keys}, () => {{\n{while_logic}"
|
|
202
204
|
|
|
203
205
|
output.append(result)
|
|
204
206
|
stack.append(('while', len(output), is_attribute_context))
|
|
@@ -215,8 +217,8 @@ class LoopHandlers:
|
|
|
215
217
|
# Attribute directive - close IIFE only
|
|
216
218
|
result = "\n}\nreturn __whileOutputContent__;\n})}"
|
|
217
219
|
else:
|
|
218
|
-
# Block directive - close
|
|
219
|
-
result = "\n}\nreturn __whileOutputContent__;\n}
|
|
220
|
+
# Block directive - close watch wrapper
|
|
221
|
+
result = "\n}\nreturn __whileOutputContent__;\n})}"
|
|
220
222
|
|
|
221
223
|
output.append(result)
|
|
222
224
|
return True
|
|
@@ -141,17 +141,13 @@ class BladeCompiler:
|
|
|
141
141
|
# Extract usestate_variables for event processor
|
|
142
142
|
usestate_variables = self._extract_usestate_variables(usestate_declarations, all_declarations)
|
|
143
143
|
|
|
144
|
-
#
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
self.template_processor.state_variables =
|
|
150
|
-
self.template_processor.
|
|
151
|
-
self.template_processor.loop_handlers.state_variables = reactive_variables
|
|
152
|
-
self.template_processor.event_processor.state_variables = reactive_variables
|
|
153
|
-
self.template_processor.echo_processor.state_variables = reactive_variables
|
|
154
|
-
self.template_processor.class_binding_handler.state_variables = reactive_variables
|
|
144
|
+
# Update template_processor with usestate_variables (don't reinitialize to preserve watch_counter)
|
|
145
|
+
self.template_processor.state_variables = usestate_variables
|
|
146
|
+
self.template_processor.conditional_handlers.state_variables = usestate_variables
|
|
147
|
+
self.template_processor.loop_handlers.state_variables = usestate_variables
|
|
148
|
+
self.template_processor.event_processor.state_variables = usestate_variables
|
|
149
|
+
self.template_processor.echo_processor.state_variables = usestate_variables
|
|
150
|
+
self.template_processor.class_binding_handler.state_variables = usestate_variables
|
|
155
151
|
|
|
156
152
|
# Parse block directives
|
|
157
153
|
blade_code = self.parsers.parse_block_directives(blade_code)
|
|
@@ -539,9 +535,9 @@ class BladeCompiler:
|
|
|
539
535
|
# Process binding directives (@val and @bind)
|
|
540
536
|
template_content = self.binding_directive_service.process_all_binding_directives(template_content)
|
|
541
537
|
|
|
542
|
-
# Update style and show handlers with
|
|
543
|
-
self.style_directive_handler.state_variables =
|
|
544
|
-
self.show_directive_handler.state_variables =
|
|
538
|
+
# Update style and show handlers with state variables
|
|
539
|
+
self.style_directive_handler.state_variables = usestate_variables
|
|
540
|
+
self.show_directive_handler.state_variables = usestate_variables
|
|
545
541
|
|
|
546
542
|
# Process @style directive
|
|
547
543
|
template_content = self.style_directive_handler.process_style_directive(template_content)
|
|
@@ -1176,54 +1172,6 @@ class BladeCompiler:
|
|
|
1176
1172
|
|
|
1177
1173
|
return usestate_variables
|
|
1178
1174
|
|
|
1179
|
-
def _extract_reactive_variables(self, all_declarations, variable_list):
|
|
1180
|
-
"""
|
|
1181
|
-
Extract ALL reactive variable names (data variables + useState + let + const)
|
|
1182
|
-
In OneJS, all these are reactive in templates:
|
|
1183
|
-
- Data variables from @vars (passed as props/data)
|
|
1184
|
-
- useState variables
|
|
1185
|
-
- let/const variables
|
|
1186
|
-
|
|
1187
|
-
Returns a set of variable names that should trigger reactive updates
|
|
1188
|
-
"""
|
|
1189
|
-
reactive_variables = set()
|
|
1190
|
-
|
|
1191
|
-
# 1. Add data variables from @vars (variable_list)
|
|
1192
|
-
if variable_list:
|
|
1193
|
-
reactive_variables.update(variable_list)
|
|
1194
|
-
|
|
1195
|
-
# 2. Add useState variables (state + setters)
|
|
1196
|
-
for decl in all_declarations:
|
|
1197
|
-
if decl.get('type') == 'useState':
|
|
1198
|
-
variables = decl.get('variables', [])
|
|
1199
|
-
for var in variables:
|
|
1200
|
-
if var.get('isUseState'):
|
|
1201
|
-
names = var.get('names', [])
|
|
1202
|
-
if names and len(names) > 0:
|
|
1203
|
-
# First name is the state variable
|
|
1204
|
-
state_var = names[0]
|
|
1205
|
-
if state_var:
|
|
1206
|
-
reactive_variables.add(state_var)
|
|
1207
|
-
# Second name is the setter
|
|
1208
|
-
if len(names) > 1:
|
|
1209
|
-
setter_var = names[1]
|
|
1210
|
-
if setter_var:
|
|
1211
|
-
reactive_variables.add(setter_var)
|
|
1212
|
-
|
|
1213
|
-
# 3. Add let/const variables
|
|
1214
|
-
for decl in all_declarations:
|
|
1215
|
-
if decl.get('type') in ['let', 'const']:
|
|
1216
|
-
variables = decl.get('variables', [])
|
|
1217
|
-
for var in variables:
|
|
1218
|
-
names = var.get('names', [])
|
|
1219
|
-
if names and len(names) > 0:
|
|
1220
|
-
# For simple declaration, first name is the variable
|
|
1221
|
-
var_name = names[0]
|
|
1222
|
-
if var_name:
|
|
1223
|
-
reactive_variables.add(var_name)
|
|
1224
|
-
|
|
1225
|
-
return reactive_variables
|
|
1226
|
-
|
|
1227
1175
|
def _detect_state_keys(self, blade_code, let_declarations, const_declarations, usestate_declarations):
|
|
1228
1176
|
"""Detect state keys from directives that use useState or destructuring"""
|
|
1229
1177
|
state_keys = set()
|
|
@@ -1031,11 +1031,11 @@ class TemplateProcessor:
|
|
|
1031
1031
|
|
|
1032
1032
|
include_call = APP_VIEW_NAMESPACE + ".renderView(this.__include('" + view_name + "', " + variables_js + "))"
|
|
1033
1033
|
|
|
1034
|
-
# If state variables are used, wrap with
|
|
1034
|
+
# If state variables are used, wrap with __watch
|
|
1035
1035
|
# Use placeholder for watch ID that will be replaced later with actual counter
|
|
1036
1036
|
if state_vars_used:
|
|
1037
1037
|
watch_keys = list(state_vars_used)
|
|
1038
|
-
return "${this.
|
|
1038
|
+
return "${this.__watch('__INCLUDE_WATCH_PLACEHOLDER__', " + str(watch_keys) + ", () => " + include_call + ")}"
|
|
1039
1039
|
|
|
1040
1040
|
return "${" + include_call + "}"
|
|
1041
1041
|
|
|
@@ -1072,11 +1072,11 @@ class TemplateProcessor:
|
|
|
1072
1072
|
|
|
1073
1073
|
include_call = APP_VIEW_NAMESPACE + ".renderView(this.__include(" + view_expr_js + ", " + variables_js + "))"
|
|
1074
1074
|
|
|
1075
|
-
# If state variables are used, wrap with
|
|
1075
|
+
# If state variables are used, wrap with __watch
|
|
1076
1076
|
# Use placeholder for watch ID that will be replaced later with actual counter
|
|
1077
1077
|
if state_vars_used:
|
|
1078
1078
|
watch_keys = list(state_vars_used)
|
|
1079
|
-
return "${this.
|
|
1079
|
+
return "${this.__watch('__INCLUDE_WATCH_PLACEHOLDER__', " + str(watch_keys) + ", () => " + include_call + ")}"
|
|
1080
1080
|
|
|
1081
1081
|
return "${" + include_call + "}"
|
|
1082
1082
|
|
package/src/core/ViewManager.js
CHANGED
|
@@ -398,40 +398,40 @@ export class ViewManager {
|
|
|
398
398
|
/**
|
|
399
399
|
* @type {ViewEngine}
|
|
400
400
|
*/
|
|
401
|
-
const cachedPageView = this.store.get(viewStoreKey);
|
|
402
|
-
if (cachedPageView && cachedPageView instanceof ViewEngine) {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
}
|
|
401
|
+
// const cachedPageView = this.store.get(viewStoreKey);
|
|
402
|
+
// if (cachedPageView && cachedPageView instanceof ViewEngine) {
|
|
403
|
+
// // SỠdỄng lẔi cached page view
|
|
404
|
+
// let html = cachedPageView.__._templateManager.renderedHtml || '';
|
|
405
|
+
// this.PAGE_VIEW = cachedPageView;
|
|
406
|
+
// let ultraView = cachedPageView;
|
|
407
|
+
// /**
|
|
408
|
+
// * @type {ViewEngine}
|
|
409
|
+
// */
|
|
410
|
+
// let superView = null;
|
|
411
|
+
|
|
412
|
+
// if (cachedPageView.superView && cachedPageView.superView instanceof ViewEngine) {
|
|
413
|
+
// superView = cachedPageView.superView;
|
|
414
|
+
// ultraView = superView;
|
|
415
|
+
// superView.__.setOriginalView(cachedPageView);
|
|
416
|
+
// this.CURRENT_SUPER_VIEW_MOUNTED = true;
|
|
417
|
+
// this.CURRENT_SUPER_VIEW = cachedPageView.superView;
|
|
418
|
+
// this.CURRENT_SUPER_VIEW_PATH = cachedPageView.superView.path;
|
|
419
|
+
// cachedPageView.__._templateManager.pushCachedSections();
|
|
420
|
+
// html = lastSuperViewPath === this.CURRENT_SUPER_VIEW_PATH ? superView.__._templateManager.renderedHtml : this.renderView(superView);
|
|
421
|
+
// }
|
|
422
|
+
// logger.log(`š App.View.loadView: Using cached view for '${name}' with URL path '${urlPath}'`);
|
|
423
|
+
// // trįŗ£ vį» kįŗæt quįŗ£
|
|
424
|
+
// return {
|
|
425
|
+
// html: html,
|
|
426
|
+
// isSuperView: superView ? true : false,
|
|
427
|
+
// needInsert: superView && (lastSuperViewPath === superView.path) ? false : true,
|
|
428
|
+
// superView: superView,
|
|
429
|
+
// ultraView: ultraView,
|
|
430
|
+
// error: null,
|
|
431
|
+
// isCached: true
|
|
432
|
+
// };
|
|
433
|
+
|
|
434
|
+
// }
|
|
435
435
|
|
|
436
436
|
let hasCache = false;
|
|
437
437
|
if (this.cachedTimes > 0) {
|
|
@@ -468,13 +468,13 @@ export class ViewManager {
|
|
|
468
468
|
}
|
|
469
469
|
|
|
470
470
|
// Lʰu view vĆ o store Äį» quįŗ£n lý vòng Äį»i (ttl mįŗ·c Äį»nh 30 phĆŗt)
|
|
471
|
-
this.store.set(viewStoreKey, view, this.storeTTL); // lưu view và o store
|
|
472
|
-
this.store.onExpire(viewStoreKey, (viewStore) => {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
});
|
|
477
|
-
logger.log(`š App.View.loadView: Using new instance view for '${name}' with URL path '${urlPath}'`);
|
|
471
|
+
// this.store.set(viewStoreKey, view, this.storeTTL); // lưu view và o store
|
|
472
|
+
// this.store.onExpire(viewStoreKey, (viewStore) => {
|
|
473
|
+
// if (viewStore && viewStore instanceof ViewEngine && viewStore != this.PAGE_VIEW) {
|
|
474
|
+
// viewStore.__._lifecycleManager.destroy();
|
|
475
|
+
// }
|
|
476
|
+
// });
|
|
477
|
+
// logger.log(`š App.View.loadView: Using new instance view for '${name}' with URL path '${urlPath}'`);
|
|
478
478
|
// Store view in array for tracking
|
|
479
479
|
this.PAGE_VIEW = view;
|
|
480
480
|
let superView = null;
|
|
@@ -602,12 +602,12 @@ export class ViewManager {
|
|
|
602
602
|
const oldSuperView = this.CURRENT_SUPER_VIEW;
|
|
603
603
|
const oldPageView = this.PAGE_VIEW;
|
|
604
604
|
if (oldSuperView && oldSuperView instanceof ViewEngine) {
|
|
605
|
-
oldSuperView.__._templateManager.updateHtmlCache();
|
|
605
|
+
// oldSuperView.__._templateManager.updateHtmlCache();
|
|
606
606
|
oldSuperView.__._lifecycleManager.unmounted();
|
|
607
607
|
}
|
|
608
608
|
if( oldPageView && oldPageView instanceof ViewEngine && oldPageView != oldSuperView){
|
|
609
|
-
oldPageView.__._templateManager.updateHtmlCache();
|
|
610
|
-
oldPageView.__._lifecycleManager.
|
|
609
|
+
// oldPageView.__._templateManager.updateHtmlCache();
|
|
610
|
+
oldPageView.__._lifecycleManager.destroy();
|
|
611
611
|
}
|
|
612
612
|
|
|
613
613
|
|
|
@@ -636,7 +636,7 @@ export class ViewManager {
|
|
|
636
636
|
oldSuperView.__.removeStyles();
|
|
637
637
|
oldSuperView.__._templateManager.updateHtmlCache();
|
|
638
638
|
}
|
|
639
|
-
oldPageView?.__.removeStyles();
|
|
639
|
+
// oldPageView?.__.removeStyles();
|
|
640
640
|
|
|
641
641
|
|
|
642
642
|
// ============================================================
|
|
@@ -655,21 +655,21 @@ export class ViewManager {
|
|
|
655
655
|
this.emitChangedSections();
|
|
656
656
|
}
|
|
657
657
|
|
|
658
|
-
if (newPageView && newPageView instanceof ViewEngine) {
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
}
|
|
666
|
-
if (newSuperView && newSuperView instanceof ViewEngine) {
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
}
|
|
658
|
+
// if (newPageView && newPageView instanceof ViewEngine) {
|
|
659
|
+
// newPageView.__.insertStyles();
|
|
660
|
+
// if( isCached && newPageView.__._templateManager.isCached ){
|
|
661
|
+
// newPageView.__._templateManager.pushCachedSections();
|
|
662
|
+
// // Re-scan and remount when loading from cache
|
|
663
|
+
// newPageView.__._renderEngine.rescanAfterCache();
|
|
664
|
+
// }
|
|
665
|
+
// }
|
|
666
|
+
// if (newSuperView && newSuperView instanceof ViewEngine) {
|
|
667
|
+
// newSuperView.__.insertStyles();
|
|
668
|
+
// if( isCached && newSuperView.__._templateManager.isCached ){
|
|
669
|
+
// // Re-scan and remount superView when loading from cache
|
|
670
|
+
// newSuperView.__._renderEngine.rescanAfterCache();
|
|
671
|
+
// }
|
|
672
|
+
// }
|
|
673
673
|
|
|
674
674
|
|
|
675
675
|
if (viewResult.ultraView && viewResult.ultraView instanceof ViewEngine) {
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Test compiler with real todo template
|
|
3
|
-
"""
|
|
4
|
-
import sys
|
|
5
|
-
from main_compiler import BladeCompiler
|
|
6
|
-
|
|
7
|
-
# Test template
|
|
8
|
-
template = """
|
|
9
|
-
@vars(['todos'])
|
|
10
|
-
|
|
11
|
-
<div>
|
|
12
|
-
<h3>Todo List</h3>
|
|
13
|
-
<ul class="todo-list">
|
|
14
|
-
@foreach ($todos as $todo)
|
|
15
|
-
<li class="todo-item {{ $todo['completed'] ? 'completed' : '' }}">
|
|
16
|
-
<input type="checkbox" @change(toggleTodo($todo['id'])) @checked($todo['completed'])>
|
|
17
|
-
{{ $todo['text'] }}
|
|
18
|
-
<button class="btn btn-sm btn-outline-danger" @click(deleteTodo($todo['id']))>Ć</button>
|
|
19
|
-
</li>
|
|
20
|
-
@endforeach
|
|
21
|
-
</ul>
|
|
22
|
-
</div>
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
# Compile
|
|
26
|
-
compiler = BladeCompiler()
|
|
27
|
-
result = compiler.compile_blade_to_js(template, 'test-todo')
|
|
28
|
-
|
|
29
|
-
# Debug: Check variable_list
|
|
30
|
-
import re as regex_module
|
|
31
|
-
vars_match = regex_module.search(r"const __VARIABLE_LIST__ = \[(.*?)\]", result)
|
|
32
|
-
if vars_match:
|
|
33
|
-
print("\nš DEBUG: __VARIABLE_LIST__ =", vars_match.group(1))
|
|
34
|
-
|
|
35
|
-
print("=" * 80)
|
|
36
|
-
print("INPUT:")
|
|
37
|
-
print(template)
|
|
38
|
-
print("\n" + "=" * 80)
|
|
39
|
-
print("OUTPUT:")
|
|
40
|
-
print(result)
|
|
41
|
-
print("=" * 80)
|
|
42
|
-
|
|
43
|
-
# Check specific patterns
|
|
44
|
-
output = result
|
|
45
|
-
|
|
46
|
-
# Check __reactive with type: 'watch'
|
|
47
|
-
if "__reactive(" in output and "{type: 'watch'}" in output:
|
|
48
|
-
print("ā
__reactive with type: 'watch' found")
|
|
49
|
-
else:
|
|
50
|
-
print("ā Missing __reactive with type: 'watch'")
|
|
51
|
-
|
|
52
|
-
# Check __foreach is inside __reactive
|
|
53
|
-
if "__reactive(" in output and "__foreach(" in output:
|
|
54
|
-
reactive_pos = output.find("__reactive(")
|
|
55
|
-
foreach_pos = output.find("__foreach(")
|
|
56
|
-
if reactive_pos < foreach_pos:
|
|
57
|
-
print("ā
__foreach is wrapped by __reactive")
|
|
58
|
-
else:
|
|
59
|
-
print("ā __foreach is NOT wrapped by __reactive")
|
|
60
|
-
|
|
61
|
-
# Check event directives
|
|
62
|
-
if "__addEventConfig" in output:
|
|
63
|
-
print("ā
Event directives compiled")
|
|
64
|
-
else:
|
|
65
|
-
print("ā Event directives missing")
|
|
66
|
-
|
|
67
|
-
# Check class binding in attribute
|
|
68
|
-
if "todo['completed'] ? 'completed' : ''" in output:
|
|
69
|
-
print("ā
Class expression compiled")
|
|
70
|
-
else:
|
|
71
|
-
print("ā Class expression missing")
|
|
72
|
-
|
|
73
|
-
# Check @checked directive
|
|
74
|
-
if "checked" in output:
|
|
75
|
-
print("ā
@checked directive compiled")
|
|
76
|
-
else:
|
|
77
|
-
print("ā @checked directive missing")
|
|
78
|
-
|
|
79
|
-
# Check text interpolation
|
|
80
|
-
if "todo['text']" in output:
|
|
81
|
-
print("ā
Text interpolation compiled")
|
|
82
|
-
else:
|
|
83
|
-
print("ā Text interpolation missing")
|