* docs: polish theme, playground, and reference pages Improve readability of the docs site with updated light/dark tokens, shared code-block styling, and playground editors that follow system color scheme. Skip CookieHub on localhost, serve the browser bundle from theme source, and use backtick titles on filter/tag reference pages for consistent navigation. Co-authored-by: Cursor <[email protected]> * docs: highlight npx in bash blocks and polish English copy Use Prism insertBefore for CLI commands like npx, tighten tutorial and reference wording, and keep YAML titles free of backticks so sidebar and page headings stay correct. Co-authored-by: Cursor <[email protected]> * docs: restore lowercase filter and tag titles Titles should match actual filter/tag identifiers (e.g. abs, append), not capitalized English labels. Co-authored-by: Cursor <[email protected]> --------- Co-authored-by: Cursor <[email protected]>
4.7 KiB
title
| title |
|---|
| Render Files |
For a typical project there could be a directory of template files, you'll need to set the template root and call renderFile or renderFileSync to render a specific file.
Render a File
For example you have a directory of templates like this:
.
├── index.js
└── views/
├── hello.liquid
└── world.liquid
hello.liquid contains a single line {%raw%}name: {{name}}{%endraw%}.
Now save the following contents into index.js:
var engine = new Liquid({
root: path.resolve(__dirname, 'views/'), // root for layouts/includes lookup
extname: '.liquid' // used for layouts/includes, defaults ""
});
engine
.renderFile("hello", {name: 'alice'}) // will read and render `views/hello.liquid`
.then(console.log) // outputs "Alice"
Run node index.js and you'll get output like this:
> node index.js
name: alice
Template Lookup
Template file names passed to renderFile, parseFile, renderFileSync, parseFileSync APIs, and include, layout tags are resolved against the root option.
It can be a string-typed path (see above example), or a list of root directories, in which case templates will be looked up in that order. e.g.
var engine = new Liquid({
root: ['views/'],
partials: ['views/partials/'],
layouts: ['views/layouts/'],
extname: '.liquid'
});
{% note tip Relative Paths %}Relative paths in root will be resolved against cwd().{% endnote %}
- When
parse(),render()functions are called, for exampleliquid.renderFile('foo'), templates underrootwill be looked up. - When a partial is requested, for example
{% raw %}{% render "foo" %}{% endraw %}, templates underpartialswill be looked up. - When a layout is requested, for example
{% raw %}{% layout "foo" %}{% endraw %}, templates underlayoutswill be looked up.
When LiquidJS is used in browser, the paths will be resolved based on current location. Here's a demo for browsers: demo/browser.
Abstract File System
LiquidJS defines an abstract file system interface and the default implementation is src/fs/fs-impl.ts for Node.js and src/build/fs-impl-browser.ts for the browser bundle.
The Liquid constructor provides a fs option to specify the file system implementation. It's supposed to be used to define customized template fetching logic, i.e. fetch template from a database table, like:
var engine = new Liquid({
fs: {
readFileSync (file) {
return db.model('Template').findByIdSync(file).text
},
async readFile (file) {
const template = await db.model('Template').findById(file)
return template.text
},
existsSync () {
return true
},
async exists () {
return true
},
contains () {
return true
},
resolve(root, file, ext) {
return file
}
}
});
{% note warn Path Traversal Vulnerability %}The built-in Node fs implements contains() with realpath so templates cannot escape the root via symlinks. The browser bundle omits contains (loader treats paths as allowed). For a custom abstract fs, implement contains unless every resolved path is trusted.{% endnote %}
In-memory Template
To facilitate rendering without files, there's a templates option to specify a mapping of filenames and their content. LiquidJS will read templates from the mapping.
const engine = new Liquid({
templates: {
'views/entry': 'header {% include "../partials/footer" %}',
'partials/footer': 'footer'
}
})
engine.renderFileSync('views/entry'))
// Result: 'header footer'
Note that file system options like root, layouts, partials, relativeReference will be ignored when templates is specified.