Permalink
Browse files

initial with new name

  • Loading branch information...
0 parents commit d6e8bb979026cec6561644077bc91c38d9ed4367 @saambarati committed May 8, 2012
Showing with 691 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +89 −0 README.md
  3. +109 −0 match.js
  4. +17 −0 package.json
  5. +18 −0 tests/test-conflict.js
  6. +37 −0 tests/test-next.js
  7. +59 −0 tests/test-readme.js
  8. +30 −0 tests/test-similar.js
  9. +110 −0 tests/test-tree.js
  10. +18 −0 tests/test-uricomponent.js
  11. +203 −0 treeRouter.js
@@ -0,0 +1 @@
+old
@@ -0,0 +1,89 @@
+
+Maple
+=====
+
+Maple is a small, recursive router for Node.js. It works by creating a routing tree and searching for full and partial matches.
+Maple is designed to be minimal. It is written with the intention that other libraries can be built on top of it or extend its functionality.
+
+####Install
+ npm install Maple
+#### From Source
+ git clone git://github.com/saambarati/Maple.git
+ cd Maple
+ npm link
+
+API
+---
+
+### Simple Routing
+ var mapleTree = require('mapleTree')
+ , router = new mapleTree.RouteTree()
+
+ router.define('/foo/bar/', function () {
+ console.log('foo/bar route')
+ })
+
+ router.define('/hello/:foo', function () {
+ console.log('hello/:foo')
+ })
+
+ router.define('/files/:file.:format/', function () {
+ console.log('file callback')
+ console.log('filename =>' + this.params.file + '.'+ this.params.format)
+ })
+
+ /*
+ * the matcher object
+ * contains a few important properties
+ * matcher.cbs = {Array} //collection of callbacks, the closest match first
+ * matcher.fn = {function} //placeholder for best matching function
+ * matcher.perfect = {boolean} default => false //were we able to match an exact path, or did we only match partially?
+ * matcher.extras = {Array} //match a regexp capture group that isn't part of params
+ * matcher.params = {Object} //collection of colon args
+ */
+ var match = router.match('/foo/bar/')
+ match.fn() //prints 'foo/bar route'
+
+ match = router.match('/hello/world')
+ match.fn() //prints 'hello/:foo'
+ console.log(match.params.foo) //prints 'world'
+
+ match = router.match('/files/index.html')
+ match.fn() //prints 'filename => index.html'
+
+
+### Partial Matches -- *first in first out / first in last out*
+ var mapleTree = require('mapleTree')
+ , router = new mapleTree.RouteTree({'fifo' : false })
+
+ router.define('/hello/', function () {
+ console.log('/hello/')
+ this.next()
+ })
+ router.define('/hello/world/', function () {
+ console.log('/hello/world/')
+ this.next()
+ })
+ router.define('/hello/world/foo/', function () {
+ console.log('/hello/world/foo/')
+ this.next()
+ })
+
+ var match = router.match('/hello/world/foo')
+ match.fn()
+ /* PRINTS =>
+ * /hello/world/foo
+ * /hello/world/
+ * /hello/
+ */
+
+ router.fifo = true //first match is invoked first now
+ //or when creating the router you can pass an options obj => new maple.RouteTree({'fifo' : true})
+ match = router.match('/hello/world/foo')
+ match.fn()
+ /* PRINTS =>
+ * /hello/
+ * /hello/world/
+ * /hello/world/foo/
+ */
+
109 match.js
@@ -0,0 +1,109 @@
+/*
+ * returns a regexp that will match against this route
+ * @param {string} aRoute
+ * @return {
+ * regexp: that matches route
+ * , params: {array} ----> /:hello/:world/ => ['hello', 'world']
+ * }
+*/
+var createRoute = function(aRoute) {
+ var cur = ''
+ , myStr = ''
+ , curIndex = 0
+ , keys = []
+ , regEx = ''
+ , flags = ['i']
+ , reservedChars = {
+ '/' : true
+ , '.' : true
+ , ':' : true
+ }
+ , badRoute = function (token) {
+ throw new Error('unexpected token within route: ' + "'" + cur + "'" + ' at index:' + curIndex)
+ }
+ , next = function(token) {
+ if (token) {
+ if (typeof token === 'string' && token !== cur) {
+ return badRoute(cur)
+ } else if (token instanceof RegExp && !token.test(cur)) {
+ return badRoute(cur)
+ }
+ }
+ curIndex += 1
+ cur = myStr.charAt(curIndex) //note, when curIndex exceeds the bounds of the string, a blank '' string is returned
+ return cur
+ }
+ , colon = function () {
+ //colons can only be followed by letters, numbers or underscores/
+ var range = /[a-zA-Z0-9\_]/
+ , aKey = ''
+ next(':') //get rid of colon
+ while (cur && !reservedChars[cur]) {
+ if (range.test(cur)) {
+ aKey += cur
+ next()
+ } else {
+ return badRoute(cur)
+ }
+ }
+ keys.push(aKey)
+
+ return '([^\/]+)'
+ }
+ , wildcard = function () {
+ return '(.+)'
+ }
+ , exactPath = function () {
+ var reg = ''
+ while (cur && !reservedChars[cur]) {
+ reg += cur
+ next()
+ }
+ return reg
+ }
+ , startMatching = function () {
+ regEx = '^\\/?'
+ while (cur) {
+ switch (cur) {
+ case '/' :
+ regEx += '\/'
+ next()
+ break
+ case '*' :
+ regEx += wildcard()
+ return regEx //we are done
+ case ':' :
+ regEx += colon()
+ break
+ case '.' :
+ regEx += '\\.'
+ next()
+ break
+ default :
+ regEx += exactPath()
+ break
+ }
+ }
+ }
+ , begin = function (stringToEvaluate) {
+ myStr = stringToEvaluate
+ cur = myStr.charAt(0)
+ curIndex = 0
+ startMatching()
+ regEx += '\\/'
+ //debugger
+ return {
+ 'params' : (keys.length ? keys : null)
+ , 'regexp' : new RegExp(regEx, flags.join(''))
+ }
+ }
+
+
+ return begin(aRoute)
+}
+
+
+module.exports = createRoute
+
+
+
@@ -0,0 +1,17 @@
+{
+ "name" : "mapleTree"
+ , "version" : "0.1.6"
+ , "private" : false
+ , "author" : "Saam Barati <saambarati1@gmail.com>"
+ , "contributors" : [ {"name" : "Saam Barati", "email" : "saambarati1@gmail.com"} ]
+ , "repository" : {
+ "type" : "git"
+ , "url" : "https://github.com/saambarati/Maple"
+ }
+ , "bugs" : { "url" : "https://github.com/saambarati/Maple/issues" }
+ , "keywords" : ["router", "routing", "route"]
+ , "license" : "MIT"
+ , "engine" : { "node" : ">=0.6.11" }
+
+ , "main" : "./treeRouter.js"
+}
@@ -0,0 +1,18 @@
+
+var maple = require('../treeRouter.js')
+ , tree = new maple.RouteTree()
+ , assert = require('assert')
+
+//test console warning. If the console doesn't print a warning, something is wrong
+// should print 1 warning per redefinition
+tree.define('/hello/:world', function () {})
+tree.define('/hello/:foo', function () {})
+
+tree.define('/wildcard/*', function (){})
+tree.define('/wildcard/*', function () {})
+
+tree.define('/foo/bar/', function () {})
+tree.define('/foo/bar/', function () {})
+
+tree.define('/home/:filename.html', function (){})
+tree.define('/home/:anothername.html', function (){})
@@ -0,0 +1,37 @@
+
+
+var maple = require('../treeRouter.js')
+ , tree = new maple.RouteTree({'fifo' : false})
+ , assert = require('assert')
+
+//note cbs.length is one less than matching routes, this is because the best match is placed in match.fn when '.match()' is invoked
+//keep in mind, these functions can be defined in any order, because there are no conflicts between them
+tree.define('/hello/', function () {
+ console.log('/hello/')
+ this.next()
+})
+tree.define('/hello/world', function () {
+ console.log('/hello/world/')
+ this.next()
+})
+tree.define('/hello/world/foo/', function () {
+ console.log('/hello/world/foo/')
+ this.next()
+})
+tree.define('/hello/world/foo/bar/', function () {
+ console.log('/hello/world/foo/bar')
+ this.next() //note, there is no next for this route, but make sure no crash
+})
+
+var match = tree.match('/hello/world/foo/bar')
+console.log('callbacks length before invocation => ' + match.cbs.length)
+match.fn()
+console.log('callbacks length after invocation => ' + match.cbs.length)
+
+console.log('\n\n')
+match = tree.match('/hello/world/')
+console.log('callbacks length before invocation => ' + match.cbs.length)
+match.fn()
+console.log('callbacks length after invocation => ' + match.cbs.length)
+
+
@@ -0,0 +1,59 @@
+
+ var maple = require('../treeRouter.js')
+ , router = new maple.RouteTree()
+
+ router.define('/foo/bar/', function () {
+ console.log('foo/bar route')
+ })
+
+ router.define('/hello/:foo', function () {
+ console.log('hello/:foo')
+ })
+
+ router.define('/files/:file.:format/', function () {
+ console.log('file callback')
+ console.log('filename =>' + this.params.file + '.' + this.params.format)
+ })
+
+ var match = router.match('/foo/bar/')
+ match.fn() //prints 'foo/bar route'
+
+ match = router.match('/hello/world')
+ match.fn() //prints 'hello/:foo'
+ console.log(match.params.foo) //prints 'world'
+
+ match = router.match('/files/index.html')
+ match.fn() //prints 'filename => index.html'
+
+
+ router = new maple.RouteTree({'fifo' : false }) //redefine router for test so we don't get route conflicts
+
+ router.define('/hello/', function () {
+ console.log('/hello/')
+ this.next()
+ })
+ router.define('/hello/world/', function () {
+ console.log('/hello/world/')
+ this.next()
+ })
+ router.define('/hello/world/foo/', function () {
+ console.log('/hello/world/foo/')
+ this.next()
+ })
+
+ var match = router.match('/hello/world/foo')
+ match.fn()
+ /* PRINTS =>
+ * /hello/world/foo
+ * /hello/world/
+ * /hello/
+ */
+
+ router.fifo = true //first match is invoked first now
+ match = router.match('/hello/world/foo')
+ match.fn()
+ /* PRINTS =>
+ * /hello/
+ * /hello/world/
+ * /hello/world/foo/
+ */
@@ -0,0 +1,30 @@
+
+
+var maple = require('../treeRouter.js')
+ , tree = new maple.RouteTree()
+ , assert = require('assert')
+
+
+//the purpose of this test is to make sure similar routes don't interfere with one another. I made this because I had an early bug where routes differing by 1 letter would sometimes match
+tree.define('/trees.e/', function () {
+ console.log('/trees.e')
+})
+
+tree.define('/trees/', function () {
+ console.log('/trees')
+})
+
+tree.define('/tree/', function () {
+ console.log('/tree')
+})
+
+var matcher
+
+matcher = tree.match('/tree')
+matcher.fn()
+
+matcher = tree.match('/trees')
+matcher.fn()
+
+matcher = tree.match('/trees.e')
+matcher.fn()
Oops, something went wrong.

0 comments on commit d6e8bb9

Please sign in to comment.