@stacksjs/stx 0.2.100 → 0.2.101
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 +501 -501
- package/dist/pwa.js +272 -272
- package/dist/signal-processing.d.ts +27 -0
- package/dist/signal-processing.js +48 -28
- package/dist/ssg.js +355 -355
- package/package.json +5 -5
|
@@ -132,6 +132,33 @@ export declare function extractExports(setupContent: string): string;
|
|
|
132
132
|
* injects the signals runtime and browser runtime.
|
|
133
133
|
*/
|
|
134
134
|
export declare function processSignals(template: string, options: StxOptions, filePath?: string, serverData?: Record<string, unknown>): Promise<string>;
|
|
135
|
+
/**
|
|
136
|
+
* Index of the first `pattern` match in `html` that is not inside a `<script>`
|
|
137
|
+
* or `<style>` block, or -1 when every match is embedded.
|
|
138
|
+
*
|
|
139
|
+
* Markup landmarks cannot be located with a plain `indexOf` / `String.replace`
|
|
140
|
+
* once a runtime has been inlined: those scripts are hundreds of kilobytes of
|
|
141
|
+
* JavaScript that legitimately mention `<body>` and `</head>` in comments,
|
|
142
|
+
* strings and regex literals. Anchoring on the first textual hit splices
|
|
143
|
+
* generated markup into the middle of a script tag, which both corrupts the
|
|
144
|
+
* script and — when the inserted markup contains `</script>` — silently ends
|
|
145
|
+
* the tag early.
|
|
146
|
+
*/
|
|
147
|
+
export declare function findMarkupIndexOutsideScripts(html: string, pattern: RegExp): number;
|
|
148
|
+
/**
|
|
149
|
+
* Turn the specifier list of an `import { … } from 'stx'` into local aliases.
|
|
150
|
+
*
|
|
151
|
+
* The setup function already destructures the stx API from `window.stx`, so a
|
|
152
|
+
* plain `{ state }` specifier needs nothing. A RENAMED one does: when the
|
|
153
|
+
* bundler inlines a composable that imports a name the outer script already
|
|
154
|
+
* binds, it emits `import { state as state2 } from '@stacksjs/stx'`. Dropping
|
|
155
|
+
* that line loses the mapping and every `state2(…)` call in the inlined module
|
|
156
|
+
* throws `state2 is not defined` — which aborts the whole setup, so no
|
|
157
|
+
* directive on the page ever binds.
|
|
158
|
+
*
|
|
159
|
+
* Type-only specifiers are erased: they have no runtime binding to alias.
|
|
160
|
+
*/
|
|
161
|
+
export declare function rewriteStxImportSpecifiers(specifiers: string): string;
|
|
135
162
|
/**
|
|
136
163
|
* Parsed form of a loop expression (`@for` / `@foreach` argument).
|
|
137
164
|
*
|
|
@@ -667,7 +667,7 @@ export async function processScriptSetup(template, filePath, serverData) {
|
|
|
667
667
|
projectRoot: process.cwd()
|
|
668
668
|
});
|
|
669
669
|
}
|
|
670
|
-
scriptContent = scriptContent.replace(/^\s*import\s+(?:type\s+)?\{[^}]
|
|
670
|
+
scriptContent = scriptContent.replace(/^\s*import\s+(?:type\s+)?\{([^}]*)\}\s+from\s+['"](?:stx|@stacksjs\/stx|@stacksjs\/browser)['"]\s*;?\s*$/gm, (_match, specifiers) => rewriteStxImportSpecifiers(specifiers));
|
|
671
671
|
const resolved = transformStoreImports(scriptContent);
|
|
672
672
|
resolvedParts.push(`// \u2500\u2500 merged signal script #${i + 1} \u2500\u2500
|
|
673
673
|
${resolved}`);
|
|
@@ -908,35 +908,22 @@ export async function processSignals(template, options, filePath, serverData) {
|
|
|
908
908
|
output = processedOutput;
|
|
909
909
|
output = await injectSignalsRuntime(output, options);
|
|
910
910
|
output = injectBrowserRuntime(output);
|
|
911
|
-
if (setupCode)
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
911
|
+
if (setupCode) {
|
|
912
|
+
const headIdx = findMarkupIndexOutsideScripts(output, /<\/head>/i), bodyIdx = headIdx === -1 ? findMarkupIndexOutsideScripts(output, /<body[^>]*>/i) : -1;
|
|
913
|
+
if (headIdx !== -1)
|
|
914
|
+
output = `${output.slice(0, headIdx)}${setupCode}
|
|
915
|
+
${output.slice(headIdx)}`;
|
|
916
|
+
else if (bodyIdx !== -1) {
|
|
917
|
+
const bodyTag = /<body[^>]*>/i.exec(output.slice(bodyIdx))[0], insertAt = bodyIdx + bodyTag.length;
|
|
918
|
+
output = `${output.slice(0, insertAt)}
|
|
919
|
+
${setupCode}${output.slice(insertAt)}`;
|
|
920
|
+
} else
|
|
921
|
+
output = `${output}
|
|
922
|
+
${setupCode}`;
|
|
923
|
+
}
|
|
921
924
|
const bodyMatch = output.replace(/<script\b[\s\S]*?<\/script>/gi, "").replace(/<style\b[\s\S]*?<\/style>/gi, "").match(/<body([^>]*)>/i), bodyHasDataStx = bodyMatch && /data-stx/.test(bodyMatch[1]);
|
|
922
925
|
if (!setupCode && !bodyHasDataStx && bodyMatch && !/data-stx-auto/.test(bodyMatch[1])) {
|
|
923
|
-
const bodyTagRe = /<body[^>]*>/i,
|
|
924
|
-
let m;
|
|
925
|
-
while ((m = scriptOrStyleRe.exec(output)) !== null)
|
|
926
|
-
skipRanges.push([m.index, m.index + m[0].length]);
|
|
927
|
-
let searchFrom = 0, bodyIdx = -1;
|
|
928
|
-
while (searchFrom < output.length) {
|
|
929
|
-
bodyTagRe.lastIndex = searchFrom;
|
|
930
|
-
const hit = bodyTagRe.exec(output.slice(searchFrom));
|
|
931
|
-
if (!hit)
|
|
932
|
-
break;
|
|
933
|
-
const absIdx = searchFrom + hit.index;
|
|
934
|
-
if (!skipRanges.some(([s, e]) => absIdx >= s && absIdx < e)) {
|
|
935
|
-
bodyIdx = absIdx;
|
|
936
|
-
break;
|
|
937
|
-
}
|
|
938
|
-
searchFrom = absIdx + hit[0].length;
|
|
939
|
-
}
|
|
926
|
+
const bodyTagRe = /<body[^>]*>/i, bodyIdx = findMarkupIndexOutsideScripts(output, bodyTagRe);
|
|
940
927
|
if (bodyIdx !== -1) {
|
|
941
928
|
const before = output.slice(0, bodyIdx), after = output.slice(bodyIdx).replace(bodyTagRe, (m) => m.replace(/^<body([^>]*)>$/i, "<body$1 data-stx-auto>"));
|
|
942
929
|
output = before + after;
|
|
@@ -944,3 +931,36 @@ ${setupCode}`);
|
|
|
944
931
|
}
|
|
945
932
|
return output;
|
|
946
933
|
}
|
|
934
|
+
export function findMarkupIndexOutsideScripts(html, pattern) {
|
|
935
|
+
const scriptOrStyleRe = /<(script|style)\b[\s\S]*?<\/\1>/gi, skipRanges = [];
|
|
936
|
+
let block;
|
|
937
|
+
while ((block = scriptOrStyleRe.exec(html)) !== null)
|
|
938
|
+
skipRanges.push([block.index, block.index + block[0].length]);
|
|
939
|
+
const probe = new RegExp(pattern.source, pattern.flags.replace(/[gy]/g, ""));
|
|
940
|
+
let searchFrom = 0;
|
|
941
|
+
while (searchFrom < html.length) {
|
|
942
|
+
const hit = probe.exec(html.slice(searchFrom));
|
|
943
|
+
if (!hit)
|
|
944
|
+
return -1;
|
|
945
|
+
const absoluteIndex = searchFrom + hit.index;
|
|
946
|
+
if (!skipRanges.some(([start, end]) => absoluteIndex >= start && absoluteIndex < end))
|
|
947
|
+
return absoluteIndex;
|
|
948
|
+
searchFrom = absoluteIndex + Math.max(hit[0].length, 1);
|
|
949
|
+
}
|
|
950
|
+
return -1;
|
|
951
|
+
}
|
|
952
|
+
const STX_IMPORT_STRIPPED = "// [stx import stripped \u2014 resolved via window.stx in __stx_setup]";
|
|
953
|
+
export function rewriteStxImportSpecifiers(specifiers) {
|
|
954
|
+
const aliases = [];
|
|
955
|
+
for (const raw of specifiers.split(",")) {
|
|
956
|
+
const specifier = raw.trim();
|
|
957
|
+
if (!specifier || specifier.startsWith("type "))
|
|
958
|
+
continue;
|
|
959
|
+
const renamed = specifier.match(/^([A-Za-z_$][\w$]*)\s+as\s+([A-Za-z_$][\w$]*)$/);
|
|
960
|
+
if (renamed && renamed[1] !== renamed[2])
|
|
961
|
+
aliases.push(`${renamed[2]} = ${renamed[1]}`);
|
|
962
|
+
}
|
|
963
|
+
if (aliases.length === 0)
|
|
964
|
+
return STX_IMPORT_STRIPPED;
|
|
965
|
+
return `const ${aliases.join(", ")}; ${STX_IMPORT_STRIPPED}`;
|
|
966
|
+
}
|