Asynchronous templates for the browser and server (LinkedIn fork)
npx @tessl/cli install tessl/npm-dustjs-linkedin@3.0.0Dustjs-LinkedIn is an asynchronous JavaScript templating system designed for both browser and server-side environments. It provides a comprehensive templating syntax with compiled templates for high performance, supports streaming output, and includes features like conditional logic, loops, partials, helpers, and filters. This package is LinkedIn's actively maintained fork of the original Dust.js project.
npm install dustjs-linkedinconst dust = require('dustjs-linkedin');For browser environments:
<script src="node_modules/dustjs-linkedin/lib/dust.js"></script>With full compiler support:
const dust = require('dustjs-linkedin');
// Includes: dust (core), dust.compile, dust.parseconst dust = require('dustjs-linkedin');
// Compile and register a template
const source = "Hello {name}! You have {count} {count eq 1 ? 'message' : 'messages'}.";
const compiled = dust.compile(source, 'greeting');
dust.loadSource(compiled);
// Render with data
dust.render('greeting', { name: 'John', count: 5 }, (err, output) => {
if (err) throw err;
console.log(output); // "Hello John! You have 5 messages."
});
// Stream rendering
dust.stream('greeting', { name: 'Jane', count: 1 })
.on('data', chunk => process.stdout.write(chunk))
.on('end', () => console.log('\nDone!'));
// Output: "Hello Jane! You have 1 message."Dustjs-LinkedIn is built around several key components:
dustc) for pre-compiling templatesinterface DustConfig {
whitespace: boolean; // Preserve whitespace in templates
amd: boolean; // Register templates as AMD modules
cjs: boolean; // Register templates as CommonJS modules
cache: boolean; // Enable template caching
}
const dust = {
config: DustConfig;
version: string; // Current version: "3.0.1"
cache: { [templateName: string]: TemplateFunction };
helpers: { [helperName: string]: HelperFunction };
filters: FiltersObject;
debugLevel: string; // 'NONE' | 'ERROR' | 'WARN' | 'INFO' | 'DEBUG'
onLoad?: OnLoadFunction;
};Core template rendering functionality with callback and streaming support. Provides synchronous compilation with asynchronous rendering for optimal performance.
function render(nameOrTemplate: string | TemplateFunction, context: any, callback: (err: Error | null, output?: string) => void): void;
function stream(nameOrTemplate: string | TemplateFunction, context: any): DustStream;
function register(name: string, compiledTemplate: TemplateFunction): void;
function loadSource(source: string): TemplateFunction;Template compilation system that converts Dust template syntax into executable JavaScript. Includes source compilation, function compilation, and template registration.
function compile(source: string, name?: string): string;
function compileFn(source: string, name?: string): TemplateFunction;
function loadSource(source: string): TemplateFunction;Template parsing functionality that converts template source code into Abstract Syntax Trees using PEG.js generated parser.
function parse(source: string): ASTNode;Stack-based context system for data resolution with scoping, inheritance, and block management.
function context(global: any, options?: ContextOptions): Context;
function makeBase(global: any, options?: ContextOptions): Context;Extensible helper system for implementing complex template logic and custom functionality.
const helpers: { [name: string]: HelperFunction };
type HelperFunction = (
chunk: Chunk,
context: Context,
bodies: Bodies,
params: Params
) => Chunk;Built-in and extensible filtering system for data transformation with automatic escaping support.
const filters: {
h: (value: any) => string; // HTML escape
j: (value: any) => string; // JavaScript string escape
u: (value: any) => string; // URL encode
uc: (value: any) => string; // URL component encode
js: (value: any) => string; // JSON stringify
jp: (value: any) => any; // JSON parse
};Command-line tools for template compilation, watching, and build integration.
dustc [options] [path1 [path2 path3...]]
Options:
-n, --name Template name for single file
-o, --output Output file for concatenation
-s, --split Separate output files per input
--pwd Base directory for template names
-w, --whitespace Preserve whitespace
-a, --amd Output AMD modules
--cjs Output CommonJS modules
--watch Watch files for changesCore utility functions for type checking, validation, and debugging support.
function isEmpty(value: any): boolean; // Test if value is "dust empty"
function isEmptyObject(obj: any): boolean; // Test if object is empty
function isArray(arr: any): boolean; // Test if value is an array
function isTemplateFn(elem: any): boolean; // Test if value is template function
function isThenable(elem: any): boolean; // Test if value is promise-like
function isStreamable(elem: any): boolean; // Test if value is streamable
function isContext(obj: any): boolean; // Test if value is Context instance
function log(message: string | Error, type?: string): void; // Logging function
function nextTick(callback: Function): void; // Async execution utilitySecurity-focused escaping functions for safe output generation.
function escapeHtml(s: any): string; // HTML entity escaping
function escapeJs(s: string): string; // JavaScript string escaping
function escapeJSON(o: any): string; // JSON escaping
function filter(string: any, auto: string | null, filters: string[], context: Context): string;interface TemplateFunction {
(chunk: Chunk, context: Context): Chunk;
__dustBody: true;
templateName?: string;
}
interface DustStream {
on(event: 'data', callback: (chunk: string) => void): DustStream;
on(event: 'error', callback: (error: Error) => void): DustStream;
on(event: 'end', callback: () => void): DustStream;
emit(type: string, data?: any): boolean;
pipe(writable: any): any;
}
interface Context {
get(path: string | string[], cur?: boolean): any;
push(head: any, idx?: number, len?: number): Context;
pop(): any;
current(): any;
rebase(head: any): Context;
clone(): Context;
getBlock(key: string | Function): Function | boolean;
shiftBlocks(locals: any): Context;
resolve(body: Function): string;
getTemplateName(): string;
}
interface ContextStatic {
wrap(context: any, name?: string): Context;
}
interface Chunk {
write(data: string): Chunk;
end(data?: string): Chunk;
render(body: any, context: Context): Chunk;
map(callback: (chunk: Chunk) => any): Chunk;
tap(tap: Function): Chunk;
untap(): Chunk;
reference(elem: any, context: Context, auto?: string, filters?: string[]): Chunk;
section(elem: any, context: Context, bodies: Bodies, params?: Params): Chunk;
exists(elem: any, context: Context, bodies: Bodies): Chunk;
notexists(elem: any, context: Context, bodies: Bodies): Chunk;
block(elem: Function, context: Context, bodies: Bodies): Chunk;
partial(elem: string | Function, context: Context, partialContext?: Context, params?: Params): Chunk;
helper(name: string, context: Context, bodies: Bodies, params?: Params, auto?: string): Chunk;
await(thenable: any, context: Context, bodies: Bodies, auto?: string, filters?: string[]): Chunk;
stream(stream: any, context: Context, bodies: Bodies, auto?: string, filters?: string[]): Chunk;
capture(body: Function, context: Context, callback: (output: string, chunk: Chunk) => any): Chunk;
setError(err: Error): Chunk;
}
interface Bodies {
block?: TemplateFunction;
else?: TemplateFunction;
}
interface Params {
[key: string]: any;
}
interface ContextOptions {
[key: string]: any;
}
interface ASTNode {
[0]: string; // Node type
[1]?: any; // Node attributes
[2]?: ASTNode[]; // Child nodes
}
interface FiltersObject {
h: (value: any) => string; // HTML escape
j: (value: any) => string; // JavaScript string escape
u: (value: any) => string; // URL encode
uc: (value: any) => string; // URL component encode
js: (value: any) => string; // JSON stringify
jp: (value: any) => any; // JSON parse
[filterName: string]: (value: any) => any;
}
type OnLoadFunction = (
name: string,
callback: (err: Error | null, template?: string | TemplateFunction) => void
) => void | (
name: string,
options: any,
callback: (err: Error | null, template?: string | TemplateFunction) => void
) => void;