juxscript 1.1.91 → 1.1.92

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "totalComponents": 63,
3
- "generatedAt": "2026-02-12T19:43:12.253Z",
3
+ "generatedAt": "2026-02-12T19:55:15.526Z",
4
4
  "components": [
5
5
  {
6
6
  "file": "alert.js",
@@ -36,8 +36,8 @@ export abstract class BaseStack extends BaseComponent<StackState> {
36
36
  private _inlineStyles: Map<string, string> = new Map();
37
37
 
38
38
  constructor(id: string, children: Record<string, any> | any[], options: StackOptions = {}) {
39
- const childArray = Array.isArray(children)
40
- ? children
39
+ const childArray = Array.isArray(children)
40
+ ? children
41
41
  : Object.values(children);
42
42
 
43
43
  super(id, {
@@ -108,7 +108,7 @@ export abstract class BaseStack extends BaseComponent<StackState> {
108
108
  const styleString = Array.from(this._inlineStyles.entries())
109
109
  .map(([prop, val]) => `${prop}: ${val}`)
110
110
  .join('; ');
111
-
111
+
112
112
  this.state.style = styleString;
113
113
  }
114
114
 
@@ -211,33 +211,33 @@ export abstract class BaseStack extends BaseComponent<StackState> {
211
211
 
212
212
  protected buildClasses(): string {
213
213
  const { spacing, align, justify, divider, responsive } = this.state;
214
-
214
+
215
215
  const classes = [this.baseClassName];
216
-
216
+
217
217
  if (spacing !== 'default') {
218
218
  classes.push(`${this.baseClassName}-${spacing}`);
219
219
  }
220
-
220
+
221
221
  if (align) {
222
222
  classes.push(`jux-stack-${align}`);
223
223
  }
224
-
224
+
225
225
  if (justify) {
226
226
  classes.push(`jux-stack-justify-${justify}`);
227
227
  }
228
-
228
+
229
229
  if (divider) {
230
230
  classes.push(`${this.baseClassName}-divider`);
231
231
  }
232
-
232
+
233
233
  if (responsive) {
234
234
  classes.push(`${this.baseClassName}-responsive`);
235
235
  }
236
-
236
+
237
237
  if (this.state.class) {
238
238
  classes.push(this.state.class);
239
239
  }
240
-
240
+
241
241
  return classes.join(' ');
242
242
  }
243
243
 
@@ -277,17 +277,17 @@ export abstract class BaseStack extends BaseComponent<StackState> {
277
277
 
278
278
  private getChildStyle(index: number): string {
279
279
  const { childStyles } = this.state;
280
-
280
+
281
281
  if (!childStyles) return '';
282
-
282
+
283
283
  if (typeof childStyles === 'function') {
284
284
  return childStyles(index);
285
285
  }
286
-
286
+
287
287
  if (Array.isArray(childStyles)) {
288
288
  return childStyles[index] || '';
289
289
  }
290
-
290
+
291
291
  return '';
292
292
  }
293
293
 
@@ -301,7 +301,7 @@ export abstract class BaseStack extends BaseComponent<StackState> {
301
301
  const wrapper = document.createElement('div');
302
302
  wrapper.className = this.buildClasses();
303
303
  wrapper.id = this._id;
304
-
304
+
305
305
  if (this.state.style) {
306
306
  wrapper.setAttribute('style', this.state.style);
307
307
  }
@@ -13,7 +13,7 @@ export class JuxCompiler {
13
13
  this.config = config;
14
14
  this.srcDir = config.srcDir || './jux';
15
15
  this.distDir = config.distDir || './.jux-dist';
16
- this.publicDir = config.publicDir || './public'; // ✅ Configurable public path
16
+ this.publicDir = config.publicDir || './public';
17
17
  this.defaults = config.defaults || {};
18
18
  this.paths = config.paths || {};
19
19
  this._juxscriptExports = null;
@@ -53,24 +53,56 @@ export class JuxCompiler {
53
53
  return null;
54
54
  }
55
55
 
56
- scanFiles() {
57
- const files = fs.readdirSync(this.srcDir)
58
- .filter(f => (f.endsWith('.jux') || f.endsWith('.js')) && !this.isAssetFile(f));
56
+ /**
57
+ * Recursively scan for .jux and .js files
58
+ */
59
+ scanFiles(dir = this.srcDir, baseDir = this.srcDir) {
60
+ const views = [];
61
+ const dataModules = [];
62
+ const sharedModules = [];
59
63
 
60
- const views = [], dataModules = [], sharedModules = [];
64
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
61
65
 
62
- files.forEach(file => {
63
- const content = fs.readFileSync(path.join(this.srcDir, file), 'utf8');
64
- const name = file.replace(/\.[^/.]+$/, '');
66
+ for (const entry of entries) {
67
+ // Skip hidden files/folders
68
+ if (entry.name.startsWith('.')) continue;
65
69
 
66
- if (file.includes('data')) {
67
- dataModules.push({ name, file, content });
68
- } else if (/export\s+(function|const|let|var|class)\s+/.test(content)) {
69
- sharedModules.push({ name, file, content });
70
- } else {
71
- views.push({ name, file, content });
70
+ const fullPath = path.join(dir, entry.name);
71
+ const relativePath = path.relative(baseDir, fullPath);
72
+
73
+ if (entry.isDirectory()) {
74
+ // Recurse into subdirectories
75
+ const nested = this.scanFiles(fullPath, baseDir);
76
+ views.push(...nested.views);
77
+ dataModules.push(...nested.dataModules);
78
+ sharedModules.push(...nested.sharedModules);
79
+ } else if ((entry.name.endsWith('.jux') || entry.name.endsWith('.js')) && !this.isAssetFile(entry.name)) {
80
+ const content = fs.readFileSync(fullPath, 'utf8');
81
+
82
+ // ✅ Generate name from folder structure
83
+ // Example: abc/juxabc.jux -> abc_juxabc
84
+ const nameFromPath = relativePath
85
+ .replace(/\.[^/.]+$/, '') // Remove extension
86
+ .replace(/\\/g, '/') // Normalize Windows paths
87
+ .replace(/\//g, '_') // Folder separator -> underscore
88
+ .replace(/[^a-zA-Z0-9_]/g, '_'); // Sanitize
89
+
90
+ const module = {
91
+ name: nameFromPath,
92
+ file: relativePath,
93
+ fullPath: fullPath,
94
+ content: content
95
+ };
96
+
97
+ if (entry.name.includes('data')) {
98
+ dataModules.push(module);
99
+ } else if (/export\s+(function|const|let|var|class)\s+/.test(content)) {
100
+ sharedModules.push(module);
101
+ } else {
102
+ views.push(module);
103
+ }
72
104
  }
73
- });
105
+ }
74
106
 
75
107
  return { views, dataModules, sharedModules };
76
108
  }
@@ -171,7 +203,220 @@ export class JuxCompiler {
171
203
  }
172
204
 
173
205
  /**
174
- * Generate entry point without layout/theme logic
206
+ * Generate routes based on folder structure
207
+ */
208
+ _generateRouter(views) {
209
+ let routeMap = '';
210
+
211
+ views.forEach(v => {
212
+ // ✅ Generate route from folder structure
213
+ // abc/juxabc.jux -> /abc/juxabc
214
+ // index.jux -> /
215
+ // abc/index.jux -> /abc
216
+
217
+ const routePath = this._generateRoutePath(v.file);
218
+ const functionName = this._generateFunctionName(v.name);
219
+
220
+ routeMap += ` '${routePath}': render${functionName},\n`;
221
+ });
222
+
223
+ return `
224
+ // --- JUX SOURCE LOADER ---
225
+ var __juxSources = null;
226
+ async function __juxLoadSources() {
227
+ if (__juxSources) return __juxSources;
228
+ try {
229
+ var res = await fetch('/__jux_sources.json');
230
+ __juxSources = await res.json();
231
+ } catch (e) {
232
+ __juxSources = {};
233
+ }
234
+ return __juxSources;
235
+ }
236
+
237
+ function __juxFindSource(stack) {
238
+ var match = stack.match(/render([A-Z][a-zA-Z0-9_]*)/);
239
+ if (match) {
240
+ var funcName = match[1];
241
+ for (var file in __juxSources || {}) {
242
+ var normalized = __juxSources[file].name
243
+ .split('_')
244
+ .map(s => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase())
245
+ .join('');
246
+
247
+ if (normalized === funcName) {
248
+ return { file: file, source: __juxSources[file], viewName: funcName };
249
+ }
250
+ }
251
+ }
252
+ return null;
253
+ }
254
+
255
+ // --- JUX RUNTIME ERROR OVERLAY ---
256
+ var __juxErrorOverlay = {
257
+ styles: \`
258
+ #__jux-error-overlay {
259
+ position: fixed; inset: 0; z-index: 99999;
260
+ background: rgba(0, 0, 0, 0.4);
261
+ display: flex; align-items: center; justify-content: center;
262
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
263
+ opacity: 0; transition: opacity 0.2s ease-out; backdrop-filter: blur(2px);
264
+ }
265
+ #__jux-error-overlay.visible { opacity: 1; }
266
+ #__jux-error-overlay * { box-sizing: border-box; }
267
+ .__jux-modal {
268
+ background: #f8f9fa; border-radius: 4px;
269
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.4);
270
+ max-width: 80vw; width: 90%; max-height: 90vh;
271
+ overflow: hidden; display: flex; flex-direction: column;
272
+ transform: translateY(10px); transition: transform 0.2s ease-out;
273
+ }
274
+ #__jux-error-overlay.visible .__jux-modal { transform: translateY(0); }
275
+ .__jux-header { background: #fff; padding: 20px 24px; border-bottom: 1px solid #e5e7eb; }
276
+ .__jux-header h3 { margin: 0 0 6px; font-weight: 600; font-size: 11px; color: #9ca3af; text-transform: uppercase; }
277
+ .__jux-header h1 { margin: 0 0 8px; font-size: 18px; font-weight: 600; color: #dc2626; line-height: 1.3; }
278
+ .__jux-header .file-info { color: #6b7280; font-size: 13px; }
279
+ .__jux-header .file-info strong { color: #dc2626; font-weight: 600; }
280
+ .__jux-source { padding: 16px 24px; overflow: auto; flex: 1; background: #f8f9fa; }
281
+ .__jux-code { background: #fff; border-radius: 8px; overflow: hidden; border: 1px solid #e5e7eb; }
282
+ .__jux-code-line { display: flex; font-size: 13px; line-height: 1.7; }
283
+ .__jux-code-line.error { background: #fef2f2; }
284
+ .__jux-code-line.error .__jux-line-code { color: #dc2626; font-weight: 500; }
285
+ .__jux-code-line.context { background: #fefce8; }
286
+ .__jux-line-num { min-width: 44px; padding: 4px 12px; text-align: right; color: #9ca3af; background: #f9fafb; border-right: 1px solid #e5e7eb; font-size: 12px; }
287
+ .__jux-code-line.error .__jux-line-num { background: #fef2f2; color: #dc2626; }
288
+ .__jux-line-code { flex: 1; padding: 4px 16px; color: #374151; white-space: pre; overflow-x: auto; }
289
+ .__jux-footer { padding: 16px 24px; background: #fff; border-top: 1px solid #e5e7eb; display: flex; justify-content: space-between; align-items: center; }
290
+ .__jux-tip { color: #6b7280; font-size: 12px; }
291
+ .__jux-dismiss { background: #f3f4f6; color: #374151; border: 1px solid #d1d5db; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 13px; font-weight: 500; }
292
+ .__jux-dismiss:hover { background: #e5e7eb; }
293
+ .__jux-no-source { color: #6b7280; padding: 24px; text-align: center; }
294
+ .__jux-no-source pre { background: #fff; padding: 16px; border-radius: 8px; margin-top: 16px; font-size: 11px; color: #6b7280; overflow-x: auto; text-align: left; border: 1px solid #e5e7eb; }
295
+ \`,
296
+
297
+ show: async function(error, title) {
298
+ title = title || 'Runtime Error';
299
+ var existing = document.getElementById('__jux-error-overlay');
300
+ if (existing) existing.remove();
301
+ await __juxLoadSources();
302
+
303
+ var overlay = document.createElement('div');
304
+ overlay.id = '__jux-error-overlay';
305
+ var stack = error && error.stack ? error.stack : '';
306
+ var msg = error && error.message ? error.message : String(error);
307
+ var found = __juxFindSource(stack);
308
+ var sourceHtml = '', fileInfo = '';
309
+
310
+ if (found && found.source && found.source.lines) {
311
+ var lines = found.source.lines;
312
+ fileInfo = '<span class="file-info">in <strong>' + found.file + '</strong></span>';
313
+ var errorLineIndex = -1;
314
+ var errorMethod = msg.match(/\\.([a-zA-Z]+)\\s*is not a function/);
315
+ if (errorMethod) {
316
+ for (var i = 0; i < lines.length; i++) {
317
+ if (lines[i].indexOf('.' + errorMethod[1]) > -1) { errorLineIndex = i; break; }
318
+ }
319
+ }
320
+ if (errorLineIndex === -1) {
321
+ for (var i = 0; i < lines.length; i++) {
322
+ if (lines[i].indexOf('throw ') > -1) { errorLineIndex = i; break; }
323
+ }
324
+ }
325
+ var contextStart = Math.max(0, errorLineIndex - 3);
326
+ var contextEnd = Math.min(lines.length - 1, errorLineIndex + 5);
327
+ if (errorLineIndex === -1) { contextStart = 0; contextEnd = Math.min(14, lines.length - 1); }
328
+
329
+ for (var i = contextStart; i <= contextEnd; i++) {
330
+ var isError = (i === errorLineIndex);
331
+ var isContext = !isError && errorLineIndex > -1 && Math.abs(i - errorLineIndex) <= 2;
332
+ var lineClass = isError ? ' error' : (isContext ? ' context' : '');
333
+ var lineCode = lines[i].replace(/</g, '&lt;').replace(/>/g, '&gt;') || ' ';
334
+ sourceHtml += '<div class="__jux-code-line' + lineClass + '"><span class="__jux-line-num">' + (i + 1) + '</span><span class="__jux-line-code">' + lineCode + '</span></div>';
335
+ }
336
+ } else {
337
+ sourceHtml = '<div class="__jux-no-source"><p>Could not locate source file.</p><pre>' + stack + '</pre></div>';
338
+ }
339
+
340
+ overlay.innerHTML = '<style>' + this.styles + '</style><div class="__jux-modal"><div class="__jux-header"><h3>' + title + '</h3><h1>' + msg + '</h1>' + fileInfo + '</div><div class="__jux-source"><div class="__jux-code">' + sourceHtml + '</div></div><div class="__jux-footer"><span class="__jux-tip">💡 Fix the error and save to reload</span><button class="__jux-dismiss" onclick="document.getElementById(\\'__jux-error-overlay\\').remove()">Dismiss</button></div></div>';
341
+ document.body.appendChild(overlay);
342
+ requestAnimationFrame(function() { overlay.classList.add('visible'); });
343
+ console.error(title + ':', error);
344
+ }
345
+ };
346
+
347
+ window.addEventListener('error', function(e) { __juxErrorOverlay.show(e.error || new Error(e.message), 'Uncaught Error'); }, true);
348
+ window.addEventListener('unhandledrejection', function(e) { __juxErrorOverlay.show(e.reason || new Error('Promise rejected'), 'Unhandled Promise Rejection'); }, true);
349
+
350
+ // --- JUX ROUTER ---
351
+ const routes = {\n${routeMap}};
352
+
353
+ async function navigate(path) {
354
+ const view = routes[path];
355
+ if (!view) {
356
+ document.getElementById('app').innerHTML = '<h1 style="padding:40px;">404 - Not Found</h1>';
357
+ return;
358
+ }
359
+ document.getElementById('app').innerHTML = '';
360
+ var overlay = document.getElementById('__jux-error-overlay');
361
+ if (overlay) overlay.remove();
362
+ try { await view(); } catch (err) { __juxErrorOverlay.show(err, 'Jux Render Error'); }
363
+ }
364
+
365
+ document.addEventListener('click', e => {
366
+ const a = e.target.closest('a');
367
+ if (!a || a.dataset.router === 'false') return;
368
+ try { if (new URL(a.href, location.origin).origin !== location.origin) return; } catch { return; }
369
+ e.preventDefault();
370
+ history.pushState({}, '', a.href);
371
+ navigate(new URL(a.href, location.origin).pathname);
372
+ });
373
+
374
+ window.addEventListener('popstate', () => navigate(location.pathname));
375
+ navigate(location.pathname);
376
+ `;
377
+ }
378
+
379
+ /**
380
+ * ✅ Generate route path from file path
381
+ * Examples:
382
+ * index.jux -> /
383
+ * abc/juxabc.jux -> /abc/juxabc
384
+ * abc/index.jux -> /abc
385
+ */
386
+ _generateRoutePath(filePath) {
387
+ // Normalize separators
388
+ const normalized = filePath.replace(/\\/g, '/');
389
+
390
+ // Remove extension
391
+ const withoutExt = normalized.replace(/\.[^/.]+$/, '');
392
+
393
+ // Handle index files
394
+ if (withoutExt === 'index') {
395
+ return '/';
396
+ }
397
+
398
+ // Remove trailing /index
399
+ const cleaned = withoutExt.replace(/\/index$/, '');
400
+
401
+ // Ensure leading slash
402
+ return '/' + cleaned.toLowerCase();
403
+ }
404
+
405
+ /**
406
+ * ✅ Generate PascalCase function name from sanitized name
407
+ * Examples:
408
+ * abc_juxabc -> AbcJuxabc
409
+ * index -> Index
410
+ */
411
+ _generateFunctionName(name) {
412
+ return name
413
+ .split('_')
414
+ .map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
415
+ .join('');
416
+ }
417
+
418
+ /**
419
+ * ✅ Generate entry point with nested folder support
175
420
  */
176
421
  generateEntryPoint(views, dataModules, sharedModules) {
177
422
  let entry = `// Auto-generated JUX entry point\n\n`;
@@ -209,7 +454,7 @@ export class JuxCompiler {
209
454
  entry += `\n// --- VIEW FUNCTIONS ---\n`;
210
455
 
211
456
  views.forEach(v => {
212
- const capitalized = v.name.charAt(0).toUpperCase() + v.name.slice(1);
457
+ const functionName = this._generateFunctionName(v.name);
213
458
  allIssues.push(...this.validateViewCode(v.name, v.content));
214
459
 
215
460
  sourceSnapshot[v.file] = {
@@ -222,7 +467,7 @@ export class JuxCompiler {
222
467
  let viewCode = this.removeImports(v.content).replace(/^\s*export\s+default\s+.*$/gm, '');
223
468
  const asyncPrefix = viewCode.includes('await ') ? 'async ' : '';
224
469
 
225
- entry += `\n${asyncPrefix}function render${capitalized}() {\n${viewCode}\n}\n`;
470
+ entry += `\n${asyncPrefix}function render${functionName}() {\n${viewCode}\n}\n`;
226
471
  });
227
472
 
228
473
  dataModules.forEach(m => {
@@ -257,10 +502,17 @@ export class JuxCompiler {
257
502
 
258
503
  _generateRouter(views) {
259
504
  let routeMap = '';
505
+
260
506
  views.forEach(v => {
261
- const cap = v.name.charAt(0).toUpperCase() + v.name.slice(1);
262
- if (v.name.toLowerCase() === 'index') routeMap += ` '/': render${cap},\n`;
263
- routeMap += ` '/${v.name.toLowerCase()}': render${cap},\n`;
507
+ // Generate route from folder structure
508
+ // abc/juxabc.jux -> /abc/juxabc
509
+ // index.jux -> /
510
+ // abc/index.jux -> /abc
511
+
512
+ const routePath = this._generateRoutePath(v.file);
513
+ const functionName = this._generateFunctionName(v.name);
514
+
515
+ routeMap += ` '${routePath}': render${functionName},\n`;
264
516
  });
265
517
 
266
518
  return `
@@ -278,12 +530,17 @@ async function __juxLoadSources() {
278
530
  }
279
531
 
280
532
  function __juxFindSource(stack) {
281
- var match = stack.match(/render(\\w+)/);
533
+ var match = stack.match(/render([A-Z][a-zA-Z0-9_]*)/);
282
534
  if (match) {
283
- var viewName = match[1].toLowerCase();
535
+ var funcName = match[1];
284
536
  for (var file in __juxSources || {}) {
285
- if (__juxSources[file].name.toLowerCase() === viewName) {
286
- return { file: file, source: __juxSources[file], viewName: match[1] };
537
+ var normalized = __juxSources[file].name
538
+ .split('_')
539
+ .map(s => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase())
540
+ .join('');
541
+
542
+ if (normalized === funcName) {
543
+ return { file: file, source: __juxSources[file], viewName: funcName };
287
544
  }
288
545
  }
289
546
  }
@@ -414,94 +671,6 @@ navigate(location.pathname);
414
671
  `;
415
672
  }
416
673
 
417
- async build() {
418
- console.log('🚀 JUX Build\n');
419
-
420
- const juxscriptPath = this.findJuxscriptPath();
421
- if (!juxscriptPath) {
422
- console.error('❌ Could not locate juxscript package');
423
- return { success: false, errors: [{ message: 'juxscript not found' }], warnings: [] };
424
- }
425
- console.log(`📦 Using: ${juxscriptPath}`);
426
-
427
- await this.loadJuxscriptExports();
428
-
429
- if (fs.existsSync(this.distDir)) {
430
- fs.rmSync(this.distDir, { recursive: true, force: true });
431
- }
432
- fs.mkdirSync(this.distDir, { recursive: true });
433
-
434
- // ✅ Copy public folder if exists
435
- this.copyPublicFolder();
436
-
437
- const { views, dataModules, sharedModules } = this.scanFiles();
438
- console.log(`📁 Found ${views.length} views, ${sharedModules.length} shared, ${dataModules.length} data`);
439
-
440
- // Copy data/shared modules to dist
441
- const juxDistDir = path.join(this.distDir, 'jux');
442
- fs.mkdirSync(juxDistDir, { recursive: true });
443
- [...dataModules, ...sharedModules].forEach(m => {
444
- fs.writeFileSync(path.join(juxDistDir, m.file), m.content);
445
- });
446
-
447
- const entryContent = this.generateEntryPoint(views, dataModules, sharedModules);
448
- const entryPath = path.join(this.distDir, 'entry.js');
449
- fs.writeFileSync(entryPath, entryContent);
450
-
451
- const snapshotPath = path.join(this.distDir, '__jux_sources.json');
452
- fs.writeFileSync(snapshotPath, JSON.stringify(this._sourceSnapshot, null, 2));
453
- console.log(`📸 Source snapshot written`);
454
-
455
- const validation = this.reportValidationIssues();
456
- if (!validation.isValid) {
457
- console.log('🛑 BUILD FAILED\n');
458
- return { success: false, errors: validation.errors, warnings: validation.warnings };
459
- }
460
-
461
- try {
462
- await esbuild.build({
463
- entryPoints: [entryPath],
464
- bundle: true,
465
- outfile: path.join(this.distDir, 'bundle.js'),
466
- format: 'esm',
467
- platform: 'browser',
468
- target: 'esnext',
469
- sourcemap: true,
470
- loader: { '.jux': 'js', '.css': 'empty' },
471
- plugins: [{
472
- name: 'juxscript-resolver',
473
- setup: (build) => {
474
- build.onResolve({ filter: /^juxscript$/ }, () => ({ path: juxscriptPath }));
475
- }
476
- }],
477
- });
478
- console.log('✅ esbuild complete');
479
- } catch (err) {
480
- console.error('❌ esbuild failed:', err);
481
- return { success: false, errors: [{ message: err.message }], warnings: [] };
482
- }
483
-
484
- const html = `<!DOCTYPE html>
485
- <html lang="en">
486
- <head>
487
- <meta charset="UTF-8">
488
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
489
- <title>JUX App</title>
490
- <script type="module" src="./bundle.js"></script>
491
- </head>
492
- <body>
493
- <div id="app"></div>
494
- </body>
495
- </html>`;
496
- fs.writeFileSync(path.join(this.distDir, 'index.html'), html);
497
-
498
- fs.unlinkSync(entryPath);
499
- fs.rmSync(juxDistDir, { recursive: true, force: true });
500
-
501
- console.log(`\n✅ Build Complete!\n`);
502
- return { success: true, errors: [], warnings: validation.warnings };
503
- }
504
-
505
674
  /**
506
675
  * Copy public folder contents to dist
507
676
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "juxscript",
3
- "version": "1.1.91",
3
+ "version": "1.1.92",
4
4
  "type": "module",
5
5
  "description": "A JavaScript UX authorship platform",
6
6
  "main": "index.js",