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

@bernierllc/template-engine

v0.4.0

Published

A core utility for template rendering and variable substitution with support for Liquid and Handlebars engines

Readme

@bernierllc/template-engine

A core utility for template rendering and variable substitution with support for Liquid and Handlebars engines. Features email-safe and documentation-safe preprocessing, template validation, and syntax checking.

Installation

npm install @bernierllc/template-engine

Usage

Basic Template Rendering

import { TemplateEngine } from '@bernierllc/template-engine';

// Create engine instance
const engine = new TemplateEngine({
  defaultEngine: 'liquid' // or 'handlebars' or 'auto'
});

// Render a template
const template = 'Hello {{name}}, welcome to {{company}}!';
const context = { name: 'John', company: 'BernierLLC' };
const result = engine.render(template, context);
console.log(result); // "Hello John, welcome to BernierLLC!"

Engine-Specific Usage

import { LiquidEngine, HandlebarsEngine } from '@bernierllc/template-engine';

// Liquid engine
const liquidEngine = new LiquidEngine();
const liquidResult = liquidEngine.render(
  'Hello {{ name | upcase }}!',
  { name: 'world' }
);

// Handlebars engine
const hbsEngine = new HandlebarsEngine();
const hbsResult = hbsEngine.render(
  'Hello {{name}}!',
  { name: 'world' }
);

Email-Safe Preprocessing

const emailTemplate = `
  <script>alert('xss')</script>
  <p>Hello {{name}}</p>
  <a href="javascript:void(0)">Click</a>
`;

const safe = engine.preprocess(emailTemplate, {
  emailSafe: true,
  removeScripts: true,
  sanitizeHTML: true
});

const result = engine.render(safe, { name: 'John' });
// Scripts and unsafe content removed

Documentation-Safe Templates

const docsTemplate = `
  # Documentation for {{project}}

  ## Features
  - Feature 1
  - Feature 2
`;

const processed = engine.preprocess(docsTemplate, {
  docsSafe: true,
  engine: 'liquid'
});

const result = engine.render(processed, { project: 'MyApp' });

Template Validation

import { TemplateValidator } from '@bernierllc/template-engine';

const validator = new TemplateValidator();
const template = '{{name}} - {{#if active}}Active{{/if}}';

const validation = validator.validate(template, 'handlebars');

if (!validation.isValid) {
  console.error('Validation errors:', validation.errors);
  console.warn('Warnings:', validation.warnings);
}

console.log('Suggestions:', validation.suggestions);

Custom Helpers and Filters

// Liquid filters
const liquidEngine = new LiquidEngine();
liquidEngine.registerFilter('reverse', (value: string) => {
  return value.split('').reverse().join('');
});

const result = liquidEngine.render(
  '{{ name | reverse }}',
  { name: 'hello' }
); // "olleh"

// Handlebars helpers
const hbsEngine = new HandlebarsEngine();
hbsEngine.registerHelper('loud', (value: string) => {
  return value.toUpperCase() + '!!!';
});

const hbsResult = hbsEngine.render(
  '{{loud greeting}}',
  { greeting: 'hello' }
); // "HELLO!!!"

Auto-Detection

const engine = new TemplateEngine({
  defaultEngine: 'auto' // Automatically detect engine from template syntax
});

// Detects Liquid syntax
const liquidResult = engine.render('{{ name | upcase }}', { name: 'test' });

// Detects Handlebars syntax
const hbsResult = engine.render('{{name}}', { name: 'test' });

API Reference

TemplateEngine

Main class for template rendering with automatic engine detection.

Constructor Options

interface EngineConfig {
  defaultEngine?: 'liquid' | 'handlebars' | 'auto';
  cacheSize?: number; // Number of compiled templates to cache (default: 100)
  strictFilters?: boolean; // Throw on undefined filters (default: false)
  strictVariables?: boolean; // Throw on undefined variables (default: false)
}

Methods

  • render(template: string, context: TemplateContext): string - Render a template with context
  • renderAsync(template: string, context: TemplateContext): Promise<string> - Async rendering
  • compile(template: string): CompiledTemplate - Compile template for reuse
  • preprocess(template: string, options: PreprocessOptions): string - Preprocess for safety
  • registerHelper(name: string, fn: HelperFunction): void - Register custom helper
  • registerFilter(name: string, fn: FilterFunction): void - Register custom filter

LiquidEngine

Liquid template engine implementation with email and docs preprocessing.

Built-in Filters

  • upcase - Convert to uppercase
  • downcase - Convert to lowercase
  • capitalize - Capitalize first letter
  • reverse - Reverse string
  • size - Get length/size
  • default - Provide default value
  • strip_html - Remove HTML tags
  • strip_newlines - Remove newlines
  • date - Format dates

HandlebarsEngine

Handlebars template engine implementation with email and docs preprocessing.

Built-in Helpers

  • if - Conditional rendering
  • unless - Inverse conditional
  • each - Loop over arrays/objects
  • with - Change context
  • eq - Equality comparison
  • ne - Not equal comparison
  • lt, gt, lte, gte - Numeric comparisons
  • and, or, not - Logical operations
  • formatDate - Date formatting
  • uppercase, lowercase - String transformations
  • default - Default values

TemplateValidator

Validates template syntax, security, and best practices.

Validation Types

  • syntax - Template syntax errors
  • variable - Undefined variable warnings
  • security - Security vulnerabilities (XSS, script injection)
  • performance - Performance suggestions
  • best-practice - Best practice recommendations

Methods

  • validate(template: string, engine: string): ValidationResult - Validate template
  • validateSyntax(template: string, engine: string): TemplateError[] - Syntax check only
  • checkSecurity(template: string): TemplateWarning[] - Security check only

Configuration

Preprocessor Options

interface PreprocessOptions {
  engine?: 'liquid' | 'handlebars' | 'auto';
  emailSafe?: boolean; // Remove scripts, sanitize HTML
  docsSafe?: boolean; // Preserve markdown, escape only when needed
  removeScripts?: boolean; // Remove all script tags
  sanitizeHTML?: boolean; // Sanitize HTML attributes
}

Template Context

interface TemplateContext {
  [key: string]: any;
  _meta?: TemplateMetadata; // Optional metadata
  _helpers?: Record<string, HelperFunction>; // Custom helpers
  _filters?: Record<string, FilterFunction>; // Custom filters
}

Integration Status

Logger Integration

  • Status: Not applicable
  • Reason: Core utility package with no logging requirements. Silent operation by design.

Docs-Suite Integration

  • Status: Ready
  • Format: TypeDoc + Markdown
  • Documentation: Full API documentation with TypeScript types and usage examples

NeverHub Integration

  • Status: Not applicable
  • Reason: Pure utility package with no service discovery or event requirements. Operates independently without runtime dependencies.

Security Considerations

The template engine includes built-in security features:

  1. Script Removal: Automatically removes <script> tags when emailSafe is enabled
  2. XSS Prevention: Detects potential XSS vulnerabilities in templates
  3. HTML Sanitization: Removes dangerous HTML attributes (onclick, onerror, etc.)
  4. Variable Escaping: Auto-escapes variables by default in both engines
  5. Validation: Syntax and security validation before rendering

Performance

  • Template Caching: Compiled templates are cached (configurable size)
  • Lazy Loading: Engines loaded only when needed
  • Async Support: Non-blocking rendering with renderAsync
  • Memory Efficient: LRU cache prevents memory leaks

Best Practices

  1. Always validate templates before rendering user-provided content
  2. Use email-safe preprocessing for email templates
  3. Enable strict mode in production for early error detection
  4. Cache compiled templates for frequently used templates
  5. Use async rendering for large templates or complex contexts

Examples

See the examples/ directory for complete working examples:

  • basic-usage.ts - Simple template rendering
  • email-templates.ts - Email-safe preprocessing
  • custom-helpers.ts - Custom helpers and filters
  • validation.ts - Template validation
  • advanced.ts - Advanced features and patterns

License

Copyright (c) 2025 Bernier LLC. All rights reserved.