juxscript 1.1.378 → 1.1.380
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/dist/components/button.d.ts +4 -0
- package/dist/components/button.d.ts.map +1 -1
- package/dist/components/button.js +13 -1
- package/dist/components/button.js.map +1 -1
- package/dist/components/checkbox.d.ts +6 -0
- package/dist/components/checkbox.d.ts.map +1 -1
- package/dist/components/checkbox.js +14 -0
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/input.d.ts +12 -0
- package/dist/components/input.d.ts.map +1 -1
- package/dist/components/input.js +43 -0
- package/dist/components/input.js.map +1 -1
- package/dist/components/link.d.ts +4 -0
- package/dist/components/link.d.ts.map +1 -1
- package/dist/components/link.js +13 -1
- package/dist/components/link.js.map +1 -1
- package/dist/components/list.d.ts +6 -0
- package/dist/components/list.d.ts.map +1 -1
- package/dist/components/list.js +26 -1
- package/dist/components/list.js.map +1 -1
- package/dist/components/nav.d.ts +6 -0
- package/dist/components/nav.d.ts.map +1 -1
- package/dist/components/nav.js +16 -0
- package/dist/components/nav.js.map +1 -1
- package/dist/components/radio.d.ts +3 -0
- package/dist/components/radio.d.ts.map +1 -1
- package/dist/components/radio.js +7 -0
- package/dist/components/radio.js.map +1 -1
- package/dist/components/select.d.ts +9 -0
- package/dist/components/select.d.ts.map +1 -1
- package/dist/components/select.js +31 -0
- package/dist/components/select.js.map +1 -1
- package/dist/components/tag.d.ts +5 -0
- package/dist/components/tag.d.ts.map +1 -1
- package/dist/components/tag.js +16 -1
- package/dist/components/tag.js.map +1 -1
- package/machinery/autowrap.js +103 -24
- package/package.json +1 -1
package/machinery/autowrap.js
CHANGED
|
@@ -31,6 +31,31 @@ function isPageStateAccess(node) {
|
|
|
31
31
|
return false;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Checks if a node is a `.state.xxx` access on a known jux component variable.
|
|
36
|
+
* e.g. `btn2.state.click` where `btn2` is in juxVarNames
|
|
37
|
+
*/
|
|
38
|
+
function isComponentStateAccess(node, juxVarNames) {
|
|
39
|
+
if (node.type !== 'MemberExpression') return false;
|
|
40
|
+
const obj = node.object;
|
|
41
|
+
// Pattern: <varName>.state.<prop>
|
|
42
|
+
if (obj.type === 'MemberExpression' &&
|
|
43
|
+
obj.object.type === 'Identifier' &&
|
|
44
|
+
juxVarNames.has(obj.object.name) &&
|
|
45
|
+
obj.property.type === 'Identifier' &&
|
|
46
|
+
obj.property.name === 'state') {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
// Pattern: <varName>.state (without further property — still reactive)
|
|
50
|
+
if (node.object.type === 'Identifier' &&
|
|
51
|
+
juxVarNames.has(node.object.name) &&
|
|
52
|
+
node.property.type === 'Identifier' &&
|
|
53
|
+
node.property.name === 'state') {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
34
59
|
function containsPageStateRef(node) {
|
|
35
60
|
let found = false;
|
|
36
61
|
walkSimple(node, {
|
|
@@ -39,6 +64,24 @@ function containsPageStateRef(node) {
|
|
|
39
64
|
return found;
|
|
40
65
|
}
|
|
41
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Checks if a node tree contains any .state. access on known jux component variables.
|
|
69
|
+
*/
|
|
70
|
+
function containsComponentStateRef(node, juxVarNames) {
|
|
71
|
+
let found = false;
|
|
72
|
+
walkSimple(node, {
|
|
73
|
+
MemberExpression(n) { if (isComponentStateAccess(n, juxVarNames)) found = true; }
|
|
74
|
+
});
|
|
75
|
+
return found;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Returns true if the node contains either a pageState ref or a component .state. ref.
|
|
80
|
+
*/
|
|
81
|
+
function containsAnyReactiveRef(node, juxVarNames) {
|
|
82
|
+
return containsPageStateRef(node) || containsComponentStateRef(node, juxVarNames);
|
|
83
|
+
}
|
|
84
|
+
|
|
42
85
|
function containsJuxCall(node) {
|
|
43
86
|
let found = false;
|
|
44
87
|
walkSimple(node, {
|
|
@@ -118,6 +161,51 @@ function containsAwait(node) {
|
|
|
118
161
|
return found;
|
|
119
162
|
}
|
|
120
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Collects variable names that are assigned from jux.xxx() calls.
|
|
166
|
+
* e.g. `let btn2 = jux.btn('id')` → adds 'btn2' to the set.
|
|
167
|
+
*/
|
|
168
|
+
function collectJuxVarNames(ast) {
|
|
169
|
+
const names = new Set();
|
|
170
|
+
for (const stmt of ast.body) {
|
|
171
|
+
if (stmt.type === 'VariableDeclaration') {
|
|
172
|
+
for (const decl of stmt.declarations) {
|
|
173
|
+
if (decl.id.type === 'Identifier' && decl.init) {
|
|
174
|
+
let call = decl.init;
|
|
175
|
+
// Unwrap chained calls: jux.btn('x').onClick(...)
|
|
176
|
+
while (call.type === 'CallExpression' &&
|
|
177
|
+
call.callee.type === 'MemberExpression' &&
|
|
178
|
+
call.callee.object.type === 'CallExpression') {
|
|
179
|
+
call = call.callee.object;
|
|
180
|
+
}
|
|
181
|
+
if (call.type === 'CallExpression' &&
|
|
182
|
+
call.callee?.type === 'MemberExpression' &&
|
|
183
|
+
call.callee.object?.type === 'Identifier' &&
|
|
184
|
+
call.callee.object.name === 'jux') {
|
|
185
|
+
names.add(decl.id.name);
|
|
186
|
+
}
|
|
187
|
+
// Also handle: await jux.xxx()
|
|
188
|
+
if (call.type === 'AwaitExpression') {
|
|
189
|
+
let inner = call.argument;
|
|
190
|
+
while (inner?.type === 'CallExpression' &&
|
|
191
|
+
inner.callee?.type === 'MemberExpression' &&
|
|
192
|
+
inner.callee.object?.type === 'CallExpression') {
|
|
193
|
+
inner = inner.callee.object;
|
|
194
|
+
}
|
|
195
|
+
if (inner?.type === 'CallExpression' &&
|
|
196
|
+
inner.callee?.type === 'MemberExpression' &&
|
|
197
|
+
inner.callee.object?.type === 'Identifier' &&
|
|
198
|
+
inner.callee.object.name === 'jux') {
|
|
199
|
+
names.add(decl.id.name);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return names;
|
|
207
|
+
}
|
|
208
|
+
|
|
121
209
|
/**
|
|
122
210
|
* @param {string} source - Raw .jux source code
|
|
123
211
|
* @param {string} [filename] - For logging
|
|
@@ -136,23 +224,23 @@ export function autowrap(source, filename = '') {
|
|
|
136
224
|
return { code: source, wrappedCount: 0, details: [`parse error: ${err.message}`] };
|
|
137
225
|
}
|
|
138
226
|
|
|
227
|
+
// Collect jux component variable names for .state. detection
|
|
228
|
+
const juxVarNames = collectJuxVarNames(ast);
|
|
229
|
+
|
|
139
230
|
const needsWatch = [];
|
|
140
231
|
let i = 0;
|
|
141
232
|
|
|
142
233
|
while (i < ast.body.length) {
|
|
143
234
|
const stmt = ast.body[i];
|
|
144
235
|
|
|
145
|
-
if (isSetupStatement(stmt)) { i++; continue; }
|
|
236
|
+
if (isSetupStatement(stmt) && !containsComponentStateRef(stmt, juxVarNames)) { i++; continue; }
|
|
146
237
|
|
|
147
238
|
// Check if this is a single __watch that contains multiple independent concerns
|
|
148
|
-
// If so, unwrap it and re-wrap each concern separately
|
|
149
239
|
if (isAlreadyWrapped(stmt)) {
|
|
150
240
|
const bodyStmts = getWatchBody(stmt);
|
|
151
241
|
if (bodyStmts && bodyStmts.length > 1) {
|
|
152
|
-
|
|
153
|
-
const groups = groupBodyStatements(bodyStmts, source);
|
|
242
|
+
const groups = groupBodyStatements(bodyStmts, source, juxVarNames);
|
|
154
243
|
if (groups.length > 1) {
|
|
155
|
-
// Verify no cross-group variable dependencies before splitting
|
|
156
244
|
const allDeclared = [];
|
|
157
245
|
let hasCrossDep = false;
|
|
158
246
|
for (const group of groups) {
|
|
@@ -160,7 +248,6 @@ export function autowrap(source, filename = '') {
|
|
|
160
248
|
for (const s of group.stmts) {
|
|
161
249
|
groupVars.push(...getDeclaredVarNames(s));
|
|
162
250
|
}
|
|
163
|
-
// Check if this group uses vars declared in a previous group
|
|
164
251
|
for (const s of group.stmts) {
|
|
165
252
|
if (allDeclared.some(v => usesIdentifier(s, v))) {
|
|
166
253
|
hasCrossDep = true;
|
|
@@ -187,19 +274,16 @@ export function autowrap(source, filename = '') {
|
|
|
187
274
|
continue;
|
|
188
275
|
}
|
|
189
276
|
|
|
190
|
-
// VariableDeclaration reading pageState
|
|
191
|
-
if (stmt.type === 'VariableDeclaration' &&
|
|
277
|
+
// VariableDeclaration reading pageState or component .state.
|
|
278
|
+
if (stmt.type === 'VariableDeclaration' && containsAnyReactiveRef(stmt, juxVarNames)) {
|
|
192
279
|
const varNames = [...getDeclaredVarNames(stmt)];
|
|
193
280
|
const groupStmts = [stmt];
|
|
194
281
|
let j = i + 1;
|
|
195
282
|
|
|
196
|
-
// Greedily consume following statements that use any of the declared variable names
|
|
197
283
|
while (j < ast.body.length) {
|
|
198
284
|
const next = ast.body[j];
|
|
199
|
-
// Check variable dependency FIRST — if it uses our vars, consume it
|
|
200
285
|
if (varNames.some(v => usesIdentifier(next, v))) {
|
|
201
286
|
groupStmts.push(next);
|
|
202
|
-
// Track any new variable declarations in the consumed statement
|
|
203
287
|
getDeclaredVarNames(next).forEach(v => varNames.push(v));
|
|
204
288
|
j++;
|
|
205
289
|
} else {
|
|
@@ -215,8 +299,8 @@ export function autowrap(source, filename = '') {
|
|
|
215
299
|
continue;
|
|
216
300
|
}
|
|
217
301
|
|
|
218
|
-
// Any other statement referencing pageState
|
|
219
|
-
if (
|
|
302
|
+
// Any other statement referencing pageState or component .state.
|
|
303
|
+
if (containsAnyReactiveRef(stmt, juxVarNames)) {
|
|
220
304
|
needsWatch.push({
|
|
221
305
|
line: getLineNumber(source, stmt.start),
|
|
222
306
|
endLine: getLineNumber(source, stmt.end),
|
|
@@ -287,29 +371,24 @@ export function autowrap(source, filename = '') {
|
|
|
287
371
|
|
|
288
372
|
/**
|
|
289
373
|
* Groups statements inside a __watch body into independent reactive groups.
|
|
290
|
-
* Uses the same logic as the top-level grouping: VariableDeclarations that
|
|
291
|
-
* read pageState get grouped with following statements that use those vars.
|
|
292
|
-
* Standalone if-statements with pageState become their own group.
|
|
293
374
|
*/
|
|
294
|
-
function groupBodyStatements(bodyStmts, source) {
|
|
375
|
+
function groupBodyStatements(bodyStmts, source, juxVarNames = new Set()) {
|
|
295
376
|
const groups = [];
|
|
296
377
|
let i = 0;
|
|
297
378
|
|
|
298
379
|
while (i < bodyStmts.length) {
|
|
299
380
|
const stmt = bodyStmts[i];
|
|
300
381
|
|
|
301
|
-
// VariableDeclaration reading pageState — group with dependents
|
|
302
|
-
if (stmt.type === 'VariableDeclaration' &&
|
|
382
|
+
// VariableDeclaration reading pageState or .state. — group with dependents
|
|
383
|
+
if (stmt.type === 'VariableDeclaration' && containsAnyReactiveRef(stmt, juxVarNames)) {
|
|
303
384
|
const varNames = getDeclaredVarNames(stmt);
|
|
304
385
|
const groupStmts = [stmt];
|
|
305
386
|
let j = i + 1;
|
|
306
387
|
|
|
307
388
|
while (j < bodyStmts.length) {
|
|
308
389
|
const next = bodyStmts[j];
|
|
309
|
-
|
|
310
|
-
if (varNames.some(v => usesIdentifier(next, v)) || !containsPageStateRef(next)) {
|
|
390
|
+
if (varNames.some(v => usesIdentifier(next, v)) || !containsAnyReactiveRef(next, juxVarNames)) {
|
|
311
391
|
groupStmts.push(next);
|
|
312
|
-
// Track any new variable declarations in the consumed statement
|
|
313
392
|
getDeclaredVarNames(next).forEach(v => varNames.push(v));
|
|
314
393
|
j++;
|
|
315
394
|
} else {
|
|
@@ -325,8 +404,8 @@ function groupBodyStatements(bodyStmts, source) {
|
|
|
325
404
|
continue;
|
|
326
405
|
}
|
|
327
406
|
|
|
328
|
-
// Any statement referencing
|
|
329
|
-
if (
|
|
407
|
+
// Any statement referencing reactive state — standalone group
|
|
408
|
+
if (containsAnyReactiveRef(stmt, juxVarNames)) {
|
|
330
409
|
groups.push({
|
|
331
410
|
stmts: [stmt],
|
|
332
411
|
lines: extractSourceLines([stmt], source),
|