minirouter.js
Star Fork IssueHomepage Documentation
Minirouter.js is an ultra-lightweight traditional router for creating minimalist front-end JavaScript projects.
Description
A lightweight, pure JavaScript routing library that provides flexible navigation with powerful features for modern web applications.
Features
- Zero dependencies
- Supports history and hash mode
- Automatic <a href> interception and normalizer
- File:// protocol compatibility
- Customizable route handling
- Query parameter extraction
- Navigation hooks (before/after)
Api
- new minirouterjs(baseUrl, hashMode)
- .go(path)
- .set(path, callback)
- .setNotFound(callback)
- .setBefore(callback)
- .setAfter(callback)
- .escapeHTML(string)
- .unescapeHTML(string)
Warning
Minirouter.js handles only front-end routing. You will need to implement server-side routing separately.
Basic Usage
Installation
Include the library via CDN:
<script src="https://cdn.jsdelivr.net/gh/milio48/minirouter.js@main/dist/v1.1/minirouter.min.js"></script>
Or download the source code from Github minirouter.js
HTML Example (Default: Blacklist Mode)
const router = new minirouterjs();
<a href="/">Home</a>
<a href="/user/1">User 1</a>
<a href="/notfound">404</a>
<!-- Disable router navigation for specific links -->
<a href="/unlist" mrt-none>unlist</a>
<a href="/download.zip" mrt-none>Download File</a>
In Blacklist Mode (whitelistMode = false), the router listens to all links, automatically ignoring external domains and target="_blank". Use blacklistAttr (e.g., mrt-none) only to manually skip internal links.
Minirouter.js will automatically listen and normalize path of href. Feel free to use relative paths like ../.
HTML Example (Whitelist Mode)
const router = new minirouterjs();
router.whitelistMode = true;
<!-- Enable router navigation for specific links -->
<a href="/" mrt>Home</a>
<a href="/user/1" mrt >User 1</a>
<a href="/notfound" mrt >404</a>
This is the "opt-in" mode. Minirouter.js will ignore all links, except for those you specifically mark with the mrt as a whitelistAttr.
Route by function
<button onclick="router.go('/dashboard')">Dashboard</button>
Initializing
// mode root domain (basic usage)
// expected http://localhost/
const router = new minirouterjs();
// non root domain
// expected http://localhost/folder
const router = new minirouterjs('/folder');
// hashes mode (support file:// protocol)
// expected http://127.0.0.1:5500/#/
// or file:///C:/www/project/file.html#/
// note : you cant combine hash mode with non root domain
const router = new minirouterjs('', true);
Customization
const router = new minirouterjs();
router.whitelistMode = false;
router.whitelistAttr = "mrt";
router.blacklistAttr = "mrt-none";
Set Path Examples
// expected http://localhost/
router.set('/', (params, target) => {
console.log(params); // { "param": "/", "query": {} }
console.log(target); // trigger element
});
// expected http://localhost/user/1
router.set('/user/:id', (params, target) => {
console.log(params); // { "param": "/user/1", "query": {}, "id": "1" }
console.log(target); // trigger element
});
Query Parameter Handling
// expected http://localhost/get/alluser/?limit=50
router.set('/get/:data', (params, target) => {
console.log(params);
/*
{
"param": "/get/alluser/?limit=50",
"query": {
"limit": "50"
},
"data": "1"
}
*/
console.log(params.query.limit);
console.log(target); // trigger element
});
Additional Routing Methods
// expected http://localhost/404
router.setNotFound((params, target) => {
console.log('Not Found :' + params + target);
});
// will executed before navigate
// possible to check authentication
router.setBefore((path, target) => {
console.log("Before Hook - Path:", path, "Target:", target);
});
// will executed after navigate
router.setAfter((path, target) => {
console.log("After Hook - Path:", path, "Target:", target);
});
Advanced Usage
Non Root Domain
// set base url to /folder
const router = new minirouterjs("/folder");
// expected http://localhost/folder as root
router.set('/', (params, target) => {
console.log(params); // { "param": "/", "query": {} }
console.log(target); // trigger element
});
// expected http://localhost/folder/docs
router.set('/docs', (params, target) => {
console.log(params); // { "param": "/", "query": {} }
console.log(target); // trigger element
});
If your domain is http://localhost/folder, you can set the base URL to /folder and still write routes as /.
This means you can easily copy your project to any domain and it will work seamlessly by simply editing the base URL.
The link <a href="/user/1">User 1</a> will automatically be normalized to <a href="/folder/user/1">User 1</a> . Enjoy the convenience!
Hashes Mode & Non HTTP Domain (file:// protocol)
// set base url to null and hashes mode to true
const router = new minirouterjs("", true);
// expected http://localhost/#/
router.set('/', (params, target) => {
console.log(params); // { "param": "/", "query": {} }
console.log(target); // trigger element
});
// expected http://localhost/#/docs
router.set('/docs', (params, target) => {
console.log(params); // { "param": "/", "query": {} }
console.log(target); // trigger element
});
This is useful for non-HTTP domains, such as file:///C:/www/project/index.html#/docs.
The link <a href="/docs/>Docs</a> will also be automatically normalized.
XSS Prevention
Minirouter.js provides escapeHTML() and unescapeHTML() methods to help prevent Cross-Site Scripting (XSS) attacks.
// non escaped
// http://127.0.0.1:5500/data?limit=<h1>XSS</h1>
router.set('/data', (params, target) => {
console.log(params);
console.log(target);
document.querySelector('#app').innerHTML = `<h1>Data</h1><p>Limit ${params.query.limit}</p>`;
// coloring by querySelector
document.querySelector('button[onclick*="/data"]').style.color = 'red';
});
// escaped html
router.set('/data', (params, target) => {
console.log(params);
console.log(target);
let escaped = router.escapeHTML(params.query.limit);
document.querySelector('#app').innerHTML = `<h1>Data</h1><p>Limit ${escaped}</p>`;
console.log(router.unescapeHTML(escaped));
// coloring by querySelector
document.querySelector('button[onclick*="/data"]').style.color = 'red';
});
Best Practices:
- Always escape user inputs before rendering
- Prefer innerText or textContent when possible
- Use escapeHTML() for rendering dynamic content
- Use unescapeHTML() only when you need to retrieve the original content