New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

router-dom

Package Overview
Dependencies
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

router-dom - npm Package Compare versions

Comparing version 1.2.1 to 2.0.0

5

dist/router.d.ts

@@ -6,2 +6,3 @@ export default class Router {

constructor(routes: [RouteParam, ...RouteParam[]], options?: Options);
private getMatchingRoute;
private doRouting;

@@ -13,3 +14,3 @@ go(path: string, state: LooseObject, params?: string): void;

changeOptions(options: Options): void;
getParams(search?: string): {
static getParams(search?: string): {
[k: string]: string;

@@ -44,3 +45,3 @@ };

to: string;
state: LooseObject;
state?: LooseObject;
params?: LooseObject;

@@ -47,0 +48,0 @@ }

90

dist/router.js

@@ -1,9 +0,7 @@

import { listen } from "quicklink";
import { pathToRegexp } from "path-to-regexp";
import { pathToRegexp, match } from "path-to-regexp";
import { render, html, hydro, $, $$ } from "hydro-js";
listen();
let router;
const outletSelector = "[data-outlet]";
const reactivityRegex = /\{\{([^]*?)\}\}/;
const flagsRegex = /:\w+/g;
const fetchCache = new WeakMap();
let base = $("base")?.getAttribute("href") || "";

@@ -14,3 +12,3 @@ if (base.endsWith("/")) {

addEventListener("popstate", async (e) => {
//@ts-ignore
//@ts-expect-error
router.doRouting(location.pathname, e);

@@ -30,19 +28,48 @@ });

router = this;
// Prefetch resources
this.routes.forEach((route) => {
//@ts-expect-error
if (route.templateUrl && !navigator.connection?.saveData) {
const controller = new AbortController();
const cache = { promise: null, controller };
fetchCache.set(route, cache);
//@ts-expect-error
requestIdleCallback(() => {
cache.promise = fetch(route.templateUrl, {
signal: controller.signal,
});
cache.promise
.then((res) => res.text())
.then((_html) => {
cache.html = _html;
})
.catch(async (err) => {
await this.options.errorHandler?.(err);
});
});
}
});
this.doRouting();
}
getMatchingRoute(path) {
if (path.startsWith(".")) {
path = path.replace(".", "");
}
return this.routes.find((route) => route.path.exec(path));
}
async doRouting(to = location.pathname, e) {
dispatchEvent(new Event("beforeRouting"));
const from = this.oldRoute ?? to;
const route = getMatchingRoute(to);
const route = this.getMatchingRoute(to);
if (route) {
try {
const [_, ...values] = to.match(route.path);
const params = Array.from(route.originalPath.matchAll(flagsRegex))
.flat()
.map((i) => i.replace(":", ""))
.reduce((state, key, idx) => {
state[key] = values[idx];
return state;
}, {});
const allParams = { ...this.getParams(), ...params };
const { params } = match(route.originalPath, {
decode: decodeURIComponent,
})(to);
const allParams = {
...Router.getParams(),
...Object.fromEntries(Object.entries(params)
.map((pair) => Number.isNaN(Number(pair[0])) && pair)
.filter(Boolean)),
};
const props = {

@@ -52,3 +79,5 @@ from: from.replace(base, ""),

...(Object.keys(allParams).length ? { params: allParams } : {}),
...history.state,
...(history.state && Object.keys(history.state).length
? { state: history.state }
: {}),
};

@@ -67,5 +96,18 @@ // Trigger leave

if (route?.templateUrl) {
const data = await fetch(route.templateUrl);
const _html = await data.text();
render(html `<div data-outlet>${_html}</div>`, outletSelector, false);
let cacheObj = fetchCache.get(route);
if (!fetchCache.has(route) || cacheObj?.promise === null) {
cacheObj.controller?.abort();
const data = await fetch(route.templateUrl);
if (!cacheObj) {
cacheObj = {
html: await data.text(),
};
fetchCache.set(route, cacheObj);
}
else {
cacheObj.html = await data.text();
}
}
Reflect.deleteProperty(cacheObj, "controller");
render(html `<div data-outlet>${await cacheObj.html}</div>`, outletSelector, false);
}

@@ -130,12 +172,6 @@ else if (route?.element) {

}
getParams(search = location.search) {
static getParams(search = location.search) {
return Object.fromEntries(new URLSearchParams(search));
}
}
function getMatchingRoute(path) {
if (path.startsWith(".")) {
path = path.replace(".", "");
}
return router.routes.find((route) => route.path.exec(path));
}
function registerAnchorEvent(anchor) {

@@ -148,3 +184,3 @@ if (anchor.getAttribute("href")?.startsWith("http"))

const hydroProp = replaceBars(hasData);
let href = anchor.getAttribute("data-href") || anchor.getAttribute("href") || "";
const href = anchor.getAttribute("href") || "";
router.go(href, hasData ? hydro[hydroProp] : void 0);

@@ -151,0 +187,0 @@ });

{
"name": "router-dom",
"version": "1.2.1",
"version": "2.0.0",
"description": "A lightweight router for everyone",

@@ -41,5 +41,4 @@ "type": "module",

"hydro-js": "^1.4.1",
"path-to-regexp": "^6.2.0",
"quicklink": "^2.1.0"
"path-to-regexp": "^6.2.0"
}
}
# router-dom
> A lightweight router for single-page applications.
> A lightweight router for single-page applications with faster subsequent page-loads by prefetching links during idle time if the user is not saving data.
>

@@ -11,2 +11,3 @@ > - it helps to reduce the delay between your pages, to minimize browser HTTP requests and enhance your user's web experience.

> - support in all modern browsers.
> - RegExp Routes

@@ -31,2 +32,3 @@ ## Demo

import Router from "https://cdn.skypack.dev/router-dom";
new Router(...) // see Constructor Documentation
</script>

@@ -37,7 +39,6 @@ ```

Use the href attribute in order to help `quicklink` prefetching the resource and use data-href as routing path.
```html
<a href="/">Home</a>
<a href="about.html" data-href="/about">About</a>
<a href="/about">About</a>
<div data-outlet></div>

@@ -49,3 +50,2 @@ ```

[path-to-regexp](https://github.com/pillarjs/path-to-regexp): Turn a path string such as '/user/:name' into a regular expression<br>
[quicklink](https://github.com/GoogleChromeLabs/quicklink): Faster subsequent page-loads by prefetching in-viewport links during idle time <br>
[hydro-js](https://github.com/Krutsch/hydro-js): Renders the view. In order to pass state via an anchor element (data attribute), a mapping on the hydro object is needed.<br>

@@ -71,3 +71,3 @@

templateUrl: "/about.html",
leave: ({ from, to, state, params }) => {},
leave: ({ from, to, params, state }) => {},
},

@@ -77,4 +77,4 @@ {

element: html`<h2>Drop a message on [...]</h2>`,
beforeEnter: ({ from, to, state, params }) => {},
afterEnter: ({ from, to, state, params }) => {},
beforeEnter: ({ from, to, params, state }) => {},
afterEnter: ({ from, to, params, state }) => {},
},

@@ -104,8 +104,4 @@ ]);

### getParams
### static getParams
- Returns the params as key-value pair.
## To Do
- Add nested routes

@@ -1,11 +0,9 @@

import { listen } from "quicklink";
import { pathToRegexp } from "path-to-regexp";
import type { MatchResult } from "path-to-regexp";
import { pathToRegexp, match } from "path-to-regexp";
import { render, html, hydro, $, $$ } from "hydro-js";
listen();
let router: Router;
const outletSelector = "[data-outlet]";
const reactivityRegex = /\{\{([^]*?)\}\}/;
const flagsRegex = /:\w+/g;
const fetchCache = new WeakMap<Route, Cache>();
let base = $("base")?.getAttribute("href") || "";

@@ -17,3 +15,3 @@ if (base.endsWith("/")) {

addEventListener("popstate", async (e) => {
//@ts-ignore
//@ts-expect-error
router.doRouting(location.pathname, e);

@@ -38,23 +36,56 @@ });

this.options = options;
router = this;
// Prefetch resources
this.routes.forEach((route) => {
//@ts-expect-error
if (route.templateUrl && !navigator.connection?.saveData) {
const controller = new AbortController();
const cache = { promise: null, controller } as Cache;
fetchCache.set(route, cache);
//@ts-expect-error
requestIdleCallback(() => {
cache.promise = fetch(route.templateUrl!, {
signal: controller.signal,
});
(cache.promise as unknown as Promise<Response>)
.then((res) => res.text())
.then((_html) => {
cache.html = _html;
})
.catch(async (err) => {
await this.options.errorHandler?.(err);
});
});
}
});
this.doRouting();
}
private getMatchingRoute(path: string): Route | undefined {
if (path.startsWith(".")) {
path = path.replace(".", "");
}
return this.routes.find((route) => route.path.exec(path));
}
private async doRouting(to: string = location.pathname, e?: PopStateEvent) {
dispatchEvent(new Event("beforeRouting"));
const from = this.oldRoute ?? to;
const route = getMatchingRoute(to);
const route = this.getMatchingRoute(to);
if (route) {
try {
const [_, ...values] = to.match(route.path)!;
const params = Array.from(route.originalPath.matchAll(flagsRegex))
.flat()
.map((i) => i.replace(":", ""))
.reduce((state: LooseObject, key, idx) => {
state[key] = values[idx];
return state;
}, {});
const allParams = { ...this.getParams(), ...params };
const { params } = match(route.originalPath, {
decode: decodeURIComponent,
})(to) as MatchResult;
const allParams = {
...Router.getParams(),
...Object.fromEntries(
Object.entries(params)
.map((pair) => Number.isNaN(Number(pair[0])) && pair)
.filter(Boolean) as Iterable<[string | symbol, string]>
),
};
const props = {

@@ -64,3 +95,5 @@ from: from.replace(base, ""),

...(Object.keys(allParams).length ? { params: allParams } : {}),
...history.state,
...(history.state && Object.keys(history.state).length
? { state: history.state }
: {}),
};

@@ -84,5 +117,23 @@

if (route?.templateUrl) {
const data = await fetch(route.templateUrl);
const _html = await data.text();
render(html`<div data-outlet>${_html}</div>`, outletSelector, false);
let cacheObj = fetchCache.get(route);
if (!fetchCache.has(route) || cacheObj?.promise === null) {
cacheObj!.controller?.abort();
const data = await fetch(route.templateUrl);
if (!cacheObj) {
cacheObj = {
html: await data.text(),
};
fetchCache.set(route, cacheObj);
} else {
cacheObj.html = await data.text();
}
}
Reflect.deleteProperty(cacheObj!, "controller");
render(
html`<div data-outlet>${await cacheObj!.html}</div>`,
outletSelector,
false
);
} else if (route?.element) {

@@ -158,3 +209,3 @@ render(

getParams(search = location.search) {
static getParams(search = location.search) {
return Object.fromEntries(new URLSearchParams(search));

@@ -164,9 +215,2 @@ }

function getMatchingRoute(path: string): Route | undefined {
if (path.startsWith(".")) {
path = path.replace(".", "");
}
return router.routes.find((route) => route.path.exec(path));
}
function registerAnchorEvent(anchor: HTMLAnchorElement) {

@@ -178,4 +222,3 @@ if (anchor.getAttribute("href")?.startsWith("http")) return;

const hydroProp = replaceBars(hasData);
let href =
anchor.getAttribute("data-href") || anchor.getAttribute("href") || "";
const href = anchor.getAttribute("href") || "";
router.go(href, hasData ? hydro[hydroProp!] : void 0);

@@ -270,5 +313,10 @@ });

to: string;
state: LooseObject;
state?: LooseObject;
params?: LooseObject;
}
type LooseObject = Record<keyof any, any>;
type Cache = {
promise?: null | Promise<Response>;
controller?: AbortController;
html?: string;
};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc