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

htmx-router

Package Overview
Dependencies
Maintainers
1
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

htmx-router - npm Package Compare versions

Comparing version 0.0.5 to 0.0.6

bin/404-route.d.ts

2

bin/cli/dynamic.js

@@ -42,3 +42,3 @@ #!/usr/bin/env node

script += "\tconst url = relative(ctx, file.slice(0, file.lastIndexOf(\".\")).replace(/\\\\/g, \"/\"));\n";
script += `\timport(file).then((mod) => Router.ingest(url, mod, []));\n`;
script += `\timport(file).then((mod) => Router.ingest(url, mod, [false]));\n`;
script += "}\n";

@@ -45,0 +45,0 @@ (0, fs_1.writeFileSync)(`${cwd}/router.ts`, script);

@@ -43,3 +43,3 @@ #!/usr/bin/env node

const file = files[i];
script += `Router.ingest("${file.slice(DIR.length - 1)}", Route${i}, []);\n`;
script += `Router.ingest("${file.slice(DIR.length - 1)}", Route${i}, [false]);\n`;
}

@@ -46,0 +46,0 @@ script += `Router.assignRoot(RootRoute);\n`;

@@ -0,4 +1,6 @@

import { ErrorResponse, Redirect, Outlet, Override } from "./shared";
import { RouteTree, IsAllowedExt } from "./router";
import { ErrorResponse, Redirect, Outlet, Override, RenderArgs } from "./shared";
import { RenderArgs } from "./render-args";
import { Link } from "./components";
import { StyleCSS } from "./helper";
export { IsAllowedExt, RouteTree, ErrorResponse, Redirect, Override, RenderArgs, Outlet, StyleCSS };
export { IsAllowedExt, RouteTree, ErrorResponse, Redirect, Override, RenderArgs, Outlet, StyleCSS, Link };
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StyleCSS = exports.RenderArgs = exports.Override = exports.Redirect = exports.ErrorResponse = exports.RouteTree = exports.IsAllowedExt = void 0;
const router_1 = require("./router");
Object.defineProperty(exports, "RouteTree", { enumerable: true, get: function () { return router_1.RouteTree; } });
Object.defineProperty(exports, "IsAllowedExt", { enumerable: true, get: function () { return router_1.IsAllowedExt; } });
exports.Link = exports.StyleCSS = exports.RenderArgs = exports.Override = exports.Redirect = exports.ErrorResponse = exports.RouteTree = exports.IsAllowedExt = void 0;
const shared_1 = require("./shared");

@@ -11,4 +8,10 @@ Object.defineProperty(exports, "ErrorResponse", { enumerable: true, get: function () { return shared_1.ErrorResponse; } });

Object.defineProperty(exports, "Override", { enumerable: true, get: function () { return shared_1.Override; } });
Object.defineProperty(exports, "RenderArgs", { enumerable: true, get: function () { return shared_1.RenderArgs; } });
const router_1 = require("./router");
Object.defineProperty(exports, "RouteTree", { enumerable: true, get: function () { return router_1.RouteTree; } });
Object.defineProperty(exports, "IsAllowedExt", { enumerable: true, get: function () { return router_1.IsAllowedExt; } });
const render_args_1 = require("./render-args");
Object.defineProperty(exports, "RenderArgs", { enumerable: true, get: function () { return render_args_1.RenderArgs; } });
const components_1 = require("./components");
Object.defineProperty(exports, "Link", { enumerable: true, get: function () { return components_1.Link; } });
const helper_1 = require("./helper");
Object.defineProperty(exports, "StyleCSS", { enumerable: true, get: function () { return helper_1.StyleCSS; } });
/// <reference types="node" />
import type http from "node:http";
import { Outlet, Override, Redirect, RenderArgs, RouteModule } from "./shared";
import { Override, Redirect, RouteModule } from "./shared";
import { MaskType, RenderArgs } from "./render-args";
export declare function IsAllowedExt(ext: string): boolean;
declare class RouteLeaf {
export declare class RouteLeaf {
module: RouteModule;
mask: boolean[];
constructor(module: RouteModule, mask: boolean[]);
makeOutlet(args: RenderArgs, outlet: Outlet, depth: number): Outlet;
render(args: RenderArgs, mask: MaskType, routeName: string): Promise<string>;
}

@@ -20,5 +21,4 @@ export declare class RouteTree {

ingest(path: string | string[], module: RouteModule, override: boolean[]): void;
calculateDepth(from: string[], to: string[]): number;
render(req: http.IncomingMessage, res: http.ServerResponse, url: URL): Promise<string | Redirect | Override>;
private _recursiveRender;
}
export {};
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RouteTree = exports.IsAllowedExt = void 0;
exports.RouteTree = exports.RouteLeaf = exports.IsAllowedExt = void 0;
const shared_1 = require("./shared");
const render_args_1 = require("./render-args");
const BlankRoute = __importStar(require("./404-route"));
function IsAllowedExt(ext) {

@@ -22,5 +47,2 @@ if (ext[0] !== ".")

exports.IsAllowedExt = IsAllowedExt;
async function blankOutlet() {
return "";
}
class RouteLeaf {

@@ -31,24 +53,28 @@ constructor(module, mask) {

}
makeOutlet(args, outlet, depth) {
const renderer = this.module.Render || blankOutlet;
const catcher = this.module.CatchError;
return async () => {
try {
args.depth = depth;
return await renderer(args, outlet);
async render(args, mask, routeName) {
try {
if (this.module.Auth)
return await this.module.Auth(args);
if (mask === render_args_1.MaskType.show) {
if (this.module.Render)
return await this.module.Render(routeName, args);
}
catch (e) {
if (e instanceof shared_1.Redirect || e instanceof shared_1.Override)
throw e;
const err = (e instanceof shared_1.ErrorResponse) ? e :
new shared_1.ErrorResponse(500, "Runtime Error", e);
if (catcher) {
args.depth = depth;
return await catcher(args, err);
}
throw err;
else {
return await args.Outlet();
}
};
}
catch (e) {
if (e instanceof shared_1.Redirect || e instanceof shared_1.Override)
throw e;
const err = (e instanceof shared_1.ErrorResponse) ? e :
new shared_1.ErrorResponse(500, "Runtime Error", e);
if (this.module.CatchError)
return await this.module.CatchError(routeName, args, err);
throw err;
}
return "";
}
}
exports.RouteLeaf = RouteLeaf;
const blankLeaf = new RouteLeaf(BlankRoute, []);
class RouteTree {

@@ -110,14 +136,43 @@ constructor() {

}
calculateDepth(from, to) {
let depth = 0;
if (from.length == 0 || to.length == 0) {
depth = 1;
}
else {
const segmentA = from.splice(0, 1)[0];
const segmentB = to.splice(0, 1)[0];
const subRoute = this.nested.get(segmentA);
if (subRoute && segmentA === segmentB) {
depth = subRoute.calculateDepth(from, to);
}
else if (this.wild) {
depth = this.wild.calculateDepth(from, to);
}
else {
return 1;
}
}
depth++;
return depth;
}
async render(req, res, url) {
const args = new shared_1.RenderArgs(req, res, url);
if (!this.default || !this.default.module.Render) {
return "";
var _a;
if (url.pathname.length != 1 && url.pathname.endsWith("/")) {
return new shared_1.Redirect(url.pathname.slice(0, -1) + url.search);
}
const frags = url.pathname.split('/').slice(1);
if (frags.length === 1 && frags[0] === "") {
frags.splice(0, 1);
}
const args = new render_args_1.RenderArgs(req, res, url);
const from = req.headers['hx-headless'] ?
new URL(((_a = req.headers['hx-current-url']) === null || _a === void 0 ? void 0 : _a.toString()) || "/").pathname :
"";
try {
const out = await this._recursiveRender(args, frags).outlet();
return out;
const depth = BuildOutlet(this, args, from);
if (from) {
res.setHeader('HX-Replace-Url', req.url || "/");
if (depth > 0) {
res.setHeader('HX-Retarget', `#hx-route-${depth.toString(16)}`);
}
res.setHeader('HX-Reswap', "outerHTML");
}
return await args.Outlet();
}

@@ -129,2 +184,3 @@ catch (e) {

return e;
console.error(e);
throw new Error(`Unhandled boil up type ${typeof (e)}: ${e}`);

@@ -134,43 +190,78 @@ }

}
_recursiveRender(args, frags) {
var _a;
let out = {
outlet: blankOutlet,
mask: [],
};
if (frags.length == 0) {
if (!this.default) {
out.outlet = () => {
throw new shared_1.ErrorResponse(404, "Resource Not Found", `Unable to find ${args.url.pathname}`);
};
}
exports.RouteTree = RouteTree;
function BuildOutlet(start, args, fromPath) {
const frags = args.url.pathname.split('/').slice(1);
if (frags.length === 1 && frags[0] === "") {
frags.splice(0, 1);
}
const from = fromPath.split('/').slice(1);
if (from.length === 1 && from[0] === "") {
from.splice(0, 1);
}
let matching = fromPath.length > 0;
let depth = -1;
const stack = [start];
let mask = null;
while (stack.length > 0) {
const cursor = stack.pop();
if (!mask) {
stack.push(cursor);
if (frags.length === 0) {
if (matching && from.length !== 0) {
depth = args._outletChain.length + stack.length;
matching = false;
}
;
if (cursor.default) {
args._addOutlet(cursor.default);
mask = cursor.default.mask;
}
else {
args._addOutlet(blankLeaf);
mask = [];
}
}
else if ((_a = this.default) === null || _a === void 0 ? void 0 : _a.module.Render) {
out.mask = [...this.default.mask];
out.outlet = this.default.makeOutlet(args, out.outlet, out.mask.length);
else {
if (matching && from.length === 0) {
depth = args._outletChain.length + stack.length;
matching = false;
}
const segment = frags.splice(0, 1)[0];
const other = from.splice(0, 1)[0];
const subRoute = cursor.nested.get(segment);
if (subRoute) {
if (matching && segment !== other) {
depth = args._outletChain.length + stack.length;
matching = false;
}
;
stack.push(subRoute);
}
else if (cursor.wild) {
if (matching && cursor.nested.has(other)) {
depth = args._outletChain.length + stack.length;
matching = false;
}
;
args.params[cursor.wildCard] = segment;
stack.push(cursor.wild);
}
else {
args._addOutlet(blankLeaf);
mask = [];
}
}
}
else {
const segment = frags.splice(0, 1)[0];
const subRoute = this.nested.get(segment);
if (subRoute) {
out = subRoute._recursiveRender(args, frags);
if (cursor.route) {
args._addOutlet(cursor.route);
}
else if (this.wild) {
args.params[this.wildCard] = segment;
out = this.wild._recursiveRender(args, frags);
}
else {
out.outlet = () => {
throw new shared_1.ErrorResponse(404, "Resource Not Found", `Unable to find ${args.url.pathname}`);
};
}
}
// Is this route masked out?
const ignored = out.mask.splice(0, 1)[0] === true;
if (!ignored && this.route) {
out.outlet = this.route.makeOutlet(args, out.outlet, out.mask.length);
}
return out;
}
if (matching) {
depth = args._outletChain.length;
}
args._applyMask(mask, depth);
return depth;
}
exports.RouteTree = RouteTree;
/// <reference types="node" />
/// <reference types="node" />
import type http from "node:http";
import { RenderArgs } from "./render-args";
export type Outlet = () => Promise<string>;
export type RenderFunction = (args: RenderArgs, Outlet: Outlet) => Promise<string>;
export type CatchFunction = (args: RenderArgs, err: ErrorResponse) => Promise<string>;
export type CatchFunction = (routeName: string, args: RenderArgs, err: ErrorResponse) => Promise<string>;
export type RenderFunction = (routeName: string, args: RenderArgs) => Promise<string>;
export type AuthFunction = (args: RenderArgs) => Promise<string>;
export type RouteModule = {
Render?: RenderFunction;
CatchError?: CatchFunction;
Auth?: AuthFunction;
};

@@ -26,18 +29,1 @@ export declare class ErrorResponse {

}
type MetaHTML = {
[key: string]: string;
};
export declare class RenderArgs {
req: http.IncomingMessage;
res: http.ServerResponse;
params: MetaHTML;
depth: number;
url: URL;
links: MetaHTML[];
meta: MetaHTML[];
constructor(req: http.IncomingMessage, res: http.ServerResponse, url: URL);
addLinks(links: MetaHTML[], override?: boolean): void;
addMeta(links: MetaHTML[], override?: boolean): void;
renderHeadHTML(): string;
}
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RenderArgs = exports.Override = exports.Redirect = exports.ErrorResponse = void 0;
exports.Override = exports.Redirect = exports.ErrorResponse = void 0;
class ErrorResponse {

@@ -29,66 +29,1 @@ constructor(statusCode, statusMessage, data) {

exports.Override = Override;
const attrRegex = /^[A-z][A-z\-0-9]+$/;
function ValidateMetaHTML(val) {
for (const key in val) {
if (!attrRegex.test(key))
return false;
}
return true;
}
function ValidateMetaHTMLs(val) {
for (const meta of val) {
if (!ValidateMetaHTML(meta))
return false;
}
return true;
}
class RenderArgs {
constructor(req, res, url) {
this.req = req;
this.res = res;
this.url = url;
this.params = {};
this.depth = -1;
this.links = [];
this.meta = [];
}
addLinks(links, override = false) {
if (!ValidateMetaHTMLs(links))
throw new Error(`Provided links have invalid attribute`);
if (override) {
this.links = links;
}
else {
this.links.push(...links);
}
}
addMeta(links, override = false) {
if (!ValidateMetaHTMLs(links))
throw new Error(`Provided links have invalid attribute`);
if (override) {
this.meta = links;
}
else {
this.meta.push(...links);
}
}
renderHeadHTML() {
let out = "";
for (const elm of this.links) {
out += "<link";
for (const attr in elm) {
out += ` ${attr}="${elm[attr].replace(/"/g, "\\\"")}"`;
}
out += "></link>";
}
for (const elm of this.meta) {
out += "<meta";
for (const attr in elm) {
out += ` ${attr}="${elm[attr].replace(/"/g, "\\\"")}"`;
}
out += "></meta>";
}
return out;
}
}
exports.RenderArgs = RenderArgs;
{
"name": "htmx-router",
"version": "0.0.5",
"version": "0.0.6",
"description": "A remix.js style file path router for htmX websites",

@@ -28,4 +28,5 @@ "main": "./bin/index.js",

"dependencies": {
"csstype": "^3.1.2"
"csstype": "^3.1.2",
"typed-html": "^3.0.1"
}
}
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