juxscript 1.1.156 → 1.1.157

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.
@@ -374,17 +374,24 @@ export class JuxCompiler {
374
374
  views.forEach((v, index) => {
375
375
  const functionName = `renderJux${index}`;
376
376
 
377
+ let codeBody = v.originalContent || v.content;
378
+ const originalLines = codeBody.split('\n');
379
+ codeBody = this._stripImportsAndExports(codeBody);
380
+ const strippedLines = codeBody.split('\n');
381
+
382
+ // Build a line map: for each stripped line, find its original line number
383
+ const lineMap = this._buildLineMap(originalLines, strippedLines);
384
+
377
385
  sourceSnapshot[v.file] = {
378
386
  name: v.name,
379
387
  file: v.file,
380
388
  content: v.originalContent || v.content,
381
- lines: (v.originalContent || v.content).split('\n'),
389
+ lines: originalLines,
390
+ strippedLines: strippedLines,
391
+ lineMap: lineMap,
382
392
  functionName
383
393
  };
384
394
 
385
- let codeBody = v.originalContent || v.content;
386
- codeBody = this._stripImportsAndExports(codeBody);
387
-
388
395
  entry += `\nasync function ${functionName}() {\n${codeBody}\n}\n`;
389
396
 
390
397
  // Generate route path
@@ -843,4 +850,39 @@ window.navigateTo = (path) => {
843
850
  .replace(/_+/g, '_') // Collapse multiple consecutive underscores
844
851
  .replace(/^_|_$/g, ''); // Remove leading/trailing underscores
845
852
  }
853
+
854
+ /**
855
+ * Build a mapping from stripped line index to original source line number.
856
+ * For each line in strippedLines, find the best matching line in originalLines.
857
+ */
858
+ _buildLineMap(originalLines, strippedLines) {
859
+ const lineMap = [];
860
+ let searchFrom = 0;
861
+
862
+ for (let i = 0; i < strippedLines.length; i++) {
863
+ const stripped = strippedLines[i].trim();
864
+ if (!stripped) {
865
+ // Empty line — estimate position
866
+ lineMap.push(searchFrom < originalLines.length ? searchFrom + 1 : originalLines.length);
867
+ continue;
868
+ }
869
+
870
+ let found = false;
871
+ for (let j = searchFrom; j < originalLines.length; j++) {
872
+ if (originalLines[j].trim() === stripped) {
873
+ lineMap.push(j + 1); // 1-based
874
+ searchFrom = j + 1;
875
+ found = true;
876
+ break;
877
+ }
878
+ }
879
+
880
+ if (!found) {
881
+ // Fallback: use last known position
882
+ lineMap.push(searchFrom < originalLines.length ? searchFrom + 1 : originalLines.length);
883
+ }
884
+ }
885
+
886
+ return lineMap;
887
+ }
846
888
  }
@@ -61,8 +61,6 @@ export function generateErrorCollector(options = {}) {
61
61
  function resolveSourceLocation(bundleLine) {
62
62
  if (!__sources || !__bundleLines || !bundleLine) return null;
63
63
 
64
- // Find the renderJuxN function that contains this line
65
- // by scanning backwards from bundleLine for "async function renderJux"
66
64
  var funcName = null;
67
65
  var funcStartLine = 0;
68
66
  for (var i = bundleLine - 1; i >= 0; i--) {
@@ -71,14 +69,13 @@ export function generateErrorCollector(options = {}) {
71
69
  var match = line.match(/async\\s+function\\s+(renderJux\\d+)/);
72
70
  if (match) {
73
71
  funcName = match[1];
74
- funcStartLine = i + 1; // 1-based
72
+ funcStartLine = i + 1;
75
73
  break;
76
74
  }
77
75
  }
78
76
 
79
77
  if (!funcName) return null;
80
78
 
81
- // Find the source entry that maps to this function
82
79
  var sourceEntry = null;
83
80
  for (var key in __sources) {
84
81
  if (__sources[key].functionName === funcName) {
@@ -89,26 +86,34 @@ export function generateErrorCollector(options = {}) {
89
86
 
90
87
  if (!sourceEntry) return null;
91
88
 
92
- // Calculate approximate original line
93
- // bundleLine is inside the function body, funcStartLine is the function declaration
94
- // +1 because function body starts after the declaration line
89
+ // Index into the function body (0-based)
95
90
  var offsetInFunc = bundleLine - funcStartLine - 1;
91
+ var lineMap = sourceEntry.lineMap || [];
96
92
  var originalLines = sourceEntry.lines || [];
97
- var approxLine = Math.max(0, Math.min(offsetInFunc, originalLines.length - 1));
93
+
94
+ // Use lineMap for accurate resolution
95
+ var originalLineNum;
96
+ if (lineMap.length > 0 && offsetInFunc >= 0 && offsetInFunc < lineMap.length) {
97
+ originalLineNum = lineMap[offsetInFunc]; // already 1-based
98
+ } else {
99
+ // Fallback: direct offset
100
+ originalLineNum = Math.max(1, Math.min(offsetInFunc + 1, originalLines.length));
101
+ }
102
+
103
+ var lineIndex = originalLineNum - 1;
104
+ var contextRadius = 3;
105
+ var contextStart = Math.max(0, lineIndex - contextRadius);
106
+ var contextEnd = Math.min(originalLines.length, lineIndex + contextRadius + 1);
98
107
 
99
108
  return {
100
109
  file: sourceEntry.file,
101
110
  name: sourceEntry.name,
102
111
  functionName: funcName,
103
- originalLine: approxLine + 1,
104
- originalCode: originalLines[approxLine] || '',
105
- // Provide surrounding context (3 lines before/after)
106
- context: originalLines.slice(
107
- Math.max(0, approxLine - 3),
108
- Math.min(originalLines.length, approxLine + 4)
109
- ),
110
- contextStartLine: Math.max(0, approxLine - 3) + 1,
111
- highlightLine: approxLine + 1
112
+ originalLine: originalLineNum,
113
+ originalCode: originalLines[lineIndex] || '',
114
+ context: originalLines.slice(contextStart, contextEnd),
115
+ contextStartLine: contextStart + 1,
116
+ highlightLine: originalLineNum
112
117
  };
113
118
  }
114
119
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "juxscript",
3
- "version": "1.1.156",
3
+ "version": "1.1.157",
4
4
  "type": "module",
5
5
  "description": "A JavaScript UX authorship platform",
6
6
  "main": "index.js",