bun-plugin-stx 0.2.337 → 0.2.339
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.
|
@@ -651,6 +651,51 @@ async function runMiddleware(middlewareNames, context) {
|
|
|
651
651
|
}
|
|
652
652
|
// ../router/src/client.ts
|
|
653
653
|
var cachedRouterScript;
|
|
654
|
+
var cachedRouterScriptDev;
|
|
655
|
+
function stripRouterLogs(source) {
|
|
656
|
+
const out = [];
|
|
657
|
+
const needle = "log(";
|
|
658
|
+
let i = 0;
|
|
659
|
+
while (i < source.length) {
|
|
660
|
+
const hit = source.indexOf(needle, i);
|
|
661
|
+
if (hit === -1) {
|
|
662
|
+
out.push(source.slice(i));
|
|
663
|
+
break;
|
|
664
|
+
}
|
|
665
|
+
const before = hit > 0 ? source[hit - 1] : " ";
|
|
666
|
+
const isDeclaration = /\bfunction\s+$/.test(source.slice(Math.max(0, hit - 16), hit));
|
|
667
|
+
if (/[\w$.]/.test(before) || isDeclaration) {
|
|
668
|
+
out.push(source.slice(i, hit + needle.length));
|
|
669
|
+
i = hit + needle.length;
|
|
670
|
+
continue;
|
|
671
|
+
}
|
|
672
|
+
out.push(source.slice(i, hit));
|
|
673
|
+
let depth = 1;
|
|
674
|
+
let j = hit + needle.length;
|
|
675
|
+
while (j < source.length && depth > 0) {
|
|
676
|
+
const character = source[j];
|
|
677
|
+
if (character === '"' || character === "'" || character === "`") {
|
|
678
|
+
const quote = character;
|
|
679
|
+
j++;
|
|
680
|
+
while (j < source.length && source[j] !== quote) {
|
|
681
|
+
if (source[j] === "\\")
|
|
682
|
+
j++;
|
|
683
|
+
j++;
|
|
684
|
+
}
|
|
685
|
+
j++;
|
|
686
|
+
continue;
|
|
687
|
+
}
|
|
688
|
+
if (character === "(")
|
|
689
|
+
depth++;
|
|
690
|
+
else if (character === ")")
|
|
691
|
+
depth--;
|
|
692
|
+
j++;
|
|
693
|
+
}
|
|
694
|
+
out.push("0");
|
|
695
|
+
i = j;
|
|
696
|
+
}
|
|
697
|
+
return out.join("");
|
|
698
|
+
}
|
|
654
699
|
function minifyRouterScript(source) {
|
|
655
700
|
try {
|
|
656
701
|
const transpiler = new Bun.Transpiler({ loader: "js", minifyWhitespace: true });
|
|
@@ -659,22 +704,109 @@ function minifyRouterScript(source) {
|
|
|
659
704
|
return source;
|
|
660
705
|
}
|
|
661
706
|
}
|
|
662
|
-
function
|
|
663
|
-
|
|
664
|
-
return cachedRouterScript;
|
|
665
|
-
const source = `
|
|
707
|
+
function routerSource() {
|
|
708
|
+
return `
|
|
666
709
|
;(function(){
|
|
667
710
|
'use strict';
|
|
668
711
|
var ROUTER_REV=7;
|
|
669
712
|
if(window.__stxRouter&&window.__stxRouter.__rev===ROUTER_REV)return;
|
|
670
713
|
|
|
671
714
|
// \u2500\u2500 Configuration \u2500\u2500
|
|
672
|
-
var defaults={container:'main',loadingClass:'stx-navigating',viewTransitions:true,cache:true,scrollToTop:true,prefetch:true,progress:true,progressColor:'#78dce8',progressHeight:'2px',interceptAllLinks:false,prefetchCacheMax:50,routeFocus:true,announceRoute:true,interceptForms:false,cssLoadTimeout:1500};
|
|
715
|
+
var defaults={container:'main',loadingClass:'stx-navigating',viewTransitions:true,cache:true,scrollToTop:true,prefetch:true,progress:true,progressColor:'#78dce8',progressHeight:'2px',interceptAllLinks:false,prefetchCacheMax:50,routeFocus:true,announceRoute:true,interceptForms:false,cssLoadTimeout:1500,scrollRestoration:true};
|
|
673
716
|
var o=Object.assign({},defaults,window.__stxRouterConfig||{},window.STX_ROUTER_OPTIONS||{});
|
|
674
717
|
var containerSel=o.container;
|
|
675
718
|
var debug=!!o.debug;
|
|
676
719
|
function log(){if(debug&&typeof console!=='undefined'&&console.log)console.log.apply(console,arguments)}
|
|
677
720
|
|
|
721
|
+
// Shorthands for the document-rooted queries this script makes ~33 times.
|
|
722
|
+
// Every page carries these bytes, and the budget in
|
|
723
|
+
// scripts/performance-budgets.ts is what noticed.
|
|
724
|
+
var LAYOUT_META='meta[name="stx-layout"]';
|
|
725
|
+
var LAYOUT_GROUP_META='meta[name="stx-layout-group"]';
|
|
726
|
+
var BUILD_META='meta[name="stx-build"]';
|
|
727
|
+
function qs(sel){return document.querySelector(sel)}
|
|
728
|
+
function qsa(sel){return document.querySelectorAll(sel)}
|
|
729
|
+
function ce(tag){return document.createElement(tag)}
|
|
730
|
+
function dhead(){return document.head}
|
|
731
|
+
|
|
732
|
+
// \u2500\u2500 Scroll position \u2500\u2500
|
|
733
|
+
// Forward navigation goes to the top, or to the hash. Back and forward return
|
|
734
|
+
// to where the entry was left -- the browser cannot do that for us, because
|
|
735
|
+
// by the time it would restore, the content of the entry has not been fetched
|
|
736
|
+
// yet, so it clamps to whatever height the outgoing page happened to have.
|
|
737
|
+
// history.scrollRestoration therefore goes to manual and the positions are
|
|
738
|
+
// kept here, keyed by a token written into each history entry (two entries
|
|
739
|
+
// for the same URL keep their own positions, which is the point).
|
|
740
|
+
//
|
|
741
|
+
// Manual restoration also takes the browser's reload behaviour away, so the
|
|
742
|
+
// positions are mirrored into sessionStorage: a reload, or a return to the
|
|
743
|
+
// tab, finds the entry's token already in history.state and restores from
|
|
744
|
+
// there. sessionStorage is per tab and dies with it, same as the history.
|
|
745
|
+
var SCROLL_TOKEN='__stxScroll';
|
|
746
|
+
var SCROLL_STORE='stx:scroll:';
|
|
747
|
+
var scrollSeq=0;
|
|
748
|
+
var pendingScroll=null;
|
|
749
|
+
var restoreScroll=!!o.scrollRestoration;
|
|
750
|
+
function newScrollToken(){return 's'+(++scrollSeq)+'-'+Date.now()}
|
|
751
|
+
var scrollToken=(history.state&&history.state[SCROLL_TOKEN])||newScrollToken();
|
|
752
|
+
// sessionStorage is the only store: it is synchronous, it is per tab, it dies
|
|
753
|
+
// with the tab exactly as the history does, and it is the one that survives a
|
|
754
|
+
// reload. A private window that refuses it degrades to scrolling to the top.
|
|
755
|
+
function readScroll(token){
|
|
756
|
+
try{
|
|
757
|
+
var parts=(window.sessionStorage.getItem(SCROLL_STORE+token)||'').split(',');
|
|
758
|
+
return parts.length===2?[parseFloat(parts[0])||0,parseFloat(parts[1])||0]:null;
|
|
759
|
+
}catch(e){return null}
|
|
760
|
+
}
|
|
761
|
+
// Called while the outgoing entry is still the current one, so the position
|
|
762
|
+
// read here belongs to the token being written.
|
|
763
|
+
function rememberScroll(){
|
|
764
|
+
if(!restoreScroll)return;
|
|
765
|
+
try{window.sessionStorage.setItem(SCROLL_STORE+scrollToken,(window.pageXOffset||window.scrollX||0)+','+(window.pageYOffset||window.scrollY||0))}catch(e){}
|
|
766
|
+
}
|
|
767
|
+
// One place decides where a swap leaves the viewport, so the fragment path
|
|
768
|
+
// and the whole-document path cannot drift apart.
|
|
769
|
+
function applyScroll(hash){
|
|
770
|
+
if(pendingScroll){
|
|
771
|
+
var at=pendingScroll;
|
|
772
|
+
pendingScroll=null;
|
|
773
|
+
window.scrollTo({left:at[0],top:at[1],behavior:'instant'});
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
if(o.scrollToTop&&!hash){window.scrollTo({top:0,behavior:'instant'});return}
|
|
777
|
+
if(hash){var el=qs(hash);if(el)el.scrollIntoView({behavior:'smooth'})}
|
|
778
|
+
}
|
|
779
|
+
// Keeps whatever another script put in the entry; only adds the token.
|
|
780
|
+
function stampScrollToken(){
|
|
781
|
+
var state={};
|
|
782
|
+
var current=history.state;
|
|
783
|
+
if(current&&typeof current==='object')for(var key in current)state[key]=current[key];
|
|
784
|
+
state[SCROLL_TOKEN]=scrollToken;
|
|
785
|
+
try{history.replaceState(state,'',location.href)}catch(e){}
|
|
786
|
+
}
|
|
787
|
+
if(restoreScroll){
|
|
788
|
+
try{history.scrollRestoration='manual'}catch(e){}
|
|
789
|
+
// A token already in the entry means this document is a reload or a
|
|
790
|
+
// restore of an entry visited before, so its position is worth asking for.
|
|
791
|
+
var known=history.state&&history.state[SCROLL_TOKEN];
|
|
792
|
+
if(known){
|
|
793
|
+
var saved=readScroll(scrollToken);
|
|
794
|
+
if(saved&&(saved[0]||saved[1])){
|
|
795
|
+
var restoreAt=function(){window.scrollTo({left:saved[0],top:saved[1],behavior:'instant'})};
|
|
796
|
+
if(document.readyState==='complete')restoreAt();
|
|
797
|
+
else window.addEventListener('load',restoreAt,{once:true});
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
else{
|
|
801
|
+
stampScrollToken();
|
|
802
|
+
}
|
|
803
|
+
// A reload or a link out of the app never calls writeHistory, so this is
|
|
804
|
+
// the only chance to record where the page was left. pagehide fires for
|
|
805
|
+
// both, and unlike beforeunload it does not keep the page out of the
|
|
806
|
+
// back/forward cache.
|
|
807
|
+
window.addEventListener('pagehide',rememberScroll);
|
|
808
|
+
}
|
|
809
|
+
|
|
678
810
|
// Replace, never merge: absent payloads must forget the outgoing page's data.
|
|
679
811
|
// Run at the committed swap, not during prefetch or a superseded navigation.
|
|
680
812
|
function hydrateServerData(html){
|
|
@@ -697,7 +829,7 @@ function getRouterScript() {
|
|
|
697
829
|
// Conservative on purpose: act only when BOTH ids are known. A missing id is
|
|
698
830
|
// "no information", never "mismatch", so statically hosted output (no headers)
|
|
699
831
|
// and older servers behave exactly as before.
|
|
700
|
-
var buildMeta=
|
|
832
|
+
var buildMeta=qs(BUILD_META);
|
|
701
833
|
var loadedBuild=buildMeta?(buildMeta.getAttribute('content')||''):'';
|
|
702
834
|
window.__stxBuild=loadedBuild;
|
|
703
835
|
function isBuildSkew(incoming){
|
|
@@ -845,7 +977,7 @@ function getRouterScript() {
|
|
|
845
977
|
function parseContainerAttrs(attrStr){
|
|
846
978
|
var map={};
|
|
847
979
|
if(!attrStr)return map;
|
|
848
|
-
var probe=
|
|
980
|
+
var probe=ce('div');
|
|
849
981
|
probe.innerHTML='<i '+attrStr+'></i>';
|
|
850
982
|
var src=probe.firstChild;
|
|
851
983
|
// getAttributeNames first: it is the same standard DOM answer and it is
|
|
@@ -934,7 +1066,7 @@ function getRouterScript() {
|
|
|
934
1066
|
}
|
|
935
1067
|
|
|
936
1068
|
function getContainer(){
|
|
937
|
-
return
|
|
1069
|
+
return qs(containerSel)||qs('[data-stx-content]')||qs('main');
|
|
938
1070
|
}
|
|
939
1071
|
|
|
940
1072
|
// \u2500\u2500 Navigation \u2500\u2500
|
|
@@ -1018,7 +1150,7 @@ function getRouterScript() {
|
|
|
1018
1150
|
// navigation. Scripts without an owner are unaffected.
|
|
1019
1151
|
function ownerStays(owner){
|
|
1020
1152
|
if(!owner)return false;
|
|
1021
|
-
var root=
|
|
1153
|
+
var root=qs('[data-stx-scope="'+owner+'"]');
|
|
1022
1154
|
return !root||typeof root.__stx_disposers==='function';
|
|
1023
1155
|
}
|
|
1024
1156
|
function hashScript(code){
|
|
@@ -1185,7 +1317,7 @@ function getRouterScript() {
|
|
|
1185
1317
|
if(!key||loadedExternalScripts[key])return null;
|
|
1186
1318
|
loadedExternalScripts[key]=1;
|
|
1187
1319
|
return new Promise(function(resolve){
|
|
1188
|
-
var el=
|
|
1320
|
+
var el=ce('script');
|
|
1189
1321
|
el.src=key;
|
|
1190
1322
|
// Deliberately NOT data-stx-page: both swap paths clear those on every
|
|
1191
1323
|
// navigation, which would sweep this away and \u2014 since it is never loaded
|
|
@@ -1194,12 +1326,12 @@ function getRouterScript() {
|
|
|
1194
1326
|
el.setAttribute('data-stx-external','');
|
|
1195
1327
|
el.onload=function(){resolve()};
|
|
1196
1328
|
el.onerror=function(){log('[router] container script failed:',key);resolve()};
|
|
1197
|
-
|
|
1329
|
+
dhead().appendChild(el);
|
|
1198
1330
|
});
|
|
1199
1331
|
}
|
|
1200
1332
|
|
|
1201
1333
|
// Record scripts from the initial page load
|
|
1202
|
-
|
|
1334
|
+
qsa('script').forEach(function(s){
|
|
1203
1335
|
var text=s.textContent||'';
|
|
1204
1336
|
if(s.hasAttribute('src'))rememberExternalScript(s.getAttribute('src'));
|
|
1205
1337
|
else if(text.trim())executedScriptHashes[hashScript(text)]=1;
|
|
@@ -1226,17 +1358,17 @@ function getRouterScript() {
|
|
|
1226
1358
|
return part?part.replace(/\\.stx$/i,''):'app';
|
|
1227
1359
|
}
|
|
1228
1360
|
function getCurrentLayoutGroup(){
|
|
1229
|
-
var meta=
|
|
1361
|
+
var meta=qs(LAYOUT_GROUP_META);
|
|
1230
1362
|
if(meta&&meta.getAttribute('content'))return meta.getAttribute('content');
|
|
1231
|
-
var layout=
|
|
1363
|
+
var layout=qs(LAYOUT_META);
|
|
1232
1364
|
return defaultLayoutGroup(layout?layout.getAttribute('content'):'');
|
|
1233
1365
|
}
|
|
1234
1366
|
function getDocLayoutGroup(doc,layout){
|
|
1235
|
-
var meta=doc&&doc.querySelector?doc.querySelector(
|
|
1367
|
+
var meta=doc&&doc.querySelector?doc.querySelector(LAYOUT_GROUP_META):null;
|
|
1236
1368
|
return meta&&meta.getAttribute('content')?meta.getAttribute('content'):defaultLayoutGroup(layout||'');
|
|
1237
1369
|
}
|
|
1238
1370
|
function checkLayoutChange(newLayout,targetUrl,newGroup){
|
|
1239
|
-
var currentLayout=
|
|
1371
|
+
var currentLayout=qs(LAYOUT_META);
|
|
1240
1372
|
var curLayoutName=currentLayout?currentLayout.getAttribute('content'):'';
|
|
1241
1373
|
var curGroup=getCurrentLayoutGroup();
|
|
1242
1374
|
var nextGroup=newGroup||defaultLayoutGroup(newLayout);
|
|
@@ -1265,9 +1397,14 @@ function getRouterScript() {
|
|
|
1265
1397
|
// through swap() to each of the three history sites would have been the
|
|
1266
1398
|
// alternative (#1807).
|
|
1267
1399
|
function writeHistory(mode,href){
|
|
1268
|
-
|
|
1269
|
-
|
|
1400
|
+
// The position belongs to the entry being left, and scrollToken still
|
|
1401
|
+
// names it here.
|
|
1402
|
+
rememberScroll();
|
|
1403
|
+
if(mode==='replace'){history.replaceState(tokenState(),'',href);return}
|
|
1404
|
+
scrollToken=newScrollToken();
|
|
1405
|
+
history.pushState(tokenState(),'',href);
|
|
1270
1406
|
}
|
|
1407
|
+
function tokenState(){var state={};state[SCROLL_TOKEN]=scrollToken;return state}
|
|
1271
1408
|
|
|
1272
1409
|
// Second arg accepts the legacy pushState boolean OR an options object
|
|
1273
1410
|
// { replace }. Callers inside this file still pass the boolean.
|
|
@@ -1289,7 +1426,7 @@ function getRouterScript() {
|
|
|
1289
1426
|
|
|
1290
1427
|
if(t.pathname===location.pathname&&t.hash){
|
|
1291
1428
|
if(pushState!==false)writeHistory(pushState,t.href);
|
|
1292
|
-
var el=
|
|
1429
|
+
var el=qs(t.hash);
|
|
1293
1430
|
if(el)el.scrollIntoView({behavior:'smooth'});
|
|
1294
1431
|
return Promise.resolve(true);
|
|
1295
1432
|
}
|
|
@@ -1434,7 +1571,7 @@ else {
|
|
|
1434
1571
|
function routeAnnouncer(){
|
|
1435
1572
|
var el=document.getElementById('stx-route-announcer');
|
|
1436
1573
|
if(el)return el;
|
|
1437
|
-
el=
|
|
1574
|
+
el=ce('div');
|
|
1438
1575
|
el.id='stx-route-announcer';
|
|
1439
1576
|
el.setAttribute('aria-live','polite');
|
|
1440
1577
|
el.setAttribute('role','status');
|
|
@@ -1467,7 +1604,7 @@ else {
|
|
|
1467
1604
|
function focusAfterNavigation(hash){
|
|
1468
1605
|
if(o.routeFocus===false)return;
|
|
1469
1606
|
var target=null;
|
|
1470
|
-
if(hash){try{target=
|
|
1607
|
+
if(hash){try{target=qs(hash)}catch(e){target=null}}
|
|
1471
1608
|
if(!target)target=getContainer();
|
|
1472
1609
|
if(!target||!target.focus)return;
|
|
1473
1610
|
// The container is not naturally focusable. tabindex="-1" makes it
|
|
@@ -1490,7 +1627,7 @@ else {
|
|
|
1490
1627
|
// be the last one, every navigation, not just the first time it is seen.
|
|
1491
1628
|
function findGeneratedCss(abs){
|
|
1492
1629
|
var found=null;
|
|
1493
|
-
|
|
1630
|
+
qsa('head link[data-css][href]').forEach(function(link){
|
|
1494
1631
|
if(new URL(link.getAttribute('href'),location.href).href!==abs)return;
|
|
1495
1632
|
// Collapse duplicates, so moving one copy to the end can never leave an
|
|
1496
1633
|
// older copy of the same sheet behind to fight it.
|
|
@@ -1519,7 +1656,7 @@ else {
|
|
|
1519
1656
|
if(link.__stxCssReady)pending.push(link.__stxCssReady);
|
|
1520
1657
|
return;
|
|
1521
1658
|
}
|
|
1522
|
-
link=
|
|
1659
|
+
link=ce('link');
|
|
1523
1660
|
link.setAttribute('data-css','generated');
|
|
1524
1661
|
link.setAttribute('rel','stylesheet');
|
|
1525
1662
|
link.setAttribute('href',new URL(href,location.href).href===abs?href:abs);
|
|
@@ -1540,7 +1677,7 @@ else {
|
|
|
1540
1677
|
link.onerror=function(){finish(true)};
|
|
1541
1678
|
});
|
|
1542
1679
|
pending.push(link.__stxCssReady);
|
|
1543
|
-
|
|
1680
|
+
dhead().appendChild(link);
|
|
1544
1681
|
});
|
|
1545
1682
|
return pending.length?Promise.all(pending).then(function(results){return results.every(function(ok){return ok!==false})}):null;
|
|
1546
1683
|
}
|
|
@@ -1576,7 +1713,7 @@ else {
|
|
|
1576
1713
|
link.removeAttribute('data-stx-css-pending');
|
|
1577
1714
|
link.removeAttribute('media');
|
|
1578
1715
|
}
|
|
1579
|
-
|
|
1716
|
+
dhead().appendChild(link);
|
|
1580
1717
|
});
|
|
1581
1718
|
}
|
|
1582
1719
|
|
|
@@ -1689,18 +1826,18 @@ else {
|
|
|
1689
1826
|
});
|
|
1690
1827
|
cleanFrag=cleanFrag.replace(new RegExp('<!--stx-held-script-(\\\\d+)-->','g'),function(m,i){return heldScripts[Number(i)]});
|
|
1691
1828
|
// Remove old page styles (not css \u2014 that gets merged)
|
|
1692
|
-
|
|
1829
|
+
qsa('style[data-stx-page]').forEach(function(s){s.remove()});
|
|
1693
1830
|
// Merge css CSS from fragment into existing css style
|
|
1694
1831
|
if(fragCss){
|
|
1695
|
-
var curCss=
|
|
1832
|
+
var curCss=qs('head style[data-css]');
|
|
1696
1833
|
if(curCss){
|
|
1697
1834
|
var merged=mergeCss(curCss.textContent||'',fragCss);
|
|
1698
1835
|
if(merged)curCss.textContent=merged;
|
|
1699
1836
|
}else{
|
|
1700
|
-
var cw=
|
|
1837
|
+
var cw=ce('style');
|
|
1701
1838
|
cw.setAttribute('data-css','generated');
|
|
1702
1839
|
cw.textContent=fragCss;
|
|
1703
|
-
|
|
1840
|
+
dhead().appendChild(cw);
|
|
1704
1841
|
}
|
|
1705
1842
|
}
|
|
1706
1843
|
// Already present ones are MOVED last, not skipped \u2014 see
|
|
@@ -1708,10 +1845,10 @@ else {
|
|
|
1708
1845
|
promoteGeneratedCss(fragCssHrefs,location.href);
|
|
1709
1846
|
// Add new page styles
|
|
1710
1847
|
fragStyles.forEach(function(s){
|
|
1711
|
-
var el=
|
|
1848
|
+
var el=ce('style');
|
|
1712
1849
|
el.textContent=s.css;
|
|
1713
1850
|
el.setAttribute('data-stx-page','');
|
|
1714
|
-
|
|
1851
|
+
dhead().appendChild(el);
|
|
1715
1852
|
});
|
|
1716
1853
|
// Swap content \u2014 apply the destination container's own attributes first
|
|
1717
1854
|
// so the incoming markup lands in a correctly-laid-out container instead
|
|
@@ -1719,11 +1856,10 @@ else {
|
|
|
1719
1856
|
applyContainerAttrs(currentContent,pendingContainerAttrs);
|
|
1720
1857
|
currentContent.innerHTML=cleanFrag;
|
|
1721
1858
|
// Remove old page scripts
|
|
1722
|
-
|
|
1859
|
+
qsa('script[data-stx-page]').forEach(function(s){s.remove()});
|
|
1723
1860
|
if(pushState!==false)writeHistory(pushState,url+(hash||''));
|
|
1724
1861
|
refreshCurrentLinks();
|
|
1725
|
-
|
|
1726
|
-
else if(hash){var el=document.querySelector(hash);if(el)el.scrollIntoView({behavior:'smooth'})}
|
|
1862
|
+
applyScroll(hash);
|
|
1727
1863
|
window.dispatchEvent(new CustomEvent('stx:navigate',{detail:{url:url}}));
|
|
1728
1864
|
// Before page scripts run, so a page that focuses its own control on
|
|
1729
1865
|
// mount still wins \u2014 its script executes after this.
|
|
@@ -1733,7 +1869,7 @@ else {
|
|
|
1733
1869
|
setTimeout(announceRoute,0);
|
|
1734
1870
|
// Execute page scripts FIRST \u2014 they define setup functions and set _latestSetup
|
|
1735
1871
|
log('[router] frag scripts:', fragScripts.length);
|
|
1736
|
-
|
|
1872
|
+
qsa('script[data-stx-page]').forEach(function(s){s.remove()});
|
|
1737
1873
|
// The page's module registry first (#1957), setups last. A fragment
|
|
1738
1874
|
// lists its scripts in document order, and the registry is emitted
|
|
1739
1875
|
// after the content it serves: a component that imports a package ran
|
|
@@ -1745,11 +1881,11 @@ else {
|
|
|
1745
1881
|
fragScripts.forEach(function(entry){
|
|
1746
1882
|
var code=entry.text;
|
|
1747
1883
|
log('[router] exec script len:', code.length, 'has __stx_setup:', code.indexOf('__stx_setup')>-1);
|
|
1748
|
-
var placeholder=
|
|
1884
|
+
var placeholder=qs('script[data-stx-route-script="'+entry.slot+'"]');
|
|
1749
1885
|
var nestedScopedTemplate=false;
|
|
1750
1886
|
var scopedLoopSetup=false;
|
|
1751
1887
|
if(entry.scoped&&placeholder){
|
|
1752
|
-
|
|
1888
|
+
qsa('template').forEach(function(template){
|
|
1753
1889
|
if(template.contains(placeholder)||(template.content&&template.content.contains(placeholder)))
|
|
1754
1890
|
nestedScopedTemplate=true;
|
|
1755
1891
|
});
|
|
@@ -1792,7 +1928,7 @@ else {
|
|
|
1792
1928
|
return;
|
|
1793
1929
|
}
|
|
1794
1930
|
executedScriptHashes[h]=1;
|
|
1795
|
-
var ns=
|
|
1931
|
+
var ns=ce('script');
|
|
1796
1932
|
var hasImport=hasStaticImport(code);
|
|
1797
1933
|
if(hasImport){
|
|
1798
1934
|
ns.type='module';
|
|
@@ -1855,7 +1991,7 @@ else {
|
|
|
1855
1991
|
var doc=parser.parseFromString(html,'text/html');
|
|
1856
1992
|
// Full documents carry the build id as a meta rather than a header, and
|
|
1857
1993
|
// this path also serves cached HTML, so check here too (#1772).
|
|
1858
|
-
var docBuildMeta=doc.querySelector(
|
|
1994
|
+
var docBuildMeta=doc.querySelector(BUILD_META);
|
|
1859
1995
|
var docBuild=docBuildMeta?(docBuildMeta.getAttribute('content')||''):'';
|
|
1860
1996
|
if(isBuildSkew(docBuild)){reloadForSkew(url,docBuild);return Promise.resolve(false)}
|
|
1861
1997
|
// Same hand-off as the fragment path, for the same reason (#1809, #1839).
|
|
@@ -1889,12 +2025,12 @@ else {
|
|
|
1889
2025
|
// \u2500\u2500 Swap <head> styles \u2500\u2500
|
|
1890
2026
|
// Inject new styles FIRST, then remove old to prevent unstyled flash
|
|
1891
2027
|
var keepIds={'stx-view-transitions':1,'stx-r-css':1};
|
|
1892
|
-
var curStyles=
|
|
2028
|
+
var curStyles=qsa('head style');
|
|
1893
2029
|
var newStyles=doc.querySelectorAll('head style');
|
|
1894
2030
|
|
|
1895
2031
|
// Merge css styles instead of replacing \u2014 persistent elements
|
|
1896
2032
|
// (nav, footer) outside <main> still need their utility classes
|
|
1897
|
-
var curCss=
|
|
2033
|
+
var curCss=qs('head style[data-css]');
|
|
1898
2034
|
var newCss=null;
|
|
1899
2035
|
newStyles.forEach(function(s){if(s.getAttribute('data-css'))newCss=s});
|
|
1900
2036
|
|
|
@@ -1906,20 +2042,20 @@ else {
|
|
|
1906
2042
|
var incoming=[];
|
|
1907
2043
|
newStyles.forEach(function(s){
|
|
1908
2044
|
if(!keepIds[s.id]&&!s.getAttribute('data-css')){
|
|
1909
|
-
var ns=
|
|
2045
|
+
var ns=ce('style');
|
|
1910
2046
|
ns.textContent=s.textContent;
|
|
1911
2047
|
ns.setAttribute('data-stx-incoming','');
|
|
1912
|
-
|
|
2048
|
+
dhead().appendChild(ns);
|
|
1913
2049
|
incoming.push(ns);
|
|
1914
2050
|
}
|
|
1915
2051
|
});
|
|
1916
2052
|
|
|
1917
2053
|
// If no existing css but new page has one, add it
|
|
1918
2054
|
if(!curCss&&newCss){
|
|
1919
|
-
var ns=
|
|
2055
|
+
var ns=ce('style');
|
|
1920
2056
|
ns.textContent=newCss.textContent;
|
|
1921
2057
|
ns.setAttribute('data-css',newCss.getAttribute('data-css'));
|
|
1922
|
-
|
|
2058
|
+
dhead().appendChild(ns);
|
|
1923
2059
|
}
|
|
1924
2060
|
|
|
1925
2061
|
// Remove old styles (except persistent ones, css, and incoming)
|
|
@@ -1946,7 +2082,7 @@ else {
|
|
|
1946
2082
|
try{docBase=new URL(url,location.href).href}catch(e){docBase=location.href}
|
|
1947
2083
|
var linkSel='link[rel="stylesheet"],link[rel="preconnect"]';
|
|
1948
2084
|
var curLinks={};
|
|
1949
|
-
|
|
2085
|
+
qsa('head '+linkSel).forEach(function(l){var h=l.getAttribute('href');if(h)curLinks[new URL(h,location.href).href]=1});
|
|
1950
2086
|
doc.querySelectorAll('head '+linkSel).forEach(function(l){
|
|
1951
2087
|
var href=l.getAttribute('href');
|
|
1952
2088
|
if(!href)return;
|
|
@@ -1956,9 +2092,9 @@ else {
|
|
|
1956
2092
|
var abs=new URL(href,docBase).href;
|
|
1957
2093
|
if(curLinks[abs])return;
|
|
1958
2094
|
curLinks[abs]=1;
|
|
1959
|
-
var nl=
|
|
2095
|
+
var nl=ce('link');
|
|
1960
2096
|
Array.from(l.attributes).forEach(function(a){nl.setAttribute(a.name,a.value)});
|
|
1961
|
-
|
|
2097
|
+
dhead().appendChild(nl);
|
|
1962
2098
|
});
|
|
1963
2099
|
// After every other stylesheet link, so the destination's complete
|
|
1964
2100
|
// utility sheet is last in the cascade.
|
|
@@ -1972,8 +2108,8 @@ else {
|
|
|
1972
2108
|
var declaredLayout=pendingLayoutDecl;
|
|
1973
2109
|
pendingLayoutDecl=null;
|
|
1974
2110
|
if(newBody){
|
|
1975
|
-
var newMeta=doc.querySelector(
|
|
1976
|
-
var curMeta=
|
|
2111
|
+
var newMeta=doc.querySelector(LAYOUT_META);
|
|
2112
|
+
var curMeta=qs(LAYOUT_META);
|
|
1977
2113
|
var curLayout=curMeta?curMeta.getAttribute('content'):'';
|
|
1978
2114
|
// The server's answer wins over the document's metas. We are only here
|
|
1979
2115
|
// because checkLayoutChange already said the group changed, based on
|
|
@@ -2041,16 +2177,16 @@ else {
|
|
|
2041
2177
|
// Copy body attributes (class, data-stx, etc.)
|
|
2042
2178
|
Array.from(newBody.attributes).forEach(function(attr){document.body.setAttribute(attr.name,attr.value)});
|
|
2043
2179
|
// Update layout meta tag
|
|
2044
|
-
var oldMeta=
|
|
2045
|
-
var freshMeta=doc.querySelector(
|
|
2180
|
+
var oldMeta=qs(LAYOUT_META);
|
|
2181
|
+
var freshMeta=doc.querySelector(LAYOUT_META);
|
|
2046
2182
|
if(oldMeta&&freshMeta)oldMeta.setAttribute('content',freshMeta.getAttribute('content')||'');
|
|
2047
|
-
else if(freshMeta){var m=
|
|
2048
|
-
var oldGroupMeta=
|
|
2049
|
-
var freshGroupMeta=doc.querySelector(
|
|
2183
|
+
else if(freshMeta){var m=ce('meta');m.name='stx-layout';m.content=freshMeta.getAttribute('content')||'';dhead().appendChild(m)}
|
|
2184
|
+
var oldGroupMeta=qs(LAYOUT_GROUP_META);
|
|
2185
|
+
var freshGroupMeta=doc.querySelector(LAYOUT_GROUP_META);
|
|
2050
2186
|
if(oldGroupMeta&&freshGroupMeta)oldGroupMeta.setAttribute('content',freshGroupMeta.getAttribute('content')||'');
|
|
2051
|
-
else if(freshGroupMeta){var gm=
|
|
2187
|
+
else if(freshGroupMeta){var gm=ce('meta');gm.name='stx-layout-group';gm.content=freshGroupMeta.getAttribute('content')||'';dhead().appendChild(gm)}
|
|
2052
2188
|
// Update container reference for script execution below
|
|
2053
|
-
currentContent=
|
|
2189
|
+
currentContent=qs(containerSel)||qs('main')||document.body;
|
|
2054
2190
|
} else {
|
|
2055
2191
|
// Same layout \u2014 swap only container content. Carry the destination
|
|
2056
2192
|
// container's attributes across too (same reason as the fragment path:
|
|
@@ -2069,7 +2205,7 @@ else {
|
|
|
2069
2205
|
|
|
2070
2206
|
// \u2500\u2500 Load new external <head> scripts \u2500\u2500
|
|
2071
2207
|
var loadedSrcs={};
|
|
2072
|
-
|
|
2208
|
+
qsa('head script[src]').forEach(function(s){loadedSrcs[s.src]=1});
|
|
2073
2209
|
var extPromises=[];
|
|
2074
2210
|
doc.querySelectorAll('head script[src]').forEach(function(s){
|
|
2075
2211
|
if(isSharedClientScript(s))return;
|
|
@@ -2079,11 +2215,11 @@ else {
|
|
|
2079
2215
|
if(loadedSrcs[src])return;
|
|
2080
2216
|
loadedSrcs[src]=1;
|
|
2081
2217
|
extPromises.push(new Promise(function(resolve,reject){
|
|
2082
|
-
var ns=
|
|
2218
|
+
var ns=ce('script');
|
|
2083
2219
|
ns.src=src;
|
|
2084
2220
|
ns.onload=resolve;
|
|
2085
2221
|
ns.onerror=reject;
|
|
2086
|
-
|
|
2222
|
+
dhead().appendChild(ns);
|
|
2087
2223
|
}));
|
|
2088
2224
|
});
|
|
2089
2225
|
|
|
@@ -2097,7 +2233,7 @@ else {
|
|
|
2097
2233
|
|
|
2098
2234
|
// \u2500\u2500 Script re-execution \u2500\u2500
|
|
2099
2235
|
// Remove previously injected page scripts
|
|
2100
|
-
|
|
2236
|
+
qsa('script[data-stx-page]').forEach(function(s){s.remove()});
|
|
2101
2237
|
|
|
2102
2238
|
var scripts=routedBodyScripts.slice();
|
|
2103
2239
|
function addScript(text, runAlways, slot, owner){
|
|
@@ -2181,8 +2317,7 @@ else {
|
|
|
2181
2317
|
refreshCurrentLinks();
|
|
2182
2318
|
|
|
2183
2319
|
// Scroll
|
|
2184
|
-
|
|
2185
|
-
else if(hash){var el=document.querySelector(hash);if(el)el.scrollIntoView({behavior:'smooth'})}
|
|
2320
|
+
applyScroll(hash);
|
|
2186
2321
|
|
|
2187
2322
|
// Update title
|
|
2188
2323
|
var newTitle=doc.querySelector('title');
|
|
@@ -2243,7 +2378,7 @@ else {
|
|
|
2243
2378
|
if(!runAlways&&!isSetup&&executedScriptHashes[h])return;
|
|
2244
2379
|
executedScriptHashes[h]=1;
|
|
2245
2380
|
// Wrap scripts with import statements as modules (Bug 3 fix)
|
|
2246
|
-
var ns=
|
|
2381
|
+
var ns=ce('script');
|
|
2247
2382
|
if(hasImport){
|
|
2248
2383
|
ns.type='module';
|
|
2249
2384
|
}
|
|
@@ -2256,7 +2391,7 @@ else {
|
|
|
2256
2391
|
var alreadyScoped=runsAlways(typeof entry==='string'?'':entry.run,text);
|
|
2257
2392
|
ns.textContent=(hasImport||alreadyScoped)?text:'{'+text+'}';
|
|
2258
2393
|
ns.setAttribute('data-stx-page','');
|
|
2259
|
-
var placeholder=entry.slot?
|
|
2394
|
+
var placeholder=entry.slot?qs('script[data-stx-route-script="'+entry.slot+'"]'):null;
|
|
2260
2395
|
if(placeholder&&placeholder.parentNode){
|
|
2261
2396
|
ns.setAttribute('data-stx-positioned','');
|
|
2262
2397
|
placeholder.parentNode.replaceChild(ns,placeholder);
|
|
@@ -2548,6 +2683,16 @@ else {
|
|
|
2548
2683
|
|
|
2549
2684
|
// \u2500\u2500 Back/forward \u2500\u2500
|
|
2550
2685
|
window.addEventListener('popstate',function(){
|
|
2686
|
+
// Nothing has scrolled yet (restoration is manual), so the viewport still
|
|
2687
|
+
// shows the entry being left: save it under its own token before adopting
|
|
2688
|
+
// the popped entry's, and hand the swap the position to land on.
|
|
2689
|
+
rememberScroll();
|
|
2690
|
+
if(restoreScroll){
|
|
2691
|
+
var popped=history.state&&history.state[SCROLL_TOKEN];
|
|
2692
|
+
scrollToken=popped||newScrollToken();
|
|
2693
|
+
if(!popped)stampScrollToken();
|
|
2694
|
+
pendingScroll=readScroll(scrollToken);
|
|
2695
|
+
}
|
|
2551
2696
|
navigate(location.pathname+location.search+location.hash,false);
|
|
2552
2697
|
});
|
|
2553
2698
|
|
|
@@ -2614,7 +2759,7 @@ else {
|
|
|
2614
2759
|
}
|
|
2615
2760
|
|
|
2616
2761
|
function updateNav(){
|
|
2617
|
-
|
|
2762
|
+
qsa('nav a[href], #mobileNav a[href], [data-stx-nav] a[href]').forEach(function(a){
|
|
2618
2763
|
if(!a.hasAttribute('data-stx-link'))return;
|
|
2619
2764
|
var st=linkState(a.getAttribute('href'),a.getAttribute('data-stx-active-match'));
|
|
2620
2765
|
if(!st)return;
|
|
@@ -2635,7 +2780,7 @@ else {
|
|
|
2635
2780
|
|
|
2636
2781
|
function updateActiveLinks(){
|
|
2637
2782
|
// Update active classes on <stx-link> elements (and legacy data-stx-link)
|
|
2638
|
-
var links=
|
|
2783
|
+
var links=qsa('[data-stx-link]');
|
|
2639
2784
|
links.forEach(function(link){
|
|
2640
2785
|
var st=linkState(link.getAttribute('to')||link.getAttribute('href')||'',link.getAttribute('data-stx-active-match'));
|
|
2641
2786
|
if(!st)return;
|
|
@@ -2677,7 +2822,7 @@ else {
|
|
|
2677
2822
|
// the cascade, or opt out entirely with viewTransitions:false.
|
|
2678
2823
|
function injectStyles(){
|
|
2679
2824
|
if(!document.getElementById('stx-r-css')){
|
|
2680
|
-
var s=
|
|
2825
|
+
var s=ce('style');s.id='stx-r-css';
|
|
2681
2826
|
// Strip characters that could escape our CSS block and inject new
|
|
2682
2827
|
// declarations: ; { } ( ) " ' \\ < > plus whitespace control chars.
|
|
2683
2828
|
// This keeps the value safe to concat into a stylesheet even if a
|
|
@@ -2699,10 +2844,10 @@ else {
|
|
|
2699
2844
|
css+='@media (prefers-reduced-motion: reduce){::view-transition-old(root),::view-transition-new(root){animation-duration:0s;animation-name:none}}';
|
|
2700
2845
|
}
|
|
2701
2846
|
s.textContent=css;
|
|
2702
|
-
|
|
2847
|
+
dhead().appendChild(s);
|
|
2703
2848
|
}
|
|
2704
2849
|
if(o.progress&&!document.getElementById('stx-router-progress')){
|
|
2705
|
-
var el=
|
|
2850
|
+
var el=ce('div');
|
|
2706
2851
|
el.id='stx-router-progress';
|
|
2707
2852
|
el.setAttribute('role','progressbar');
|
|
2708
2853
|
el.setAttribute('aria-hidden','true');
|
|
@@ -2719,7 +2864,7 @@ else {
|
|
|
2719
2864
|
|
|
2720
2865
|
function injectViewTransitionCSS(){
|
|
2721
2866
|
if(document.getElementById('stx-view-transitions'))return;
|
|
2722
|
-
var s=
|
|
2867
|
+
var s=ce('style');s.id='stx-view-transitions';
|
|
2723
2868
|
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}';
|
|
2724
2869
|
(document.head||document.documentElement).appendChild(s);
|
|
2725
2870
|
}
|
|
@@ -2777,9 +2922,19 @@ else {
|
|
|
2777
2922
|
if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',init);else init();
|
|
2778
2923
|
})();
|
|
2779
2924
|
`;
|
|
2780
|
-
|
|
2925
|
+
}
|
|
2926
|
+
function getRouterScript() {
|
|
2927
|
+
if (cachedRouterScript)
|
|
2928
|
+
return cachedRouterScript;
|
|
2929
|
+
cachedRouterScript = minifyRouterScript(stripRouterLogs(routerSource()));
|
|
2781
2930
|
return cachedRouterScript;
|
|
2782
2931
|
}
|
|
2932
|
+
function getRouterScriptDev() {
|
|
2933
|
+
if (cachedRouterScriptDev)
|
|
2934
|
+
return cachedRouterScriptDev;
|
|
2935
|
+
cachedRouterScriptDev = minifyRouterScript(routerSource());
|
|
2936
|
+
return cachedRouterScriptDev;
|
|
2937
|
+
}
|
|
2783
2938
|
export {
|
|
2784
2939
|
setAppUrl,
|
|
2785
2940
|
runMiddleware,
|
|
@@ -2794,6 +2949,7 @@ export {
|
|
|
2794
2949
|
isNonPageRoutePattern,
|
|
2795
2950
|
isNonPageRoutePath,
|
|
2796
2951
|
hasMiddleware,
|
|
2952
|
+
getRouterScriptDev,
|
|
2797
2953
|
getRouterScript,
|
|
2798
2954
|
getMiddlewareNames,
|
|
2799
2955
|
getMiddleware,
|
package/dist/serve.js
CHANGED
|
@@ -9791,7 +9791,7 @@ function __stxOverlay(errs){
|
|
|
9791
9791
|
rebuildDiscoveredPagePaths(kept);
|
|
9792
9792
|
await indexPageMiddleware(kept);
|
|
9793
9793
|
try {
|
|
9794
|
-
const { Router } = await import("./chunk-
|
|
9794
|
+
const { Router } = await import("./chunk-zd4nfpfq.js");
|
|
9795
9795
|
const pagesDirs = patterns.map((p) => p.replace(/\/$/, "")).filter(Boolean);
|
|
9796
9796
|
const router = new Router(process19.cwd(), { pagesDirs, stateDir: stateDirName(), exclude: options.exclude });
|
|
9797
9797
|
if (!options.quiet)
|
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.339",
|
|
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",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"typecheck": "bun tsc --noEmit"
|
|
75
75
|
},
|
|
76
76
|
"dependencies": {
|
|
77
|
-
"@stacksjs/stx": "0.2.
|
|
78
|
-
"stx-router": "0.2.
|
|
77
|
+
"@stacksjs/stx": "0.2.339",
|
|
78
|
+
"stx-router": "0.2.339"
|
|
79
79
|
}
|
|
80
80
|
}
|