• Stars
    star
    223
  • Rank 178,458 (Top 4 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created almost 9 years ago
  • Updated over 7 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

fast, modular client-side router

sheet-router stability

npm version build status test coverage downloads js-standard-style

sheet-router is a fast, modular client-side router. It enables view composition and is tuned for performance by statically declaring routes in a radix-trie. Weighs 1.5KB minified and gzipped.

Installation

$ npm install sheet-router

Features

  • View composition through functions
  • Tuned for performance by generating a radix-trie
  • Not bound to any framework
  • Minimal dependencies and tiny code size
  • HTML5 history support
  • Catch and handle <a href=""> links

Usage

sheet-router tries to make routing understandable and pleasant to work with. It does so by using a lisp-like structure which is internally compiled to an efficient data structure. Here each route takes either an array of children or a callback, which are then translated to paths that take callbacks

const sheetRouter = require('sheet-router')
const html = require('bel')

// default to `/404` if no path matches
const router = sheetRouter({ default: '/404' }, [
  ['/', (params) => html`<div>Welcome to router land!</div>`],
  ['/:username', (params) => html`<div>${params.username}</div>`, [
    ['/orgs', (params) => html`<div>${params.username}'s orgs!</div>`]
  ]],
  ['/404', (params) => html`<div>Oh no, path not found!</div>`],
])

router('/hughsk/orgs')

history

Interacting with the browser history is a common action, sheet-router supports this out of the box. When the forwards or backwards buttons in the browser are clicked, or history.back / history.go are called sheet-router will update accordingly.

const history = require('sheet-router/history')
history(function (href) {
  router(href)
  console.log('history changed: ' + href)
})

hash

Interacting with hash changes is often a common fallback scenario for those who don't have support for browser history. Whenever a hashchange event is triggered, sheet-router will trigger an update as seen below. However in order to match hash prefixed routes, the hash-match module can be used to normalize routes (ex: #/foo becomes /foo).

const hash = require('sheet-router/hash')
const match = require('hash-match')
hash(function (href) {
  router(match(href))
  console.log('hash location changed: ' + href)
})

href

In HTML links are represented with <a href=""> style tags. Sheet-router can be smart about these and handle them globally. This way there's no need to attach specific listeners to each link and static HTML templates can be upgraded seemlessly to include single-page routing.

const href = require('sheet-router/href')
href(function (href) {
  router(href)
  console.log('link was clicked: ' + href)
})

You can ignore specific links that you do not want to process through routing by adding the data-no-routing attribute.

<a href="/my-external-link" data-no-routing>Non routed link</a>
<a href="/another-external-link" data-no-routing="true">Not routed either</a>

Also, if you pass an optional root node reference as a second argument to href, it will never intercept clicks outside that node. This is useful when your app is confined to a widget in a larger document.

href(function (href) {
  router(href)
  console.log('link was clicked: ' + href)
}, document.getElementById("app-root"))

qs

Sometimes query strings must be decoded. In order to do this, the ./qs.js file is included.

const qs = require('./qs')
qs('https://www.npmjs.com/search?q=query+string')
// => { q: 'query+string' }

walk

Sometimes it's necessary to walk the trie to apply transformations. In order to access the raw callback and prevent unnecessary function calls we need to disable the default thunking mechanism by passing { thunk: false }:

const sheetRouter = require('sheet-router')
const walk = require('sheet-router/walk')

const router = sheetRouter({ thunk: false }, [
  ['/multiply', (x, y) => x * y],
  ['/divide', (x, y) => x / y]
])

walk(router, (route, cb) => {
  const y = 2
  return function (params, x) {
    return cb(x, y)
  }
})

router('/multiply', 4)
// => 8
router('/divide', 8)
// => 4

We could change our transformed function to be thunked by changing walk to return a function, and setting { thunk: 'match' } so only the match function thunks. This is pretty advanced stuff, so don't sweat it too much - but it's super useful to create performant frameworks!

const router = sheetRouter({ thunk: 'match' }, [
  ['/foo', (x, y) => x * y],
  ['/bar', (x, y) => x / y]
])

walk(router, (route, cb) => {
  const y = 2
  return function (params) {
    return function (x) {
      return cb(x, y)
    }
  }
})

router('/multiply', 4)
// => 8
router('/multiply', 4)
// => 8 (but this time around this is computed faster)
router('/divide', 8)
// => 4

create-location

Sometimes you want to mirror the browser location API inside an object to use inside a framework. The hard part is to compute the new href from a set of changes. create-location provides an API to do just that:

const createLocation = require('sheet-router/create-location')

document.location = '/foo/bar#hey?beep=boop'
var location = createLocation()
// => {
//    pathname: '/',
//    hash: '#hey',
//    search: { beep: 'boop' },
//    href: '/foo/bar#hey?beep=boop'
//  }

const hashPatch = { hash: '#oh-no' }
var location = createLocation(location, hashPatch)
// => {
//    pathname: '/',
//    hash: '#oh-no',
//    search: { beep: 'boop' },
//    href: '/foo/bar#oh-no?beep=boop'
//  }

const uriPatch = '/hey/hello'
var location = createLocation(location, uriPatch)
// => {
//    pathname: '/hey/hello',
//    hash: '',
//    search: { },
//    href: '/hey/hello'
//  }

virtual-dom example

const render = require('virtual-dom/create-element')
const sheetRouter = require('sheet-router')
const h = require('virtual-dom/h')
const hyperx = require('hyperx')

const html = hyperx(h)

const router = sheetRouter([
  ['/foo/bar', (params, h, state) => html`<div>hello world!</div>`]
])

const node = render(router('/foo/bar', h, { name: 'Jane' }))
document.body.appendChild(node)
<body>
  <div>hello world</div>
</body>

react example

const sheetRouter = require('sheet-router')
const render = require('react-dom')
const hyperx = require('hyperx')
const react = require('react')

const html = hyperx(react.createElement)

const router = sheetRouter([
  ['/foo/bar', (params, h, state) => html`<div>hello world!</div>`]
])

render(router('/foo', react.createElement, { name: 'Jane' }), document.body)
<body>
  <div>hello world</div>
</body>

API

router = sheetRouter(opts?, [routes])

Create a new router from a nested array. Takes an optional options object as the first argument. Options are:

  • opts.default: defaults to '/404', default path to use if no paths match
  • opts.thunk: defaults to true. Toggle if callbacks should be thunked or not. Can be set to 'match' to only have the returned router.match() function expect thunks to exist. Useful to write a custom walk function that creates a different signature

router(path, [,...])

Match a route on the router. Takes a path and an arbitrary list of arguments that are then passed to the matched routes. Cleans urls to only match the pathname.

history(cb(href))

Call a callback to handle html5 pushsState history.

href(cb(href))

Call a callback to handle <a href="#"> clicks.

See Also

License

MIT

More Repositories

1

rust-for-js-peeps

Know JS, want to try Rust, but not sure where to start? This is for you!
1,262
star
2

vmd

πŸ™ preview markdown files
JavaScript
1,181
star
3

notes

notes on things
839
star
4

tiny-guide-to-non-fancy-node

A tiny guide to non fancy, high-value Node.js things
735
star
5

futures-concurrency

Structured concurrency operations for async Rust
Rust
403
star
6

github-standard-labels

Create a standard set of issue labels for a GitHub project
JavaScript
241
star
7

pretty-hot-ranking-algorithm

Algorithm that measures how relevant a given data set is, kinda like Reddit
JavaScript
204
star
8

markdown-to-medium

Publish markdown to medium
JavaScript
198
star
9

html

Type-safe HTML support for Rust
HTML
186
star
10

barracks

🚞 action dispatcher for unidirectional data flows
JavaScript
177
star
11

virtual-html

🌴 HTML β†’ virtual-dom
JavaScript
174
star
12

es2020

Because in hindsight we don't need most of ES6
JavaScript
126
star
13

dotfiles-linux-2019

Linux desktop config
Shell
126
star
14

miow

A zero-overhead Windows I/O library, focusing on IOCP
Rust
111
star
15

fsm-event

🎰 stateful finite state machine
JavaScript
91
star
16

changelog

Changelog generator
Rust
85
star
17

vel

minimal virtual-dom library
JavaScript
84
star
18

fd-lock

Advisory cross-platform file locks using file descriptors
Rust
69
star
19

exponential-backoff

Exponential backoff generator with jitter.
Rust
66
star
20

memdb

Thread-safe in-memory key-value store.
Rust
64
star
21

previewify

Preview tool for applications
JavaScript
62
star
22

server-router

Server router
JavaScript
61
star
23

speaking

Slides, proposals and more for talks I give
JavaScript
57
star
24

electron-collection

Set of helper modules to build Electron applications
JavaScript
57
star
25

cache-element

Cache an HTML element that's used in DOM diffing algorithms
JavaScript
56
star
26

mdjson

πŸ“– Transform markdown to an object where headings are keys
JavaScript
55
star
27

context-attribute

Set the error context using doc comments
Rust
53
star
28

copy-template-dir

High throughput template dir writes
JavaScript
52
star
29

newspeak

πŸ’¬ natural language localization
JavaScript
51
star
30

assert-snapshot

Snapshot UI testing for tape tests
JavaScript
50
star
31

polite-element

Politely waits to render an element until the browser has spare time
JavaScript
45
star
32

choo-persist

Synchronize choo state with indexedDB
JavaScript
44
star
33

power-warn

Warn on low power level.
Rust
42
star
34

base-elements

A selection of configurable native DOM UI elements
JavaScript
41
star
35

nanostack

Small middleware stack library
JavaScript
40
star
36

millennial-js

πŸ’
CSS
39
star
37

on-intersect

Call back when an element intersects with another
JavaScript
35
star
38

github-templates

Generate .github templates
Rust
35
star
39

microcomponent

Smol event based component library
JavaScript
35
star
40

observe-resize

Trigger a callback when an element is resized
JavaScript
33
star
41

hypertorrent

Stream a torrent into a hyperdrive
JavaScript
31
star
42

npm-install-package

Install an npm package
JavaScript
30
star
43

async-iterator

An async version of iterator
Rust
30
star
44

rust-lib-template

Rust lib template repository
Rust
29
star
45

heckcheck

A heckin small test generator
Rust
29
star
46

maxstache

Minimalist mustache template replacement
JavaScript
28
star
47

normcore

No-config distributed streams using hypercore
JavaScript
28
star
48

winstall

Install all dependencies required by a project
JavaScript
27
star
49

chic

Pretty parser error reporting.
Rust
27
star
50

validate-formdata

Data structure for validating form data
JavaScript
25
star
51

playground-tide-mongodb

Example using tide + mongodb
Rust
24
star
52

playground-nanoframework

Building tiny frameworks yo
JavaScript
24
star
53

hyperlapse

Distributed process manager
JavaScript
23
star
54

promise-each

Call a function for each value in an array and return a Promise
JavaScript
23
star
55

omnom

Streaming parser extensions for BufRead
Rust
23
star
56

virtual-widget

Create a virtual-dom widget
JavaScript
22
star
57

tasky

fluent async task spawning experiments
Rust
22
star
58

debug-to-json

πŸ”§ Convert debug logs to JSON
JavaScript
22
star
59

http-sse

Create server-sent-events
JavaScript
21
star
60

initialize

Generate a fresh package
JavaScript
21
star
61

kv-log-macro

Log macro for logs kv-unstable backend
Rust
21
star
62

github-changelist

Generate a list of merged PRs since the last release
Rust
21
star
63

assert-html

Assert two HTML strings are equal
JavaScript
21
star
64

cargo-task-wasm

A sandboxed local task runner for Rust
Rust
21
star
65

workshop-distributed-patterns

Learn how to create robust multi-server applications in Node
HTML
20
star
66

crossgen

Cross compilation template generator
Rust
20
star
67

electron-crash-report-service

Aggregate crash reports for Electron apps
JavaScript
19
star
68

pid-lite

A small PID controller library
Rust
19
star
69

playground-virtual-app

playground with some virtual-* tech
JavaScript
19
star
70

virtual-raf

Create a RAF loop for virtual-dom
JavaScript
19
star
71

promise-map

Map over an array and return a Promise.
JavaScript
19
star
72

how

how(1) - learn how to do anything
Rust
18
star
73

secure-password

Safe password hashing.
Rust
18
star
74

futures-time

async time combinators
Rust
18
star
75

microanalytics

Capture analytics events in the browser
JavaScript
18
star
76

noop2

No operation as a moduleβ„’
Makefile
18
star
77

github-to-hypercore

Stream a github event feed into a hypercore
JavaScript
17
star
78

hyperreduce

Distributed reduce on top of hypercore
JavaScript
17
star
79

microframe

Smol requestAnimationFrame package
JavaScript
17
star
80

github_auth

Authenticate with GitHub from the command line.
Rust
17
star
81

virtual-streamgraph

Create a virtual-dom streamgraph
JavaScript
16
star
82

rust-cli

rust(1) cli prototype
Rust
16
star
83

extract-html-class

Extract all classes from html
JavaScript
16
star
84

templates

Template files used to generate things
Shell
16
star
85

from2-string

Create a stream from a string. Sugary wrapper around from2
JavaScript
16
star
86

fin

Simple finance visualizations
JavaScript
16
star
87

async-collection

Collection of async functions
JavaScript
15
star
88

document-ready

Document ready listener for browsers
Rust
15
star
89

buffer-graph

Resolve a dependency graph for buffer creation
JavaScript
15
star
90

choo-pull

Wrap handlers to use pull-stream in a choo plugin
JavaScript
15
star
91

json-stream-to-object

Parse a JSON stream into an object
JavaScript
15
star
92

promise-reduce

Reduce an array and return a Promise
JavaScript
14
star
93

formdata-to-object

Convert a formData object or form DOM node to a KV object
JavaScript
14
star
94

ergonomic-viewport

Get the current ergonomic viewport
JavaScript
14
star
95

choo-model

Experimental state management lib for choo
JavaScript
14
star
96

shared-component

Share a component instance inside a window context
JavaScript
13
star
97

multipart-read-stream

Read a multipart stream over HTTP
JavaScript
13
star
98

nanopubsub

Tiny message bus
JavaScript
13
star
99

server-render

HTML server rendering middleware
JavaScript
13
star
100

const-combinations

Experiment to get k-combinations working as a const fn
Rust
13
star