@stacksjs/stx 0.2.110 → 0.2.112
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/cli.js +734 -643
- package/dist/expressions.js +6 -1
- package/dist/includes.js +8 -8
- package/dist/parser/directive-parser.d.ts +15 -0
- package/dist/parser/directive-parser.js +10 -0
- package/dist/pwa.js +466 -375
- package/dist/signal-processing.js +62 -56
- package/dist/signals.js +107 -13
- package/dist/ssg.js +555 -464
- package/dist/style-scoping.d.ts +0 -3
- package/dist/style-scoping.js +4 -3
- package/dist/variable-extractor.js +1 -1
- package/dist/web-components/css-scoping.js +33 -0
- package/package.json +5 -5
package/dist/expressions.js
CHANGED
|
@@ -269,12 +269,17 @@ function expressionUsesOnlyContextVars(expr, context) {
|
|
|
269
269
|
if (ch === "$" && exprWithoutStrings[ti + 1] === "{") {
|
|
270
270
|
tplDepth++;
|
|
271
271
|
ti++;
|
|
272
|
+
tplResult += " ";
|
|
272
273
|
continue;
|
|
273
274
|
}
|
|
274
275
|
if (ch === "}" && tplDepth > 0) {
|
|
275
276
|
tplDepth--;
|
|
276
277
|
continue;
|
|
277
278
|
}
|
|
279
|
+
if (tplDepth > 0) {
|
|
280
|
+
tplResult += ch;
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
278
283
|
continue;
|
|
279
284
|
}
|
|
280
285
|
tplResult += ch;
|
|
@@ -378,7 +383,7 @@ export function processExpressions(template, context, filePath, options) {
|
|
|
378
383
|
return "";
|
|
379
384
|
try {
|
|
380
385
|
const value = evaluateExpression(expr, context);
|
|
381
|
-
if (
|
|
386
|
+
if (hasSignals && !expressionUsesOnlyContextVars(trimmedExpr, context))
|
|
382
387
|
return match;
|
|
383
388
|
if (value === void 0 && context.__stx_buildMode === "compile" && !hasSignals)
|
|
384
389
|
return createPlaceholder("expr", trimmedExpr);
|
package/dist/includes.js
CHANGED
|
@@ -189,8 +189,8 @@ ${scriptContent}
|
|
|
189
189
|
${tail}})();
|
|
190
190
|
`;
|
|
191
191
|
}
|
|
192
|
-
function
|
|
193
|
-
|
|
192
|
+
function buildScopeRegistrationTail(scriptContent, scopeId) {
|
|
193
|
+
return `
|
|
194
194
|
// Register scope variables for STX runtime
|
|
195
195
|
if (!window.stx._scopes) window.stx._scopes = {};
|
|
196
196
|
var __scopeRegistration = { __destroyCallbacks: __destroyHooks };
|
|
@@ -202,7 +202,10 @@ ${extractExports(scriptContent).split(",").map((s) => s.trim()).filter(Boolean).
|
|
|
202
202
|
// shadowing import. __stxScopeRenames is emitted by bundleClientScript.
|
|
203
203
|
try { if (typeof __stxScopeRenames !== 'undefined' && __stxScopeRenames) { for (var __stxRK in __stxScopeRenames) __scopeRegistration[__stxRK] = __stxScopeRenames[__stxRK]; } } catch (e) { /* no renames */ }
|
|
204
204
|
window.stx._scopes['${scopeId}'] = __scopeRegistration;
|
|
205
|
-
|
|
205
|
+
`;
|
|
206
|
+
}
|
|
207
|
+
function transformSignalScript(scriptContent, scopeId) {
|
|
208
|
+
const tail = buildScopeRegistrationTail(scriptContent, scopeId), head = `
|
|
206
209
|
(function() {
|
|
207
210
|
var __stxScopeEl = (typeof document !== 'undefined') ? document.querySelector('[data-stx-scope="${scopeId}"]') : null;
|
|
208
211
|
var __stxPrevEl = (typeof window !== 'undefined') ? window.__STX_CURRENT_ELEMENT__ : undefined;
|
|
@@ -542,7 +545,7 @@ export async function processIncludes(template, context, filePath, options, depe
|
|
|
542
545
|
if (options.debug)
|
|
543
546
|
console.warn(`[stx] partial ES import extraction skipped for ${includeFilePath}:`, err instanceof Error ? err.message : err);
|
|
544
547
|
}
|
|
545
|
-
const templateMatch = workingContent.match(/<template\b(?![^>]*(?:\b(?:id|x-for|x-if|@for|@if|:for|:if)\s*=|\s#[\w-]|\bv-slot|\bslot\s*=))[^>]*>([\s\S]*?)<\/template>/i);
|
|
548
|
+
const templateMatch = workingContent.match(/<template\b(?![^>]*(?:\b(?:id|x-for|x-if|x-else|@for|@if|@else|:for|:if|:else)\s*=|\s#[\w-]|\bv-slot|\bslot\s*=))[^>]*>([\s\S]*?)<\/template>/i);
|
|
546
549
|
if (templateMatch)
|
|
547
550
|
workingContent = templateMatch[1].trim();
|
|
548
551
|
const styleMatch = partialContent.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, "").match(/<style\b([^>]*)>([\s\S]*?)<\/style>/i);
|
|
@@ -604,10 +607,7 @@ export async function processIncludes(template, context, filePath, options, depe
|
|
|
604
607
|
if (!isServerScript && !isSignalScript) {
|
|
605
608
|
const extraAttrs = scriptAttrs.replace(/\bclient\b/i, "").trim();
|
|
606
609
|
signalScopeId = `stx_scope_${path.basename(includeFilePath, ".stx").replace(/[^a-zA-Z0-9]/g, "_")}_${++scopeIdCounter}`;
|
|
607
|
-
const resolvedContent = transformStoreImports(scriptContent), tail =
|
|
608
|
-
if (!window.stx._scopes) window.stx._scopes = {};
|
|
609
|
-
window.stx._scopes['${signalScopeId}'] = { __destroyCallbacks: __destroyHooks };
|
|
610
|
-
`, wrapped = wrapClientScript(resolvedContent, tail);
|
|
610
|
+
const resolvedContent = transformStoreImports(scriptContent), tail = buildScopeRegistrationTail(resolvedContent, signalScopeId), wrapped = wrapClientScript(resolvedContent, tail);
|
|
611
611
|
preservedScript += `${vendorStyleTags}<script data-stx-scoped${extraAttrs ? ` ${extraAttrs}` : ""}>${wrapped}</script>
|
|
612
612
|
`;
|
|
613
613
|
}
|
|
@@ -11,6 +11,21 @@ export declare function extractParenthesizedExpression(source: string, startPos:
|
|
|
11
11
|
endPos: number
|
|
12
12
|
} | null;
|
|
13
13
|
export declare function extractParenthesizedExpressionDetailed(source: string, startPos: number): ExtractParenResult;
|
|
14
|
+
/**
|
|
15
|
+
* Whether `pos` in `source` falls INSIDE an HTML tag (`<...>`) — i.e. the nearest
|
|
16
|
+
* angle bracket looking backwards is an unclosed `<`.
|
|
17
|
+
*
|
|
18
|
+
* Directive tokens (`@if`/`@elseif`/`@else`/`@endif`) only ever occur in text
|
|
19
|
+
* content, never inside a tag. The reactive-signal pass, however, rewrites a
|
|
20
|
+
* NESTED reactive conditional into HTML-attribute markers BEFORE this server pass
|
|
21
|
+
* runs — e.g. `@if (isPro())A@else B@endif` becomes
|
|
22
|
+
* `<template @if="isPro()">A</template><template @else>B</template>`. Without this
|
|
23
|
+
* guard the branch scanner matches that `@else` ATTRIBUTE as the enclosing server
|
|
24
|
+
* `@if`'s top-level `@else`, mismatching branch/`@endif` boundaries and corrupting
|
|
25
|
+
* the rest of the template. Skipping tag-interior tokens keeps the two passes from
|
|
26
|
+
* disagreeing on what is a directive.
|
|
27
|
+
*/
|
|
28
|
+
export declare function isInsideTag(source: string, pos: number): boolean;
|
|
14
29
|
/**
|
|
15
30
|
* Find the matching end tag for a directive, handling nested instances
|
|
16
31
|
*
|
|
@@ -14,6 +14,12 @@ export function extractParenthesizedExpressionDetailed(source, startPos) {
|
|
|
14
14
|
return { ok: !1, reason: "unclosed-paren", pos };
|
|
15
15
|
return { ok: !0, expression: source.slice(pos + 1, closePos), endPos: closePos + 1 };
|
|
16
16
|
}
|
|
17
|
+
export function isInsideTag(source, pos) {
|
|
18
|
+
const lastOpen = source.lastIndexOf("<", pos);
|
|
19
|
+
if (lastOpen === -1)
|
|
20
|
+
return !1;
|
|
21
|
+
return lastOpen > source.lastIndexOf(">", pos);
|
|
22
|
+
}
|
|
17
23
|
export function findMatchingEndTag(source, startName, endName, startPos) {
|
|
18
24
|
let depth = 1, pos = startPos;
|
|
19
25
|
const openPattern = new RegExp(`@${startName}\\s*\\(`, "g"), closePattern = new RegExp(`@${endName}(?![a-z])`, "g");
|
|
@@ -52,6 +58,10 @@ export function parseConditionalBlock(source, startPos) {
|
|
|
52
58
|
break;
|
|
53
59
|
currentPos = atIdx;
|
|
54
60
|
const remaining = fullContent.substring(atIdx);
|
|
61
|
+
if (isInsideTag(fullContent, atIdx)) {
|
|
62
|
+
currentPos++;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
55
65
|
if (/^@if\s*\(/.test(remaining)) {
|
|
56
66
|
nestedDepth++;
|
|
57
67
|
currentPos++;
|