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,574 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Blade Template Builder
4
+ Usage: python3 build.py [context]
5
+ context: web, admin, or all (default: all)
6
+ Examples:
7
+ python3 build.py # Build all contexts
8
+ python3 build.py web # Build web context only
9
+ python3 build.py admin # Build admin context only
10
+ """
11
+
12
+ import os
13
+ import sys
14
+ import json
15
+ import shutil
16
+ import argparse
17
+ from pathlib import Path
18
+
19
+ # Import the compiler from the modular architecture
20
+ # Using the new modular compiler
21
+ try:
22
+ from compile import compile_blade_to_js
23
+ from compiler.config import CompilerConfig
24
+ config = CompilerConfig()
25
+ print("āœ“ Using modular Blade compiler")
26
+ except ImportError as e:
27
+ print(f"Error: compiler module not found: {e}")
28
+ print("Please ensure the compiler directory exists.")
29
+ sys.exit(1)
30
+
31
+ def convert_path_to_view_name(file_path, views_root_path):
32
+ """
33
+ Convert file path to view name format
34
+ Example: resources/views/web/abc.blade.php -> web.abc
35
+ """
36
+ # Get relative path from resources/views
37
+ relative_path = os.path.relpath(file_path, views_root_path)
38
+
39
+ # Remove .blade.php extension
40
+ if relative_path.endswith('.blade.php'):
41
+ relative_path = relative_path[:-10] # Remove .blade.php
42
+
43
+ # Replace path separators with dots
44
+ view_name = relative_path.replace(os.path.sep, '.').replace('/', '.')
45
+
46
+ return view_name
47
+
48
+ def scan_directory(root_path):
49
+ """
50
+ Recursively scan directory for .blade.php files
51
+ Returns list of blade file paths (excluding files starting with *)
52
+ """
53
+ blade_files = []
54
+
55
+ for root, dirs, files in os.walk(root_path):
56
+ for file in files:
57
+ if file.endswith('.blade.php'):
58
+ # Skip files starting with asterisk (special files)
59
+ # Files starting with underscore (_) will be compiled
60
+ if file.startswith('*'):
61
+ print(f"Skipping special file: {file}")
62
+ continue
63
+
64
+ file_path = os.path.join(root, file)
65
+ blade_files.append(file_path)
66
+
67
+ return blade_files
68
+
69
+ def compile_blade_file(file_path, root_path):
70
+ """
71
+ Compile a single blade file to JavaScript
72
+ """
73
+ try:
74
+ with open(file_path, 'r', encoding='utf-8') as f:
75
+ blade_content = f.read()
76
+
77
+ view_name = convert_path_to_view_name(file_path, root_path)
78
+ result = compile_blade_to_js(blade_content, view_name)
79
+ return result
80
+
81
+ except Exception as e:
82
+ print(f"Error compiling {file_path}: {str(e)}")
83
+ return None
84
+
85
+ def build_scope_file(scope, compiled_views, scopes_dir):
86
+ """
87
+ Build a single scope file with new object structure
88
+ """
89
+ # Create scopes directory if it doesn't exist
90
+ os.makedirs(scopes_dir, exist_ok=True)
91
+
92
+ # Build scope content
93
+ js_content = f"App.View.templates['{scope}'] = {{\n"
94
+
95
+ for view_name, view_function in compiled_views.items():
96
+ # view_function is now a complete function that returns an object
97
+ js_content += f" '{view_name}': {view_function},\n"
98
+
99
+ # Remove last comma and close the scope
100
+ if compiled_views:
101
+ js_content = js_content.rstrip(',\n') + '\n'
102
+
103
+ js_content += "};\n"
104
+
105
+ # Write to scope file (build location)
106
+ scope_file = config.get_build_scope_output_path(scope)
107
+ try:
108
+ with open(scope_file, 'w', encoding='utf-8') as f:
109
+ f.write(js_content)
110
+ print(f"Successfully built scope file: {scope_file}")
111
+ return True
112
+ except Exception as e:
113
+ print(f"Error writing to {scope_file}: {str(e)}")
114
+ return False
115
+
116
+ def build_individual_view_files(compiled_views, blade_files_data, context='all'):
117
+ """
118
+ Build individual view files for each compiled view
119
+ """
120
+ # Always use flat views directory (don't use context subdirectories)
121
+ views_dir = os.path.join(config.js_input_path, 'views')
122
+
123
+ # Clean views directory before building
124
+ if os.path.exists(views_dir):
125
+ shutil.rmtree(views_dir)
126
+ print(f"āœ“ Cleaned views directory: {views_dir}")
127
+
128
+ os.makedirs(views_dir, exist_ok=True)
129
+
130
+ created_files = []
131
+
132
+ for view_name, view_function in compiled_views.items():
133
+ # Convert view name to function name (e.g., web.home -> WebHome)
134
+ function_name = convert_view_name_to_function_name(view_name)
135
+
136
+ # Create individual view file
137
+ view_file_path = os.path.join(views_dir, f'{function_name}.js')
138
+
139
+ # Build file content
140
+ file_content = ""
141
+
142
+ # Check if view_function starts with setup script (import statements)
143
+ if view_function.strip().startswith('import '):
144
+ # Split setup script and function
145
+ lines = view_function.split('\n')
146
+ setup_lines = []
147
+ function_lines = []
148
+ in_function = False
149
+
150
+ for line in lines:
151
+ if line.strip().startswith('export function ') and not in_function:
152
+ in_function = True
153
+ # Keep the export function line as is
154
+ function_lines.append(line)
155
+ elif in_function:
156
+ function_lines.append(line)
157
+ else:
158
+ # Only add non-empty lines to setup
159
+ if line.strip():
160
+ setup_lines.append(line)
161
+
162
+ # Add setup script first (without export)
163
+ if setup_lines:
164
+ file_content += '\n'.join(setup_lines) + '\n\n'
165
+
166
+ # Add function (already has export)
167
+ function_content = '\n'.join(function_lines)
168
+ file_content += function_content
169
+ else:
170
+ # Handle files without setup script - use as is (already has export)
171
+ file_content += view_function
172
+
173
+ # Write file
174
+ try:
175
+ with open(view_file_path, 'w', encoding='utf-8') as f:
176
+ f.write(file_content)
177
+ created_files.append((view_name, function_name, view_file_path))
178
+ print(f"Created view file: {function_name}.js")
179
+ except Exception as e:
180
+ print(f"Error writing {view_file_path}: {str(e)}")
181
+ return False
182
+
183
+ return created_files
184
+
185
+ def convert_view_name_to_function_name(view_name):
186
+ """
187
+ Convert view name to function name
188
+ Example: web.home -> WebHome, admin.dashboard -> AdminDashboard, web.user-detail -> WebUserDetail, web.layouts-base_a1 -> WebLayoutsBaseA1
189
+ """
190
+ # Split by dot and process each part
191
+ parts = view_name.split('.')
192
+ function_parts = []
193
+
194
+ for part in parts:
195
+ # Remove both - and _ and capitalize after each removal
196
+ # First split by - and _, then capitalize each segment
197
+ segments = []
198
+ for separator in ['-', '_']:
199
+ if separator in part:
200
+ part = part.replace(separator, ' ')
201
+
202
+ # Split by space and capitalize each word
203
+ words = part.split()
204
+ for word in words:
205
+ if word:
206
+ segments.append(word.capitalize())
207
+
208
+ if segments:
209
+ function_parts.append(''.join(segments))
210
+
211
+ return ''.join(function_parts)
212
+
213
+
214
+
215
+ def build_view_template_importer(created_files, output_path, context='all'):
216
+ """
217
+ Build ViewTemplate.js that imports all individual view files
218
+ """
219
+ # Get registry output path from build.config.json if context is specified
220
+ build_config = load_build_config()
221
+
222
+ if build_config and context != 'all' and context in build_config['contexts']:
223
+ # Use context-specific registry file
224
+ output_path = os.path.join(config.project_root, build_config['contexts'][context]['output']['register'])
225
+
226
+ # Create output directory if it doesn't exist
227
+ os.makedirs(os.path.dirname(output_path), exist_ok=True)
228
+
229
+ # Build import statements
230
+ imports = []
231
+ template_assignments = []
232
+
233
+ for view_name, function_name, file_path in created_files:
234
+ # Extract actual function name from the compiled file
235
+ actual_function_name = function_name # Default to converted name
236
+ try:
237
+ with open(file_path, 'r', encoding='utf-8') as f:
238
+ first_line = f.readline()
239
+ # Extract function name from: export function _systemPageEnd(...
240
+ if 'export function ' in first_line:
241
+ start = first_line.index('export function ') + len('export function ')
242
+ end = first_line.index('(', start)
243
+ actual_function_name = first_line[start:end].strip()
244
+ except Exception as e:
245
+ print(f"Warning: Could not extract function name from {file_path}: {e}")
246
+
247
+ # Calculate relative path from output to view file
248
+ relative_path = os.path.relpath(file_path, os.path.dirname(output_path))
249
+ relative_path = relative_path.replace('\\', '/') # Normalize path separators
250
+
251
+ imports.append(f"import {{ {actual_function_name} }} from './{relative_path}';")
252
+ template_assignments.append(f" '{view_name}': {actual_function_name},")
253
+
254
+ # Build file content
255
+ file_content = "// Auto-generated ViewTemplate.js\n"
256
+ file_content += "// This file imports all view functions and assigns them to templates\n\n"
257
+
258
+ # Add imports
259
+ file_content += "\n".join(imports) + "\n\n"
260
+
261
+ # Add template assignment
262
+ file_content += "export const ViewTemplates = {\n"
263
+ file_content += "\n".join(template_assignments)
264
+ file_content += "\n};\n"
265
+
266
+ # Write file
267
+ try:
268
+ with open(output_path, 'w', encoding='utf-8') as f:
269
+ f.write(file_content)
270
+ print(f"Successfully built ViewTemplate.js: {output_path}")
271
+ return True
272
+ except Exception as e:
273
+ print(f"Error writing to {output_path}: {str(e)}")
274
+ return False
275
+
276
+ def copy_essential_files_to_build():
277
+ """
278
+ Copy view.templates.js to resources/js/app/views/templates.js
279
+ """
280
+ print("\n=== Copying view.templates.js to app/views ===")
281
+
282
+ # Create views directory if it doesn't exist
283
+ views_dir = os.path.join(config.js_input_path, 'views')
284
+
285
+ # Clean views directory before copying templates
286
+ if os.path.exists(views_dir):
287
+ shutil.rmtree(views_dir)
288
+ print(f"āœ“ Cleaned views directory before copying templates: {views_dir}")
289
+
290
+ os.makedirs(views_dir, exist_ok=True)
291
+
292
+ # Copy view.templates.js to resources/js/app/views/templates.js
293
+ build_templates = config.get_build_view_templates_output_path()
294
+ app_templates = os.path.join(views_dir, 'templates.js')
295
+
296
+ if os.path.exists(build_templates):
297
+ shutil.copy2(build_templates, app_templates)
298
+ print(f"āœ“ Copied view.templates.js: {build_templates} -> {app_templates}")
299
+ else:
300
+ print(f"āœ— Build view.templates.js not found: {build_templates}")
301
+ return False
302
+
303
+ print("=== Copy completed ===")
304
+ return True
305
+
306
+ def copy_build_to_public():
307
+ """
308
+ Copy only main.js from resources/build to public/static/app
309
+ Keep original files in resources/build intact
310
+ """
311
+ print("\n=== Copying main.js to public ===")
312
+
313
+ # Copy only main.js
314
+ build_main = config.get_build_main_output_path()
315
+ public_main = config.get_main_output_path()
316
+
317
+ if os.path.exists(build_main):
318
+ os.makedirs(os.path.dirname(public_main), exist_ok=True)
319
+ shutil.copy2(build_main, public_main)
320
+ print(f"āœ“ Copied main.js: {build_main} -> {public_main}")
321
+ else:
322
+ print(f"āœ— Build main.js not found: {build_main}")
323
+ return False
324
+
325
+ print("=== Copy completed ===")
326
+ return True
327
+
328
+ def build_main_spa_file():
329
+ """
330
+ Build the main spa file by combining all modules according to auto-generated build.config.json
331
+ """
332
+ config_path = os.path.join(config.js_input_path, 'build.config.json')
333
+
334
+ try:
335
+ with open(config_path, 'r', encoding='utf-8') as f:
336
+ build_config = json.load(f)
337
+
338
+ # Check if config was auto-generated
339
+ if build_config.get('auto_discovery'):
340
+ print(f"šŸ“¦ Using auto-discovered modules ({len(build_config['modules'])} modules)")
341
+ else:
342
+ print(f"šŸ“¦ Using manual module configuration ({len(build_config['modules'])} modules)")
343
+
344
+ except Exception as e:
345
+ print(f"Error reading build config {config_path}: {str(e)}")
346
+ print("šŸ’” Run 'npm run discover' to auto-generate module configuration")
347
+ return False
348
+
349
+ output_file = build_config.get('output', 'main.js')
350
+ modules = build_config.get('modules', [])
351
+
352
+ if not modules:
353
+ print("No modules specified in build config")
354
+ return False
355
+
356
+ # Build the combined content
357
+ combined_content = ""
358
+ app_dir = config.js_input_path
359
+
360
+ for module in modules:
361
+ module_path = os.path.join(app_dir, module)
362
+ if os.path.exists(module_path):
363
+ try:
364
+ with open(module_path, 'r', encoding='utf-8') as f:
365
+ module_content = f.read()
366
+ combined_content += f"/* === {module} === */\n"
367
+ combined_content += module_content + "\n\n"
368
+ print(f"Added module: {module}")
369
+ except Exception as e:
370
+ print(f"Error reading module {module}: {str(e)}")
371
+ return False
372
+ else:
373
+ print(f"Warning: Module file not found: {module_path}")
374
+
375
+ # Write the combined file
376
+ output_path = config.get_build_main_output_path()
377
+ try:
378
+ with open(output_path, 'w', encoding='utf-8') as f:
379
+ f.write(combined_content)
380
+ print(f"Successfully built main spa file: {output_path}")
381
+ return True
382
+ except Exception as e:
383
+ print(f"Error writing to {output_path}: {str(e)}")
384
+ return False
385
+
386
+ def load_build_config():
387
+ """Load build.config.json"""
388
+ # Use the config object to find the project root
389
+ config_path = os.path.join(config.project_root, 'build.config.json')
390
+ if not os.path.exists(config_path):
391
+ return None
392
+
393
+ with open(config_path, 'r', encoding='utf-8') as f:
394
+ return json.load(f)
395
+
396
+ def get_contexts_to_build(requested_context='all'):
397
+ """Get list of contexts to build based on request"""
398
+ build_config = load_build_config()
399
+
400
+ if not build_config or 'contexts' not in build_config:
401
+ return None
402
+
403
+ if requested_context == 'all':
404
+ return build_config['contexts'].keys()
405
+ elif requested_context in build_config['contexts']:
406
+ return [requested_context]
407
+ else:
408
+ print(f"Error: Unknown context '{requested_context}'")
409
+ print(f"Available contexts: {', '.join(build_config['contexts'].keys())}")
410
+ sys.exit(1)
411
+
412
+ def get_source_directories(context_name=None):
413
+ """Get source directories for a specific context or all"""
414
+ # Try to load from build.config.json first
415
+ build_config = load_build_config()
416
+
417
+ if build_config and context_name and context_name in build_config['contexts']:
418
+ # Return sources for specific context
419
+ sources = build_config['contexts'][context_name]['sources']
420
+ # Convert relative paths to absolute
421
+ base_path = config.project_root
422
+ return [os.path.join(base_path, src) for src in sources]
423
+ elif build_config and context_name == 'all':
424
+ # Return all sources from all contexts
425
+ base_path = config.project_root
426
+ all_sources = set()
427
+ for ctx in build_config['contexts'].values():
428
+ for src in ctx['sources']:
429
+ all_sources.add(os.path.join(base_path, src))
430
+ return list(all_sources)
431
+ else:
432
+ # Fallback to config.get_build_directories()
433
+ return config.get_build_directories()
434
+
435
+ def main():
436
+ """
437
+ Main build function
438
+ """
439
+ # Parse arguments
440
+ parser = argparse.ArgumentParser(description='Build blade templates for specific context')
441
+ parser.add_argument('context', nargs='?', default='all',
442
+ help='Context to build: web, admin, or all (default: all)')
443
+ args = parser.parse_args()
444
+
445
+ print("Starting build script...")
446
+ print(f"Context: {args.context}")
447
+
448
+ # Get build directories based on context
449
+ build_directories = get_source_directories(args.context)
450
+
451
+ if not build_directories:
452
+ print("Error: No build directories configured")
453
+ print("Please add 'build_directories' to compiler.config.json or contexts to build.config.json")
454
+ sys.exit(1)
455
+
456
+ print(f"Build directories: {len(build_directories)} directories")
457
+ for i, dir_path in enumerate(build_directories, 1):
458
+ print(f" {i}. {dir_path}")
459
+
460
+ # Compile all directories
461
+ all_compiled_views = {}
462
+ all_blade_files_data = {}
463
+ total_success = 0
464
+ total_files = 0
465
+
466
+ for dir_path in build_directories:
467
+ print(f"\n=== Building directory: {dir_path} ===")
468
+
469
+ # Validate directory
470
+ if not os.path.exists(dir_path):
471
+ print(f"Warning: Directory '{dir_path}' does not exist, skipping...")
472
+ continue
473
+
474
+ if not os.path.isdir(dir_path):
475
+ print(f"Warning: '{dir_path}' is not a directory, skipping...")
476
+ continue
477
+
478
+ # Scan for blade files in this directory
479
+ blade_files = scan_directory(dir_path)
480
+
481
+ if not blade_files:
482
+ print(f"No .blade.php files found in {dir_path}")
483
+ continue
484
+
485
+ print(f"Found {len(blade_files)} blade files")
486
+ total_files += len(blade_files)
487
+
488
+ # Compile all blade files in this directory
489
+ compiled_views = {}
490
+ success_count = 0
491
+
492
+ for file_path in blade_files:
493
+ print(f"Compiling: {file_path}")
494
+
495
+ try:
496
+ # Convert file path to view name (relative to resources/views)
497
+ view_name = convert_path_to_view_name(file_path, config.views_input_path)
498
+
499
+ # Read blade code for script extraction
500
+ with open(file_path, 'r', encoding='utf-8') as f:
501
+ blade_code = f.read()
502
+
503
+ # Compile the blade file
504
+ view_data = compile_blade_file(file_path, config.views_input_path)
505
+
506
+ if view_data:
507
+ compiled_views[view_name] = view_data
508
+ all_compiled_views[view_name] = view_data
509
+ all_blade_files_data[view_name] = blade_code
510
+ success_count += 1
511
+ total_success += 1
512
+ print(f" -> {view_name} [SUCCESS]")
513
+ else:
514
+ print(f" -> Failed to compile [ERROR]")
515
+ except Exception as e:
516
+ print(f" -> Exception: {str(e)} [ERROR]")
517
+
518
+ print(f"Directory completed: {success_count}/{len(blade_files)} files successfully")
519
+
520
+ print(f"\n=== Overall Results ===")
521
+ print(f"Total compiled: {total_success}/{total_files} files successfully")
522
+
523
+ if all_compiled_views:
524
+ # Build individual view files
525
+ print(f"\n=== Building individual view files ===")
526
+ created_files = build_individual_view_files(all_compiled_views, all_blade_files_data, args.context)
527
+
528
+ if created_files:
529
+ # Build context-specific registry (templates.web.js, templates.admin.js)
530
+ view_template_path = os.path.join(config.js_input_path, 'core', 'ViewTemplate.js')
531
+ if build_view_template_importer(created_files, view_template_path, args.context):
532
+ # Get the actual registry path that was created
533
+ build_config = load_build_config()
534
+ if build_config and args.context != 'all' and args.context in build_config['contexts']:
535
+ registry_path = build_config['contexts'][args.context]['output']['register']
536
+ registry_filename = os.path.basename(registry_path)
537
+
538
+ # Create a proxy ViewTemplate.js in core/ that re-exports from context registry
539
+ core_template_path = os.path.join(config.js_input_path, 'core', 'ViewTemplate.js')
540
+ relative_to_registry = os.path.relpath(
541
+ os.path.join(config.project_root, registry_path),
542
+ os.path.dirname(core_template_path)
543
+ ).replace('\\', '/')
544
+
545
+ proxy_content = f"""// Auto-generated proxy to context-specific registry
546
+ // This file re-exports from {registry_filename}
547
+
548
+ export {{ ViewTemplates }} from '{relative_to_registry}';
549
+ """
550
+
551
+ with open(core_template_path, 'w', encoding='utf-8') as f:
552
+ f.write(proxy_content)
553
+
554
+ print(f"Created proxy ViewTemplate.js: {core_template_path}")
555
+ print(f" -> Points to: {registry_filename}")
556
+
557
+ print(f"\nāœ… Python build completed successfully!")
558
+ print(f"šŸ“¦ Total views: {len(all_compiled_views)}")
559
+ print(f"šŸ“„ Views: {list(all_compiled_views.keys())}")
560
+ print(f"šŸ“ Registry: {view_template_path}")
561
+ print(f"šŸ“ Individual view files: {os.path.join(config.js_input_path, 'views')}")
562
+ print(f"\nšŸ’” Next step: Run 'npm run compile' to build main.js")
563
+ else:
564
+ print(f"Failed to build ViewTemplate.js!")
565
+ sys.exit(1)
566
+ else:
567
+ print(f"Failed to build individual view files!")
568
+ sys.exit(1)
569
+ else:
570
+ print("No files were successfully compiled!")
571
+ sys.exit(1)
572
+
573
+ if __name__ == "__main__":
574
+ main()