Skip to content

Commit 6aeed25

Browse files
Yang Junharttle
Yang Jun
authored andcommitted
feat: support custom key-value separator, #752
1 parent 5ada07c commit 6aeed25

File tree

10 files changed

+18
-11
lines changed

10 files changed

+18
-11
lines changed

src/liquid-options.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ export interface LiquidOptions {
6868
greedy?: boolean;
6969
/** `fs` is used to override the default file-system module with a custom implementation. */
7070
fs?: FS;
71+
/** keyValue separator */
72+
keyValueSeparator?: string;
7173
/** Render from in-memory `templates` mapping instead of file system. File system related options like `fs`, 'root', and `relativeReference` will be ignored when `templates` is specified. */
7274
templates?: {[key: string]: string};
7375
/** the global scope passed down to all partial and layout templates, i.e. templates included by `include`, `layout` and `render` tags. */
@@ -166,6 +168,7 @@ export const defaultOptions: NormalizedFullOptions = {
166168
partials: ['.'],
167169
relativeReference: true,
168170
jekyllInclude: false,
171+
keyValueSeparator: ':',
169172
cache: undefined,
170173
extname: '',
171174
fs: fs,

src/parser/tokenizer.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { FilteredValueToken, TagToken, HTMLToken, HashToken, QuotedToken, LiquidTagToken, OutputToken, ValueToken, Token, RangeToken, FilterToken, TopLevelToken, PropertyAccessToken, OperatorToken, LiteralToken, IdentifierToken, NumberToken } from '../tokens'
22
import { OperatorHandler } from '../render/operator'
3-
import { TrieNode, LiteralValue, Trie, createTrie, ellipsis, literalValues, TokenizationError, TYPES, QUOTE, BLANK, NUMBER, SIGN, isWord } from '../util'
3+
import { TrieNode, LiteralValue, Trie, createTrie, ellipsis, literalValues, TokenizationError, TYPES, QUOTE, BLANK, NUMBER, SIGN, isWord, isString } from '../util'
44
import { Operators, Expression } from '../render'
55
import { NormalizedFullOptions, defaultOptions } from '../liquid-options'
66
import { FilterArg } from './filter-arg'
@@ -261,7 +261,7 @@ export class Tokenizer {
261261
return this.readIdentifier().getText()
262262
}
263263

264-
readHashes (jekyllStyle?: boolean) {
264+
readHashes (jekyllStyle?: boolean | string) {
265265
const hashes = []
266266
while (true) {
267267
const hash = this.readHash(jekyllStyle)
@@ -270,7 +270,7 @@ export class Tokenizer {
270270
}
271271
}
272272

273-
readHash (jekyllStyle?: boolean): HashToken | undefined {
273+
readHash (jekyllStyle?: boolean | string): HashToken | undefined {
274274
this.skipBlank()
275275
if (this.peek() === ',') ++this.p
276276
const begin = this.p
@@ -279,7 +279,7 @@ export class Tokenizer {
279279
let value
280280

281281
this.skipBlank()
282-
const sep = jekyllStyle ? '=' : ':'
282+
const sep = isString(jekyllStyle) ? jekyllStyle : (jekyllStyle ? '=' : ':')
283283
if (this.peek() === sep) {
284284
++this.p
285285
value = this.readValue()

src/tags/for.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export default class extends Tag {
2525

2626
this.variable = variable.content
2727
this.collection = collection
28-
this.hash = new Hash(this.tokenizer.remaining())
28+
this.hash = new Hash(this.tokenizer.remaining(), liquid.options.keyValueSeparator)
2929
this.templates = []
3030
this.elseTemplates = []
3131

src/tags/include.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export default class extends Tag {
2121
} else tokenizer.p = begin
2222
} else tokenizer.p = begin
2323

24-
this.hash = new Hash(tokenizer.remaining(), this.liquid.options.jekyllInclude)
24+
this.hash = new Hash(tokenizer.remaining(), liquid.options.jekyllInclude || liquid.options.keyValueSeparator)
2525
}
2626
* render (ctx: Context, emitter: Emitter): Generator<unknown, void, unknown> {
2727
const { liquid, hash, withVar } = this

src/tags/layout.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export default class extends Tag {
1212
super(token, remainTokens, liquid)
1313
this.file = parseFilePath(this.tokenizer, this.liquid, parser)
1414
this['currentFile'] = token.file
15-
this.args = new Hash(this.tokenizer.remaining())
15+
this.args = new Hash(this.tokenizer.remaining(), liquid.options.keyValueSeparator)
1616
this.templates = parser.parseTokens(remainTokens)
1717
}
1818
* render (ctx: Context, emitter: Emitter): Generator<unknown, unknown, unknown> {

src/tags/render.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export default class extends Tag {
4545
tokenizer.p = begin
4646
break
4747
}
48-
this.hash = new Hash(tokenizer.remaining())
48+
this.hash = new Hash(tokenizer.remaining(), liquid.options.keyValueSeparator)
4949
}
5050
* render (ctx: Context, emitter: Emitter): Generator<unknown, void, unknown> {
5151
const { liquid, hash } = this

src/tags/tablerow.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export default class extends Tag {
2121

2222
this.variable = variable.content
2323
this.collection = collectionToken
24-
this.args = new Hash(this.tokenizer.remaining())
24+
this.args = new Hash(this.tokenizer.remaining(), liquid.options.keyValueSeparator)
2525
this.templates = []
2626

2727
let p

src/template/hash.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,8 @@ describe('Hash', function () {
3939
num3: 4
4040
})
4141
})
42+
it('should support custom separator', async function () {
43+
const hash = await toPromise(new Hash('num=2.3', '=').render(new Context()))
44+
expect(hash.num).toBe(2.3)
45+
})
4246
})

src/template/hash.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ type HashValueTokens = Record<string, Token | undefined>
1515
*/
1616
export class Hash {
1717
hash: HashValueTokens = {}
18-
constructor (markup: string, jekyllStyle?: boolean) {
18+
constructor (markup: string, jekyllStyle?: boolean | string) {
1919
const tokenizer = new Tokenizer(markup, {})
2020
for (const hash of tokenizer.readHashes(jekyllStyle)) {
2121
this.hash[hash.name.content] = hash.value

src/template/tag-options-adapter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export function createTagClass (options: TagImplOptions): TagClass {
2121
}
2222
}
2323
* render (ctx: Context, emitter: Emitter): TagRenderReturn {
24-
const hash = (yield new Hash(this.token.args).render(ctx)) as Record<string, any>
24+
const hash = (yield new Hash(this.token.args, ctx.opts.keyValueSeparator).render(ctx)) as Record<string, any>
2525
return yield options.render.call(this, ctx, emitter, hash)
2626
}
2727
}

0 commit comments

Comments
 (0)