mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-15 04:10:40 -07:00
feat: support jekyll-like include, see #433
This commit is contained in:
@@ -5,7 +5,7 @@ title: Include
|
|||||||
{% since %}v1.9.1{% endsince %}
|
{% since %}v1.9.1{% endsince %}
|
||||||
|
|
||||||
{% note warn Deprecated %}
|
{% note warn Deprecated %}
|
||||||
This tag is deprecated, use <a href="./render.html">render</a> tag instead for better encapsulation.
|
This tag is deprecated, use <a href="./render.html">render</a> tag instead, which contains all the features of `include` and provides better encapsulation.
|
||||||
{% endnote %}
|
{% endnote %}
|
||||||
|
|
||||||
## Include a Template
|
## Include a Template
|
||||||
@@ -16,7 +16,7 @@ Renders a partial template from the template [roots][root].
|
|||||||
{% include 'footer.liquid' %}
|
{% include 'footer.liquid' %}
|
||||||
```
|
```
|
||||||
|
|
||||||
When the [extname][extname] option is set, the above `.liquid` extension can be omitted and writes:
|
If [extname][extname] option is set, the above `.liquid` extension becomes optional:
|
||||||
|
|
||||||
```liquid
|
```liquid
|
||||||
{% include 'footer' %}
|
{% include 'footer' %}
|
||||||
@@ -44,5 +44,32 @@ A single object can be passed to a snippet by using the `with...as` syntax:
|
|||||||
|
|
||||||
In the example above, the `product` variable in the partial template will hold the value of `featured_product` in the parent template.
|
In the example above, the `product` variable in the partial template will hold the value of `featured_product` in the parent template.
|
||||||
|
|
||||||
|
## Outputs & Filters
|
||||||
|
|
||||||
|
When filename is specified as literal string, it supports Liquid output and filter syntax. Useful when concatenating strings for a complex filename.
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% include "prefix/{{name | append: \".html\"}}" %}
|
||||||
|
```
|
||||||
|
|
||||||
|
{% note info Escaping %}
|
||||||
|
In LiquidJS, `"` within quoted string literals need to be escaped. Adding a slash before the quote, e.g. `\"`. Using Jekyll-like filenames can make this easier, see below.
|
||||||
|
{% endnote %}
|
||||||
|
|
||||||
|
## Jekyll-like filenames
|
||||||
|
|
||||||
|
Setting [dynamicPartials][dynamicPartials] to `false` will enable Jekyll-like includes, file names are specified as literal string. And it also supports Liquid outputs and filters.
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% include prefix/{{ page.my_variable }}/suffix %}
|
||||||
|
```
|
||||||
|
|
||||||
|
This way, you don't need to escape `"` in the filename expression.
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% include prefix/{{name | append: ".html"}} %}
|
||||||
|
```
|
||||||
|
|
||||||
[extname]: ../api/interfaces/liquid_options_.liquidoptions.html#Optional-extname
|
[extname]: ../api/interfaces/liquid_options_.liquidoptions.html#Optional-extname
|
||||||
[root]: ../api/interfaces/liquid_options_.liquidoptions.html#Optional-root
|
[root]: ../api/interfaces/liquid_options_.liquidoptions.html#Optional-root
|
||||||
|
[dynamicPartials]: ../api/interfaces/liquid_options_.liquidoptions.html#dynamicPartials
|
||||||
|
|||||||
+74
-33
@@ -4,21 +4,67 @@ title: Layout
|
|||||||
|
|
||||||
{% since %}v1.9.1{% endsince %}
|
{% since %}v1.9.1{% endsince %}
|
||||||
|
|
||||||
## Using a Layout Template
|
## Using a Layout
|
||||||
|
|
||||||
Renders current template inside a layout template from the template [roots][root].
|
Introduce a layout template for the current template to render in. The directory for layout files are defined by [layouts][layouts] or [root][root].
|
||||||
|
|
||||||
```liquid
|
```liquid
|
||||||
{% layout 'footer.liquid' %}
|
// default-layout.liquid
|
||||||
|
Header
|
||||||
|
{% block %}{% endblock %}
|
||||||
|
Footer
|
||||||
|
|
||||||
|
// page.liquid
|
||||||
|
{% layout "default-layout.liquid" %}
|
||||||
|
{% block %}My page content{% endblock %}
|
||||||
|
|
||||||
|
// result
|
||||||
|
Header
|
||||||
|
My page content
|
||||||
|
Footer
|
||||||
```
|
```
|
||||||
|
|
||||||
When the [extname][extname] option is set, the above `.liquid` extension can be omitted and writes:
|
If [extname][extname] option is set, the `.liquid` extension becomes optional:
|
||||||
|
|
||||||
```liquid
|
```liquid
|
||||||
{% layout 'footer' %}
|
{% layout 'default-layout' %}
|
||||||
```
|
```
|
||||||
|
|
||||||
When a partial template is rendered by `layout`, the code inside it can access its caller's variables but its parent cannot access variables defined inside a included template.
|
{% note info Scoping %}
|
||||||
|
When a partial template is rendered by <code>layout</code>, its template have access for its caller's variables but not vice versa. Variables defined in layout will be popped out before control returning to its caller.
|
||||||
|
{% endnote %}
|
||||||
|
|
||||||
|
## Multiple Blocks
|
||||||
|
|
||||||
|
The layout file can contain multiple blocks, each with a specified name. The following snippets yield same result as in the above example.
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
// default-layout.liquid
|
||||||
|
{% block header %}{% endblock %}
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
{% block footer %}{% endblock %}
|
||||||
|
|
||||||
|
// page.liquid
|
||||||
|
{% layout "default-layout.liquid" %}
|
||||||
|
{% block header %}Header{% endblock %}
|
||||||
|
{% block content %}My page content{% endblock %}
|
||||||
|
{% block footer %}Footer{% endblock %}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Default Block Contents
|
||||||
|
|
||||||
|
In the above layout files, blocks has empty contents. But it's not necessarily be empty, in which case, the block contents in layout files will be used as default templates. The following snippets are also equivalent to the above examples:
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
// default-layout.liquid
|
||||||
|
{% block header %}Header{% endblock %}
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
{% block footer %}Footer{% endblock %}
|
||||||
|
|
||||||
|
// page.liquid
|
||||||
|
{% layout "default-layout.liquid" %}
|
||||||
|
{% block content %}My page content{% endblock %}
|
||||||
|
```
|
||||||
|
|
||||||
## Passing Variables
|
## Passing Variables
|
||||||
|
|
||||||
@@ -29,38 +75,33 @@ Variables defined in current template can be passed to a the layout template by
|
|||||||
{% layout 'name', my_variable: my_variable, my_other_variable: 'oranges' %}
|
{% layout 'name', my_variable: my_variable, my_other_variable: 'oranges' %}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Blocks
|
## Outputs & Filters
|
||||||
|
|
||||||
The layout file can contain multiple `block`s which will be populated by the child template (the caller). For example we have a `default-layout.liquid` file with the following contents:
|
When filename is specified as literal string, it supports Liquid output and filter syntax. Useful when concatenating strings for a complex filename.
|
||||||
|
|
||||||
```
|
```liquid
|
||||||
Header
|
{% layout "prefix/{{name | append: \".html\"}}" %}
|
||||||
{% block content %}My default content{% endblock %}
|
|
||||||
Footer
|
|
||||||
```
|
```
|
||||||
|
|
||||||
And it's called by a `page.liquid` file with `layout` tag:
|
{% note info Escaping %}
|
||||||
|
In LiquidJS, `"` within quoted string literals need to be escaped. Adding a slash before the quote, e.g. `\"`. Using Jekyll-like filenames can make this easier, see below.
|
||||||
```
|
|
||||||
{% layout "default-layout" %}
|
|
||||||
{% block content %}My page content{% endblock %}
|
|
||||||
```
|
|
||||||
|
|
||||||
The render result of `page.liquid` will be :
|
|
||||||
|
|
||||||
```
|
|
||||||
Header
|
|
||||||
My page content
|
|
||||||
Footer
|
|
||||||
```
|
|
||||||
|
|
||||||
{% note tip Block %}
|
|
||||||
<ul>
|
|
||||||
<li>Multiple blocks can be defined within a layout template;</li>
|
|
||||||
<li>The block name is optional when there's only one block.</li>
|
|
||||||
<li>The block contents will fallback to parent's corresponding block if not provided by child template.</li>
|
|
||||||
</ul>
|
|
||||||
{% endnote %}
|
{% endnote %}
|
||||||
|
|
||||||
|
## Jekyll-like Filenames
|
||||||
|
|
||||||
|
Setting [dynamicPartials][dynamicPartials] to `false` will enable Jekyll-like filenames, file names are specified as literal string. And it also supports Liquid outputs and filters.
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% layout prefix/{{ page.my_variable }}/suffix %}
|
||||||
|
```
|
||||||
|
|
||||||
|
This way, you don't need to escape `"` in the filename expression.
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% layout prefix/{{name | append: ".html"}} %}
|
||||||
|
```
|
||||||
|
|
||||||
[extname]: ../api/interfaces/liquid_options_.liquidoptions.html#Optional-extname
|
[extname]: ../api/interfaces/liquid_options_.liquidoptions.html#Optional-extname
|
||||||
[root]: ../api/interfaces/liquid_options_.liquidoptions.html#Optional-root
|
[root]: ../api/interfaces/liquid_options_.liquidoptions.html#Optional-root
|
||||||
|
[layouts]: ../api/interfaces/liquid_options_.liquidoptions.html#Optional-layouts
|
||||||
|
[dynamicPartials]: ../api/interfaces/liquid_options_.liquidoptions.html#dynamicPartials
|
||||||
|
|||||||
@@ -4,26 +4,33 @@ title: Render
|
|||||||
|
|
||||||
{% since %}v9.2.0{% endsince %}
|
{% since %}v9.2.0{% endsince %}
|
||||||
|
|
||||||
## Basic Usage
|
## Render a Template
|
||||||
|
|
||||||
### Render a Template
|
Render a partial template from partials directory specified by [partials][partials] or [root][root].
|
||||||
|
|
||||||
Renders a partial template from the template [root][root]s.
|
|
||||||
|
|
||||||
```liquid
|
```liquid
|
||||||
|
// index.liquid
|
||||||
|
Contents
|
||||||
{% render 'footer.liquid' %}
|
{% render 'footer.liquid' %}
|
||||||
|
|
||||||
|
// footer.liquid
|
||||||
|
Footer
|
||||||
|
|
||||||
|
// result
|
||||||
|
Contents
|
||||||
|
Footer
|
||||||
```
|
```
|
||||||
|
|
||||||
When the [extname][extname] option is set, the above `.liquid` extension can be omitted and writes:
|
If [extname][extname] option is set, the above `.liquid` extension becomes optional:
|
||||||
|
|
||||||
```liquid
|
```liquid
|
||||||
{% render 'footer' %}
|
{% render 'footer' %}
|
||||||
```
|
```
|
||||||
|
|
||||||
{% note info Variable Scope %}
|
{% note info Variable Scope %}
|
||||||
When a partial template is rendered, the code inside it can't access its parent's variables and its variables won't be accessible by its parent. This encapsulation helps make theme code easier to understand and maintain.{% endnote %}
|
When a partial template is rendered, the code inside it can't access its parent's variables and its variables won't be accessible by its parent. This encapsulation makes partials easier to understand and maintain.{% endnote %}
|
||||||
|
|
||||||
### Passing Variables
|
## Passing Variables
|
||||||
|
|
||||||
Variables defined in parent's scope can be passed to a the partial template by listing them as parameters on the render tag:
|
Variables defined in parent's scope can be passed to a the partial template by listing them as parameters on the render tag:
|
||||||
|
|
||||||
@@ -34,6 +41,32 @@ Variables defined in parent's scope can be passed to a the partial template by l
|
|||||||
|
|
||||||
[globals][globals] don't need to be passed down. They are accessible from all files.
|
[globals][globals] don't need to be passed down. They are accessible from all files.
|
||||||
|
|
||||||
|
## Outputs & Filters
|
||||||
|
|
||||||
|
When filename is specified as literal string, it supports Liquid output and filter syntax. Useful when concatenating strings for a complex filename.
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% render "prefix/{{name | append: \".html\"}}" %}
|
||||||
|
```
|
||||||
|
|
||||||
|
{% note info Escaping %}
|
||||||
|
In LiquidJS, `"` within quoted string literals need to be escaped. Adding a slash before the quote, e.g. `\"`. Using Jekyll-like filenames can make this easier, see below.
|
||||||
|
{% endnote %}
|
||||||
|
|
||||||
|
## Jekyll-like Filenames
|
||||||
|
|
||||||
|
Setting [dynamicPartials][dynamicPartials] to `false` will enable Jekyll-like filenames, file names are specified as literal string. And it also supports Liquid outputs and filters.
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% render prefix/{{ page.my_variable }}/suffix %}
|
||||||
|
```
|
||||||
|
|
||||||
|
This way, you don't need to escape `"` in the filename expression.
|
||||||
|
|
||||||
|
```liquid
|
||||||
|
{% render prefix/{{name | append: ".html"}} %}
|
||||||
|
```
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
### The `with` Parameter
|
### The `with` Parameter
|
||||||
@@ -63,4 +96,6 @@ In the example above, the partial template will be rendered once for each `varia
|
|||||||
[forloop]: ./for.html
|
[forloop]: ./for.html
|
||||||
[extname]: ../api/interfaces/liquid_options_.liquidoptions.html#Optional-extname
|
[extname]: ../api/interfaces/liquid_options_.liquidoptions.html#Optional-extname
|
||||||
[root]: ../api/interfaces/liquid_options_.liquidoptions.html#Optional-root
|
[root]: ../api/interfaces/liquid_options_.liquidoptions.html#Optional-root
|
||||||
|
[partials]: ../api/interfaces/liquid_options_.liquidoptions.html#Optional-partials
|
||||||
[globals]: ../api/interfaces/liquid_options_.liquidoptions.html#Optional-globals
|
[globals]: ../api/interfaces/liquid_options_.liquidoptions.html#Optional-globals
|
||||||
|
[dynamicPartials]: ../api/interfaces/liquid_options_.liquidoptions.html#dynamicPartials
|
||||||
|
|||||||
@@ -92,15 +92,20 @@ export function parseFilePath (tokenizer: Tokenizer, liquid: Liquid): ParsedFile
|
|||||||
if (file.getText() === 'none') return null
|
if (file.getText() === 'none') return null
|
||||||
if (TypeGuards.isQuotedToken(file)) {
|
if (TypeGuards.isQuotedToken(file)) {
|
||||||
// for filenames like "files/{{file}}", eval as liquid template
|
// for filenames like "files/{{file}}", eval as liquid template
|
||||||
const tpls = liquid.parse(evalQuotedToken(file))
|
const templates = liquid.parse(evalQuotedToken(file))
|
||||||
// for filenames like "files/file.liquid", extract the string directly
|
return optimize(templates)
|
||||||
if (tpls.length === 1 && TypeGuards.isHTMLToken(tpls[0].token)) return tpls[0].token.getContent()
|
|
||||||
return tpls
|
|
||||||
}
|
}
|
||||||
return file
|
return file
|
||||||
}
|
}
|
||||||
const filepath = tokenizer.readFileName().getText()
|
const tokens = [...tokenizer.readFileNameTemplate(liquid.options)]
|
||||||
return filepath === 'none' ? null : filepath
|
const templates = optimize(liquid.parser.parseTokens(tokens))
|
||||||
|
return templates === 'none' ? null : templates
|
||||||
|
}
|
||||||
|
|
||||||
|
function optimize (templates: Template[]): string | Template[] {
|
||||||
|
// for filenames like "files/file.liquid", extract the string directly
|
||||||
|
if (templates.length === 1 && TypeGuards.isHTMLToken(templates[0].token)) return templates[0].token.getContent()
|
||||||
|
return templates
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderFilePath (file: ParsedFileName, ctx: Context, liquid: Liquid) {
|
export function renderFilePath (file: ParsedFileName, ctx: Context, liquid: Liquid) {
|
||||||
|
|||||||
+14
-10
@@ -33,7 +33,7 @@ export class Tokenizer {
|
|||||||
constructor (
|
constructor (
|
||||||
public input: string,
|
public input: string,
|
||||||
private trie: Trie,
|
private trie: Trie,
|
||||||
private file: string = ''
|
public file: string = ''
|
||||||
) {
|
) {
|
||||||
this.N = input.length
|
this.N = input.length
|
||||||
}
|
}
|
||||||
@@ -119,15 +119,13 @@ export class Tokenizer {
|
|||||||
if (this.rawBeginAt > -1) return this.readEndrawOrRawContent(options)
|
if (this.rawBeginAt > -1) return this.readEndrawOrRawContent(options)
|
||||||
if (this.match(tagDelimiterLeft)) return this.readTagToken(options)
|
if (this.match(tagDelimiterLeft)) return this.readTagToken(options)
|
||||||
if (this.match(outputDelimiterLeft)) return this.readOutputToken(options)
|
if (this.match(outputDelimiterLeft)) return this.readOutputToken(options)
|
||||||
return this.readHTMLToken(options)
|
return this.readHTMLToken([tagDelimiterLeft, outputDelimiterLeft])
|
||||||
}
|
}
|
||||||
|
|
||||||
readHTMLToken (options: NormalizedFullOptions): HTMLToken {
|
readHTMLToken (stopStrings: string[]): HTMLToken {
|
||||||
const begin = this.p
|
const begin = this.p
|
||||||
while (this.p < this.N) {
|
while (this.p < this.N) {
|
||||||
const { tagDelimiterLeft, outputDelimiterLeft } = options
|
if (stopStrings.some(str => this.match(str))) break
|
||||||
if (this.match(tagDelimiterLeft)) break
|
|
||||||
if (this.match(outputDelimiterLeft)) break
|
|
||||||
++this.p
|
++this.p
|
||||||
}
|
}
|
||||||
return new HTMLToken(this.input, begin, this.p, this.file)
|
return new HTMLToken(this.input, begin, this.p, this.file)
|
||||||
@@ -334,10 +332,16 @@ export class Tokenizer {
|
|||||||
return new QuotedToken(this.input, begin, this.p, this.file)
|
return new QuotedToken(this.input, begin, this.p, this.file)
|
||||||
}
|
}
|
||||||
|
|
||||||
readFileName (): IdentifierToken {
|
* readFileNameTemplate (options: NormalizedFullOptions): IterableIterator<TopLevelToken> {
|
||||||
const begin = this.p
|
const { outputDelimiterLeft } = options
|
||||||
while (!(this.peekType() & BLANK) && this.peek() !== ',' && this.p < this.N) this.p++
|
const htmlStopStrings = [',', ' ', outputDelimiterLeft]
|
||||||
return new IdentifierToken(this.input, begin, this.p, this.file)
|
const htmlStopStringSet = new Set(htmlStopStrings)
|
||||||
|
// break on ',' and ' ', outputDelimiterLeft only stops HTML token
|
||||||
|
while (this.p < this.N && !htmlStopStringSet.has(this.peek())) {
|
||||||
|
yield this.match(outputDelimiterLeft)
|
||||||
|
? this.readOutputToken(options)
|
||||||
|
: this.readHTMLToken(htmlStopStrings)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match (word: string) {
|
match (word: string) {
|
||||||
|
|||||||
@@ -161,4 +161,20 @@ describe('Issues', function () {
|
|||||||
const tpl = engine.parse('Welcome to {{ now | date: "%Y-%m-%d" }}!')
|
const tpl = engine.parse('Welcome to {{ now | date: "%Y-%m-%d" }}!')
|
||||||
expect(engine.render(tpl, { now: new Date('2019/02/01') })).to.eventually.equal('Welcome to 2019-02-01')
|
expect(engine.render(tpl, { now: new Date('2019/02/01') })).to.eventually.equal('Welcome to 2019-02-01')
|
||||||
})
|
})
|
||||||
|
it('#433 Support Jekyll-like includes', async () => {
|
||||||
|
const engine = new Liquid({
|
||||||
|
dynamicPartials: false,
|
||||||
|
root: '/tmp',
|
||||||
|
fs: {
|
||||||
|
readFileSync: (file: string) => file,
|
||||||
|
async readFile (file: string) { return `CONTENT for ${file}` },
|
||||||
|
existsSync (file: string) { return true },
|
||||||
|
async exists (file: string) { return true },
|
||||||
|
resolve: (dir: string, file: string) => dir + '/' + file
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const tpl = engine.parse('{% include prefix/{{ my_variable | append: "-bar" }}/suffix %}')
|
||||||
|
const html = await engine.render(tpl, { my_variable: 'foo' })
|
||||||
|
expect(html).to.equal('CONTENT for /tmp/prefix/foo-bar/suffix')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -35,6 +35,14 @@ describe('tags/include', function () {
|
|||||||
const html = await liquid.renderFile('/current.html', { name: 'foo.html' })
|
const html = await liquid.renderFile('/current.html', { name: 'foo.html' })
|
||||||
return expect(html).to.equal('barfoobar')
|
return expect(html).to.equal('barfoobar')
|
||||||
})
|
})
|
||||||
|
it('should allow escape in template string', async function () {
|
||||||
|
mock({
|
||||||
|
'/current.html': 'bar{% include "bar/{{name | append: \\".html\\"}}" %}bar',
|
||||||
|
'/bar/foo.html': 'foo'
|
||||||
|
})
|
||||||
|
const html = await liquid.renderFile('/current.html', { name: 'foo' })
|
||||||
|
return expect(html).to.equal('barfoobar')
|
||||||
|
})
|
||||||
|
|
||||||
it('should throw when not specified', function () {
|
it('should throw when not specified', function () {
|
||||||
mock({
|
mock({
|
||||||
@@ -155,7 +163,7 @@ describe('tags/include', function () {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('static partial', function () {
|
describe('static partial', function () {
|
||||||
it('should support filename with extention', async function () {
|
it('should support filename with extension', async function () {
|
||||||
mock({
|
mock({
|
||||||
'/parent.html': 'X{% include child.html color:"red" %}Y',
|
'/parent.html': 'X{% include child.html color:"red" %}Y',
|
||||||
'/child.html': 'child with {{color}}'
|
'/child.html': 'child with {{color}}'
|
||||||
@@ -194,6 +202,16 @@ describe('tags/include', function () {
|
|||||||
const html = await staticLiquid.renderFile('parent.html')
|
const html = await staticLiquid.renderFile('parent.html')
|
||||||
return expect(html).to.equal('Xchild with redY')
|
return expect(html).to.equal('Xchild with redY')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should support single liquid output', async function () {
|
||||||
|
mock({
|
||||||
|
'/parent.html': 'X{% include {{child}}, color:"red" %}Y',
|
||||||
|
'/child.html': 'child with {{color}}'
|
||||||
|
})
|
||||||
|
const staticLiquid = new Liquid({ dynamicPartials: false, root: '/' })
|
||||||
|
const html = await staticLiquid.renderFile('parent.html', { child: 'child.html' })
|
||||||
|
return expect(html).to.equal('Xchild with redY')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
describe('sync support', function () {
|
describe('sync support', function () {
|
||||||
it('should support quoted string', function () {
|
it('should support quoted string', function () {
|
||||||
@@ -204,7 +222,7 @@ describe('tags/include', function () {
|
|||||||
const html = liquid.renderFileSync('/current.html')
|
const html = liquid.renderFileSync('/current.html')
|
||||||
return expect(html).to.equal('barfoobar')
|
return expect(html).to.equal('barfoobar')
|
||||||
})
|
})
|
||||||
it('should support template string', function () {
|
it('should support variable', function () {
|
||||||
mock({
|
mock({
|
||||||
'/current.html': 'bar{% include name %}bar',
|
'/current.html': 'bar{% include name %}bar',
|
||||||
'/bar/foo.html': 'foo'
|
'/bar/foo.html': 'foo'
|
||||||
@@ -220,7 +238,7 @@ describe('tags/include', function () {
|
|||||||
const html = liquid.renderFileSync('with.html')
|
const html = liquid.renderFileSync('with.html')
|
||||||
return expect(html).to.equal('color:red, shape:rect')
|
return expect(html).to.equal('color:red, shape:rect')
|
||||||
})
|
})
|
||||||
it('should support filename with extention', function () {
|
it('should support filename with extension', function () {
|
||||||
mock({
|
mock({
|
||||||
'/parent.html': 'X{% include child.html color:"red" %}Y',
|
'/parent.html': 'X{% include child.html color:"red" %}Y',
|
||||||
'/child.html': 'child with {{color}}'
|
'/child.html': 'child with {{color}}'
|
||||||
|
|||||||
@@ -260,12 +260,15 @@ describe('tags/render', function () {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('static partial', function () {
|
describe('static partial', function () {
|
||||||
|
let staticLiquid: Liquid
|
||||||
|
beforeEach(() => {
|
||||||
|
staticLiquid = new Liquid({ dynamicPartials: false, root: '/' })
|
||||||
|
})
|
||||||
it('should support filename with extension', async function () {
|
it('should support filename with extension', async function () {
|
||||||
mock({
|
mock({
|
||||||
'/parent.html': 'X{% render child.html color:"red" %}Y',
|
'/parent.html': 'X{% render child.html color:"red" %}Y',
|
||||||
'/child.html': 'child with {{color}}'
|
'/child.html': 'child with {{color}}'
|
||||||
})
|
})
|
||||||
const staticLiquid = new Liquid({ dynamicPartials: false, root: '/' })
|
|
||||||
const html = await staticLiquid.renderFile('parent.html')
|
const html = await staticLiquid.renderFile('parent.html')
|
||||||
expect(html).to.equal('Xchild with redY')
|
expect(html).to.equal('Xchild with redY')
|
||||||
})
|
})
|
||||||
@@ -275,7 +278,6 @@ describe('tags/render', function () {
|
|||||||
'/parent.html': 'X{% render bar/./../foo/child.html %}Y',
|
'/parent.html': 'X{% render bar/./../foo/child.html %}Y',
|
||||||
'/foo/child.html': 'child'
|
'/foo/child.html': 'child'
|
||||||
})
|
})
|
||||||
const staticLiquid = new Liquid({ dynamicPartials: false, root: '/' })
|
|
||||||
const html = await staticLiquid.renderFile('parent.html')
|
const html = await staticLiquid.renderFile('parent.html')
|
||||||
expect(html).to.equal('XchildY')
|
expect(html).to.equal('XchildY')
|
||||||
})
|
})
|
||||||
@@ -285,7 +287,6 @@ describe('tags/render', function () {
|
|||||||
'/parent.html': 'X{% render foo/child.html %}Y',
|
'/parent.html': 'X{% render foo/child.html %}Y',
|
||||||
'/foo/child.html': 'child'
|
'/foo/child.html': 'child'
|
||||||
})
|
})
|
||||||
const staticLiquid = new Liquid({ dynamicPartials: false, root: '/' })
|
|
||||||
const html = await staticLiquid.renderFile('parent.html')
|
const html = await staticLiquid.renderFile('parent.html')
|
||||||
expect(html).to.equal('XchildY')
|
expect(html).to.equal('XchildY')
|
||||||
})
|
})
|
||||||
@@ -295,10 +296,27 @@ describe('tags/render', function () {
|
|||||||
'/parent.html': 'X{% render child.html, color:"red" %}Y',
|
'/parent.html': 'X{% render child.html, color:"red" %}Y',
|
||||||
'/child.html': 'child with {{color}}'
|
'/child.html': 'child with {{color}}'
|
||||||
})
|
})
|
||||||
const staticLiquid = new Liquid({ dynamicPartials: false, root: '/' })
|
|
||||||
const html = await staticLiquid.renderFile('parent.html')
|
const html = await staticLiquid.renderFile('parent.html')
|
||||||
expect(html).to.equal('Xchild with redY')
|
expect(html).to.equal('Xchild with redY')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should support template string', async function () {
|
||||||
|
mock({
|
||||||
|
'/current.html': 'bar{% render bar/{{name}} %}bar',
|
||||||
|
'/bar/foo.html': 'foo'
|
||||||
|
})
|
||||||
|
const html = await staticLiquid.renderFile('/current.html', { name: 'foo.html' })
|
||||||
|
expect(html).to.equal('barfoobar')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should support filters in template string', async function () {
|
||||||
|
mock({
|
||||||
|
'/current.html': 'bar{% render bar/{{name | append: ".html"}} %}bar',
|
||||||
|
'/bar/foo.html': 'foo'
|
||||||
|
})
|
||||||
|
const html = await staticLiquid.renderFile('/current.html', { name: 'foo' })
|
||||||
|
expect(html).to.equal('barfoobar')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
describe('sync support', function () {
|
describe('sync support', function () {
|
||||||
it('should support quoted string', function () {
|
it('should support quoted string', function () {
|
||||||
|
|||||||
Reference in New Issue
Block a user