Skip to content

Instantly share code, notes, and snippets.

@wisniewski94
Last active March 21, 2021 17:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wisniewski94/45551543b80e4361de2a94dadeff6f60 to your computer and use it in GitHub Desktop.
Save wisniewski94/45551543b80e4361de2a94dadeff6f60 to your computer and use it in GitHub Desktop.
class Router {
constructor() {
this.init();
}
paths = {};
handleError() {
console.error('Route pattern does not match url. Redirecting client to 404 page');
}
transformRegexOutput(input) {
try {
return Object
.keys(input)
.filter(key => Number(key))
.reduce((obj, key) => ({ ...obj, [key]: input[key] }), {});
} catch (error) {
this.handleError();
return {};
}
}
mergeObjects(obj1, obj2) {
let iterator = -1;
return Object
.entries(obj1)
.reduce((obj, key, index) => {
if (obj1[index + 1] == '*') iterator += 1;
return ({ ...obj, [obj1[index + 1] == '*' ? iterator : obj1[index + 1].substring(1)]: obj2[index + 1] })
}, {})
}
parsePattern(pattern) {
return '^' + pattern.replaceAll('/', '\\/').replaceAll(/(\*|:\w*)/gm, '(:?[A-z|*]*)') + '(?:\\/?)$';
}
get(pattern, callback) {
const { paths } = this;
if (!paths[pattern]) {
paths[pattern] = {};
paths[pattern].callbacks = [];
}
paths[pattern].reg = this.parsePattern(pattern);
paths[pattern].callbacks.push(callback);
return true;
}
checkIfAnyPatternIsMatching(url) {
return (element, index, array) => {
const pattern = this.paths[element].reg;
const newRegex = new RegExp(pattern, 'i').exec(url);
if (!newRegex) { return false };
return true;
}
}
getParams(pattern, url) {
const parsedPattern = this.paths[pattern].reg;
const regex = new RegExp(parsedPattern, 'i');
const tokens = this.transformRegexOutput(regex.exec(pattern));
const params = this.transformRegexOutput(regex.exec(url));
return this.mergeObjects(tokens, params);
}
processURL(pattern, url) {
const result = this.getParams(pattern, url);
return this.paths[pattern].callbacks.forEach(callback => callback(result));
}
checkPatterns(url) {
const result = Object.keys(this.paths).find(this.checkIfAnyPatternIsMatching(url));
if (!result) {
this.handleError();
return false;
}
this.processURL(result, url);
return true;
}
init() {
this.get('/fd', data => {
console.log(data)
});
this.get('/ds/:abc/*/*/*/:dsa/*', data => {
console.log(data)
});
this.get('/ds', data => {
console.log(data)
});
window.addEventListener('DOMContentLoaded', (e) => {
e.preventDefault();
const { location } = window;
this.checkPatterns(location.pathname);
});
window.addEventListener('popstate', (e) => {
e.preventDefault();
const { location } = window;
this.checkPatterns(location.pathname);
return false;
})
}
}
export default Router;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment