arc-router
Advanced tools
Comparing version 1.1.2 to 1.2.0
70
index.js
@@ -0,1 +1,2 @@ | ||
const querystring = require('querystring'); | ||
const is = require('arc-is'); | ||
@@ -42,2 +43,6 @@ const ArcRegExp = require('arc-reg-exp'); | ||
constructor(_routeMap){ | ||
this.stripQueryParams = true; | ||
this.stripAnchors = true; | ||
this.captureQuery = false; | ||
this.captureAnchor = false; | ||
if(_routeMap){ | ||
@@ -56,5 +61,21 @@ this.setMap(_routeMap); | ||
setStripQueryParams(_stripQueryParams) { | ||
this.stripQueryParams = _stripQueryParams; | ||
} | ||
setStripAnchors(_stripAnchors) { | ||
this.stripAnchors = _stripAnchors; | ||
} | ||
setCaptureQuery(_captureQuery) { | ||
this.captureQuery = _captureQuery; | ||
} | ||
setCaptureAnchor(_captureAnchor) { | ||
this.captureAnchor = _captureAnchor; | ||
} | ||
travel(_route){ | ||
const index = {}; | ||
const route = _route; | ||
const { route, queryCapture, anchorCapture } = this._stripRoute(_route); | ||
const uriArray = this._trimAndBreakRoute(route); | ||
@@ -80,2 +101,9 @@ const routeMatches = this.routeMap.reduce((_routeMatches,_view,_route)=>{ | ||
delete routeData.routeWeight; | ||
if(this.captureQuery) { | ||
routeData.query = queryCapture; | ||
} | ||
if(this.captureAnchor) { | ||
routeData.anchor = anchorCapture; | ||
} | ||
return routeData; | ||
@@ -87,2 +115,40 @@ } | ||
_stripRoute(_route) { | ||
let route = _route; | ||
let queryCapture = false; | ||
let anchorCapture = false; | ||
if(this.stripQueryParams) { | ||
const queryRX = new ArcRegExp(/([^\?]*)\?{0,1}(.*)/); | ||
route = queryRX.exec(route)[1]; | ||
if(this.captureQuery) { | ||
queryCapture = this._queryParse(_route) | ||
} | ||
} | ||
if(this.stripAnchors) { | ||
const anchorRX = new ArcRegExp(/([^\#]*)\#{0,1}([^\?]*)\?{0,1}(.*)/); | ||
const anchorParsed = anchorRX.exec(route); | ||
route = `${anchorParsed[1]}${anchorParsed[3] ? `?${anchorParsed[3]}` : ''}`; | ||
if(anchorParsed[2]) { | ||
anchorCapture = anchorParsed[2]; | ||
} | ||
} | ||
return { route, queryCapture, anchorCapture } | ||
} | ||
_queryParse(_route) { | ||
let urlSplit = _route.split("?"); | ||
urlSplit.shift(); | ||
urlSplit = decodeURI(urlSplit.join("?")).toLowerCase(); | ||
urlSplit = ArcObject.wrap(querystring.parse(urlSplit)); | ||
urlSplit = urlSplit.reduce((_params, _val, _key)=>{ | ||
try{ | ||
_params[_key] = JSON.parse(_val); | ||
} catch (_e) { | ||
_params[_key] = _val; | ||
} | ||
return _params; | ||
}, {}); | ||
return urlSplit || {}; | ||
} | ||
_resolveViews(_routeMatches,_index){ | ||
@@ -102,3 +168,3 @@ if(_routeMatches.count() === 1){ | ||
},new ArcObject); | ||
matchedIndex = this._reduceByHighestValue(matchedIndex,'tokensMatched'); | ||
@@ -105,0 +171,0 @@ if(matchedIndex.count() === 1){ |
{ | ||
"name": "arc-router", | ||
"version": "1.1.2", | ||
"version": "1.2.0", | ||
"description": "A purely functional router for independently evaluating a path against a list of routes", | ||
@@ -25,3 +25,3 @@ "main": "index.js", | ||
"devDependencies": { | ||
"jest": "^20.0.0" | ||
"jest": "^25.1.0" | ||
}, | ||
@@ -28,0 +28,0 @@ "dependencies": { |
@@ -67,2 +67,14 @@ # arc-router [![Build Status](https://travis-ci.org/anyuzer/arc-router.svg?branch=master)](https://travis-ci.org/anyuzer/arc-router) | ||
### .setStripQueryParams(value:Boolean) | ||
Sets whether or not the router should strip patterns that look like URL query params from a route being traveled. (ie `?var=1`). By default set to `TRUE` | ||
### .setStripAnchor(value:Boolean) | ||
Sets whether or not the router should strip patterns that look like a URL anchor from a route being traveled (ie. `#someAnchor`). By default set to `TRUE` | ||
### .setCaptureQuery(value:Boolean) | ||
Sets whether or not query parameter like patterns should be captured, parsed and returned as part of the routeData object on return. By default set to `FALSE`. If set to `TRUE` query parameters will be appended to the routeData object as a `{key:val}` object under `query` | ||
### .setCaptureAnchor(value:Boolean) | ||
Sets whether or not query parameter like patterns should be captured, parsed and returned as part of the routeData object on return. By default set to `FALSE`. If set to `TRUE` any value after a URL `#` will become the value of `anchor` on the RouteData object. | ||
### .travel(routeString:String) | ||
@@ -74,2 +86,53 @@ Accept a string to travel the route map with. Travel returns a routeData object, binding variables based on the map route patterns. | ||
npm test | ||
``` | ||
``` | ||
## Rule Explanation | ||
! is an explicit match - format: `/!stringToMatch` Note: not case sensitive. stringToMatch is also used as keyName (boolean value) | ||
\+ is a Filter match - format: `/+keyName(filterName)` Note: requires a Filter object to be added through the AddFilter method | ||
\: is a Regex match - format: `/:keyName(regExPattern)` Note: regex current cannot use / anywhere in the pattern (we may handle this later on) | ||
\# is a numeric match - format: `/#keyName` | ||
\* is a wildcard match - format: `/\*keyName` | ||
### Additional modifiers: | ||
Recursive Matching - Modifier*2 | ||
usage: `!!/++/::/##/!**` | ||
Recursive states attempt to consume everything from that point until the next identifier matches. | ||
So for example: `/!wallpaper/!**filePath/:fileName([^\.]*\.jpg)` would match the following route `/wallpaper/vacations/australia/goldcoast/beach.jpg` | ||
In the event of recursive or multiple matching the data is stored in an array (so `routeData.filePath` would === `[vacations,australia,goldcoast]`) | ||
### Multi Match - IntModifier | ||
usage. `2* or 3+` etc | ||
Multi states require the full number of matches to successfully match to be a match | ||
So for example: `/!file/3*namespace/!*object` would match the following `/file/Ocelot/Engine/Toolbox/Router.php` | ||
### Binding Modifier - \[BindingPattern\] (must be at end of routeChunk) | ||
usage: `[/]` | ||
This is used to bind certain parts of the route back together | ||
So for example: `/!file/3*namespace[/]/!*object` would still match the following `/file/Ocelot/Engine/Toolbox/Router.php` | ||
but RouteData->namespace() would no longer be an array, instead it would be Ocelot/Engine/Toolbox | ||
#### Note: | ||
This code was based upon ancient code, which was based upon ancient code, continually tweaked as we used it for more. It works fairly well but has some assumed bugs | ||
Bug2: / in anything will pretty much fail. While we built a special case for the binding parameter, we still use it to split which will result in obvious failure | ||
These bugs are all pretty fixable. | ||
`/` will continue to be what we split with but for regEx we could tokenize the regex the same we tokenize the binding, and then reassign |
30914
12
615
137