-
Notifications
You must be signed in to change notification settings - Fork 57
Expand file tree
/
Copy pathrouter.js
More file actions
103 lines (88 loc) · 2.66 KB
/
router.js
File metadata and controls
103 lines (88 loc) · 2.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import extractLocation from '../shared/extractLocation'
import client from './client'
import environment from './environment'
import page from './page'
import { updateParams } from './params'
import segments from './segments'
import windowEvent from './windowEvent'
import worker from './worker'
import deserialize from '../shared/deserialize'
let redirectTimer = null
class Router {
event = 'nullstack.router';
previous = null
_changed = false
_segments = segments
constructor() {
const { hash, url } = extractLocation(window.location.pathname + window.location.search)
this._url = url
this._hash = hash
}
async _popState() {
const { urlWithHash } = extractLocation(window.location.pathname + window.location.search)
await this._update(urlWithHash, false)
}
async _update(target, push) {
const { url, path, hash, urlWithHash } = extractLocation(target)
if (url === this._url && this._hash === hash) return
this.previous = this.url
clearTimeout(redirectTimer)
redirectTimer = setTimeout(async () => {
page.status = 200
if (environment.mode === 'ssg') {
worker.fetching = true
const api = '/index.json'
const endpoint = path === '/' ? api : path + api
try {
const response = await fetch(endpoint)
const meta = await response.text()
const payload = deserialize(meta)
client.memory = payload.instances
for (const key in payload.page) {
page[key] = payload.page[key]
}
worker.responsive = true
} catch (error) {
worker.responsive = false
}
worker.fetching = false
}
if (push) {
history.pushState({}, document.title, urlWithHash)
}
this._url = url
this._hash = hash
this._changed = true
updateParams(url)
client.update()
windowEvent('router')
}, 0)
}
async _redirect(target) {
if (/^(\w+:|\/\/)([^.]+.)/.test(target)) {
return (window.location.href = target)
}
const absoluteUrl = new URL(target, document.baseURI)
await this._update(absoluteUrl.pathname + absoluteUrl.search + absoluteUrl.hash, true)
window.scroll({ top: 0, left: 0, behavior: 'instant' })
}
get url() {
return this._url
}
set url(target) {
this._redirect(target)
}
get path() {
return extractLocation(this._url).path
}
set path(target) {
this._redirect(target + window.location.search)
}
get base() {
if (this._base) return this._base
this._base = new URL(document.querySelector('[rel="canonical"]').href).origin
return this._base
}
}
const router = new Router()
export default router