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.
- package/README.md +1 -1
- package/bin/onejs-build.js +32 -0
- package/index.js +3 -1
- package/package.json +11 -3
- package/scripts/README-template-compiler.md +133 -0
- package/scripts/README.md +61 -0
- package/scripts/__pycache__/build.cpython-314.pyc +0 -0
- package/scripts/__pycache__/compile.cpython-313.pyc +0 -0
- package/scripts/__pycache__/compile.cpython-314.pyc +0 -0
- package/scripts/build.py +574 -0
- package/scripts/check-system-errors.php +214 -0
- package/scripts/compile.py +101 -0
- package/scripts/compiler/README_CONFIG.md +196 -0
- package/scripts/compiler/__init__.py +18 -0
- package/scripts/compiler/__pycache__/__init__.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/__init__.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/binding_directive_service.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/class_binding_handler.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/compiler_utils.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/compiler_utils.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/conditional_handlers.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/conditional_handlers.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/config.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/config.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/declaration_tracker.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/directive_processors.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/directive_processors.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/echo_processor.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/event_directive_processor.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/event_directive_processor.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/function_generators.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/function_generators.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/loop_handlers.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/loop_handlers.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/main_compiler.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/main_compiler.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/parsers.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/parsers.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/php_converter.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/php_converter.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/php_js_converter.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/php_js_converter.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/register_parser.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/register_parser.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/section_handlers.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/section_handlers.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/show_directive_handler.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/style_directive_handler.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/template_analyzer.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/template_analyzer.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/template_processor.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/template_processor.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/template_processors.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/template_processors.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/utils.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/utils.cpython-314.pyc +0 -0
- package/scripts/compiler/__pycache__/wrapper_parser.cpython-313.pyc +0 -0
- package/scripts/compiler/__pycache__/wrapper_parser.cpython-314.pyc +0 -0
- package/scripts/compiler/binding_directive_service.py +103 -0
- package/scripts/compiler/class_binding_handler.py +347 -0
- package/scripts/compiler/cli.py +34 -0
- package/scripts/compiler/code_generator.py +141 -0
- package/scripts/compiler/compiler.config.json +36 -0
- package/scripts/compiler/compiler_utils.py +55 -0
- package/scripts/compiler/conditional_handlers.py +252 -0
- package/scripts/compiler/config.py +107 -0
- package/scripts/compiler/declaration_tracker.py +420 -0
- package/scripts/compiler/directive_processors.py +603 -0
- package/scripts/compiler/echo_processor.py +667 -0
- package/scripts/compiler/event_directive_processor.py +1099 -0
- package/scripts/compiler/fetch_parser.py +49 -0
- package/scripts/compiler/function_generators.py +310 -0
- package/scripts/compiler/loop_handlers.py +224 -0
- package/scripts/compiler/main_compiler.py +1763 -0
- package/scripts/compiler/parsers.py +1418 -0
- package/scripts/compiler/php_converter.py +470 -0
- package/scripts/compiler/php_js_converter.py +603 -0
- package/scripts/compiler/register_parser.py +480 -0
- package/scripts/compiler/section_handlers.py +122 -0
- package/scripts/compiler/show_directive_handler.py +85 -0
- package/scripts/compiler/style_directive_handler.py +169 -0
- package/scripts/compiler/template_analyzer.py +162 -0
- package/scripts/compiler/template_processor.py +1167 -0
- package/scripts/compiler/template_processors.py +1557 -0
- package/scripts/compiler/test_compiler.py +69 -0
- package/scripts/compiler/utils.py +54 -0
- package/scripts/compiler/variables_analyzer.py +135 -0
- package/scripts/compiler/view_identifier_generator.py +278 -0
- package/scripts/compiler/wrapper_parser.py +78 -0
- package/scripts/dev-context.js +311 -0
- package/scripts/dev.js +109 -0
- package/scripts/generate-assets-order.js +208 -0
- package/scripts/migrate-namespace.php +146 -0
- package/scripts/node/MIGRATION.md +190 -0
- package/scripts/node/README.md +269 -0
- package/scripts/node/build.js +208 -0
- package/scripts/node/compiler/compiler-utils.js +38 -0
- package/scripts/node/compiler/conditional-handlers.js +45 -0
- package/scripts/node/compiler/config.js +178 -0
- package/scripts/node/compiler/directive-processors.js +51 -0
- package/scripts/node/compiler/event-directive-processor.js +182 -0
- package/scripts/node/compiler/function-generators.js +239 -0
- package/scripts/node/compiler/loop-handlers.js +45 -0
- package/scripts/node/compiler/main-compiler.js +236 -0
- package/scripts/node/compiler/parsers.js +358 -0
- package/scripts/node/compiler/php-converter.js +227 -0
- package/scripts/node/compiler/register-parser.js +32 -0
- package/scripts/node/compiler/section-handlers.js +46 -0
- package/scripts/node/compiler/template-analyzer.js +50 -0
- package/scripts/node/compiler/template-processor.js +371 -0
- package/scripts/node/compiler/template-processors.js +219 -0
- package/scripts/node/compiler/utils.js +203 -0
- package/scripts/node/compiler/wrapper-parser.js +25 -0
- package/scripts/node/package.json +24 -0
- package/scripts/node/test-compiler.js +52 -0
- package/scripts/node-run.cjs +28 -0
- package/scripts/standardize-directories.php +92 -0
- package/src/core/ViewManager.js +4 -4
- package/templates/view.module.js +2 -0
- package/templates/view.tpl-raw.js +13 -0
- 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;
|