Velocity.js Template Engine
velocityjs is a JavaScript implementation of the Apache Velocity Template Language (VTL), providing a robust solution for server-side and client-side templating. The current stable version is 2.1.5, offering full compatibility with Java Velocity syntax. It distinguishes itself by separating template parsing into an Abstract Syntax Tree (AST) from the rendering phase, allowing for optimized compilation and execution. Key features include high performance, a lightweight footprint, and comprehensive support for VTL directives such as `#set`, `#foreach`, `#if`, and custom `#macro` definitions. While a specific release cadence isn't detailed, the library appears mature and stable, making it a reliable choice for projects needing VTL capabilities in a JavaScript environment.
Common errors
-
TypeError: (0, velocityjs__WEBPACK_IMPORTED_MODULE_0__.render) is not a function
cause This usually indicates an incorrect import statement, especially in environments that transpile ESM to CJS or when using older Node.js versions or bundler configurations not fully supporting ESM named exports.fixEnsure you are using `import { render } from 'velocityjs'`. If you are in a strict CommonJS environment, try `const { render } = require('velocityjs')` as a fallback, though direct ESM named imports are preferred for this library. -
Error: Undefined variable in development environment: $myVariable
cause The `env: 'development'` option was set during compilation, and a variable (`$myVariable`) referenced in the template was not found in the provided context object.fixEither ensure the `$myVariable` is always present in your context object, or change the `Compile` configuration to remove `env: 'development'` if you prefer missing variables to resolve silently (e.g., to null). -
ReferenceError: $user is not defined at line 1, column 5
cause A variable or property, such as `$user.name`, is being accessed in the template, but the base object (`$user`) is not defined or provided in the rendering context, leading to a `ReferenceError`.fixEnsure that all top-level variables and objects expected by your template are present in the context object passed to `render` or `Compile.render()`. Use `#if($user) $user.name #end` for optional properties.
Warnings
- gotcha HTML escaping for variables is disabled by default. When rendering user-generated content, you must explicitly enable escaping using `escape: true` in the Compile configuration, or manually sanitize output, to prevent Cross-Site Scripting (XSS) vulnerabilities.
- breaking The package requires Node.js version 16.0.0 or higher. Running `velocityjs` in older Node.js environments will result in compatibility errors or failures.
- gotcha When the `Compile` configuration `env` is set to 'development', accessing undefined variables within a template will throw an error instead of silently resolving to `null` or an empty string. While useful for debugging, this can cause unexpected crashes in environments where this behavior is not anticipated.
- gotcha Prior to version 2, `velocityjs` might have primarily supported CommonJS modules. If migrating from an older version or using a build system that defaults to CommonJS, ensure you are using the correct import syntax (named imports via `import { ... } from 'velocityjs'`) as shown in the documentation.
Install
-
npm install velocityjs -
yarn add velocityjs -
pnpm add velocityjs
Imports
- render
const { render } = require('velocityjs')import { render } from 'velocityjs' - parse
const parse = require('velocityjs').parseimport { parse } from 'velocityjs' - Compile
const Compile = require('velocityjs').Compileimport { Compile } from 'velocityjs'
Quickstart
import { render, parse, Compile } from 'velocityjs';
// Simple rendering
const result = render('Hello $name!', { name: 'World' });
console.log(result); // Output: Hello World!
// With macros and custom logic
const macros = {
include: (path) => {
// In a real application, you'd load content from 'path'
// For this example, we'll simulate it.
if (path === 'header.vm') {
return '<h1>Welcome!</h1>';
} else if (path === 'footer.vm') {
return '<p>Copyright 2024</p>';
} else {
return `<!-- Error: ${path} not found -->`;
}
}
};
const template = '#include("header.vm") Hello $name! Today is $date. #include("footer.vm")';
const context = { name: 'Velocity.js User', date: new Date().toLocaleDateString() };
const renderedWithMacros = render(template, context, macros);
console.log(renderedWithMacros);
// Using Compile for performance or advanced parsing
const asts = parse('The answer is $answer.');
const compiledTemplate = new Compile(asts, { escape: true }); // Enable HTML escaping
const compiledResult = compiledTemplate.render({ answer: '<script>alert("XSS!")</script>' });
console.log(compiledResult); // Output: The answer is <script>alert("XSS!")</script>