-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Finally, done #1
Comments
router.js (move it as v2 of const PREFIX_FOR_ROUTES = 'DUSH__ROUTES__'
module.exports = () => (app) => {
app.on('route', (view, context) => view(context))
let el = null
const { on, emit } = app
app.on = (route, fn) => {
if (route.charAt(0) === '/') {
const handler = app.createRoute(route, fn)
on(`${PREFIX_FOR_ROUTES}${route}`, handler)
} else {
on(route, fn)
}
}
// eslint-disable-next-line max-params
app.emit = (...args) => {
if (args[0].charAt(0) === '/') {
return (el = navigate(...args))
} else {
// dush: max 3 args are supported to be emitted
emit(...args)
}
}
app.createRoute = (route, fn) => {
const res = makeRoute(route)
const r = Object.assign({ route, fn }, res)
r.matcher = (fp) => (r.regex.test(fp) ? collectParams(r, fp) : 0)
// eslint-disable-next-line
return Object.assign((...args) => fn(...args), r)
}
function navigate (pathname, state) {
let found = 0
const routes = app.getRoutes()
/* eslint-disable fp/no-loops */
for (let name in routes) {
if (found || !routes[name]) {
break
}
/* eslint-disable prefer-destructuring */
const route = routes[name]
const params = route.matcher(pathname)
// if `0` -> no match and no params
// if `{}` -> no params
if (!params) {
continue
}
found = 1
const context = Object.assign({}, route, { state, params, pathname })
emit('route', (...args) => (el = route.fn(...args)), context, el)
}
if (!found) {
emit('notFound', { state, pathname })
}
return el
}
// get route object from:
// - routePath, e.g. /users/:user/photos/:photoId
// - pathname, e.g. /users/charlike/photos/345345
// - or get all routes
//
// returns object { [routePath]: Object }
app.getRoutes = (name) => {
name = name || 0
let routes = {}
Object.keys(app._allEvents)
.filter((routeName) => routeName.startsWith(PREFIX_FOR_ROUTES))
.forEach((route) => {
const routeName = route.slice(PREFIX_FOR_ROUTES.length)
const routeObject = app._allEvents[route][0] // eslint-disable-line
if (!name) {
routes[routeName] = routeObject || 0
}
if (name && (name.indexOf(':') > 0 || routeObject.matcher(name))) {
// eslint-disable-next-line
routes = routeObject
}
})
return routes
}
}
function makeRoute (route) {
let keys = []
let re = route.replace(/\//g, '\\/').replace(/:(\w+)/g, (_, name) => {
keys.push(name)
return '(\\w+)'
})
let regex = `^${re}$`
return {
regex: new RegExp(regex, 'i'),
keys: keys
}
}
function collectParams (r, pathname) {
r.params = {}
pathname.replace(r.regex, (...args) => {
args.slice(1, -2).map((val, i) => {
r.params[r.keys[i]] = val
})
})
return r.params
} |
browser-router.js - handling module.exports = () => (app) => {
onHistory((node, e) => {
app.emit('historyChange', node, e)
})
onHref((node, e) => {
app.emit('hrefChange', node, e)
})
}
/**
* UTILS
*/
function onHistory (func) {
window.addEventListener('popstate', function onpopstate (e) {
// fails, probably because can't understand `window`
// eslint-disable-next-line
const { pathname, search, href, hash } = window.location
func({ pathname, search, href, hash }, e)
})
}
function onHref (func) {
window.addEventListener('click', function onclick (e) {
if (which(e) !== 1) {
return
}
if (
e.metaKey ||
e.ctrlKey ||
e.shiftKey ||
e.altKey ||
e.defaultPrevented
) {
return
}
// ensure link
// use shadow dom when available
/* eslint-disable fp/no-loops, prefer-destructuring */
let el = e.path ? e.path[0] : e.target
while (el && el.nodeName !== 'A') {
el = el.parentNode
}
if (!el || el.nodeName !== 'A') {
return
}
// allow mailto links to work normally
const link = el.getAttribute('href')
if (link && link.indexOf('mailto:') > -1) {
return
}
// allow external links to work normally
const sameHost = el.host === window.location.host
if (!sameHost) {
return
}
// prevent default behaviour on internal links
if (sameHost || el.pathname === window.location.pathname) {
e.preventDefault()
}
// allow opt out when custom attribute
if (!el.hasAttribute('data-no-routing')) {
func(el, e)
// eslint-disable-next-line
return
}
})
}
function which (e) {
e = e || window.event
return e.which === null ? e.button : e.which
} |
Example 1 (bel + nanomorph) const html = require('bel/browser')
const morph = require('nanomorph')
const sleep = require('delay')
// ==================
const App = require('./lib/chika-app')
const app = App({
state: { title: 'Hello nigga here, Initial!!1!', count: 0 },
effects: {
async add ({ actions }) {
actions.updateCount()
await sleep(1000)
actions.updateCount(2)
}
},
reducers: {
updateCount: ({ state, actions }, num) => ({
count: state.count + (num || 1)
})
}
})
/**
* Always set error listener
**/
app.once('error', (err) => {
console.error('ERR!', err)
})
/**
* Add diffing algorithm as `app.diff`
**/
app.use(() => {
app.diff = (oldTree, newTree) => morph(oldTree, newTree)
return app
})
/**
* Define your routes, just like event listeners,
* but starting with `/` always.
**/
app.on(
'/',
({ state }) => html`<div>
<h1>home</h1><h2>${state.title}</h2>
</div>`
)
app.on(
'/about',
({ state }) => html`<div><h1>about</h1><h2>${state.title}</h2></div>`
)
app.on(
'/users/:user',
({ state }, { user }) => html`<div>
<h1>user</h1>
<h2>${user}</h2>
<h3>${state.title}</h3>
</div>`
)
app.on(
'/groups/:group/users/:user/edit',
({ state }, params) => html`<div>
<h1>edit user from group ${params.group}</h1>
<h2>${params.user}</h2>
<h3>${state.title}</h3>
</div>`
)
app.on(
'/users/:user/edit',
({ state, params, actions }, p) => html`<div>
<h1 id="clickme">user edit, cnt: ${state.count}</h1>
<h2>':user' is: ${JSON.stringify(params)}</h2>
<h2>'pams': ${JSON.stringify(p)}</h2>
<h3>'state.title' is: ${state.title}</h3>
<button onclick=${actions.add}>add +1</button>
</div>`
)
const tree = app.start()
const main = document.querySelector('#app')
main.appendChild(tree) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Around
1.81kb min+gzip
- without the diffing and html/jsx thing. You can choose how to work under the hood - with virtual dom or not. So if you choose virtual dom and jsx, then from the views return jsx, and pass Virtual dom diffing algorithm asapp.diff(oldTree, newTree)
.Otherwise, good combo is
bel
plusnanomorph
but minified and gzipped with them is~5.63kb
Main Parts:
dush-browser-router
- belowindex.js
The text was updated successfully, but these errors were encountered: