mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-15 04:10:40 -07:00
feat: support custom key-value separator, #752
This commit is contained in:
@@ -68,6 +68,8 @@ export interface LiquidOptions {
|
|||||||
greedy?: boolean;
|
greedy?: boolean;
|
||||||
/** `fs` is used to override the default file-system module with a custom implementation. */
|
/** `fs` is used to override the default file-system module with a custom implementation. */
|
||||||
fs?: FS;
|
fs?: FS;
|
||||||
|
/** keyValue separator */
|
||||||
|
keyValueSeparator?: string;
|
||||||
/** 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. */
|
/** 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. */
|
||||||
templates?: {[key: string]: string};
|
templates?: {[key: string]: string};
|
||||||
/** the global scope passed down to all partial and layout templates, i.e. templates included by `include`, `layout` and `render` tags. */
|
/** 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 = {
|
|||||||
partials: ['.'],
|
partials: ['.'],
|
||||||
relativeReference: true,
|
relativeReference: true,
|
||||||
jekyllInclude: false,
|
jekyllInclude: false,
|
||||||
|
keyValueSeparator: ':',
|
||||||
cache: undefined,
|
cache: undefined,
|
||||||
extname: '',
|
extname: '',
|
||||||
fs: fs,
|
fs: fs,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { FilteredValueToken, TagToken, HTMLToken, HashToken, QuotedToken, LiquidTagToken, OutputToken, ValueToken, Token, RangeToken, FilterToken, TopLevelToken, PropertyAccessToken, OperatorToken, LiteralToken, IdentifierToken, NumberToken } from '../tokens'
|
import { FilteredValueToken, TagToken, HTMLToken, HashToken, QuotedToken, LiquidTagToken, OutputToken, ValueToken, Token, RangeToken, FilterToken, TopLevelToken, PropertyAccessToken, OperatorToken, LiteralToken, IdentifierToken, NumberToken } from '../tokens'
|
||||||
import { OperatorHandler } from '../render/operator'
|
import { OperatorHandler } from '../render/operator'
|
||||||
import { TrieNode, LiteralValue, Trie, createTrie, ellipsis, literalValues, TokenizationError, TYPES, QUOTE, BLANK, NUMBER, SIGN, isWord } from '../util'
|
import { TrieNode, LiteralValue, Trie, createTrie, ellipsis, literalValues, TokenizationError, TYPES, QUOTE, BLANK, NUMBER, SIGN, isWord, isString } from '../util'
|
||||||
import { Operators, Expression } from '../render'
|
import { Operators, Expression } from '../render'
|
||||||
import { NormalizedFullOptions, defaultOptions } from '../liquid-options'
|
import { NormalizedFullOptions, defaultOptions } from '../liquid-options'
|
||||||
import { FilterArg } from './filter-arg'
|
import { FilterArg } from './filter-arg'
|
||||||
@@ -261,7 +261,7 @@ export class Tokenizer {
|
|||||||
return this.readIdentifier().getText()
|
return this.readIdentifier().getText()
|
||||||
}
|
}
|
||||||
|
|
||||||
readHashes (jekyllStyle?: boolean) {
|
readHashes (jekyllStyle?: boolean | string) {
|
||||||
const hashes = []
|
const hashes = []
|
||||||
while (true) {
|
while (true) {
|
||||||
const hash = this.readHash(jekyllStyle)
|
const hash = this.readHash(jekyllStyle)
|
||||||
@@ -270,7 +270,7 @@ export class Tokenizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readHash (jekyllStyle?: boolean): HashToken | undefined {
|
readHash (jekyllStyle?: boolean | string): HashToken | undefined {
|
||||||
this.skipBlank()
|
this.skipBlank()
|
||||||
if (this.peek() === ',') ++this.p
|
if (this.peek() === ',') ++this.p
|
||||||
const begin = this.p
|
const begin = this.p
|
||||||
@@ -279,7 +279,7 @@ export class Tokenizer {
|
|||||||
let value
|
let value
|
||||||
|
|
||||||
this.skipBlank()
|
this.skipBlank()
|
||||||
const sep = jekyllStyle ? '=' : ':'
|
const sep = isString(jekyllStyle) ? jekyllStyle : (jekyllStyle ? '=' : ':')
|
||||||
if (this.peek() === sep) {
|
if (this.peek() === sep) {
|
||||||
++this.p
|
++this.p
|
||||||
value = this.readValue()
|
value = this.readValue()
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ export default class extends Tag {
|
|||||||
|
|
||||||
this.variable = variable.content
|
this.variable = variable.content
|
||||||
this.collection = collection
|
this.collection = collection
|
||||||
this.hash = new Hash(this.tokenizer.remaining())
|
this.hash = new Hash(this.tokenizer.remaining(), liquid.options.keyValueSeparator)
|
||||||
this.templates = []
|
this.templates = []
|
||||||
this.elseTemplates = []
|
this.elseTemplates = []
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ export default class extends Tag {
|
|||||||
} else tokenizer.p = begin
|
} else tokenizer.p = begin
|
||||||
} else tokenizer.p = begin
|
} else tokenizer.p = begin
|
||||||
|
|
||||||
this.hash = new Hash(tokenizer.remaining(), this.liquid.options.jekyllInclude)
|
this.hash = new Hash(tokenizer.remaining(), liquid.options.jekyllInclude || liquid.options.keyValueSeparator)
|
||||||
}
|
}
|
||||||
* render (ctx: Context, emitter: Emitter): Generator<unknown, void, unknown> {
|
* render (ctx: Context, emitter: Emitter): Generator<unknown, void, unknown> {
|
||||||
const { liquid, hash, withVar } = this
|
const { liquid, hash, withVar } = this
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ export default class extends Tag {
|
|||||||
super(token, remainTokens, liquid)
|
super(token, remainTokens, liquid)
|
||||||
this.file = parseFilePath(this.tokenizer, this.liquid, parser)
|
this.file = parseFilePath(this.tokenizer, this.liquid, parser)
|
||||||
this['currentFile'] = token.file
|
this['currentFile'] = token.file
|
||||||
this.args = new Hash(this.tokenizer.remaining())
|
this.args = new Hash(this.tokenizer.remaining(), liquid.options.keyValueSeparator)
|
||||||
this.templates = parser.parseTokens(remainTokens)
|
this.templates = parser.parseTokens(remainTokens)
|
||||||
}
|
}
|
||||||
* render (ctx: Context, emitter: Emitter): Generator<unknown, unknown, unknown> {
|
* render (ctx: Context, emitter: Emitter): Generator<unknown, unknown, unknown> {
|
||||||
|
|||||||
+1
-1
@@ -45,7 +45,7 @@ export default class extends Tag {
|
|||||||
tokenizer.p = begin
|
tokenizer.p = begin
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
this.hash = new Hash(tokenizer.remaining())
|
this.hash = new Hash(tokenizer.remaining(), liquid.options.keyValueSeparator)
|
||||||
}
|
}
|
||||||
* render (ctx: Context, emitter: Emitter): Generator<unknown, void, unknown> {
|
* render (ctx: Context, emitter: Emitter): Generator<unknown, void, unknown> {
|
||||||
const { liquid, hash } = this
|
const { liquid, hash } = this
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default class extends Tag {
|
|||||||
|
|
||||||
this.variable = variable.content
|
this.variable = variable.content
|
||||||
this.collection = collectionToken
|
this.collection = collectionToken
|
||||||
this.args = new Hash(this.tokenizer.remaining())
|
this.args = new Hash(this.tokenizer.remaining(), liquid.options.keyValueSeparator)
|
||||||
this.templates = []
|
this.templates = []
|
||||||
|
|
||||||
let p
|
let p
|
||||||
|
|||||||
@@ -39,4 +39,8 @@ describe('Hash', function () {
|
|||||||
num3: 4
|
num3: 4
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
it('should support custom separator', async function () {
|
||||||
|
const hash = await toPromise(new Hash('num=2.3', '=').render(new Context()))
|
||||||
|
expect(hash.num).toBe(2.3)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ type HashValueTokens = Record<string, Token | undefined>
|
|||||||
*/
|
*/
|
||||||
export class Hash {
|
export class Hash {
|
||||||
hash: HashValueTokens = {}
|
hash: HashValueTokens = {}
|
||||||
constructor (markup: string, jekyllStyle?: boolean) {
|
constructor (markup: string, jekyllStyle?: boolean | string) {
|
||||||
const tokenizer = new Tokenizer(markup, {})
|
const tokenizer = new Tokenizer(markup, {})
|
||||||
for (const hash of tokenizer.readHashes(jekyllStyle)) {
|
for (const hash of tokenizer.readHashes(jekyllStyle)) {
|
||||||
this.hash[hash.name.content] = hash.value
|
this.hash[hash.name.content] = hash.value
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export function createTagClass (options: TagImplOptions): TagClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
* render (ctx: Context, emitter: Emitter): TagRenderReturn {
|
* render (ctx: Context, emitter: Emitter): TagRenderReturn {
|
||||||
const hash = (yield new Hash(this.token.args).render(ctx)) as Record<string, any>
|
const hash = (yield new Hash(this.token.args, ctx.opts.keyValueSeparator).render(ctx)) as Record<string, any>
|
||||||
return yield options.render.call(this, ctx, emitter, hash)
|
return yield options.render.call(this, ctx, emitter, hash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user