124 lines
2.5 KiB
JavaScript
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,
|
|
}
|