bun-plugin-stx 0.2.47 → 0.2.54
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/chunk-93ete56h.js +23 -0
- package/dist/{chunk-mf3agv0w.js → chunk-nznv3e0m.js} +126 -57
- package/dist/serve.js +6 -1
- package/package.json +11 -9
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// ../router/src/layout-metadata.ts
|
|
3
|
+
function deriveLayoutGroup(layoutPath) {
|
|
4
|
+
const normalized = layoutPath.replace(/\\/g, "/");
|
|
5
|
+
const segments = normalized.split("/").filter(Boolean);
|
|
6
|
+
const layoutsIndex = segments.lastIndexOf("layouts");
|
|
7
|
+
const layoutSegment = layoutsIndex >= 0 ? segments[layoutsIndex + 1] : segments.at(-1);
|
|
8
|
+
if (!layoutSegment)
|
|
9
|
+
return "app";
|
|
10
|
+
return layoutSegment.replace(/\.stx$/i, "") || "app";
|
|
11
|
+
}
|
|
12
|
+
function extractLayoutMetadata(html) {
|
|
13
|
+
const layoutMeta = html.match(/<meta\b[^>]*name=["']stx-layout["'][^>]*content=["']([^"']+)["'][^>]*>/i);
|
|
14
|
+
const groupMeta = html.match(/<meta\b[^>]*name=["']stx-layout-group["'][^>]*content=["']([^"']+)["'][^>]*>/i);
|
|
15
|
+
const layoutComment = html.match(/<!--\s*stx-layout:\s*([^ ]+)\s*-->/i);
|
|
16
|
+
const layout = layoutMeta?.[1] || layoutComment?.[1] || "";
|
|
17
|
+
return {
|
|
18
|
+
layout,
|
|
19
|
+
group: groupMeta?.[1] || deriveLayoutGroup(layout)
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { deriveLayoutGroup, extractLayoutMetadata };
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
import {
|
|
3
|
+
deriveLayoutGroup,
|
|
4
|
+
extractLayoutMetadata
|
|
5
|
+
} from "./chunk-93ete56h.js";
|
|
2
6
|
import"./chunk-2mx7fq49.js";
|
|
3
7
|
|
|
4
8
|
// ../router/src/file-router.ts
|
|
@@ -585,6 +589,8 @@ function getRouterScript() {
|
|
|
585
589
|
var defaults={container:'main',loadingClass:'stx-navigating',viewTransitions:true,cache:true,scrollToTop:true,prefetch:true,progress:true,progressColor:'#78dce8',progressHeight:'2px',interceptAllLinks:false};
|
|
586
590
|
var o=Object.assign({},defaults,window.__stxRouterConfig||{},window.STX_ROUTER_OPTIONS||{});
|
|
587
591
|
var containerSel=o.container;
|
|
592
|
+
var debug=!!o.debug;
|
|
593
|
+
function log(){if(debug&&typeof console!=='undefined'&&console.log)console.log.apply(console,arguments)}
|
|
588
594
|
|
|
589
595
|
// \u2500\u2500 Progress bar (0\u2192100% at top of viewport) \u2500\u2500
|
|
590
596
|
// Native loading indicator baked into the router. Starts when navigation
|
|
@@ -676,6 +682,7 @@ function getRouterScript() {
|
|
|
676
682
|
// Layout group detection \u2014 layouts in the same group share a <main> container.
|
|
677
683
|
// Only truly different layout groups trigger a full page reload.
|
|
678
684
|
var layoutCache={};
|
|
685
|
+
var layoutGroupCache={};
|
|
679
686
|
// Track executed script hashes to prevent redeclaration errors on navigation.
|
|
680
687
|
// Layout-level scripts (theme, nav setup) execute on initial page load and
|
|
681
688
|
// should NOT re-execute when navigating to another page with the same layout.
|
|
@@ -689,33 +696,54 @@ function getRouterScript() {
|
|
|
689
696
|
var text=s.textContent||'';
|
|
690
697
|
if(text.trim()&&!s.hasAttribute('src'))executedScriptHashes[hashScript(text)]=1;
|
|
691
698
|
});
|
|
692
|
-
function
|
|
699
|
+
function cacheKey(url){
|
|
700
|
+
var u=new URL(url,location.origin);
|
|
701
|
+
return u.pathname+u.search;
|
|
702
|
+
}
|
|
703
|
+
function defaultLayoutGroup(layout){
|
|
693
704
|
if(!layout)return 'app';
|
|
694
|
-
|
|
695
|
-
|
|
705
|
+
var clean=String(layout).replace(/\\\\/g,'/');
|
|
706
|
+
var parts=clean.split('/').filter(Boolean);
|
|
707
|
+
var idx=parts.lastIndexOf('layouts');
|
|
708
|
+
var part=idx>=0?parts[idx+1]:parts[parts.length-1];
|
|
709
|
+
return part?part.replace(/\\.stx$/i,''):'app';
|
|
710
|
+
}
|
|
711
|
+
function getCurrentLayoutGroup(){
|
|
712
|
+
var meta=document.querySelector('meta[name="stx-layout-group"]');
|
|
713
|
+
if(meta&&meta.getAttribute('content'))return meta.getAttribute('content');
|
|
714
|
+
var layout=document.querySelector('meta[name="stx-layout"]');
|
|
715
|
+
return defaultLayoutGroup(layout?layout.getAttribute('content'):'');
|
|
716
|
+
}
|
|
717
|
+
function getDocLayoutGroup(doc,layout){
|
|
718
|
+
var meta=doc&&doc.querySelector?doc.querySelector('meta[name="stx-layout-group"]'):null;
|
|
719
|
+
return meta&&meta.getAttribute('content')?meta.getAttribute('content'):defaultLayoutGroup(layout||'');
|
|
696
720
|
}
|
|
697
|
-
function checkLayoutChange(newLayout,targetUrl){
|
|
721
|
+
function checkLayoutChange(newLayout,targetUrl,newGroup){
|
|
698
722
|
var currentLayout=document.querySelector('meta[name="stx-layout"]');
|
|
699
723
|
var curLayoutName=currentLayout?currentLayout.getAttribute('content'):'';
|
|
700
|
-
var curGroup=
|
|
701
|
-
var newGroup
|
|
702
|
-
|
|
724
|
+
var curGroup=getCurrentLayoutGroup();
|
|
725
|
+
var nextGroup=newGroup||defaultLayoutGroup(newLayout);
|
|
726
|
+
log('[router] layout check: current='+curLayoutName+'('+curGroup+') new='+(newLayout||'')+'('+nextGroup+')');
|
|
703
727
|
// Different layout GROUP (e.g. app \u2192 auth): full reload
|
|
704
|
-
if(curGroup!==
|
|
705
|
-
|
|
728
|
+
if(curGroup!==nextGroup){
|
|
729
|
+
log('[router] layout group change:',curGroup,'\u2192',nextGroup,'\u2014 full reload to:',targetUrl);
|
|
706
730
|
return true;
|
|
707
731
|
}
|
|
708
732
|
// Same group but different SPECIFIC layout (e.g. layouts/app \u2192 layouts/coach):
|
|
709
733
|
// full body swap so nav, sidebar, and other layout-level elements update
|
|
710
734
|
if(curLayoutName && newLayout && curLayoutName!==newLayout){
|
|
711
|
-
|
|
735
|
+
log('[router] layout name change:',curLayoutName,'\u2192',newLayout,'\u2014 full body swap');
|
|
712
736
|
return true;
|
|
713
737
|
}
|
|
714
738
|
return false;
|
|
715
739
|
}
|
|
716
740
|
|
|
741
|
+
function shouldUseFragmentResponse(){
|
|
742
|
+
return containerSel==='main'||containerSel==='[data-stx-content]';
|
|
743
|
+
}
|
|
744
|
+
|
|
717
745
|
function navigate(url,pushState,force){
|
|
718
|
-
|
|
746
|
+
log('[router] navigate() called:',url,'isNavigating:',isNavigating);
|
|
719
747
|
if(isNavigating)return;
|
|
720
748
|
var t=new URL(url,location.origin);
|
|
721
749
|
|
|
@@ -728,27 +756,33 @@ function getRouterScript() {
|
|
|
728
756
|
return;
|
|
729
757
|
}
|
|
730
758
|
|
|
731
|
-
if
|
|
759
|
+
// Skip if user clicks a link to the page they're already on. We
|
|
760
|
+
// deliberately allow popstate (pushState===false) through because
|
|
761
|
+
// the browser has already updated location.href to the popped
|
|
762
|
+
// entry \u2014 without this allowance, hitting back would early-return
|
|
763
|
+
// and the visible page content would be left frozen on the
|
|
764
|
+
// forward-navigation page.
|
|
765
|
+
if(pushState!==false&&t.href===location.href&&!t.hash&&!force)return;
|
|
732
766
|
|
|
733
767
|
isNavigating=true;
|
|
734
768
|
document.body.classList.add(o.loadingClass);
|
|
735
769
|
startProgress();
|
|
736
770
|
|
|
737
771
|
var targetHref=t.href;
|
|
738
|
-
var targetPath=
|
|
772
|
+
var targetPath=cacheKey(url);
|
|
739
773
|
var targetHash=t.hash;
|
|
740
774
|
|
|
741
775
|
function done(){isNavigating=false;document.body.classList.remove(o.loadingClass);finishProgress()}
|
|
742
776
|
|
|
743
777
|
if(o.cache&&cache[targetPath]&&!force){
|
|
744
|
-
if(checkLayoutChange(layoutCache[targetPath],url)){
|
|
778
|
+
if(checkLayoutChange(layoutCache[targetPath],url,layoutGroupCache[targetPath])){
|
|
745
779
|
// Layout changed \u2014 fetch full page and do full document swap
|
|
746
|
-
|
|
780
|
+
log('[router] cache hit but layout changed \u2014 fetching full page');
|
|
747
781
|
fetch(url,{headers:{'Accept':'text/html'}}).then(function(r){
|
|
748
782
|
if(!r.ok)throw new Error(r.status);
|
|
749
783
|
return r.text();
|
|
750
784
|
}).then(function(html){
|
|
751
|
-
|
|
785
|
+
log('[router] full page fetched from cache path, len:',html.length);
|
|
752
786
|
swap(html,targetPath,pushState,targetHash);
|
|
753
787
|
}).catch(function(err){
|
|
754
788
|
console.error('[router] full page fetch error:',err);
|
|
@@ -761,28 +795,32 @@ function getRouterScript() {
|
|
|
761
795
|
}
|
|
762
796
|
else {
|
|
763
797
|
if(force&&cache[targetPath])delete cache[targetPath];
|
|
764
|
-
// First fetch as fragment (SPA mode)
|
|
765
|
-
|
|
798
|
+
// First fetch as fragment (SPA mode) when the configured container is
|
|
799
|
+
// the page content. Custom app-shell containers need full documents so
|
|
800
|
+
// the router does not inject a <main> fragment into the wrong element.
|
|
801
|
+
var wantsFragment=shouldUseFragmentResponse();
|
|
802
|
+
fetch(url,{headers:wantsFragment?{'X-STX-Router':'true','Accept':'text/html'}:{'Accept':'text/html'}}).then(function(r){
|
|
766
803
|
if(!r.ok)throw new Error(r.status);
|
|
767
|
-
var isFragment=r.headers.get('X-STX-Fragment')==='true';
|
|
804
|
+
var isFragment=wantsFragment&&r.headers.get('X-STX-Fragment')==='true';
|
|
768
805
|
var newLayout=r.headers.get('X-STX-Layout')||'';
|
|
806
|
+
var newGroup=r.headers.get('X-STX-Layout-Group')||'';
|
|
769
807
|
// Layout change? Fetch the FULL page (no X-STX-Router header) and do full document swap
|
|
770
|
-
if(isFragment&&checkLayoutChange(newLayout,url)){
|
|
771
|
-
|
|
808
|
+
if(isFragment&&checkLayoutChange(newLayout,url,newGroup)){
|
|
809
|
+
log('[router] layout change \u2014 fetching full page for document swap');
|
|
772
810
|
return fetch(url,{headers:{'Accept':'text/html'}}).then(function(fullRes){
|
|
773
|
-
|
|
811
|
+
log('[router] full page fetched:',fullRes.status,'ok:',fullRes.ok);
|
|
774
812
|
if(!fullRes.ok)throw new Error(fullRes.status);
|
|
775
813
|
return fullRes.text().then(function(html){
|
|
776
|
-
|
|
777
|
-
return{html:html,isFragment:false,layout:newLayout};
|
|
814
|
+
log('[router] full page html length:',html.length);
|
|
815
|
+
return{html:html,isFragment:false,layout:newLayout,layoutGroup:newGroup};
|
|
778
816
|
});
|
|
779
817
|
});
|
|
780
818
|
}
|
|
781
|
-
return r.text().then(function(html){return{html:html,isFragment:isFragment,layout:newLayout}});
|
|
819
|
+
return r.text().then(function(html){return{html:html,isFragment:isFragment,layout:newLayout,layoutGroup:newGroup}});
|
|
782
820
|
}).then(function(result){
|
|
783
821
|
if(!result)return;
|
|
784
822
|
if(result.isFragment)result.html='<!--stx-fragment-->'+result.html;
|
|
785
|
-
if(o.cache){cache[targetPath]=result.html;layoutCache[targetPath]=result.layout}
|
|
823
|
+
if(o.cache){cache[targetPath]=result.html;layoutCache[targetPath]=result.layout;layoutGroupCache[targetPath]=result.layoutGroup}
|
|
786
824
|
swap(result.html,targetPath,pushState,targetHash);
|
|
787
825
|
}).catch(function(err){
|
|
788
826
|
console.error('[router] fetch error:',err);
|
|
@@ -795,8 +833,8 @@ else {
|
|
|
795
833
|
var isFragment=html.indexOf('<!--stx-fragment-->')===0;
|
|
796
834
|
if(isFragment)html=html.slice('<!--stx-fragment-->'.length);
|
|
797
835
|
var currentContent=getContainer();
|
|
798
|
-
|
|
799
|
-
if(!currentContent){
|
|
836
|
+
log('[router] swap: isFragment='+isFragment+' container='+!!currentContent+' tag='+(currentContent&¤tContent.tagName)+' selector='+containerSel+' htmlLen='+html.length);
|
|
837
|
+
if(!currentContent){log('[router] no container \u2014 falling back');location.href=url;return}
|
|
800
838
|
|
|
801
839
|
// Fragment mode: server returned just the page content (no document wrapper)
|
|
802
840
|
if(isFragment){
|
|
@@ -851,10 +889,22 @@ else {
|
|
|
851
889
|
else if(hash){var el=document.querySelector(hash);if(el)el.scrollIntoView({behavior:'smooth'})}
|
|
852
890
|
window.dispatchEvent(new CustomEvent('stx:navigate',{detail:{url:url}}));
|
|
853
891
|
// Execute page scripts FIRST \u2014 they define setup functions and set _latestSetup
|
|
854
|
-
|
|
892
|
+
log('[router] frag scripts:', fragScripts.length);
|
|
855
893
|
document.querySelectorAll('script[data-stx-page]').forEach(function(s){s.remove()});
|
|
856
894
|
fragScripts.forEach(function(code){
|
|
857
|
-
|
|
895
|
+
log('[router] exec script len:', code.length, 'has __stx_setup:', code.indexOf('__stx_setup')>-1);
|
|
896
|
+
// Skip scripts that were already executed (layout-level partials
|
|
897
|
+
// like theme.stx, stores.stx, nav.stx). Their top-level const/let
|
|
898
|
+
// declarations would throw "Identifier has already been declared"
|
|
899
|
+
// on re-execution. Setup functions (__stx_setup_) must always
|
|
900
|
+
// re-execute because each page has its own setup.
|
|
901
|
+
var h=hashScript(code);
|
|
902
|
+
var isSetup=code.indexOf('__stx_setup_')!==-1;
|
|
903
|
+
if(!isSetup&&executedScriptHashes[h]){
|
|
904
|
+
log('[router] skipping already-executed script (hash dedup)');
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
executedScriptHashes[h]=1;
|
|
858
908
|
var ns=document.createElement('script');
|
|
859
909
|
// Wrap in block scope to prevent const/let collisions on re-navigation.
|
|
860
910
|
// Without this, navigating away and back throws "Identifier has already
|
|
@@ -865,7 +915,7 @@ else {
|
|
|
865
915
|
ns.setAttribute('data-stx-page','');
|
|
866
916
|
document.body.appendChild(ns);
|
|
867
917
|
});
|
|
868
|
-
|
|
918
|
+
log('[router] scripts done. _latestSetup:', !!window.stx._latestSetup);
|
|
869
919
|
// THEN fire stx:load \u2014 now _latestSetup is set and processElement has the right scope
|
|
870
920
|
window.dispatchEvent(new Event('stx:load'));
|
|
871
921
|
}
|
|
@@ -937,12 +987,14 @@ else {
|
|
|
937
987
|
if(newBody){
|
|
938
988
|
var newMeta=doc.querySelector('meta[name="stx-layout"]');
|
|
939
989
|
var curMeta=document.querySelector('meta[name="stx-layout"]');
|
|
940
|
-
var
|
|
941
|
-
var
|
|
942
|
-
|
|
990
|
+
var curLayout=curMeta?curMeta.getAttribute('content'):'';
|
|
991
|
+
var newLayout=newMeta?newMeta.getAttribute('content'):'';
|
|
992
|
+
var curGroup=getCurrentLayoutGroup();
|
|
993
|
+
var newGroup=getDocLayoutGroup(doc,newLayout);
|
|
994
|
+
isLayoutChange=curGroup!==newGroup||(curLayout&&newLayout&&curLayout!==newLayout);
|
|
943
995
|
}
|
|
944
996
|
if(isLayoutChange&&newBody){
|
|
945
|
-
|
|
997
|
+
log('[router] full body swap for layout change');
|
|
946
998
|
// Replace entire body content \u2014 layout chrome and all
|
|
947
999
|
var bodyHTML=newBody.innerHTML.replace(new RegExp('<scr'+'ipt\\\\b[^>]*>[\\\\s\\\\S]*?<\\\\/scr'+'ipt\\\\s*>','gi'),'');
|
|
948
1000
|
document.body.innerHTML=bodyHTML;
|
|
@@ -953,6 +1005,10 @@ else {
|
|
|
953
1005
|
var freshMeta=doc.querySelector('meta[name="stx-layout"]');
|
|
954
1006
|
if(oldMeta&&freshMeta)oldMeta.setAttribute('content',freshMeta.getAttribute('content')||'');
|
|
955
1007
|
else if(freshMeta){var m=document.createElement('meta');m.name='stx-layout';m.content=freshMeta.getAttribute('content')||'';document.head.appendChild(m)}
|
|
1008
|
+
var oldGroupMeta=document.querySelector('meta[name="stx-layout-group"]');
|
|
1009
|
+
var freshGroupMeta=doc.querySelector('meta[name="stx-layout-group"]');
|
|
1010
|
+
if(oldGroupMeta&&freshGroupMeta)oldGroupMeta.setAttribute('content',freshGroupMeta.getAttribute('content')||'');
|
|
1011
|
+
else if(freshGroupMeta){var gm=document.createElement('meta');gm.name='stx-layout-group';gm.content=freshGroupMeta.getAttribute('content')||'';document.head.appendChild(gm)}
|
|
956
1012
|
// Update container reference for script execution below
|
|
957
1013
|
currentContent=document.querySelector(containerSel)||document.querySelector('main')||document.body;
|
|
958
1014
|
} else {
|
|
@@ -983,6 +1039,9 @@ else {
|
|
|
983
1039
|
document.querySelectorAll('script[data-stx-page]').forEach(function(s){s.remove()});
|
|
984
1040
|
|
|
985
1041
|
var scripts=[];
|
|
1042
|
+
function addScript(text, runAlways){
|
|
1043
|
+
scripts.push({text:text,runAlways:!!runAlways});
|
|
1044
|
+
}
|
|
986
1045
|
if(isLayoutChange){
|
|
987
1046
|
// Layout change: collect ALL scripts from the new document body
|
|
988
1047
|
// (layout scripts, component mounts, setup functions \u2014 everything)
|
|
@@ -995,7 +1054,7 @@ else {
|
|
|
995
1054
|
// Skip the signals runtime IIFE \u2014 it's already loaded
|
|
996
1055
|
if(text.indexOf("'use strict';var cloakStyle")!==-1)return;
|
|
997
1056
|
if(text.indexOf('__stxRouter')!==-1)return;
|
|
998
|
-
|
|
1057
|
+
addScript(text,true);
|
|
999
1058
|
});
|
|
1000
1059
|
}
|
|
1001
1060
|
// Also collect setup functions from <head>
|
|
@@ -1003,7 +1062,7 @@ else {
|
|
|
1003
1062
|
var text=s.textContent||'';
|
|
1004
1063
|
if(s.hasAttribute('src'))return;
|
|
1005
1064
|
if(!text.trim())return;
|
|
1006
|
-
if(text.indexOf('__stx_setup_')!==-1)
|
|
1065
|
+
if(text.indexOf('__stx_setup_')!==-1)addScript(text,true);
|
|
1007
1066
|
});
|
|
1008
1067
|
} else {
|
|
1009
1068
|
// Same layout: collect scripts from the container
|
|
@@ -1011,26 +1070,27 @@ else {
|
|
|
1011
1070
|
var text=s.textContent||'';
|
|
1012
1071
|
if(s.hasAttribute('src'))return;
|
|
1013
1072
|
if(!text.trim())return;
|
|
1014
|
-
|
|
1073
|
+
addScript(text,true);
|
|
1015
1074
|
});
|
|
1016
|
-
// Collect
|
|
1075
|
+
// Collect page scripts from <head> AND <body> (outside container).
|
|
1017
1076
|
// SSG builds place the setup function in <body> before <main>, not
|
|
1018
1077
|
// in <head>. Without this, SPA navigation on static sites never
|
|
1019
1078
|
// runs the setup and reactive data stays empty.
|
|
1020
1079
|
var seenSetups={};
|
|
1021
|
-
scripts.forEach(function(
|
|
1080
|
+
scripts.forEach(function(entry){var t=entry.text;if(t.indexOf('__stx_setup_')!==-1)seenSetups[t.substring(0,80)]=1});
|
|
1022
1081
|
doc.querySelectorAll('script').forEach(function(s){
|
|
1023
1082
|
var text=s.textContent||'';
|
|
1024
1083
|
if(s.hasAttribute('src'))return;
|
|
1025
1084
|
if(!text.trim())return;
|
|
1026
|
-
if(text.indexOf('__stx_setup_')===-1)return;
|
|
1027
1085
|
// Skip signals runtime and router (they contain __stx_setup references but aren't setup functions)
|
|
1028
1086
|
if(text.indexOf("'use strict';var cloakStyle")!==-1)return;
|
|
1029
1087
|
if(text.indexOf('__stxRouter')!==-1)return;
|
|
1088
|
+
if(newContent.contains(s))return;
|
|
1089
|
+
if(text.indexOf('__stx_setup_')===-1&&!s.hasAttribute('data-stx-scoped')&&!s.hasAttribute('data-stx-page'))return;
|
|
1030
1090
|
var key=text.substring(0,80);
|
|
1031
1091
|
if(seenSetups[key])return;
|
|
1032
1092
|
seenSetups[key]=1;
|
|
1033
|
-
|
|
1093
|
+
addScript(text,true);
|
|
1034
1094
|
});
|
|
1035
1095
|
}
|
|
1036
1096
|
|
|
@@ -1060,7 +1120,9 @@ else {
|
|
|
1060
1120
|
|
|
1061
1121
|
// Execute page scripts FIRST \u2014 they define setup functions and set _latestSetup
|
|
1062
1122
|
function execScripts(){
|
|
1063
|
-
scripts.forEach(function(
|
|
1123
|
+
scripts.forEach(function(entry){
|
|
1124
|
+
var text=typeof entry==='string'?entry:entry.text;
|
|
1125
|
+
var runAlways=typeof entry==='string'?false:entry.runAlways;
|
|
1064
1126
|
// Skip scripts that were already executed (layout-level partials
|
|
1065
1127
|
// like theme.stx). Their top-level const/function declarations
|
|
1066
1128
|
// would throw "Identifier has already been declared" on re-execution.
|
|
@@ -1070,7 +1132,7 @@ else {
|
|
|
1070
1132
|
var h=hashScript(text);
|
|
1071
1133
|
var isSetup=text.indexOf('__stx_setup_')!==-1;
|
|
1072
1134
|
var hasImport=text.indexOf('import ')!==-1;
|
|
1073
|
-
if(!isSetup&&executedScriptHashes[h])return;
|
|
1135
|
+
if(!runAlways&&!isSetup&&executedScriptHashes[h])return;
|
|
1074
1136
|
executedScriptHashes[h]=1;
|
|
1075
1137
|
// Wrap scripts with import statements as modules (Bug 3 fix)
|
|
1076
1138
|
var ns=document.createElement('script');
|
|
@@ -1140,12 +1202,12 @@ else {
|
|
|
1140
1202
|
}
|
|
1141
1203
|
if(!link){return}
|
|
1142
1204
|
var href=link.getAttribute('href');
|
|
1143
|
-
|
|
1144
|
-
if(!href||href.startsWith('http')||href.startsWith('#')||href.startsWith('mailto:')||href.startsWith('tel:')){
|
|
1205
|
+
log('[router] click intercepted:',href,'container:',!!getContainer(),'defaultPrevented:',e.defaultPrevented);
|
|
1206
|
+
if(!href||href.startsWith('http')||href.startsWith('#')||href.startsWith('mailto:')||href.startsWith('tel:')){log('[router] skipped:',href);return}
|
|
1145
1207
|
if(link.target==='_blank'||link.hasAttribute('download'))return;
|
|
1146
1208
|
e.preventDefault();
|
|
1147
1209
|
e.stopPropagation();
|
|
1148
|
-
|
|
1210
|
+
log('[router] navigating to:',href);
|
|
1149
1211
|
navigate(href);
|
|
1150
1212
|
},true);
|
|
1151
1213
|
|
|
@@ -1161,15 +1223,18 @@ else {
|
|
|
1161
1223
|
var link=e.target.closest('[data-stx-link]');
|
|
1162
1224
|
if(!link)return;
|
|
1163
1225
|
var href=link.getAttribute('href');
|
|
1164
|
-
|
|
1165
|
-
prefetching[
|
|
1166
|
-
|
|
1167
|
-
|
|
1226
|
+
var key=cacheKey(href);
|
|
1227
|
+
if(cache[key]||prefetching[key])return;
|
|
1228
|
+
prefetching[key]=true;
|
|
1229
|
+
var wantsFragment=shouldUseFragmentResponse();
|
|
1230
|
+
fetch(href,{headers:wantsFragment?{'X-STX-Router':'true','Accept':'text/html'}:{'Accept':'text/html'}}).then(function(r){
|
|
1231
|
+
var isFrag=wantsFragment&&r.headers.get('X-STX-Fragment')==='true';
|
|
1168
1232
|
var pLayout=r.headers.get('X-STX-Layout')||'';
|
|
1169
|
-
|
|
1233
|
+
var pGroup=r.headers.get('X-STX-Layout-Group')||'';
|
|
1234
|
+
return r.text().then(function(html){return{html:isFrag?'<!--stx-fragment-->'+html:html,layout:pLayout,layoutGroup:pGroup}});
|
|
1170
1235
|
}).then(function(result){
|
|
1171
|
-
if(o.cache){cache[
|
|
1172
|
-
}).catch(function(){}).finally(function(){delete prefetching[
|
|
1236
|
+
if(o.cache){cache[key]=result.html;layoutCache[key]=result.layout;layoutGroupCache[key]=result.layoutGroup}
|
|
1237
|
+
}).catch(function(){}).finally(function(){delete prefetching[key]});
|
|
1173
1238
|
},true);
|
|
1174
1239
|
}
|
|
1175
1240
|
|
|
@@ -1262,11 +1327,13 @@ else {
|
|
|
1262
1327
|
navigate:navigate,
|
|
1263
1328
|
navigateTo:navigate,
|
|
1264
1329
|
prefetch:function(url){
|
|
1265
|
-
|
|
1266
|
-
|
|
1330
|
+
var key=cacheKey(url);
|
|
1331
|
+
if(!cache[key]){
|
|
1332
|
+
var wantsFragment=shouldUseFragmentResponse();
|
|
1333
|
+
fetch(url,{headers:wantsFragment?{'X-STX-Router':'true'}:{'Accept':'text/html'}}).then(function(r){var isFrag=wantsFragment&&r.headers.get('X-STX-Fragment')==='true';var pLayout=r.headers.get('X-STX-Layout')||'';var pGroup=r.headers.get('X-STX-Layout-Group')||'';return r.text().then(function(html){return{html:isFrag?'<!--stx-fragment-->'+html:html,layout:pLayout,layoutGroup:pGroup}})}).then(function(result){cache[key]=result.html;layoutCache[key]=result.layout;layoutGroupCache[key]=result.layoutGroup}).catch(function(){});
|
|
1267
1334
|
}
|
|
1268
1335
|
},
|
|
1269
|
-
clearCache:function(){for(var k in cache)delete cache[k]},
|
|
1336
|
+
clearCache:function(){for(var k in cache)delete cache[k];for(var lk in layoutCache)delete layoutCache[lk];for(var gk in layoutGroupCache)delete layoutGroupCache[gk]},
|
|
1270
1337
|
cache:cache,
|
|
1271
1338
|
swap:swap,
|
|
1272
1339
|
updateNav:updateNav
|
|
@@ -1308,6 +1375,8 @@ export {
|
|
|
1308
1375
|
formatRoutes,
|
|
1309
1376
|
findErrorPage,
|
|
1310
1377
|
filePathToPattern,
|
|
1378
|
+
extractLayoutMetadata,
|
|
1379
|
+
deriveLayoutGroup,
|
|
1311
1380
|
defineRoutes,
|
|
1312
1381
|
defineRoute,
|
|
1313
1382
|
defineMiddleware,
|
package/dist/serve.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
+
import {
|
|
4
|
+
deriveLayoutGroup
|
|
5
|
+
} from "./chunk-93ete56h.js";
|
|
3
6
|
import {
|
|
4
7
|
__require
|
|
5
8
|
} from "./chunk-2mx7fq49.js";
|
|
@@ -8956,7 +8959,7 @@ After installing: bun add bun-plugin-stx`);
|
|
|
8956
8959
|
pageMiddlewarePatterns.length = 0;
|
|
8957
8960
|
await Promise.all(files.map((f) => detectPageMiddleware(f)));
|
|
8958
8961
|
try {
|
|
8959
|
-
const { Router } = await import("./chunk-
|
|
8962
|
+
const { Router } = await import("./chunk-nznv3e0m.js");
|
|
8960
8963
|
const pagesDirs = patterns.map((p) => p.replace(/\/$/, "")).filter(Boolean);
|
|
8961
8964
|
const router = new Router(process19.cwd(), { pagesDirs });
|
|
8962
8965
|
console.log(`[stx] Generated ${router.routes.length} routes \u2192 .stx/routes.ts`);
|
|
@@ -9540,6 +9543,7 @@ ${output}`;
|
|
|
9540
9543
|
if (isSpaNav) {
|
|
9541
9544
|
const layoutMatch = content.match(/<!-- stx-layout: ([^ ]+) -->/);
|
|
9542
9545
|
const pageLayout = layoutMatch ? layoutMatch[1] : "default";
|
|
9546
|
+
const pageLayoutGroup = deriveLayoutGroup(pageLayout);
|
|
9543
9547
|
let fragment = content;
|
|
9544
9548
|
const headStyles = [];
|
|
9545
9549
|
const headMatch = content.match(/<head\b[^>]*>([\s\S]*?)<\/head>/i);
|
|
@@ -9608,6 +9612,7 @@ ${pageSetupScripts.join(`
|
|
|
9608
9612
|
"Content-Type": "text/html; charset=utf-8",
|
|
9609
9613
|
"X-STX-Fragment": "true",
|
|
9610
9614
|
"X-STX-Layout": pageLayout,
|
|
9615
|
+
"X-STX-Layout-Group": pageLayoutGroup,
|
|
9611
9616
|
"Cache-Control": "no-cache",
|
|
9612
9617
|
...corsHeaders
|
|
9613
9618
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bun-plugin-stx",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.54",
|
|
5
5
|
"description": "A Bun plugin that allows for using Laravel Blade-like syntax.",
|
|
6
6
|
"author": "Chris Breuer <chris@stacksjs.org>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -43,8 +43,9 @@
|
|
|
43
43
|
"import": "./dist/serve.js"
|
|
44
44
|
},
|
|
45
45
|
"./*": {
|
|
46
|
-
"bun": "./dist
|
|
47
|
-
"
|
|
46
|
+
"bun": "./dist/*.js",
|
|
47
|
+
"types": "./dist/*.d.ts",
|
|
48
|
+
"import": "./dist/*.js"
|
|
48
49
|
}
|
|
49
50
|
},
|
|
50
51
|
"module": "./dist/index.js",
|
|
@@ -60,18 +61,19 @@
|
|
|
60
61
|
],
|
|
61
62
|
"scripts": {
|
|
62
63
|
"build": "bun --bun build.ts",
|
|
63
|
-
"lint": "
|
|
64
|
-
"lint:fix": "
|
|
65
|
-
"fresh": "
|
|
66
|
-
"changelog": "
|
|
64
|
+
"lint": "bun x --bun pickier lint",
|
|
65
|
+
"lint:fix": "bun x --bun pickier lint --fix",
|
|
66
|
+
"fresh": "bun x rimraf node_modules/ bun.lock && bun i",
|
|
67
|
+
"changelog": "bun x changelogen --output CHANGELOG.md",
|
|
67
68
|
"prepublishOnly": "bun run build",
|
|
68
|
-
"release": "bun run changelog &&
|
|
69
|
+
"release": "bun run changelog && bun x bumpp package.json --all",
|
|
69
70
|
"test": "bun test --preload ../../test-utils/happy-dom.ts",
|
|
70
71
|
"test:watch": "bun test --watch --preload ../../test-utils/happy-dom.ts",
|
|
71
72
|
"test:coverage": "bun test --coverage --preload ../../test-utils/happy-dom.ts",
|
|
72
73
|
"typecheck": "bun tsc --noEmit"
|
|
73
74
|
},
|
|
74
75
|
"dependencies": {
|
|
75
|
-
"@stacksjs/stx": "0.2.
|
|
76
|
+
"@stacksjs/stx": "0.2.54",
|
|
77
|
+
"stx-router": "0.2.53"
|
|
76
78
|
}
|
|
77
79
|
}
|