flaska/bottle.js

124 lines
2.5 KiB
JavaScript

/**
* Router
*/
function Branch() {
this._map = new Map()
this._paramName = null
this._paramPrototype = null
this._handler = null
}
const __paramMapName = '__param'
function BottleRouter() {
this._root = new Branch()
}
BottleRouter.prototype.addRoute = function(route, handler) {
if (route[0] !== '/')
throw new Error(`route "${route}" must start with forward slash`);
let start = 1;
let end = 1;
let name = '';
let param = '';
let objectPrototype = {};
let paramDefined = false;
let isParam = false;
let branch = this._root;
let hashConflict = new Map();
for (let i = 1; i <= route.length; i++) {
if ((i === route.length || route[i] === '/') && end > start) {
let child;
let number = 0;
name = route.substring(start, end);
if (isParam) {
param = name;
name = __paramMapName;
}
if (branch._map.has(name)) {
child = branch._map.get(name);
}
else {
child = new Branch();
branch._map.set(name, child);
}
branch = child;
end = i;
start = i;
if (isParam) {
branch._paramName = param;
Object.defineProperty(objectPrototype, param, {
enumerable: true,
writable: true,
value: '',
});
paramDefined = true;
isParam = false;
}
}
if (i === route.length) {
branch._handler = handler;
branch._paramPrototype = objectPrototype;
continue;
}
if (route[i] === ':') {
isParam = true;
end = start = i + 1;
}
else if (route[i] === '/') {
end = start = i + 1;
}
else {
end++;
}
}
}
BottleRouter.prototype.match = function(url) {
let branch = this._root;
let start = 1;
let end = 1;
let output;
let map;
let name;
let char;
let paramMap = new Map();
for (let i = 1; i <= url.length; i++) {
char = url[i];
if ((i === url.length || char === '/') && end > start) {
name = url.slice(start, end);
map = branch._map;
if (output = map.get(name)) {
branch = output;
}
else if (output = map.get(__paramMapName)) {
branch = output;
paramMap.set(branch._paramName, name);
} else {
return null
}
i++;
end = start = i;
char = url[i];
}
if (i >= url.length) {
return {
handler: branch._handler,
params: paramMap,
};
}
if (char === '/') {
end = start = i + 1;
}
else {
end++;
}
}
return null;
}
export {
BottleRouter,
}