CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-hbs

Express.js template engine plugin for Handlebars

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

helper-management.mddocs/

Helper Management

Register and manage Handlebars helper functions, including asynchronous helpers with callback support for complex operations.

Capabilities

Synchronous Helpers

Register standard Handlebars helpers that return values immediately.

/**
 * Register synchronous helper function
 * @param name - Helper name to use in templates
 * @param helper - Helper function that returns a value
 */
function registerHelper(name, helper);

Usage Examples:

const hbs = require('hbs');

// Simple string helper
hbs.registerHelper('uppercase', function(str) {
  return str.toUpperCase();
});

// Helper with multiple parameters
hbs.registerHelper('link_to', function(title, url) {
  return '<a href="' + url + '">' + title + '</a>';
});

// Block helper
hbs.registerHelper('list', function(items, options) {
  let out = '<ul>';
  for (let i = 0; i < items.length; i++) {
    out += '<li>' + options.fn(items[i]) + '</li>';
  }
  return out + '</ul>';
});

// Helper with context access
hbs.registerHelper('conditional', function(v1, operator, v2, options) {
  switch (operator) {
    case '==':
      return (v1 == v2) ? options.fn(this) : options.inverse(this);
    case '!=':
      return (v1 != v2) ? options.fn(this) : options.inverse(this);
    default:
      return options.inverse(this);
  }
});

In Templates:

<!-- Simple helper -->
{{uppercase "hello world"}}
<!-- Output: HELLO WORLD -->

<!-- Helper with parameters -->
{{{link_to "Google" "https://google.com"}}}
<!-- Output: <a href="https://google.com">Google</a> -->

<!-- Block helper -->
{{#list people}}
  {{name}} - {{age}}
{{/list}}

<!-- Conditional helper -->
{{#conditional score ">=" 90}}
  Grade: A
{{else}}
  Grade: B or lower
{{/conditional}}

Asynchronous Helpers

Register helpers that perform asynchronous operations like API calls, file I/O, or database queries.

/**
 * Register asynchronous helper function
 * @param name - Helper name to use in templates
 * @param helper - Helper function that calls callback with result
 */
function registerAsyncHelper(name, helper);

Usage Examples:

const hbs = require('hbs');
const fs = require('fs');

// File reading helper
hbs.registerAsyncHelper('readFile', function(filename, callback) {
  fs.readFile(filename, 'utf8', (err, data) => {
    if (err) {
      callback('Error reading file');
    } else {
      callback(data);
    }
  });
});

// API call helper
hbs.registerAsyncHelper('fetchUserName', function(userId, callback) {
  // Simulate API call
  setTimeout(() => {
    const users = { 1: 'Alice', 2: 'Bob', 3: 'Charlie' };
    callback(users[userId] || 'Unknown User');
  }, 100);
});

// Helper with multiple parameters
hbs.registerAsyncHelper('formatDate', function(date, format, callback) {
  // Simulate async date formatting
  process.nextTick(() => {
    const formatted = new Date(date).toLocaleDateString();
    callback(formatted);
  });
});

// Helper with context access
hbs.registerAsyncHelper('checkPermission', function(action, callback) {
  // this.user would be available from template context
  const user = this.user || {};
  
  // Simulate permission check
  setTimeout(() => {
    const hasPermission = user.permissions && user.permissions.includes(action);
    callback(hasPermission ? 'Allowed' : 'Denied');
  }, 50);
});

In Templates:

<!-- File content helper -->
<pre>{{readFile "config.txt"}}</pre>

<!-- User data helper -->
<p>Welcome, {{fetchUserName userId}}!</p>

<!-- Date formatting helper -->
<span>Created: {{formatDate createdAt "short"}}</span>

<!-- Permission helper -->
<div class="status">{{checkPermission "admin"}}</div>

Handlebars Access

Direct access to the underlying Handlebars instance for advanced operations.

/**
 * Direct access to Handlebars instance
 * @type HandlebarsStatic
 */
handlebars;

Usage Examples:

const hbs = require('hbs');

// Access Handlebars directly
const SafeString = hbs.handlebars.SafeString;
const Utils = hbs.handlebars.Utils;

// Use Handlebars SafeString in helpers
hbs.registerHelper('safeHtml', function(html) {
  return new SafeString(html);
});

// Use Handlebars utilities
hbs.registerHelper('escapeExpression', function(str) {
  return hbs.handlebars.Utils.escapeExpression(str);
});

// Register helper on Handlebars directly (not recommended)
hbs.handlebars.registerHelper('directHelper', function() {
  return 'Registered directly';
});

Helper Context and Options

All helpers receive the current template context as this and access to Handlebars options.

Context Access

hbs.registerHelper('contextExample', function() {
  // Access current template data
  console.log('Current context:', this);
  
  // Access specific properties
  return this.someProperty || 'default';
});

Block Helper Options

Block helpers receive an options parameter with additional functionality:

hbs.registerHelper('blockExample', function(options) {
  // options.fn - renders the block content
  // options.inverse - renders the {{else}} content
  // options.hash - contains hash parameters
  // options.data - contains @index, @first, @last, etc.
  
  return options.fn(this); // Render block content
});

Hash Parameters

Helpers can accept named parameters via hash notation:

hbs.registerHelper('withDefaults', function(options) {
  const defaults = {
    color: 'blue',
    size: 'medium',
    ...options.hash // Override with provided values
  };
  
  return `<div class="${defaults.color} ${defaults.size}">Content</div>`;
});

In Template:

{{withDefaults color="red" size="large"}}
<!-- Output: <div class="red large">Content</div> -->

Async Helper Coordination

Asynchronous helpers are automatically coordinated so templates wait for all async operations to complete before rendering.

Async Flow:

  1. Template parsing identifies async helper calls
  2. Each async helper receives a unique callback
  3. Template rendering waits for all callbacks to complete
  4. Final template output includes all async results
  5. Placeholders are replaced with actual values

Multiple Async Helpers:

hbs.registerAsyncHelper('slowHelper1', function(callback) {
  setTimeout(() => callback('Result 1'), 100);
});

hbs.registerAsyncHelper('slowHelper2', function(callback) {
  setTimeout(() => callback('Result 2'), 200);
});

In Template:

<p>{{slowHelper1}} and {{slowHelper2}}</p>
<!-- Template waits for both helpers, then outputs: -->
<!-- <p>Result 1 and Result 2</p> -->

docs

express-integration.md

helper-management.md

index.md

partial-management.md

tile.json