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.
Files changed (121) hide show
  1. package/README.md +1 -1
  2. package/bin/onejs-build.js +32 -0
  3. package/index.js +3 -1
  4. package/package.json +11 -3
  5. package/scripts/README-template-compiler.md +133 -0
  6. package/scripts/README.md +61 -0
  7. package/scripts/__pycache__/build.cpython-314.pyc +0 -0
  8. package/scripts/__pycache__/compile.cpython-313.pyc +0 -0
  9. package/scripts/__pycache__/compile.cpython-314.pyc +0 -0
  10. package/scripts/build.py +574 -0
  11. package/scripts/check-system-errors.php +214 -0
  12. package/scripts/compile.py +101 -0
  13. package/scripts/compiler/README_CONFIG.md +196 -0
  14. package/scripts/compiler/__init__.py +18 -0
  15. package/scripts/compiler/__pycache__/__init__.cpython-313.pyc +0 -0
  16. package/scripts/compiler/__pycache__/__init__.cpython-314.pyc +0 -0
  17. package/scripts/compiler/__pycache__/binding_directive_service.cpython-314.pyc +0 -0
  18. package/scripts/compiler/__pycache__/class_binding_handler.cpython-314.pyc +0 -0
  19. package/scripts/compiler/__pycache__/compiler_utils.cpython-313.pyc +0 -0
  20. package/scripts/compiler/__pycache__/compiler_utils.cpython-314.pyc +0 -0
  21. package/scripts/compiler/__pycache__/conditional_handlers.cpython-313.pyc +0 -0
  22. package/scripts/compiler/__pycache__/conditional_handlers.cpython-314.pyc +0 -0
  23. package/scripts/compiler/__pycache__/config.cpython-313.pyc +0 -0
  24. package/scripts/compiler/__pycache__/config.cpython-314.pyc +0 -0
  25. package/scripts/compiler/__pycache__/declaration_tracker.cpython-314.pyc +0 -0
  26. package/scripts/compiler/__pycache__/directive_processors.cpython-313.pyc +0 -0
  27. package/scripts/compiler/__pycache__/directive_processors.cpython-314.pyc +0 -0
  28. package/scripts/compiler/__pycache__/echo_processor.cpython-314.pyc +0 -0
  29. package/scripts/compiler/__pycache__/event_directive_processor.cpython-313.pyc +0 -0
  30. package/scripts/compiler/__pycache__/event_directive_processor.cpython-314.pyc +0 -0
  31. package/scripts/compiler/__pycache__/function_generators.cpython-313.pyc +0 -0
  32. package/scripts/compiler/__pycache__/function_generators.cpython-314.pyc +0 -0
  33. package/scripts/compiler/__pycache__/loop_handlers.cpython-313.pyc +0 -0
  34. package/scripts/compiler/__pycache__/loop_handlers.cpython-314.pyc +0 -0
  35. package/scripts/compiler/__pycache__/main_compiler.cpython-313.pyc +0 -0
  36. package/scripts/compiler/__pycache__/main_compiler.cpython-314.pyc +0 -0
  37. package/scripts/compiler/__pycache__/parsers.cpython-313.pyc +0 -0
  38. package/scripts/compiler/__pycache__/parsers.cpython-314.pyc +0 -0
  39. package/scripts/compiler/__pycache__/php_converter.cpython-313.pyc +0 -0
  40. package/scripts/compiler/__pycache__/php_converter.cpython-314.pyc +0 -0
  41. package/scripts/compiler/__pycache__/php_js_converter.cpython-313.pyc +0 -0
  42. package/scripts/compiler/__pycache__/php_js_converter.cpython-314.pyc +0 -0
  43. package/scripts/compiler/__pycache__/register_parser.cpython-313.pyc +0 -0
  44. package/scripts/compiler/__pycache__/register_parser.cpython-314.pyc +0 -0
  45. package/scripts/compiler/__pycache__/section_handlers.cpython-313.pyc +0 -0
  46. package/scripts/compiler/__pycache__/section_handlers.cpython-314.pyc +0 -0
  47. package/scripts/compiler/__pycache__/show_directive_handler.cpython-314.pyc +0 -0
  48. package/scripts/compiler/__pycache__/style_directive_handler.cpython-314.pyc +0 -0
  49. package/scripts/compiler/__pycache__/template_analyzer.cpython-313.pyc +0 -0
  50. package/scripts/compiler/__pycache__/template_analyzer.cpython-314.pyc +0 -0
  51. package/scripts/compiler/__pycache__/template_processor.cpython-313.pyc +0 -0
  52. package/scripts/compiler/__pycache__/template_processor.cpython-314.pyc +0 -0
  53. package/scripts/compiler/__pycache__/template_processors.cpython-313.pyc +0 -0
  54. package/scripts/compiler/__pycache__/template_processors.cpython-314.pyc +0 -0
  55. package/scripts/compiler/__pycache__/utils.cpython-313.pyc +0 -0
  56. package/scripts/compiler/__pycache__/utils.cpython-314.pyc +0 -0
  57. package/scripts/compiler/__pycache__/wrapper_parser.cpython-313.pyc +0 -0
  58. package/scripts/compiler/__pycache__/wrapper_parser.cpython-314.pyc +0 -0
  59. package/scripts/compiler/binding_directive_service.py +103 -0
  60. package/scripts/compiler/class_binding_handler.py +347 -0
  61. package/scripts/compiler/cli.py +34 -0
  62. package/scripts/compiler/code_generator.py +141 -0
  63. package/scripts/compiler/compiler.config.json +36 -0
  64. package/scripts/compiler/compiler_utils.py +55 -0
  65. package/scripts/compiler/conditional_handlers.py +252 -0
  66. package/scripts/compiler/config.py +107 -0
  67. package/scripts/compiler/declaration_tracker.py +420 -0
  68. package/scripts/compiler/directive_processors.py +603 -0
  69. package/scripts/compiler/echo_processor.py +667 -0
  70. package/scripts/compiler/event_directive_processor.py +1099 -0
  71. package/scripts/compiler/fetch_parser.py +49 -0
  72. package/scripts/compiler/function_generators.py +310 -0
  73. package/scripts/compiler/loop_handlers.py +224 -0
  74. package/scripts/compiler/main_compiler.py +1763 -0
  75. package/scripts/compiler/parsers.py +1418 -0
  76. package/scripts/compiler/php_converter.py +470 -0
  77. package/scripts/compiler/php_js_converter.py +603 -0
  78. package/scripts/compiler/register_parser.py +480 -0
  79. package/scripts/compiler/section_handlers.py +122 -0
  80. package/scripts/compiler/show_directive_handler.py +85 -0
  81. package/scripts/compiler/style_directive_handler.py +169 -0
  82. package/scripts/compiler/template_analyzer.py +162 -0
  83. package/scripts/compiler/template_processor.py +1167 -0
  84. package/scripts/compiler/template_processors.py +1557 -0
  85. package/scripts/compiler/test_compiler.py +69 -0
  86. package/scripts/compiler/utils.py +54 -0
  87. package/scripts/compiler/variables_analyzer.py +135 -0
  88. package/scripts/compiler/view_identifier_generator.py +278 -0
  89. package/scripts/compiler/wrapper_parser.py +78 -0
  90. package/scripts/dev-context.js +311 -0
  91. package/scripts/dev.js +109 -0
  92. package/scripts/generate-assets-order.js +208 -0
  93. package/scripts/migrate-namespace.php +146 -0
  94. package/scripts/node/MIGRATION.md +190 -0
  95. package/scripts/node/README.md +269 -0
  96. package/scripts/node/build.js +208 -0
  97. package/scripts/node/compiler/compiler-utils.js +38 -0
  98. package/scripts/node/compiler/conditional-handlers.js +45 -0
  99. package/scripts/node/compiler/config.js +178 -0
  100. package/scripts/node/compiler/directive-processors.js +51 -0
  101. package/scripts/node/compiler/event-directive-processor.js +182 -0
  102. package/scripts/node/compiler/function-generators.js +239 -0
  103. package/scripts/node/compiler/loop-handlers.js +45 -0
  104. package/scripts/node/compiler/main-compiler.js +236 -0
  105. package/scripts/node/compiler/parsers.js +358 -0
  106. package/scripts/node/compiler/php-converter.js +227 -0
  107. package/scripts/node/compiler/register-parser.js +32 -0
  108. package/scripts/node/compiler/section-handlers.js +46 -0
  109. package/scripts/node/compiler/template-analyzer.js +50 -0
  110. package/scripts/node/compiler/template-processor.js +371 -0
  111. package/scripts/node/compiler/template-processors.js +219 -0
  112. package/scripts/node/compiler/utils.js +203 -0
  113. package/scripts/node/compiler/wrapper-parser.js +25 -0
  114. package/scripts/node/package.json +24 -0
  115. package/scripts/node/test-compiler.js +52 -0
  116. package/scripts/node-run.cjs +28 -0
  117. package/scripts/standardize-directories.php +92 -0
  118. package/src/core/ViewManager.js +4 -4
  119. package/templates/view.module.js +2 -0
  120. package/templates/view.tpl-raw.js +13 -0
  121. package/templates/wraper.js +71 -0
@@ -0,0 +1,169 @@
1
+ """
2
+ Style Directive Handler - Xử lý @style directive
3
+ Supports: dynamic inline styles với reactive binding
4
+ Uses __styleBinding() method for reactive style management
5
+ """
6
+
7
+ import re
8
+ from php_js_converter import php_to_js_advanced
9
+
10
+ class StyleDirectiveHandler:
11
+ def __init__(self, state_variables=None):
12
+ self.state_variables = state_variables or set()
13
+
14
+ def process_style_directive(self, content):
15
+ """
16
+ Process @style directive với format:
17
+ @style(['color' => $textColor, 'font-size' => $fontSize])
18
+ @style(['background-color' => $isActive ? '#green' : '#red'])
19
+
20
+ Output format: ${this.__styleBinding([...])}
21
+
22
+ Note: Supports multi-line directives within HTML tag attributes
23
+ """
24
+ result = content
25
+
26
+ # Process all @style directives globally (supports multi-line)
27
+ while True:
28
+ match = re.search(r'@style\s*\(', result)
29
+ if not match:
30
+ break
31
+
32
+ # Find matching closing parenthesis (can span multiple lines)
33
+ start_pos = match.end() - 1
34
+ paren_count = 0
35
+ i = start_pos
36
+
37
+ while i < len(result):
38
+ if result[i] == '(':
39
+ paren_count += 1
40
+ elif result[i] == ')':
41
+ paren_count -= 1
42
+ if paren_count == 0:
43
+ # Found complete directive
44
+ expression = result[start_pos + 1:i].strip()
45
+ replacement = self._generate_style_output(expression)
46
+ result = result[:match.start()] + replacement + result[i + 1:]
47
+ break
48
+ i += 1
49
+ else:
50
+ # No matching closing paren found - skip this one
51
+ break
52
+
53
+ return result
54
+
55
+ def _generate_style_output(self, expression):
56
+ """
57
+ Generate reactive style binding output
58
+
59
+ Input: ['color' => $textColor, 'font-size' => $fontSize]
60
+ Output: ${this.__styleBinding([['color', textColor], ['font-size', fontSize]])}
61
+ """
62
+ # Parse PHP array syntax
63
+ styles = self._parse_style_expression(expression)
64
+
65
+ if not styles:
66
+ return ''
67
+
68
+ # Extract state variables used
69
+ state_vars = self._extract_state_variables(styles)
70
+
71
+ # Build JavaScript array of [key, value] pairs
72
+ js_bindings = []
73
+ for prop, value in styles:
74
+ # Convert PHP expression to JS
75
+ js_value = php_to_js_advanced(value)
76
+ js_bindings.append(f"['{prop}', {js_value}]")
77
+
78
+ js_array = '[' + ', '.join(js_bindings) + ']'
79
+
80
+ # Generate reactive binding with state tracking
81
+ if state_vars:
82
+ watch_keys = list(state_vars)
83
+ return f"${{this.__styleBinding({watch_keys}, {js_array})}}"
84
+ else:
85
+ # No state vars, but still use binding for consistency
86
+ return f"${{this.__styleBinding([], {js_array})}}"
87
+
88
+ def _parse_style_expression(self, expression):
89
+ """
90
+ Parse PHP array expression into list of (property, value) tuples
91
+
92
+ Input: 'color' => $textColor, 'font-size' => $fontSize
93
+ Output: [('color', '$textColor'), ('font-size', '$fontSize')]
94
+ """
95
+ styles = []
96
+
97
+ # Remove outer brackets if present
98
+ expression = expression.strip()
99
+ if expression.startswith('[') and expression.endswith(']'):
100
+ expression = expression[1:-1].strip()
101
+
102
+ # Split by commas (but not inside quotes or parentheses)
103
+ parts = self._smart_split(expression, ',')
104
+
105
+ for part in parts:
106
+ part = part.strip()
107
+ if not part:
108
+ continue
109
+
110
+ # Split by =>
111
+ if '=>' in part:
112
+ key_value = part.split('=>', 1)
113
+ if len(key_value) == 2:
114
+ key = key_value[0].strip().strip('\'"')
115
+ value = key_value[1].strip()
116
+ styles.append((key, value))
117
+
118
+ return styles
119
+
120
+ def _smart_split(self, text, delimiter):
121
+ """
122
+ Split text by delimiter, but ignore delimiters inside quotes or parentheses
123
+ """
124
+ parts = []
125
+ current = []
126
+ depth = 0
127
+ in_quote = False
128
+ quote_char = None
129
+
130
+ for i, char in enumerate(text):
131
+ if char in ('"', "'") and (i == 0 or text[i-1] != '\\'):
132
+ if not in_quote:
133
+ in_quote = True
134
+ quote_char = char
135
+ elif char == quote_char:
136
+ in_quote = False
137
+ quote_char = None
138
+
139
+ if not in_quote:
140
+ if char in '([{':
141
+ depth += 1
142
+ elif char in ')]}':
143
+ depth -= 1
144
+ elif char == delimiter and depth == 0:
145
+ parts.append(''.join(current))
146
+ current = []
147
+ continue
148
+
149
+ current.append(char)
150
+
151
+ if current:
152
+ parts.append(''.join(current))
153
+
154
+ return parts
155
+
156
+ def _extract_state_variables(self, styles):
157
+ """
158
+ Extract state variable names from style values
159
+ """
160
+ state_vars = set()
161
+
162
+ for _, value in styles:
163
+ # Find all PHP variables ($varName)
164
+ var_matches = re.findall(r'\$([a-zA-Z_][a-zA-Z0-9_]*)', value)
165
+ for var_name in var_matches:
166
+ if var_name in self.state_variables:
167
+ state_vars.add(var_name)
168
+
169
+ return state_vars
@@ -0,0 +1,162 @@
1
+ """
2
+ Analyzer cho template content và sections
3
+ """
4
+
5
+ from config import JS_FUNCTION_PREFIX
6
+ import re
7
+
8
+ class TemplateAnalyzer:
9
+ def __init__(self):
10
+ pass
11
+
12
+ def analyze_sections_info(self, sections, vars_declaration, has_await, has_fetch):
13
+ """Analyze sections and return detailed information"""
14
+ sections_dict = {} # Use dict to avoid duplicates, key = section_name
15
+
16
+ if not sections:
17
+ return []
18
+
19
+ # Extract variable names from vars_declaration
20
+ var_names = []
21
+ if vars_declaration:
22
+ vars_match = re.search(r'let\s*\{\s*([^}]+)\s*\}', vars_declaration)
23
+ if vars_match:
24
+ vars_content = vars_match.group(1)
25
+ for var_part in vars_content.split(','):
26
+ var_name = var_part.split('=')[0].strip()
27
+ var_names.append(var_name)
28
+
29
+ for section in sections:
30
+ # Extract section name and content
31
+ # Support both App.View.section, this.__section, and this.__block
32
+ section_match = re.search(r'(?:App\.View\.section|this\.__section|this\.__block)\([\'"]([^\'"]+)[\'"]', section)
33
+ if not section_match:
34
+ continue
35
+
36
+ section_name = section_match.group(1)
37
+
38
+ # Determine section type
39
+ # Long sections contain template string (backtick)
40
+ # Short sections don't contain template string
41
+ if '`' in section:
42
+ # Contains template string -> long section
43
+ section_type = "long"
44
+ else:
45
+ # No template string -> short section
46
+ section_type = "short"
47
+
48
+ # Check if section uses variables from @vars
49
+ use_vars = False
50
+ if var_names:
51
+ for var_name in var_names:
52
+ # Check for various patterns that indicate variable usage in compiled JavaScript
53
+ patterns = [
54
+ f'${{{var_name}}}', # Template literal usage
55
+ f'${{{JS_FUNCTION_PREFIX}.escString({var_name})}}', # Escaped string
56
+ f'${{{JS_FUNCTION_PREFIX}.foreach({var_name}', # Foreach loop
57
+ f'${{{JS_FUNCTION_PREFIX}.foreach({var_name},', # Foreach loop with comma
58
+ f'${{{JS_FUNCTION_PREFIX}.foreach({var_name})', # Foreach loop with paren
59
+ f'{JS_FUNCTION_PREFIX}.foreach({var_name}', # Foreach loop without ${
60
+ f'{JS_FUNCTION_PREFIX}.foreach({var_name},', # Foreach loop with comma without ${
61
+ f'{JS_FUNCTION_PREFIX}.foreach({var_name})', # Foreach loop with paren without ${
62
+ f', {var_name})', # Function parameter
63
+ f'({var_name})', # Function call
64
+ f', {var_name}', # Array/object property
65
+ f' {var_name}', # Space before variable
66
+ f'{var_name}', # Direct variable usage
67
+ f'"{var_name}":', # Object property
68
+ f"'{var_name}':", # Object property with single quotes
69
+ f'{{"{var_name}":', # Object with variable
70
+ f"{{'{var_name}':", # Object with variable single quotes
71
+ ]
72
+
73
+ for pattern in patterns:
74
+ if pattern in section:
75
+ use_vars = True
76
+ break
77
+ if use_vars:
78
+ break
79
+
80
+ # Determine preloader
81
+ preloader = use_vars and (has_await or has_fetch)
82
+
83
+ # Only add or update if not exists, or if current has useVars=True and existing doesn't
84
+ if section_name not in sections_dict:
85
+ sections_dict[section_name] = {
86
+ "name": section_name,
87
+ "type": section_type,
88
+ "useVars": use_vars,
89
+ "preloader": preloader
90
+ }
91
+ else:
92
+ # Update if current section has useVars=True and existing doesn't
93
+ existing = sections_dict[section_name]
94
+ if use_vars and not existing['useVars']:
95
+ sections_dict[section_name] = {
96
+ "name": section_name,
97
+ "type": section_type,
98
+ "useVars": use_vars,
99
+ "preloader": preloader
100
+ }
101
+
102
+ # Convert dict back to list
103
+ return list(sections_dict.values())
104
+
105
+ def analyze_conditional_structures(self, template_content, vars_declaration, has_await, has_fetch):
106
+ """Analyze conditional structures outside sections that use vars and need async data"""
107
+ conditional_info = {
108
+ 'has_conditional_with_vars': False,
109
+ 'conditional_content': template_content
110
+ }
111
+
112
+ if not vars_declaration or not (has_await or has_fetch):
113
+ return conditional_info
114
+
115
+ # Extract variable names from vars_declaration
116
+ var_names = []
117
+ vars_match = re.search(r'let\s*\{\s*([^}]+)\s*\}', vars_declaration)
118
+ if vars_match:
119
+ vars_content = vars_match.group(1)
120
+ for var_part in vars_content.split(','):
121
+ var_name = var_part.split('=')[0].strip()
122
+ var_names.append(var_name)
123
+
124
+ if not var_names:
125
+ return conditional_info
126
+
127
+ # Check if template has conditional structures outside sections
128
+ # Look for @if, @elseif, @else, @endif, @switch, @case, @default, @endswitch
129
+ conditional_patterns = [
130
+ r'@if\s*\([^)]+\)',
131
+ r'@elseif\s*\([^)]+\)',
132
+ r'@else',
133
+ r'@endif',
134
+ r'@switch\s*\([^)]+\)',
135
+ r'@case\s*\([^)]+\)',
136
+ r'@default',
137
+ r'@endswitch'
138
+ ]
139
+
140
+ has_conditionals = any(re.search(pattern, template_content) for pattern in conditional_patterns)
141
+
142
+ if has_conditionals:
143
+ # Check if any conditional uses variables from @vars
144
+ for var_name in var_names:
145
+ patterns = [
146
+ f'\${{{var_name}}}',
147
+ f'\${{{JS_FUNCTION_PREFIX}.escString\({var_name}\)}}',
148
+ f'\${{{JS_FUNCTION_PREFIX}.foreach\({var_name}',
149
+ f', {var_name}\)',
150
+ f'\({var_name}\)',
151
+ f', {var_name}',
152
+ f' {var_name}',
153
+ ]
154
+
155
+ for pattern in patterns:
156
+ if re.search(pattern, template_content):
157
+ conditional_info['has_conditional_with_vars'] = True
158
+ break
159
+ if conditional_info['has_conditional_with_vars']:
160
+ break
161
+
162
+ return conditional_info