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,358 @@
1
+ /**
2
+ * Parsers for directives (@extends, @vars, @fetch, @onInit)
3
+ */
4
+
5
+ const { extractBalancedParentheses } = require('./utils');
6
+ const { phpToJs, convertPhpArrayToJson } = require('./php-converter');
7
+
8
+ class DirectiveParsers {
9
+ constructor() {
10
+ // No initialization needed
11
+ }
12
+
13
+ _removeScriptTags(bladeCode) {
14
+ /** Remove JavaScript code in <script> tags to avoid processing useState in JS */
15
+ // Remove all content in <script> tags
16
+ const filteredCode = bladeCode.replace(/<script[^>]*>.*?<\/script>/gis, '');
17
+ return filteredCode;
18
+ }
19
+
20
+ parseExtends(bladeCode) {
21
+ /** Parse @extends directive */
22
+ const extendsMatch = bladeCode.match(/@extends\s*\(\s*([^)]+)\s*\)/s);
23
+ if (!extendsMatch) {
24
+ return { extendedView: null, extendsExpression: null, extendsData: null };
25
+ }
26
+
27
+ let extendsContent = extendsMatch[1].trim();
28
+
29
+ // Check if there's a comma (indicating data parameter)
30
+ const commaPos = extendsContent.indexOf(',');
31
+ let viewExpr, dataExpr, extendsData;
32
+
33
+ if (commaPos !== -1) {
34
+ viewExpr = extendsContent.substring(0, commaPos).trim();
35
+ dataExpr = extendsContent.substring(commaPos + 1).trim();
36
+ extendsData = this._convertExtendsData(dataExpr);
37
+ } else {
38
+ viewExpr = extendsContent;
39
+ extendsData = null;
40
+ }
41
+
42
+ // Check if it's a simple string literal (avoid $ issues)
43
+ const dollarChar = '$';
44
+ let extendedView, extendsExpression;
45
+
46
+ if ((viewExpr.startsWith('"') && viewExpr.endsWith('"') && !viewExpr.includes(dollarChar)) ||
47
+ (viewExpr.startsWith("'") && viewExpr.endsWith("'") && !viewExpr.includes(dollarChar))) {
48
+ extendedView = viewExpr.slice(1, -1); // Remove quotes
49
+ extendsExpression = null;
50
+ } else {
51
+ // Complex expression - need to evaluate at runtime
52
+ if (viewExpr.startsWith('"') && viewExpr.endsWith('"')) {
53
+ const innerContent = viewExpr.slice(1, -1);
54
+ const processedContent = innerContent.replace(/\$(\w+)/g, '${$1}');
55
+ extendsExpression = "`" + processedContent + "`";
56
+ } else {
57
+ extendsExpression = phpToJs(viewExpr);
58
+ }
59
+ extendedView = null;
60
+ }
61
+
62
+ return { extendedView, extendsExpression, extendsData };
63
+ }
64
+
65
+ parseVars(bladeCode) {
66
+ /** Parse @vars directive - improved to handle complex arrays like Event directive */
67
+ const varsMatch = bladeCode.match(/@vars\s*\(\s*(.*?)\s*\)/s);
68
+ if (!varsMatch) {
69
+ return '';
70
+ }
71
+
72
+ const varsContent = varsMatch[1];
73
+ const varParts = [];
74
+
75
+ // Special handling for object destructuring syntax {var1, var2}
76
+ const trimmedContent = varsContent.trim();
77
+ let parts;
78
+
79
+ if (trimmedContent.startsWith('{') && trimmedContent.endsWith('}')) {
80
+ // Extract content inside braces
81
+ const innerContent = trimmedContent.slice(1, -1);
82
+ // Split by comma at level 0
83
+ parts = this._splitVarsContentCorrect(innerContent);
84
+ } else {
85
+ // Use improved splitting logic (same as Event directive)
86
+ parts = this._splitVarsContentCorrect(varsContent);
87
+ }
88
+
89
+ for (const varItem of parts) {
90
+ const varStr = varItem.trim();
91
+ if (varStr.includes('=')) {
92
+ const equalsPos = this._findFirstEquals(varStr);
93
+ if (equalsPos !== -1) {
94
+ const varName = varStr.substring(0, equalsPos).trim().replace(/^\$/, '');
95
+ const varValue = varStr.substring(equalsPos + 1).trim();
96
+ // Convert PHP array syntax to JavaScript
97
+ const convertedValue = this._convertPhpToJs(varValue);
98
+ varParts.push(`${varName} = ${convertedValue}`);
99
+ } else {
100
+ const varName = varStr.trim().replace(/^\$/, '');
101
+ varParts.push(varName);
102
+ }
103
+ } else {
104
+ const varName = varStr.trim().replace(/^\$/, '');
105
+ varParts.push(varName);
106
+ }
107
+ }
108
+
109
+ return `let {${varParts.join(', ')}} = $$$DATA$$$ || {};`;
110
+ }
111
+
112
+ parseLetDirectives(bladeCode) {
113
+ /** Parse @let directives - only process Blade directives, not JavaScript code */
114
+ // Remove JavaScript code in <script> tags before parsing
115
+ const bladeCodeFiltered = this._removeScriptTags(bladeCode);
116
+
117
+ // Use balanced parentheses to parse correctly
118
+ const letMatches = [];
119
+ const letPattern = /@let\s*\(/g;
120
+ let match;
121
+
122
+ while ((match = letPattern.exec(bladeCodeFiltered)) !== null) {
123
+ const startPos = match.index + match[0].length - 1; // Position of opening parenthesis
124
+ const [content, endPos] = extractBalancedParentheses(bladeCodeFiltered, startPos);
125
+
126
+ if (content !== null) {
127
+ letMatches.push(content);
128
+ }
129
+ }
130
+
131
+ const letDeclarations = [];
132
+ for (const match of letMatches) {
133
+ const parts = this._splitVarsContentCorrect(match);
134
+ for (const part of parts) {
135
+ const trimmedPart = part.trim();
136
+ if (trimmedPart) {
137
+ letDeclarations.push(`let ${trimmedPart};`);
138
+ }
139
+ }
140
+ }
141
+
142
+ return letDeclarations;
143
+ }
144
+
145
+ parseConstDirectives(bladeCode) {
146
+ /** Parse @const directives */
147
+ const constMatches = [];
148
+ const constPattern = /@const\s*\(/g;
149
+ let match;
150
+
151
+ while ((match = constPattern.exec(bladeCode)) !== null) {
152
+ const startPos = match.index + match[0].length - 1;
153
+ const [content, endPos] = extractBalancedParentheses(bladeCode, startPos);
154
+
155
+ if (content !== null) {
156
+ constMatches.push(content);
157
+ }
158
+ }
159
+
160
+ const constDeclarations = [];
161
+ for (const match of constMatches) {
162
+ const parts = this._splitVarsContentCorrect(match);
163
+ for (const part of parts) {
164
+ const trimmedPart = part.trim();
165
+ if (trimmedPart) {
166
+ constDeclarations.push(`const ${trimmedPart};`);
167
+ }
168
+ }
169
+ }
170
+
171
+ return constDeclarations;
172
+ }
173
+
174
+ parseUseStateDirectives(bladeCode) {
175
+ /** Parse @useState directives */
176
+ const useStateMatches = [];
177
+ const useStatePattern = /@useState\s*\(/g;
178
+ let match;
179
+
180
+ while ((match = useStatePattern.exec(bladeCode)) !== null) {
181
+ const startPos = match.index + match[0].length - 1;
182
+ const [content, endPos] = extractBalancedParentheses(bladeCode, startPos);
183
+
184
+ if (content !== null) {
185
+ useStateMatches.push(content);
186
+ }
187
+ }
188
+
189
+ const useStateDeclarations = [];
190
+ for (const match of useStateMatches) {
191
+ const parts = this._splitVarsContentCorrect(match);
192
+ for (const part of parts) {
193
+ const trimmedPart = part.trim();
194
+ if (trimmedPart) {
195
+ useStateDeclarations.push(`const [${trimmedPart}] = this.useState(${trimmedPart} || null);`);
196
+ }
197
+ }
198
+ }
199
+
200
+ return useStateDeclarations;
201
+ }
202
+
203
+ parseFetch(bladeCode) {
204
+ /** Parse @fetch directive */
205
+ const fetchMatch = bladeCode.match(/@fetch\s*\(\s*(.*?)\s*\)/s);
206
+ if (!fetchMatch) {
207
+ return null;
208
+ }
209
+
210
+ const fetchContent = fetchMatch[1];
211
+ try {
212
+ // Try to parse as JSON first
213
+ return JSON.parse(fetchContent);
214
+ } catch (e) {
215
+ // If not valid JSON, treat as JavaScript expression
216
+ return fetchContent;
217
+ }
218
+ }
219
+
220
+ parseInit(bladeCode) {
221
+ /** Parse @onInit directive */
222
+ const initMatches = [];
223
+ const initPattern = /@onInit\s*\(\s*(.*?)\s*\)/gs;
224
+ let match;
225
+
226
+ while ((match = initPattern.exec(bladeCode)) !== null) {
227
+ initMatches.push(match[1]);
228
+ }
229
+
230
+ const initFunctions = [];
231
+ const cssContent = [];
232
+
233
+ for (const initContent of initMatches) {
234
+ // Check if it contains CSS
235
+ if (initContent.includes('addCSS') || initContent.includes('style')) {
236
+ cssContent.push(initContent);
237
+ } else {
238
+ initFunctions.push(initContent);
239
+ }
240
+ }
241
+
242
+ return { initFunctions, cssContent };
243
+ }
244
+
245
+ parseViewType(bladeCode) {
246
+ /** Parse @viewType directive */
247
+ const viewTypeMatch = bladeCode.match(/@viewType\s*\(\s*([^)]+)\s*\)/);
248
+ if (!viewTypeMatch) {
249
+ return { type: 'component' };
250
+ }
251
+
252
+ const viewTypeContent = viewTypeMatch[1].trim().replace(/['"]/g, '');
253
+ return { type: viewTypeContent };
254
+ }
255
+
256
+ parseRegister(bladeCode) {
257
+ /** Parse @register directive */
258
+ const registerMatch = bladeCode.match(/@register\s*\(\s*(.*?)\s*\)/s);
259
+ if (!registerMatch) {
260
+ return '';
261
+ }
262
+
263
+ return registerMatch[1];
264
+ }
265
+
266
+ parseWrapper(bladeCode) {
267
+ /** Parse @wrapper directive */
268
+ const wrapperMatch = bladeCode.match(/@wrapper\s*\(\s*(.*?)\s*\)/s);
269
+ if (!wrapperMatch) {
270
+ return '';
271
+ }
272
+
273
+ return wrapperMatch[1];
274
+ }
275
+
276
+ _splitVarsContentCorrect(content) {
277
+ /** Split content by comma, respecting nested parentheses and quotes */
278
+ const result = [];
279
+ let current = '';
280
+ let depth = 0;
281
+ let inQuotes = false;
282
+ let quoteChar = '';
283
+
284
+ for (let i = 0; i < content.length; i++) {
285
+ const char = content[i];
286
+
287
+ if (!inQuotes && (char === '"' || char === "'")) {
288
+ inQuotes = true;
289
+ quoteChar = char;
290
+ } else if (inQuotes && char === quoteChar) {
291
+ inQuotes = false;
292
+ quoteChar = '';
293
+ } else if (!inQuotes && char === '(') {
294
+ depth++;
295
+ } else if (!inQuotes && char === ')') {
296
+ depth--;
297
+ } else if (!inQuotes && depth === 0 && char === ',') {
298
+ result.push(current.trim());
299
+ current = '';
300
+ continue;
301
+ }
302
+
303
+ current += char;
304
+ }
305
+
306
+ if (current.trim()) {
307
+ result.push(current.trim());
308
+ }
309
+
310
+ return result;
311
+ }
312
+
313
+ _findFirstEquals(str) {
314
+ /** Find first equals sign not inside quotes or parentheses */
315
+ let depth = 0;
316
+ let inQuotes = false;
317
+ let quoteChar = '';
318
+
319
+ for (let i = 0; i < str.length; i++) {
320
+ const char = str[i];
321
+
322
+ if (!inQuotes && (char === '"' || char === "'")) {
323
+ inQuotes = true;
324
+ quoteChar = char;
325
+ } else if (inQuotes && char === quoteChar) {
326
+ inQuotes = false;
327
+ quoteChar = '';
328
+ } else if (!inQuotes && char === '(') {
329
+ depth++;
330
+ } else if (!inQuotes && char === ')') {
331
+ depth--;
332
+ } else if (!inQuotes && depth === 0 && char === '=') {
333
+ return i;
334
+ }
335
+ }
336
+
337
+ return -1;
338
+ }
339
+
340
+ _convertPhpToJs(phpCode) {
341
+ /** Convert PHP code to JavaScript */
342
+ return phpToJs(phpCode);
343
+ }
344
+
345
+ _convertExtendsData(dataExpr) {
346
+ /** Convert extends data expression */
347
+ if (!dataExpr) return null;
348
+
349
+ try {
350
+ return JSON.parse(dataExpr);
351
+ } catch (e) {
352
+ return dataExpr;
353
+ }
354
+ }
355
+ }
356
+
357
+ module.exports = DirectiveParsers;
358
+
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Convert PHP expressions to JavaScript
3
+ */
4
+
5
+ const { JS_FUNCTION_PREFIX } = require('./config');
6
+ const { normalizeQuotes } = require('./utils');
7
+
8
+ function convertPhpArrayToJson(expr) {
9
+ /** Convert PHP array syntax to JSON object/array syntax */
10
+ if (!expr || !expr.includes('[')) {
11
+ return expr;
12
+ }
13
+
14
+ // Find all array patterns and convert them
15
+ function replaceArray(match) {
16
+ const inner = match[1].trim();
17
+ if (!inner) {
18
+ return '[]';
19
+ }
20
+
21
+ // Check if this is array access vs array literal
22
+ if ((("'" in inner && (inner.match(/'/g) || []).length === 2 && !inner.includes('=>')) ||
23
+ ('"' in inner && (inner.match(/"/g) || []).length === 2 && !inner.includes('=>')) ||
24
+ (inner.replace(/[_\.]/g, '').match(/^\w+$/) && !inner.includes('=>')))) {
25
+ return '[' + inner + ']'; // Keep as array access
26
+ }
27
+
28
+ // Process array elements
29
+ const elements = [];
30
+ let currentElement = '';
31
+ let parenCount = 0;
32
+ let bracketCount = 0;
33
+ let inQuotes = false;
34
+ let quoteChar = '';
35
+ let i = 0;
36
+
37
+ while (i < inner.length) {
38
+ const char = inner[i];
39
+
40
+ if ((char === '"' || char === "'") && !inQuotes) {
41
+ inQuotes = true;
42
+ quoteChar = char;
43
+ } else if (char === quoteChar && inQuotes) {
44
+ inQuotes = false;
45
+ quoteChar = '';
46
+ } else if (!inQuotes) {
47
+ if (char === '(') {
48
+ parenCount += 1;
49
+ } else if (char === ')') {
50
+ parenCount -= 1;
51
+ } else if (char === '[') {
52
+ bracketCount += 1;
53
+ } else if (char === ']') {
54
+ bracketCount -= 1;
55
+ } else if (char === ',' && parenCount === 0 && bracketCount === 0) {
56
+ elements.push(currentElement.trim());
57
+ currentElement = '';
58
+ i++;
59
+ continue;
60
+ }
61
+ }
62
+
63
+ currentElement += char;
64
+ i++;
65
+ }
66
+
67
+ if (currentElement.trim()) {
68
+ elements.push(currentElement.trim());
69
+ }
70
+
71
+ // Process each element
72
+ const processedElements = elements.map(element => {
73
+ element = element.trim();
74
+
75
+ // Check if it's a key => value pair
76
+ if (element.includes('=>')) {
77
+ const arrowIndex = element.indexOf('=>');
78
+ const key = element.substring(0, arrowIndex).trim();
79
+ const value = element.substring(arrowIndex + 2).trim();
80
+
81
+ // Process key
82
+ let processedKey = key;
83
+ if ((key.startsWith("'") && key.endsWith("'")) ||
84
+ (key.startsWith('"') && key.endsWith('"'))) {
85
+ processedKey = key; // Keep as string literal
86
+ } else if (key.match(/^\d+$/)) {
87
+ processedKey = key; // Keep as number
88
+ } else {
89
+ processedKey = `"${key}"`; // Convert to string
90
+ }
91
+
92
+ // Process value
93
+ const processedValue = convertPhpArrayToJson(value);
94
+
95
+ return `${processedKey}: ${processedValue}`;
96
+ } else {
97
+ return convertPhpArrayToJson(element);
98
+ }
99
+ });
100
+
101
+ // Check if all elements are key-value pairs
102
+ const hasKeyValuePairs = elements.some(element => element.includes('=>'));
103
+
104
+ if (hasKeyValuePairs) {
105
+ return `{${processedElements.join(', ')}}`;
106
+ } else {
107
+ return `[${processedElements.join(', ')}]`;
108
+ }
109
+ }
110
+
111
+ // Replace array patterns
112
+ return expr.replace(/\[(.*?)\]/g, replaceArray);
113
+ }
114
+
115
+ function phpToJs(phpCode) {
116
+ /** Convert PHP code to JavaScript */
117
+ if (!phpCode) return phpCode;
118
+
119
+ let jsCode = phpCode;
120
+
121
+ // Convert PHP variables ($var -> var)
122
+ jsCode = jsCode.replace(/\$(\w+)/g, '$1');
123
+
124
+ // Convert PHP array syntax to JavaScript
125
+ jsCode = convertPhpArrayToJson(jsCode);
126
+
127
+ // Convert PHP function calls to JavaScript
128
+ jsCode = jsCode.replace(/App\.Helper\.(\w+)/g, `${JS_FUNCTION_PREFIX}.Helper.$1`);
129
+
130
+ // Convert PHP string concatenation
131
+ jsCode = jsCode.replace(/\s*\.\s*/g, ' + ');
132
+
133
+ // Normalize quotes
134
+ jsCode = normalizeQuotes(jsCode);
135
+
136
+ return jsCode;
137
+ }
138
+
139
+ function phpToJsAdvanced(phpCode) {
140
+ /** Advanced PHP to JavaScript conversion */
141
+ if (!phpCode) return phpCode;
142
+
143
+ let jsCode = phpCode;
144
+
145
+ // Convert PHP variables
146
+ jsCode = jsCode.replace(/\$(\w+)/g, '$1');
147
+
148
+ // Convert PHP array syntax
149
+ jsCode = convertPhpArrayToJson(jsCode);
150
+
151
+ // Convert PHP operators
152
+ jsCode = jsCode.replace(/===/g, '===');
153
+ jsCode = jsCode.replace(/!==/g, '!==');
154
+ jsCode = jsCode.replace(/&&/g, '&&');
155
+ jsCode = jsCode.replace(/\|\|/g, '||');
156
+
157
+ // Convert PHP function calls
158
+ jsCode = jsCode.replace(/App\.Helper\.(\w+)/g, `${JS_FUNCTION_PREFIX}.Helper.$1`);
159
+ jsCode = jsCode.replace(/App\.View\.(\w+)/g, `${JS_FUNCTION_PREFIX}.$1`);
160
+
161
+ // Convert string concatenation
162
+ jsCode = jsCode.replace(/\s*\.\s*/g, ' + ');
163
+
164
+ // Convert PHP null coalescing operator
165
+ jsCode = jsCode.replace(/\?\?/g, '||');
166
+
167
+ // Convert PHP ternary operator
168
+ jsCode = jsCode.replace(/\?\s*([^:]+)\s*:\s*([^;]+)/g, '? $1 : $2');
169
+
170
+ // Normalize quotes
171
+ jsCode = normalizeQuotes(jsCode);
172
+
173
+ return jsCode;
174
+ }
175
+
176
+ function convertPhpExpression(expr) {
177
+ /** Convert PHP expression to JavaScript expression */
178
+ if (!expr) return expr;
179
+
180
+ // Handle different types of expressions
181
+ if (expr.includes('[') && expr.includes(']')) {
182
+ // Array expression
183
+ return convertPhpArrayToJson(expr);
184
+ } else if (expr.includes('$')) {
185
+ // Variable expression
186
+ return phpToJs(expr);
187
+ } else {
188
+ // Simple expression
189
+ return expr;
190
+ }
191
+ }
192
+
193
+ function isPhpExpression(expr) {
194
+ /** Check if expression contains PHP syntax */
195
+ return expr.includes('$') || expr.includes('[') || expr.includes('=>');
196
+ }
197
+
198
+ function escapePhpString(str) {
199
+ /** Escape PHP string for JavaScript */
200
+ return str.replace(/\\/g, '\\\\')
201
+ .replace(/'/g, "\\'")
202
+ .replace(/"/g, '\\"')
203
+ .replace(/\n/g, '\\n')
204
+ .replace(/\r/g, '\\r')
205
+ .replace(/\t/g, '\\t');
206
+ }
207
+
208
+ function unescapePhpString(str) {
209
+ /** Unescape PHP string */
210
+ return str.replace(/\\\\/g, '\\')
211
+ .replace(/\\'/g, "'")
212
+ .replace(/\\"/g, '"')
213
+ .replace(/\\n/g, '\n')
214
+ .replace(/\\r/g, '\r')
215
+ .replace(/\\t/g, '\t');
216
+ }
217
+
218
+ module.exports = {
219
+ convertPhpArrayToJson,
220
+ phpToJs,
221
+ phpToJsAdvanced,
222
+ convertPhpExpression,
223
+ isPhpExpression,
224
+ escapePhpString,
225
+ unescapePhpString
226
+ };
227
+
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Register parser
3
+ */
4
+
5
+ class RegisterParser {
6
+ constructor() {
7
+ this.parseRegisterContent = {};
8
+ }
9
+
10
+ parseRegisterContent(registerContent) {
11
+ /** Parse register content */
12
+ if (!registerContent || !registerContent.trim()) {
13
+ return {};
14
+ }
15
+
16
+ try {
17
+ // Try to parse as JSON
18
+ return JSON.parse(registerContent);
19
+ } catch (e) {
20
+ // If not valid JSON, return empty object
21
+ return {};
22
+ }
23
+ }
24
+
25
+ reset() {
26
+ /** Reset parser state */
27
+ this.parseRegisterContent = {};
28
+ }
29
+ }
30
+
31
+ module.exports = RegisterParser;
32
+
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Section handlers for @section, @yield, etc.
3
+ */
4
+
5
+ class SectionHandlers {
6
+ constructor() {
7
+ // No initialization needed
8
+ }
9
+
10
+ processSectionDirective(line, stack, output, sections) {
11
+ /** Process section directives */
12
+ const trimmedLine = line.trim();
13
+
14
+ if (trimmedLine.startsWith('@section')) {
15
+ const match = trimmedLine.match(/@section\s*\(\s*['"]([^'"]+)['"]\s*\)/);
16
+ if (match) {
17
+ const sectionName = match[1];
18
+ sections.push({
19
+ name: sectionName,
20
+ type: 'long',
21
+ preloader: false,
22
+ useVars: false,
23
+ script: {}
24
+ });
25
+ stack.push(['section', sectionName]);
26
+ }
27
+ return null;
28
+ } else if (trimmedLine.startsWith('@endsection')) {
29
+ if (stack.length > 0 && stack[stack.length - 1][0] === 'section') {
30
+ stack.pop();
31
+ }
32
+ return null;
33
+ } else if (trimmedLine.startsWith('@yield')) {
34
+ const match = trimmedLine.match(/@yield\s*\(\s*['"]([^'"]+)['"]\s*\)/);
35
+ if (match) {
36
+ const sectionName = match[1];
37
+ return `\${App.View.yield('${sectionName}')}`;
38
+ }
39
+ }
40
+
41
+ return null;
42
+ }
43
+ }
44
+
45
+ module.exports = SectionHandlers;
46
+