(function(__exports__) { "use strict"; var specials = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\' ]; var escapeRegex = new RegExp('(\\' + specials.join('|\\') + ')', 'g'); function isArray(test) { return Object.prototype.toString.call(test) === "[object Array]"; } // A Segment represents a segment in the original route description. // Each Segment type provides an `eachChar` and `regex` method. // // The `eachChar` method invokes the callback with one or more character // specifications. A character specification consumes one or more input // characters. // // The `regex` method returns a regex fragment for the segment. If the // segment is a dynamic of star segment, the regex fragment also includes // a capture. // // A character specification contains: // // * `validChars`: a String with a list of all valid characters, or // * `invalidChars`: a String with a list of all invalid characters // * `repeat`: true if the character specification can repeat function StaticSegment(string) { this.string = string; } StaticSegment.prototype = { eachChar: function(callback) { var string = this.string, ch; for (var i=0, l=string.length; i " + n.nextStates.map(function(s) { return s.debug() }).join(" or ") + " )"; }).join(", ") } END IF **/ // This is a somewhat naive strategy, but should work in a lot of cases // A better strategy would properly resolve /posts/:id/new and /posts/edit/:id. // // This strategy generally prefers more static and less dynamic matching. // Specifically, it // // * prefers fewer stars to more, then // * prefers using stars for less of the match to more, then // * prefers fewer dynamic segments to more, then // * prefers more static segments to more function sortSolutions(states) { return states.sort(function(a, b) { if (a.types.stars !== b.types.stars) { return a.types.stars - b.types.stars; } if (a.types.stars) { if (a.types.statics !== b.types.statics) { return b.types.statics - a.types.statics; } if (a.types.dynamics !== b.types.dynamics) { return b.types.dynamics - a.types.dynamics; } } if (a.types.dynamics !== b.types.dynamics) { return a.types.dynamics - b.types.dynamics; } if (a.types.statics !== b.types.statics) { return b.types.statics - a.types.statics; } return 0; }); } function recognizeChar(states, ch) { var nextStates = []; for (var i=0, l=states.length; i 2 && key.slice(keyLength -2) === '[]') { isArray = true; key = key.slice(0, keyLength - 2); if(!queryParams[key]) { queryParams[key] = []; } } value = pair[1] ? decodeURIComponent(pair[1]) : ''; } if (isArray) { queryParams[key].push(value); } else { queryParams[key] = decodeURIComponent(value); } } return queryParams; }, recognize: function(path) { var states = [ this.rootState ], pathLen, i, l, queryStart, queryParams = {}, isSlashDropped = false; path = decodeURI(path); queryStart = path.indexOf('?'); if (queryStart !== -1) { var queryString = path.substr(queryStart + 1, path.length); path = path.substr(0, queryStart); queryParams = this.parseQueryString(queryString); } // DEBUG GROUP path if (path.charAt(0) !== "/") { path = "/" + path; } pathLen = path.length; if (pathLen > 1 && path.charAt(pathLen - 1) === "/") { path = path.substr(0, pathLen - 1); isSlashDropped = true; } for (i=0, l=path.length; i