92 lines
2.5 KiB
TypeScript
92 lines
2.5 KiB
TypeScript
export interface Route {
|
|
type: 'blog' | 'post' | 'browser-services' | 'browser-collections' | 'browser-record' | 'new'
|
|
handle?: string
|
|
collection?: string
|
|
rkey?: string
|
|
service?: string
|
|
}
|
|
|
|
export function parseRoute(pathname: string): Route {
|
|
const parts = pathname.split('/').filter(Boolean)
|
|
|
|
// / - Blog top
|
|
if (parts.length === 0) {
|
|
return { type: 'blog' }
|
|
}
|
|
|
|
// /new - New post form
|
|
if (parts[0] === 'new') {
|
|
return { type: 'new' }
|
|
}
|
|
|
|
// /app - SPA entry point (same as blog)
|
|
if (parts[0] === 'app') {
|
|
return { type: 'blog' }
|
|
}
|
|
|
|
// /post/${rkey} - Post detail
|
|
if (parts[0] === 'post' && parts[1]) {
|
|
return { type: 'post', rkey: parts[1] }
|
|
}
|
|
|
|
// /at/${handle} - Browser services
|
|
// /at/${handle}/${service-or-collection} - Browser collections or records
|
|
// /at/${handle}/${collection}/${rkey} - Browser record detail
|
|
if (parts[0] === 'at' && parts[1]) {
|
|
const handle = parts[1]
|
|
|
|
if (!parts[2]) {
|
|
// /at/${handle}
|
|
return { type: 'browser-services', handle }
|
|
}
|
|
|
|
if (!parts[3]) {
|
|
// /at/${handle}/${service-or-collection}
|
|
// If it looks like a domain (2 parts), treat as service
|
|
// Otherwise treat as collection NSID (3+ parts)
|
|
const segment = parts[2]
|
|
if (segment.split('.').length <= 2) {
|
|
// Likely a service domain like "bsky.app"
|
|
return { type: 'browser-collections', handle, service: segment }
|
|
} else {
|
|
// Likely a collection NSID like "app.bsky.feed.post"
|
|
// Show record list for this collection
|
|
return { type: 'browser-record', handle, collection: segment }
|
|
}
|
|
}
|
|
|
|
// /at/${handle}/${collection}/${rkey}
|
|
return { type: 'browser-record', handle, collection: parts[2], rkey: parts[3] }
|
|
}
|
|
|
|
// Fallback to blog
|
|
return { type: 'blog' }
|
|
}
|
|
|
|
export function buildPath(route: Route): string {
|
|
switch (route.type) {
|
|
case 'blog':
|
|
return '/'
|
|
case 'new':
|
|
return '/new'
|
|
case 'post':
|
|
return `/post/${route.rkey}`
|
|
case 'browser-services':
|
|
return `/at/${route.handle}`
|
|
case 'browser-collections':
|
|
return `/at/${route.handle}/${route.service}`
|
|
case 'browser-record':
|
|
if (route.rkey) {
|
|
return `/at/${route.handle}/${route.collection}/${route.rkey}`
|
|
}
|
|
return `/at/${route.handle}/${route.collection}`
|
|
default:
|
|
return '/'
|
|
}
|
|
}
|
|
|
|
export function navigate(path: string): void {
|
|
window.history.pushState({}, '', path)
|
|
window.dispatchEvent(new PopStateEvent('popstate'))
|
|
}
|