1
Fork 0

initial version of stuff

This commit is contained in:
Conduitry 2017-07-03 19:13:15 -04:00
parent e3eabd418e
commit dbd10b859f
5 changed files with 137 additions and 0 deletions

View File

@ -0,0 +1,8 @@
<script>
export default {
oncreate() {
let { r: { router }, to, push } = this.get()
router.go(to, !push)
},
}
</script>

40
src/components/Route.html Normal file
View File

@ -0,0 +1,40 @@
<div ref:mount/>
<script>
import matchPath from '../utils/matchPath.js'
export default {
oncreate() {
this.observe('r', update.bind(this))
this.observe('path', update.bind(this))
},
}
function update() {
let {
r: { match, pathname, router },
path,
exact,
component,
} = this.get()
let { _r } = this
if (path) {
let match = matchPath(pathname, { path, exact })
if (match) {
if (_r) {
_r.set({ match, r: { match, pathname, router } })
} else {
_r = new component({ target: this.refs.mount, data: { match, r: { match, pathname, router } } })
}
} else if (_r) {
_r.destroy()
_r = null
}
} else if (_r) {
_r.set({ match, r: { match, pathname, router } })
} else {
_r = new component({ target: this.refs.mount, data: { match, r: { match, pathname, router } } })
}
this._r = _r
}
</script>

View File

@ -0,0 +1,51 @@
<div ref:mount/>
<script>
export default {
oncreate() {
document.addEventListener('click', clickHandler.bind(this))
window.addEventListener('popstate', popHandler.bind(this))
this._r = new (this.get('component'))({ target: this.refs.mount, data: { r: { router: this, pathname: document.location.pathname } } })
},
methods: {
go(url, replace) {
history[replace ? 'replaceState' : 'pushState'](null, '', location.origin + url)
if (this._r) {
let r = this._r.get('r')
r.pathname = url
this._r.set({ r })
}
},
},
}
function clickHandler(event) {
if (event.ctrlKey || event.metaKey || event.shiftKey || event.which !== 1) {
return
}
let elm = event.target
while (elm.nodeName !== 'A') {
elm = elm.parentElement
if (!elm) {
return
}
}
if (elm.target) {
return
}
let url = elm.href
if (!url.startsWith(document.location.origin + '/')) {
return
}
event.preventDefault()
this.go(url.slice(document.location.origin.length))
}
function popHandler() {
if (this._r) {
let r = this._r.get('r')
r.pathname = document.location.pathname
this._r.set({ r })
}
}
</script>

4
src/index.js Normal file
View File

@ -0,0 +1,4 @@
export { default as Redirect } from './components/Redirect.html'
export { default as Route } from './components/Route.html'
export { default as Router } from './components/Router.html'
export { default as matchPath } from './utils/matchPath.js'

34
src/utils/matchPath.js Normal file
View File

@ -0,0 +1,34 @@
let cache = new Map()
let escapeRe = /[\\^$.*+?()[\]{}|]/g
let paramRe = /:\w+/
export default function matchPath(pathname, { path, exact }) {
let key = path + !!exact
let regex
let names
if (cache.has(key)) {
({ regex, names } = cache.get(key))
} else {
let rest = path
regex = '^'
names = []
let match
while ((match = rest.match(paramRe))) {
regex += rest.slice(0, match.index).replace(escapeRe, '\\$&') + '([^/]+)'
names.push(match[0].slice(1))
rest = rest.slice(match.index + match[0].length)
}
regex += rest.replace(escapeRe, '\\$&') + (exact ? '$' : '(?=\\/|$)')
regex = new RegExp(regex)
cache.set(key, { regex, names })
}
let match = pathname.match(regex)
if (!match) {
return null
}
let params = {}
for (let i = 0; i < names.length; i++) {
params[names[i]] = match[i + 1]
}
return { path, url: match[0], params }
}