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

@ololoepepe/template-renderer

v0.3.0

Published

eta-based template renderer

Readme

@ololoepepe/template-renderer

A thin wrapper around Eta for rendering text templates from a directory.

It fixes one templates directory at construction time, defaults Eta to plain text rather than HTML, and exposes three ways to render: asynchronous, synchronous, and synchronous-but-never-throwing.

Installation

npm install @ololoepepe/template-renderer

Requires Node.js >= 24. Written in TypeScript — the type declarations ship with the package, so there is no @types/… to install.

Usage

import {TemplateRenderer} from '@ololoepepe/template-renderer';

const templateRenderer = new TemplateRenderer('/path/to/templates', {
  defaultExtension: '.txt'
});

const text = await templateRenderer.renderTemplate('mail/welcome.txt', {
  name: 'Andrey'
});

With templates/mail/welcome.txt containing:

Hello, <%= it.name %>!

Template variables arrive as it — that is Eta's varName, and it can be renamed through the settings like any other Eta option.

Template names

A name that does not start with @ is a path relative to the templates directory. Eta refuses to resolve it outside that directory, so a name coming from user input cannot be used to read arbitrary files — the render fails instead.

A name that starts with @ refers to a template registered at runtime with loadTemplateSync, not to a file.

API

new TemplateRenderer(templatesDirectory, templateSettings?)

templatesDirectory is an absolute path to the directory holding the templates. templateSettings is passed through to Eta, so every Eta configuration option works, with three defaults changed:

| Option | Default here | Eta's default | Why | | --- | --- | --- | --- | | autoEscape | false | true | Templates here are plain text more often than HTML. | | cache | true | false | Templates are read from disk once and reused. | | defaultExtension | '' | '.eta' | Template names carry their own extension. |

views is the one option that cannot be set: it is what templatesDirectory fills in. Passing it is a type error.

Turn autoEscape back on when rendering HTML from data you do not control — with the default off, <%= it.name %> interpolates markup verbatim.

The settings type is exported as TemplateRendererSettings.

renderTemplate(templateName, variables?)

Renders asynchronously and resolves with the result. Rejects when the template cannot be found, parsed or rendered. variables defaults to {}.

const text = await templateRenderer.renderTemplate('welcome.txt', {name: 'Andrey'});

renderTemplateSync(templateName, variables?)

The same, synchronously. Throws instead of rejecting.

renderTemplateSafe(templateName, variables?)

Synchronous, and returns null instead of throwing — for the cases where a missing or broken template is an acceptable outcome rather than a failure.

const signature = templateRenderer.renderTemplateSafe('signature.txt') ?? '';

It swallows the error along with its message, so do not use it where you need to know why rendering failed.

loadTemplateSync(name, text)

Registers a template that is not stored in the templates directory — one that came from a database, an API, or a string in the code. Render it by prefixing the name with @:

templateRenderer.loadTemplateSync('welcome', 'Hello, <%= it.name %>!');

templateRenderer.renderTemplateSync('@welcome', {name: 'Andrey'});
await templateRenderer.renderTemplate('@welcome', {name: 'Andrey'});

The name is registered for all three render methods.

Errors

Everything thrown comes from Eta: EtaFileResolutionError for a template that cannot be resolved, EtaNameResolutionError for an unknown @name, EtaParseError for a template that does not compile, and whatever the template code itself throws at render time. They are exported by eta, so a caller that needs to tell them apart can import them from there.

Development

| Command | What it does | | --- | --- | | npm run lint | ESLint over the whole repository. | | npm run typecheck | tsc over src, test and scripts, no emit. | | npm test | The node:test suite; Node runs the TypeScript sources directly. | | npm run build | Compiles src into dist/node/ — the ESM and .d.ts that get published. |

Internal imports go through the #src/*.ts subpath map rather than relative paths. dist/node/ gets its own package.json remapping #src/*.ts to the compiled files, which is what makes those imports resolve for consumers.

License

UNLICENSED — private package.