mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-18 14:00:39 -07:00
feat: move filters/tags to instances, fixes #188
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
import { FilterImplOptions } from './filter-impl-options'
|
||||
import { Filter, FilterArgs } from './filter'
|
||||
import { assert } from '../../util/assert'
|
||||
|
||||
export class FilterMap {
|
||||
private impls: {[key: string]: FilterImplOptions} = {}
|
||||
|
||||
constructor (private readonly strictFilters: boolean) {}
|
||||
|
||||
get (name: string) {
|
||||
const impl = this.impls[name]
|
||||
assert(impl || !this.strictFilters, `undefined filter: ${name}`)
|
||||
return impl
|
||||
}
|
||||
|
||||
set (name: string, impl: FilterImplOptions) {
|
||||
this.impls[name] = impl
|
||||
}
|
||||
|
||||
create (name: string, args: FilterArgs) {
|
||||
return new Filter(name, this.get(name), args)
|
||||
}
|
||||
}
|
||||
@@ -11,12 +11,8 @@ export class Filter {
|
||||
public name: string
|
||||
public args: FilterArgs
|
||||
private impl: FilterImplOptions
|
||||
private static impls: {[key: string]: FilterImplOptions} = {}
|
||||
|
||||
public constructor (name: string, args: FilterArgs, strictFilters: boolean) {
|
||||
const impl = Filter.impls[name]
|
||||
if (!impl && strictFilters) throw new TypeError(`undefined filter: ${name}`)
|
||||
|
||||
public constructor (name: string, impl: FilterImplOptions, args: FilterArgs) {
|
||||
this.name = name
|
||||
this.impl = impl || identify
|
||||
this.args = args
|
||||
@@ -29,12 +25,6 @@ export class Filter {
|
||||
}
|
||||
return this.impl.apply({ context }, [value, ...argv])
|
||||
}
|
||||
public static register (name: string, filter: FilterImplOptions) {
|
||||
Filter.impls[name] = filter
|
||||
}
|
||||
public static clear () {
|
||||
Filter.impls = {}
|
||||
}
|
||||
}
|
||||
|
||||
function isKeyValuePair (arr: FilterArg): arr is KeyValuePair {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { TemplateImpl } from '../template/template-impl'
|
||||
import { Template } from '../template/template'
|
||||
import { ITemplate } from '../template/itemplate'
|
||||
import { HTMLToken } from '../parser/html-token'
|
||||
import { Context } from '../context/context'
|
||||
import { Emitter } from '../render/emitter'
|
||||
|
||||
export class HTML extends Template<HTMLToken> implements ITemplate {
|
||||
export class HTML extends TemplateImpl<HTMLToken> implements Template {
|
||||
private str: string
|
||||
public constructor (token: HTMLToken) {
|
||||
super(token)
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import { Context } from '../context/context'
|
||||
import { Token } from '../parser/token'
|
||||
import { Emitter } from '../render/emitter'
|
||||
|
||||
export interface ITemplate {
|
||||
token: Token;
|
||||
render(ctx: Context, emitter: Emitter): any;
|
||||
}
|
||||
@@ -1,16 +1,17 @@
|
||||
import { Value } from './value'
|
||||
import { FilterMap } from './filter/filter-map'
|
||||
import { stringify, toValue } from '../util/underscore'
|
||||
import { TemplateImpl } from '../template/template-impl'
|
||||
import { Template } from '../template/template'
|
||||
import { ITemplate } from '../template/itemplate'
|
||||
import { Context } from '../context/context'
|
||||
import { Emitter } from '../render/emitter'
|
||||
import { OutputToken } from '../parser/output-token'
|
||||
|
||||
export class Output extends Template<OutputToken> implements ITemplate {
|
||||
export class Output extends TemplateImpl<OutputToken> implements Template {
|
||||
private value: Value
|
||||
public constructor (token: OutputToken, strictFilters: boolean) {
|
||||
public constructor (token: OutputToken, filters: FilterMap) {
|
||||
super(token)
|
||||
this.value = new Value(token.value, strictFilters)
|
||||
this.value = new Value(token.value, filters)
|
||||
}
|
||||
public * render (ctx: Context, emitter: Emitter) {
|
||||
const val = yield this.value.value(ctx)
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
import { Liquid } from '../../liquid'
|
||||
import { ITagImplOptions } from './itag-impl-options'
|
||||
|
||||
export interface ITagImpl extends ITagImplOptions {
|
||||
liquid: Liquid;
|
||||
[key: string]: any;
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Context } from '../../context/context'
|
||||
import { TagToken } from '../../parser/tag-token'
|
||||
import { Token } from '../../parser/token'
|
||||
import { ITagImpl } from './itag-impl'
|
||||
import { TagImpl } from './tag-impl'
|
||||
import { Hash } from '../../template/tag/hash'
|
||||
import { Emitter } from '../../render/emitter'
|
||||
|
||||
export interface ITagImplOptions {
|
||||
parse?: (this: ITagImpl, token: TagToken, remainingTokens: Token[]) => void;
|
||||
render: (this: ITagImpl, ctx: Context, hash: Hash, emitter: Emitter) => any;
|
||||
export interface TagImplOptions {
|
||||
parse?: (this: TagImpl, token: TagToken, remainingTokens: Token[]) => void;
|
||||
render: (this: TagImpl, ctx: Context, hash: Hash, emitter: Emitter) => any;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { Liquid } from '../../liquid'
|
||||
import { TagImplOptions } from './tag-impl-options'
|
||||
|
||||
export interface TagImpl extends TagImplOptions {
|
||||
liquid: Liquid;
|
||||
[key: string]: any;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { TagImplOptions } from './tag-impl-options'
|
||||
import { assert } from '../../util/assert'
|
||||
|
||||
export class TagMap {
|
||||
private impls: {[key: string]: TagImplOptions} = {}
|
||||
|
||||
get (name: string) {
|
||||
const impl = this.impls[name]
|
||||
assert(impl, `tag "${name}" not found`)
|
||||
return impl
|
||||
}
|
||||
|
||||
set (name: string, impl: TagImplOptions) {
|
||||
this.impls[name] = impl
|
||||
}
|
||||
}
|
||||
+7
-15
@@ -1,21 +1,19 @@
|
||||
import { isFunction } from '../../util/underscore'
|
||||
import { assert } from '../../util/assert'
|
||||
import { Liquid } from '../../liquid'
|
||||
import { Template } from '../../template/template'
|
||||
import { Emitter, Hash, Context, ITagImplOptions, TagToken, ITemplate, Token } from '../../types'
|
||||
import { ITagImpl } from './itag-impl'
|
||||
import { TemplateImpl } from '../../template/template-impl'
|
||||
import { Emitter, Hash, Context, TagImplOptions, TagToken, Template, Token } from '../../types'
|
||||
import { TagImpl } from './tag-impl'
|
||||
|
||||
export class Tag extends Template<TagToken> implements ITemplate {
|
||||
export class Tag extends TemplateImpl<TagToken> implements Template {
|
||||
public name: string
|
||||
private impl: ITagImpl
|
||||
private static impls: { [key: string]: ITagImplOptions } = {}
|
||||
private impl: TagImpl
|
||||
private static impls: { [key: string]: TagImplOptions } = {}
|
||||
|
||||
public constructor (token: TagToken, tokens: Token[], liquid: Liquid) {
|
||||
super(token)
|
||||
this.name = token.name
|
||||
|
||||
const impl = Tag.impls[token.name]
|
||||
assert(impl, `tag ${token.name} not found`)
|
||||
const impl = liquid.tags.get(token.name)
|
||||
|
||||
this.impl = Object.create(impl)
|
||||
this.impl.liquid = liquid
|
||||
@@ -28,10 +26,4 @@ export class Tag extends Template<TagToken> implements ITemplate {
|
||||
const impl = this.impl
|
||||
if (isFunction(impl.render)) return yield impl.render(ctx, hash, emitter)
|
||||
}
|
||||
public static register (name: string, tag: ITagImplOptions) {
|
||||
Tag.impls[name] = tag
|
||||
}
|
||||
public static clear () {
|
||||
Tag.impls = {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
export abstract class TemplateImpl<T> {
|
||||
public token: T;
|
||||
public constructor (token: T) {
|
||||
this.token = token
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
export abstract class Template<T> {
|
||||
public token: T;
|
||||
public constructor (token: T) {
|
||||
this.token = token
|
||||
}
|
||||
import { Context } from '../context/context'
|
||||
import { Token } from '../parser/token'
|
||||
import { Emitter } from '../render/emitter'
|
||||
|
||||
export interface Template {
|
||||
token: Token;
|
||||
render(ctx: Context, emitter: Emitter): any;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
import { Expression } from '../render/expression'
|
||||
import { FilterMap } from '../template/filter/filter-map'
|
||||
import { FilterArgs, Filter } from './filter/filter'
|
||||
import { Context } from '../context/context'
|
||||
|
||||
export class Value {
|
||||
public readonly filters: Filter[] = []
|
||||
public readonly initial: string
|
||||
private strictFilters: boolean
|
||||
|
||||
/**
|
||||
* @param str value string, like: "i have a dream | truncate: 3
|
||||
*/
|
||||
public constructor (str: string, strictFilters: boolean) {
|
||||
public constructor (str: string, private readonly filterMap: FilterMap) {
|
||||
const tokens = Value.tokenize(str)
|
||||
this.strictFilters = strictFilters
|
||||
this.initial = tokens[0]
|
||||
this.parseFilters(tokens, 1)
|
||||
}
|
||||
@@ -45,7 +44,7 @@ export class Value {
|
||||
argValue = tokens[i]
|
||||
}
|
||||
}
|
||||
this.filters.push(new Filter(name, args, this.strictFilters))
|
||||
this.filters.push(new Filter(name, this.filterMap.get(name), args))
|
||||
}
|
||||
public * value (ctx: Context) {
|
||||
let val = yield new Expression(this.initial).evaluate(ctx)
|
||||
|
||||
Reference in New Issue
Block a user