@ilha/router 0.6.3 → 0.6.4
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/index.js +1 -1
- package/dist/rolldown.js +1 -1
- package/dist/rspack.d.ts +1 -2
- package/dist/rspack.js +1 -1
- package/dist/src-Cprpo919.js +3 -0
- package/dist/vite.js +1 -1
- package/package.json +2 -2
- package/dist/src-ObXICXKp.js +0 -3
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{C as e,E as t,S as n,T as r,_ as i,a,b as o,c as s,d as c,f as l,g as u,h as d,i as f,l as p,m,n as h,o as g,p as _,r as v,s as y,t as b,u as x,v as S,w as C,x as w,y as T}from"./src-
|
|
1
|
+
import{C as e,E as t,S as n,T as r,_ as i,a,b as o,c as s,d as c,f as l,g as u,h as d,i as f,l as p,m,n as h,o as g,p as _,r as v,s as y,t as b,u as x,v as S,w as C,x as w,y as T}from"./src-Cprpo919.js";export{b as LOADER_ENDPOINT,h as LoaderError,v as Redirect,f as RouterLink,a as RouterView,g as composeLoaders,w as default,y as defineLayout,s as enableLinkInterception,p as error,r as getHistoryMode,x as isActive,c as loader,l as navigate,_ as prefetch,m as prime,d as redirect,u as routeHash,i as routeParams,S as routePath,T as routeSearch,o as router,t as setHistoryMode,n as useRoute,e as wrapError,C as wrapLayout};
|
package/dist/rolldown.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{C as e,w as t}from"./src-
|
|
1
|
+
import{C as e,w as t}from"./src-Cprpo919.js";import{t as n}from"./plugin-OpojKenS.js";function r(e={}){return n.rolldown(e)}export{n as ilhaPages,r as pages,e as wrapError,t as wrapLayout};
|
package/dist/rspack.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { H as wrapLayout, V as wrapError, n as ErrorHandler, s as LayoutHandler, t as AppError, v as RouteSnapshot } from "./index-DZA_1KrG.js";
|
|
2
2
|
import { n as ilhaPages, t as IlhaPagesOptions } from "./plugin-rauddckN.js";
|
|
3
|
-
import * as _$unplugin from "unplugin";
|
|
4
3
|
|
|
5
4
|
//#region src/rspack.d.ts
|
|
6
5
|
/** Rspack plugin — use via `@ilha/router/rspack`. */
|
|
7
|
-
declare function pages(options?: IlhaPagesOptions):
|
|
6
|
+
declare function pages(options?: IlhaPagesOptions): RspackPluginInstance;
|
|
8
7
|
//#endregion
|
|
9
8
|
export { type AppError, type ErrorHandler, type IlhaPagesOptions, type LayoutHandler, type RouteSnapshot, ilhaPages, pages, wrapError, wrapLayout };
|
package/dist/rspack.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{C as e,w as t}from"./src-
|
|
1
|
+
import{C as e,w as t}from"./src-Cprpo919.js";import{t as n}from"./plugin-OpojKenS.js";function r(e={}){return n.rspack(e)}export{n as ilhaPages,r as pages,e as wrapError,t as wrapLayout};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import e,{ISLAND_MOUNT_INTERNAL as t,context as n,html as r,mount as i}from"ilha";import{addRoute as a,createRouter as o,findRoute as s}from"rou3";const c=typeof window<`u`&&typeof document<`u`,l={readLocation(){return c?{pathname:location.pathname,search:location.search,hash:location.hash}:{pathname:`/`,search:``,hash:``}},push(e){c&&history.pushState(null,``,e)},replace(e){c&&history.replaceState(null,``,e)},onChange(e){return c?(window.addEventListener(`popstate`,e),()=>window.removeEventListener(`popstate`,e)):()=>{}},toLinkHref(e){return e},extractLogicalPath(e){let t=e.getAttribute(`href`);return!t||e.protocol&&!/^(http:|https:)$/.test(e.protocol)||t.startsWith(`#`)||e.hostname&&(e.hostname!==location.hostname||e.protocol!==location.protocol)?null:e.pathname+e.search+e.hash}};function u(e){let t=e.startsWith(`#`)?e.slice(1):e,n=t===``?`/`:t.startsWith(`/`)?t:`/`+t,r=new URL(n,`http://_`);return{pathname:r.pathname,search:r.search,hash:r.hash}}const d={readLocation(){return c?u(location.hash):{pathname:`/`,search:``,hash:``}},push(e){c&&history.pushState(null,``,e.startsWith(`#`)?e:`#`+e)},replace(e){c&&history.replaceState(null,``,e.startsWith(`#`)?e:`#`+e)},onChange(e){return c?(window.addEventListener(`popstate`,e),window.addEventListener(`hashchange`,e),()=>{window.removeEventListener(`popstate`,e),window.removeEventListener(`hashchange`,e)}):()=>{}},toLinkHref(e){return e.startsWith(`#`)?e:`#`+e},extractLogicalPath(e){let t=e.getAttribute(`href`);if(!t||e.protocol&&!/^(http:|https:)$/.test(e.protocol))return null;if(t.startsWith(`#`)){let e=t.slice(1);return e===``||!e.startsWith(`/`)?null:e}if(/^https?:\/\//i.test(t))try{let e=new URL(t);if(e.origin!==location.origin||!e.hash||e.hash===`#`)return null;let n=e.hash.slice(1);return n.startsWith(`/`)?n:null}catch{return null}return t}};let f=`history`,p=l;function m(e){f=e,p=e===`hash`?d:l}function h(){return f}function g(){return p}const _=typeof window<`u`&&typeof document<`u`;function v(e){return e}var y=class{__ilhaRedirect=!0;to;status;constructor(e,t=302){this.to=e,this.status=t}},b=class{__ilhaLoaderError=!0;status;message;constructor(e,t){this.status=e,this.message=t}};function x(e,t=302){throw new y(e,t)}function S(e,t){throw new b(e,t)}function C(e){return e.length===0?async()=>({}):e.length===1?e[0]:async t=>{let n=await Promise.all(e.map(e=>e(t)));return Object.assign({},...n)}}const w=Symbol.for(`ilha.router.wrapLayout.leaf`),T=Symbol.for(`ilha.router.wrapLayout.handler`);function E(e){let t=e.match(/^<([a-zA-Z][\w-]*)\s[^>]*>([\s\S]*)<\/\1>\s*$/);return t?t[2]:e}function ee(e){let t=e.match(/^<([a-zA-Z][\w-]*)\s([^>]*)>/);return t?{tag:t[1],attrs:t[2]}:null}const te=/<(pre|script|style|textarea)\b/i;function ne(e,t,n){let r=RegExp(`<${n}\\b`,`gi`),i=RegExp(`</${n}>`,`gi`),a=1,o=t;for(;a>0&&o<e.length;){r.lastIndex=o,i.lastIndex=o;let t=r.exec(e),n=i.exec(e);if(!n)return null;if(t&&t.index<n.index)a+=1,o=t.index+t[0].length;else{if(--a,a===0)return n.index+n[0].length;o=n.index+n[0].length}}return o}function re(e,t){let n=t;for(;n<e.length;){if(e.startsWith(`<!--`,n)){let t=e.indexOf(`-->`,n);if(t===-1)return null;n=t+3;continue}let t=e.slice(n).match(te);if(t&&t.index!=null&&t.index>=0){let r=n+t.index,i=!1,a=n;for(;a<r;){let t=e.indexOf(`<!--`,a);if(t===-1||t>=r)break;let o=e.indexOf(`-->`,t);if(o===-1)return null;if(r<o+3){n=o+3,i=!0;break}a=o+3}if(i)continue;let o=e.indexOf(`<div`,n),s=e.indexOf(`</div>`,n);if(!(o!==-1&&o<r||s!==-1&&s<r)){let i=t[1].toLowerCase(),a=ne(e,r+t[0].length,i);if(a===null)return null;n=a;continue}}let r=e.indexOf(`<div`,n),i=e.indexOf(`</div>`,n);return i===-1&&r===-1?null:r===-1||i!==-1&&i<r?{kind:`close`,index:i}:{kind:`open`,index:r}}return null}function ie(e){let t=[];for(let n of e.matchAll(/<div\s[^>]*data-ilha-slot="k:page"[^>]*>/g)){let r=n.index+n[0].length,i=1,a=r;for(;i>0;){let n=re(e,a);if(!n)break;if(n.kind===`open`)i+=1,a=n.index+4;else{if(--i,i===0){t.push({openEnd:r,closeStart:n.index});break}a=n.index+6}}}return t}function D(e,t,n){let r=ie(e);if(r.length===0)return e;let i=n===`innermost`?r[r.length-1]:r[0];return e.slice(0,i.openEnd)+t+e.slice(i.closeStart)}function O(e,t){let n=e[T];if(!n)return e.toString(t);let r=e[w]??e;return n(Object.assign(r.key(`page`),{toString:()=>``})).toString(t)}async function ae(e,t,n,r){let i=E(await t.hydratable(n,r));return D(D(O(e,n),``,`innermost`),i,`innermost`)}function oe(e,n){let r=n[w]??n,i=r===n?null:n,a=e(Object.assign(n.key(`page`),{toString:n.toString.bind(n)}));a[w]=r,a[T]=e;function o(e){let t=[...e.querySelectorAll(`[data-ilha-slot="k:page"]`)].filter(t=>{let n=t.closest(`[data-ilha]`);return n===null||n===e});return t.length===0?e:t[t.length-1]}function s(e,t){if(t.hasAttribute(`data-ilha-state`))return;let n=e.getAttribute(`data-ilha-state`);if(n)try{let e=JSON.parse(n);delete e._skipOnMount,t.setAttribute(`data-ilha-state`,JSON.stringify(e))}catch{}}let c=a.mount.bind(a),l=a[t];function u(e){s(e,o(e)),e.removeAttribute(`data-ilha-state`)}return a.mount=(e,t)=>(u(e),c(e,t)),a[t]=(e,t)=>(u(e),typeof l==`function`?l(e,t):{unmount:c(e,t),updateProps:()=>{}}),a.hydratable=async(e,t)=>{if(!t?.name)throw Error(`wrapLayout: hydratable requires options.name`);let n=e??{},o=await r.hydratable(n,t),s=ee(o);if(!s)return o;let c=E(o);i&&(c=await ae(i,r,n,t));let l=D(D(O(a,n),``,`first`),c,`first`);return`<${s.tag} ${s.attrs}>${l}</${s.tag}>`},a}function se(n,r){let i=e.render(()=>{try{return r.toString()}catch(e){let t={path:P(),params:F(),search:I(),hash:L()};return n({message:e.message,status:e.status,stack:e.stack},t).toString()}});return i.mount=(e,t)=>{try{return r.mount(e,t)}catch(r){let i={path:P(),params:F(),search:I(),hash:L()},a=n({message:r.message,status:r.status,stack:r.stack},i);return e.innerHTML=a.toString(),a.mount(e,t)}},i[t]=(e,i)=>{try{let n=r[t];return typeof n==`function`?n(e,i):{unmount:r.mount(e,i),updateProps:()=>{}}}catch(t){let r={path:P(),params:F(),search:I(),hash:L()},a=n({message:t.message,status:t.status,stack:t.stack},r);return e.innerHTML=a.toString(),{unmount:a.mount(e,i),updateProps:()=>{}}}},i.hydratable=async(e,t)=>{if(!t?.name)throw Error(`wrapError: hydratable requires options.name`);return r.hydratable(e??{},t)},i}function ce(e){return e}function k(e){let t=new Map;for(let[n,r]of Object.entries(e))t.has(r)||t.set(r,n);return t}const A=`/__ilha/loader`,j=new Map;async function M(e,t){let n=j.get(e);if(n){j.delete(e);try{return await n}catch{}}let r=`${A}?path=${encodeURIComponent(e)}`;try{let e=await fetch(r,{signal:t,headers:{accept:`application/json`}});if(!e.ok){try{let t=await e.json();if(t&&typeof t==`object`&&`kind`in t)return t}catch{}return{kind:`error`,status:e.status,message:e.statusText}}return await e.json()}catch(e){if(e?.name===`AbortError`)throw e;return{kind:`error`,status:0,message:e?.message??`network error`}}}function N(e){if(!_||j.has(e))return;let t=e.split(`?`)[0]??``;if(!s(V,`GET`,t)?.data?.hasLoader)return;let n=M(e).catch(e=>({kind:`error`,status:0,message:e?.message??`prefetch failed`}));j.set(e,n)}async function le(e,t,n,r,i,a){if(!e)return t.innerHTML=`<div data-router-empty></div>`,()=>{};let o=!!s(V,`GET`,n.split(`?`)[0]??``)?.data?.hasLoader,c={},l=o?await M(n,r):{kind:`data`,data:{}};if(l.kind===`redirect`)return J(l.to,{replace:!0}),()=>{};if(l.kind===`error`){let e=String(l.message).replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`);return t.innerHTML=`<div data-router-view data-router-error="${l.status}">${e}</div>`,()=>{}}if(l.kind===`not-found`)return t.innerHTML=`<div data-router-empty></div>`,()=>{};if(c=l.data,!i)return console.warn(`[ilha-router] No registry provided for client-side navigation. Island will not be interactive.`),t.innerHTML=`<div data-router-view>${e.toString(c)}</div>`,()=>{};let u=a?.get(e)??Object.entries(i).find(([,t])=>t===e)?.[0];if(!u)return console.warn(`[ilha-router] Island not found in registry for client-side navigation.`),t.innerHTML=`<div data-router-view>${e.toString(c)}</div>`,()=>{};t.innerHTML=`<div data-router-view>${await e.hydratable(c,{name:u,as:`div`,snapshot:!0})}</div>`;let d=t.querySelector(`[data-ilha="${u}"]`);return d?e.mount(d):()=>{}}const P=n(`router.path`,``),F=n(`router.params`,{}),I=n(`router.search`,``),L=n(`router.hash`,``);function R(){return{path:P,params:F,search:I,hash:L}}const z=n(`router.active`,null);let B=[],V=o(),H=new Map,U=new Map;function W(e){let t={};if(e)for(let[n,r]of Object.entries(e))t[n]=decodeURIComponent(r);return t}function G(e){let t=typeof e==`string`?new URL(e,`http://localhost`):e,n=s(V,`GET`,t.pathname);P(t.pathname),F(W(n?.params)),I(t.search),L(t.hash),z(n?.data?.island??null)}function K(){let e=g().readLocation(),t=s(V,`GET`,e.pathname);P(e.pathname),F(W(t?.params)),I(e.search),L(e.hash),z(t?.data?.island??null)}function q(){_&&K()}function J(e,t={}){if(!_)return;let n=g(),r=n.readLocation();e!==r.pathname+r.search+r.hash&&(t.replace?n.replace(e):n.push(e),K())}function Y(e=document,t={}){if(!_)return()=>{};let n=t.prefetch!==!1;function r(e,t){let n=e.getAttribute(`target`)===`_blank`,r=!!t&&(t.ctrlKey||t.metaKey||t.shiftKey),i=e.hasAttribute(`data-no-intercept`);return n||r||i?null:g().extractLogicalPath(e)}let i=e=>{if(e.defaultPrevented)return;let t=e.target.closest(`a`);if(!t)return;let n=r(t,e);n!==null&&(e.preventDefault(),J(n))},a=e=>{let t=e.target.closest(`a`);if(!t)return;let n=t.getAttribute(`data-prefetch`);if(n===null||n===`false`)return;let i=r(t);i!==null&&N(i.split(`#`)[0]??i)};return e.addEventListener(`click`,i),n&&e.addEventListener(`mouseover`,a,{passive:!0}),()=>{e.removeEventListener(`click`,i),n&&e.removeEventListener(`mouseover`,a)}}const X=e.render(()=>{let e=z();return e?`<div data-router-view>${e.toString()}</div>`:`<div data-router-empty></div>`}),Z=e.state(`href`,``).state(`label`,``).on(`[data-link]@click`,({state:e,event:t})=>{t.preventDefault(),J(e.href())}).on(`[data-link]@mouseenter`,({state:e})=>{let t=e.href();if(t){if(/^https?:\/\//i.test(t))try{let e=new URL(t);if(e.origin!==location.origin)return;N(e.pathname+e.search);return}catch{return}N(t)}}).render(({state:e})=>r`<a data-link data-prefetch href="${()=>g().toLinkHref(e.href())}"
|
|
2
|
+
>${e.label}</a
|
|
3
|
+
>`);function Q(e){let t=s(V,`GET`,P());return t?H.get(t.data.island)===e:!1}function ue(e){return typeof e==`string`?new URL(e,`http://localhost`):e}function de(e){try{return new Request(e.toString())}catch{return{url:e.toString(),headers:new Headers}}}async function fe(e,t,n,r,i){try{return{kind:`data`,data:await e({params:n,request:r,url:t,signal:i})??{}}}catch(e){return e instanceof y?{kind:`redirect`,to:e.to,status:e.status}:e instanceof b?{kind:`error`,status:e.status,message:e.message}:{kind:`error`,status:e?.status??500,message:e?.message??`Loader failed`}}}function $(t={}){let n=t.mode??`spa`,r=t.interceptLinks!==!1;B=[],V=o(),H=new Map,U=new Map;let c=null,l=null,u={route(e,t,n){let r=!!n,i={island:t,loader:n,hasLoader:r};return B.push({pattern:e,island:t,loader:n,hasLoader:r}),a(V,`GET`,e,i),U.set(e,i),H.has(t)||H.set(t,e),u},attachLoader(e,t){let n=U.get(e);if(!n)return console.warn(`[ilha-router] attachLoader("${e}", …): pattern was never registered via .route(). The loader will be ignored.`),u;n.loader=t,n.hasLoader=!0;let r=B.find(t=>t.pattern===e);return r&&(r.loader=t,r.hasLoader=!0),u},markLoader(e){let t=U.get(e);if(!t)return console.warn(`[ilha-router] markLoader("${e}"): pattern was never registered via .route(). The loader marker will be ignored.`),u;t.hasLoader=!0;let n=B.find(t=>t.pattern===e);return n&&(n.hasLoader=!0),u},routes(){return B.map(e=>({...e}))},prime:q,hydrateStatic(e,t={}){if(!_)return()=>{};let n=t.root??document.body;q();let{unmount:r}=i(e,{root:n});return r},mount(t,{hydrate:i=!1,registry:a,interceptLinks:o}={}){if(!_)return console.warn(`[ilha-router] mount() called in a non-browser environment`),()=>{};let u=typeof t==`string`?document.querySelector(t):t;if(!u)return console.warn(`[ilha-router] No element found for selector "${t}"`),()=>{};if(K(),n===`static`)return console.warn(`[ilha-router] router.mount() called in static mode. Use router.hydrateStatic(registry) instead.`),()=>{};c=g().onChange(()=>K()),l=o??r?Y(document):null;let d=null,f=null;if(i){h()===`hash`&&console.warn("[ilha-router] mount({ hydrate: true }) was called in hash mode. SSR + hydration assumes the server can render the active route, but in hash mode the server only ever sees the document URL. Use plain SPA mode (`mount(target)` without `hydrate: true`) for hash-mode apps.");let t=u.querySelector(`[data-router-view]`)??u,n=z(),r=a?k(a):void 0,i=0,o=e.render(()=>{let e=z();if(e!==n){let o=++i;f?.abort(),f=new AbortController;let s=f.signal;queueMicrotask(async()=>{if(o===i){d?.();try{let n=g().readLocation();d=await le(e,t,n.pathname+n.search,s,a,r)}catch(e){if(e?.name===`AbortError`)return;throw e}n=e}})}return``}),s=document.createElement(`div`);s.style.display=`none`,u.appendChild(s);let p=o.mount(s);return()=>{++i,f?.abort(),p(),s.remove(),d?.(),c?.(),l?.(),c=null,l=null}}let p=null,m=null,v=0;d=X.mount(u);async function y(e,t){if(p?.(),p=null,m=e,!e)return;let n=u?.querySelector(`[data-router-view]`);if(!n)return;let r=g().readLocation(),i=s(V,`GET`,r.pathname)?.data?.hasLoader?await M(r.pathname+r.search,t):{kind:`data`,data:{}};if(t.aborted)return;if(i.kind===`redirect`){J(i.to,{replace:!0});return}let a=i.kind===`data`?i.data:{};n.innerHTML=e.toString(a),p=e.mount(n,a)}f=new AbortController,y(z(),f.signal);let b=e.render(()=>{let e=z();if(e!==m){let t=++v;f?.abort(),f=new AbortController;let n=f.signal;queueMicrotask(()=>{t===v&&y(e,n)})}return``}),x=document.createElement(`div`);x.style.display=`none`,u.appendChild(x);let S=b.mount(x);return()=>{++v,f?.abort(),p?.(),S(),x.remove(),d?.(),c?.(),l?.(),c=null,l=null}},render(e){return G(e),X.toString()},async renderHydratable(e,t,n={},r){let i=await this.renderResponse(e,t,n,r);return i.kind===`html`||i.kind===`error`?i.html:`<meta http-equiv="refresh" content="0; url=${i.to}">`},async renderResponse(e,t,n={},r){let i=ue(e);G(i);let a=s(V,`GET`,i.pathname),o=a?.data?.island??null;if(!o)return{kind:`html`,html:`<div data-router-empty></div>`,status:404};let c={};if(a?.data?.loader){let e=r??de(i),t=new AbortController,n=await fe(a.data.loader,i,F(),e,t.signal);if(n.kind===`redirect`)return{kind:`redirect`,to:n.to,status:n.status};if(n.kind===`error`){let e=String(n.message).replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`),t=`<div data-router-view data-router-error="${n.status}">${e}</div>`;return{kind:`error`,status:n.status,message:n.message,html:t}}c=n.data}let l=k(t).get(o);return l?{kind:`html`,html:`<div data-router-view>${await o.hydratable(c,{name:l,as:`div`,snapshot:!0,...n})}</div>`}:(console.warn(`[ilha-router] renderHydratable: active island for "${P()}" is not in the registry. Falling back to plain SSR — the island will not be interactive on the client.`),{kind:`html`,html:`<div data-router-view>${o.toString(c)}</div>`})},async runLoader(e,t){let n=ue(e),r=s(V,`GET`,n.pathname);if(!r?.data?.island)return{kind:`not-found`};if(!r.data.loader)return{kind:`data`,data:{}};let i=W(r.params),a=t??de(n),o=new AbortController;return fe(r.data.loader,n,i,a,o.signal)},hydrate(e,t={}){if(!_)return console.warn(`[ilha-router] hydrate() called in a non-browser environment`),()=>{};let n=t.root??document.body,r=t.target??n;q();let{unmount:a}=i(e,{root:n}),o=this.mount(r,{hydrate:!0,registry:e,interceptLinks:t.interceptLinks});return()=>{a(),o()}}};return u}var pe={router:$,navigate:J,useRoute:R,isActive:Q,enableLinkInterception:Y,prime:q,prefetch:N,RouterView:X,RouterLink:Z,loader:v,redirect:x,error:S,composeLoaders:C};export{se as C,m as E,R as S,h as T,F as _,X as a,$ as b,Y as c,v as d,J as f,L as g,x as h,Z as i,S as l,q as m,b as n,C as o,N as p,y as r,ce as s,A as t,Q as u,P as v,oe as w,pe as x,I as y};
|
package/dist/vite.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{C as e,w as t}from"./src-
|
|
1
|
+
import{C as e,w as t}from"./src-Cprpo919.js";import{t as n}from"./plugin-OpojKenS.js";function r(e={}){return n.vite(e)}export{n as ilhaPages,r as pages,e as wrapError,t as wrapLayout};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ilha/router",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.4",
|
|
4
4
|
"description": "A tiny SPA router for Ilha",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"frontend",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"test": "bun test"
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"ilha": "0.8.
|
|
63
|
+
"ilha": "0.8.1",
|
|
64
64
|
"rou3": "0.8.1",
|
|
65
65
|
"unplugin": "3.0.0"
|
|
66
66
|
},
|
package/dist/src-ObXICXKp.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import e,{ISLAND_MOUNT_INTERNAL as t,context as n,html as r,mount as i}from"ilha";import{addRoute as a,createRouter as o,findRoute as s}from"rou3";const c=typeof window<`u`&&typeof document<`u`,l={readLocation(){return c?{pathname:location.pathname,search:location.search,hash:location.hash}:{pathname:`/`,search:``,hash:``}},push(e){c&&history.pushState(null,``,e)},replace(e){c&&history.replaceState(null,``,e)},onChange(e){return c?(window.addEventListener(`popstate`,e),()=>window.removeEventListener(`popstate`,e)):()=>{}},toLinkHref(e){return e},extractLogicalPath(e){let t=e.getAttribute(`href`);return!t||e.protocol&&!/^(http:|https:)$/.test(e.protocol)||t.startsWith(`#`)||e.hostname&&(e.hostname!==location.hostname||e.protocol!==location.protocol)?null:e.pathname+e.search+e.hash}};function u(e){let t=e.startsWith(`#`)?e.slice(1):e,n=t===``?`/`:t.startsWith(`/`)?t:`/`+t,r=new URL(n,`http://_`);return{pathname:r.pathname,search:r.search,hash:r.hash}}const d={readLocation(){return c?u(location.hash):{pathname:`/`,search:``,hash:``}},push(e){c&&history.pushState(null,``,e.startsWith(`#`)?e:`#`+e)},replace(e){c&&history.replaceState(null,``,e.startsWith(`#`)?e:`#`+e)},onChange(e){return c?(window.addEventListener(`popstate`,e),window.addEventListener(`hashchange`,e),()=>{window.removeEventListener(`popstate`,e),window.removeEventListener(`hashchange`,e)}):()=>{}},toLinkHref(e){return e.startsWith(`#`)?e:`#`+e},extractLogicalPath(e){let t=e.getAttribute(`href`);if(!t||e.protocol&&!/^(http:|https:)$/.test(e.protocol))return null;if(t.startsWith(`#`)){let e=t.slice(1);return e===``||!e.startsWith(`/`)?null:e}if(/^https?:\/\//i.test(t))try{let e=new URL(t);if(e.origin!==location.origin||!e.hash||e.hash===`#`)return null;let n=e.hash.slice(1);return n.startsWith(`/`)?n:null}catch{return null}return t}};let f=`history`,p=l;function m(e){f=e,p=e===`hash`?d:l}function h(){return f}function g(){return p}const _=typeof window<`u`&&typeof document<`u`;function v(e){return e}var y=class{__ilhaRedirect=!0;to;status;constructor(e,t=302){this.to=e,this.status=t}},b=class{__ilhaLoaderError=!0;status;message;constructor(e,t){this.status=e,this.message=t}};function x(e,t=302){throw new y(e,t)}function S(e,t){throw new b(e,t)}function C(e){return e.length===0?async()=>({}):e.length===1?e[0]:async t=>{let n=await Promise.all(e.map(e=>e(t)));return Object.assign({},...n)}}const w=Symbol.for(`ilha.router.wrapLayout.leaf`);function T(e){let t=e.match(/^<([a-zA-Z][\w-]*)\s[^>]*>([\s\S]*)<\/\1>\s*$/);return t?t[2]:e}function ee(e){let t=e.match(/^<([a-zA-Z][\w-]*)\s([^>]*)>/);return t?{tag:t[1],attrs:t[2]}:null}function te(e){let t=[];for(let n of e.matchAll(/<div\s[^>]*data-ilha-slot="k:page"[^>]*>/g)){let r=n.index+n[0].length,i=1,a=r;for(;a<e.length&&i>0;){let n=e.indexOf(`<div`,a),o=e.indexOf(`</div>`,a);if(o===-1)break;if(n!==-1&&n<o)i+=1,a=n+4;else{if(--i,i===0){t.push({openEnd:r,closeStart:o});break}a=o+6}}}return t}function E(e,t,n){let r=te(e);if(r.length===0)return e;let i=n===`innermost`?r[r.length-1]:r[0];return e.slice(0,i.openEnd)+t+e.slice(i.closeStart)}async function ne(e,t,n,r){let i=T(await t.hydratable(n,r));return E(e.toString(n),i,`innermost`)}function re(e,n){let r=n[w]??n,i=r===n?null:n,a=e(Object.assign(n.key(`page`),{toString:n.toString.bind(n)}));a[w]=r;function o(e){let t=[...e.querySelectorAll(`[data-ilha-slot="k:page"]`)].filter(t=>{let n=t.closest(`[data-ilha]`);return n===null||n===e});return t.length===0?e:t[t.length-1]}function s(e,t){if(t.hasAttribute(`data-ilha-state`))return;let n=e.getAttribute(`data-ilha-state`);if(n)try{let e=JSON.parse(n);delete e._skipOnMount,t.setAttribute(`data-ilha-state`,JSON.stringify(e))}catch{}}let c=a.mount.bind(a),l=a[t];function u(e){s(e,o(e)),e.removeAttribute(`data-ilha-state`)}return a.mount=(e,t)=>(u(e),c(e,t)),a[t]=(e,t)=>(u(e),typeof l==`function`?l(e,t):{unmount:c(e,t),updateProps:()=>{}}),a.hydratable=async(e,t)=>{if(!t?.name)throw Error(`wrapLayout: hydratable requires options.name`);let n=e??{},o=await r.hydratable(n,t),s=ee(o);if(!s)return o;let c=T(o),l=i?await ne(i,r,n,t):c,u=E(a.toString(n),l,`first`);return`<${s.tag} ${s.attrs}>${u}</${s.tag}>`},a}function ie(n,r){let i=e.render(()=>{try{return r.toString()}catch(e){let t={path:M(),params:N(),search:P(),hash:F()};return n({message:e.message,status:e.status,stack:e.stack},t).toString()}});return i.mount=(e,t)=>{try{return r.mount(e,t)}catch(r){let i={path:M(),params:N(),search:P(),hash:F()},a=n({message:r.message,status:r.status,stack:r.stack},i);return e.innerHTML=a.toString(),a.mount(e,t)}},i[t]=(e,i)=>{try{let n=r[t];return typeof n==`function`?n(e,i):{unmount:r.mount(e,i),updateProps:()=>{}}}catch(t){let r={path:M(),params:N(),search:P(),hash:F()},a=n({message:t.message,status:t.status,stack:t.stack},r);return e.innerHTML=a.toString(),{unmount:a.mount(e,i),updateProps:()=>{}}}},i.hydratable=async(e,t)=>{if(!t?.name)throw Error(`wrapError: hydratable requires options.name`);return r.hydratable(e??{},t)},i}function ae(e){return e}function D(e){let t=new Map;for(let[n,r]of Object.entries(e))t.has(r)||t.set(r,n);return t}const O=`/__ilha/loader`,k=new Map;async function A(e,t){let n=k.get(e);if(n){k.delete(e);try{return await n}catch{}}let r=`${O}?path=${encodeURIComponent(e)}`;try{let e=await fetch(r,{signal:t,headers:{accept:`application/json`}});if(!e.ok){try{let t=await e.json();if(t&&typeof t==`object`&&`kind`in t)return t}catch{}return{kind:`error`,status:e.status,message:e.statusText}}return await e.json()}catch(e){if(e?.name===`AbortError`)throw e;return{kind:`error`,status:0,message:e?.message??`network error`}}}function j(e){if(!_||k.has(e))return;let t=e.split(`?`)[0]??``;if(!s(z,`GET`,t)?.data?.hasLoader)return;let n=A(e).catch(e=>({kind:`error`,status:0,message:e?.message??`prefetch failed`}));k.set(e,n)}async function oe(e,t,n,r,i,a){if(!e)return t.innerHTML=`<div data-router-empty></div>`,()=>{};let o=!!s(z,`GET`,n.split(`?`)[0]??``)?.data?.hasLoader,c={},l=o?await A(n,r):{kind:`data`,data:{}};if(l.kind===`redirect`)return K(l.to,{replace:!0}),()=>{};if(l.kind===`error`){let e=String(l.message).replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`);return t.innerHTML=`<div data-router-view data-router-error="${l.status}">${e}</div>`,()=>{}}if(l.kind===`not-found`)return t.innerHTML=`<div data-router-empty></div>`,()=>{};if(c=l.data,!i)return console.warn(`[ilha-router] No registry provided for client-side navigation. Island will not be interactive.`),t.innerHTML=`<div data-router-view>${e.toString(c)}</div>`,()=>{};let u=a?.get(e)??Object.entries(i).find(([,t])=>t===e)?.[0];if(!u)return console.warn(`[ilha-router] Island not found in registry for client-side navigation.`),t.innerHTML=`<div data-router-view>${e.toString(c)}</div>`,()=>{};t.innerHTML=`<div data-router-view>${await e.hydratable(c,{name:u,as:`div`,snapshot:!0})}</div>`;let d=t.querySelector(`[data-ilha="${u}"]`);return d?e.mount(d):()=>{}}const M=n(`router.path`,``),N=n(`router.params`,{}),P=n(`router.search`,``),F=n(`router.hash`,``);function I(){return{path:M,params:N,search:P,hash:F}}const L=n(`router.active`,null);let R=[],z=o(),B=new Map,V=new Map;function H(e){let t={};if(e)for(let[n,r]of Object.entries(e))t[n]=decodeURIComponent(r);return t}function U(e){let t=typeof e==`string`?new URL(e,`http://localhost`):e,n=s(z,`GET`,t.pathname);M(t.pathname),N(H(n?.params)),P(t.search),F(t.hash),L(n?.data?.island??null)}function W(){let e=g().readLocation(),t=s(z,`GET`,e.pathname);M(e.pathname),N(H(t?.params)),P(e.search),F(e.hash),L(t?.data?.island??null)}function G(){_&&W()}function K(e,t={}){if(!_)return;let n=g(),r=n.readLocation();e!==r.pathname+r.search+r.hash&&(t.replace?n.replace(e):n.push(e),W())}function q(e=document,t={}){if(!_)return()=>{};let n=t.prefetch!==!1;function r(e,t){let n=e.getAttribute(`target`)===`_blank`,r=!!t&&(t.ctrlKey||t.metaKey||t.shiftKey),i=e.hasAttribute(`data-no-intercept`);return n||r||i?null:g().extractLogicalPath(e)}let i=e=>{if(e.defaultPrevented)return;let t=e.target.closest(`a`);if(!t)return;let n=r(t,e);n!==null&&(e.preventDefault(),K(n))},a=e=>{let t=e.target.closest(`a`);if(!t)return;let n=t.getAttribute(`data-prefetch`);if(n===null||n===`false`)return;let i=r(t);i!==null&&j(i.split(`#`)[0]??i)};return e.addEventListener(`click`,i),n&&e.addEventListener(`mouseover`,a,{passive:!0}),()=>{e.removeEventListener(`click`,i),n&&e.removeEventListener(`mouseover`,a)}}const J=e.render(()=>{let e=L();return e?`<div data-router-view>${e.toString()}</div>`:`<div data-router-empty></div>`}),Y=e.state(`href`,``).state(`label`,``).on(`[data-link]@click`,({state:e,event:t})=>{t.preventDefault(),K(e.href())}).on(`[data-link]@mouseenter`,({state:e})=>{let t=e.href();if(t){if(/^https?:\/\//i.test(t))try{let e=new URL(t);if(e.origin!==location.origin)return;j(e.pathname+e.search);return}catch{return}j(t)}}).render(({state:e})=>r`<a data-link data-prefetch href="${()=>g().toLinkHref(e.href())}"
|
|
2
|
-
>${e.label}</a
|
|
3
|
-
>`);function X(e){let t=s(z,`GET`,M());return t?B.get(t.data.island)===e:!1}function Z(e){return typeof e==`string`?new URL(e,`http://localhost`):e}function Q(e){try{return new Request(e.toString())}catch{return{url:e.toString(),headers:new Headers}}}async function $(e,t,n,r,i){try{return{kind:`data`,data:await e({params:n,request:r,url:t,signal:i})??{}}}catch(e){return e instanceof y?{kind:`redirect`,to:e.to,status:e.status}:e instanceof b?{kind:`error`,status:e.status,message:e.message}:{kind:`error`,status:e?.status??500,message:e?.message??`Loader failed`}}}function se(t={}){let n=t.mode??`spa`,r=t.interceptLinks!==!1;R=[],z=o(),B=new Map,V=new Map;let c=null,l=null,u={route(e,t,n){let r=!!n,i={island:t,loader:n,hasLoader:r};return R.push({pattern:e,island:t,loader:n,hasLoader:r}),a(z,`GET`,e,i),V.set(e,i),B.has(t)||B.set(t,e),u},attachLoader(e,t){let n=V.get(e);if(!n)return console.warn(`[ilha-router] attachLoader("${e}", …): pattern was never registered via .route(). The loader will be ignored.`),u;n.loader=t,n.hasLoader=!0;let r=R.find(t=>t.pattern===e);return r&&(r.loader=t,r.hasLoader=!0),u},markLoader(e){let t=V.get(e);if(!t)return console.warn(`[ilha-router] markLoader("${e}"): pattern was never registered via .route(). The loader marker will be ignored.`),u;t.hasLoader=!0;let n=R.find(t=>t.pattern===e);return n&&(n.hasLoader=!0),u},routes(){return R.map(e=>({...e}))},prime:G,hydrateStatic(e,t={}){if(!_)return()=>{};let n=t.root??document.body;G();let{unmount:r}=i(e,{root:n});return r},mount(t,{hydrate:i=!1,registry:a,interceptLinks:o}={}){if(!_)return console.warn(`[ilha-router] mount() called in a non-browser environment`),()=>{};let u=typeof t==`string`?document.querySelector(t):t;if(!u)return console.warn(`[ilha-router] No element found for selector "${t}"`),()=>{};if(W(),n===`static`)return console.warn(`[ilha-router] router.mount() called in static mode. Use router.hydrateStatic(registry) instead.`),()=>{};c=g().onChange(()=>W()),l=o??r?q(document):null;let d=null,f=null;if(i){h()===`hash`&&console.warn("[ilha-router] mount({ hydrate: true }) was called in hash mode. SSR + hydration assumes the server can render the active route, but in hash mode the server only ever sees the document URL. Use plain SPA mode (`mount(target)` without `hydrate: true`) for hash-mode apps.");let t=u.querySelector(`[data-router-view]`)??u,n=L(),r=a?D(a):void 0,i=0,o=e.render(()=>{let e=L();if(e!==n){let o=++i;f?.abort(),f=new AbortController;let s=f.signal;queueMicrotask(async()=>{if(o===i){d?.();try{let n=g().readLocation();d=await oe(e,t,n.pathname+n.search,s,a,r)}catch(e){if(e?.name===`AbortError`)return;throw e}n=e}})}return``}),s=document.createElement(`div`);s.style.display=`none`,u.appendChild(s);let p=o.mount(s);return()=>{++i,f?.abort(),p(),s.remove(),d?.(),c?.(),l?.(),c=null,l=null}}let p=null,m=null,v=0;d=J.mount(u);async function y(e,t){if(p?.(),p=null,m=e,!e)return;let n=u?.querySelector(`[data-router-view]`);if(!n)return;let r=g().readLocation(),i=s(z,`GET`,r.pathname)?.data?.hasLoader?await A(r.pathname+r.search,t):{kind:`data`,data:{}};if(t.aborted)return;if(i.kind===`redirect`){K(i.to,{replace:!0});return}let a=i.kind===`data`?i.data:{};n.innerHTML=e.toString(a),p=e.mount(n,a)}f=new AbortController,y(L(),f.signal);let b=e.render(()=>{let e=L();if(e!==m){let t=++v;f?.abort(),f=new AbortController;let n=f.signal;queueMicrotask(()=>{t===v&&y(e,n)})}return``}),x=document.createElement(`div`);x.style.display=`none`,u.appendChild(x);let S=b.mount(x);return()=>{++v,f?.abort(),p?.(),S(),x.remove(),d?.(),c?.(),l?.(),c=null,l=null}},render(e){return U(e),J.toString()},async renderHydratable(e,t,n={},r){let i=await this.renderResponse(e,t,n,r);return i.kind===`html`||i.kind===`error`?i.html:`<meta http-equiv="refresh" content="0; url=${i.to}">`},async renderResponse(e,t,n={},r){let i=Z(e);U(i);let a=s(z,`GET`,i.pathname),o=a?.data?.island??null;if(!o)return{kind:`html`,html:`<div data-router-empty></div>`,status:404};let c={};if(a?.data?.loader){let e=r??Q(i),t=new AbortController,n=await $(a.data.loader,i,N(),e,t.signal);if(n.kind===`redirect`)return{kind:`redirect`,to:n.to,status:n.status};if(n.kind===`error`){let e=String(n.message).replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`),t=`<div data-router-view data-router-error="${n.status}">${e}</div>`;return{kind:`error`,status:n.status,message:n.message,html:t}}c=n.data}let l=D(t).get(o);return l?{kind:`html`,html:`<div data-router-view>${await o.hydratable(c,{name:l,as:`div`,snapshot:!0,...n})}</div>`}:(console.warn(`[ilha-router] renderHydratable: active island for "${M()}" is not in the registry. Falling back to plain SSR — the island will not be interactive on the client.`),{kind:`html`,html:`<div data-router-view>${o.toString(c)}</div>`})},async runLoader(e,t){let n=Z(e),r=s(z,`GET`,n.pathname);if(!r?.data?.island)return{kind:`not-found`};if(!r.data.loader)return{kind:`data`,data:{}};let i=H(r.params),a=t??Q(n),o=new AbortController;return $(r.data.loader,n,i,a,o.signal)},hydrate(e,t={}){if(!_)return console.warn(`[ilha-router] hydrate() called in a non-browser environment`),()=>{};let n=t.root??document.body,r=t.target??n;G();let{unmount:a}=i(e,{root:n}),o=this.mount(r,{hydrate:!0,registry:e,interceptLinks:t.interceptLinks});return()=>{a(),o()}}};return u}var ce={router:se,navigate:K,useRoute:I,isActive:X,enableLinkInterception:q,prime:G,prefetch:j,RouterView:J,RouterLink:Y,loader:v,redirect:x,error:S,composeLoaders:C};export{ie as C,m as E,I as S,h as T,N as _,J as a,se as b,q as c,v as d,K as f,F as g,x as h,Y as i,S as l,G as m,b as n,C as o,j as p,y as r,ae as s,O as t,X as u,M as v,re as w,ce as x,P as y};
|