Skip to content

Commit

Permalink
tmp
Browse files Browse the repository at this point in the history
  • Loading branch information
yoshuawuyts committed Dec 20, 2015
1 parent a5eb180 commit 53f3e1b
Show file tree
Hide file tree
Showing 6 changed files with 253 additions and 180 deletions.
23 changes: 17 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
# Change Log
All notable changes to this project will be documented in this file. This
project adheres to [Semantic Versioning](http://semver.org/).
# Change Log All notable changes to this project will be documented in this
file. This project adheres to [Semantic Versioning](http://semver.org/).

## [unreleased](https://github.com/yoshuawuyts/wayfarer/compare/v5.0.1...HEAD)
### Changed
- removed multiplexed events
- removed symbols dependency
- removed internal method exposure; should never be a need for that again

### Added
- __changelog__: add
- matched routes can now return values

### Fixed
- moved back to using prototypes (speed improvement)
- moved to using a single trie which greatly decreases lookup times
- moved lookup logic to data structure which improves perf

## [5.0.1](https://github.com/yoshuawuyts/wayfarer/compare/v5.0.0...v5.0.1) - 2015-08-24
## [5.0.1](https://github.com/yoshuawuyts/wayfarer/compare/v5.0.0...v5.0.1) -
2015-08-24
### Fixed
- [[`3e0317d`](https://github.com/yoshuawuyts/wayfarer/commit/3e0317d)]
__nesting__: add fallback for 0.12

## [5.0.0](https://github.com/yoshuawuyts/wayfarer/compare/v4.3.1...v5.0.0) - 2015-08-23
## [5.0.0](https://github.com/yoshuawuyts/wayfarer/compare/v4.3.1...v5.0.0) -
2015-08-23
### Added
- [[`d3ff446`](https://github.com/yoshuawuyts/wayfarer/commit/d3ff446)]
__docs:__ document internals
Expand Down
92 changes: 59 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
# wayfarer
[![NPM version][npm-image]][npm-url]
[![build status][travis-image]][travis-url]
[![Test coverage][coveralls-image]][coveralls-url]
[![Downloads][downloads-image]][downloads-url]
[![js-standard-style][standard-image]][standard-url]
# wayfarer [![stability][0]][1]
[![npm version][2]][3] [![build status][4]][5] [![test coverage][6]][7]
[![downloads][8]][9] [![js-standard-style][10]][11]

Composable [trie based](https://github.com/jonathanong/routington/) router.
It is faster than traditional, linear, regular expression-matching routers,
It's faster than traditional, linear, regular expression-matching routers,
although insignficantly, and scales with the number of routes.

### features
- works with any framework
- built for speed
- minimal dependencies
- extensible

## Installation
```bash
```sh
$ npm install wayfarer
```

Expand All @@ -22,9 +25,9 @@ const router = wayfarer('/404')

router.on('/', () => console.log('/'))
router.on('/404', () => console.log('404 not found'))
router.on('/:user', params => console.log('user is %s', params.user))
router.on('/:user', ctx => console.log('user is %s', ctx.params.user))

router('/tobi')
router('tobi')
// => 'user is tobi'

router('/uh/oh')
Expand All @@ -48,24 +51,40 @@ r1('/dada/child')

## API
### router = wayfarer(default)
Initialize a router with a default route. Doesn't ignore querystrings and hashes.
Initialize a router with a default route. Doesn't ignore querystrings and
hashes.

### router.on(route, cb(params))
### el = router.on(route, cb(ctx, arguments...))
Register a new route. The order in which routes are registered does not matter.
Routes can register multiple callbacks. See
[`routington.define()`](https://github.com/pillarjs/routington#nodes-node--routerdefineroute)
for all route options.
for all route options. When called, the callback is passed a context object and
any additional arguments from `router()`. The context object has the following
properties:
- __route__: the remaining route that wasn't matched

### router(route)
### router(route|context, arguments...)
Match a route and execute the corresponding callback. Alias: `router.emit()`.
Accepts either a `route` string, or a context object with the following
possible properties:
- __route__: the route to be matched
- __params__: an parameters object
Any arguments passed after the `route/context` are passed as-is into the
function handler.

## Events
### router.on('error', cb(err, params, route, arguments...))
Aside from having a default path, a listener can be attached to handle errors.
If no listener is attached, an error will be thrown.

## Internals
__Warning__: these methods are considered internal and should only be used when
extending wayfarer.
- `router._default(params)`: Trigger the default route. Useful to propagate
error states.
- `routes = router._routes`: Expose the mounted routes.
- `subrouters = router._subrouters`: Expose the mounted subrouters.
Wayfarer is built on an internal trie structure. If you want to build a router
using this trie structure it can be accessed through
`require('wayfarer/trie')`. It exposes the following methods:
- `trie = Trie()` - create a new trie
- `node = trie.create(route)` - create a node at a path, and return a node
- `node = trie.match(route)` - match a route on the the trie and return a node
- `trie.mount(path, trie)` - mount a trie onto a node at route

## FAQ
### Why did you build this?
Expand All @@ -80,20 +99,27 @@ strip it of querystrings and hashes using the
[pathname-match](https://github.com/yoshuawuyts/pathname-match) module.

## See Also
- [hash-match](https://github.com/sethvincent/hash-match) - easy `window.location.hash` matching
- [pathname-match](https://github.com/yoshuawuyts/pathname-match) - strip querystrings and hashes from a url
- [wayfarer-to-server](https://github.com/yoshuawuyts/wayfarer-to-server) - Wrap wayfarer to provide HTTP method matching and `req, res` delegation
- [hash-match](https://github.com/sethvincent/hash-match) - easy
`window.location.hash` matching
- [pathname-match](https://github.com/yoshuawuyts/pathname-match) - strip
querystrings and hashes from a url
- [wayfarer-to-server](https://github.com/yoshuawuyts/wayfarer-to-server) -
Wrap wayfarer to provide HTTP method matching and `req, res` delegation

## License
[MIT](https://tldrlegal.com/license/mit-license)

[npm-image]: https://img.shields.io/npm/v/wayfarer.svg?style=flat-square
[npm-url]: https://npmjs.org/package/wayfarer
[travis-image]: https://img.shields.io/travis/yoshuawuyts/wayfarer/master.svg?style=flat-square
[travis-url]: https://travis-ci.org/yoshuawuyts/wayfarer
[coveralls-image]: https://img.shields.io/coveralls/yoshuawuyts/wayfarer.svg?style=flat-square
[coveralls-url]: https://coveralls.io/r/yoshuawuyts/wayfarer?branch=master
[downloads-image]: http://img.shields.io/npm/dm/wayfarer.svg?style=flat-square
[downloads-url]: https://npmjs.org/package/wayfarer
[standard-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square
[standard-url]: https://github.com/feross/standard
[0]: https://img.shields.io/badge/stability-2%20stable-brightgreen.svg?style=flat-square
[1]: https://nodejs.org/api/documentation.html#documentation_stability_index
[2]: https://img.shields.io/npm/v/wayfarer.svg?style=flat-square
[3]: https://npmjs.org/package/wayfarer
[4]: https://img.shields.io/travis/yoshuawuyts/wayfarer/master.svg?style=flat-square
[5]: https://travis-ci.org/yoshuawuyts/wayfarer
[6]: https://img.shields.io/codecov/c/github/yoshuawuyts/wayfarer/master.svg?style=flat-square
[7]: https://codecov.io/github/yoshuawuyts/wayfarer
[8]: http://img.shields.io/npm/dm/wayfarer.svg?style=flat-square
[9]: https://npmjs.org/package/wayfarer
[10]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square
[11]: https://github.com/feross/standard
[12]: http://github.com/raynos/mercury
[13]: http://github.com/raynos/virtual-dom
121 changes: 30 additions & 91 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,113 +1,52 @@
const routington = require('routington')
const symbol = require('es6-symbol')
const assert = require('assert')
const xtend = require('xtend')
const trie = require('./trie')

const sym = symbol('wayfarer')

module.exports = wayfarer
module.exports = Wayfarer

// create a router
// str -> obj
function wayfarer (dft) {
dft = sanitizeUri(dft) || ''
const routes = routington()
const subrouters = routington()
function Wayfarer (dft) {
if (!(this instanceof Wayfarer)) return new Wayfarer(dft)

emit._subrouters = subrouters
emit._default = defaultFn
emit._routes = routes
emit[sym] = true
emit._sym = sym
const _default = (dft || '').replace(/^\//, '')
const _trie = trie()

emit.emit = emit
emit.on = on
emit._trie = _trie
emit.emit = emit.bind(this)
emit.on = on.bind(this)
emit._wayfarer = true

return emit

// define a path
// define a route
// (str, fn) -> obj
function on (path, cb) {
assert.equal(typeof path, 'string')
function on (route, cb) {
assert.equal(typeof route, 'string')
assert.equal(typeof cb, 'function')
path = sanitizeUri(path) || ''
const node = cb[sym] ? subrouters.define(path)[0] : routes.define(path)[0]
if (Array.isArray(node.cb)) node.cb.push(cb)
else node.cb = [cb]
return emit
}

// match and call a route
// str -> null
function emit (path, params, parentDefault) {
path = sanitizeUri(path) || ''
params = params || {}

const sub = matchSub(path)
if (sub) path = sub.path
route = route || '/'

const localDft = routes.match(dft) || parentDefault
const match = sub ? sub.matched : routes.match(path) || localDft
assert.ok(match, 'path ' + path + ' did not match')
params = xtend(params, match.param)

// only nested routers need a path
match.node.cb.forEach(function (cb) {
sub ? cb(path, params, localDft) : cb(params)
})
}
if (cb && cb._wayfarer && cb._trie) {
_trie.mount(route, cb._trie.trie)
} else {
const node = _trie.create(route)
node.cb = cb
}

// match the default route
// obj? -> null
function defaultFn (params) {
emit(dft, params)
return this
}

// match a mounted router
// str -> obj|null
function matchSub (path) {
var match = null
const split = path.split('/')
var count = split.length

var n = 0
while (n < split.length) {
var arr = []
var ln = split.length - n
var cnt = -1

while (++cnt < ln) {
arr.push(split[cnt])
}

var nw = arr.join('/')
var imatch = subrouters.match(nw)
if (imatch) {
match = imatch
count = arr.length
break
}
n++
}
// match and call a route
// (str, obj?) -> null
function emit (route) {
assert.notEqual(route, undefined, "'route' must be defined")

if (!match) return
const node = _trie.match(route) || _trie.match(_default)
assert.ok(node, "route '" + route + "' did not match")

while (count--) {
split.shift()
}
console.log(node)
console.log(JSON.stringify(_trie))

path = split.join('/')
const ret = {
matched: match,
path: path
}
return ret
return node.cb(node.params)
}
}

// strip leading `/`
// str -> str
function sanitizeUri (str) {
str = str || ''
return str.replace(/^\//, '')
}
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@
],
"license": "MIT",
"dependencies": {
"es6-symbol": "^2.0.1",
"routington": "^1.0.2",
"xtend": "^4.0.0"
"xtend": "^4.0.1"
},
"devDependencies": {
"istanbul": "^0.2.11",
Expand All @@ -38,6 +36,7 @@
"files": [
"LICENSE",
"index.js",
"trie.js",
"README.md"
]
}
Loading

0 comments on commit 53f3e1b

Please sign in to comment.