Skip to content

Commit

Permalink
Merge branch 'master' into init-stores-with-state
Browse files Browse the repository at this point in the history
* master:
  Match route before init stores (choojs#698)
  more timings (choojs#578)
  Disable hash routing by default (choojs#699)
  • Loading branch information
tornqvist committed Jun 12, 2019
2 parents 11e8ed0 + a871818 commit d15e1f6
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 19 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,12 +284,12 @@ Querystrings (e.g. `?foo=bar`) are ignored when matching routes. An object
containing the key-value mappings exists as `state.query`.

### Hash routing
By default hashes are treated as part of the url when routing. Using hashes to
delimit routes (e.g. `/foo#bar`) can be disabled by setting the `hash`
[option](#app--chooopts) to `false`. Regardless, when a hash is found we also
check if there's an available anchor on the same page, and will scroll the
screen to the position. Using both hashes in URLs and anchor links on the page
is generally not recommended.
By default, hashes are ignored when routing. When enabling hash routing
(`choo({ hash: true })`) hashes will be treated as part of the url, converting
`/foo#bar` to `/foo/bar`. This is useful if the application is not mounted at
the website root. Unless hash routing is enabled, if a hash is found we check if
there's an anchor on the same page, and will scroll the element into view. Using
both hashes in URLs and anchor links on the page is generally not recommended.

### Following links
By default all clicks on `<a>` tags are handled by the router through the
Expand Down Expand Up @@ -534,7 +534,7 @@ Initialize a new `choo` instance. `opts` can also contain the following values:
- __opts.cache:__ default: `undefined`. Override default class cache used by
`state.cache`. Can be a a `number` (maximum number of instances in cache,
default `100`) or an `object` with a [nanolru][nanolru]-compatible API.
- __opts.hash:__ default: `true`. Treat hashes in URLs as part of the pathname,
- __opts.hash:__ default: `false`. Treat hashes in URLs as part of the pathname,
transforming `/foo#bar` to `/foo/bar`. This is useful if the application is
not mounted at the website root.

Expand Down
15 changes: 12 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module.exports = Choo
var HISTORY_OBJECT = {}

function Choo (opts) {
var timing = nanotiming('choo.constructor')
if (!(this instanceof Choo)) return new Choo(opts)
opts = opts || {}

Expand All @@ -37,7 +38,7 @@ function Choo (opts) {
// properties for internal use only
this._historyEnabled = opts.history === undefined ? true : opts.history
this._hrefEnabled = opts.href === undefined ? true : opts.href
this._hashEnabled = opts.hash === undefined ? true : opts.hash
this._hashEnabled = opts.hash === undefined ? false : opts.hash
this._hasWindow = typeof window !== 'undefined'
this._cache = opts.cache
this._loaded = false
Expand Down Expand Up @@ -72,12 +73,15 @@ function Choo (opts) {
if (self._hasWindow) document.title = title
})
}
timing()
}

Choo.prototype.route = function (route, handler) {
var routeTiming = nanotiming("choo.route('" + route + "')")
assert.equal(typeof route, 'string', 'choo.route: route should be type string')
assert.equal(typeof handler, 'function', 'choo.handler: route should be type function')
this.router.on(route, handler)
routeTiming()
}

Choo.prototype.use = function (cb) {
Expand All @@ -94,6 +98,7 @@ Choo.prototype.use = function (cb) {

Choo.prototype.start = function () {
assert.equal(typeof window, 'object', 'choo.start: window was not found. .start() must be called in a browser, use .toString() if running in Node')
var startTiming = nanotiming('choo.start')

var self = this
if (this._historyEnabled) {
Expand Down Expand Up @@ -139,11 +144,11 @@ Choo.prototype.start = function () {
}

this._setCache(this.state)
this._matchRoute(this.state)
this._stores.forEach(function (initStore) {
initStore(self.state)
})

this._matchRoute(this.state)
this._tree = this._prerender(this.state)
assert.ok(this._tree, 'choo.start: no valid DOM node returned for location ' + this.state.href)

Expand All @@ -168,13 +173,16 @@ Choo.prototype.start = function () {
self._loaded = true
})

startTiming()
return this._tree
}

Choo.prototype.mount = function mount (selector) {
var mountTiming = nanotiming("choo.mount('" + selector + "')")
if (typeof window !== 'object') {
assert.ok(typeof selector === 'string', 'choo.mount: selector should be type String')
this.selector = selector
mountTiming()
return this
}

Expand Down Expand Up @@ -202,6 +210,7 @@ Choo.prototype.mount = function mount (selector) {

renderTiming()
})
mountTiming()
}

Choo.prototype.toString = function (location, state) {
Expand All @@ -214,12 +223,12 @@ Choo.prototype.toString = function (location, state) {
assert.equal(typeof state, 'object', 'choo.toString: state should be type object')

this._setCache(state)
this._matchRoute(state, location)
this.emitter.removeAllListeners()
this._stores.forEach(function (initStore) {
initStore(state)
})

this._matchRoute(state, location)
var html = this._prerender(state)
assert.ok(html, 'choo.toString: no valid value returned for the route ' + location)
assert(!Array.isArray(html), 'choo.toString: return value was an array for the route ' + location)
Expand Down
31 changes: 26 additions & 5 deletions test/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ tape('should expose a public API', function (t) {
t.end()
})

tape('should enable history and hash by defaut', function (t) {
tape('should enable history and href by defaut', function (t) {
var app = choo()
t.true(app._historyEnabled, 'history enabled')
t.true(app._hrefEnabled, 'href enabled')
Expand Down Expand Up @@ -82,9 +82,9 @@ tape('router should support a default route', function (t) {
app.mount(container)
})

tape('router should treat hashes as slashes by default', function (t) {
tape('enabling hash routing should treat hashes as slashes', function (t) {
t.plan(1)
var app = choo()
var app = choo({ hash: true })
var container = init('/account#security')
app.route('/account/security', function (state, emit) {
t.pass()
Expand All @@ -93,9 +93,9 @@ tape('router should treat hashes as slashes by default', function (t) {
app.mount(container)
})

tape('router should ignore hashes if hash is disabled', function (t) {
tape('router should ignore hashes by default', function (t) {
t.plan(1)
var app = choo({ hash: false })
var app = choo()
var container = init('/account#security')
app.route('/account', function (state, emit) {
t.pass()
Expand Down Expand Up @@ -191,6 +191,27 @@ tape('state should include location on render', function (t) {
app.mount(container)
})

tape('state should include location on store init', function (t) {
t.plan(6)
var app = choo()
var container = init('/foo/bar/file.txt?bin=baz')
app.use(store)
app.route('/:first/:second/*', function (state, emit) {
return html`<div></div>`
})
app.mount(container)

function store (state, emit) {
var params = { first: 'foo', second: 'bar', wildcard: 'file.txt' }
t.equal(state.href, '/foo/bar/file.txt', 'state has href')
t.equal(state.route, ':first/:second/*', 'state has route')
t.ok(state.hasOwnProperty('params'), 'state has params')
t.deepEqual(state.params, params, 'params match')
t.ok(state.hasOwnProperty('query'), 'state has query')
t.deepEqual(state.query, { bin: 'baz' }, 'query match')
}
})

tape('state should include title', function (t) {
t.plan(3)
document.title = 'foo'
Expand Down
28 changes: 24 additions & 4 deletions test/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ tape('router should support a default route', function (t) {
t.end()
})

tape('router should treat hashes as slashes by default', function (t) {
tape('enabling hash routing should treat hashes as slashes', function (t) {
t.plan(1)
var app = choo()
var app = choo({ hash: true })
app.route('/account/security', function (state, emit) {
t.pass()
return html`<div></div>`
Expand All @@ -87,9 +87,9 @@ tape('router should treat hashes as slashes by default', function (t) {
t.end()
})

tape('router should ignore hashes if hash is disabled', function (t) {
tape('router should ignore hashes by default', function (t) {
t.plan(1)
var app = choo({ hash: false })
var app = choo()
app.route('/account', function (state, emit) {
t.pass()
return html`<div></div>`
Expand Down Expand Up @@ -185,6 +185,26 @@ tape('state should include location on render', function (t) {
t.end()
})

tape('state should include location on store init', function (t) {
t.plan(6)
var app = choo()
app.use(store)
app.route('/:first/:second/*', function (state, emit) {
return html`<div></div>`
})
app.toString('/foo/bar/file.txt?bin=baz')

function store (state, emit) {
var params = { first: 'foo', second: 'bar', wildcard: 'file.txt' }
t.equal(state.href, '/foo/bar/file.txt', 'state has href')
t.equal(state.route, ':first/:second/*', 'state has route')
t.ok(state.hasOwnProperty('params'), 'state has params')
t.deepEqual(state.params, params, 'params match')
t.ok(state.hasOwnProperty('query'), 'state has query')
t.deepEqual(state.query, { bin: 'baz' }, 'query match')
}
})

tape('state should include cache', function (t) {
t.plan(6)
var app = choo()
Expand Down

0 comments on commit d15e1f6

Please sign in to comment.