refactor: strictly typed

This commit is contained in:
harttle
2019-02-23 00:49:54 +08:00
parent 51f7e66f60
commit 5b6100d12b
86 changed files with 2630 additions and 2590 deletions
+3
View File
@@ -0,0 +1,3 @@
type FilterImpl = (value: any, ...args: any[]) => any
export default FilterImpl
@@ -2,19 +2,18 @@ import assert from 'src/util/assert'
import * as lexical from 'src/parser/lexical'
import { evalValue } from 'src/render/syntax'
import Scope from 'src/scope/scope'
type impl = (value: any, ...args: any[]) => any
import FilterImpl from './filter-impl'
const valueRE = new RegExp(`${lexical.value.source}`, 'g')
export default class Filter {
name: string
impl: impl
impl: FilterImpl
args: string[]
private static impls: {[key: string]: impl} = {}
private static impls: {[key: string]: FilterImpl} = {}
constructor (str: string, strictFilters: boolean = false) {
const match = lexical.filterLine.exec(str)
const match = lexical.filterLine.exec(str) as string[]
assert(match, 'illegal filter: ' + str)
const name = match[1]
@@ -27,7 +26,7 @@ export default class Filter {
this.args = this.parseArgs(argList)
}
parseArgs (argList: string): string[] {
let match; const args = []
let match; const args: string[] = []
while ((match = valueRE.exec(argList.trim()))) {
const v = match[0]
const re = new RegExp(`${v}\\s*:`, 'g')
@@ -39,10 +38,9 @@ export default class Filter {
}
render (value: any, scope: Scope): any {
const args = this.args.map(arg => evalValue(arg, scope))
args.unshift(value)
return this.impl.apply(null, args)
return this.impl.apply(null, [value, ...args])
}
static register (name, filter) {
static register (name: string, filter: FilterImpl) {
Filter.impls[name] = filter
}
static clear () {
+3 -3
View File
@@ -1,10 +1,10 @@
import Template from 'src/template/template'
import ITemplate from 'src/template/itemplate'
import Token from 'src/parser/token'
import HTMLToken from 'src/parser/html-token'
export default class extends Template implements ITemplate {
export default class extends Template<HTMLToken> implements ITemplate {
str: string
constructor (token: Token) {
constructor (token: HTMLToken) {
super(token)
this.str = token.value
}
+1 -1
View File
@@ -5,7 +5,7 @@ import ITemplate from 'src/template/itemplate'
import Scope from 'src/scope/scope'
import OutputToken from 'src/parser/output-token'
export default class Output extends Template implements ITemplate {
export default class Output extends Template<OutputToken> implements ITemplate {
value: Value
constructor (token: OutputToken, strictFilters?: boolean) {
super(token)
+45
View File
@@ -0,0 +1,45 @@
import { create, stringify } from 'src/util/underscore'
import assert from 'src/util/assert'
import Scope from 'src/scope/scope'
import ITagImpl from './itag-impl'
import ITagImplOptions from './itag-impl-options'
import Liquid from 'src/liquid'
import Hash from './hash'
import Template from 'src/template/template'
import ITemplate from 'src/template/itemplate'
import TagToken from 'src/parser/tag-token'
import Token from 'src/parser/token'
export default class Tag extends Template<TagToken> implements ITemplate {
name: string
private impl: ITagImpl
static impls: { [key: string]: ITagImplOptions } = {}
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`)
this.impl = create<ITagImplOptions, ITagImpl>(impl)
this.impl.liquid = liquid
if (this.impl.parse) {
this.impl.parse(token, tokens)
}
}
async render (scope: Scope) {
const hash = new Hash(this.token.args, scope)
const impl = this.impl
if (typeof impl.render !== 'function') {
return ''
}
const html = await impl.render(scope, hash)
return stringify(html)
}
static register (name: string, tag: ITagImplOptions) {
Tag.impls[name] = tag
}
static clear () {
Tag.impls = {}
}
}
+2 -1
View File
@@ -1,5 +1,6 @@
import { hashCapture } from 'src/parser/lexical'
import { evalValue } from 'src/render/syntax'
import Scope from 'src/scope/scope';
/**
* Key-Value Pairs Representing Tag Arguments
@@ -9,7 +10,7 @@ import { evalValue } from 'src/render/syntax'
*/
export default class Hash {
[key: string]: any
constructor (markup, scope) {
constructor (markup: string, scope: Scope) {
let match
hashCapture.lastIndex = 0
while ((match = hashCapture.exec(markup))) {
+2 -1
View File
@@ -2,5 +2,6 @@ import Liquid from 'src/liquid'
import ITagImplOptions from './itag-impl-options'
export default interface ITagImpl extends ITagImplOptions {
liquid: Liquid
liquid: Liquid,
[key: string]: any
}
+1 -2
View File
@@ -10,9 +10,8 @@ import ITemplate from 'src/template/itemplate'
import TagToken from 'src/parser/tag-token'
import Token from 'src/parser/token'
export default class Tag extends Template implements ITemplate {
export default class Tag extends Template<TagToken> implements ITemplate {
name: string
token: TagToken
private impl: ITagImpl
static impls: { [key: string]: ITagImplOptions } = {}
+3 -5
View File
@@ -1,8 +1,6 @@
import Token from 'src/parser/token'
export default class Template {
token: Token;
constructor (token) {
export default abstract class Template<T> {
token: T;
constructor (token: T) {
this.token = token
}
}
+5 -9
View File
@@ -1,26 +1,22 @@
import { evalExp } from 'src/render/syntax'
import * as lexical from 'src/parser/lexical'
import assert from 'src/util/assert'
import Filter from './filter'
import Filter from './filter/filter'
import Scope from 'src/scope/scope'
export default class {
initial: any
filters: Array<any>
filters: Array<Filter> = []
constructor (str: string, strictFilters?: boolean) {
let match = lexical.matchValue(str)
let match: RegExpExecArray | null = lexical.matchValue(str) as RegExpExecArray
assert(match, `illegal value string: ${str}`)
const initial = match[0]
this.initial = match[0]
str = str.substr(match.index + match[0].length)
const filters = []
while ((match = lexical.filter.exec(str))) {
filters.push([match[0].trim()])
this.filters.push(new Filter(match[0].trim(), strictFilters))
}
this.initial = initial
this.filters = filters.map(str => new Filter(str, strictFilters))
}
value (scope: Scope) {
return this.filters.reduce(