mirror of
https://github.com/sbrl/powahroot.git
synced 2024-12-22 11:15:01 +00:00
Start writing the documentation, but there's a bunch of work left still to do.
This commit is contained in:
parent
c3e352b77b
commit
71fc76521a
7 changed files with 119 additions and 58 deletions
|
@ -2,7 +2,18 @@
|
|||
|
||||
import EventEmitter from 'event-emitter-es6';
|
||||
|
||||
import { pathspec_to_regex } from '../Shared/Pathspec.mjs';
|
||||
|
||||
/**
|
||||
* Client-side request router.
|
||||
* @extends EventEmitter
|
||||
*/
|
||||
class ClientRouter extends EventEmitter {
|
||||
/**
|
||||
* Creates a new client-side request router.
|
||||
* You should use this in a browser. If you're not in a browser, you probably want ServerRouter instead.
|
||||
* @param {object} options The options object to use when creating the router.
|
||||
*/
|
||||
constructor(options) {
|
||||
super();
|
||||
|
||||
|
@ -30,18 +41,34 @@ class ClientRouter extends EventEmitter {
|
|||
}).bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the function to execute when no other route could be matched.
|
||||
* @param {Function} callback The callback to execute.
|
||||
* @example router.add_404((path) => console.log(`Oops! Couldn't find a route to handle '${path}'.`));
|
||||
*/
|
||||
add_404(callback) {
|
||||
this.callback_404 = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a route to the router.
|
||||
* @param {string|RegExp} routespec The route specification that the route should match against. May contain regular expression syntax, and the domain-specific :param syntax. A raw regular expression may also be passed, if you need the flexibility.
|
||||
* @param {Function} callback The callback to execute when the route is matched.
|
||||
* @example router.add_page("/add/vegetable/:name/:weight", (params) => console.log(`We added a ${params.name} with a weight of ${params.weight}g.`));
|
||||
*/
|
||||
add_page(routespec, callback) {
|
||||
this.routes.push({
|
||||
spec: routespec,
|
||||
match: this.pathspec_to_regex(routespec),
|
||||
match: pathspec instanceof RegExp ? { regex: routespec, tokens: [] } : pathspec_to_regex(routespec),
|
||||
callback
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually navigate to a given path.
|
||||
* @param {string} path The path to navigate to.
|
||||
* @example router.navigate("/add/carrot/frederick/10001");
|
||||
*/
|
||||
navigate(path) {
|
||||
for(let route_info of this.routes) {
|
||||
const matches = path.match(route_info.match.regex);
|
||||
|
@ -71,35 +98,13 @@ class ClientRouter extends EventEmitter {
|
|||
this.callback_404(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigate to the current URL's hash value - i.e. the bit after the '#' symbol in the URL.
|
||||
* @example router.navigate_current_hash();
|
||||
*/
|
||||
navigate_current_hash() {
|
||||
this.navigate(window.location.hash.substr(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a path specification into a regular expression.
|
||||
* From the server-side sibling of this (client-side) router.
|
||||
* @param {string} pathspec The path specification to convert.
|
||||
* @return {RegExp} The resulting regular expression
|
||||
*/
|
||||
pathspec_to_regex(pathspec) {
|
||||
if(pathspec == "*") // Support wildcards
|
||||
return { regex: /^/, tokens: [] };
|
||||
|
||||
let tokens = [];
|
||||
let regex = new RegExp("^" + pathspec.replace(/::?([a-zA-Z0-9\-_]+)/g, (substr/*, index, template (not used)*/) => {
|
||||
tokens.push(substr.replace(/:/g, ""));
|
||||
|
||||
// FUTURE: We could add optional param support here too
|
||||
if(substr.startsWith("::"))
|
||||
return `(.+)`;
|
||||
else
|
||||
return `([^\/]+)`;
|
||||
}) + "$", "i");
|
||||
|
||||
if(this.verbose) console.info("[router/verbose] Created regex", regex);
|
||||
|
||||
return { regex, tokens };
|
||||
}
|
||||
}
|
||||
|
||||
export default ClientRouter;
|
||||
|
|
47
README.md
47
README.md
|
@ -1,7 +1,52 @@
|
|||
# powahroot
|
||||
# ![](https://raw.githubusercontent.com/sbrl/powahroot/master/logo-large.png)powahroot
|
||||
|
||||
> Client and server-side routing micro frameworks
|
||||
|
||||
_Powerahroot_ is a pair of micro routing frameworks, presented as an ES6 module:
|
||||
|
||||
- The first is for client-side single-page web applications
|
||||
- The other is for handling server-side Node.js requests
|
||||
|
||||
## Getting Started
|
||||
Install powahroot as a dependency with npm:
|
||||
|
||||
```bash
|
||||
npm install --save powahroot
|
||||
```
|
||||
|
||||
Then `import` the router you're after:
|
||||
|
||||
```js
|
||||
import { ServerRouter } from 'powahroot';
|
||||
```
|
||||
|
||||
```js
|
||||
import { ClientRouter } from 'powahroot';
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Paths
|
||||
Powahroot supports multiple syntax bells and whistles when defining routes. These are documented below:
|
||||
|
||||
Syntax | Meaning
|
||||
--------------------------------|----------------------------------------
|
||||
`/index.html` | Regular route. Matches exactly what it says on the tin.
|
||||
`*` | Special key(word?) that matches _any_ route. Must be present on its own without any other characters.
|
||||
`/add/vegetable/:name/:weight` | Parameters. Match values an pull them into an object automatically. Does not like forward slashes in parameter values.
|
||||
`/images/::path` | Parameter values with forward slashes. If you want to use parameters, but need values to be able to contain forward slashes `/`, this is for you. Don't forget you can mix-and-match this with the previous example!
|
||||
|
||||
|
||||
### Client
|
||||
Initialise a new router like this:
|
||||
|
||||
```js
|
||||
const router = new ClientRouter({
|
||||
// Options object. Default settings:
|
||||
verbose: false, // Whether to be verbose in console.log() messages
|
||||
listen_pushstate: true, // Whether to react to browser pushstate events (excluding those generated by powahroot itself, because that would cause an infinite loop :P)
|
||||
});
|
||||
```
|
||||
|
||||
## Licence
|
||||
Everything in this repository _except_ the logo is licenced under the _Mozilla Public License 2.0.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
import RouterContext from './RouterContext.mjs';
|
||||
import { pathspec_to_regex } from '../Shared/Pathspec.mjs';
|
||||
|
||||
/**
|
||||
* A standalone HTTP router that's based on the principle of middleware.
|
||||
|
@ -50,7 +51,7 @@ class Router
|
|||
* @param {Function} action The action to execute. Will be passed the parameters `context` (Object) and `next` (Function).
|
||||
*/
|
||||
on(methods, pathspec, action) {
|
||||
let regex_info = pathspec instanceof RegExp ? {regex: pathspec, tokens: [] } : this.pathspec_to_regex(pathspec);
|
||||
let regex_info = pathspec instanceof RegExp ? {regex: pathspec, tokens: [] } : pathspec_to_regex(pathspec);
|
||||
|
||||
// next must be a generator that returns each action in turn
|
||||
this.actions.push(async (context, next) => {
|
||||
|
@ -93,31 +94,6 @@ class Router
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a path specification into a regular expression.
|
||||
* @param {string} pathspec The path specification to convert.
|
||||
* @return {RegExp} The resulting regular expression
|
||||
*/
|
||||
pathspec_to_regex(pathspec) {
|
||||
if(pathspec == "*") // Support wildcards
|
||||
return { regex: /^/, tokens: [] };
|
||||
|
||||
let tokens = [];
|
||||
let regex = new RegExp("^" + pathspec.replace(/::?([a-zA-Z0-9\-_]+)/g, (substr/*, index, template (not actually used)*/) => {
|
||||
tokens.push(substr.replace(/:/g, ""));
|
||||
|
||||
// FUTURE: We could add optional param support here too
|
||||
if(substr.startsWith("::"))
|
||||
return `(.+)`;
|
||||
else
|
||||
return `([^\/]+)`;
|
||||
}) + "$", "i");
|
||||
|
||||
/*if(this.verbose)*/ console.error("[router/verbose] Created regex", regex);
|
||||
|
||||
return { regex, tokens };
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the specified request.
|
||||
* @param {http.ClientRequest} request The request to handle.
|
||||
|
|
28
Shared/Pathspec.mjs
Normal file
28
Shared/Pathspec.mjs
Normal file
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Converts a path specification into a regular expression.
|
||||
* Originally from the server-side sibling of this (client-side) router.
|
||||
* @param {string} pathspec The path specification to convert.
|
||||
* @param {Boolean} verbose Optional. Whether to be verbose and log some stuff to the console. Default: false
|
||||
* @return {RegExp} The resulting regular expression
|
||||
*/
|
||||
function pathspec_to_regex(pathspec, verbose = false) {
|
||||
if(pathspec == "*") // Support wildcards
|
||||
return { regex: /^/, tokens: [] };
|
||||
|
||||
let tokens = [];
|
||||
let regex = new RegExp("^" + pathspec.replace(/::?([a-zA-Z0-9\-_]+)/g, (substr/*, index, template (not used)*/) => {
|
||||
tokens.push(substr.replace(/:/g, ""));
|
||||
|
||||
// FUTURE: We could add optional param support here too
|
||||
if(substr.startsWith("::"))
|
||||
return `(.+)`;
|
||||
else
|
||||
return `([^\/]+)`;
|
||||
}) + "$", "i");
|
||||
|
||||
if(verbose) console.info("[router/verbose] Created regex", regex);
|
||||
|
||||
return { regex, tokens };
|
||||
}
|
||||
|
||||
export { pathspec_to_regex };
|
BIN
logo-large.png
Normal file
BIN
logo-large.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 696 B |
10
package-lock.json
generated
10
package-lock.json
generated
|
@ -1,9 +1,15 @@
|
|||
{
|
||||
"name": "powerroot",
|
||||
"version": "1.0.0",
|
||||
"name": "powahroot",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@types/event-emitter-es6": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/event-emitter-es6/-/event-emitter-es6-1.1.0.tgz",
|
||||
"integrity": "sha512-A0010GUMSopVYUlDdzhYAD8Z2qGC2hG2H32IHy554NpGEHmsx8M6/lLZRRqxXCxLq28aYrmaZtGwDJjeNXbTDQ==",
|
||||
"dev": true
|
||||
},
|
||||
"await-fs": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/await-fs/-/await-fs-1.0.0.tgz",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "powerroot",
|
||||
"version": "1.0.0",
|
||||
"name": "powahroot",
|
||||
"version": "0.1.0",
|
||||
"description": "Client and server-side routing micro frameworks",
|
||||
"main": "index.mjs",
|
||||
"scripts": {
|
||||
|
@ -24,6 +24,7 @@
|
|||
"nightink": "^0.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/event-emitter-es6": "^1.1.0",
|
||||
"event-emitter-es6": "^1.1.5"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue