npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

web-router.js

v4.1.3

Published

A modern vanilla web router, inspired by Navigo, testing with Jest & JSDOM

Downloads

21

Readme

WebRouter.js

A modern vanilla JavaScript web router, inspired by Navigo API. Testing with Jest & JSDOM and bundled with microbundle.

Some of the improvements from the inspirational project: before, after and leave hook accept either a function or an array of functions. Previous methods can cancel the call chain for later methods see hooks section for details.

Additionally, improved RegExp matching, direct access to all routes, statically via WebRouter.routes, modern JavaScript codebase without the need for Babel and more.

Does not support hash routing. Consider Navigo if you need to support old browsers.

Usage

.on() Route Handlers

This method be called multiple times, see chaining section below. It accepts a route name, parameterized URL string or RegExp to match against. The second argument is the main render method and an optional third argument of hooks. See the hooks section for more information

const router = new WebRouter();
router.on('/somepage/:myParam', ({myParam})=>{
  console.log('Page loaded', myParam);
}).resolve();

.on() RegExp Handlers or Parameterized URL Strings

const router = new WebRouter();
router.on(/myapp\/(bar|car)\/([A-Za-z0-9]{10,})/, (arg1, arg2)=>{
  console.log('Page loaded', arg1, arg2);
})
router.on(/myapp\/search\/([^/]{1,})/, (searchPhrase)=>{
  // Render app
}, {
  before:(done, params)=>{
    // must call done. pass `false` to terminate
    done();
  }
});
router.on('/profile/:userName', ({userName})=>{
  // only called when URL is /profile/WebRouter
  // based on before
}, {
  before:(done, {userName})=>{
    if(userName === 'WebRouter') {
      done();
    } else {
      done(false);
    }
    
  }
});
router.resolve();

Accessing GET Parameters

Can be done easily with window.location.search, it is advisable to use the const params = new URLSearchParams(window.location.search) and params.get('getParamName')

.off() Route Handlers

Omitting all arguments will delete all routes from the router. To remove individual routes, pass in the matching path that was passed as the first argument to .on()

const route = new WebRouter();
route.on('/somepage/:myParam', ()=>{
  // ... rendering
});
// disable that route
route.off('/somepage/:myParam');

.navigate( url, [data] ) Method

You can initiate a navigation from JavaScript by using the router.navigate method. The navigate method can accept an optional second parameter, which will be passed to pushState and available via event.state.

.resolve( path ) Method

WebRouter isn't started until router.resolve() is called. As a default argument, when no arguments are passed, .resolve uses window.location.pathname. However, you can manually intercede by passing the URL of the route you would prefer to resolve.

.updatePageLinks() Method

Identical to navigo, WebRouter supports integration with existing links using the router.updatePageLinks() method call. Add the attribute data-navigo or data-route to enable a link integration with the WebRouter. WebRouter will use the href attribute and call navigate on the users behalf when they click the link.

<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>
  <div>
    <a href="/some/url" data-route>Regular Link</a>
  </div>
</body>
</html>
new WebRouter({
'/some/url':()=>{ /* ... */ } 
}).resolve();

WebRouter.reset() Method

Similar to passing no arguments to an instance .off() method, calling WebRouter.reset() will reset the application and all stored routes.

Hooks

Hooks allow access to routes before, after and when the user navigates away via leave. They can accept a single function, as declared below or an array of functions

With hooks, passing an explicit false or falsy value as the first argument will terminate the call chain. Like before, the after and leave hooks receive done callback. Additionally, passing an explicit false to the after and leave hooks will cause the hooks to terminate, but have no effect on the primary route method.

route.on('/', ()=>{}, {
  before:(done, params)=>{
    // before anything, call done();
  },
  after:(done, params)=>{
    // immediately after render
  },
  leave:(done, params)=>{
    // on user navigate away
  }
});

Hooks, array of functions

route.on('/', ()=>{}, {
  before:[(done, params)=>{
    // allow
    done();
  }, (done, params)=>{
    // can reject
    done(false)
  }],
  after:[(done, params)=>{
    done(false);
  }, (done, params)=>{
    // terminated by done(false) in first method
    done();
  }],
  leave:[(done, params)=>{
    // can terminate chain by done(false) 
    done();
  }]
});

Hooks can be used together or as needed. For instance, if you wanted to call 5 methods before a route is invoked, but do not need to use after or leave, that's possible. For instanc presume we want to see if a user has a token, get the credentials is a user has said token that's simple

router.on('/user', ()=>{
  const div = document.createElement('div')
  div.innerText = localStorage.getItem('user')
  document.body.appendChild(div);
}, {
  before:[(done, params)=>{
    const token = localStorage.getItem('token');
    if(!token) done(false);
    done();
  }, (done, params)=>{
    /**
      Assumes API response is
      {user:'your name'}
    */
    fetch('/v3/user')
      .then(data=>data.json())
      .then(data=>{
        localStorage.setItem('user', user.name);
        done();
      }).catch(err=>{
        done(false);
      })
  }];
})
Hook Detail: after called unless route changes

Please note, while this will not apply to most users, it's worth nothing that the after hooks will be called for a route unless the route explicitly changes even if you cancel in the before method.

Chaining .on(), .on() and .resolve()

WebRouter supports call chaining for easier declarative routes

const router = new WebRouter();
router.on(/^\/foo1\/([^/]{1,})$/, (arg1)=>{
  // Do main rendering...
}, {
  before:[(done,params)=>{
    // ...
    done();
  },(done, params)=>{
    // ...
    done();
  }]
}).on('/foo2', ()=>{
  // Do main rendering...
}, {
  after:[(done,params)=>{
    // ...
    done();
  },(done, params)=>{
    // ...
    done();
  }]
}).resolve();

Convenience, Simple Declarations

If you don't need any RegExp support in your route or hooks, you can use the first argument of the WebRouter constructor to declare routes.

const router = new WebRouter({
  '/foo1':()=>{
    /* ... */
  },
  '/foo2/field2':()=>{
    /* ... */
  }
});
Developing for WebRouter Project

Configuration For Testing: It is advised to use at least node version 16.6.2

nvm install 16.6.2