juxscript 1.1.137 → 1.1.138
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/dom-structure-map.json +1 -1
- package/machinery/compiler3.js +40 -67
- package/package.json +1 -1
package/dom-structure-map.json
CHANGED
package/machinery/compiler3.js
CHANGED
|
@@ -18,6 +18,7 @@ export class JuxCompiler {
|
|
|
18
18
|
this.paths = config.paths || {};
|
|
19
19
|
this._juxscriptExports = null;
|
|
20
20
|
this._juxscriptPath = null;
|
|
21
|
+
this._renderFunctionCounter = 0; // ✅ Add counter for unique IDs
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
/**
|
|
@@ -245,48 +246,46 @@ export class JuxCompiler {
|
|
|
245
246
|
|
|
246
247
|
entry += `\n// --- VIEW FUNCTIONS ---\n`;
|
|
247
248
|
|
|
249
|
+
// ✅ Map to store route → function name mappings
|
|
250
|
+
const routeToFunctionMap = new Map();
|
|
251
|
+
|
|
248
252
|
views.forEach(v => {
|
|
249
|
-
// ✅
|
|
250
|
-
|
|
251
|
-
const
|
|
252
|
-
.replace(/[\/\\.\\-\s]/g, '_') // Replace /, \, ., -, spaces with _
|
|
253
|
-
.replace(/[^a-zA-Z0-9_]/g, '_') // Replace any other invalid chars with _
|
|
254
|
-
.replace(/_+/g, '_') // Collapse multiple consecutive underscores
|
|
255
|
-
.replace(/^_|_$/g, ''); // Remove leading/trailing underscores
|
|
256
|
-
|
|
257
|
-
const capitalized = sanitizedName.charAt(0).toUpperCase() + sanitizedName.slice(1);
|
|
258
|
-
|
|
259
|
-
// ✅ Check for duplicate function names and warn
|
|
260
|
-
const functionName = `render${capitalized}`;
|
|
261
|
-
if (sourceSnapshot[functionName]) {
|
|
262
|
-
console.error(`❌ DUPLICATE FUNCTION NAME: ${functionName}`);
|
|
263
|
-
console.error(` Conflict between:`);
|
|
264
|
-
console.error(` 1. ${sourceSnapshot[functionName].file}`);
|
|
265
|
-
console.error(` 2. ${v.file}`);
|
|
266
|
-
console.error(` This will cause a build error. Rename one of these files.`);
|
|
267
|
-
throw new Error(`Duplicate function name: ${functionName}`);
|
|
268
|
-
}
|
|
253
|
+
// ✅ Generate TRULY UNIQUE serial ID
|
|
254
|
+
const serialId = this._renderFunctionCounter++;
|
|
255
|
+
const functionName = `renderJux${serialId}`;
|
|
269
256
|
|
|
270
257
|
sourceSnapshot[v.file] = {
|
|
271
258
|
name: v.name,
|
|
272
259
|
file: v.file,
|
|
273
260
|
content: v.content,
|
|
274
|
-
lines: v.content.split('\n')
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
// ✅ Also track by function name to catch duplicates
|
|
278
|
-
sourceSnapshot[functionName] = {
|
|
279
|
-
name: v.name,
|
|
280
|
-
file: v.file,
|
|
281
|
-
content: v.content,
|
|
282
|
-
lines: v.content.split('\n')
|
|
261
|
+
lines: v.content.split('\n'),
|
|
262
|
+
functionName // ✅ Store the unique function name
|
|
283
263
|
};
|
|
284
264
|
|
|
285
265
|
let viewCode = this.removeImports(v.content).replace(/^\s*export\s+default\s+.*$/gm, '');
|
|
286
266
|
const asyncPrefix = viewCode.includes('await ') ? 'async ' : '';
|
|
287
267
|
|
|
288
|
-
// Use
|
|
268
|
+
// ✅ Use truly unique serial function name
|
|
289
269
|
entry += `\n${asyncPrefix}function ${functionName}() {\n${viewCode}\n}\n`;
|
|
270
|
+
|
|
271
|
+
// ✅ Generate URL-safe route path from original name
|
|
272
|
+
const routePath = v.name
|
|
273
|
+
.toLowerCase()
|
|
274
|
+
.replace(/\\/g, '/')
|
|
275
|
+
.replace(/\.jux$/i, '')
|
|
276
|
+
.replace(/\./g, '-')
|
|
277
|
+
.replace(/\s+/g, '-')
|
|
278
|
+
.replace(/[^a-z0-9\/_-]/g, '')
|
|
279
|
+
.replace(/-+/g, '-')
|
|
280
|
+
.replace(/^-|-$/g, '');
|
|
281
|
+
|
|
282
|
+
// ✅ Handle index route
|
|
283
|
+
if (routePath === 'index' || routePath === '') {
|
|
284
|
+
routeToFunctionMap.set('/', functionName);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// ✅ Map route to function
|
|
288
|
+
routeToFunctionMap.set(`/${routePath}`, functionName);
|
|
290
289
|
});
|
|
291
290
|
|
|
292
291
|
dataModules.forEach(m => {
|
|
@@ -298,7 +297,9 @@ export class JuxCompiler {
|
|
|
298
297
|
|
|
299
298
|
this._sourceSnapshot = sourceSnapshot;
|
|
300
299
|
this._validationIssues = allIssues;
|
|
301
|
-
|
|
300
|
+
|
|
301
|
+
// ✅ Pass the route map to router generator
|
|
302
|
+
entry += this._generateRouter(routeToFunctionMap);
|
|
302
303
|
return entry;
|
|
303
304
|
}
|
|
304
305
|
|
|
@@ -319,39 +320,11 @@ export class JuxCompiler {
|
|
|
319
320
|
return { isValid: errors.length === 0, errors, warnings };
|
|
320
321
|
}
|
|
321
322
|
|
|
322
|
-
_generateRouter(
|
|
323
|
+
_generateRouter(routeToFunctionMap) {
|
|
324
|
+
// ✅ Build route map from Map object
|
|
323
325
|
let routeMap = '';
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
const sanitizedName = v.name
|
|
327
|
-
.replace(/[\/\\.\\-\s]/g, '_')
|
|
328
|
-
.replace(/[^a-zA-Z0-9_]/g, '_')
|
|
329
|
-
.replace(/_+/g, '_')
|
|
330
|
-
.replace(/^_|_$/g, '');
|
|
331
|
-
|
|
332
|
-
const cap = sanitizedName.charAt(0).toUpperCase() + sanitizedName.slice(1);
|
|
333
|
-
|
|
334
|
-
// ✅ Generate URL-safe route path from original name
|
|
335
|
-
// Convert: 'menus/main' → '/menus/main'
|
|
336
|
-
// Convert: 'about-us' → '/about-us'
|
|
337
|
-
// Convert: 'blog.post' → '/blog-post' (dots become dashes for URLs)
|
|
338
|
-
const routePath = v.name
|
|
339
|
-
.toLowerCase()
|
|
340
|
-
.replace(/\\/g, '/') // Normalize backslashes to forward slashes
|
|
341
|
-
.replace(/\.jux$/i, '') // Remove .jux extension if present
|
|
342
|
-
.replace(/\./g, '-') // Convert dots to dashes (blog.post → blog-post)
|
|
343
|
-
.replace(/\s+/g, '-') // Convert spaces to dashes
|
|
344
|
-
.replace(/[^a-z0-9\/_-]/g, '') // Remove any other unsafe URL chars
|
|
345
|
-
.replace(/-+/g, '-') // Collapse multiple dashes
|
|
346
|
-
.replace(/^-|-$/g, ''); // Remove leading/trailing dashes
|
|
347
|
-
|
|
348
|
-
// ✅ Handle index route
|
|
349
|
-
if (routePath === 'index' || routePath === '') {
|
|
350
|
-
routeMap += ` '/': render${cap},\n`;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
// ✅ Add regular route
|
|
354
|
-
routeMap += ` '/${routePath}': render${cap},\n`;
|
|
326
|
+
routeToFunctionMap.forEach((functionName, route) => {
|
|
327
|
+
routeMap += ` '${route}': ${functionName},\n`;
|
|
355
328
|
});
|
|
356
329
|
|
|
357
330
|
return `
|
|
@@ -369,12 +342,12 @@ async function __juxLoadSources() {
|
|
|
369
342
|
}
|
|
370
343
|
|
|
371
344
|
function __juxFindSource(stack) {
|
|
372
|
-
var match = stack.match(/
|
|
345
|
+
var match = stack.match(/renderJux(\\d+)/);
|
|
373
346
|
if (match) {
|
|
374
|
-
var
|
|
347
|
+
var functionName = 'renderJux' + match[1];
|
|
375
348
|
for (var file in __juxSources || {}) {
|
|
376
|
-
if (__juxSources[file].
|
|
377
|
-
return { file: file, source: __juxSources[file],
|
|
349
|
+
if (__juxSources[file].functionName === functionName) {
|
|
350
|
+
return { file: file, source: __juxSources[file], functionName: functionName };
|
|
378
351
|
}
|
|
379
352
|
}
|
|
380
353
|
}
|