bun-plugin-stx 0.2.46 → 0.2.51
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-nyzhqegd.js → chunk-0nwya50v.js} +122 -58
- package/dist/chunk-93ete56h.js +23 -0
- package/dist/serve.js +8 -3
- package/package.json +6 -4
|
@@ -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
|
|
@@ -153,25 +157,35 @@ function scanDirectory(dir, extensions) {
|
|
|
153
157
|
class Router {
|
|
154
158
|
routes;
|
|
155
159
|
pagesDir;
|
|
160
|
+
pagesDirs;
|
|
156
161
|
config;
|
|
157
162
|
constructor(baseDir, config = {}) {
|
|
158
163
|
this.config = config;
|
|
159
|
-
|
|
164
|
+
const rawDirs = config.pagesDirs && config.pagesDirs.length > 0 ? config.pagesDirs : [config.pagesDir || "pages"];
|
|
165
|
+
this.pagesDirs = rawDirs.map((d) => path4.resolve(baseDir, d));
|
|
166
|
+
this.pagesDir = this.pagesDirs[0];
|
|
160
167
|
const extensions = config.extensions || [".stx"];
|
|
161
|
-
const
|
|
162
|
-
this.routes =
|
|
163
|
-
|
|
164
|
-
const
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
pattern
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
168
|
+
const seenPatterns = new Set;
|
|
169
|
+
this.routes = [];
|
|
170
|
+
for (const dir of this.pagesDirs) {
|
|
171
|
+
const files = scanDirectory(dir, extensions);
|
|
172
|
+
for (const filePath of files) {
|
|
173
|
+
const pattern = filePathToPattern(filePath, dir);
|
|
174
|
+
if (seenPatterns.has(pattern))
|
|
175
|
+
continue;
|
|
176
|
+
seenPatterns.add(pattern);
|
|
177
|
+
const { regex, params } = patternToRegex(pattern);
|
|
178
|
+
const layouts = config.layouts !== false ? resolveLayoutChain(filePath, dir) : [];
|
|
179
|
+
this.routes.push({
|
|
180
|
+
pattern,
|
|
181
|
+
regex,
|
|
182
|
+
params,
|
|
183
|
+
filePath,
|
|
184
|
+
isDynamic: params.length > 0,
|
|
185
|
+
layout: layouts.length > 0 ? layouts[layouts.length - 1] : undefined
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
175
189
|
this.routes.sort((a, b) => {
|
|
176
190
|
if (!a.isDynamic && b.isDynamic)
|
|
177
191
|
return -1;
|
|
@@ -575,6 +589,8 @@ function getRouterScript() {
|
|
|
575
589
|
var defaults={container:'main',loadingClass:'stx-navigating',viewTransitions:true,cache:true,scrollToTop:true,prefetch:true,progress:true,progressColor:'#78dce8',progressHeight:'2px',interceptAllLinks:false};
|
|
576
590
|
var o=Object.assign({},defaults,window.__stxRouterConfig||{},window.STX_ROUTER_OPTIONS||{});
|
|
577
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)}
|
|
578
594
|
|
|
579
595
|
// \u2500\u2500 Progress bar (0\u2192100% at top of viewport) \u2500\u2500
|
|
580
596
|
// Native loading indicator baked into the router. Starts when navigation
|
|
@@ -666,6 +682,7 @@ function getRouterScript() {
|
|
|
666
682
|
// Layout group detection \u2014 layouts in the same group share a <main> container.
|
|
667
683
|
// Only truly different layout groups trigger a full page reload.
|
|
668
684
|
var layoutCache={};
|
|
685
|
+
var layoutGroupCache={};
|
|
669
686
|
// Track executed script hashes to prevent redeclaration errors on navigation.
|
|
670
687
|
// Layout-level scripts (theme, nav setup) execute on initial page load and
|
|
671
688
|
// should NOT re-execute when navigating to another page with the same layout.
|
|
@@ -679,33 +696,50 @@ function getRouterScript() {
|
|
|
679
696
|
var text=s.textContent||'';
|
|
680
697
|
if(text.trim()&&!s.hasAttribute('src'))executedScriptHashes[hashScript(text)]=1;
|
|
681
698
|
});
|
|
682
|
-
function
|
|
699
|
+
function cacheKey(url){
|
|
700
|
+
var u=new URL(url,location.origin);
|
|
701
|
+
return u.pathname+u.search;
|
|
702
|
+
}
|
|
703
|
+
function defaultLayoutGroup(layout){
|
|
683
704
|
if(!layout)return 'app';
|
|
684
|
-
|
|
685
|
-
|
|
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||'');
|
|
686
720
|
}
|
|
687
|
-
function checkLayoutChange(newLayout,targetUrl){
|
|
721
|
+
function checkLayoutChange(newLayout,targetUrl,newGroup){
|
|
688
722
|
var currentLayout=document.querySelector('meta[name="stx-layout"]');
|
|
689
723
|
var curLayoutName=currentLayout?currentLayout.getAttribute('content'):'';
|
|
690
|
-
var curGroup=
|
|
691
|
-
var newGroup
|
|
692
|
-
|
|
724
|
+
var curGroup=getCurrentLayoutGroup();
|
|
725
|
+
var nextGroup=newGroup||defaultLayoutGroup(newLayout);
|
|
726
|
+
log('[router] layout check: current='+curLayoutName+'('+curGroup+') new='+(newLayout||'')+'('+nextGroup+')');
|
|
693
727
|
// Different layout GROUP (e.g. app \u2192 auth): full reload
|
|
694
|
-
if(curGroup!==
|
|
695
|
-
|
|
728
|
+
if(curGroup!==nextGroup){
|
|
729
|
+
log('[router] layout group change:',curGroup,'\u2192',nextGroup,'\u2014 full reload to:',targetUrl);
|
|
696
730
|
return true;
|
|
697
731
|
}
|
|
698
732
|
// Same group but different SPECIFIC layout (e.g. layouts/app \u2192 layouts/coach):
|
|
699
733
|
// full body swap so nav, sidebar, and other layout-level elements update
|
|
700
734
|
if(curLayoutName && newLayout && curLayoutName!==newLayout){
|
|
701
|
-
|
|
735
|
+
log('[router] layout name change:',curLayoutName,'\u2192',newLayout,'\u2014 full body swap');
|
|
702
736
|
return true;
|
|
703
737
|
}
|
|
704
738
|
return false;
|
|
705
739
|
}
|
|
706
740
|
|
|
707
741
|
function navigate(url,pushState,force){
|
|
708
|
-
|
|
742
|
+
log('[router] navigate() called:',url,'isNavigating:',isNavigating);
|
|
709
743
|
if(isNavigating)return;
|
|
710
744
|
var t=new URL(url,location.origin);
|
|
711
745
|
|
|
@@ -718,27 +752,33 @@ function getRouterScript() {
|
|
|
718
752
|
return;
|
|
719
753
|
}
|
|
720
754
|
|
|
721
|
-
if
|
|
755
|
+
// Skip if user clicks a link to the page they're already on. We
|
|
756
|
+
// deliberately allow popstate (pushState===false) through because
|
|
757
|
+
// the browser has already updated location.href to the popped
|
|
758
|
+
// entry \u2014 without this allowance, hitting back would early-return
|
|
759
|
+
// and the visible page content would be left frozen on the
|
|
760
|
+
// forward-navigation page.
|
|
761
|
+
if(pushState!==false&&t.href===location.href&&!t.hash&&!force)return;
|
|
722
762
|
|
|
723
763
|
isNavigating=true;
|
|
724
764
|
document.body.classList.add(o.loadingClass);
|
|
725
765
|
startProgress();
|
|
726
766
|
|
|
727
767
|
var targetHref=t.href;
|
|
728
|
-
var targetPath=
|
|
768
|
+
var targetPath=cacheKey(url);
|
|
729
769
|
var targetHash=t.hash;
|
|
730
770
|
|
|
731
771
|
function done(){isNavigating=false;document.body.classList.remove(o.loadingClass);finishProgress()}
|
|
732
772
|
|
|
733
773
|
if(o.cache&&cache[targetPath]&&!force){
|
|
734
|
-
if(checkLayoutChange(layoutCache[targetPath],url)){
|
|
774
|
+
if(checkLayoutChange(layoutCache[targetPath],url,layoutGroupCache[targetPath])){
|
|
735
775
|
// Layout changed \u2014 fetch full page and do full document swap
|
|
736
|
-
|
|
776
|
+
log('[router] cache hit but layout changed \u2014 fetching full page');
|
|
737
777
|
fetch(url,{headers:{'Accept':'text/html'}}).then(function(r){
|
|
738
778
|
if(!r.ok)throw new Error(r.status);
|
|
739
779
|
return r.text();
|
|
740
780
|
}).then(function(html){
|
|
741
|
-
|
|
781
|
+
log('[router] full page fetched from cache path, len:',html.length);
|
|
742
782
|
swap(html,targetPath,pushState,targetHash);
|
|
743
783
|
}).catch(function(err){
|
|
744
784
|
console.error('[router] full page fetch error:',err);
|
|
@@ -756,23 +796,24 @@ else {
|
|
|
756
796
|
if(!r.ok)throw new Error(r.status);
|
|
757
797
|
var isFragment=r.headers.get('X-STX-Fragment')==='true';
|
|
758
798
|
var newLayout=r.headers.get('X-STX-Layout')||'';
|
|
799
|
+
var newGroup=r.headers.get('X-STX-Layout-Group')||'';
|
|
759
800
|
// Layout change? Fetch the FULL page (no X-STX-Router header) and do full document swap
|
|
760
|
-
if(isFragment&&checkLayoutChange(newLayout,url)){
|
|
761
|
-
|
|
801
|
+
if(isFragment&&checkLayoutChange(newLayout,url,newGroup)){
|
|
802
|
+
log('[router] layout change \u2014 fetching full page for document swap');
|
|
762
803
|
return fetch(url,{headers:{'Accept':'text/html'}}).then(function(fullRes){
|
|
763
|
-
|
|
804
|
+
log('[router] full page fetched:',fullRes.status,'ok:',fullRes.ok);
|
|
764
805
|
if(!fullRes.ok)throw new Error(fullRes.status);
|
|
765
806
|
return fullRes.text().then(function(html){
|
|
766
|
-
|
|
767
|
-
return{html:html,isFragment:false,layout:newLayout};
|
|
807
|
+
log('[router] full page html length:',html.length);
|
|
808
|
+
return{html:html,isFragment:false,layout:newLayout,layoutGroup:newGroup};
|
|
768
809
|
});
|
|
769
810
|
});
|
|
770
811
|
}
|
|
771
|
-
return r.text().then(function(html){return{html:html,isFragment:isFragment,layout:newLayout}});
|
|
812
|
+
return r.text().then(function(html){return{html:html,isFragment:isFragment,layout:newLayout,layoutGroup:newGroup}});
|
|
772
813
|
}).then(function(result){
|
|
773
814
|
if(!result)return;
|
|
774
815
|
if(result.isFragment)result.html='<!--stx-fragment-->'+result.html;
|
|
775
|
-
if(o.cache){cache[targetPath]=result.html;layoutCache[targetPath]=result.layout}
|
|
816
|
+
if(o.cache){cache[targetPath]=result.html;layoutCache[targetPath]=result.layout;layoutGroupCache[targetPath]=result.layoutGroup}
|
|
776
817
|
swap(result.html,targetPath,pushState,targetHash);
|
|
777
818
|
}).catch(function(err){
|
|
778
819
|
console.error('[router] fetch error:',err);
|
|
@@ -785,8 +826,8 @@ else {
|
|
|
785
826
|
var isFragment=html.indexOf('<!--stx-fragment-->')===0;
|
|
786
827
|
if(isFragment)html=html.slice('<!--stx-fragment-->'.length);
|
|
787
828
|
var currentContent=getContainer();
|
|
788
|
-
|
|
789
|
-
if(!currentContent){
|
|
829
|
+
log('[router] swap: isFragment='+isFragment+' container='+!!currentContent+' tag='+(currentContent&¤tContent.tagName)+' selector='+containerSel+' htmlLen='+html.length);
|
|
830
|
+
if(!currentContent){log('[router] no container \u2014 falling back');location.href=url;return}
|
|
790
831
|
|
|
791
832
|
// Fragment mode: server returned just the page content (no document wrapper)
|
|
792
833
|
if(isFragment){
|
|
@@ -841,10 +882,22 @@ else {
|
|
|
841
882
|
else if(hash){var el=document.querySelector(hash);if(el)el.scrollIntoView({behavior:'smooth'})}
|
|
842
883
|
window.dispatchEvent(new CustomEvent('stx:navigate',{detail:{url:url}}));
|
|
843
884
|
// Execute page scripts FIRST \u2014 they define setup functions and set _latestSetup
|
|
844
|
-
|
|
885
|
+
log('[router] frag scripts:', fragScripts.length);
|
|
845
886
|
document.querySelectorAll('script[data-stx-page]').forEach(function(s){s.remove()});
|
|
846
887
|
fragScripts.forEach(function(code){
|
|
847
|
-
|
|
888
|
+
log('[router] exec script len:', code.length, 'has __stx_setup:', code.indexOf('__stx_setup')>-1);
|
|
889
|
+
// Skip scripts that were already executed (layout-level partials
|
|
890
|
+
// like theme.stx, stores.stx, nav.stx). Their top-level const/let
|
|
891
|
+
// declarations would throw "Identifier has already been declared"
|
|
892
|
+
// on re-execution. Setup functions (__stx_setup_) must always
|
|
893
|
+
// re-execute because each page has its own setup.
|
|
894
|
+
var h=hashScript(code);
|
|
895
|
+
var isSetup=code.indexOf('__stx_setup_')!==-1;
|
|
896
|
+
if(!isSetup&&executedScriptHashes[h]){
|
|
897
|
+
log('[router] skipping already-executed script (hash dedup)');
|
|
898
|
+
return;
|
|
899
|
+
}
|
|
900
|
+
executedScriptHashes[h]=1;
|
|
848
901
|
var ns=document.createElement('script');
|
|
849
902
|
// Wrap in block scope to prevent const/let collisions on re-navigation.
|
|
850
903
|
// Without this, navigating away and back throws "Identifier has already
|
|
@@ -855,7 +908,7 @@ else {
|
|
|
855
908
|
ns.setAttribute('data-stx-page','');
|
|
856
909
|
document.body.appendChild(ns);
|
|
857
910
|
});
|
|
858
|
-
|
|
911
|
+
log('[router] scripts done. _latestSetup:', !!window.stx._latestSetup);
|
|
859
912
|
// THEN fire stx:load \u2014 now _latestSetup is set and processElement has the right scope
|
|
860
913
|
window.dispatchEvent(new Event('stx:load'));
|
|
861
914
|
}
|
|
@@ -927,12 +980,14 @@ else {
|
|
|
927
980
|
if(newBody){
|
|
928
981
|
var newMeta=doc.querySelector('meta[name="stx-layout"]');
|
|
929
982
|
var curMeta=document.querySelector('meta[name="stx-layout"]');
|
|
930
|
-
var
|
|
931
|
-
var
|
|
932
|
-
|
|
983
|
+
var curLayout=curMeta?curMeta.getAttribute('content'):'';
|
|
984
|
+
var newLayout=newMeta?newMeta.getAttribute('content'):'';
|
|
985
|
+
var curGroup=getCurrentLayoutGroup();
|
|
986
|
+
var newGroup=getDocLayoutGroup(doc,newLayout);
|
|
987
|
+
isLayoutChange=curGroup!==newGroup||(curLayout&&newLayout&&curLayout!==newLayout);
|
|
933
988
|
}
|
|
934
989
|
if(isLayoutChange&&newBody){
|
|
935
|
-
|
|
990
|
+
log('[router] full body swap for layout change');
|
|
936
991
|
// Replace entire body content \u2014 layout chrome and all
|
|
937
992
|
var bodyHTML=newBody.innerHTML.replace(new RegExp('<scr'+'ipt\\\\b[^>]*>[\\\\s\\\\S]*?<\\\\/scr'+'ipt\\\\s*>','gi'),'');
|
|
938
993
|
document.body.innerHTML=bodyHTML;
|
|
@@ -943,6 +998,10 @@ else {
|
|
|
943
998
|
var freshMeta=doc.querySelector('meta[name="stx-layout"]');
|
|
944
999
|
if(oldMeta&&freshMeta)oldMeta.setAttribute('content',freshMeta.getAttribute('content')||'');
|
|
945
1000
|
else if(freshMeta){var m=document.createElement('meta');m.name='stx-layout';m.content=freshMeta.getAttribute('content')||'';document.head.appendChild(m)}
|
|
1001
|
+
var oldGroupMeta=document.querySelector('meta[name="stx-layout-group"]');
|
|
1002
|
+
var freshGroupMeta=doc.querySelector('meta[name="stx-layout-group"]');
|
|
1003
|
+
if(oldGroupMeta&&freshGroupMeta)oldGroupMeta.setAttribute('content',freshGroupMeta.getAttribute('content')||'');
|
|
1004
|
+
else if(freshGroupMeta){var gm=document.createElement('meta');gm.name='stx-layout-group';gm.content=freshGroupMeta.getAttribute('content')||'';document.head.appendChild(gm)}
|
|
946
1005
|
// Update container reference for script execution below
|
|
947
1006
|
currentContent=document.querySelector(containerSel)||document.querySelector('main')||document.body;
|
|
948
1007
|
} else {
|
|
@@ -1130,12 +1189,12 @@ else {
|
|
|
1130
1189
|
}
|
|
1131
1190
|
if(!link){return}
|
|
1132
1191
|
var href=link.getAttribute('href');
|
|
1133
|
-
|
|
1134
|
-
if(!href||href.startsWith('http')||href.startsWith('#')||href.startsWith('mailto:')||href.startsWith('tel:')){
|
|
1192
|
+
log('[router] click intercepted:',href,'container:',!!getContainer(),'defaultPrevented:',e.defaultPrevented);
|
|
1193
|
+
if(!href||href.startsWith('http')||href.startsWith('#')||href.startsWith('mailto:')||href.startsWith('tel:')){log('[router] skipped:',href);return}
|
|
1135
1194
|
if(link.target==='_blank'||link.hasAttribute('download'))return;
|
|
1136
1195
|
e.preventDefault();
|
|
1137
1196
|
e.stopPropagation();
|
|
1138
|
-
|
|
1197
|
+
log('[router] navigating to:',href);
|
|
1139
1198
|
navigate(href);
|
|
1140
1199
|
},true);
|
|
1141
1200
|
|
|
@@ -1151,15 +1210,17 @@ else {
|
|
|
1151
1210
|
var link=e.target.closest('[data-stx-link]');
|
|
1152
1211
|
if(!link)return;
|
|
1153
1212
|
var href=link.getAttribute('href');
|
|
1154
|
-
|
|
1155
|
-
prefetching[
|
|
1213
|
+
var key=cacheKey(href);
|
|
1214
|
+
if(cache[key]||prefetching[key])return;
|
|
1215
|
+
prefetching[key]=true;
|
|
1156
1216
|
fetch(href,{headers:{'X-STX-Router':'true','Accept':'text/html'}}).then(function(r){
|
|
1157
1217
|
var isFrag=r.headers.get('X-STX-Fragment')==='true';
|
|
1158
1218
|
var pLayout=r.headers.get('X-STX-Layout')||'';
|
|
1159
|
-
|
|
1219
|
+
var pGroup=r.headers.get('X-STX-Layout-Group')||'';
|
|
1220
|
+
return r.text().then(function(html){return{html:isFrag?'<!--stx-fragment-->'+html:html,layout:pLayout,layoutGroup:pGroup}});
|
|
1160
1221
|
}).then(function(result){
|
|
1161
|
-
if(o.cache){cache[
|
|
1162
|
-
}).catch(function(){}).finally(function(){delete prefetching[
|
|
1222
|
+
if(o.cache){cache[key]=result.html;layoutCache[key]=result.layout;layoutGroupCache[key]=result.layoutGroup}
|
|
1223
|
+
}).catch(function(){}).finally(function(){delete prefetching[key]});
|
|
1163
1224
|
},true);
|
|
1164
1225
|
}
|
|
1165
1226
|
|
|
@@ -1252,11 +1313,12 @@ else {
|
|
|
1252
1313
|
navigate:navigate,
|
|
1253
1314
|
navigateTo:navigate,
|
|
1254
1315
|
prefetch:function(url){
|
|
1255
|
-
|
|
1256
|
-
|
|
1316
|
+
var key=cacheKey(url);
|
|
1317
|
+
if(!cache[key]){
|
|
1318
|
+
fetch(url,{headers:{'X-STX-Router':'true'}}).then(function(r){var isFrag=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(){});
|
|
1257
1319
|
}
|
|
1258
1320
|
},
|
|
1259
|
-
clearCache:function(){for(var k in cache)delete cache[k]},
|
|
1321
|
+
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]},
|
|
1260
1322
|
cache:cache,
|
|
1261
1323
|
swap:swap,
|
|
1262
1324
|
updateNav:updateNav
|
|
@@ -1298,6 +1360,8 @@ export {
|
|
|
1298
1360
|
formatRoutes,
|
|
1299
1361
|
findErrorPage,
|
|
1300
1362
|
filePathToPattern,
|
|
1363
|
+
extractLayoutMetadata,
|
|
1364
|
+
deriveLayoutGroup,
|
|
1301
1365
|
defineRoutes,
|
|
1302
1366
|
defineRoute,
|
|
1303
1367
|
defineMiddleware,
|
|
@@ -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 };
|
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,9 +8959,9 @@ 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-
|
|
8960
|
-
const
|
|
8961
|
-
const router = new Router(process19.cwd(), {
|
|
8962
|
+
const { Router } = await import("./chunk-0nwya50v.js");
|
|
8963
|
+
const pagesDirs = patterns.map((p) => p.replace(/\/$/, "")).filter(Boolean);
|
|
8964
|
+
const router = new Router(process19.cwd(), { pagesDirs });
|
|
8962
8965
|
console.log(`[stx] Generated ${router.routes.length} routes \u2192 .stx/routes.ts`);
|
|
8963
8966
|
} catch (e) {}
|
|
8964
8967
|
return files;
|
|
@@ -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.51",
|
|
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",
|
|
@@ -72,6 +73,7 @@
|
|
|
72
73
|
"typecheck": "bun tsc --noEmit"
|
|
73
74
|
},
|
|
74
75
|
"dependencies": {
|
|
75
|
-
"@stacksjs/stx": "0.2.
|
|
76
|
+
"@stacksjs/stx": "0.2.51",
|
|
77
|
+
"stx-router": "0.2.51"
|
|
76
78
|
}
|
|
77
79
|
}
|