mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-16 12:50:38 -07:00
feat: override output/tag delimiter, fixes #54
This commit is contained in:
@@ -196,6 +196,10 @@ Otherwise, undefined variables will cause an exception. Defaults to `false`.
|
|||||||
|
|
||||||
* `trim_output_left` is similiar to `trim_output_right`, whereas the `\n` is exclusive. Defaults to `false`. See [Whitespace Control][whitespace control] for details.
|
* `trim_output_left` is similiar to `trim_output_right`, whereas the `\n` is exclusive. Defaults to `false`. See [Whitespace Control][whitespace control] for details.
|
||||||
|
|
||||||
|
* `tag_delimiter_left` and `tag_delimiter_right` are used to override the delimiter for liquid tags.
|
||||||
|
|
||||||
|
* `output_delimiter_left` and `output_delimiter_right` are used to override the delimiter for liquid outputs.
|
||||||
|
|
||||||
* `greedy` is used to specify whether `trim_left`/`trim_right` is greedy. When set to `true`, all consecutive blank characters including `\n` will be trimed regardless of line breaks. Defaults to `true`.
|
* `greedy` is used to specify whether `trim_left`/`trim_right` is greedy. When set to `true`, all consecutive blank characters including `\n` will be trimed regardless of line breaks. Defaults to `true`.
|
||||||
|
|
||||||
## Register Filters
|
## Register Filters
|
||||||
|
|||||||
@@ -23,6 +23,12 @@ export interface LiquidOptions {
|
|||||||
trim_output_right?: boolean
|
trim_output_right?: boolean
|
||||||
/** `trim_output_left` is similar to `trim_output_right`, whereas the `\n` is exclusive. Defaults to `false`. See Whitespace Control for details. */
|
/** `trim_output_left` is similar to `trim_output_right`, whereas the `\n` is exclusive. Defaults to `false`. See Whitespace Control for details. */
|
||||||
trim_output_left?: boolean
|
trim_output_left?: boolean
|
||||||
|
/** `tag_delimiter_left` and `tag_delimiter_right` are used to override the delimiter for liquid tags **/
|
||||||
|
tag_delimiter_left?: string,
|
||||||
|
tag_delimiter_right?: string,
|
||||||
|
/** `output_delimiter_left` and `output_delimiter_right` are used to override the delimiter for liquid outputs **/
|
||||||
|
output_delimiter_left?: string,
|
||||||
|
output_delimiter_right?: string,
|
||||||
/** `greedy` is used to specify whether `trim_left`/`trim_right` is greedy. When set to `true`, all consecutive blank characters including `\n` will be trimed regardless of line breaks. Defaults to `true`. */
|
/** `greedy` is used to specify whether `trim_left`/`trim_right` is greedy. When set to `true`, all consecutive blank characters including `\n` will be trimed regardless of line breaks. Defaults to `true`. */
|
||||||
greedy?: boolean
|
greedy?: boolean
|
||||||
}
|
}
|
||||||
@@ -55,6 +61,10 @@ const defaultOptions: NormalizedFullOptions = {
|
|||||||
trim_output_right: false,
|
trim_output_right: false,
|
||||||
trim_output_left: false,
|
trim_output_left: false,
|
||||||
greedy: true,
|
greedy: true,
|
||||||
|
tag_delimiter_left: '{%',
|
||||||
|
tag_delimiter_right: '%}',
|
||||||
|
output_delimiter_left: '{{',
|
||||||
|
output_delimiter_right: '}}',
|
||||||
strict_filters: false,
|
strict_filters: false,
|
||||||
strict_variables: false
|
strict_variables: false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,15 @@ import Token from './token'
|
|||||||
export default class DelimitedToken extends Token {
|
export default class DelimitedToken extends Token {
|
||||||
trimLeft: boolean
|
trimLeft: boolean
|
||||||
trimRight: boolean
|
trimRight: boolean
|
||||||
constructor (raw, pos, input, file, line) {
|
constructor (raw, value, pos, input, file, line) {
|
||||||
super(raw, pos, input, file, line)
|
super(raw, pos, input, file, line)
|
||||||
this.trimLeft = raw[2] === '-'
|
this.trimLeft = value[0] === '-'
|
||||||
this.trimRight = raw[raw.length - 3] === '-'
|
this.trimRight = value[value.length - 1] === '-'
|
||||||
this.value = raw.slice(this.trimLeft ? 3 : 2, this.trimRight ? -3 : -2).trim()
|
this.value = value
|
||||||
|
.slice(
|
||||||
|
this.trimLeft ? 1 : 0,
|
||||||
|
this.trimRight ? -1 : value.length
|
||||||
|
)
|
||||||
|
.trim()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import DelimitedToken from './delimited-token'
|
import DelimitedToken from './delimited-token'
|
||||||
|
|
||||||
export default class OutputToken extends DelimitedToken {
|
export default class OutputToken extends DelimitedToken {
|
||||||
constructor (raw, pos, input, file, line) {
|
constructor (raw, value, pos, input, file, line) {
|
||||||
super(raw, pos, input, file, line)
|
super(raw, value, pos, input, file, line)
|
||||||
this.type = 'output'
|
this.type = 'output'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import * as lexical from './lexical'
|
|||||||
export default class TagToken extends DelimitedToken {
|
export default class TagToken extends DelimitedToken {
|
||||||
name: string
|
name: string
|
||||||
args: string
|
args: string
|
||||||
constructor (raw, pos, input, file, line) {
|
constructor (raw, value, pos, input, file, line) {
|
||||||
super(raw, pos, input, file, line)
|
super(raw, value, pos, input, file, line)
|
||||||
this.type = 'tag'
|
this.type = 'tag'
|
||||||
const match = this.value.match(lexical.tagLine)
|
const match = this.value.match(lexical.tagLine)
|
||||||
if (!match) {
|
if (!match) {
|
||||||
|
|||||||
+24
-13
@@ -15,6 +15,10 @@ export default class Tokenizer {
|
|||||||
}
|
}
|
||||||
tokenize (input: string, file?: string) {
|
tokenize (input: string, file?: string) {
|
||||||
const tokens = []
|
const tokens = []
|
||||||
|
const tagL = this.options.tag_delimiter_left
|
||||||
|
const tagR = this.options.tag_delimiter_right
|
||||||
|
const outputL = this.options.output_delimiter_left
|
||||||
|
const outputR = this.options.output_delimiter_right
|
||||||
let p = 0
|
let p = 0
|
||||||
let curLine = 1
|
let curLine = 1
|
||||||
let state = ParseState.HTML
|
let state = ParseState.HTML
|
||||||
@@ -28,30 +32,37 @@ export default class Tokenizer {
|
|||||||
curLine++
|
curLine++
|
||||||
lineBegin = p + 1
|
lineBegin = p + 1
|
||||||
}
|
}
|
||||||
const bin = input.substr(p, 2)
|
|
||||||
if (state === ParseState.HTML) {
|
if (state === ParseState.HTML) {
|
||||||
if (bin === '{{' || bin === '{%') {
|
if (input.substr(p, outputL.length) === outputL) {
|
||||||
if (buffer) tokens.push(new HTMLToken(buffer, col, input, file, line))
|
if (buffer) tokens.push(new HTMLToken(buffer, col, input, file, line))
|
||||||
buffer = bin
|
buffer = outputL
|
||||||
line = curLine
|
line = curLine
|
||||||
col = p - lineBegin + 1
|
col = p - lineBegin + 1
|
||||||
p += 2
|
p += outputL.length
|
||||||
state = bin === '{{' ? ParseState.OUTPUT : ParseState.TAG
|
state = ParseState.OUTPUT
|
||||||
|
continue
|
||||||
|
} else if (input.substr(p, tagL.length) === tagL) {
|
||||||
|
if (buffer) tokens.push(new HTMLToken(buffer, col, input, file, line))
|
||||||
|
buffer = tagL
|
||||||
|
line = curLine
|
||||||
|
col = p - lineBegin + 1
|
||||||
|
p += tagL.length
|
||||||
|
state = ParseState.TAG
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else if (state === ParseState.OUTPUT && bin === '}}') {
|
} else if (state === ParseState.OUTPUT && input.substr(p, outputR.length) === outputR) {
|
||||||
buffer += '}}'
|
buffer += outputR
|
||||||
tokens.push(new OutputToken(buffer, col, input, file, line))
|
tokens.push(new OutputToken(buffer, buffer.slice(outputL.length, -outputR.length), col, input, file, line))
|
||||||
p += 2
|
p += outputR.length
|
||||||
buffer = ''
|
buffer = ''
|
||||||
line = curLine
|
line = curLine
|
||||||
col = p - lineBegin + 1
|
col = p - lineBegin + 1
|
||||||
state = ParseState.HTML
|
state = ParseState.HTML
|
||||||
continue
|
continue
|
||||||
} else if (bin === '%}') {
|
} else if (input.substr(p, tagR.length) === tagR) {
|
||||||
buffer += '%}'
|
buffer += tagR
|
||||||
tokens.push(new TagToken(buffer, col, input, file, line))
|
tokens.push(new TagToken(buffer, buffer.slice(tagL.length, -tagR.length), col, input, file, line))
|
||||||
p += 2
|
p += tagR.length
|
||||||
buffer = ''
|
buffer = ''
|
||||||
line = curLine
|
line = curLine
|
||||||
col = p - lineBegin + 1
|
col = p - lineBegin + 1
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import DelimitedToken from 'src/parser/delimited-token'
|
import DelimitedToken from 'src/parser/delimited-token'
|
||||||
import Token from 'src/parser/token'
|
import Token from 'src/parser/token'
|
||||||
import TagToken from 'src/parser/tag-token'
|
import TagToken from 'src/parser/tag-token'
|
||||||
import { LiquidOptions } from 'src/liquid-options'
|
import { NormalizedFullOptions } from 'src/liquid-options'
|
||||||
|
|
||||||
export default function whiteSpaceCtrl (tokens: Token[], options: LiquidOptions) {
|
export default function whiteSpaceCtrl (tokens: Token[], options: NormalizedFullOptions) {
|
||||||
options = { greedy: true, ...options }
|
options = { greedy: true, ...options }
|
||||||
let inRaw = false
|
let inRaw = false
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { expect } from 'chai'
|
||||||
|
import Liquid from 'src/liquid'
|
||||||
|
|
||||||
|
describe('LiquidOptions#*_delimiter_*', function () {
|
||||||
|
it('should respect tag_delimiter_*', async function () {
|
||||||
|
const engine = new Liquid({
|
||||||
|
tag_delimiter_left: '<%=',
|
||||||
|
tag_delimiter_right: '%>'
|
||||||
|
})
|
||||||
|
const html = await engine.parseAndRender('<%=if true%>foo<%=endif%> ')
|
||||||
|
return expect(html).to.equal('foo ')
|
||||||
|
})
|
||||||
|
it('should respect output_delimiter_*', async function () {
|
||||||
|
const engine = new Liquid({
|
||||||
|
output_delimiter_left: '<<',
|
||||||
|
output_delimiter_right: '>>'
|
||||||
|
})
|
||||||
|
const html = await engine.parseAndRender('<< "liquid" | capitalize >>')
|
||||||
|
return expect(html).to.equal('Liquid')
|
||||||
|
})
|
||||||
|
it('should support trimming with tag_delimiter_* set', async function () {
|
||||||
|
const engine = new Liquid({
|
||||||
|
tag_delimiter_left: '<%=',
|
||||||
|
tag_delimiter_right: '%>',
|
||||||
|
trim_tag_left: true,
|
||||||
|
trim_tag_right: true
|
||||||
|
})
|
||||||
|
const html = await engine.parseAndRender(' <%=if true%> \tfoo\t <%=endif%> ')
|
||||||
|
return expect(html).to.equal('foo')
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user