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.
- package/README.md +1 -1
- package/bin/onejs-build.js +32 -0
- 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 +573 -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 +200 -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/templates/view.module.js +2 -0
- package/templates/view.tpl-raw.js +13 -0
- package/templates/wraper.js +71 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generators for functions (render, prerender, init, etc.)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const { JS_FUNCTION_PREFIX, HTML_ATTR_PREFIX } = require('./config');
|
|
6
|
+
|
|
7
|
+
class FunctionGenerators {
|
|
8
|
+
constructor() {
|
|
9
|
+
// No initialization needed
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
generateRenderFunction(templateContent, varsDeclaration, extendedView, extendsData, sectionsInfo = null, hasPrerender = false, setupScript = "", directivesLine = "") {
|
|
13
|
+
/** Generate render function */
|
|
14
|
+
const varsLine = varsDeclaration ? " " + varsDeclaration + "\n" : "";
|
|
15
|
+
const viewIdLine = " \n";
|
|
16
|
+
|
|
17
|
+
// Filter out sections that are already in prerender
|
|
18
|
+
// Only filter if hasPrerender is true (meaning some sections are in prerender)
|
|
19
|
+
let filteredTemplate = templateContent;
|
|
20
|
+
if (sectionsInfo && hasPrerender) {
|
|
21
|
+
for (const section of sectionsInfo) {
|
|
22
|
+
const sectionName = section.name;
|
|
23
|
+
const useVars = section.useVars || false;
|
|
24
|
+
const preloader = section.preloader || false;
|
|
25
|
+
const sectionType = section.type || 'long';
|
|
26
|
+
|
|
27
|
+
// Remove sections that are already in prerender
|
|
28
|
+
// Only remove static sections (not using vars) that are in prerender
|
|
29
|
+
if (!useVars) {
|
|
30
|
+
if (sectionType === 'short') {
|
|
31
|
+
const pattern = new RegExp(`\\$\\{${JS_FUNCTION_PREFIX}\\.section\\(['"]${sectionName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}['"],\\s*[^)]+\\)\\}`, 'g');
|
|
32
|
+
filteredTemplate = filteredTemplate.replace(pattern, '');
|
|
33
|
+
} else { // long section
|
|
34
|
+
const pattern = new RegExp(`\\$\\{${JS_FUNCTION_PREFIX}\\.section\\(['"]${sectionName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}['"],\\s*\`[^\`]*\`,\\s*['"]html['"]\\)\\}`, 'gs');
|
|
35
|
+
filteredTemplate = filteredTemplate.replace(pattern, '');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// If section uses vars, keep it in render (dynamic sections)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// No need to escape template content as it's already processed correctly
|
|
43
|
+
const filteredTemplateEscaped = filteredTemplate;
|
|
44
|
+
|
|
45
|
+
// Add setup script but remove useState declarations if register & update mechanism exists
|
|
46
|
+
let setupLine = "";
|
|
47
|
+
if (setupScript) {
|
|
48
|
+
// Check if register & update mechanism exists (has updateStateByKey)
|
|
49
|
+
const hasRegisterUpdate = directivesLine && directivesLine.includes('updateStateByKey');
|
|
50
|
+
|
|
51
|
+
if (hasRegisterUpdate) {
|
|
52
|
+
// If register & update mechanism exists, remove useState declarations from setup script
|
|
53
|
+
// Only remove useState declarations that have state key already registered
|
|
54
|
+
let filteredSetup = setupScript;
|
|
55
|
+
// Filter logic here if needed
|
|
56
|
+
setupLine = filteredSetup ? " " + filteredSetup + "\n" : "";
|
|
57
|
+
} else {
|
|
58
|
+
setupLine = " " + setupScript + "\n";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (extendedView) {
|
|
63
|
+
const dataParam = extendsData ? ", " + extendsData : "";
|
|
64
|
+
return `function(__$spaViewData$__ = {}) {
|
|
65
|
+
${varsLine}${directivesLine}${viewIdLine}${setupLine} let __outputRenderedContent__ = '';
|
|
66
|
+
try {
|
|
67
|
+
__outputRenderedContent__ = \`${filteredTemplateEscaped}\`;
|
|
68
|
+
} catch(e) {
|
|
69
|
+
__outputRenderedContent__ = this.showError(e.message);
|
|
70
|
+
}
|
|
71
|
+
return ${JS_FUNCTION_PREFIX}.extendView('${extendedView}'${dataParam});
|
|
72
|
+
}`;
|
|
73
|
+
} else {
|
|
74
|
+
return `function(__$spaViewData$__ = {}) {
|
|
75
|
+
${varsLine}${directivesLine}${viewIdLine}${setupLine} let __outputRenderedContent__ = '';
|
|
76
|
+
try {
|
|
77
|
+
__outputRenderedContent__ = \`${filteredTemplateEscaped}\`;
|
|
78
|
+
} catch(e) {
|
|
79
|
+
__outputRenderedContent__ = this.showError(e.message);
|
|
80
|
+
}
|
|
81
|
+
return __outputRenderedContent__;
|
|
82
|
+
}`;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
generateLoadServerDataFunction(varsDeclaration, setupScript = "", directivesLine = "") {
|
|
87
|
+
/** Generate loadServerData function - similar to render but without template content and return */
|
|
88
|
+
const varsLine = varsDeclaration ? " " + varsDeclaration + "\n" : "";
|
|
89
|
+
const viewIdLine = " \n";
|
|
90
|
+
|
|
91
|
+
let setupLine = "";
|
|
92
|
+
if (setupScript) {
|
|
93
|
+
// Filter setup script to remove useState declarations if needed
|
|
94
|
+
const filteredSetup = setupScript;
|
|
95
|
+
setupLine = filteredSetup.trim() ? " " + filteredSetup + "\n" : "";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return `function(__$spaViewData$__ = {}) {
|
|
99
|
+
${varsLine}${directivesLine}${viewIdLine}${setupLine} // Load server data - no template content needed
|
|
100
|
+
// This function is only for loading data when view is rendered from server
|
|
101
|
+
}`;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
generatePrerenderFunction(hasAwait, hasFetch, varsLine, viewIdLine, templateContent, extendedView = null, extendsData = null, sectionsInfo = null, conditionalContent = null, hasPrerender = true) {
|
|
105
|
+
/** Generate prerender function */
|
|
106
|
+
if (hasAwait || hasFetch) {
|
|
107
|
+
if (extendedView) {
|
|
108
|
+
const dataParam = extendsData ? ", " + extendsData : "";
|
|
109
|
+
return `function(__$spaViewData$__ = {}) {
|
|
110
|
+
${varsLine}${viewIdLine} let __outputRenderedContent__ = '';
|
|
111
|
+
try {
|
|
112
|
+
__outputRenderedContent__ = \`<div class="${HTML_ATTR_PREFIX}preloader" ref="\${__VIEW_ID__}" data-view-name="\${__VIEW_PATH__}">\${${JS_FUNCTION_PREFIX}.text('loading')}</div>\`;
|
|
113
|
+
} catch(e) {
|
|
114
|
+
__outputRenderedContent__ = this.showError(e.message);
|
|
115
|
+
}
|
|
116
|
+
return ${JS_FUNCTION_PREFIX}.extendView('${extendedView}'${dataParam});
|
|
117
|
+
}`;
|
|
118
|
+
} else {
|
|
119
|
+
return `function(__$spaViewData$__ = {}) {
|
|
120
|
+
${varsLine}${viewIdLine} let __outputRenderedContent__ = '';
|
|
121
|
+
try {
|
|
122
|
+
__outputRenderedContent__ = \`<div class="${HTML_ATTR_PREFIX}preloader" ref="\${__VIEW_ID__}" data-view-name="\${__VIEW_PATH__}">\${${JS_FUNCTION_PREFIX}.text('loading')}</div>\`;
|
|
123
|
+
} catch(e) {
|
|
124
|
+
__outputRenderedContent__ = this.showError(e.message);
|
|
125
|
+
}
|
|
126
|
+
return __outputRenderedContent__;
|
|
127
|
+
}`;
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
// No await/fetch - use conditional content or empty
|
|
131
|
+
const content = conditionalContent || '';
|
|
132
|
+
|
|
133
|
+
if (extendedView) {
|
|
134
|
+
const dataParam = extendsData ? ", " + extendsData : "";
|
|
135
|
+
return `function(__$spaViewData$__ = {}) {
|
|
136
|
+
${varsLine}${viewIdLine} let __outputRenderedContent__ = '';
|
|
137
|
+
try {
|
|
138
|
+
__outputRenderedContent__ = \`${content}\`;
|
|
139
|
+
} catch(e) {
|
|
140
|
+
__outputRenderedContent__ = this.showError(e.message);
|
|
141
|
+
}
|
|
142
|
+
return ${JS_FUNCTION_PREFIX}.extendView('${extendedView}'${dataParam});
|
|
143
|
+
}`;
|
|
144
|
+
} else {
|
|
145
|
+
return `function(__$spaViewData$__ = {}) {
|
|
146
|
+
${varsLine}${viewIdLine} let __outputRenderedContent__ = '';
|
|
147
|
+
try {
|
|
148
|
+
__outputRenderedContent__ = \`${content}\`;
|
|
149
|
+
} catch(e) {
|
|
150
|
+
__outputRenderedContent__ = this.showError(e.message);
|
|
151
|
+
}
|
|
152
|
+
return __outputRenderedContent__;
|
|
153
|
+
}`;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
generateCssFunctions(viewName, cssContent = null) {
|
|
159
|
+
/** Generate CSS functions (addCSS, removeCSS) */
|
|
160
|
+
if (cssContent && cssContent.length > 0) {
|
|
161
|
+
// Separate inline CSS and external CSS
|
|
162
|
+
const inlineCss = [];
|
|
163
|
+
const externalCss = [];
|
|
164
|
+
|
|
165
|
+
for (const css of cssContent) {
|
|
166
|
+
if (css.startsWith('<link') || css.includes('href=')) {
|
|
167
|
+
externalCss.push(css);
|
|
168
|
+
} else {
|
|
169
|
+
inlineCss.push(css);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const addCssFunction = `,
|
|
174
|
+
addCSS: function() {
|
|
175
|
+
${inlineCss.length > 0 ? `
|
|
176
|
+
const style = document.createElement('style');
|
|
177
|
+
style.setAttribute('data-view-name', '${viewName}');
|
|
178
|
+
style.textContent = \`${inlineCss.join('\n')}\`;
|
|
179
|
+
document.head.appendChild(style);` : ''}
|
|
180
|
+
${externalCss.length > 0 ? `
|
|
181
|
+
const existingLinks = document.querySelectorAll('link[data-view-name="${viewName}"]');
|
|
182
|
+
existingLinks.forEach(link => link.remove());
|
|
183
|
+
${externalCss.map(css => `
|
|
184
|
+
const link = document.createElement('link');
|
|
185
|
+
link.rel = 'stylesheet';
|
|
186
|
+
link.setAttribute('data-view-name', '${viewName}');
|
|
187
|
+
link.href = '${css}';
|
|
188
|
+
document.head.appendChild(link);`).join('')}` : ''}
|
|
189
|
+
}`;
|
|
190
|
+
|
|
191
|
+
const removeCssFunction = `,
|
|
192
|
+
removeCSS: function() {
|
|
193
|
+
const styles = document.querySelectorAll('style[data-view-name="${viewName}"]');
|
|
194
|
+
styles.forEach(style => style.remove());
|
|
195
|
+
const links = document.querySelectorAll('link[data-view-name="${viewName}"]');
|
|
196
|
+
links.forEach(link => link.remove());
|
|
197
|
+
}`;
|
|
198
|
+
|
|
199
|
+
return addCssFunction + removeCssFunction;
|
|
200
|
+
} else {
|
|
201
|
+
return `,
|
|
202
|
+
addCSS: function() {
|
|
203
|
+
// No CSS content found in @onInit
|
|
204
|
+
},
|
|
205
|
+
removeCSS: function() {
|
|
206
|
+
const styles = document.querySelectorAll('style[data-view-name="${viewName}"]');
|
|
207
|
+
styles.forEach(style => style.remove());
|
|
208
|
+
}`;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
generateInitFunction(initCode) {
|
|
213
|
+
/** Generate init function */
|
|
214
|
+
if (!initCode || !initCode.trim()) {
|
|
215
|
+
return "function(__$spaViewData$__ = {}) { }";
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return `function(__$spaViewData$__ = {}) {
|
|
219
|
+
${initCode}
|
|
220
|
+
}`;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
generateDestroyFunction() {
|
|
224
|
+
/** Generate destroy function */
|
|
225
|
+
return "function() { }";
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
generateWrapperFunction(wrapperContent) {
|
|
229
|
+
/** Generate wrapper function */
|
|
230
|
+
if (!wrapperContent || !wrapperContent.trim()) {
|
|
231
|
+
return "";
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return wrapperContent;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
module.exports = FunctionGenerators;
|
|
239
|
+
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loop handlers for @foreach, @for, etc.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
class LoopHandlers {
|
|
6
|
+
constructor() {
|
|
7
|
+
// No initialization needed
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
processLoopDirective(line, stack, output) {
|
|
11
|
+
/** Process loop directives */
|
|
12
|
+
const trimmedLine = line.trim();
|
|
13
|
+
|
|
14
|
+
if (trimmedLine.startsWith('@foreach')) {
|
|
15
|
+
stack.push(['foreach', trimmedLine]);
|
|
16
|
+
return null;
|
|
17
|
+
} else if (trimmedLine.startsWith('@endforeach')) {
|
|
18
|
+
if (stack.length > 0 && stack[stack.length - 1][0] === 'foreach') {
|
|
19
|
+
stack.pop();
|
|
20
|
+
return '}';
|
|
21
|
+
}
|
|
22
|
+
} else if (trimmedLine.startsWith('@for')) {
|
|
23
|
+
stack.push(['for', trimmedLine]);
|
|
24
|
+
return null;
|
|
25
|
+
} else if (trimmedLine.startsWith('@endfor')) {
|
|
26
|
+
if (stack.length > 0 && stack[stack.length - 1][0] === 'for') {
|
|
27
|
+
stack.pop();
|
|
28
|
+
return '}';
|
|
29
|
+
}
|
|
30
|
+
} else if (trimmedLine.startsWith('@while')) {
|
|
31
|
+
stack.push(['while', trimmedLine]);
|
|
32
|
+
return null;
|
|
33
|
+
} else if (trimmedLine.startsWith('@endwhile')) {
|
|
34
|
+
if (stack.length > 0 && stack[stack.length - 1][0] === 'while') {
|
|
35
|
+
stack.pop();
|
|
36
|
+
return '}';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = LoopHandlers;
|
|
45
|
+
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main compiler class that combines all modules
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const {
|
|
8
|
+
JS_FUNCTION_PREFIX,
|
|
9
|
+
HTML_ATTR_PREFIX,
|
|
10
|
+
ViewConfig
|
|
11
|
+
} = require('./config');
|
|
12
|
+
const {
|
|
13
|
+
extractBalancedParentheses,
|
|
14
|
+
formatAttrs,
|
|
15
|
+
normalizeQuotes,
|
|
16
|
+
formatJsOutput,
|
|
17
|
+
replaceAll
|
|
18
|
+
} = require('./utils');
|
|
19
|
+
|
|
20
|
+
class BladeCompiler {
|
|
21
|
+
constructor() {
|
|
22
|
+
this.parsers = new (require('./parsers'))();
|
|
23
|
+
this.templateProcessor = new (require('./template-processor'))();
|
|
24
|
+
this.templateAnalyzer = new (require('./template-analyzer'))();
|
|
25
|
+
this.functionGenerators = new (require('./function-generators'))();
|
|
26
|
+
this.compilerUtils = new (require('./compiler-utils'))();
|
|
27
|
+
this.wrapperParser = new (require('./wrapper-parser'))();
|
|
28
|
+
this.registerParser = new (require('./register-parser'))();
|
|
29
|
+
this.viewConfig = new ViewConfig();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
convertViewPathToFunctionName(viewPath) {
|
|
33
|
+
/** Convert view path to function name (e.g., web.demo-if -> WebDemoIf) */
|
|
34
|
+
// Split by dots and hyphens
|
|
35
|
+
const parts = viewPath.split(/[.-]/);
|
|
36
|
+
// Capitalize each part and join
|
|
37
|
+
const functionName = parts.map(part =>
|
|
38
|
+
part.charAt(0).toUpperCase() + part.slice(1)
|
|
39
|
+
).join('');
|
|
40
|
+
return functionName;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
compileBladeToJs(bladeCode, viewName) {
|
|
44
|
+
/** Main compiler function */
|
|
45
|
+
bladeCode = bladeCode.trim();
|
|
46
|
+
|
|
47
|
+
// Reset parser states to avoid data leakage between views
|
|
48
|
+
if (typeof this.registerParser.reset === 'function') {
|
|
49
|
+
this.registerParser.reset();
|
|
50
|
+
}
|
|
51
|
+
// Note: wrapper_parser doesn't reset because data from wrapper.js doesn't change
|
|
52
|
+
|
|
53
|
+
// Parse wrapper content
|
|
54
|
+
const { wrapperFunctionContent, wrapperConfigContent } = this.wrapperParser.parseWrapperFile();
|
|
55
|
+
|
|
56
|
+
// Convert view path to function name
|
|
57
|
+
const functionName = this.convertViewPathToFunctionName(viewName);
|
|
58
|
+
|
|
59
|
+
// Remove Blade comments
|
|
60
|
+
bladeCode = bladeCode.replace(/\{\{--.*?--\}\}/gs, '');
|
|
61
|
+
|
|
62
|
+
// Check for directives
|
|
63
|
+
const hasAwait = bladeCode.includes('@await(');
|
|
64
|
+
const hasFetch = bladeCode.includes('@fetch(');
|
|
65
|
+
|
|
66
|
+
// Parse main components
|
|
67
|
+
const { extendedView, extendsExpression, extendsData } = this.parsers.parseExtends(bladeCode);
|
|
68
|
+
const varsDeclaration = this.parsers.parseVars(bladeCode);
|
|
69
|
+
const letDeclarations = this.parsers.parseLetDirectives(bladeCode);
|
|
70
|
+
const constDeclarations = this.parsers.parseConstDirectives(bladeCode);
|
|
71
|
+
const useStateDeclarations = this.parsers.parseUseStateDirectives(bladeCode);
|
|
72
|
+
const fetchConfig = hasFetch ? this.parsers.parseFetch(bladeCode) : null;
|
|
73
|
+
const { initFunctions, cssContent } = this.parsers.parseInit(bladeCode);
|
|
74
|
+
const viewTypeData = this.parsers.parseViewType(bladeCode);
|
|
75
|
+
|
|
76
|
+
// Parse @register directive
|
|
77
|
+
const registerContent = this.parsers.parseRegister(bladeCode);
|
|
78
|
+
const registerData = this.registerParser.parseRegisterContent(registerContent);
|
|
79
|
+
|
|
80
|
+
// Parse @wrapper directive
|
|
81
|
+
const wrapperContent = this.parsers.parseWrapper(bladeCode);
|
|
82
|
+
|
|
83
|
+
// Process template content
|
|
84
|
+
const { templateContent, sections } = this.templateProcessor.processTemplate(bladeCode);
|
|
85
|
+
|
|
86
|
+
// Analyze template
|
|
87
|
+
const analysis = this.templateAnalyzer.analyzeTemplate(templateContent);
|
|
88
|
+
|
|
89
|
+
// Determine view type
|
|
90
|
+
const viewType = viewTypeData.type || 'component';
|
|
91
|
+
|
|
92
|
+
// Generate sections info
|
|
93
|
+
const sectionsInfo = this.compilerUtils.generateSectionsInfo(sections, analysis);
|
|
94
|
+
|
|
95
|
+
// Generate view ID line
|
|
96
|
+
const viewIdLine = ` const __VIEW_ID__ = data.__SSR_VIEW_ID__ || ${JS_FUNCTION_PREFIX}.generateViewId();\n`;
|
|
97
|
+
|
|
98
|
+
// Generate setup script
|
|
99
|
+
let setupScript = '';
|
|
100
|
+
if (wrapperFunctionContent) {
|
|
101
|
+
setupScript = wrapperFunctionContent;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Generate directives line
|
|
105
|
+
let directivesLine = '';
|
|
106
|
+
if (letDeclarations || constDeclarations || useStateDeclarations) {
|
|
107
|
+
const allDeclarations = [
|
|
108
|
+
...(letDeclarations || []),
|
|
109
|
+
...(constDeclarations || []),
|
|
110
|
+
...(useStateDeclarations || [])
|
|
111
|
+
];
|
|
112
|
+
directivesLine = ' ' + allDeclarations.join('\n ') + '\n';
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Generate user defined line
|
|
116
|
+
let userDefinedLine = '';
|
|
117
|
+
if (registerData && Object.keys(registerData).length > 0) {
|
|
118
|
+
userDefinedLine = `\n userDefined: ${JSON.stringify(registerData)},\n`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Generate resources line
|
|
122
|
+
let resourcesLine = '';
|
|
123
|
+
if (registerData && registerData.resources && registerData.resources.length > 0) {
|
|
124
|
+
resourcesLine = `\n resources: ${JSON.stringify(registerData.resources)},\n`;
|
|
125
|
+
} else {
|
|
126
|
+
resourcesLine = '\n resources: [],\n';
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Generate render function (setup script will be added to view function instead)
|
|
130
|
+
const renderFunction = this.functionGenerators.generateRenderFunction(
|
|
131
|
+
templateContent, varsDeclaration, extendedView, extendsData,
|
|
132
|
+
sectionsInfo, analysis.hasPrerender, '', directivesLine
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
// Generate init function
|
|
136
|
+
const initCode = initFunctions ? initFunctions.join('\n ') : '';
|
|
137
|
+
const initFunction = `function(__$spaViewData$__ = {}) { ${initCode} }`;
|
|
138
|
+
|
|
139
|
+
// Generate prerender function (only use pure vars_declaration, no directives)
|
|
140
|
+
let prerenderVarsLine = '';
|
|
141
|
+
if (varsDeclaration) {
|
|
142
|
+
prerenderVarsLine = ' ' + varsDeclaration + '\n';
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const prerenderFunc = this.functionGenerators.generatePrerenderFunction(
|
|
146
|
+
hasAwait, hasFetch, prerenderVarsLine, viewIdLine, templateContent,
|
|
147
|
+
extendedView, extendsData, sectionsInfo, analysis.conditionalContent,
|
|
148
|
+
analysis.hasPrerender
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
// Generate loadServerData function
|
|
152
|
+
const loadServerDataFunc = this.functionGenerators.generateLoadServerDataFunction(
|
|
153
|
+
varsDeclaration, '', directivesLine
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
// CSS functions - combine CSS from @onInit and @register
|
|
157
|
+
const combinedCssContent = cssContent ? [...cssContent] : [];
|
|
158
|
+
|
|
159
|
+
// Add CSS from @register
|
|
160
|
+
if (registerData && registerData.css) {
|
|
161
|
+
const cssData = registerData.css;
|
|
162
|
+
|
|
163
|
+
// Add inline CSS
|
|
164
|
+
if (cssData.inline) {
|
|
165
|
+
combinedCssContent.push(cssData.inline);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Add external CSS links
|
|
169
|
+
if (cssData.external && cssData.external.length > 0) {
|
|
170
|
+
combinedCssContent.push(...cssData.external);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const cssFunctions = this.functionGenerators.generateCssFunctions(viewName, combinedCssContent);
|
|
175
|
+
|
|
176
|
+
// Generate wrapper config line
|
|
177
|
+
let wrapperConfigLine = '';
|
|
178
|
+
if (wrapperConfigContent) {
|
|
179
|
+
wrapperConfigLine = wrapperConfigContent;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Generate super view config
|
|
183
|
+
let superViewConfig = 'null';
|
|
184
|
+
let hasSuperView = 'false';
|
|
185
|
+
if (extendedView) {
|
|
186
|
+
superViewConfig = `'${extendedView}'`;
|
|
187
|
+
hasSuperView = 'true';
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Generate setup script line
|
|
191
|
+
let setupScriptLine = '';
|
|
192
|
+
if (setupScript) {
|
|
193
|
+
setupScriptLine = setupScript + '\n';
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Generate wrapper function line
|
|
197
|
+
let wrapperFunctionLine = '';
|
|
198
|
+
if (wrapperContent) {
|
|
199
|
+
wrapperFunctionLine = wrapperContent + '\n';
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Build the return string carefully to avoid syntax errors
|
|
203
|
+
return `export function ${functionName}(data = {}) {
|
|
204
|
+
const {App, View} = data;
|
|
205
|
+
const __VIEW_PATH__ = '${viewName}';
|
|
206
|
+
const __VIEW_ID__ = data.__SSR_VIEW_ID__ || ${JS_FUNCTION_PREFIX}.generateViewId();
|
|
207
|
+
const __VIEW_TYPE__ = '${viewType}';
|
|
208
|
+
${wrapperFunctionLine}
|
|
209
|
+
self.setup('${viewName}', {
|
|
210
|
+
superView: ${superViewConfig},
|
|
211
|
+
hasSuperView: ${hasSuperView},
|
|
212
|
+
viewType: '${viewType}',
|
|
213
|
+
sections: ${JSON.stringify(sectionsInfo)},
|
|
214
|
+
hasAwaitData: ${hasAwait},
|
|
215
|
+
hasFetchData: ${hasFetch},
|
|
216
|
+
fetch: ${fetchConfig ? this.compilerUtils.formatFetchConfig(fetchConfig) : 'null'},
|
|
217
|
+
data: data,
|
|
218
|
+
viewId: __VIEW_ID__,
|
|
219
|
+
path: __VIEW_PATH__,
|
|
220
|
+
usesVars: ${!!varsDeclaration},
|
|
221
|
+
hasSections: ${!!sections.length},
|
|
222
|
+
hasSectionPreload: ${sectionsInfo.some(section => section.preloader)},
|
|
223
|
+
hasPrerender: ${analysis.hasPrerender},${userDefinedLine}${resourcesLine}
|
|
224
|
+
prerender: ${prerenderFunc},
|
|
225
|
+
render: ${renderFunction},
|
|
226
|
+
loadServerData: ${loadServerDataFunc},
|
|
227
|
+
init: ${initFunction},
|
|
228
|
+
destroy: function() {},${cssFunctions}${wrapperConfigLine}
|
|
229
|
+
});
|
|
230
|
+
return self;
|
|
231
|
+
}`;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
module.exports = BladeCompiler;
|
|
236
|
+
|