Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

got router mapping both ways

  • Loading branch information...
commit 066cea4ce2fc45de055cec2c3592424730345d15 1 parent c56714a
@markevans authored
View
1  Cakefile
@@ -57,4 +57,5 @@ task 'build_tests', 'Build tests from source files', ->
'test/src/jquery_plugins'
'test/src/presenter'
'test/src/datastore'
+ 'test/src/router'
], 'test/tests'
View
3  src/core_ext.coffee
@@ -13,3 +13,6 @@ Object.isEmpty = (obj)->
for key of obj
return false if obj.hasOwnProperty(key)
true
+
+RegExp.escape = (text)->
+ text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&")
View
56 src/router.coffee
@@ -1,12 +1,26 @@
-queryString = (params)->
- parts = []
- for key, value of params
- parts.push("#{encodeURIComponent(key)}=#{encodeURIComponent(value)}")
- parts.join('&')
-
class Route
- constructor: (@pattern)->
+
+ queryString = (params)->
+ parts = []
+ for key, value of params
+ parts.push("#{encodeURIComponent(key)}=#{encodeURIComponent(value)}")
+ parts.join('&')
+
+ compile = (pattern)->
+ pattern = RegExp.escape(pattern)
+ tokenPattern = /:([\w_]+)/
+ # Regexify all the ":token" parts and record their names
+ paramNames = []
+ while matches = pattern.match(tokenPattern)
+ paramNames.push matches[1]
+ pattern = pattern.replace(tokenPattern, '([\\w_]+)')
+ # Allow for a query string
+ pattern = pattern.replace('\\#','(?:\\?.*)?#')
+ [new RegExp("^#{pattern}$"), paramNames]
+
+ constructor: (@name, @pattern)->
[@path, @hash] = @pattern.split('#')
+ [@matcher, @paramNames] = compile(@pattern)
toURL: (params)->
path = @path
@@ -25,13 +39,23 @@ class Route
url += "##{hash}" if hash
url
+ matches: (url)->
+ @matcher.test(url)
+
+ paramsFor: (url)->
+ params = {}
+ matches = @matcher.exec(url)
+ for group, i in matches[1..matches.length]
+ params[@paramNames[i]] = group
+ params
+
class egg.Router extends egg.Base
@init (opts={})->
@window = opts.window || window
if opts.routes
@routes = {}
- @routes[name] = new Route(pattern) for name, pattern of opts.routes
+ @routes[name] = new Route(name, pattern) for name, pattern of opts.routes
else
throw("Router needs a 'routes' option!")
@@ -39,3 +63,19 @@ class egg.Router extends egg.Base
route = @routes[action]
if route
@window.history.pushState({}, "", route.toURL(params))
+
+ paramsFor: (url)->
+ @routeFor(url)?.paramsFor(url)
+
+ runURL: (url=@currentURL())->
+ route = @routeFor(url)
+ if route
+ @emit("route:#{route.name}", route.paramsFor(url))
+
+ currentURL: ->
+ @window.location + @window.search + @window.hash
+
+ routeFor: (url)->
+ for name, route of @routes
+ return route if route.matches(url)
+ null
View
23 test/src/router.coffee
@@ -0,0 +1,23 @@
+describe "egg.Router", ->
+ window.router = egg.Router.create(routes:
+ 'breads:index': '/breads'
+ 'breads:show': '/breads/:id'
+ 'breads:show:stuff': '/breads/:id#foo/:bar'
+ )
+
+ it "should match the correct route", ->
+ expect( router.routeFor('/breads').name ).toEqual('breads:index')
+ expect( router.routeFor('/breads/234').name ).toEqual('breads:show')
+
+ it "should not match routes that don't exist", ->
+ expect( router.routeFor('shenanigans/pans') ).toEqual(null)
+ expect( router.routeFor('/breads/234/shenanigans') ).toEqual(null)
+ expect( router.routeFor('naan/breads') ).toEqual(null)
+
+ it "should work for hashes and shiz", ->
+ expect( router.routeFor('/breads/234#foo/dunk').name ).toEqual('breads:show:stuff')
+
+ it "should parse the url correctly", ->
+ expect( router.paramsFor('/breads' ) ).toEqual({})
+ expect( router.paramsFor('/breads/234' ) ).toEqual(id: '234')
+ expect( router.paramsFor('/breads/234#foo/dunk') ).toEqual(id: '234', bar: 'dunk')
Please sign in to comment.
Something went wrong with that request. Please try again.