onelaraveljs 1.0.0 → 1.1.1

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 (119) hide show
  1. package/README.md +1 -1
  2. package/bin/onejs-build.js +32 -0
  3. package/package.json +11 -3
  4. package/scripts/README-template-compiler.md +133 -0
  5. package/scripts/README.md +61 -0
  6. package/scripts/__pycache__/build.cpython-314.pyc +0 -0
  7. package/scripts/__pycache__/compile.cpython-313.pyc +0 -0
  8. package/scripts/__pycache__/compile.cpython-314.pyc +0 -0
  9. package/scripts/build.py +573 -0
  10. package/scripts/check-system-errors.php +214 -0
  11. package/scripts/compile.py +101 -0
  12. package/scripts/compiler/README_CONFIG.md +196 -0
  13. package/scripts/compiler/__init__.py +18 -0
  14. package/scripts/compiler/__pycache__/__init__.cpython-313.pyc +0 -0
  15. package/scripts/compiler/__pycache__/__init__.cpython-314.pyc +0 -0
  16. package/scripts/compiler/__pycache__/binding_directive_service.cpython-314.pyc +0 -0
  17. package/scripts/compiler/__pycache__/class_binding_handler.cpython-314.pyc +0 -0
  18. package/scripts/compiler/__pycache__/compiler_utils.cpython-313.pyc +0 -0
  19. package/scripts/compiler/__pycache__/compiler_utils.cpython-314.pyc +0 -0
  20. package/scripts/compiler/__pycache__/conditional_handlers.cpython-313.pyc +0 -0
  21. package/scripts/compiler/__pycache__/conditional_handlers.cpython-314.pyc +0 -0
  22. package/scripts/compiler/__pycache__/config.cpython-313.pyc +0 -0
  23. package/scripts/compiler/__pycache__/config.cpython-314.pyc +0 -0
  24. package/scripts/compiler/__pycache__/declaration_tracker.cpython-314.pyc +0 -0
  25. package/scripts/compiler/__pycache__/directive_processors.cpython-313.pyc +0 -0
  26. package/scripts/compiler/__pycache__/directive_processors.cpython-314.pyc +0 -0
  27. package/scripts/compiler/__pycache__/echo_processor.cpython-314.pyc +0 -0
  28. package/scripts/compiler/__pycache__/event_directive_processor.cpython-313.pyc +0 -0
  29. package/scripts/compiler/__pycache__/event_directive_processor.cpython-314.pyc +0 -0
  30. package/scripts/compiler/__pycache__/function_generators.cpython-313.pyc +0 -0
  31. package/scripts/compiler/__pycache__/function_generators.cpython-314.pyc +0 -0
  32. package/scripts/compiler/__pycache__/loop_handlers.cpython-313.pyc +0 -0
  33. package/scripts/compiler/__pycache__/loop_handlers.cpython-314.pyc +0 -0
  34. package/scripts/compiler/__pycache__/main_compiler.cpython-313.pyc +0 -0
  35. package/scripts/compiler/__pycache__/main_compiler.cpython-314.pyc +0 -0
  36. package/scripts/compiler/__pycache__/parsers.cpython-313.pyc +0 -0
  37. package/scripts/compiler/__pycache__/parsers.cpython-314.pyc +0 -0
  38. package/scripts/compiler/__pycache__/php_converter.cpython-313.pyc +0 -0
  39. package/scripts/compiler/__pycache__/php_converter.cpython-314.pyc +0 -0
  40. package/scripts/compiler/__pycache__/php_js_converter.cpython-313.pyc +0 -0
  41. package/scripts/compiler/__pycache__/php_js_converter.cpython-314.pyc +0 -0
  42. package/scripts/compiler/__pycache__/register_parser.cpython-313.pyc +0 -0
  43. package/scripts/compiler/__pycache__/register_parser.cpython-314.pyc +0 -0
  44. package/scripts/compiler/__pycache__/section_handlers.cpython-313.pyc +0 -0
  45. package/scripts/compiler/__pycache__/section_handlers.cpython-314.pyc +0 -0
  46. package/scripts/compiler/__pycache__/show_directive_handler.cpython-314.pyc +0 -0
  47. package/scripts/compiler/__pycache__/style_directive_handler.cpython-314.pyc +0 -0
  48. package/scripts/compiler/__pycache__/template_analyzer.cpython-313.pyc +0 -0
  49. package/scripts/compiler/__pycache__/template_analyzer.cpython-314.pyc +0 -0
  50. package/scripts/compiler/__pycache__/template_processor.cpython-313.pyc +0 -0
  51. package/scripts/compiler/__pycache__/template_processor.cpython-314.pyc +0 -0
  52. package/scripts/compiler/__pycache__/template_processors.cpython-313.pyc +0 -0
  53. package/scripts/compiler/__pycache__/template_processors.cpython-314.pyc +0 -0
  54. package/scripts/compiler/__pycache__/utils.cpython-313.pyc +0 -0
  55. package/scripts/compiler/__pycache__/utils.cpython-314.pyc +0 -0
  56. package/scripts/compiler/__pycache__/wrapper_parser.cpython-313.pyc +0 -0
  57. package/scripts/compiler/__pycache__/wrapper_parser.cpython-314.pyc +0 -0
  58. package/scripts/compiler/binding_directive_service.py +103 -0
  59. package/scripts/compiler/class_binding_handler.py +347 -0
  60. package/scripts/compiler/cli.py +34 -0
  61. package/scripts/compiler/code_generator.py +141 -0
  62. package/scripts/compiler/compiler.config.json +36 -0
  63. package/scripts/compiler/compiler_utils.py +55 -0
  64. package/scripts/compiler/conditional_handlers.py +252 -0
  65. package/scripts/compiler/config.py +107 -0
  66. package/scripts/compiler/declaration_tracker.py +420 -0
  67. package/scripts/compiler/directive_processors.py +603 -0
  68. package/scripts/compiler/echo_processor.py +667 -0
  69. package/scripts/compiler/event_directive_processor.py +1099 -0
  70. package/scripts/compiler/fetch_parser.py +49 -0
  71. package/scripts/compiler/function_generators.py +310 -0
  72. package/scripts/compiler/loop_handlers.py +224 -0
  73. package/scripts/compiler/main_compiler.py +1763 -0
  74. package/scripts/compiler/parsers.py +1418 -0
  75. package/scripts/compiler/php_converter.py +470 -0
  76. package/scripts/compiler/php_js_converter.py +603 -0
  77. package/scripts/compiler/register_parser.py +480 -0
  78. package/scripts/compiler/section_handlers.py +122 -0
  79. package/scripts/compiler/show_directive_handler.py +85 -0
  80. package/scripts/compiler/style_directive_handler.py +169 -0
  81. package/scripts/compiler/template_analyzer.py +162 -0
  82. package/scripts/compiler/template_processor.py +1167 -0
  83. package/scripts/compiler/template_processors.py +1557 -0
  84. package/scripts/compiler/test_compiler.py +69 -0
  85. package/scripts/compiler/utils.py +54 -0
  86. package/scripts/compiler/variables_analyzer.py +135 -0
  87. package/scripts/compiler/view_identifier_generator.py +278 -0
  88. package/scripts/compiler/wrapper_parser.py +78 -0
  89. package/scripts/dev-context.js +311 -0
  90. package/scripts/dev.js +109 -0
  91. package/scripts/generate-assets-order.js +200 -0
  92. package/scripts/migrate-namespace.php +146 -0
  93. package/scripts/node/MIGRATION.md +190 -0
  94. package/scripts/node/README.md +269 -0
  95. package/scripts/node/build.js +208 -0
  96. package/scripts/node/compiler/compiler-utils.js +38 -0
  97. package/scripts/node/compiler/conditional-handlers.js +45 -0
  98. package/scripts/node/compiler/config.js +178 -0
  99. package/scripts/node/compiler/directive-processors.js +51 -0
  100. package/scripts/node/compiler/event-directive-processor.js +182 -0
  101. package/scripts/node/compiler/function-generators.js +239 -0
  102. package/scripts/node/compiler/loop-handlers.js +45 -0
  103. package/scripts/node/compiler/main-compiler.js +236 -0
  104. package/scripts/node/compiler/parsers.js +358 -0
  105. package/scripts/node/compiler/php-converter.js +227 -0
  106. package/scripts/node/compiler/register-parser.js +32 -0
  107. package/scripts/node/compiler/section-handlers.js +46 -0
  108. package/scripts/node/compiler/template-analyzer.js +50 -0
  109. package/scripts/node/compiler/template-processor.js +371 -0
  110. package/scripts/node/compiler/template-processors.js +219 -0
  111. package/scripts/node/compiler/utils.js +203 -0
  112. package/scripts/node/compiler/wrapper-parser.js +25 -0
  113. package/scripts/node/package.json +24 -0
  114. package/scripts/node/test-compiler.js +52 -0
  115. package/scripts/node-run.cjs +28 -0
  116. package/scripts/standardize-directories.php +92 -0
  117. package/templates/view.module.js +2 -0
  118. package/templates/view.tpl-raw.js +13 -0
  119. package/templates/wraper.js +71 -0
@@ -0,0 +1,55 @@
1
+ """
2
+ Utility methods cho compiler
3
+ """
4
+
5
+ import json
6
+ from config import JS_FUNCTION_PREFIX
7
+
8
+ class CompilerUtils:
9
+ def __init__(self):
10
+ pass
11
+
12
+ def format_fetch_config(self, fetch_config):
13
+ """Format fetch config without extra quotes around template strings"""
14
+ if not fetch_config:
15
+ return 'null'
16
+
17
+ # Format the config manually to avoid json.dumps adding quotes
18
+ config_parts = []
19
+ for key, value in fetch_config.items():
20
+ if isinstance(value, str):
21
+ # Check if it's a template string (starts with ` and ends with `)
22
+ if value.startswith('`') and value.endswith('`'):
23
+ # Template string - don't add quotes
24
+ config_parts.append(f'"{key}": {value}')
25
+ else:
26
+ # Regular string - add quotes
27
+ config_parts.append(f'"{key}": "{value}"')
28
+ elif isinstance(value, (dict, list)):
29
+ # Object or array - use json.dumps
30
+ config_parts.append(f'"{key}": {json.dumps(value, ensure_ascii=False)}')
31
+ else:
32
+ # Other types (numbers, booleans, etc.) - use json.dumps
33
+ config_parts.append(f'"{key}": {json.dumps(value, ensure_ascii=False)}')
34
+
35
+ return '{' + ', '.join(config_parts) + '}'
36
+
37
+ def format_attrs(self, attrs_dict):
38
+ """Format attributes dictionary to JavaScript object string"""
39
+ import json
40
+ return json.dumps(attrs_dict, separators=(',', ':'))
41
+
42
+ def format_attributes_to_json(self, attributes):
43
+ """Format attributes dictionary to JSON string for scripts/styles"""
44
+ if not attributes:
45
+ return '{}'
46
+
47
+ # Handle boolean and string attributes properly
48
+ formatted_attrs = {}
49
+ for key, value in attributes.items():
50
+ if isinstance(value, bool):
51
+ formatted_attrs[key] = value
52
+ else:
53
+ formatted_attrs[key] = str(value)
54
+
55
+ return json.dumps(formatted_attrs, separators=(',', ':'))
@@ -0,0 +1,252 @@
1
+ """
2
+ Handlers cho các conditional directives (@if, @switch, etc.)
3
+ """
4
+
5
+ from config import JS_FUNCTION_PREFIX
6
+ from php_converter import php_to_js
7
+ from utils import extract_balanced_parentheses
8
+ import re
9
+
10
+ class ConditionalHandlers:
11
+ def __init__(self, state_variables=None, processor=None):
12
+ self.state_variables = state_variables or set()
13
+ self.processor = processor
14
+
15
+ def _extract_variables(self, expr):
16
+ """Extract variable names from expression, excluding method names after dot notation"""
17
+ variables = set()
18
+
19
+ # Remove method calls after dots (e.g., App.Helper.count -> remove count)
20
+ # Replace .methodName( with .PLACEHOLDER( to avoid extracting method names
21
+ expr_cleaned = re.sub(r'\.([a-zA-Z_][a-zA-Z0-9_]*)\s*\(', '.METHODCALL(', expr)
22
+
23
+ var_pattern = r'\b([a-zA-Z_][a-zA-Z0-9_]*)\b'
24
+ matches = re.findall(var_pattern, expr_cleaned)
25
+ for var_name in matches:
26
+ # Exclude JS keywords, common functions, and placeholder
27
+ if var_name not in ['if', 'else', 'return', 'function', 'const', 'let', 'var', 'true', 'false', 'null', 'undefined', 'Array', 'Object', 'String', 'Number', 'METHODCALL', 'App', 'View', 'Helper']:
28
+ variables.add(var_name)
29
+ return variables
30
+
31
+ def process_if_directive(self, line, stack, output, is_attribute_context=False):
32
+ """Process @if directive
33
+
34
+ Args:
35
+ is_attribute_context: True if directive is in tag attributes (e.g., <div @if(...)>)
36
+ False if directive is in block/content (e.g., <div>@if(...))
37
+ """
38
+ if_pos = line.find('(')
39
+ if if_pos != -1:
40
+ condition_text, end_pos = extract_balanced_parentheses(line, if_pos)
41
+ if condition_text is not None:
42
+ condition_php = condition_text.strip()
43
+ condition = php_to_js(condition_php)
44
+
45
+ # Extract variables from condition
46
+ variables = self._extract_variables(condition)
47
+ state_vars_used = variables & self.state_variables
48
+
49
+ # Store state vars for this if block (will be used in endif)
50
+ watch_keys = list(state_vars_used) if state_vars_used else []
51
+
52
+ # Check if inside a loop (for/while only, NOT foreach)
53
+ # @foreach uses callback that returns template literal directly
54
+ # Only @for and @while use __outputContent__ concatenation pattern
55
+ parent_is_loop = False
56
+ parent_concat_var = ""
57
+ if stack:
58
+ parent_type = stack[-1][0]
59
+ if parent_type in ['for', 'while']:
60
+ parent_is_loop = True
61
+ parent_concat_var = f"__{parent_type}OutputContent__"
62
+
63
+ # If inside a loop and has state vars, use concat += with __watch
64
+ if parent_is_loop and watch_keys:
65
+ if self.processor:
66
+ self.processor.watch_counter += 1
67
+ watch_id = f"`${{__VIEW_ID__}}-watch-{self.processor.watch_counter}-${{__loop.index}}`"
68
+ else:
69
+ watch_id = "`${__VIEW_ID__}-watch-0-${__loop.index}`"
70
+ result = f"{parent_concat_var} += this.__watch({watch_id}, {watch_keys}, () => {{ if({condition}){{ return `"
71
+ # If inside a loop but no state vars, use concat += with IIFE
72
+ elif parent_is_loop:
73
+ result = f"{parent_concat_var} += (() => {{ if({condition}){{ return `"
74
+ # Only wrap with __watch for block-level directives (not attributes, not in loops)
75
+ elif is_attribute_context or not watch_keys:
76
+ # Attribute directive or no state vars - no watch wrapping
77
+ result = f"${{this.__execute(() => {{ if({condition}){{ return `"
78
+ else:
79
+ # Block directive with state vars - wrap with __watch
80
+ if self.processor:
81
+ self.processor.watch_counter += 1
82
+ watch_id = f"`${{__VIEW_ID__}}-watch-{self.processor.watch_counter}`"
83
+ else:
84
+ watch_id = "`${__VIEW_ID__}-watch-0`"
85
+ result = f"${{this.__watch({watch_id}, {watch_keys}, () => {{ if({condition}){{ return `"
86
+
87
+ output.append(result)
88
+ stack.append(('if', len(output), watch_keys, is_attribute_context, parent_is_loop))
89
+ return True
90
+ return False
91
+
92
+ def process_elseif_directive(self, line, stack, output):
93
+ """Process @elseif directive"""
94
+ elseif_pos = line.find('(')
95
+ if elseif_pos != -1:
96
+ condition_text, end_pos = extract_balanced_parentheses(line, elseif_pos)
97
+ if condition_text is not None:
98
+ condition_php = condition_text.strip()
99
+ condition = php_to_js(condition_php)
100
+
101
+ # Extract variables and merge with existing if block's watch keys
102
+ variables = self._extract_variables(condition)
103
+ state_vars_used = variables & self.state_variables
104
+
105
+ # Update watch_keys in stack
106
+ if stack and stack[-1][0] == 'if':
107
+ existing_keys = set(stack[-1][2]) if len(stack[-1]) > 2 else set()
108
+ new_keys = existing_keys | state_vars_used
109
+ stack[-1] = ('if', stack[-1][1], list(new_keys))
110
+
111
+ result = f"`; }} else if({condition}){{ return `"
112
+ output.append(result)
113
+ return True
114
+ return False
115
+
116
+ def process_else_directive(self, line, stack, output):
117
+ """Process @else directive"""
118
+ # Check if we're inside a loop (need to escape backticks)
119
+ parent_is_loop = False
120
+ if stack and stack[-1][0] == 'if':
121
+ parent_is_loop = stack[-1][4] if len(stack[-1]) > 4 else False
122
+
123
+ result = f"`; }} else {{ return `"
124
+ output.append(result)
125
+ return True
126
+
127
+ def process_endif_directive(self, stack, output):
128
+ """Process @endif directive"""
129
+ if stack and stack[-1][0] == 'if':
130
+ is_attribute = stack[-1][3] if len(stack[-1]) > 3 else False
131
+ parent_is_loop = stack[-1][4] if len(stack[-1]) > 4 else False
132
+ watch_keys = stack[-1][2] if len(stack[-1]) > 2 else []
133
+ stack.pop()
134
+
135
+ output.append('`; }')
136
+ output.append("return '';")
137
+
138
+ if parent_is_loop and watch_keys:
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
+ elif parent_is_loop:
143
+ # Inside loop without state vars - close IIFE with immediate execution
144
+ output.append('})')
145
+ else:
146
+ # Normal block - close IIFE or watch
147
+ output.append('})}')
148
+ return True
149
+
150
+ def process_switch_directive(self, line, stack, output, is_attribute_context=False):
151
+ """Process @switch directive
152
+
153
+ Args:
154
+ is_attribute_context: True if directive is in tag attributes
155
+ False if directive is in block/content
156
+ """
157
+ switch_pos = line.find('(')
158
+ if switch_pos != -1:
159
+ switch_content, end_pos = extract_balanced_parentheses(line, switch_pos)
160
+ if switch_content is not None:
161
+ condition_php = switch_content.strip()
162
+ condition = php_to_js(condition_php)
163
+
164
+ # Extract variables from condition
165
+ variables = self._extract_variables(condition)
166
+ state_vars_used = variables & self.state_variables
167
+ watch_keys = list(state_vars_used) if state_vars_used else []
168
+
169
+ # Check if parent is a loop using concatenation pattern
170
+ parent_is_concat = False
171
+ parent_type_name = None
172
+ if stack:
173
+ parent_type = stack[-1][0]
174
+ if parent_type in ['for', 'foreach', 'while']:
175
+ parent_is_concat = True
176
+ parent_type_name = parent_type
177
+
178
+ # Generate switch statement
179
+ switch_logic = f"let __switchOutputContent__ = '';\nswitch({condition}) {{"
180
+
181
+ # Determine output format based on parent context
182
+ if parent_is_concat:
183
+ # Parent uses concatenation (+=), so add concat prefix and use this.__execute()
184
+ concat_var = f"__{parent_type_name}OutputContent__"
185
+ if is_attribute_context or not watch_keys:
186
+ result = f"{concat_var} += this.__execute(() => {{\n{switch_logic}"
187
+ else:
188
+ if self.processor:
189
+ self.processor.watch_counter += 1
190
+ watch_id = f"`${{__VIEW_ID__}}-watch-{self.processor.watch_counter}`"
191
+ else:
192
+ watch_id = "`${__VIEW_ID__}-watch-0`"
193
+ result = f"{concat_var} += this.__watch({watch_id}, {watch_keys}, () => {{\n{switch_logic}"
194
+ else:
195
+ # Parent uses template literal, so output template expression
196
+ if is_attribute_context or not watch_keys:
197
+ result = f"${{this.__execute(() => {{\n{switch_logic}"
198
+ else:
199
+ if self.processor:
200
+ self.processor.watch_counter += 1
201
+ watch_id = f"`${{__VIEW_ID__}}-watch-{self.processor.watch_counter}`"
202
+ else:
203
+ watch_id = "`${__VIEW_ID__}-watch-0`"
204
+ result = f"${{this.__watch({watch_id}, {watch_keys}, () => {{\n{switch_logic}"
205
+
206
+ output.append(result)
207
+ stack.append(('switch', len(output), watch_keys, is_attribute_context, parent_is_concat))
208
+ return True
209
+ return False
210
+
211
+ def process_case_directive(self, line, stack, output):
212
+ """Process @case directive"""
213
+ case_pos = line.find('(')
214
+ if case_pos != -1:
215
+ case_content, end_pos = extract_balanced_parentheses(line, case_pos)
216
+ if case_content is not None:
217
+ condition = php_to_js(case_content.strip())
218
+ result = f"\ncase {condition}:\n__switchOutputContent__ += `"
219
+ output.append(result)
220
+ # Don't push to stack - case is part of switch
221
+ return True
222
+ return False
223
+
224
+ def process_default_directive(self, line, stack, output):
225
+ """Process @default directive"""
226
+ result = f"\ndefault:\n__switchOutputContent__ += `"
227
+ output.append(result)
228
+ # Don't push to stack - default is part of switch
229
+ return True
230
+
231
+ def process_break_directive(self, line, stack, output):
232
+ """Process @break directive"""
233
+ result = f"`;\nbreak;"
234
+ output.append(result)
235
+ return True
236
+
237
+ def process_endswitch_directive(self, stack, output):
238
+ """Process @endswitch directive"""
239
+ if stack and stack[-1][0] == 'switch':
240
+ switch_info = stack.pop()
241
+ parent_is_concat = switch_info[4] if len(switch_info) > 4 else False
242
+
243
+ if parent_is_concat:
244
+ # Parent uses concatenation, close with })
245
+ result = "`;\n}\nreturn __switchOutputContent__;\n})"
246
+ else:
247
+ # Parent uses template literal, output template expression
248
+ result = "`;\n}\nreturn __switchOutputContent__;\n})}"
249
+
250
+ output.append(result)
251
+ return True
252
+ return False
@@ -0,0 +1,107 @@
1
+ """
2
+ Configuration file for Python Blade Compiler (Library Version)
3
+ """
4
+ import os
5
+ import json
6
+
7
+ class CompilerConfig:
8
+ """Configuration class for Blade compiler paths and settings"""
9
+
10
+ def __init__(self, config_file=None):
11
+ # 1. Project Root: Taken from environment variable (Passed by CLI wrapper)
12
+ self.project_root = os.environ.get('ONEJS_PROJECT_ROOT')
13
+ if not self.project_root:
14
+ # Fallback for dev/testing in library itself
15
+ self.project_root = os.getcwd()
16
+
17
+ # 2. Library Root: Taken from environment variable (Passed by CLI wrapper)
18
+ self.lib_root = os.environ.get('ONEJS_LIB_ROOT')
19
+ if not self.lib_root:
20
+ # Fallback relative to this file
21
+ self.lib_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
22
+
23
+ # Load build config from PROJECT root (User's project)
24
+ # It's usually build.config.json or compiler.config.json
25
+ # We try to find build.config.json first as it is the new standard
26
+ self.build_config_file = os.path.join(self.project_root, 'build.config.json')
27
+ self.build_config_data = {}
28
+
29
+ if os.path.exists(self.build_config_file):
30
+ try:
31
+ with open(self.build_config_file, 'r', encoding='utf-8') as f:
32
+ self.build_config_data = json.load(f)
33
+ except Exception as e:
34
+ print(f"Warning: Could not load build.config.json: {e}")
35
+
36
+ # Default paths
37
+ self.views_input_path = os.path.join(self.project_root, 'resources/views')
38
+ # Default js output: resources/js (The compiler will append /views or /config internally)
39
+ self.js_input_path = os.path.join(self.project_root, 'resources/js')
40
+
41
+ # Template path (Internal to Library)
42
+ self.wrapper_template_path = os.path.join(self.lib_root, 'templates')
43
+
44
+ # Files
45
+ self.view_templates_file = 'templates.js'
46
+
47
+ # Other settings from config or defaults
48
+ self.config_data = self.build_config_data # Alias for compatibility
49
+
50
+ def get_wrapper_template_path(self):
51
+ """Get path to the wrapper template inside the library"""
52
+ return self.wrapper_template_path
53
+
54
+ def get_build_directories(self):
55
+ """Get list of directories to build (relative to views root)"""
56
+ # If 'contexts' is defined in build.config.json, we don't use this old method usually,
57
+ # but for compatibility or simple usage:
58
+ return []
59
+
60
+ def get_views_path(self, scope=None):
61
+ if scope:
62
+ return os.path.join(self.views_input_path, scope)
63
+ return self.views_input_path
64
+
65
+ def get_js_input_path(self):
66
+ return self.js_input_path
67
+
68
+ # Constants for backward compatibility
69
+ JS_FUNCTION_PREFIX = "App.View"
70
+ HTML_ATTR_PREFIX = "data-"
71
+ SPA_YIELD_ATTR_PREFIX = "data-yield-attr"
72
+ SPA_YIELD_SUBSCRIBE_KEY_PREFIX = "data-yield-key"
73
+ SPA_YIELD_SUBSCRIBE_TARGET_PREFIX = "data-yield-target"
74
+ SPA_YIELD_SUBSCRIBE_ATTR_PREFIX = "data-yield-attr"
75
+ SPA_YIELD_CONTENT_PREFIX = "data-yield-content"
76
+ SPA_YIELD_CHILDREN_PREFIX = "data-yield-children"
77
+ SPA_STATECHANGE_PREFIX = "data-statechange-"
78
+ APP_VIEW_NAMESPACE = "App.View"
79
+ APP_HELPER_NAMESPACE = "App.Helper"
80
+
81
+ class ViewConfig:
82
+ VIEW_FUNCTIONS = [
83
+ 'generateViewId', 'execute', 'evaluate', 'escString', 'text', 'templateToDom',
84
+ 'view', 'loadView', 'renderView', 'include', 'includeIf', 'extendView',
85
+ 'setSuperViewPath', 'addViewEngine', 'callViewEngineMounted',
86
+ 'startWrapper', 'endWrapper', 'registerSubscribe',
87
+ 'section', 'yield', 'yieldContent', 'renderSections', 'hasSection',
88
+ 'getChangedSections', 'resetChangedSections', 'isChangedSection', 'emitChangedSections',
89
+ 'push', 'stack', 'once', 'route', 'on', 'off', 'emit',
90
+ 'init', 'setApp', 'setContainer', 'clearOldRendering',
91
+ 'isAuth', 'can', 'cannot', 'hasError', 'firstError', 'csrfToken',
92
+ 'foreach', 'foreachTemplate'
93
+ ]
94
+
95
+ @classmethod
96
+ def is_view_function(cls, function_name):
97
+ return function_name in cls.VIEW_FUNCTIONS
98
+
99
+ @classmethod
100
+ def is_helper_function(cls, function_name):
101
+ return not cls.is_view_function(function_name)
102
+
103
+ @classmethod
104
+ def get_function_source(cls, function_name):
105
+ return 'View' if cls.is_view_function(function_name) else 'Helper'
106
+
107
+ config = CompilerConfig()