Logic-less {{mustache}} templates with JavaScript
npx @tessl/cli install tessl/npm-mustache@4.2.0Mustache.js is a zero-dependency implementation of the Mustache template system in JavaScript. It provides logic-less templating with support for variable interpolation, sections, partials, and custom delimiters, compatible with web browsers, Node.js, and CouchDB views.
npm install mustacheESM (import):
import Mustache from "mustache";CommonJS (require):
const Mustache = require("mustache");
// or
var Mustache = require("mustache");AMD:
define(["mustache"], function(Mustache) {
// Use Mustache
});Browser global:
<script src="https://unpkg.com/mustache@latest"></script>
<script>
// Mustache is available globally
</script>import Mustache from "mustache";
// Simple template rendering
const template = "Hello {{name}}!";
const view = { name: "World" };
const output = Mustache.render(template, view);
// Output: "Hello World!"
// Template with sections
const listTemplate = `
{{#users}}
<li>{{name}} - {{email}}</li>
{{/users}}
`;
const listView = {
users: [
{ name: "Alice", email: "alice@example.com" },
{ name: "Bob", email: "bob@example.com" }
]
};
const listOutput = Mustache.render(listTemplate, listView);
// Using partials
const partials = {
header: "<h1>{{title}}</h1>",
footer: "<footer>{{year}}</footer>"
};
const mainTemplate = "{{>header}}<p>Content</p>{{>footer}}";
const mainView = { title: "My Page", year: 2024 };
const result = Mustache.render(mainTemplate, mainView, partials);Mustache.js is built around several key components:
Primary function for rendering Mustache templates with data and optional partials.
/**
* Renders the template with the given view, partials, and config
* @param {string} template - The Mustache template string
* @param {any} view - The view object containing data for rendering
* @param {object|function} [partials] - Optional object containing partial templates or function to load partials
* @param {object|array} [config] - Optional configuration object or array for custom tags/escaping
* @returns {string} The rendered string
*/
Mustache.render(template, view, partials, config)Usage Examples:
// Basic rendering
const output = Mustache.render("{{greeting}} {{name}}!", {
greeting: "Hello",
name: "World"
});
// With partials object
const partials = { user: "{{name}} ({{email}})" };
const result = Mustache.render("User: {{>user}}", {
name: "Alice",
email: "alice@example.com"
}, partials);
// With partials function
const partialLoader = (name) => {
const templates = {
header: "<h1>{{title}}</h1>",
footer: "<p>{{copyright}}</p>"
};
return templates[name];
};
const page = Mustache.render("{{>header}}Content{{>footer}}", {
title: "My Site",
copyright: "2024"
}, partialLoader);
// With custom configuration
const customTags = ["<%", "%>"];
const erbStyle = Mustache.render("<% name %>", { name: "Alice" }, {}, customTags);
// With escape configuration
const config = {
tags: ["{{", "}}"],
escape: (text) => text.toUpperCase() // Custom escaping
};
const escaped = Mustache.render("{{name}}", { name: "alice" }, {}, config);Pre-parses and caches templates for improved performance on repeated renders.
/**
* Parses and caches the given template and returns the array of tokens
* @param {string} template - The Mustache template string to parse
* @param {string[]} [tags] - Optional array of opening and closing tag strings
* @returns {array} Array of parsed tokens
*/
Mustache.parse(template, tags)Usage Examples:
// Pre-parse for performance
const template = "Hello {{name}}!";
Mustache.parse(template);
// Later rendering uses cached version
const output = Mustache.render(template, { name: "World" });
// Pre-parse with custom tags
const erbTemplate = "Hello <% name %>!";
const tokens = Mustache.parse(erbTemplate, ["<%", "%>"]);Clears all cached parsed templates to free memory.
/**
* Clears all cached templates in the default writer
* @returns {void}
*/
Mustache.clearCache()Usage Examples:
// Clear cache to free memory
Mustache.clearCache();
// Useful in long-running applications
setInterval(() => {
Mustache.clearCache();
}, 60000); // Clear cache every minuteConfigurable HTML escaping function for secure template rendering.
/**
* HTML escaping function (can be overridden)
* @param {string} text - String to escape
* @returns {string} HTML-escaped string
*/
Mustache.escape(text)Usage Examples:
// Default HTML escaping
const escaped = Mustache.escape("<script>alert('xss')</script>");
// Result: "<script>alert('xss')</script>"
// Override escaping globally
Mustache.escape = function(text) {
return text; // Disable escaping
};
// Or use per-render configuration
const config = {
escape: (text) => text.replace(/</g, "<").replace(/>/g, ">")
};
Mustache.render("{{html}}", { html: "<b>bold</b>" }, {}, config);Configurable template delimiters for custom syntax.
/**
* Default template delimiter tags
* @type {string[]} Array containing opening and closing delimiter strings
*/
Mustache.tagsUsage Examples:
// View current tags
console.log(Mustache.tags); // ["{{", "}}"]
// Set custom tags globally
Mustache.tags = ["<%", "%>"];
const output = Mustache.render("<% name %>", { name: "Alice" });
// Reset to default
Mustache.tags = ["{{", "}}"];
// Or use per-render tags
const result = Mustache.render("<% greeting %>", { greeting: "Hello" }, {}, ["<%", "%>"]);Advanced cache management with custom storage strategies.
/**
* Template cache storage object with get/set/clear methods
* @type {object} Cache object with set, get, clear methods
*/
Mustache.templateCache
/**
* Set custom template cache
* @param {object|undefined} cache - Cache object or undefined to disable caching
*/
Mustache.templateCache = cacheUsage Examples:
// View current cache
console.log(Object.keys(Mustache.templateCache._cache));
// Custom cache implementation
const customCache = {
_storage: new Map(),
set(key, value) {
this._storage.set(key, value);
},
get(key) {
return this._storage.get(key);
},
clear() {
this._storage.clear();
}
};
Mustache.templateCache = customCache;
// Disable caching entirely
Mustache.templateCache = undefined;Version and identification information.
/**
* Library name identifier
* @type {string}
*/
Mustache.name
/**
* Library version string
* @type {string}
*/
Mustache.versionUsage Examples:
console.log(`Using ${Mustache.name} version ${Mustache.version}`);
// Output: "Using mustache.js version 4.2.0"Low-level string scanner for custom template parsing.
/**
* String scanner constructor for template parsing
* @param {string} string - String to scan
* @constructor
*/
new Mustache.Scanner(string)
/**
* Check if scanner is at end of string
* @returns {boolean} True if at end of string
*/
Scanner.prototype.eos()
/**
* Try to match regex at current position, advance if matched
* @param {RegExp} re - Regular expression to match
* @returns {string} Matched text or empty string
*/
Scanner.prototype.scan(re)
/**
* Scan until regex matches, return skipped content
* @param {RegExp} re - Regular expression to match
* @returns {string} Skipped content
*/
Scanner.prototype.scanUntil(re)Usage Examples:
const scanner = new Mustache.Scanner("Hello {{name}}!");
// Scan until opening tag
const text = scanner.scanUntil(/\{\{/);
console.log(text); // "Hello "
// Check if at end
console.log(scanner.eos()); // false
// Scan opening tag
const tag = scanner.scan(/\{\{/);
console.log(tag); // "{{"Template rendering context for variable resolution.
/**
* Context constructor for template rendering
* @param {any} view - View object for this context
* @param {Context} [parentContext] - Optional parent context
* @constructor
*/
new Mustache.Context(view, parentContext)
/**
* Create child context with new view
* @param {any} view - View object for child context
* @returns {Context} New child context
*/
Context.prototype.push(view)
/**
* Look up variable name in context hierarchy
* @param {string} name - Variable name to look up
* @returns {any} Variable value or undefined
*/
Context.prototype.lookup(name)Usage Examples:
// Create context
const context = new Mustache.Context({ name: "Alice", age: 30 });
// Look up values
console.log(context.lookup("name")); // "Alice"
console.log(context.lookup("missing")); // undefined
// Create child context
const childContext = context.push({ name: "Bob", city: "NYC" });
console.log(childContext.lookup("name")); // "Bob" (child overrides)
console.log(childContext.lookup("age")); // 30 (inherited from parent)Advanced template writer for custom rendering workflows.
/**
* Writer constructor for template rendering
* @constructor
*/
new Mustache.Writer()
/**
* Clear this writer's template cache
* @returns {void}
*/
Writer.prototype.clearCache()
/**
* Parse template into tokens
* @param {string} template - Template string to parse
* @param {string[]} [tags] - Optional custom tags
* @returns {array} Array of tokens
*/
Writer.prototype.parse(template, tags)
/**
* Render template with view and options
* @param {string} template - Template string
* @param {any} view - View object with data
* @param {any} [partials] - Optional partials
* @param {any} [config] - Optional configuration
* @returns {string} Rendered output
*/
Writer.prototype.render(template, view, partials, config)
/**
* Render pre-parsed tokens
* @param {array} tokens - Pre-parsed tokens
* @param {Context} context - Rendering context
* @param {any} [partials] - Optional partials
* @param {string} [originalTemplate] - Original template string
* @param {any} [config] - Optional configuration
* @returns {string} Rendered output
*/
Writer.prototype.renderTokens(tokens, context, partials, originalTemplate, config)Usage Examples:
// Create custom writer
const writer = new Mustache.Writer();
// Use writer for rendering
const template = "Hello {{name}}!";
const tokens = writer.parse(template);
const context = new Mustache.Context({ name: "World" });
const output = writer.renderTokens(tokens, context);
console.log(output); // "Hello World!"
// Clear only this writer's cache
writer.clearCache();// HTML-escaped output
"{{name}}" // Outputs escaped value
// Unescaped output
"{{{name}}}" // Outputs raw HTML
"{{&name}}" // Alternative unescaped syntax
// Dot notation
"{{user.name}}" // Access nested properties
"{{user.address.city}}" // Deep nesting// Conditional sections
"{{#person}}Hello {{name}}!{{/person}}" // Renders if person exists
// Iteration sections
"{{#users}}{{name}}: {{email}}{{/users}}" // Repeats for each user
// Inverted sections
"{{^users}}No users found{{/users}}" // Renders if users is empty/false// Include partial template
"{{>header}}" // Includes header partial
"{{>user}}" // Includes user partial with current context"{{! This is a comment }}" // Comments are not rendered// Change delimiters within template
"{{=<% %>=}}"
"<% name %>" // Now uses ERB-style delimiters
"<%={{ }}=%>" // Switch back to defaultMustache.js includes a command-line tool for template rendering.
npm install -g mustache# Basic syntax
mustache <view> <template> [output]
# Basic usage - render to stdout
mustache view.json template.mustache
# Render to output file
mustache view.json template.mustache output.html
# Using stdin for view data
cat view.json | mustache - template.mustache > output.html
echo '{"name": "World"}' | mustache - template.mustache
# With single partial
mustache -p header.mustache view.json main.mustache
# With multiple partials
mustache -p header.mustache -p footer.mustache view.json main.mustache
mustache -p partials/nav.mustache -p partials/sidebar.mustache data.json page.mustache
# Show version
mustache --version
mustache -vThe CLI accepts view data in multiple formats:
# JSON file
mustache data.json template.mustache
# JavaScript module (exports object)
mustache data.js template.mustache
mustache data.cjs template.mustache
# Stdin with dash
echo '{"name": "World"}' | mustache - template.mustache
cat view.json | mustache - template.mustacheNote: Partial names are derived from the filename without the .mustache extension. For example, -p header.mustache creates a partial named header.
Common errors and their meanings:
// Template syntax errors
try {
Mustache.render("{{#section}}", {});
} catch (error) {
// Error: Unclosed section "section" at position X
}
// Invalid tags
try {
Mustache.render("template", {}, {}, ["{{", ">>"]);
} catch (error) {
// Error: Invalid tags: {{,>>
}
// Type validation
try {
Mustache.render(123, {});
} catch (error) {
// TypeError: Invalid template! Template should be a "string"
}For TypeScript users, type definitions are available via @types/mustache:
npm install --save-dev @types/mustacheThis provides full type safety and IntelliSense support for all Mustache.js APIs.