@shaun/alpinejs-router
Version:
A lightweight client-side router for Alpine.js that adds declarative routes, link navigation, dynamic params, external templates, and hash or HTML5 history modes without turning your app into a larger framework.
100 lines (79 loc) • 2.08 kB
JavaScript
export class RouterURL {
#url
#path
constructor(url, opts = {}) {
this.#url = new URL(url)
this.mode = opts.mode ?? 'web'
this.base = opts.base ?? ''
}
set url (val) {
this.#url = new URL(val)
this.#path = undefined
}
get url () {
return this.#url.href
}
get path () {
this.#path ??= this.#resolvePath()
return this.#path
}
#hashContent () {
return this.#url.hash.slice(1).split('#').shift()
}
#resolvePath () {
if (this.mode === 'hash' && this.#url.hash) {
return this.#hashContent().split('?').shift() || '/'
}
const pathname = this.#url.pathname
const base = this.base && this.base !== '/'
? this.base.replace(/\/$/, '')
: ''
if (!base) {
return pathname
}
if (pathname === base) {
return '/'
}
if (pathname.startsWith(base + '/')) {
return pathname.slice(base.length) || '/'
}
return pathname
}
get query () {
const search = this.mode === 'hash' && this.#url.hash
? this.#hashContent().split('?').slice(1).join('?')
: this.#url.search
return Object.fromEntries(new URLSearchParams(search))
}
resolve (path, params, replace = false) {
const l = this.#url.origin + this.base + (this.mode === 'hash' ? '#' : '') + path
const r = replace
? new URLSearchParams(params).toString()
: new URLSearchParams({ ...this.query, ...params }).toString()
this.url = l + (r ? '?' + r : '')
return this
}
static resolveTemplatePath (pathname, tpl) {
if (!tpl) return tpl
if (tpl.startsWith('/')) {
return tpl
}
const dir = pathname.slice(0, pathname.lastIndexOf('/'))
if (tpl.startsWith('./')) {
return dir + tpl.slice(1)
}
if (tpl.startsWith('../')) {
const re = /\.\.\//g
let i = tpl.match(re).length
let arr = dir.split('/')
while (i--) {
arr.pop()
}
if (arr.length === 0) {
arr = ['']
}
return [...arr, tpl.replace(re, '')].join('/')
}
return tpl
}
}