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,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js Build Script - Main entry point
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const glob = require('glob');
|
|
8
|
+
const { CompilerConfig } = require('./compiler/config');
|
|
9
|
+
const BladeCompiler = require('./compiler/main-compiler');
|
|
10
|
+
|
|
11
|
+
class NodeBuildScript {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.config = new CompilerConfig();
|
|
14
|
+
this.compiler = new BladeCompiler();
|
|
15
|
+
this.verbose = false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async run() {
|
|
19
|
+
/** Main build function */
|
|
20
|
+
console.log('✓ Using Node.js Blade compiler');
|
|
21
|
+
console.log('Starting build script...');
|
|
22
|
+
|
|
23
|
+
if (this.verbose) {
|
|
24
|
+
this.config.printConfig();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const buildDirectories = this.config.get('build_directories');
|
|
28
|
+
console.log(`Build directories: ${buildDirectories.length} directories`);
|
|
29
|
+
|
|
30
|
+
for (let i = 0; i < buildDirectories.length; i++) {
|
|
31
|
+
const dir = buildDirectories[i];
|
|
32
|
+
const dirPath = path.join(this.config.get('paths.views_input'), dir);
|
|
33
|
+
console.log(` ${i + 1}. ${dirPath}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let totalCompiled = 0;
|
|
37
|
+
let totalViews = [];
|
|
38
|
+
|
|
39
|
+
// Build each directory
|
|
40
|
+
for (const dir of buildDirectories) {
|
|
41
|
+
const result = await this.buildDirectory(dir);
|
|
42
|
+
totalCompiled += result.compiled;
|
|
43
|
+
totalViews.push(...result.views);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
console.log('\n=== Overall Results ===');
|
|
47
|
+
console.log(`Total compiled: ${totalCompiled}/${totalCompiled} files successfully`);
|
|
48
|
+
|
|
49
|
+
// Build individual view files
|
|
50
|
+
await this.buildIndividualViews(totalViews);
|
|
51
|
+
|
|
52
|
+
console.log('\n✅ Node.js build completed successfully!');
|
|
53
|
+
console.log(`📦 Total views: ${totalViews.length}`);
|
|
54
|
+
console.log(`📄 Views: [${totalViews.map(v => `'${v}'`).join(', ')}]`);
|
|
55
|
+
console.log(`📁 ViewTemplate.js: ${path.join(this.config.get('paths.js_input'), 'core', 'ViewTemplate.js')}`);
|
|
56
|
+
console.log(`📁 Individual view files: ${path.join(this.config.get('paths.js_input'), 'views')}`);
|
|
57
|
+
console.log('\n💡 Next step: Run \'npm run compile\' to build main.js');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async buildDirectory(dirName) {
|
|
61
|
+
/** Build a single directory */
|
|
62
|
+
const dirPath = path.join(this.config.get('paths.views_input'), dirName);
|
|
63
|
+
|
|
64
|
+
if (!fs.existsSync(dirPath)) {
|
|
65
|
+
console.log(`\n=== Building directory: ${dirPath} ===`);
|
|
66
|
+
console.log(`Directory not found: ${dirPath}`);
|
|
67
|
+
return { compiled: 0, views: [] };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
console.log(`\n=== Building directory: ${dirPath} ===`);
|
|
71
|
+
|
|
72
|
+
// Find all blade files
|
|
73
|
+
const pattern = path.join(dirPath, '**/*.blade.php');
|
|
74
|
+
const files = glob.sync(pattern);
|
|
75
|
+
|
|
76
|
+
console.log(`Found ${files.length} blade files`);
|
|
77
|
+
|
|
78
|
+
let compiled = 0;
|
|
79
|
+
const views = [];
|
|
80
|
+
|
|
81
|
+
for (const file of files) {
|
|
82
|
+
const relativePath = path.relative(this.config.get('paths.views_input'), file);
|
|
83
|
+
const viewName = relativePath.replace(/\.blade\.php$/, '').replace(/\//g, '.');
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
const bladeCode = fs.readFileSync(file, 'utf8');
|
|
87
|
+
const jsCode = this.compiler.compileBladeToJs(bladeCode, viewName);
|
|
88
|
+
|
|
89
|
+
// Generate function name
|
|
90
|
+
const functionName = this.compiler.convertViewPathToFunctionName(viewName);
|
|
91
|
+
|
|
92
|
+
console.log(`Compiling: ${file}`);
|
|
93
|
+
console.log(` -> ${viewName} [SUCCESS]`);
|
|
94
|
+
|
|
95
|
+
// Store for later processing
|
|
96
|
+
views.push({
|
|
97
|
+
name: viewName,
|
|
98
|
+
functionName: functionName,
|
|
99
|
+
code: jsCode
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
compiled++;
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.log(`Compiling: ${file}`);
|
|
105
|
+
console.log(` -> ${viewName} [ERROR: ${error.message}]`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
console.log(`Directory completed: ${compiled}/${files.length} files successfully`);
|
|
110
|
+
return { compiled, views };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async buildIndividualViews(views) {
|
|
114
|
+
/** Build individual view files */
|
|
115
|
+
const viewsDir = path.join(this.config.get('paths.js_input'), 'views');
|
|
116
|
+
|
|
117
|
+
// Clean views directory
|
|
118
|
+
if (fs.existsSync(viewsDir)) {
|
|
119
|
+
const files = fs.readdirSync(viewsDir);
|
|
120
|
+
for (const file of files) {
|
|
121
|
+
if (file.endsWith('.js')) {
|
|
122
|
+
fs.unlinkSync(path.join(viewsDir, file));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
fs.mkdirSync(viewsDir, { recursive: true });
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
console.log(`✓ Cleaned views directory: ${viewsDir}`);
|
|
130
|
+
|
|
131
|
+
// Write individual view files
|
|
132
|
+
for (const view of views) {
|
|
133
|
+
const fileName = `${view.functionName}.js`;
|
|
134
|
+
const filePath = path.join(viewsDir, fileName);
|
|
135
|
+
|
|
136
|
+
fs.writeFileSync(filePath, view.code);
|
|
137
|
+
console.log(`Created view file: ${fileName}`);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Build ViewTemplate.js
|
|
141
|
+
await this.buildViewTemplate(views);
|
|
142
|
+
|
|
143
|
+
console.log(`Successfully built ViewTemplate.js: ${path.join(this.config.get('paths.js_input'), 'core', 'ViewTemplate.js')}`);
|
|
144
|
+
console.log(`ViewTemplate.js built successfully: ${path.join(this.config.get('paths.js_input'), 'core', 'ViewTemplate.js')}`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async buildViewTemplate(views) {
|
|
148
|
+
/** Build ViewTemplate.js file */
|
|
149
|
+
const viewTemplateContent = this.generateViewTemplateContent(views);
|
|
150
|
+
const viewTemplatePath = path.join(this.config.get('paths.js_input'), 'core', 'ViewTemplate.js');
|
|
151
|
+
|
|
152
|
+
// Ensure core directory exists
|
|
153
|
+
const coreDir = path.dirname(viewTemplatePath);
|
|
154
|
+
if (!fs.existsSync(coreDir)) {
|
|
155
|
+
fs.mkdirSync(coreDir, { recursive: true });
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
fs.writeFileSync(viewTemplatePath, viewTemplateContent);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
generateViewTemplateContent(views) {
|
|
162
|
+
/** Generate ViewTemplate.js content */
|
|
163
|
+
const imports = views.map(view =>
|
|
164
|
+
`import { ${view.functionName} } from '../views/${view.functionName}.js';`
|
|
165
|
+
).join('\n');
|
|
166
|
+
|
|
167
|
+
const viewObjects = views.map(view =>
|
|
168
|
+
` '${view.name}': ${view.functionName}`
|
|
169
|
+
).join(',\n');
|
|
170
|
+
|
|
171
|
+
return `// Auto-generated ViewTemplate.js
|
|
172
|
+
// Generated by Node.js Blade Compiler
|
|
173
|
+
|
|
174
|
+
${imports}
|
|
175
|
+
|
|
176
|
+
const ViewTemplate = {
|
|
177
|
+
${viewObjects}
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
export default ViewTemplate;
|
|
181
|
+
`;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
setVerbose(verbose) {
|
|
185
|
+
/** Set verbose mode */
|
|
186
|
+
this.verbose = verbose;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// CLI interface
|
|
191
|
+
if (require.main === module) {
|
|
192
|
+
const buildScript = new NodeBuildScript();
|
|
193
|
+
|
|
194
|
+
// Parse command line arguments
|
|
195
|
+
const args = process.argv.slice(2);
|
|
196
|
+
if (args.includes('--verbose') || args.includes('-v')) {
|
|
197
|
+
buildScript.setVerbose(true);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Run build
|
|
201
|
+
buildScript.run().catch(error => {
|
|
202
|
+
console.error('Build failed:', error);
|
|
203
|
+
process.exit(1);
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
module.exports = NodeBuildScript;
|
|
208
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compiler utilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
class CompilerUtils {
|
|
6
|
+
constructor() {
|
|
7
|
+
// No initialization needed
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
generateSectionsInfo(sections, analysis) {
|
|
11
|
+
/** Generate sections info */
|
|
12
|
+
const sectionsInfo = [];
|
|
13
|
+
|
|
14
|
+
for (const section of sections) {
|
|
15
|
+
sectionsInfo.push({
|
|
16
|
+
name: section.name,
|
|
17
|
+
type: section.type || 'long',
|
|
18
|
+
preloader: section.preloader || false,
|
|
19
|
+
useVars: section.useVars || false,
|
|
20
|
+
script: section.script || {}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return sectionsInfo;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
formatFetchConfig(fetchConfig) {
|
|
28
|
+
/** Format fetch config */
|
|
29
|
+
if (typeof fetchConfig === 'string') {
|
|
30
|
+
return fetchConfig;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return JSON.stringify(fetchConfig);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = CompilerUtils;
|
|
38
|
+
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conditional handlers for @if, @unless, etc.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
class ConditionalHandlers {
|
|
6
|
+
constructor() {
|
|
7
|
+
// No initialization needed
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
processConditionalDirective(line, stack, output) {
|
|
11
|
+
/** Process conditional directives */
|
|
12
|
+
const trimmedLine = line.trim();
|
|
13
|
+
|
|
14
|
+
if (trimmedLine.startsWith('@if')) {
|
|
15
|
+
stack.push(['if', trimmedLine]);
|
|
16
|
+
return null;
|
|
17
|
+
} else if (trimmedLine.startsWith('@elseif')) {
|
|
18
|
+
if (stack.length > 0 && stack[stack.length - 1][0] === 'if') {
|
|
19
|
+
return '} else if (';
|
|
20
|
+
}
|
|
21
|
+
} else if (trimmedLine.startsWith('@else')) {
|
|
22
|
+
if (stack.length > 0 && stack[stack.length - 1][0] === 'if') {
|
|
23
|
+
return '} else {';
|
|
24
|
+
}
|
|
25
|
+
} else if (trimmedLine.startsWith('@endif')) {
|
|
26
|
+
if (stack.length > 0 && stack[stack.length - 1][0] === 'if') {
|
|
27
|
+
stack.pop();
|
|
28
|
+
return '}';
|
|
29
|
+
}
|
|
30
|
+
} else if (trimmedLine.startsWith('@unless')) {
|
|
31
|
+
stack.push(['unless', trimmedLine]);
|
|
32
|
+
return null;
|
|
33
|
+
} else if (trimmedLine.startsWith('@endunless')) {
|
|
34
|
+
if (stack.length > 0 && stack[stack.length - 1][0] === 'unless') {
|
|
35
|
+
stack.pop();
|
|
36
|
+
return '}';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = ConditionalHandlers;
|
|
45
|
+
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
|
|
3
|
+
class CompilerConfig {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.config = {
|
|
6
|
+
paths: {
|
|
7
|
+
views_input: "resources/views",
|
|
8
|
+
js_input: "resources/js/app",
|
|
9
|
+
build_output: "resources/js/build",
|
|
10
|
+
build_scopes: "resources/js/build/scopes",
|
|
11
|
+
public_static: "public/static",
|
|
12
|
+
app_output: "public/static/app",
|
|
13
|
+
scopes_output: "public/static/app/scopes"
|
|
14
|
+
},
|
|
15
|
+
files: {
|
|
16
|
+
view_templates: "view.templates.js",
|
|
17
|
+
wrapper: "wraper.js",
|
|
18
|
+
main: "main.js"
|
|
19
|
+
},
|
|
20
|
+
patterns: {
|
|
21
|
+
blade: "**/*.blade.php",
|
|
22
|
+
js: "**/*.js"
|
|
23
|
+
},
|
|
24
|
+
settings: {
|
|
25
|
+
default_scope: "web",
|
|
26
|
+
auto_create_dirs: true,
|
|
27
|
+
verbose: false
|
|
28
|
+
},
|
|
29
|
+
build_directories: [
|
|
30
|
+
"web",
|
|
31
|
+
"admin",
|
|
32
|
+
"layouts",
|
|
33
|
+
"partials",
|
|
34
|
+
"custom",
|
|
35
|
+
"base"
|
|
36
|
+
]
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get(key) {
|
|
41
|
+
return key.split('.').reduce((obj, k) => obj && obj[k], this.config);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
set(key, value) {
|
|
45
|
+
const keys = key.split('.');
|
|
46
|
+
const lastKey = keys.pop();
|
|
47
|
+
const target = keys.reduce((obj, k) => obj[k] = obj[k] || {}, this.config);
|
|
48
|
+
target[lastKey] = value;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
printConfig() {
|
|
52
|
+
console.log("=============================");
|
|
53
|
+
console.log("Compiler Configuration:");
|
|
54
|
+
console.log("=============================");
|
|
55
|
+
console.log("Views input:", this.get('paths.views_input'));
|
|
56
|
+
console.log("JS input:", this.get('paths.js_input'));
|
|
57
|
+
console.log("Build output:", this.get('paths.build_output'));
|
|
58
|
+
console.log("App output:", this.get('paths.app_output'));
|
|
59
|
+
console.log("Default scope:", this.get('settings.default_scope'));
|
|
60
|
+
console.log("Auto create dirs:", this.get('settings.auto_create_dirs'));
|
|
61
|
+
console.log("Verbose:", this.get('settings.verbose'));
|
|
62
|
+
console.log("Build directories:");
|
|
63
|
+
this.get('build_directories').forEach((dir, i) => {
|
|
64
|
+
console.log(` ${i + 1}. ${dir}`);
|
|
65
|
+
});
|
|
66
|
+
console.log("=============================");
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Constants for backward compatibility
|
|
71
|
+
const JS_FUNCTION_PREFIX = "App.View";
|
|
72
|
+
const HTML_ATTR_PREFIX = "one-";
|
|
73
|
+
const SPA_YIELD_ATTR_PREFIX = "one-yield-attr";
|
|
74
|
+
const SPA_YIELD_SUBSCRIBE_KEY_PREFIX = "one-yield-key";
|
|
75
|
+
const SPA_YIELD_SUBSCRIBE_TARGET_PREFIX = "one-yield-target";
|
|
76
|
+
const SPA_YIELD_SUBSCRIBE_ATTR_PREFIX = "one-yield-attr";
|
|
77
|
+
const SPA_YIELD_CONTENT_PREFIX = "one-yield-content";
|
|
78
|
+
const SPA_YIELD_CHILDREN_PREFIX = "one-yield-children";
|
|
79
|
+
const APP_VIEW_NAMESPACE = "App.View";
|
|
80
|
+
const APP_HELPER_NAMESPACE = "App.Helper";
|
|
81
|
+
|
|
82
|
+
// View functions configuration
|
|
83
|
+
class ViewConfig {
|
|
84
|
+
constructor() {
|
|
85
|
+
// View functions - all other functions go to Helper
|
|
86
|
+
this.VIEW_FUNCTIONS = [
|
|
87
|
+
// Core functions
|
|
88
|
+
'generateViewId',
|
|
89
|
+
'execute',
|
|
90
|
+
'evaluate',
|
|
91
|
+
'escString',
|
|
92
|
+
'text',
|
|
93
|
+
'templateToDom',
|
|
94
|
+
|
|
95
|
+
// View management
|
|
96
|
+
'view',
|
|
97
|
+
'loadView',
|
|
98
|
+
'renderView',
|
|
99
|
+
'include',
|
|
100
|
+
'includeIf',
|
|
101
|
+
'extendView',
|
|
102
|
+
|
|
103
|
+
// View lifecycle
|
|
104
|
+
'setSuperViewPath',
|
|
105
|
+
'addViewEngine',
|
|
106
|
+
'callViewEngineMounted',
|
|
107
|
+
|
|
108
|
+
// Wrapper functions
|
|
109
|
+
'startWrapper',
|
|
110
|
+
'endWrapper',
|
|
111
|
+
'registerSubscribe',
|
|
112
|
+
'wrapAttr',
|
|
113
|
+
// Sections
|
|
114
|
+
'section',
|
|
115
|
+
'yield',
|
|
116
|
+
'yieldContent',
|
|
117
|
+
'renderSections',
|
|
118
|
+
'hasSection',
|
|
119
|
+
'getChangedSections',
|
|
120
|
+
'resetChangedSections',
|
|
121
|
+
'isChangedSection',
|
|
122
|
+
'emitChangedSections',
|
|
123
|
+
|
|
124
|
+
// Stacks
|
|
125
|
+
'push',
|
|
126
|
+
'stack',
|
|
127
|
+
|
|
128
|
+
// Once
|
|
129
|
+
'once',
|
|
130
|
+
|
|
131
|
+
// Route
|
|
132
|
+
'route',
|
|
133
|
+
|
|
134
|
+
// Events
|
|
135
|
+
'on',
|
|
136
|
+
'off',
|
|
137
|
+
'emit',
|
|
138
|
+
|
|
139
|
+
// Initialization
|
|
140
|
+
'init',
|
|
141
|
+
'setApp',
|
|
142
|
+
'setContainer',
|
|
143
|
+
'clearOldRendering',
|
|
144
|
+
|
|
145
|
+
// Auth & Error functions (for Blade compatibility)
|
|
146
|
+
'isAuth',
|
|
147
|
+
'can',
|
|
148
|
+
'cannot',
|
|
149
|
+
'hasError',
|
|
150
|
+
'firstError',
|
|
151
|
+
'csrfToken',
|
|
152
|
+
|
|
153
|
+
// Loop functions (for Blade compatibility)
|
|
154
|
+
'foreach',
|
|
155
|
+
'foreachTemplate'
|
|
156
|
+
];
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
isViewFunction(functionName) {
|
|
160
|
+
return this.VIEW_FUNCTIONS.includes(functionName);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
module.exports = {
|
|
165
|
+
CompilerConfig,
|
|
166
|
+
JS_FUNCTION_PREFIX,
|
|
167
|
+
HTML_ATTR_PREFIX,
|
|
168
|
+
SPA_YIELD_ATTR_PREFIX,
|
|
169
|
+
SPA_YIELD_SUBSCRIBE_KEY_PREFIX,
|
|
170
|
+
SPA_YIELD_SUBSCRIBE_TARGET_PREFIX,
|
|
171
|
+
SPA_YIELD_SUBSCRIBE_ATTR_PREFIX,
|
|
172
|
+
SPA_YIELD_CONTENT_PREFIX,
|
|
173
|
+
SPA_YIELD_CHILDREN_PREFIX,
|
|
174
|
+
APP_VIEW_NAMESPACE,
|
|
175
|
+
APP_HELPER_NAMESPACE,
|
|
176
|
+
ViewConfig
|
|
177
|
+
};
|
|
178
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Directive processors for various Blade directives
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
class DirectiveProcessor {
|
|
6
|
+
constructor() {
|
|
7
|
+
// No initialization needed
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
processDirective(line, stack, output) {
|
|
11
|
+
/** Process various directives */
|
|
12
|
+
const trimmedLine = line.trim();
|
|
13
|
+
|
|
14
|
+
// Handle @include
|
|
15
|
+
if (trimmedLine.startsWith('@include')) {
|
|
16
|
+
const match = trimmedLine.match(/@include\s*\(\s*['"]([^'"]+)['"]\s*\)/);
|
|
17
|
+
if (match) {
|
|
18
|
+
const viewName = match[1];
|
|
19
|
+
return `\${App.View.include('${viewName}')}`;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Handle @csrf
|
|
24
|
+
if (trimmedLine.startsWith('@csrf')) {
|
|
25
|
+
return `\${App.View.csrfToken()}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Handle @method
|
|
29
|
+
if (trimmedLine.startsWith('@method')) {
|
|
30
|
+
const match = trimmedLine.match(/@method\s*\(\s*['"]([^'"]+)['"]\s*\)/);
|
|
31
|
+
if (match) {
|
|
32
|
+
const method = match[1];
|
|
33
|
+
return `<input type="hidden" name="_method" value="${method}">`;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Handle @error
|
|
38
|
+
if (trimmedLine.startsWith('@error')) {
|
|
39
|
+
const match = trimmedLine.match(/@error\s*\(\s*['"]([^'"]+)['"]\s*\)/);
|
|
40
|
+
if (match) {
|
|
41
|
+
const field = match[1];
|
|
42
|
+
return `\${App.View.hasError('${field}') ? App.View.firstError('${field}') : ''}`;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = DirectiveProcessor;
|
|
51
|
+
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event directive processor
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
class EventDirectiveProcessor {
|
|
6
|
+
constructor() {
|
|
7
|
+
// No initialization needed
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
processEventDirective(eventType, expression) {
|
|
11
|
+
/** Process event directive */
|
|
12
|
+
try {
|
|
13
|
+
// Parse expression to extract handlers
|
|
14
|
+
const handlers = this.parseEventHandlers(expression);
|
|
15
|
+
|
|
16
|
+
if (!handlers || handlers.length === 0) {
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Build event config
|
|
21
|
+
const eventConfig = this.buildEventConfig(eventType, handlers);
|
|
22
|
+
|
|
23
|
+
// Return event config with template string wrapper
|
|
24
|
+
return `\${${eventConfig}}`;
|
|
25
|
+
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.error(`Event directive error: ${error.message}`);
|
|
28
|
+
return '';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
parseEventHandlers(expression) {
|
|
33
|
+
/** Parse multiple event handlers from expression */
|
|
34
|
+
const handlers = [];
|
|
35
|
+
|
|
36
|
+
// Split by comma, respecting nested parentheses
|
|
37
|
+
const handlerStrings = this.splitByComma(expression);
|
|
38
|
+
|
|
39
|
+
for (const handlerString of handlerStrings) {
|
|
40
|
+
const trimmed = handlerString.trim();
|
|
41
|
+
if (!trimmed) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Parse handler name and parameters
|
|
46
|
+
const handler = this.parseHandler(trimmed);
|
|
47
|
+
if (handler) {
|
|
48
|
+
handlers.push(handler);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return handlers;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
parseHandler(handlerString) {
|
|
56
|
+
/** Parse handler name and parameters */
|
|
57
|
+
const parenIndex = handlerString.indexOf('(');
|
|
58
|
+
|
|
59
|
+
if (parenIndex === -1) {
|
|
60
|
+
// No parameters
|
|
61
|
+
return {
|
|
62
|
+
handler: handlerString.trim(),
|
|
63
|
+
params: []
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const handlerName = handlerString.substring(0, parenIndex).trim();
|
|
68
|
+
const paramsString = handlerString.substring(parenIndex + 1, handlerString.lastIndexOf(')'));
|
|
69
|
+
|
|
70
|
+
const params = this.parseHandlerParameters(paramsString);
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
handler: handlerName,
|
|
74
|
+
params: params
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
parseHandlerParameters(paramsString) {
|
|
79
|
+
/** Parse handler parameters */
|
|
80
|
+
if (!paramsString.trim()) {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const params = this.splitByComma(paramsString);
|
|
85
|
+
const processedParams = [];
|
|
86
|
+
|
|
87
|
+
for (const param of params) {
|
|
88
|
+
const processedParam = this.processParameter(param.trim());
|
|
89
|
+
processedParams.push(processedParam);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return processedParams;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
processParameter(param) {
|
|
96
|
+
/** Process individual parameter */
|
|
97
|
+
// Handle Event parameters in all contexts first
|
|
98
|
+
param = this.processEventInString(param);
|
|
99
|
+
|
|
100
|
+
// Handle @attr(...) -> "#ATTR:..."
|
|
101
|
+
param = this.processAttrPropInString(param, '@attr', '#ATTR');
|
|
102
|
+
|
|
103
|
+
// Handle @prop(...) -> "#PROP:..."
|
|
104
|
+
param = this.processAttrPropInString(param, '@prop', '#PROP');
|
|
105
|
+
|
|
106
|
+
// Handle @val(...) -> "#VALUE:..."
|
|
107
|
+
param = this.processAttrPropInString(param, '@val', '#VALUE');
|
|
108
|
+
|
|
109
|
+
// Handle @value(...) -> "#VALUE:..."
|
|
110
|
+
param = this.processAttrPropInString(param, '@value', '#VALUE');
|
|
111
|
+
|
|
112
|
+
// Convert PHP array syntax to JavaScript object syntax
|
|
113
|
+
param = this.convertPhpArrayToJsObject(param);
|
|
114
|
+
|
|
115
|
+
return param;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
processEventInString(str) {
|
|
119
|
+
/** Process Event parameters */
|
|
120
|
+
return str.replace(/Event/g, '@EVENT');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
processAttrPropInString(str, prefix, replacement) {
|
|
124
|
+
/** Process @attr/@prop/@val/@value parameters */
|
|
125
|
+
const regex = new RegExp(`${prefix}\\(([^)]+)\\)`, 'g');
|
|
126
|
+
return str.replace(regex, (match, content) => {
|
|
127
|
+
return `${replacement}:${content}`;
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
convertPhpArrayToJsObject(phpCode) {
|
|
132
|
+
/** Convert PHP array syntax to JavaScript object syntax */
|
|
133
|
+
// Simple conversion for now
|
|
134
|
+
return phpCode.replace(/\$(\w+)/g, '$1');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
splitByComma(text) {
|
|
138
|
+
/** Split text by comma, respecting nested parentheses and quotes */
|
|
139
|
+
const result = [];
|
|
140
|
+
let current = '';
|
|
141
|
+
let depth = 0;
|
|
142
|
+
let inQuotes = false;
|
|
143
|
+
let quoteChar = '';
|
|
144
|
+
|
|
145
|
+
for (let i = 0; i < text.length; i++) {
|
|
146
|
+
const char = text[i];
|
|
147
|
+
|
|
148
|
+
if (!inQuotes && (char === '"' || char === "'")) {
|
|
149
|
+
inQuotes = true;
|
|
150
|
+
quoteChar = char;
|
|
151
|
+
} else if (inQuotes && char === quoteChar) {
|
|
152
|
+
inQuotes = false;
|
|
153
|
+
quoteChar = '';
|
|
154
|
+
} else if (!inQuotes && char === '(') {
|
|
155
|
+
depth++;
|
|
156
|
+
} else if (!inQuotes && char === ')') {
|
|
157
|
+
depth--;
|
|
158
|
+
} else if (!inQuotes && depth === 0 && char === ',') {
|
|
159
|
+
result.push(current.trim());
|
|
160
|
+
current = '';
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
current += char;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (current.trim()) {
|
|
168
|
+
result.push(current.trim());
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return result;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
buildEventConfig(eventType, handlers) {
|
|
175
|
+
/** Build event config */
|
|
176
|
+
const handlersJson = JSON.stringify(handlers);
|
|
177
|
+
return `self.addEventConfig("${eventType}", ${handlersJson})`;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
module.exports = EventDirectiveProcessor;
|
|
182
|
+
|