You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
2.1 KiB
JavaScript
100 lines
2.1 KiB
JavaScript
'use strict'
|
|
var utils = require('./utils')
|
|
|
|
var noop = utils.noop
|
|
var assign = utils.assign
|
|
var isString = utils.isString
|
|
|
|
function RouteNode (options) {
|
|
options = options || {}
|
|
this._children = Object.create(null)
|
|
this._regExs = Object.create(null)
|
|
}
|
|
|
|
assign(RouteNode.prototype, {
|
|
handler: null,
|
|
|
|
add: function add(parts, handler, context) {
|
|
parts = parts || []
|
|
handler = handler || noop
|
|
context = context || null
|
|
|
|
if (parts.length === 0) {
|
|
this.handler = handler
|
|
this.context = context
|
|
return this
|
|
}
|
|
var part = parts.shift()
|
|
var node = null
|
|
|
|
if (isString(part)) {
|
|
node = this._children[part]
|
|
} else {
|
|
this._regExs[part] = part
|
|
}
|
|
|
|
if (node == null) {
|
|
node = new RouteNode()
|
|
this._children[part] = node
|
|
}
|
|
return node.add(parts, handler, context)
|
|
},
|
|
|
|
get: function get(parts, args, done) {
|
|
parts = parts || []
|
|
args = args || []
|
|
|
|
if (parts.length === 0) {
|
|
return done(null, this.handler, this.context, args)
|
|
}
|
|
var part = parts.shift()
|
|
var childNode = this._children[part]
|
|
if (childNode) {
|
|
return childNode.get(parts, args, done)
|
|
} else {
|
|
var results = this._getRegexChild(part)
|
|
if (results && results.node) {
|
|
return results.node.get(parts, args.concat(results.args), done)
|
|
} else {
|
|
return done(new Error('not found'))
|
|
}
|
|
}
|
|
},
|
|
|
|
_getRegexChild: function _getRegexChild(part) {
|
|
var childKey = null
|
|
var args = []
|
|
var self = this
|
|
|
|
Object.keys(this._regExs).forEach(function checkRegex(key) {
|
|
if (childKey) {
|
|
return
|
|
}
|
|
var regex = self._regExs[key]
|
|
var results = regex.exec(part)
|
|
var lastIndex = null
|
|
if (results) {
|
|
childKey = key
|
|
}
|
|
while (results && results.index !== lastIndex) {
|
|
args = args.concat(results[0])
|
|
lastIndex = results.index
|
|
results = regex.exec(part)
|
|
}
|
|
})
|
|
|
|
if (childKey) {
|
|
return {
|
|
args: args,
|
|
key: childKey,
|
|
node: this._children[childKey]
|
|
}
|
|
} else {
|
|
return null
|
|
}
|
|
}
|
|
|
|
})
|
|
|
|
module.exports = RouteNode
|