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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lara-node/html

v0.2.1

Published

Handlebars-based HTML template rendering with Express response helpers for Lara-Node

Readme

@lara-node/html

Handlebars-based HTML template rendering with a rich set of built-in helpers, minification, sanitization, and Express response helpers for Lara-Node.

Installation

npm install @lara-node/html
# or
pnpm add @lara-node/html

Peer dependencies: express


Quick Start

import { Html } from '@lara-node/html';

// Inline template rendering
const html = Html.render('<h1>Hello, {{name}}!</h1>', { name: 'World' });

// File-based template
const page = await Html.renderFile('/views/user.hbs', { user });

// Express route
app.get('/dashboard', async (req, res) => {
  await Html.fileResponse(res, '/views/dashboard.hbs', { user: req.user });
});

Template Rendering

Html.render(template, data?)

Render a Handlebars template string synchronously. Results are cached automatically.

const html = Html.render(
  '<p>{{uppercase name}} — {{date joinedAt}}</p>',
  { name: 'alice', joinedAt: '2024-01-15' }
);
// <p>ALICE — 1/15/2024</p>

Html.renderFile(filePath, data?)

Read and render a template file (async).

const html = await Html.renderFile('/views/invoice.hbs', {
  invoice,
  company: config.company,
});

Html.compile(template)

Compile a template string into a reusable function for repeated renders.

const tpl = Html.compile('<li>{{name}}: {{score}}</li>');
const rows = users.map((u) => tpl(u)).join('');

Template Cache

The package caches compiled templates by template source string for performance.

Html.cacheSize();  // number of cached templates
Html.clearCache(); // reset the cache

Built-in Handlebars Helpers

All helpers are registered globally and available in every template.

String Helpers

| Helper | Usage | Example output | |--------|-------|----------------| | uppercase | {{uppercase str}} | HELLO | | lowercase | {{lowercase str}} | hello | | capitalize | {{capitalize str}} | Hello | | titleCase | {{titleCase str}} | Hello World | | truncate | {{truncate str 50 '...'}} | Hello... | | slugify | {{slugify str}} | hello-world | | nl2br | {{nl2br str}} | Hello<br>World | | replace | {{replace str 'a' 'b'}} | replaces a with b | | startsWith | {{startsWith str 'He'}} | true | | endsWith | {{endsWith str 'lo'}} | true | | padStart | {{padStart str 5 '0'}} | 00042 | | padEnd | {{padEnd str 5 '-'}} | 42--- | | repeat | {{repeat '* ' 3}} | * * * | | join | {{join array ', '}} | a, b, c |

Number Helpers

| Helper | Usage | Example output | |--------|-------|----------------| | currency | {{currency price symbol='$'}} | $9.99 | | numberFormat | {{numberFormat n decimals=2}} | 1,234.50 | | percentage | {{percentage value total}} | 45.5% | | round | {{round n 2}} | 3.14 | | abs | {{abs n}} | 42 | | add | {{add a b}} | 10 | | sub | {{sub a b}} | 5 | | mul | {{mul a b}} | 20 | | div | {{div a b}} | 2.5 |

Date Helpers

| Helper | Usage | Example output | |--------|-------|----------------| | date | {{date value locale='en-US'}} | 1/15/2024 | | dateTime | {{dateTime value}} | 1/15/2024, 3:00:00 PM |

Logic & Comparison Helpers

| Helper | Usage | Description | |--------|-------|-------------| | eq | {{#if (eq a b)}} | Strict equality | | neq | {{#if (neq a b)}} | Strict inequality | | gt | {{#if (gt a b)}} | Greater than | | gte | {{#if (gte a b)}} | Greater than or equal | | lt | {{#if (lt a b)}} | Less than | | lte | {{#if (lte a b)}} | Less than or equal | | and | {{#if (and a b)}} | Logical AND | | or | {{#if (or a b)}} | Logical OR | | not | {{#if (not a)}} | Logical NOT | | isEmpty | {{#if (isEmpty arr)}} | Empty check (string/array/object) | | includes | {{#if (includes arr item)}} | Array or string includes |

Iteration Helpers

| Helper | Usage | Description | |--------|-------|-------------| | times | {{#times 3}}...{{/times}} | Repeat a block N times (exposes index, first, last) | | range | {{#range 1 5}}{{this}}{{/range}} | Iterate from start to end inclusive |

Miscellaneous

| Helper | Usage | Description | |--------|-------|-------------| | pluralize | {{pluralize count 'item' 'items'}} | Singular/plural based on count | | default | {{default value 'N/A'}} | Fallback for null/undefined/empty | | json | {{{json obj}}} | Pretty-print JSON (triple-mustache to skip escaping) |


Partials & Custom Helpers

// Register a partial
Html.registerPartial('header', '<header><h1>{{title}}</h1></header>');

// Use it: {{> header title="Dashboard"}}

// Register a custom helper
Html.registerHelper('formatPhone', (value: unknown) =>
  String(value).replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3'),
);
// Use it: {{formatPhone phone}}

HTML Generation Utilities

Html.table(data, options?)

Generate an HTML <table> from an array of objects.

const html = Html.table(users, {
  columns: ['id', 'name', 'email'],
  headers: ['#', 'Full Name', 'Email Address'],
  tableAttributes: { class: 'table table-bordered' },
  stripedClass: 'odd',
  caption: 'Active Users',
});

Html.list(items, options?)

Generate a <ul> or <ol> from an array.

// Simple string list
Html.list(['Home', 'About', 'Contact'], { type: 'ol', listClass: 'nav' });

// Object list with links
Html.list(pages, {
  type: 'ul',
  labelKey: 'title',
  hrefKey: 'url',
  itemClass: 'nav-item',
});

Html.pagination(currentPage, totalPages, options)

Generate paginated navigation links.

const nav = Html.pagination(3, 10, {
  urlTemplate: '/users?page={page}',
  navClass: 'pagination',
  linkClass: 'page-link',
  activeClass: 'active',
  disabledClass: 'disabled',
  window: 2,
  prevLabel: '← Prev',
  nextLabel: 'Next →',
});

Html.breadcrumbs(items, options?)

Generate an accessible breadcrumb trail.

const crumbs = Html.breadcrumbs(
  [
    { label: 'Home', href: '/' },
    { label: 'Users', href: '/users' },
    { label: 'Alice' },
  ],
  { separator: ' › ', navClass: 'breadcrumb', ariaLabel: 'breadcrumb' },
);

Html.meta(tags)

Generate <meta> tags from a descriptor array.

const meta = Html.meta([
  { charset: 'UTF-8' },
  { name: 'description', content: 'My awesome app' },
  { name: 'viewport', content: 'width=device-width, initial-scale=1' },
  { property: 'og:title', content: 'My App' },
  { property: 'og:image', content: 'https://example.com/og.png' },
  { httpEquiv: 'X-UA-Compatible', content: 'IE=edge' },
]);

Html.definitionList(data, dlClass?)

Generate a <dl> definition list from a record.

const dl = Html.definitionList({ Name: 'Alice', Role: 'Admin', Status: 'Active' }, 'dl-horizontal');

Html.select(name, options, selected?, attributes?)

Generate a <select> dropdown.

const select = Html.select(
  'country',
  [{ value: 'ke', label: 'Kenya' }, { value: 'ng', label: 'Nigeria' }],
  'ke',
  { class: 'form-select' },
);

Html.tag(tag, content, attributes?) / Html.link() / Html.image()

Low-level element generators.

Html.tag('span', 'Active', { class: 'badge badge-green' });
Html.link('/profile', 'View Profile', { class: 'btn' });
Html.image('/avatar.png', 'User avatar', { class: 'avatar', width: '64' });

Minification

const minified = Html.minify(html, {
  removeComments: true,       // default: true
  collapseWhitespace: true,   // default: true
  removeEmptyAttributes: true, // default: false
});

Sanitization

Removes dangerous tags, event handlers, and javascript: URIs.

const safe = Html.sanitize(userInput, {
  // Completely removed (including inner content)
  blockedTags: ['script', 'style', 'iframe', 'form'],
  // Only these tags are allowed (others are stripped, inner text preserved)
  allowedTags: ['p', 'b', 'i', 'a', 'ul', 'li'],
  // Additional attributes to strip
  stripAttributes: ['style'],
});

Text Utilities

Html.strip(html)

Remove all HTML tags and decode common entities.

const text = Html.strip('<p>Hello <b>World</b></p>');
// "Hello World"

Html.excerpt(html, length?, suffix?)

Extract a plain-text excerpt from HTML content.

const summary = Html.excerpt(articleHtml, 160, '…');

File Output

// Save rendered template to disk
await Html.store('/public/report.html', template, { report });

Express Helpers

// Render inline template → HTML response
Html.response(res, '{{> layout}}', data);

// Render template file → HTML response
await Html.fileResponse(res, '/views/page.hbs', data);

// Send HTML file download
Html.download(res, generatedHtml, 'report.html');

// Send JSON response
Html.json(res, { success: true, data: users }, 200);

License

MIT