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,50 @@
1
+ /**
2
+ * Template analyzer - analyzes template content
3
+ */
4
+
5
+ class TemplateAnalyzer {
6
+ constructor() {
7
+ // No initialization needed
8
+ }
9
+
10
+ analyzeTemplate(templateContent) {
11
+ /** Analyze template content */
12
+ const analysis = {
13
+ hasPrerender: false,
14
+ conditionalContent: '',
15
+ sections: [],
16
+ variables: [],
17
+ directives: []
18
+ };
19
+
20
+ // Check for prerender content
21
+ if (templateContent.includes('preloader') || templateContent.includes('loading')) {
22
+ analysis.hasPrerender = true;
23
+ }
24
+
25
+ // Check for conditional content
26
+ if (templateContent.includes('@if') || templateContent.includes('@unless')) {
27
+ analysis.conditionalContent = templateContent;
28
+ }
29
+
30
+ // Extract sections
31
+ const sectionMatches = templateContent.match(/\$\{App\.View\.section\(['"]([^'"]+)['"][^}]*\)\}/g);
32
+ if (sectionMatches) {
33
+ analysis.sections = sectionMatches.map(match => {
34
+ const nameMatch = match.match(/['"]([^'"]+)['"]/);
35
+ return nameMatch ? nameMatch[1] : null;
36
+ }).filter(Boolean);
37
+ }
38
+
39
+ // Extract variables
40
+ const varMatches = templateContent.match(/\$\{([^}]+)\}/g);
41
+ if (varMatches) {
42
+ analysis.variables = varMatches.map(match => match.slice(2, -1));
43
+ }
44
+
45
+ return analysis;
46
+ }
47
+ }
48
+
49
+ module.exports = TemplateAnalyzer;
50
+
@@ -0,0 +1,371 @@
1
+ /**
2
+ * Main template processor that handles template content
3
+ */
4
+
5
+ const { extractBalancedParentheses, splitByComma } = require('./utils');
6
+ const ConditionalHandlers = require('./conditional-handlers');
7
+ const LoopHandlers = require('./loop-handlers');
8
+ const SectionHandlers = require('./section-handlers');
9
+ const TemplateProcessors = require('./template-processors');
10
+ const DirectiveProcessor = require('./directive-processors');
11
+ const EventDirectiveProcessor = require('./event-directive-processor');
12
+
13
+ class TemplateProcessor {
14
+ constructor() {
15
+ this.conditionalHandlers = new ConditionalHandlers();
16
+ this.loopHandlers = new LoopHandlers();
17
+ this.sectionHandlers = new SectionHandlers();
18
+ this.templateProcessors = new TemplateProcessors();
19
+ this.directiveProcessors = new DirectiveProcessor();
20
+ this.eventProcessor = new EventDirectiveProcessor();
21
+ }
22
+
23
+ processTemplate(bladeCode) {
24
+ /** Process template content and extract sections */
25
+ // Remove already processed directives
26
+ let processedCode = bladeCode.replace(/@extends\s*\([^)]*\)/gs, '');
27
+ processedCode = processedCode.replace(/@vars\s*\([^)]*\)/gs, '');
28
+
29
+ // Remove @let directives with balanced parentheses
30
+ const letPattern = /@let\s*\(/g;
31
+ let match;
32
+ while ((match = letPattern.exec(processedCode)) !== null) {
33
+ const startPos = match.index + match[0].length - 1;
34
+ const [content, endPos] = extractBalancedParentheses(processedCode, startPos);
35
+ if (content !== null) {
36
+ processedCode = processedCode.substring(0, match.index) + processedCode.substring(startPos + content.length + 2);
37
+ } else {
38
+ break;
39
+ }
40
+ }
41
+
42
+ // Remove @const directives with balanced parentheses
43
+ const constPattern = /@const\s*\(/g;
44
+ while ((match = constPattern.exec(processedCode)) !== null) {
45
+ const startPos = match.index + match[0].length - 1;
46
+ const [content, endPos] = extractBalancedParentheses(processedCode, startPos);
47
+ if (content !== null) {
48
+ processedCode = processedCode.substring(0, match.index) + processedCode.substring(startPos + content.length + 2);
49
+ } else {
50
+ break;
51
+ }
52
+ }
53
+
54
+ // Remove @useState directives with balanced parentheses
55
+ const useStatePattern = /@useState\s*\(/g;
56
+ while ((match = useStatePattern.exec(processedCode)) !== null) {
57
+ const startPos = match.index + match[0].length - 1;
58
+ const [content, endPos] = extractBalancedParentheses(processedCode, startPos);
59
+ if (content !== null) {
60
+ processedCode = processedCode.substring(0, match.index) + processedCode.substring(startPos + content.length + 2);
61
+ } else {
62
+ break;
63
+ }
64
+ }
65
+
66
+ // Remove @onInit directives with balanced parentheses
67
+ const onInitPattern = /@onInit\s*\(/gs;
68
+ while ((match = onInitPattern.exec(processedCode)) !== null) {
69
+ const startPos = match.index + match[0].length - 1;
70
+ const [content, endPos] = extractBalancedParentheses(processedCode, startPos);
71
+ if (content !== null) {
72
+ processedCode = processedCode.substring(0, match.index) + processedCode.substring(startPos + content.length + 2);
73
+ } else {
74
+ break;
75
+ }
76
+ }
77
+
78
+ // Remove @register directives with balanced parentheses
79
+ const registerPattern = /@register\s*\(/gs;
80
+ while ((match = registerPattern.exec(processedCode)) !== null) {
81
+ const startPos = match.index + match[0].length - 1;
82
+ const [content, endPos] = extractBalancedParentheses(processedCode, startPos);
83
+ if (content !== null) {
84
+ processedCode = processedCode.substring(0, match.index) + processedCode.substring(startPos + content.length + 2);
85
+ } else {
86
+ break;
87
+ }
88
+ }
89
+
90
+ // Remove @wrapper directives with balanced parentheses
91
+ const wrapperPattern = /@wrapper\s*\(/gs;
92
+ while ((match = wrapperPattern.exec(processedCode)) !== null) {
93
+ const startPos = match.index + match[0].length - 1;
94
+ const [content, endPos] = extractBalancedParentheses(processedCode, startPos);
95
+ if (content !== null) {
96
+ processedCode = processedCode.substring(0, match.index) + processedCode.substring(startPos + content.length + 2);
97
+ } else {
98
+ break;
99
+ }
100
+ }
101
+
102
+ // Remove @viewType directives
103
+ processedCode = processedCode.replace(/@viewType\s*\([^)]*\)/g, '');
104
+
105
+ // Remove @await directives with balanced parentheses
106
+ const awaitPattern = /@await\s*\(/gs;
107
+ while ((match = awaitPattern.exec(processedCode)) !== null) {
108
+ const startPos = match.index + match[0].length - 1;
109
+ const [content, endPos] = extractBalancedParentheses(processedCode, startPos);
110
+ if (content !== null) {
111
+ processedCode = processedCode.substring(0, match.index) + processedCode.substring(startPos + content.length + 2);
112
+ } else {
113
+ break;
114
+ }
115
+ }
116
+
117
+ // Remove @fetch directives with balanced parentheses
118
+ const fetchPattern = /@fetch\s*\(/gs;
119
+ while ((match = fetchPattern.exec(processedCode)) !== null) {
120
+ const startPos = match.index + match[0].length - 1;
121
+ const [content, endPos] = extractBalancedParentheses(processedCode, startPos);
122
+ if (content !== null) {
123
+ processedCode = processedCode.substring(0, match.index) + processedCode.substring(startPos + content.length + 2);
124
+ } else {
125
+ break;
126
+ }
127
+ }
128
+
129
+ // Process the template content
130
+ const lines = processedCode.split('\n');
131
+ const output = [];
132
+ const sections = [];
133
+ const stack = [];
134
+ let skipUntil = null;
135
+ let removeDirectiveMarkers = false;
136
+
137
+ for (let i = 0; i < lines.length; i++) {
138
+ let line = lines[i];
139
+ const originalLine = line;
140
+
141
+ // Handle skip modes
142
+ if (skipUntil) {
143
+ if (skipUntil === '@endserverside') {
144
+ const endserversideAliases = [
145
+ '@endserverside', '@endServerSide', '@endSSR', '@endSsr',
146
+ '@EndSSR', '@EndSsr', '@endssr'
147
+ ];
148
+ if (endserversideAliases.some(alias => line.trim().startsWith(alias))) {
149
+ skipUntil = null;
150
+ removeDirectiveMarkers = false;
151
+ i++; // Skip the end directive line
152
+ continue;
153
+ }
154
+ } else if (skipUntil === '@endclientside') {
155
+ const endclientsideAliases = [
156
+ '@endclientside', '@endClientSide', '@endcsr', '@endCSR',
157
+ '@endCsr', '@endusecsr', '@endUseCSR', '@endUseCsr'
158
+ ];
159
+ if (endclientsideAliases.some(alias => line.trim().startsWith(alias))) {
160
+ skipUntil = null;
161
+ removeDirectiveMarkers = false;
162
+ i++; // Skip the end directive line
163
+ continue;
164
+ } else if (removeDirectiveMarkers) {
165
+ // Process line normally (convert PHP to JS) but without adding directive markers
166
+ const processedLine = this.templateProcessors.processTemplateLine(line);
167
+ output.push(processedLine);
168
+ }
169
+ }
170
+ i++;
171
+ continue;
172
+ }
173
+
174
+ // Skip empty lines
175
+ if (!line.trim()) {
176
+ output.push('');
177
+ continue;
178
+ }
179
+
180
+ // Process line directives
181
+ const processed = this._processLineDirectives(line, stack, output, sections);
182
+ if (processed) {
183
+ if (processed === 'skip_until_@endserverside') {
184
+ skipUntil = '@endserverside';
185
+ // Skip the @ssr line itself
186
+ i++;
187
+ continue;
188
+ } else if (processed === 'remove_directive_markers_until_@endclientside') {
189
+ skipUntil = '@endclientside';
190
+ removeDirectiveMarkers = true;
191
+ // Skip the @csr line itself
192
+ i++;
193
+ continue;
194
+ } else {
195
+ // Append the processed directive result
196
+ output.push(processed);
197
+ }
198
+ i++;
199
+ continue;
200
+ }
201
+
202
+ // Check if we're inside a php block first
203
+ if (stack.length > 0 && stack[stack.length - 1][0] === 'php') {
204
+ // Convert PHP to JavaScript
205
+ if (line.trim()) {
206
+ const jsLine = this.templateProcessors.processTemplateLine(line);
207
+ output.push(jsLine);
208
+ } else {
209
+ output.push('');
210
+ }
211
+ continue;
212
+ }
213
+
214
+ // Process template line
215
+ const processedLine = this.templateProcessors.processTemplateLine(line);
216
+ output.push(processedLine);
217
+ }
218
+
219
+ const templateContent = output.filter(item => typeof item === 'string').join('\n');
220
+ return { templateContent, sections };
221
+ }
222
+
223
+ _processLineDirectives(line, stack, output, sections) {
224
+ /** Process line-level directives */
225
+ // Check for section directives
226
+ const sectionProcessed = this.sectionHandlers.processSectionDirective(line, stack, output, sections);
227
+ if (sectionProcessed) {
228
+ return sectionProcessed;
229
+ }
230
+
231
+ // Check for conditional directives
232
+ const conditionalProcessed = this.conditionalHandlers.processConditionalDirective(line, stack, output);
233
+ if (conditionalProcessed) {
234
+ return conditionalProcessed;
235
+ }
236
+
237
+ // Check for loop directives
238
+ const loopProcessed = this.loopHandlers.processLoopDirective(line, stack, output);
239
+ if (loopProcessed) {
240
+ return loopProcessed;
241
+ }
242
+
243
+ // Check for other directives
244
+ const otherProcessed = this.directiveProcessors.processDirective(line, stack, output);
245
+ if (otherProcessed) {
246
+ return otherProcessed;
247
+ }
248
+
249
+ // Check for event directives
250
+ const eventProcessed = this._processEventDirectives(line);
251
+ if (eventProcessed) {
252
+ return eventProcessed;
253
+ }
254
+
255
+ // Check for server/client side directives
256
+ const serversideProcessed = this.templateProcessors.processServersideDirective(line);
257
+ if (serversideProcessed) {
258
+ return serversideProcessed;
259
+ }
260
+
261
+ const clientsideProcessed = this.templateProcessors.processClientsideDirective(line);
262
+ if (clientsideProcessed) {
263
+ return clientsideProcessed;
264
+ }
265
+
266
+ return null;
267
+ }
268
+
269
+ _processEventDirectives(line) {
270
+ /** Process event directives (@click, @change, @submit, etc.) */
271
+ // List of event types to check - comprehensive DOM events
272
+ const eventTypes = [
273
+ // Mouse Events
274
+ 'click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mouseout', 'mousemove',
275
+ 'mouseenter', 'mouseleave', 'wheel', 'auxclick',
276
+
277
+ // Keyboard Events
278
+ 'keydown', 'keyup', 'keypress',
279
+
280
+ // Form Events
281
+ 'input', 'change', 'submit', 'reset', 'invalid', 'search',
282
+
283
+ // Focus Events
284
+ 'focus', 'blur', 'focusin', 'focusout',
285
+
286
+ // Selection Events
287
+ 'select', 'selectstart', 'selectionchange',
288
+
289
+ // Touch Events
290
+ 'touchstart', 'touchmove', 'touchend', 'touchcancel',
291
+
292
+ // Drag & Drop Events
293
+ 'dragstart', 'drag', 'dragend', 'dragenter', 'dragleave', 'dragover', 'drop',
294
+
295
+ // Media Events
296
+ 'play', 'pause', 'ended', 'loadstart', 'loadeddata', 'loadedmetadata', 'canplay',
297
+ 'canplaythrough', 'waiting', 'seeking', 'seeked', 'ratechange', 'durationchange',
298
+ 'volumechange', 'suspend', 'stalled', 'progress', 'emptied', 'encrypted', 'wakeup',
299
+
300
+ // Window Events
301
+ 'load', 'unload', 'beforeunload', 'resize', 'scroll', 'orientationchange',
302
+ 'visibilitychange', 'pagehide', 'pageshow', 'popstate', 'hashchange', 'online', 'offline',
303
+
304
+ // Document Events
305
+ 'DOMContentLoaded', 'readystatechange',
306
+
307
+ // Error Events
308
+ 'error', 'abort',
309
+
310
+ // Context Menu
311
+ 'contextmenu',
312
+
313
+ // Animation Events
314
+ 'animationstart', 'animationend', 'animationiteration',
315
+
316
+ // Transition Events
317
+ 'transitionstart', 'transitionend', 'transitionrun', 'transitioncancel',
318
+
319
+ // Pointer Events (Modern browsers)
320
+ 'pointerdown', 'pointerup', 'pointermove', 'pointerover', 'pointerout',
321
+ 'pointerenter', 'pointerleave', 'pointercancel', 'gotpointercapture', 'lostpointercapture',
322
+
323
+ // Fullscreen Events
324
+ 'fullscreenchange', 'fullscreenerror',
325
+
326
+ // Clipboard Events
327
+ 'copy', 'cut', 'paste',
328
+
329
+ // Gamepad Events
330
+ 'gamepadconnected', 'gamepaddisconnected',
331
+
332
+ // Battery Events
333
+ 'batterychargingchange', 'batterylevelchange',
334
+
335
+ // Device Orientation Events
336
+ 'deviceorientation', 'devicemotion', 'devicelight', 'deviceproximity',
337
+
338
+ // WebGL Events
339
+ 'webglcontextlost', 'webglcontextrestored'
340
+ ];
341
+
342
+ let result = line;
343
+ let changed = false;
344
+
345
+ // Process all event directives in the line
346
+ for (const eventType of eventTypes) {
347
+ // Check for @eventType(...) pattern with balanced parentheses
348
+ const pattern = new RegExp(`@${eventType}\\s*\\(`, 'i');
349
+ const match = result.match(pattern);
350
+ if (match) {
351
+ // Extract content within balanced parentheses
352
+ const startPos = match.index + match[0].length - 1; // Position of opening parenthesis
353
+ const [content, endPos] = extractBalancedParentheses(result, startPos);
354
+ if (content !== null) {
355
+ // Replace only the directive part, keep the rest of the HTML
356
+ const eventConfig = this.eventProcessor.processEventDirective(eventType, content);
357
+ // Replace @eventType(...) with event config using balanced parentheses
358
+ const startPos = match.index;
359
+ const endPos = startPos + match[0].length + content.length + 1; // +1 for closing )
360
+ result = result.substring(0, startPos) + eventConfig + result.substring(endPos);
361
+ changed = true;
362
+ }
363
+ }
364
+ }
365
+
366
+ return changed ? result : null;
367
+ }
368
+ }
369
+
370
+ module.exports = TemplateProcessor;
371
+
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Template Processors
3
+ * Handles template line processing and directives
4
+ */
5
+
6
+ class TemplateProcessors {
7
+ constructor() {
8
+ // Initialize processors
9
+ }
10
+
11
+ /**
12
+ * Process template line
13
+ * Handles @serverside and @clientside directives
14
+ */
15
+ processTemplateLine(line) {
16
+ if (!line || typeof line !== 'string') {
17
+ return line;
18
+ }
19
+
20
+ // Process server-side content
21
+ let processed = this.processServersideDirective(line);
22
+
23
+ // Process client-side content
24
+ processed = this.processClientsideDirective(processed);
25
+
26
+ return processed;
27
+ }
28
+
29
+ /**
30
+ * Process @serverside directive
31
+ * Replaces @serverside(...) with its content
32
+ */
33
+ processServersideDirective(line) {
34
+ const pattern = /@serverside\s*\(/g;
35
+ let match;
36
+ let result = line;
37
+
38
+ while ((match = pattern.exec(result)) !== null) {
39
+ const startPos = match.index + match[0].length - 1;
40
+ const content = this._extractBalancedParentheses(result, startPos);
41
+
42
+ if (content !== null) {
43
+ // Replace @serverside(...) with just the content
44
+ const fullMatch = result.substring(match.index, startPos + content.length + 2);
45
+ result = result.replace(fullMatch, content);
46
+ pattern.lastIndex = 0; // Reset regex
47
+ } else {
48
+ break;
49
+ }
50
+ }
51
+
52
+ return result;
53
+ }
54
+
55
+ /**
56
+ * Process @clientside directive
57
+ * Replaces @clientside(...) with empty string (client-only content)
58
+ */
59
+ processClientsideDirective(line) {
60
+ const pattern = /@clientside\s*\(/g;
61
+ let match;
62
+ let result = line;
63
+
64
+ while ((match = pattern.exec(result)) !== null) {
65
+ const startPos = match.index + match[0].length - 1;
66
+ const content = this._extractBalancedParentheses(result, startPos);
67
+
68
+ if (content !== null) {
69
+ // Remove @clientside(...) entirely for SSR
70
+ const fullMatch = result.substring(match.index, startPos + content.length + 2);
71
+ result = result.replace(fullMatch, '');
72
+ pattern.lastIndex = 0; // Reset regex
73
+ } else {
74
+ break;
75
+ }
76
+ }
77
+
78
+ return result;
79
+ }
80
+
81
+ /**
82
+ * Extract content within balanced parentheses
83
+ * Returns the content without outer parentheses
84
+ */
85
+ _extractBalancedParentheses(str, startPos) {
86
+ if (str[startPos] !== '(') {
87
+ return null;
88
+ }
89
+
90
+ let depth = 0;
91
+ let inSingleQuote = false;
92
+ let inDoubleQuote = false;
93
+ let escaped = false;
94
+
95
+ for (let i = startPos; i < str.length; i++) {
96
+ const char = str[i];
97
+
98
+ if (escaped) {
99
+ escaped = false;
100
+ continue;
101
+ }
102
+
103
+ if (char === '\\') {
104
+ escaped = true;
105
+ continue;
106
+ }
107
+
108
+ if (char === "'" && !inDoubleQuote) {
109
+ inSingleQuote = !inSingleQuote;
110
+ continue;
111
+ }
112
+
113
+ if (char === '"' && !inSingleQuote) {
114
+ inDoubleQuote = !inDoubleQuote;
115
+ continue;
116
+ }
117
+
118
+ if (!inSingleQuote && !inDoubleQuote) {
119
+ if (char === '(') {
120
+ depth++;
121
+ } else if (char === ')') {
122
+ depth--;
123
+ if (depth === 0) {
124
+ // Found matching closing parenthesis
125
+ return str.substring(startPos + 1, i);
126
+ }
127
+ }
128
+ }
129
+ }
130
+
131
+ return null; // Unbalanced parentheses
132
+ }
133
+
134
+ /**
135
+ * Split string by delimiter at top level only
136
+ * Ignores delimiters inside parentheses, brackets, braces, and quotes
137
+ */
138
+ _splitTopLevel(str, delimiter) {
139
+ const parts = [];
140
+ let buffer = '';
141
+ let depthParen = 0;
142
+ let depthBracket = 0;
143
+ let depthBrace = 0;
144
+ let inSingleQuote = false;
145
+ let inDoubleQuote = false;
146
+
147
+ let i = 0;
148
+ const delimLen = delimiter.length;
149
+
150
+ while (i < str.length) {
151
+ const char = str[i];
152
+
153
+ // Handle escape sequences
154
+ if (char === '\\' && i + 1 < str.length) {
155
+ buffer += char + str[i + 1];
156
+ i += 2;
157
+ continue;
158
+ }
159
+
160
+ // Handle quotes
161
+ if (inSingleQuote) {
162
+ buffer += char;
163
+ if (char === "'") inSingleQuote = false;
164
+ i++;
165
+ continue;
166
+ }
167
+
168
+ if (inDoubleQuote) {
169
+ buffer += char;
170
+ if (char === '"') inDoubleQuote = false;
171
+ i++;
172
+ continue;
173
+ }
174
+
175
+ if (char === "'") {
176
+ inSingleQuote = true;
177
+ buffer += char;
178
+ i++;
179
+ continue;
180
+ }
181
+
182
+ if (char === '"') {
183
+ inDoubleQuote = true;
184
+ buffer += char;
185
+ i++;
186
+ continue;
187
+ }
188
+
189
+ // Track nesting depth
190
+ if (char === '(') depthParen++;
191
+ else if (char === ')') depthParen = Math.max(0, depthParen - 1);
192
+ else if (char === '[') depthBracket++;
193
+ else if (char === ']') depthBracket = Math.max(0, depthBracket - 1);
194
+ else if (char === '{') depthBrace++;
195
+ else if (char === '}') depthBrace = Math.max(0, depthBrace - 1);
196
+
197
+ // Check for delimiter at top level
198
+ if (depthParen === 0 && depthBracket === 0 && depthBrace === 0) {
199
+ if (str.substring(i, i + delimLen) === delimiter) {
200
+ parts.push(buffer);
201
+ buffer = '';
202
+ i += delimLen;
203
+ continue;
204
+ }
205
+ }
206
+
207
+ buffer += char;
208
+ i++;
209
+ }
210
+
211
+ if (buffer !== '') {
212
+ parts.push(buffer);
213
+ }
214
+
215
+ return parts;
216
+ }
217
+ }
218
+
219
+ module.exports = TemplateProcessors;