0
# LiquidJS
1
2
LiquidJS is a simple, expressive and safe Shopify/GitHub Pages compatible template engine in pure JavaScript. It provides a complete implementation of the Shopify Liquid templating language, enabling developers to render dynamic templates with full compatibility across Node.js, browsers, and CLI environments.
3
4
## Package Information
5
6
- **Package Name**: liquidjs
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install liquidjs`
10
11
## Core Imports
12
13
```typescript
14
import { Liquid } from "liquidjs";
15
```
16
17
For specific imports:
18
19
```typescript
20
import { Liquid, Context, Template, LiquidOptions } from "liquidjs";
21
```
22
23
CommonJS:
24
25
```javascript
26
const { Liquid } = require("liquidjs");
27
```
28
29
## Basic Usage
30
31
```typescript
32
import { Liquid } from "liquidjs";
33
34
// Create engine instance
35
const engine = new Liquid();
36
37
// Parse and render template
38
const template = `Hello {{ name | capitalize }}!`;
39
const result = await engine.parseAndRender(template, { name: "world" });
40
// Result: "Hello World!"
41
42
// Parse template once, render multiple times
43
const tpl = engine.parse(`
44
{% for user in users %}
45
<li>{{ user.name }} ({{ user.age }})</li>
46
{% endfor %}
47
`);
48
49
const html = await engine.render(tpl, {
50
users: [
51
{ name: "Alice", age: 25 },
52
{ name: "Bob", age: 30 }
53
]
54
});
55
```
56
57
## Architecture
58
59
LiquidJS is built around several key components:
60
61
- **Liquid Engine**: Main class orchestrating parsing, rendering, and configuration
62
- **Template System**: Parsed template representation with rendering capabilities
63
- **Context Management**: Variable scoping and data access control
64
- **Filter System**: Built-in and custom transformation functions for template outputs
65
- **Tag System**: Built-in and custom logic blocks for template control flow
66
- **Parser/Tokenizer**: Template parsing and tokenization engine
67
- **File System Abstraction**: Template loading from files or in-memory sources
68
69
## Capabilities
70
71
### Core Template Engine
72
73
Main Liquid class providing parsing, rendering, and template management functionality. Supports both sync/async operations and multiple output formats.
74
75
```typescript { .api }
76
class Liquid {
77
constructor(opts?: LiquidOptions);
78
79
// Parsing
80
parse(html: string, filepath?: string): Template[];
81
parseFile(file: string, lookupType?: LookupType): Promise<Template[]>;
82
parseFileSync(file: string, lookupType?: LookupType): Template[];
83
84
// Rendering
85
render(tpl: Template[], scope?: object, renderOptions?: RenderOptions): Promise<any>;
86
renderSync(tpl: Template[], scope?: object, renderOptions?: RenderOptions): any;
87
renderToNodeStream(tpl: Template[], scope?: object, renderOptions?: RenderOptions): NodeJS.ReadableStream;
88
89
// Parse and render combined
90
parseAndRender(html: string, scope?: Context | object, renderOptions?: RenderOptions): Promise<any>;
91
parseAndRenderSync(html: string, scope?: Context | object, renderOptions?: RenderOptions): any;
92
93
// File operations
94
renderFile(file: string, ctx?: Context | object, renderFileOptions?: RenderFileOptions): Promise<any>;
95
renderFileSync(file: string, ctx?: Context | object, renderFileOptions?: RenderFileOptions): any;
96
}
97
```
98
99
[Core Template Engine](./core-engine.md)
100
101
### Configuration
102
103
Comprehensive configuration system for customizing engine behavior, file handling, template processing, and performance settings.
104
105
```typescript { .api }
106
interface LiquidOptions {
107
// File system
108
root?: string | string[];
109
partials?: string | string[];
110
layouts?: string | string[];
111
fs?: FS;
112
113
// Template processing
114
strictFilters?: boolean;
115
strictVariables?: boolean;
116
dynamicPartials?: boolean;
117
jekyllInclude?: boolean;
118
119
// Output control
120
outputEscape?: 'escape' | 'json' | ((value: any) => string);
121
keepOutputType?: boolean;
122
123
// Performance limits
124
parseLimit?: number;
125
renderLimit?: number;
126
memoryLimit?: number;
127
}
128
```
129
130
[Configuration](./configuration.md)
131
132
### Built-in Filters
133
134
Comprehensive collection of 80+ built-in filters for data transformation, organized into categories including array manipulation, string processing, mathematical operations, date formatting, HTML processing, and URL handling.
135
136
```typescript { .api }
137
// Array filters
138
join(array: any[], separator?: string): string;
139
map(array: any[], property: string): any[];
140
where(array: any[], property: string, value?: any): any[];
141
sort(array: any[], property?: string): any[];
142
143
// String filters
144
append(string: string, suffix: string): string;
145
capitalize(string: string): string;
146
downcase(string: string): string;
147
replace(string: string, search: string, replacement: string): string;
148
149
// Math filters
150
abs(number: number): number;
151
plus(number: number, operand: number): number;
152
minus(number: number, operand: number): number;
153
times(number: number, operand: number): number;
154
```
155
156
[Built-in Filters](./filters.md)
157
158
### Built-in Tags
159
160
Complete set of 21 built-in tags providing control flow, variable assignment, template inclusion, and content manipulation capabilities.
161
162
```typescript { .api }
163
// Control flow
164
{% if condition %}...{% endif %}
165
{% unless condition %}...{% endunless %}
166
{% case variable %}{% when value %}...{% endcase %}
167
{% for item in array %}...{% endfor %}
168
169
// Variable assignment
170
{% assign variable = value %}
171
{% capture variable %}...{% endcapture %}
172
{% increment variable %}
173
{% decrement variable %}
174
175
// Template inclusion
176
{% include 'template' %}
177
{% render 'template' with data %}
178
{% layout 'template' %}
179
```
180
181
[Built-in Tags](./built-in-tags.md)
182
183
### Context and Scoping
184
185
Variable management and scoping system providing controlled access to template data with support for nested scopes and variable resolution.
186
187
```typescript { .api }
188
class Context {
189
constructor(scope?: object, options?: NormalizedFullOptions, renderOptions?: RenderOptions);
190
191
get(path: string): any;
192
set(path: string, value: any): void;
193
push(scope: object): Context;
194
pop(): Context | undefined;
195
196
getAll(): object;
197
environments: Scope[];
198
}
199
200
interface Scope {
201
[key: string]: any;
202
}
203
```
204
205
[Context and Scoping](./context-and-scoping.md)
206
207
### Custom Extensions
208
209
System for registering custom filters and tags to extend LiquidJS functionality with domain-specific template processing capabilities.
210
211
```typescript { .api }
212
// Custom filters
213
registerFilter(name: string, filter: FilterImplOptions): void;
214
215
// Custom tags
216
registerTag(name: string, tag: TagClass | TagImplOptions): void;
217
218
// Plugin system
219
plugin(plugin: (this: Liquid, L: typeof Liquid) => void): void;
220
221
interface FilterImplOptions {
222
(this: FilterImpl, value: any, ...args: any[]): any;
223
}
224
225
interface TagImplOptions {
226
parse?(token: TagToken, remainTokens: TopLevelToken[]): void;
227
render?(ctx: Context, emitter: Emitter): any;
228
}
229
```
230
231
[Custom Extensions](./extensions.md)
232
233
### Static Analysis
234
235
Comprehensive template analysis functionality for extracting variable dependencies, performing static analysis, and understanding template requirements without rendering.
236
237
```typescript { .api }
238
// Basic variable analysis
239
variables(template: string | Template[], options?: StaticAnalysisOptions): Promise<string[]>;
240
variablesSync(template: string | Template[], options?: StaticAnalysisOptions): string[];
241
fullVariables(template: string | Template[], options?: StaticAnalysisOptions): Promise<string[]>;
242
fullVariablesSync(template: string | Template[], options?: StaticAnalysisOptions): string[];
243
244
// Variable segments analysis
245
variableSegments(template: string | Template[], options?: StaticAnalysisOptions): Promise<SegmentArray[]>;
246
variableSegmentsSync(template: string | Template[], options?: StaticAnalysisOptions): SegmentArray[];
247
248
// Global variable analysis
249
globalVariables(template: string | Template[], options?: StaticAnalysisOptions): Promise<string[]>;
250
globalVariablesSync(template: string | Template[], options?: StaticAnalysisOptions): string[];
251
globalFullVariables(template: string | Template[], options?: StaticAnalysisOptions): Promise<string[]>;
252
globalFullVariablesSync(template: string | Template[], options?: StaticAnalysisOptions): string[];
253
globalVariableSegments(template: string | Template[], options?: StaticAnalysisOptions): Promise<SegmentArray[]>;
254
globalVariableSegmentsSync(template: string | Template[], options?: StaticAnalysisOptions): SegmentArray[];
255
256
// Comprehensive analysis
257
analyze(template: Template[], options?: StaticAnalysisOptions): Promise<StaticAnalysis>;
258
analyzeSync(template: Template[], options?: StaticAnalysisOptions): StaticAnalysis;
259
parseAndAnalyze(html: string, filename?: string, options?: StaticAnalysisOptions): Promise<StaticAnalysis>;
260
parseAndAnalyzeSync(html: string, filename?: string, options?: StaticAnalysisOptions): StaticAnalysis;
261
262
interface StaticAnalysis {
263
variables: Variables;
264
globals: Variables;
265
locals: Variables;
266
}
267
```
268
269
[Static Analysis](./analysis.md)
270
271
### File System and Templates
272
273
File system abstraction and template loading capabilities supporting both file-based and in-memory template sources.
274
275
```typescript { .api }
276
interface FS {
277
exists(file: string): boolean | Promise<boolean>;
278
readFile(file: string): string | Promise<string>;
279
dirname(file: string): string;
280
sep: string;
281
}
282
283
// Template loading
284
parseFile(file: string, lookupType?: LookupType): Promise<Template[]>;
285
renderFile(file: string, ctx?: Context | object, renderFileOptions?: RenderFileOptions): Promise<any>;
286
287
enum LookupType {
288
Root = 'fs',
289
Partials = 'partials',
290
Layouts = 'layouts'
291
}
292
```
293
294
[File System and Templates](./filesystem.md)
295
296
## Types
297
298
### Core Types
299
300
```typescript { .api }
301
interface Template {
302
token: Token;
303
render(ctx: Context, emitter: Emitter): any;
304
}
305
306
interface RenderOptions {
307
sync?: boolean;
308
globals?: object;
309
strictVariables?: boolean;
310
ownPropertyOnly?: boolean;
311
}
312
313
interface RenderFileOptions extends RenderOptions {
314
lookupType?: LookupType;
315
}
316
317
type FilterImplOptions = (this: FilterImpl, value: any, ...args: any[]) => any;
318
type TagClass = new (token: TagToken, remainTokens: TopLevelToken[], liquid: Liquid) => Tag;
319
```
320
321
### Error Types
322
323
```typescript { .api }
324
class LiquidError extends Error {
325
originalError?: Error;
326
token?: Token;
327
}
328
329
class ParseError extends LiquidError {}
330
class RenderError extends LiquidError {}
331
class UndefinedVariableError extends LiquidError {}
332
class TokenizationError extends LiquidError {}
333
class AssertionError extends LiquidError {}
334
```