mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Improved Crossroads
This commit is contained in:
parent
1f187dd9f2
commit
9f5f066dbf
2 changed files with 70 additions and 108 deletions
|
|
@ -108,7 +108,7 @@ export class AbstractSettingsScreen extends AbstractScreen {
|
||||||
rules = {
|
rules = {
|
||||||
subname: /^(.*)$/,
|
subname: /^(.*)$/,
|
||||||
normalize_: (rquest, vals) => {
|
normalize_: (rquest, vals) => {
|
||||||
vals.subname = undefined === vals.subname ? defaultRoute : pString(vals.subname);
|
vals.subname = null == vals.subname ? defaultRoute : pString(vals.subname);
|
||||||
return [vals.subname];
|
return [vals.subname];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
140
vendors/routes/crossroads.js
vendored
140
vendors/routes/crossroads.js
vendored
|
|
@ -12,7 +12,7 @@
|
||||||
// Crossroads --------
|
// Crossroads --------
|
||||||
//====================
|
//====================
|
||||||
|
|
||||||
class Crossroads {
|
global.Crossroads = class Crossroads {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this._routes = [];
|
this._routes = [];
|
||||||
|
|
@ -25,38 +25,19 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
parse(request) {
|
parse(request) {
|
||||||
var routes = this._getMatchedRoutes(request || ''),
|
request = request || '';
|
||||||
i = 0,
|
var i = 0,
|
||||||
n = routes.length,
|
|
||||||
cur;
|
|
||||||
|
|
||||||
if (n) {
|
|
||||||
//shold be incremental loop, execute routes in order
|
|
||||||
while (i < n) {
|
|
||||||
cur = routes[i];
|
|
||||||
cur.route.callback && cur.route.callback(...cur.params);
|
|
||||||
cur.isFirst = !i;
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_getMatchedRoutes(request) {
|
|
||||||
var res = [],
|
|
||||||
routes = this._routes,
|
routes = this._routes,
|
||||||
n = routes.length,
|
n = routes.length,
|
||||||
route;
|
route;
|
||||||
//should be decrement loop since higher priorities are added at the end of array
|
//should be decrement loop since higher priorities are added at the end of array
|
||||||
while (n) {
|
while (n--) {
|
||||||
route = routes[--n];
|
route = routes[n];
|
||||||
if ((!res.length || route.greedy) && route.match(request)) {
|
if ((!i || route.greedy) && route.match(request)) {
|
||||||
res.push({
|
route.callback && route.callback(...route._getParamsArray(request));
|
||||||
route : route,
|
++i;
|
||||||
params : route._getParamsArray(request)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,35 +47,28 @@
|
||||||
class Route {
|
class Route {
|
||||||
|
|
||||||
constructor(pattern, callback, router) {
|
constructor(pattern, callback, router) {
|
||||||
this.greedy = false;
|
|
||||||
this.rules = {};
|
|
||||||
var isRegexPattern = pattern instanceof RegExp;
|
var isRegexPattern = pattern instanceof RegExp;
|
||||||
this._router = router;
|
Object.assign(this, {
|
||||||
this._pattern = pattern;
|
greedy: false,
|
||||||
this._paramsIds = isRegexPattern ? null : patternLexer.getParamIds(this._pattern);
|
rules: {},
|
||||||
this._optionalParamsIds = isRegexPattern ? null : patternLexer.getOptionalParamsIds(this._pattern);
|
_router: router,
|
||||||
this._matchRegexp = isRegexPattern ? pattern : patternLexer.compilePattern(pattern);
|
_pattern: pattern,
|
||||||
this.callback = isFunction(callback) ? callback : null;
|
_paramsIds: isRegexPattern ? null : captureVals(PARAMS_REGEXP, pattern),
|
||||||
|
_optionalParamsIds: isRegexPattern ? null : captureVals(OPTIONAL_PARAMS_REGEXP, pattern),
|
||||||
|
_matchRegexp: isRegexPattern ? pattern : compilePattern(pattern),
|
||||||
|
callback: isFunction(callback) ? callback : null
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
match(request) {
|
match(request) {
|
||||||
return this._matchRegexp.test(request) && this._validateParams(request); //validate params even if regexp because of `request_` rule.
|
// validate params even if regexp.
|
||||||
}
|
|
||||||
|
|
||||||
_validateParams(request) {
|
|
||||||
var values = this._getParamsObject(request);
|
var values = this._getParamsObject(request);
|
||||||
return 0 == Object.keys(this.rules).filter(key =>
|
return this._matchRegexp.test(request)
|
||||||
key !== 'normalize_' && !this._isValidParam(request, key, values)
|
&& 0 == Object.entries(this.rules).filter(([key, validationRule]) => {
|
||||||
).length;
|
var val = values[key],
|
||||||
}
|
|
||||||
|
|
||||||
_isValidParam(request, prop, values) {
|
|
||||||
var validationRule = this.rules[prop],
|
|
||||||
val = values[prop],
|
|
||||||
isValid = false;
|
isValid = false;
|
||||||
|
if (key === 'normalize_'
|
||||||
if (val == null && this._optionalParamsIds && this._optionalParamsIds.indexOf(prop) !== -1) {
|
|| (val == null && this._optionalParamsIds && this._optionalParamsIds.indexOf(key) !== -1)) {
|
||||||
isValid = true;
|
isValid = true;
|
||||||
}
|
}
|
||||||
else if (validationRule instanceof RegExp) {
|
else if (validationRule instanceof RegExp) {
|
||||||
|
|
@ -106,28 +80,27 @@
|
||||||
else if (isFunction(validationRule)) {
|
else if (isFunction(validationRule)) {
|
||||||
isValid = validationRule(val, request, values);
|
isValid = validationRule(val, request, values);
|
||||||
}
|
}
|
||||||
|
// fail silently if validationRule is from an unsupported type
|
||||||
return isValid; //fail silently if validationRule is from an unsupported type
|
return !isValid;
|
||||||
|
}).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
_getParamsObject(request) {
|
_getParamsObject(request) {
|
||||||
var values = patternLexer.getParamValues(request, this._matchRegexp),
|
var values = getParamValues(request, this._matchRegexp) || [],
|
||||||
o = {},
|
|
||||||
n = values.length;
|
n = values.length;
|
||||||
|
if (this._paramsIds) {
|
||||||
while (n--) {
|
while (n--) {
|
||||||
o[n] = values[n]; //for RegExp pattern and also alias to normal paths
|
values[this._paramsIds[n]] = values[n];
|
||||||
this._paramsIds && (o[this._paramsIds[n]] = values[n]);
|
|
||||||
}
|
}
|
||||||
o.request_ = request;
|
}
|
||||||
o.vals_ = values;
|
return values;
|
||||||
return o;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_getParamsArray(request) {
|
_getParamsArray(request) {
|
||||||
var norm = this.rules.normalize_;
|
var norm = this.rules.normalize_;
|
||||||
return isFunction(norm)
|
return isFunction(norm)
|
||||||
? norm(request, this._getParamsObject(request))
|
? norm(request, this._getParamsObject(request))
|
||||||
: patternLexer.getParamValues(request, this._matchRegexp);
|
: getParamValues(request, this._matchRegexp);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -166,41 +139,30 @@
|
||||||
return vals;
|
return vals;
|
||||||
},
|
},
|
||||||
|
|
||||||
tokenize = pattern => {
|
getParamValues = (request, regexp) => {
|
||||||
//save chars that shouldn't be escaped
|
|
||||||
return pattern.replace(OPTIONAL_SLASHES_REGEXP, '$1'+ SAVE_OPTIONAL_SLASHES +'$2')
|
|
||||||
.replace(REQUIRED_SLASHES_REGEXP, '$1'+ SAVE_REQUIRED_SLASHES +'$2')
|
|
||||||
.replace(OPTIONAL_PARAMS_REGEXP, SAVE_OPTIONAL_PARAMS)
|
|
||||||
.replace(REQUIRED_PARAMS_REGEXP, SAVE_REQUIRED_PARAMS);
|
|
||||||
},
|
|
||||||
|
|
||||||
untokenize = pattern => {
|
|
||||||
return pattern.replace(SAVED_OPTIONAL_SLASHES_REGEXP, '\\/?')
|
|
||||||
.replace(SAVED_REQUIRED_SLASHES_REGEXP, '\\/')
|
|
||||||
.replace(SAVED_OPTIONAL_REGEXP, '([^\\/]+)?/?')
|
|
||||||
.replace(SAVED_REQUIRED_REGEXP, '([^\\/]+)');
|
|
||||||
},
|
|
||||||
|
|
||||||
patternLexer = {
|
|
||||||
getParamIds : pattern => captureVals(PARAMS_REGEXP, pattern),
|
|
||||||
getOptionalParamsIds : pattern => captureVals(OPTIONAL_PARAMS_REGEXP, pattern),
|
|
||||||
getParamValues : (request, regexp) => {
|
|
||||||
var vals = regexp.exec(request);
|
var vals = regexp.exec(request);
|
||||||
if (vals) {
|
if (vals) {
|
||||||
vals.shift();
|
vals.shift();
|
||||||
}
|
}
|
||||||
return vals;
|
return vals;
|
||||||
},
|
},
|
||||||
compilePattern : pattern => {
|
compilePattern = pattern => {
|
||||||
pattern = pattern
|
return new RegExp('^' + (pattern
|
||||||
? untokenize(
|
? pattern
|
||||||
tokenize(pattern.replace(UNNECESSARY_SLASHES_REGEXP, '')).replace(ESCAPE_CHARS_REGEXP, '\\$&')
|
// tokenize, save chars that shouldn't be escaped
|
||||||
)
|
.replace(UNNECESSARY_SLASHES_REGEXP, '')
|
||||||
: '';
|
.replace(OPTIONAL_SLASHES_REGEXP, '$1'+ SAVE_OPTIONAL_SLASHES +'$2')
|
||||||
return new RegExp('^'+ pattern + '/?$'); //trailing slash is optional
|
.replace(REQUIRED_SLASHES_REGEXP, '$1'+ SAVE_REQUIRED_SLASHES +'$2')
|
||||||
}
|
.replace(OPTIONAL_PARAMS_REGEXP, SAVE_OPTIONAL_PARAMS)
|
||||||
|
.replace(REQUIRED_PARAMS_REGEXP, SAVE_REQUIRED_PARAMS)
|
||||||
|
.replace(ESCAPE_CHARS_REGEXP, '\\$&')
|
||||||
|
// untokenize
|
||||||
|
.replace(SAVED_OPTIONAL_SLASHES_REGEXP, '\\/?')
|
||||||
|
.replace(SAVED_REQUIRED_SLASHES_REGEXP, '\\/')
|
||||||
|
.replace(SAVED_OPTIONAL_REGEXP, '([^\\/]+)?/?')
|
||||||
|
.replace(SAVED_REQUIRED_REGEXP, '([^\\/]+)')
|
||||||
|
: ''
|
||||||
|
) + '/?$'); //trailing slash is optional
|
||||||
};
|
};
|
||||||
|
|
||||||
global.Crossroads = Crossroads;
|
|
||||||
|
|
||||||
})(this);
|
})(this);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue