stx-router 0.2.337 → 0.2.338
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/client.d.ts +15 -0
- package/dist/client.js +129 -68
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -1 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The router script as it ships: debug logging removed, then minified.
|
|
3
|
+
*
|
|
4
|
+
* Every page carries this, so the 32 `log()` call sites -- 2.3KB of the
|
|
5
|
+
* delivered bytes, printing nothing unless `debug` is set -- are not part of
|
|
6
|
+
* it. Stripping happens outside the try, as in generateSignalsRuntime: losing
|
|
7
|
+
* minification makes the script bigger, losing the strip would ship the logs.
|
|
8
|
+
*/
|
|
1
9
|
export declare function getRouterScript(): string;
|
|
10
|
+
/**
|
|
11
|
+
* The router script with its `log()` calls intact, for development.
|
|
12
|
+
*
|
|
13
|
+
* Set `debug` in the router config to see them. Minified the same way, so what
|
|
14
|
+
* a developer runs behaves exactly like what ships.
|
|
15
|
+
*/
|
|
16
|
+
export declare function getRouterScriptDev(): string;
|
package/dist/client.js
CHANGED
|
@@ -1,4 +1,45 @@
|
|
|
1
|
-
let cachedRouterScript;
|
|
1
|
+
let cachedRouterScript, cachedRouterScriptDev;
|
|
2
|
+
function stripRouterLogs(source) {
|
|
3
|
+
const out = [], needle = "log(";
|
|
4
|
+
let i = 0;
|
|
5
|
+
while (i < source.length) {
|
|
6
|
+
const hit = source.indexOf(needle, i);
|
|
7
|
+
if (hit === -1) {
|
|
8
|
+
out.push(source.slice(i));
|
|
9
|
+
break;
|
|
10
|
+
}
|
|
11
|
+
const before = hit > 0 ? source[hit - 1] : " ", isDeclaration = /\bfunction\s+$/.test(source.slice(Math.max(0, hit - 16), hit));
|
|
12
|
+
if (/[\w$.]/.test(before) || isDeclaration) {
|
|
13
|
+
out.push(source.slice(i, hit + needle.length));
|
|
14
|
+
i = hit + needle.length;
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
out.push(source.slice(i, hit));
|
|
18
|
+
let depth = 1, j = hit + needle.length;
|
|
19
|
+
while (j < source.length && depth > 0) {
|
|
20
|
+
const character = source[j];
|
|
21
|
+
if (character === '"' || character === "'" || character === "`") {
|
|
22
|
+
const quote = character;
|
|
23
|
+
j++;
|
|
24
|
+
while (j < source.length && source[j] !== quote) {
|
|
25
|
+
if (source[j] === "\\")
|
|
26
|
+
j++;
|
|
27
|
+
j++;
|
|
28
|
+
}
|
|
29
|
+
j++;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (character === "(")
|
|
33
|
+
depth++;
|
|
34
|
+
else if (character === ")")
|
|
35
|
+
depth--;
|
|
36
|
+
j++;
|
|
37
|
+
}
|
|
38
|
+
out.push("0");
|
|
39
|
+
i = j;
|
|
40
|
+
}
|
|
41
|
+
return out.join("");
|
|
42
|
+
}
|
|
2
43
|
function minifyRouterScript(source) {
|
|
3
44
|
try {
|
|
4
45
|
return new Bun.Transpiler({ loader: "js", minifyWhitespace: !0 }).transformSync(source).replace(/\}(var |let |const |function )/g, "};$1").trim();
|
|
@@ -6,10 +47,8 @@ function minifyRouterScript(source) {
|
|
|
6
47
|
return source;
|
|
7
48
|
}
|
|
8
49
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return cachedRouterScript;
|
|
12
|
-
cachedRouterScript = minifyRouterScript(`
|
|
50
|
+
function routerSource() {
|
|
51
|
+
return `
|
|
13
52
|
;(function(){
|
|
14
53
|
'use strict';
|
|
15
54
|
var ROUTER_REV=7;
|
|
@@ -22,6 +61,17 @@ export function getRouterScript() {
|
|
|
22
61
|
var debug=!!o.debug;
|
|
23
62
|
function log(){if(debug&&typeof console!=='undefined'&&console.log)console.log.apply(console,arguments)}
|
|
24
63
|
|
|
64
|
+
// Shorthands for the document-rooted queries this script makes ~33 times.
|
|
65
|
+
// Every page carries these bytes, and the budget in
|
|
66
|
+
// scripts/performance-budgets.ts is what noticed.
|
|
67
|
+
var LAYOUT_META='meta[name="stx-layout"]';
|
|
68
|
+
var LAYOUT_GROUP_META='meta[name="stx-layout-group"]';
|
|
69
|
+
var BUILD_META='meta[name="stx-build"]';
|
|
70
|
+
function qs(sel){return document.querySelector(sel)}
|
|
71
|
+
function qsa(sel){return document.querySelectorAll(sel)}
|
|
72
|
+
function ce(tag){return document.createElement(tag)}
|
|
73
|
+
function dhead(){return document.head}
|
|
74
|
+
|
|
25
75
|
// Replace, never merge: absent payloads must forget the outgoing page's data.
|
|
26
76
|
// Run at the committed swap, not during prefetch or a superseded navigation.
|
|
27
77
|
function hydrateServerData(html){
|
|
@@ -44,7 +94,7 @@ export function getRouterScript() {
|
|
|
44
94
|
// Conservative on purpose: act only when BOTH ids are known. A missing id is
|
|
45
95
|
// "no information", never "mismatch", so statically hosted output (no headers)
|
|
46
96
|
// and older servers behave exactly as before.
|
|
47
|
-
var buildMeta=
|
|
97
|
+
var buildMeta=qs(BUILD_META);
|
|
48
98
|
var loadedBuild=buildMeta?(buildMeta.getAttribute('content')||''):'';
|
|
49
99
|
window.__stxBuild=loadedBuild;
|
|
50
100
|
function isBuildSkew(incoming){
|
|
@@ -192,7 +242,7 @@ export function getRouterScript() {
|
|
|
192
242
|
function parseContainerAttrs(attrStr){
|
|
193
243
|
var map={};
|
|
194
244
|
if(!attrStr)return map;
|
|
195
|
-
var probe=
|
|
245
|
+
var probe=ce('div');
|
|
196
246
|
probe.innerHTML='<i '+attrStr+'></i>';
|
|
197
247
|
var src=probe.firstChild;
|
|
198
248
|
// getAttributeNames first: it is the same standard DOM answer and it is
|
|
@@ -281,7 +331,7 @@ export function getRouterScript() {
|
|
|
281
331
|
}
|
|
282
332
|
|
|
283
333
|
function getContainer(){
|
|
284
|
-
return
|
|
334
|
+
return qs(containerSel)||qs('[data-stx-content]')||qs('main');
|
|
285
335
|
}
|
|
286
336
|
|
|
287
337
|
// \u2500\u2500 Navigation \u2500\u2500
|
|
@@ -365,7 +415,7 @@ export function getRouterScript() {
|
|
|
365
415
|
// navigation. Scripts without an owner are unaffected.
|
|
366
416
|
function ownerStays(owner){
|
|
367
417
|
if(!owner)return false;
|
|
368
|
-
var root=
|
|
418
|
+
var root=qs('[data-stx-scope="'+owner+'"]');
|
|
369
419
|
return !root||typeof root.__stx_disposers==='function';
|
|
370
420
|
}
|
|
371
421
|
function hashScript(code){
|
|
@@ -532,7 +582,7 @@ export function getRouterScript() {
|
|
|
532
582
|
if(!key||loadedExternalScripts[key])return null;
|
|
533
583
|
loadedExternalScripts[key]=1;
|
|
534
584
|
return new Promise(function(resolve){
|
|
535
|
-
var el=
|
|
585
|
+
var el=ce('script');
|
|
536
586
|
el.src=key;
|
|
537
587
|
// Deliberately NOT data-stx-page: both swap paths clear those on every
|
|
538
588
|
// navigation, which would sweep this away and \u2014 since it is never loaded
|
|
@@ -541,12 +591,12 @@ export function getRouterScript() {
|
|
|
541
591
|
el.setAttribute('data-stx-external','');
|
|
542
592
|
el.onload=function(){resolve()};
|
|
543
593
|
el.onerror=function(){log('[router] container script failed:',key);resolve()};
|
|
544
|
-
|
|
594
|
+
dhead().appendChild(el);
|
|
545
595
|
});
|
|
546
596
|
}
|
|
547
597
|
|
|
548
598
|
// Record scripts from the initial page load
|
|
549
|
-
|
|
599
|
+
qsa('script').forEach(function(s){
|
|
550
600
|
var text=s.textContent||'';
|
|
551
601
|
if(s.hasAttribute('src'))rememberExternalScript(s.getAttribute('src'));
|
|
552
602
|
else if(text.trim())executedScriptHashes[hashScript(text)]=1;
|
|
@@ -573,17 +623,17 @@ export function getRouterScript() {
|
|
|
573
623
|
return part?part.replace(/\\.stx$/i,''):'app';
|
|
574
624
|
}
|
|
575
625
|
function getCurrentLayoutGroup(){
|
|
576
|
-
var meta=
|
|
626
|
+
var meta=qs(LAYOUT_GROUP_META);
|
|
577
627
|
if(meta&&meta.getAttribute('content'))return meta.getAttribute('content');
|
|
578
|
-
var layout=
|
|
628
|
+
var layout=qs(LAYOUT_META);
|
|
579
629
|
return defaultLayoutGroup(layout?layout.getAttribute('content'):'');
|
|
580
630
|
}
|
|
581
631
|
function getDocLayoutGroup(doc,layout){
|
|
582
|
-
var meta=doc&&doc.querySelector?doc.querySelector(
|
|
632
|
+
var meta=doc&&doc.querySelector?doc.querySelector(LAYOUT_GROUP_META):null;
|
|
583
633
|
return meta&&meta.getAttribute('content')?meta.getAttribute('content'):defaultLayoutGroup(layout||'');
|
|
584
634
|
}
|
|
585
635
|
function checkLayoutChange(newLayout,targetUrl,newGroup){
|
|
586
|
-
var currentLayout=
|
|
636
|
+
var currentLayout=qs(LAYOUT_META);
|
|
587
637
|
var curLayoutName=currentLayout?currentLayout.getAttribute('content'):'';
|
|
588
638
|
var curGroup=getCurrentLayoutGroup();
|
|
589
639
|
var nextGroup=newGroup||defaultLayoutGroup(newLayout);
|
|
@@ -636,7 +686,7 @@ export function getRouterScript() {
|
|
|
636
686
|
|
|
637
687
|
if(t.pathname===location.pathname&&t.hash){
|
|
638
688
|
if(pushState!==false)writeHistory(pushState,t.href);
|
|
639
|
-
var el=
|
|
689
|
+
var el=qs(t.hash);
|
|
640
690
|
if(el)el.scrollIntoView({behavior:'smooth'});
|
|
641
691
|
return Promise.resolve(true);
|
|
642
692
|
}
|
|
@@ -781,7 +831,7 @@ else {
|
|
|
781
831
|
function routeAnnouncer(){
|
|
782
832
|
var el=document.getElementById('stx-route-announcer');
|
|
783
833
|
if(el)return el;
|
|
784
|
-
el=
|
|
834
|
+
el=ce('div');
|
|
785
835
|
el.id='stx-route-announcer';
|
|
786
836
|
el.setAttribute('aria-live','polite');
|
|
787
837
|
el.setAttribute('role','status');
|
|
@@ -814,7 +864,7 @@ else {
|
|
|
814
864
|
function focusAfterNavigation(hash){
|
|
815
865
|
if(o.routeFocus===false)return;
|
|
816
866
|
var target=null;
|
|
817
|
-
if(hash){try{target=
|
|
867
|
+
if(hash){try{target=qs(hash)}catch(e){target=null}}
|
|
818
868
|
if(!target)target=getContainer();
|
|
819
869
|
if(!target||!target.focus)return;
|
|
820
870
|
// The container is not naturally focusable. tabindex="-1" makes it
|
|
@@ -837,7 +887,7 @@ else {
|
|
|
837
887
|
// be the last one, every navigation, not just the first time it is seen.
|
|
838
888
|
function findGeneratedCss(abs){
|
|
839
889
|
var found=null;
|
|
840
|
-
|
|
890
|
+
qsa('head link[data-css][href]').forEach(function(link){
|
|
841
891
|
if(new URL(link.getAttribute('href'),location.href).href!==abs)return;
|
|
842
892
|
// Collapse duplicates, so moving one copy to the end can never leave an
|
|
843
893
|
// older copy of the same sheet behind to fight it.
|
|
@@ -866,7 +916,7 @@ else {
|
|
|
866
916
|
if(link.__stxCssReady)pending.push(link.__stxCssReady);
|
|
867
917
|
return;
|
|
868
918
|
}
|
|
869
|
-
link=
|
|
919
|
+
link=ce('link');
|
|
870
920
|
link.setAttribute('data-css','generated');
|
|
871
921
|
link.setAttribute('rel','stylesheet');
|
|
872
922
|
link.setAttribute('href',new URL(href,location.href).href===abs?href:abs);
|
|
@@ -887,7 +937,7 @@ else {
|
|
|
887
937
|
link.onerror=function(){finish(true)};
|
|
888
938
|
});
|
|
889
939
|
pending.push(link.__stxCssReady);
|
|
890
|
-
|
|
940
|
+
dhead().appendChild(link);
|
|
891
941
|
});
|
|
892
942
|
return pending.length?Promise.all(pending).then(function(results){return results.every(function(ok){return ok!==false})}):null;
|
|
893
943
|
}
|
|
@@ -923,7 +973,7 @@ else {
|
|
|
923
973
|
link.removeAttribute('data-stx-css-pending');
|
|
924
974
|
link.removeAttribute('media');
|
|
925
975
|
}
|
|
926
|
-
|
|
976
|
+
dhead().appendChild(link);
|
|
927
977
|
});
|
|
928
978
|
}
|
|
929
979
|
|
|
@@ -1036,18 +1086,18 @@ else {
|
|
|
1036
1086
|
});
|
|
1037
1087
|
cleanFrag=cleanFrag.replace(new RegExp('<!--stx-held-script-(\\\\d+)-->','g'),function(m,i){return heldScripts[Number(i)]});
|
|
1038
1088
|
// Remove old page styles (not css \u2014 that gets merged)
|
|
1039
|
-
|
|
1089
|
+
qsa('style[data-stx-page]').forEach(function(s){s.remove()});
|
|
1040
1090
|
// Merge css CSS from fragment into existing css style
|
|
1041
1091
|
if(fragCss){
|
|
1042
|
-
var curCss=
|
|
1092
|
+
var curCss=qs('head style[data-css]');
|
|
1043
1093
|
if(curCss){
|
|
1044
1094
|
var merged=mergeCss(curCss.textContent||'',fragCss);
|
|
1045
1095
|
if(merged)curCss.textContent=merged;
|
|
1046
1096
|
}else{
|
|
1047
|
-
var cw=
|
|
1097
|
+
var cw=ce('style');
|
|
1048
1098
|
cw.setAttribute('data-css','generated');
|
|
1049
1099
|
cw.textContent=fragCss;
|
|
1050
|
-
|
|
1100
|
+
dhead().appendChild(cw);
|
|
1051
1101
|
}
|
|
1052
1102
|
}
|
|
1053
1103
|
// Already present ones are MOVED last, not skipped \u2014 see
|
|
@@ -1055,10 +1105,10 @@ else {
|
|
|
1055
1105
|
promoteGeneratedCss(fragCssHrefs,location.href);
|
|
1056
1106
|
// Add new page styles
|
|
1057
1107
|
fragStyles.forEach(function(s){
|
|
1058
|
-
var el=
|
|
1108
|
+
var el=ce('style');
|
|
1059
1109
|
el.textContent=s.css;
|
|
1060
1110
|
el.setAttribute('data-stx-page','');
|
|
1061
|
-
|
|
1111
|
+
dhead().appendChild(el);
|
|
1062
1112
|
});
|
|
1063
1113
|
// Swap content \u2014 apply the destination container's own attributes first
|
|
1064
1114
|
// so the incoming markup lands in a correctly-laid-out container instead
|
|
@@ -1066,11 +1116,11 @@ else {
|
|
|
1066
1116
|
applyContainerAttrs(currentContent,pendingContainerAttrs);
|
|
1067
1117
|
currentContent.innerHTML=cleanFrag;
|
|
1068
1118
|
// Remove old page scripts
|
|
1069
|
-
|
|
1119
|
+
qsa('script[data-stx-page]').forEach(function(s){s.remove()});
|
|
1070
1120
|
if(pushState!==false)writeHistory(pushState,url+(hash||''));
|
|
1071
1121
|
refreshCurrentLinks();
|
|
1072
1122
|
if(o.scrollToTop&&!hash)window.scrollTo({top:0,behavior:'instant'});
|
|
1073
|
-
else if(hash){var el=
|
|
1123
|
+
else if(hash){var el=qs(hash);if(el)el.scrollIntoView({behavior:'smooth'})}
|
|
1074
1124
|
window.dispatchEvent(new CustomEvent('stx:navigate',{detail:{url:url}}));
|
|
1075
1125
|
// Before page scripts run, so a page that focuses its own control on
|
|
1076
1126
|
// mount still wins \u2014 its script executes after this.
|
|
@@ -1080,7 +1130,7 @@ else {
|
|
|
1080
1130
|
setTimeout(announceRoute,0);
|
|
1081
1131
|
// Execute page scripts FIRST \u2014 they define setup functions and set _latestSetup
|
|
1082
1132
|
log('[router] frag scripts:', fragScripts.length);
|
|
1083
|
-
|
|
1133
|
+
qsa('script[data-stx-page]').forEach(function(s){s.remove()});
|
|
1084
1134
|
// The page's module registry first (#1957), setups last. A fragment
|
|
1085
1135
|
// lists its scripts in document order, and the registry is emitted
|
|
1086
1136
|
// after the content it serves: a component that imports a package ran
|
|
@@ -1092,11 +1142,11 @@ else {
|
|
|
1092
1142
|
fragScripts.forEach(function(entry){
|
|
1093
1143
|
var code=entry.text;
|
|
1094
1144
|
log('[router] exec script len:', code.length, 'has __stx_setup:', code.indexOf('__stx_setup')>-1);
|
|
1095
|
-
var placeholder=
|
|
1145
|
+
var placeholder=qs('script[data-stx-route-script="'+entry.slot+'"]');
|
|
1096
1146
|
var nestedScopedTemplate=false;
|
|
1097
1147
|
var scopedLoopSetup=false;
|
|
1098
1148
|
if(entry.scoped&&placeholder){
|
|
1099
|
-
|
|
1149
|
+
qsa('template').forEach(function(template){
|
|
1100
1150
|
if(template.contains(placeholder)||(template.content&&template.content.contains(placeholder)))
|
|
1101
1151
|
nestedScopedTemplate=true;
|
|
1102
1152
|
});
|
|
@@ -1139,7 +1189,7 @@ else {
|
|
|
1139
1189
|
return;
|
|
1140
1190
|
}
|
|
1141
1191
|
executedScriptHashes[h]=1;
|
|
1142
|
-
var ns=
|
|
1192
|
+
var ns=ce('script');
|
|
1143
1193
|
var hasImport=hasStaticImport(code);
|
|
1144
1194
|
if(hasImport){
|
|
1145
1195
|
ns.type='module';
|
|
@@ -1202,7 +1252,7 @@ else {
|
|
|
1202
1252
|
var doc=parser.parseFromString(html,'text/html');
|
|
1203
1253
|
// Full documents carry the build id as a meta rather than a header, and
|
|
1204
1254
|
// this path also serves cached HTML, so check here too (#1772).
|
|
1205
|
-
var docBuildMeta=doc.querySelector(
|
|
1255
|
+
var docBuildMeta=doc.querySelector(BUILD_META);
|
|
1206
1256
|
var docBuild=docBuildMeta?(docBuildMeta.getAttribute('content')||''):'';
|
|
1207
1257
|
if(isBuildSkew(docBuild)){reloadForSkew(url,docBuild);return Promise.resolve(false)}
|
|
1208
1258
|
// Same hand-off as the fragment path, for the same reason (#1809, #1839).
|
|
@@ -1236,12 +1286,12 @@ else {
|
|
|
1236
1286
|
// \u2500\u2500 Swap <head> styles \u2500\u2500
|
|
1237
1287
|
// Inject new styles FIRST, then remove old to prevent unstyled flash
|
|
1238
1288
|
var keepIds={'stx-view-transitions':1,'stx-r-css':1};
|
|
1239
|
-
var curStyles=
|
|
1289
|
+
var curStyles=qsa('head style');
|
|
1240
1290
|
var newStyles=doc.querySelectorAll('head style');
|
|
1241
1291
|
|
|
1242
1292
|
// Merge css styles instead of replacing \u2014 persistent elements
|
|
1243
1293
|
// (nav, footer) outside <main> still need their utility classes
|
|
1244
|
-
var curCss=
|
|
1294
|
+
var curCss=qs('head style[data-css]');
|
|
1245
1295
|
var newCss=null;
|
|
1246
1296
|
newStyles.forEach(function(s){if(s.getAttribute('data-css'))newCss=s});
|
|
1247
1297
|
|
|
@@ -1253,20 +1303,20 @@ else {
|
|
|
1253
1303
|
var incoming=[];
|
|
1254
1304
|
newStyles.forEach(function(s){
|
|
1255
1305
|
if(!keepIds[s.id]&&!s.getAttribute('data-css')){
|
|
1256
|
-
var ns=
|
|
1306
|
+
var ns=ce('style');
|
|
1257
1307
|
ns.textContent=s.textContent;
|
|
1258
1308
|
ns.setAttribute('data-stx-incoming','');
|
|
1259
|
-
|
|
1309
|
+
dhead().appendChild(ns);
|
|
1260
1310
|
incoming.push(ns);
|
|
1261
1311
|
}
|
|
1262
1312
|
});
|
|
1263
1313
|
|
|
1264
1314
|
// If no existing css but new page has one, add it
|
|
1265
1315
|
if(!curCss&&newCss){
|
|
1266
|
-
var ns=
|
|
1316
|
+
var ns=ce('style');
|
|
1267
1317
|
ns.textContent=newCss.textContent;
|
|
1268
1318
|
ns.setAttribute('data-css',newCss.getAttribute('data-css'));
|
|
1269
|
-
|
|
1319
|
+
dhead().appendChild(ns);
|
|
1270
1320
|
}
|
|
1271
1321
|
|
|
1272
1322
|
// Remove old styles (except persistent ones, css, and incoming)
|
|
@@ -1293,7 +1343,7 @@ else {
|
|
|
1293
1343
|
try{docBase=new URL(url,location.href).href}catch(e){docBase=location.href}
|
|
1294
1344
|
var linkSel='link[rel="stylesheet"],link[rel="preconnect"]';
|
|
1295
1345
|
var curLinks={};
|
|
1296
|
-
|
|
1346
|
+
qsa('head '+linkSel).forEach(function(l){var h=l.getAttribute('href');if(h)curLinks[new URL(h,location.href).href]=1});
|
|
1297
1347
|
doc.querySelectorAll('head '+linkSel).forEach(function(l){
|
|
1298
1348
|
var href=l.getAttribute('href');
|
|
1299
1349
|
if(!href)return;
|
|
@@ -1303,9 +1353,9 @@ else {
|
|
|
1303
1353
|
var abs=new URL(href,docBase).href;
|
|
1304
1354
|
if(curLinks[abs])return;
|
|
1305
1355
|
curLinks[abs]=1;
|
|
1306
|
-
var nl=
|
|
1356
|
+
var nl=ce('link');
|
|
1307
1357
|
Array.from(l.attributes).forEach(function(a){nl.setAttribute(a.name,a.value)});
|
|
1308
|
-
|
|
1358
|
+
dhead().appendChild(nl);
|
|
1309
1359
|
});
|
|
1310
1360
|
// After every other stylesheet link, so the destination's complete
|
|
1311
1361
|
// utility sheet is last in the cascade.
|
|
@@ -1319,8 +1369,8 @@ else {
|
|
|
1319
1369
|
var declaredLayout=pendingLayoutDecl;
|
|
1320
1370
|
pendingLayoutDecl=null;
|
|
1321
1371
|
if(newBody){
|
|
1322
|
-
var newMeta=doc.querySelector(
|
|
1323
|
-
var curMeta=
|
|
1372
|
+
var newMeta=doc.querySelector(LAYOUT_META);
|
|
1373
|
+
var curMeta=qs(LAYOUT_META);
|
|
1324
1374
|
var curLayout=curMeta?curMeta.getAttribute('content'):'';
|
|
1325
1375
|
// The server's answer wins over the document's metas. We are only here
|
|
1326
1376
|
// because checkLayoutChange already said the group changed, based on
|
|
@@ -1388,16 +1438,16 @@ else {
|
|
|
1388
1438
|
// Copy body attributes (class, data-stx, etc.)
|
|
1389
1439
|
Array.from(newBody.attributes).forEach(function(attr){document.body.setAttribute(attr.name,attr.value)});
|
|
1390
1440
|
// Update layout meta tag
|
|
1391
|
-
var oldMeta=
|
|
1392
|
-
var freshMeta=doc.querySelector(
|
|
1441
|
+
var oldMeta=qs(LAYOUT_META);
|
|
1442
|
+
var freshMeta=doc.querySelector(LAYOUT_META);
|
|
1393
1443
|
if(oldMeta&&freshMeta)oldMeta.setAttribute('content',freshMeta.getAttribute('content')||'');
|
|
1394
|
-
else if(freshMeta){var m=
|
|
1395
|
-
var oldGroupMeta=
|
|
1396
|
-
var freshGroupMeta=doc.querySelector(
|
|
1444
|
+
else if(freshMeta){var m=ce('meta');m.name='stx-layout';m.content=freshMeta.getAttribute('content')||'';dhead().appendChild(m)}
|
|
1445
|
+
var oldGroupMeta=qs(LAYOUT_GROUP_META);
|
|
1446
|
+
var freshGroupMeta=doc.querySelector(LAYOUT_GROUP_META);
|
|
1397
1447
|
if(oldGroupMeta&&freshGroupMeta)oldGroupMeta.setAttribute('content',freshGroupMeta.getAttribute('content')||'');
|
|
1398
|
-
else if(freshGroupMeta){var gm=
|
|
1448
|
+
else if(freshGroupMeta){var gm=ce('meta');gm.name='stx-layout-group';gm.content=freshGroupMeta.getAttribute('content')||'';dhead().appendChild(gm)}
|
|
1399
1449
|
// Update container reference for script execution below
|
|
1400
|
-
currentContent=
|
|
1450
|
+
currentContent=qs(containerSel)||qs('main')||document.body;
|
|
1401
1451
|
} else {
|
|
1402
1452
|
// Same layout \u2014 swap only container content. Carry the destination
|
|
1403
1453
|
// container's attributes across too (same reason as the fragment path:
|
|
@@ -1416,7 +1466,7 @@ else {
|
|
|
1416
1466
|
|
|
1417
1467
|
// \u2500\u2500 Load new external <head> scripts \u2500\u2500
|
|
1418
1468
|
var loadedSrcs={};
|
|
1419
|
-
|
|
1469
|
+
qsa('head script[src]').forEach(function(s){loadedSrcs[s.src]=1});
|
|
1420
1470
|
var extPromises=[];
|
|
1421
1471
|
doc.querySelectorAll('head script[src]').forEach(function(s){
|
|
1422
1472
|
if(isSharedClientScript(s))return;
|
|
@@ -1426,11 +1476,11 @@ else {
|
|
|
1426
1476
|
if(loadedSrcs[src])return;
|
|
1427
1477
|
loadedSrcs[src]=1;
|
|
1428
1478
|
extPromises.push(new Promise(function(resolve,reject){
|
|
1429
|
-
var ns=
|
|
1479
|
+
var ns=ce('script');
|
|
1430
1480
|
ns.src=src;
|
|
1431
1481
|
ns.onload=resolve;
|
|
1432
1482
|
ns.onerror=reject;
|
|
1433
|
-
|
|
1483
|
+
dhead().appendChild(ns);
|
|
1434
1484
|
}));
|
|
1435
1485
|
});
|
|
1436
1486
|
|
|
@@ -1444,7 +1494,7 @@ else {
|
|
|
1444
1494
|
|
|
1445
1495
|
// \u2500\u2500 Script re-execution \u2500\u2500
|
|
1446
1496
|
// Remove previously injected page scripts
|
|
1447
|
-
|
|
1497
|
+
qsa('script[data-stx-page]').forEach(function(s){s.remove()});
|
|
1448
1498
|
|
|
1449
1499
|
var scripts=routedBodyScripts.slice();
|
|
1450
1500
|
function addScript(text, runAlways, slot, owner){
|
|
@@ -1529,7 +1579,7 @@ else {
|
|
|
1529
1579
|
|
|
1530
1580
|
// Scroll
|
|
1531
1581
|
if(o.scrollToTop&&!hash)window.scrollTo({top:0,behavior:'instant'});
|
|
1532
|
-
else if(hash){var el=
|
|
1582
|
+
else if(hash){var el=qs(hash);if(el)el.scrollIntoView({behavior:'smooth'})}
|
|
1533
1583
|
|
|
1534
1584
|
// Update title
|
|
1535
1585
|
var newTitle=doc.querySelector('title');
|
|
@@ -1590,7 +1640,7 @@ else {
|
|
|
1590
1640
|
if(!runAlways&&!isSetup&&executedScriptHashes[h])return;
|
|
1591
1641
|
executedScriptHashes[h]=1;
|
|
1592
1642
|
// Wrap scripts with import statements as modules (Bug 3 fix)
|
|
1593
|
-
var ns=
|
|
1643
|
+
var ns=ce('script');
|
|
1594
1644
|
if(hasImport){
|
|
1595
1645
|
ns.type='module';
|
|
1596
1646
|
}
|
|
@@ -1603,7 +1653,7 @@ else {
|
|
|
1603
1653
|
var alreadyScoped=runsAlways(typeof entry==='string'?'':entry.run,text);
|
|
1604
1654
|
ns.textContent=(hasImport||alreadyScoped)?text:'{'+text+'}';
|
|
1605
1655
|
ns.setAttribute('data-stx-page','');
|
|
1606
|
-
var placeholder=entry.slot?
|
|
1656
|
+
var placeholder=entry.slot?qs('script[data-stx-route-script="'+entry.slot+'"]'):null;
|
|
1607
1657
|
if(placeholder&&placeholder.parentNode){
|
|
1608
1658
|
ns.setAttribute('data-stx-positioned','');
|
|
1609
1659
|
placeholder.parentNode.replaceChild(ns,placeholder);
|
|
@@ -1961,7 +2011,7 @@ else {
|
|
|
1961
2011
|
}
|
|
1962
2012
|
|
|
1963
2013
|
function updateNav(){
|
|
1964
|
-
|
|
2014
|
+
qsa('nav a[href], #mobileNav a[href], [data-stx-nav] a[href]').forEach(function(a){
|
|
1965
2015
|
if(!a.hasAttribute('data-stx-link'))return;
|
|
1966
2016
|
var st=linkState(a.getAttribute('href'),a.getAttribute('data-stx-active-match'));
|
|
1967
2017
|
if(!st)return;
|
|
@@ -1982,7 +2032,7 @@ else {
|
|
|
1982
2032
|
|
|
1983
2033
|
function updateActiveLinks(){
|
|
1984
2034
|
// Update active classes on <stx-link> elements (and legacy data-stx-link)
|
|
1985
|
-
var links=
|
|
2035
|
+
var links=qsa('[data-stx-link]');
|
|
1986
2036
|
links.forEach(function(link){
|
|
1987
2037
|
var st=linkState(link.getAttribute('to')||link.getAttribute('href')||'',link.getAttribute('data-stx-active-match'));
|
|
1988
2038
|
if(!st)return;
|
|
@@ -2024,7 +2074,7 @@ else {
|
|
|
2024
2074
|
// the cascade, or opt out entirely with viewTransitions:false.
|
|
2025
2075
|
function injectStyles(){
|
|
2026
2076
|
if(!document.getElementById('stx-r-css')){
|
|
2027
|
-
var s=
|
|
2077
|
+
var s=ce('style');s.id='stx-r-css';
|
|
2028
2078
|
// Strip characters that could escape our CSS block and inject new
|
|
2029
2079
|
// declarations: ; { } ( ) " ' \\ < > plus whitespace control chars.
|
|
2030
2080
|
// This keeps the value safe to concat into a stylesheet even if a
|
|
@@ -2046,10 +2096,10 @@ else {
|
|
|
2046
2096
|
css+='@media (prefers-reduced-motion: reduce){::view-transition-old(root),::view-transition-new(root){animation-duration:0s;animation-name:none}}';
|
|
2047
2097
|
}
|
|
2048
2098
|
s.textContent=css;
|
|
2049
|
-
|
|
2099
|
+
dhead().appendChild(s);
|
|
2050
2100
|
}
|
|
2051
2101
|
if(o.progress&&!document.getElementById('stx-router-progress')){
|
|
2052
|
-
var el=
|
|
2102
|
+
var el=ce('div');
|
|
2053
2103
|
el.id='stx-router-progress';
|
|
2054
2104
|
el.setAttribute('role','progressbar');
|
|
2055
2105
|
el.setAttribute('aria-hidden','true');
|
|
@@ -2066,7 +2116,7 @@ else {
|
|
|
2066
2116
|
|
|
2067
2117
|
function injectViewTransitionCSS(){
|
|
2068
2118
|
if(document.getElementById('stx-view-transitions'))return;
|
|
2069
|
-
var s=
|
|
2119
|
+
var s=ce('style');s.id='stx-view-transitions';
|
|
2070
2120
|
s.textContent='::view-transition-group(root){animation:none}::view-transition-old(root){animation:none}::view-transition-new(root){animation:none}main,#app-content,[data-stx-content]{view-transition-name:stx-content}::view-transition-old(stx-content){animation:stx-fade-out .15s ease-out both}::view-transition-new(stx-content){animation:stx-fade-in .15s ease-in .1s both}@keyframes stx-fade-out{from{opacity:1}to{opacity:0}}@keyframes stx-fade-in{from{opacity:0}to{opacity:1}}::view-transition{background:transparent}::view-transition-group(stx-content){background:inherit;overflow:hidden}';
|
|
2071
2121
|
(document.head||document.documentElement).appendChild(s);
|
|
2072
2122
|
}
|
|
@@ -2123,6 +2173,17 @@ else {
|
|
|
2123
2173
|
|
|
2124
2174
|
if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',init);else init();
|
|
2125
2175
|
})();
|
|
2126
|
-
|
|
2176
|
+
`;
|
|
2177
|
+
}
|
|
2178
|
+
export function getRouterScript() {
|
|
2179
|
+
if (cachedRouterScript)
|
|
2180
|
+
return cachedRouterScript;
|
|
2181
|
+
cachedRouterScript = minifyRouterScript(stripRouterLogs(routerSource()));
|
|
2127
2182
|
return cachedRouterScript;
|
|
2128
2183
|
}
|
|
2184
|
+
export function getRouterScriptDev() {
|
|
2185
|
+
if (cachedRouterScriptDev)
|
|
2186
|
+
return cachedRouterScriptDev;
|
|
2187
|
+
cachedRouterScriptDev = minifyRouterScript(routerSource());
|
|
2188
|
+
return cachedRouterScriptDev;
|
|
2189
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -52,4 +52,4 @@ export { generateRouteTypes, generateRouteManifest } from './codegen';
|
|
|
52
52
|
// Which files under a page root are public routes (#1866)
|
|
53
53
|
export { NON_PAGE_DIRS, isNonPageRoutePath, isNonPageRoutePattern } from './page-routes';
|
|
54
54
|
// Client-side SPA navigation
|
|
55
|
-
export { getRouterScript } from './client';
|
|
55
|
+
export { getRouterScript, getRouterScriptDev } from './client';
|
package/dist/index.js
CHANGED
|
@@ -22,4 +22,4 @@ export { resolveLayoutChain } from "./nested-layouts.js";
|
|
|
22
22
|
export { deriveLayoutGroup, extractLayoutMetadata } from "./layout-metadata.js";
|
|
23
23
|
export { generateRouteTypes, generateRouteManifest } from "./codegen.js";
|
|
24
24
|
export { NON_PAGE_DIRS, isNonPageRoutePath, isNonPageRoutePattern } from "./page-routes.js";
|
|
25
|
-
export { getRouterScript } from "./client.js";
|
|
25
|
+
export { getRouterScript, getRouterScriptDev } from "./client.js";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stx-router",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.338",
|
|
5
5
|
"description": "File-based router for STX — .stx template discovery, nested layouts, typed route params, middleware, and client-side SPA navigation.",
|
|
6
6
|
"author": "Chris Breuer <chris@stacksjs.org>",
|
|
7
7
|
"license": "MIT",
|