style: introduce @typescript-eslint/recommended

This commit is contained in:
harttle
2019-07-06 14:33:34 +08:00
parent e6f5f1cd85
commit 88c89fe3b3
48 changed files with 260 additions and 235 deletions
+9 -1
View File
@@ -1,5 +1,5 @@
{
"extends": "standard",
"extends": ["standard", "plugin:@typescript-eslint/recommended"],
"env": {
"mocha": true,
"es6": true,
@@ -17,6 +17,14 @@
"no-var": 2,
"prefer-const": 2,
"no-unused-vars": "off",
"indent": "off",
"@typescript-eslint/indent": ["error", 2],
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-object-literal-type-assertion": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/interface-name-prefix": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"import/export": "off",
"@typescript-eslint/no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": false }]
}
+36 -23
View File
@@ -448,6 +448,12 @@
"integrity": "sha512-aRnpPa7ysx3aNW60hTiCtLHlQaIFsXFCgQlpakNgDNVFzbtusSY8PwjAQgRWfSk0ekNoBjO51eQRB6upA9uuyw==",
"dev": true
},
"@types/eslint-visitor-keys": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
"integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==",
"dev": true
},
"@types/estree": {
"version": "0.0.39",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
@@ -568,31 +574,44 @@
"dev": true
},
"@typescript-eslint/eslint-plugin": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.3.0.tgz",
"integrity": "sha512-s+vjO9+PvYS2A6FnQC/imyEDOkrEKIzSpPf2OEGnkKqa5+1d0cuXgCi/oROtuBht2/u/iK22nrYcO/Ei4R8F/g==",
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.11.0.tgz",
"integrity": "sha512-mXv9ccCou89C8/4avKHuPB2WkSZyY/XcTQUXd5LFZAcLw1I3mWYVjUu6eS9Ja0QkP/ClolbcW9tb3Ov/pMdcqw==",
"dev": true,
"requires": {
"@typescript-eslint/parser": "1.3.0",
"requireindex": "^1.2.0",
"@typescript-eslint/experimental-utils": "1.11.0",
"eslint-utils": "^1.3.1",
"functional-red-black-tree": "^1.0.1",
"regexpp": "^2.0.1",
"tsutils": "^3.7.0"
}
},
"@typescript-eslint/parser": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.3.0.tgz",
"integrity": "sha512-Q5cz9nyEQyRrtItRElvQXdNs0Xja1xvOdphDQR7N6MqUdi4juWVNxHKypdHQCx9OcEBev6pWHOda8lwg/2W9/g==",
"@typescript-eslint/experimental-utils": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.11.0.tgz",
"integrity": "sha512-7LbfaqF6B8oa8cp/315zxKk8FFzosRzzhF8Kn/ZRsRsnpm7Qcu25cR/9RnAQo5utZ2KIWVgaALr+ZmcbG47ruw==",
"dev": true,
"requires": {
"@typescript-eslint/typescript-estree": "1.3.0",
"eslint-scope": "^4.0.0",
"@typescript-eslint/typescript-estree": "1.11.0",
"eslint-scope": "^4.0.0"
}
},
"@typescript-eslint/parser": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.11.0.tgz",
"integrity": "sha512-5xBExyXaxVyczrZvbRKEXvaTUFFq7gIM9BynXukXZE0zF3IQP/FxF4mPmmh3gJ9egafZFqByCpPTFm3dk4SY7Q==",
"dev": true,
"requires": {
"@types/eslint-visitor-keys": "^1.0.0",
"@typescript-eslint/experimental-utils": "1.11.0",
"@typescript-eslint/typescript-estree": "1.11.0",
"eslint-visitor-keys": "^1.0.0"
}
},
"@typescript-eslint/typescript-estree": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.3.0.tgz",
"integrity": "sha512-h6UxHSmBUopFcxHg/eryrA+GwHMbh7PxotMbkq9p2f3nX60CKm5Zc0VN8krBD3IS5KqsK0iOz24VpEWrP+JZ2Q==",
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.11.0.tgz",
"integrity": "sha512-fquUHF5tAx1sM2OeRCC7wVxFd1iMELWMGCzOSmJ3pLzArj9+kRixdlC4d5MncuzXpjEqc6045p3KwM0o/3FuUA==",
"dev": true,
"requires": {
"lodash.unescape": "4.0.1",
@@ -9316,12 +9335,6 @@
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
"dev": true
},
"requireindex": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz",
"integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==",
"dev": true
},
"resolve": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz",
@@ -10475,9 +10488,9 @@
"dev": true
},
"tsutils": {
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.8.0.tgz",
"integrity": "sha512-XQdPhgcoTbCD8baXC38PQ0vpTZ8T3YrE+vR66YIj/xvDt1//8iAhafpIT/4DmvzzC1QFapEImERu48Pa01dIUA==",
"version": "3.14.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.14.0.tgz",
"integrity": "sha512-SmzGbB0l+8I0QwsPgjooFRaRvHLBLNYM8SeQ0k6rtNDru5sCGeLJcZdwilNndN+GysuFjF5EIYgN8GfFG6UeUw==",
"dev": true,
"requires": {
"tslib": "^1.8.1"
+2 -1
View File
@@ -57,7 +57,8 @@
"@types/sinon": "^7.0.6",
"@types/sinon-chai": "^3.2.2",
"@types/supertest": "^2.0.7",
"@typescript-eslint/eslint-plugin": "^1.3.0",
"@typescript-eslint/eslint-plugin": "^1.11.0",
"@typescript-eslint/parser": "^1.11.0",
"benchmark": "^2.1.4",
"chai": "^4.2.0",
"chai-as-promised": "^7.1.1",
+1 -1
View File
@@ -9,7 +9,7 @@ export default {
'reverse': (v: any[]) => [...v].reverse(),
'sort': <T>(v: T[], arg: (lhs: T, rhs: T) => number) => v.sort(arg),
'size': (v: string | any[]) => v.length,
'concat': <T1, T2>(v: T1[], arg: T2[] | T2): Array<T1 | T2> => Array.prototype.concat.call(v, arg),
'concat': <T1, T2>(v: T1[], arg: T2[] | T2): (T1 | T2)[] => Array.prototype.concat.call(v, arg),
'slice': <T>(v: T[], begin: number, length: number = 1): T[] => {
begin = begin < 0 ? v.length + begin : begin
return v.slice(begin, begin + length)
+1 -1
View File
@@ -18,7 +18,7 @@ export default {
'times': (v: number, arg: number) => v * arg
}
function caseInsensitiveCmp (a, b) {
function caseInsensitiveCmp (a: any, b: any) {
if (!b) return -1
if (!a) return 1
a = toLowerCase.call(a)
+2 -2
View File
@@ -8,7 +8,7 @@ import ITagImplOptions from '../../template/tag/itag-impl-options'
const groupRE = new RegExp(`^(?:(${rValue.source})\\s*:\\s*)?(.*)$`)
const candidatesRE = new RegExp(rValue.source, 'g')
export default <ITagImplOptions>{
export default {
parse: function (tagToken: TagToken) {
let match: RegExpExecArray | null = groupRE.exec(tagToken.args) as RegExpExecArray
assert(match, `illegal tag: ${tagToken.raw}`)
@@ -40,4 +40,4 @@ export default <ITagImplOptions>{
return evalValue(candidate, ctx)
}
}
} as ITagImplOptions
+2 -2
View File
@@ -17,7 +17,7 @@ const re = new RegExp(`^(${identifier.source})\\s+in\\s+` +
`(?:\\s+(reversed))?` +
`(?:\\s+${hash.source})*$`)
export default <ITagImplOptions>{
export default {
type: 'block',
parse: function (tagToken: TagToken, remainTokens: Token[]) {
const match = re.exec(tagToken.args) as RegExpExecArray
@@ -79,4 +79,4 @@ export default <ITagImplOptions>{
ctx.pop()
return html
}
}
} as ITagImplOptions
+2 -2
View File
@@ -10,7 +10,7 @@ import ITagImplOptions from '../../template/tag/itag-impl-options'
const staticFileRE = /[^\s,]+/
const withRE = new RegExp(`with\\s+(${value.source})`)
export default <ITagImplOptions>{
export default {
parse: function (token: TagToken) {
let match = staticFileRE.exec(token.args)
if (match) this.staticValue = match[0]
@@ -51,4 +51,4 @@ export default <ITagImplOptions>{
ctx.setRegister('blockMode', originBlockMode)
return html
}
}
} as ITagImplOptions
+2 -2
View File
@@ -2,7 +2,7 @@ import TagToken from '../../parser/tag-token'
import Token from '../../parser/token'
import ITagImplOptions from '../../template/tag/itag-impl-options'
export default <ITagImplOptions>{
export default {
parse: function (tagToken: TagToken, remainTokens: Token[]) {
this.tokens = []
@@ -20,4 +20,4 @@ export default <ITagImplOptions>{
render: function () {
return this.tokens.map((token: Token) => token.raw).join('')
}
}
} as ITagImplOptions
+11 -11
View File
@@ -6,25 +6,25 @@ import { NormalizedFullOptions, applyDefault } from '../liquid-options'
import { Scope } from './scope'
export default class Context {
opts: NormalizedFullOptions
environments: Scope
private scopes: Array<Scope> = [{}]
private scopes: Scope[] = [{}]
private registers = {}
constructor (ctx: object = {}, opts?: NormalizedFullOptions) {
public environments: Scope
public opts: NormalizedFullOptions
public constructor (ctx: object = {}, opts?: NormalizedFullOptions) {
this.opts = applyDefault(opts)
this.environments = ctx
}
getRegister (key: string, defaultValue = {}) {
public getRegister (key: string, defaultValue = {}) {
return (this.registers[key] = this.registers[key] || defaultValue)
}
setRegister (key: string, value: any) {
public setRegister (key: string, value: any) {
return (this.registers[key] = value)
}
getAll () {
public getAll () {
return [this.environments, ...this.scopes]
.reduce((ctx, val) => __assign(ctx, val), {})
}
async get (path: string) {
public async get (path: string) {
const paths = await this.parseProp(path)
let ctx = this.findScope(paths[0]) || this.environments
for (const path of paths) {
@@ -35,13 +35,13 @@ export default class Context {
}
return ctx
}
push (ctx: object) {
public push (ctx: object) {
return this.scopes.push(ctx)
}
pop () {
public pop () {
return this.scopes.pop()
}
front () {
public front () {
return this.scopes[0]
}
private findScope (key: string) {
+3 -3
View File
@@ -1,8 +1,8 @@
import { Drop } from '../drop/drop'
type PlainObject = {
[key: string]: any
toLiquid?: () => any
interface PlainObject {
[key: string]: any;
toLiquid?: () => any;
}
export type Scope = PlainObject | Drop
+1 -1
View File
@@ -2,7 +2,7 @@ import { isNil, isString, toValue } from '../util/underscore'
import { EmptyDrop } from '../drop/empty-drop'
export class BlankDrop extends EmptyDrop {
equals (value: any) {
public equals (value: any) {
if (value === false) return true
if (isNil(toValue(value))) return true
if (isString(value)) return /^\s*$/.test(value)
+2 -2
View File
@@ -1,9 +1,9 @@
export abstract class Drop {
valueOf (): any {
public valueOf (): any {
return undefined
}
liquidMethodMissing (key: string): Promise<string | undefined> | string | undefined {
public liquidMethodMissing (key: string): Promise<string | undefined> | string | undefined {
return undefined
}
}
+6 -6
View File
@@ -3,24 +3,24 @@ import { IComparable } from './icomparable'
import { isObject, isString, isArray } from '../util/underscore'
export class EmptyDrop extends Drop implements IComparable {
equals (value: any) {
public equals (value: any) {
if (isString(value) || isArray(value)) return value.length === 0
if (isObject(value)) return Object.keys(value).length === 0
return false
}
gt () {
public gt () {
return false
}
geq () {
public geq () {
return false
}
lt () {
public lt () {
return false
}
leq () {
public leq () {
return false
}
valueOf () {
public valueOf () {
return ''
}
}
+10 -10
View File
@@ -2,33 +2,33 @@ import { Drop } from './drop'
export class ForloopDrop extends Drop {
protected i: number = 0
length: number
constructor (length: number) {
public length: number
public constructor (length: number) {
super()
this.length = length
}
next () {
public next () {
this.i++
}
index0 () {
public index0 () {
return this.i
}
index () {
public index () {
return this.i + 1
}
first () {
public first () {
return this.i === 0
}
last () {
public last () {
return this.i === this.length - 1
}
rindex () {
public rindex () {
return this.length - this.i
}
rindex0 () {
public rindex0 () {
return this.length - this.i - 1
}
valueOf () {
public valueOf () {
return JSON.stringify(this)
}
}
+5 -5
View File
@@ -1,11 +1,11 @@
import { isFunction } from '../util/underscore'
export interface IComparable {
equals: (rhs: any) => boolean
gt: (rhs: any) => boolean
geq: (rhs: any) => boolean
lt: (rhs: any) => boolean
leq: (rhs: any) => boolean
equals: (rhs: any) => boolean;
gt: (rhs: any) => boolean;
geq: (rhs: any) => boolean;
lt: (rhs: any) => boolean;
leq: (rhs: any) => boolean;
}
export function isComparable (arg: any): arg is IComparable {
+6 -6
View File
@@ -4,22 +4,22 @@ import { isNil, toValue } from '../util/underscore'
import { BlankDrop } from '../drop/blank-drop'
export class NullDrop extends Drop implements IComparable {
equals (value: any) {
public equals (value: any) {
return isNil(toValue(value)) || value instanceof BlankDrop
}
gt () {
public gt () {
return false
}
geq () {
public geq () {
return false
}
lt () {
public lt () {
return false
}
leq () {
public leq () {
return false
}
valueOf () {
public valueOf () {
return null
}
}
+6 -6
View File
@@ -2,24 +2,24 @@ import { ForloopDrop } from './forloop-drop'
export class TablerowloopDrop extends ForloopDrop {
private cols: number
constructor (length: number, cols: number) {
public constructor (length: number, cols: number) {
super(length)
this.length = length
this.cols = cols
}
row () {
public row () {
return Math.floor(this.i / this.cols) + 1
}
col0 () {
public col0 () {
return (this.i % this.cols)
}
col () {
public col () {
return this.col0() + 1
}
col_first () { // eslint-disable-line
public col_first () { // eslint-disable-line
return this.col0() === 0
}
col_last () { // eslint-disable-line
public col_last () { // eslint-disable-line
return this.col() === this.cols
}
}
+3 -3
View File
@@ -1,5 +1,5 @@
export default interface IFS {
exists: (filepath: string) => Promise<boolean>
readFile: (filepath:string) => Promise<string>
resolve: (root: string, file: string, ext: string) => string
exists: (filepath: string) => Promise<boolean>;
readFile: (filepath: string) => Promise<string>;
resolve: (root: string, file: string, ext: string) => string;
}
+32 -32
View File
@@ -3,57 +3,57 @@ import IFS from './fs/ifs'
export interface LiquidOptions {
/** `root` is a directory or an array of directories to resolve layouts and includes, as well as the filename passed in when calling `.renderFile()`. If an array, the files are looked up in the order they occur in the array. Defaults to `["."]` */
root?: string | string[]
root?: string | string[];
/** `extname` is used to lookup the template file when filepath doesn't include an extension name. Eg: setting to `".html"` will allow including file by basename. Defaults to `""`. */
extname?: string
extname?: string;
/** `cache` indicates whether or not to cache resolved templates. Defaults to `false`. */
cache?: boolean
cache?: boolean;
/** `dynamicPartials`: if set, treat `<filepath>` parameter in `{%include filepath %}`, `{%layout filepath%}` as a variable, otherwise as a literal value. Defaults to `true`. */
dynamicPartials?: boolean
dynamicPartials?: boolean;
/** `strictFilters` is used to enable strict filter existence. If set to `false`, undefined filters will be rendered as empty string. Otherwise, undefined filters will cause an exception. Defaults to `false`. */
strictFilters?: boolean
strictFilters?: boolean;
/** `strictVariables` is used to enable strict variable derivation. If set to `false`, undefined variables will be rendered as empty string. Otherwise, undefined variables will cause an exception. Defaults to `false`. */
strictVariables?: boolean
strictVariables?: boolean;
/** `trimTagRight` is used to strip blank characters (including ` `, `\t`, and `\r`) from the right of tags (`{% %}`) until `\n` (inclusive). Defaults to `false`. */
trimTagRight?: boolean
trimTagRight?: boolean;
/** `trimTagLeft` is similar to `trimTagRight`, whereas the `\n` is exclusive. Defaults to `false`. See Whitespace Control for details. */
trimTagLeft?: boolean
trimTagLeft?: boolean;
/** ``trimOutputRight` is used to strip blank characters (including ` `, `\t`, and `\r`) from the right of values (`{{ }}`) until `\n` (inclusive). Defaults to `false`. */
trimOutputRight?: boolean
trimOutputRight?: boolean;
/** `trimOutputLeft` is similar to `trimOutputRight`, whereas the `\n` is exclusive. Defaults to `false`. See Whitespace Control for details. */
trimOutputLeft?: boolean
trimOutputLeft?: boolean;
/** `tagDelimiterLeft` and `tagDelimiterRight` are used to override the delimiter for liquid tags **/
tagDelimiterLeft?: string,
tagDelimiterRight?: string,
tagDelimiterLeft?: string;
tagDelimiterRight?: string;
/** `outputDelimiterLeft` and `outputDelimiterRight` are used to override the delimiter for liquid outputs **/
outputDelimiterLeft?: string,
outputDelimiterRight?: string,
outputDelimiterLeft?: string;
outputDelimiterRight?: 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?: boolean,
greedy?: boolean;
/** `fs` is used to override the default file-system module with a custom implementation */
fs?: IFS
fs?: IFS;
}
interface NormalizedOptions extends LiquidOptions {
root?: string[]
root?: string[];
}
export interface NormalizedFullOptions extends NormalizedOptions {
root: string[]
extname: string
cache: boolean
dynamicPartials: boolean
strictFilters: boolean
strictVariables: boolean
trimTagRight: boolean
trimTagLeft: boolean
trimOutputRight: boolean
trimOutputLeft: boolean
tagDelimiterLeft: string,
tagDelimiterRight: string,
outputDelimiterLeft: string,
outputDelimiterRight: string,
greedy: boolean
root: string[];
extname: string;
cache: boolean;
dynamicPartials: boolean;
strictFilters: boolean;
strictVariables: boolean;
trimTagRight: boolean;
trimTagLeft: boolean;
trimOutputRight: boolean;
trimOutputLeft: boolean;
tagDelimiterLeft: string;
tagDelimiterRight: string;
outputDelimiterLeft: string;
outputDelimiterRight: string;
greedy: boolean;
}
const defaultOptions: NormalizedFullOptions = {
+17 -17
View File
@@ -25,7 +25,7 @@ export default class Liquid {
private tokenizer: Tokenizer
private fs: IFS
constructor (opts: LiquidOptions = {}) {
public constructor (opts: LiquidOptions = {}) {
this.options = applyDefault(normalize(opts))
this.parser = new Parser(this)
this.renderer = new Render()
@@ -35,20 +35,20 @@ export default class Liquid {
_.forOwn(builtinTags, (conf, name) => this.registerTag(name, conf))
_.forOwn(builtinFilters, (handler, name) => this.registerFilter(name, handler))
}
parse (html: string, filepath?: string) {
public parse (html: string, filepath?: string) {
const tokens = this.tokenizer.tokenize(html, filepath)
return this.parser.parse(tokens)
}
render (tpl: Array<ITemplate>, ctx?: object, opts?: LiquidOptions) {
public render (tpl: ITemplate[], ctx?: object, opts?: LiquidOptions) {
const options = { ...this.options, ...normalize(opts) }
const scope = new Context(ctx, options)
return this.renderer.renderTemplates(tpl, scope)
}
async parseAndRender (html: string, ctx?: object, opts?: LiquidOptions) {
public async parseAndRender (html: string, ctx?: object, opts?: LiquidOptions) {
const tpl = await this.parse(html)
return this.render(tpl, ctx, opts)
}
async getTemplate (file: string, opts?: LiquidOptions) {
public async getTemplate (file: string, opts?: LiquidOptions) {
const options = normalize(opts)
const roots = options.root ? [...options.root, ...this.options.root] : this.options.root
const paths = roots.map(root => this.fs.resolve(root, file, this.options.extname))
@@ -68,34 +68,34 @@ export default class Liquid {
err.code = 'ENOENT'
throw err
}
async renderFile (file: string, ctx?: object, opts?: LiquidOptions) {
public async renderFile (file: string, ctx?: object, opts?: LiquidOptions) {
const options = normalize(opts)
const templates = await this.getTemplate(file, options)
return this.render(templates, ctx, opts)
}
evalValue (str: string, ctx: Context) {
public evalValue (str: string, ctx: Context) {
return new Value(str, this.options.strictFilters).value(ctx)
}
registerFilter (name: string, filter: FilterImplOptions) {
public registerFilter (name: string, filter: FilterImplOptions) {
return Filter.register(name, filter)
}
registerTag (name: string, tag: ITagImplOptions) {
public registerTag (name: string, tag: ITagImplOptions) {
return Tag.register(name, tag)
}
plugin (plugin: (this: Liquid, L: typeof Liquid) => void) {
public plugin (plugin: (this: Liquid, L: typeof Liquid) => void) {
return plugin.call(this, Liquid)
}
express () {
public express () {
const self = this
return function (this: any, filePath: string, ctx: object, cb: (err: Error | null, html?: string) => void) {
const opts = { root: this.root }
self.renderFile(filePath, ctx, opts).then(html => cb(null, html), cb)
}
}
static default = Liquid
static isTruthy = isTruthy
static isFalsy = isFalsy
static evalExp = evalExp
static evalValue = evalValue
static Types = Types
public static default = Liquid
public static isTruthy = isTruthy
public static isFalsy = isFalsy
public static evalExp = evalExp
public static evalValue = evalValue
public static Types = Types
}
+1 -1
View File
@@ -2,7 +2,7 @@ import Token from './token'
import { last } from '../util/underscore'
export default class DelimitedToken extends Token {
constructor (
public constructor (
raw: string,
value: string,
input: string,
+2 -2
View File
@@ -1,12 +1,12 @@
import Token from './token'
export default class HTMLToken extends Token {
constructor (str: string, input: string, line: number, col: number, file?: string) {
public constructor (str: string, input: string, line: number, col: number, file?: string) {
super(str, input, line, col, file)
this.type = 'html'
this.value = str
}
static is (token: Token): token is HTMLToken {
public static is (token: Token): token is HTMLToken {
return token.type === 'html'
}
}
+2 -2
View File
@@ -3,7 +3,7 @@ import Token from './token'
import { NormalizedFullOptions } from '../liquid-options'
export default class OutputToken extends DelimitedToken {
constructor (
public constructor (
raw: string,
value: string,
input: string,
@@ -15,7 +15,7 @@ export default class OutputToken extends DelimitedToken {
super(raw, value, input, line, pos, options.trimOutputLeft, options.trimOutputRight, file)
this.type = 'output'
}
static is (token: Token): token is OutputToken {
public static is (token: Token): token is OutputToken {
return token.type === 'output'
}
}
+6 -6
View File
@@ -2,19 +2,19 @@ import Token from '../parser/token'
import ITemplate from '../template/itemplate'
import TagToken from './tag-token'
type ParseToken = ((token: Token, remainTokens: Array<Token>) => ITemplate)
type ParseToken = ((token: Token, remainTokens: Token[]) => ITemplate)
export default class ParseStream {
private tokens: Array<Token>
private tokens: Token[]
private handlers: {[key: string]: (arg: any) => void} = {}
private stopRequested: boolean = false
private parseToken: ParseToken
constructor (tokens: Array<Token>, parseToken: ParseToken) {
public constructor (tokens: Token[], parseToken: ParseToken) {
this.tokens = tokens
this.parseToken = parseToken
}
on<T extends ITemplate | Token | undefined> (name: string, cb: (arg: T) => void): ParseStream {
public on<T extends ITemplate | Token | undefined> (name: string, cb: (arg: T) => void): ParseStream {
this.handlers[name] = cb
return this
}
@@ -22,7 +22,7 @@ export default class ParseStream {
const h = this.handlers[event]
return h ? (h(arg), true) : false
}
start () {
public start () {
this.trigger('start')
let token: Token | undefined
while (!this.stopRequested && (token = this.tokens.shift())) {
@@ -36,7 +36,7 @@ export default class ParseStream {
if (!this.stopRequested) this.trigger('end')
return this
}
stop () {
public stop () {
this.stopRequested = true
return this
}
+5 -5
View File
@@ -10,12 +10,12 @@ import HTML from '../template/html'
import ITemplate from '../template/itemplate'
export default class Parser {
liquid: Liquid
private liquid: Liquid
constructor (liquid: Liquid) {
public constructor (liquid: Liquid) {
this.liquid = liquid
}
parse (tokens: Array<Token>) {
public parse (tokens: Token[]) {
let token
const templates: ITemplate[] = []
while ((token = tokens.shift())) {
@@ -23,7 +23,7 @@ export default class Parser {
}
return templates
}
parseToken (token: Token, remainTokens: Array<Token>) {
public parseToken (token: Token, remainTokens: Token[]) {
try {
if (TagToken.is(token)) {
return new Tag(token, remainTokens, this.liquid)
@@ -36,7 +36,7 @@ export default class Parser {
throw new ParseError(e, token)
}
}
parseStream (tokens: Array<Token>) {
public parseStream (tokens: Token[]) {
return new ParseStream(tokens, (token, tokens) => this.parseToken(token, tokens))
}
}
+4 -4
View File
@@ -5,9 +5,9 @@ import * as lexical from './lexical'
import { NormalizedFullOptions } from '../liquid-options'
export default class TagToken extends DelimitedToken {
name: string
args: string
constructor (
public name: string
public args: string
public constructor (
raw: string,
value: string,
input: string,
@@ -25,7 +25,7 @@ export default class TagToken extends DelimitedToken {
this.name = match[1]
this.args = match[2]
}
static is (token: Token): token is TagToken {
public static is (token: Token): token is TagToken {
return token.type === 'tag'
}
}
+10 -10
View File
@@ -1,14 +1,14 @@
export default class Token {
trimLeft: boolean = false
trimRight: boolean = false
type: string = 'notset'
line: number
col: number
raw: string
input: string
file?: string
value: string
constructor (raw: string, input: string, line: number, col: number, file?: string) {
public trimLeft: boolean = false
public trimRight: boolean = false
public type: string = 'notset'
public line: number
public col: number
public raw: string
public input: string
public file?: string
public value: string
public constructor (raw: string, input: string, line: number, col: number, file?: string) {
this.col = col
this.line = line
this.raw = raw
+2 -2
View File
@@ -10,10 +10,10 @@ enum ParseState { HTML, OUTPUT, TAG }
export default class Tokenizer {
private options: NormalizedFullOptions
constructor (options?: NormalizedFullOptions) {
public constructor (options?: NormalizedFullOptions) {
this.options = applyDefault(options)
}
tokenize (input: string, file?: string) {
public tokenize (input: string, file?: string) {
const tokens: Token[] = []
const {
tagDelimiterLeft,
+1 -1
View File
@@ -4,7 +4,7 @@ import Context from '../context/context'
import ITemplate from '../template/itemplate'
export default class Render {
async renderTemplates (templates: ITemplate[], ctx: Context) {
public async renderTemplates (templates: ITemplate[], ctx: Context) {
assert(ctx, 'unable to evalTemplates: context undefined')
let html = ''
+1 -1
View File
@@ -1,5 +1,5 @@
import Context from '../../context/context'
export interface FilterImpl {
context: Context
context: Context;
}
+8 -8
View File
@@ -5,15 +5,15 @@ import { FilterImplOptions } from './filter-impl-options'
type KeyValuePair = [string?, string?]
type FilterArg = string|KeyValuePair
export type FilterArgs = Array<FilterArg>
export type FilterArgs = FilterArg[]
export class Filter {
name: string
impl: FilterImplOptions
args: FilterArgs
private name: string
private impl: FilterImplOptions
private args: FilterArgs
private static impls: {[key: string]: FilterImplOptions} = {}
constructor (name: string, args: FilterArgs, strictFilters: boolean) {
public constructor (name: string, args: FilterArgs, strictFilters: boolean) {
const impl = Filter.impls[name]
if (!impl && strictFilters) throw new TypeError(`undefined filter: ${name}`)
@@ -21,7 +21,7 @@ export class Filter {
this.impl = impl || (x => x)
this.args = args
}
async render (value: any, context: Context) {
public async render (value: any, context: Context) {
const argv: any[] = []
for (const arg of this.args) {
if (isKeyValuePair(arg)) argv.push([arg[0], await parseValue(arg[1], context)])
@@ -29,10 +29,10 @@ export class Filter {
}
return this.impl.apply({ context }, [value, ...argv])
}
static register (name: string, filter: FilterImplOptions) {
public static register (name: string, filter: FilterImplOptions) {
Filter.impls[name] = filter
}
static clear () {
public static clear () {
Filter.impls = {}
}
}
+3 -3
View File
@@ -3,12 +3,12 @@ import ITemplate from '../template/itemplate'
import HTMLToken from '../parser/html-token'
export default class extends Template<HTMLToken> implements ITemplate {
str: string
constructor (token: HTMLToken) {
private str: string
public constructor (token: HTMLToken) {
super(token)
this.str = token.value
}
async render (): Promise<string> {
public async render (): Promise<string> {
return this.str
}
}
+3 -3
View File
@@ -6,12 +6,12 @@ import Context from '../context/context'
import OutputToken from '../parser/output-token'
export default class Output extends Template<OutputToken> implements ITemplate {
value: Value
constructor (token: OutputToken, strictFilters: boolean) {
private value: Value
public constructor (token: OutputToken, strictFilters: boolean) {
super(token)
this.value = new Value(token.value, strictFilters)
}
async render (ctx: Context): Promise<string> {
public async render (ctx: Context): Promise<string> {
const val = await this.value.value(ctx)
return stringify(toValue(val))
}
+1 -1
View File
@@ -10,7 +10,7 @@ import Context from '../../context/context'
*/
export default class Hash {
[key: string]: any
static async create (markup: string, ctx: Context) {
public static async create (markup: string, ctx: Context) {
const instance = new Hash()
let match
hashCapture.lastIndex = 0
+2 -2
View File
@@ -5,6 +5,6 @@ import Hash from '../../template/tag/hash'
import ITagImpl from './itag-impl'
export default interface ITagImplOptions {
parse?: (this: ITagImpl, token: TagToken, remainingTokens: Array<Token>) => void
render?: (this: ITagImpl, ctx: Context, hash: Hash) => any | Promise<any>
parse?: (this: ITagImpl, token: TagToken, remainingTokens: Token[]) => void;
render?: (this: ITagImpl, ctx: Context, hash: Hash) => any | Promise<any>;
}
+2 -2
View File
@@ -2,6 +2,6 @@ import Liquid from '../../liquid'
import ITagImplOptions from './itag-impl-options'
export default interface ITagImpl extends ITagImplOptions {
liquid: Liquid,
[key: string]: any
liquid: Liquid;
[key: string]: any;
}
+6 -6
View File
@@ -11,11 +11,11 @@ import TagToken from '../../parser/tag-token'
import Token from '../../parser/token'
export default class Tag extends Template<TagToken> implements ITemplate {
name: string
public name: string
private impl: ITagImpl
static impls: { [key: string]: ITagImplOptions } = {}
private static impls: { [key: string]: ITagImplOptions } = {}
constructor (token: TagToken, tokens: Token[], liquid: Liquid) {
public constructor (token: TagToken, tokens: Token[], liquid: Liquid) {
super(token)
this.name = token.name
@@ -28,15 +28,15 @@ export default class Tag extends Template<TagToken> implements ITemplate {
this.impl.parse(token, tokens)
}
}
async render (ctx: Context) {
public async render (ctx: Context) {
const hash = await Hash.create(this.token.args, ctx)
const impl = this.impl
return isFunction(impl.render) ? stringify(await impl.render(ctx, hash)) : ''
}
static register (name: string, tag: ITagImplOptions) {
public static register (name: string, tag: ITagImplOptions) {
Tag.impls[name] = tag
}
static clear () {
public static clear () {
Tag.impls = {}
}
}
+2 -2
View File
@@ -1,6 +1,6 @@
export default abstract class Template<T> {
token: T;
constructor (token: T) {
public token: T;
public constructor (token: T) {
this.token = token
}
}
+5 -5
View File
@@ -5,12 +5,12 @@ import Context from '../context/context'
export default class Value {
private strictFilters: boolean
private initial: string
private filters: Array<Filter> = []
private filters: Filter[] = []
/**
* @param str value string, like: "i have a dream | truncate: 3
*/
constructor (str: string, strictFilters: boolean) {
public constructor (str: string, strictFilters: boolean) {
const tokens = Value.tokenize(str)
this.strictFilters = strictFilters
this.initial = tokens[0]
@@ -35,7 +35,7 @@ export default class Value {
for (let i = begin + 1; i < end + 1; i++) {
if (i === end || tokens[i] === ',') {
if (argName || argValue) {
args.push(argName ? [argName, argValue] : <string>argValue)
args.push(argName ? [argName, argValue] : argValue as string)
}
argValue = argName = undefined
} else if (tokens[i] === ':') {
@@ -47,14 +47,14 @@ export default class Value {
}
this.filters.push(new Filter(name, args, this.strictFilters))
}
async value (ctx: Context) {
public async value (ctx: Context) {
let val = await parseExp(this.initial, ctx)
for (const filter of this.filters) {
val = await filter.render(val, ctx)
}
return val
}
static tokenize (str: string): Array<'|' | ',' | ':' | string> {
public static tokenize (str: string): ('|' | ',' | ':' | string)[] {
const tokens = []
let i = 0
while (i < str.length) {
+7 -7
View File
@@ -5,7 +5,7 @@ import ITemplate from '../template/itemplate'
abstract class LiquidError extends Error {
private token: Token
private originalError: Error
constructor (err: Error, token: Token) {
public constructor (err: Error, token: Token) {
super(err.message)
this.originalError = err
this.token = token
@@ -20,7 +20,7 @@ abstract class LiquidError extends Error {
}
export class TokenizationError extends LiquidError {
constructor (message: string, token: Token) {
public constructor (message: string, token: Token) {
super(new Error(message), token)
this.name = 'TokenizationError'
super.update()
@@ -28,7 +28,7 @@ export class TokenizationError extends LiquidError {
}
export class ParseError extends LiquidError {
constructor (err: Error, token: Token) {
public constructor (err: Error, token: Token) {
super(err, token)
this.name = 'ParseError'
this.message = err.message
@@ -37,7 +37,7 @@ export class ParseError extends LiquidError {
}
export class RenderError extends LiquidError {
constructor (err: Error, tpl: ITemplate) {
public constructor (err: Error, tpl: ITemplate) {
super(err, tpl.token)
this.name = 'RenderError'
this.message = err.message
@@ -46,8 +46,8 @@ export class RenderError extends LiquidError {
}
export class RenderBreakError extends Error {
resolvedHTML: string = ''
constructor (message: string) {
public resolvedHTML: string = ''
public constructor (message: string) {
super(message)
this.name = 'RenderBreakError'
this.message = message + ''
@@ -55,7 +55,7 @@ export class RenderBreakError extends Error {
}
export class AssertionError extends Error {
constructor (message: string) {
public constructor (message: string) {
super(message)
this.name = 'AssertionError'
this.message = message + ''
+1 -1
View File
@@ -16,7 +16,7 @@ export function isFunction (value: any): value is Function {
}
export function promisify<T1, T2> (fn: (arg1: T1, cb: (err: Error | null, result: T2) => void) => void): (arg1: T1) => Promise<T2>;
export function promisify<T1, T2, T3> (fn: (arg1: T1, arg2: T2, cb: (err: Error | null, result: T3) => void) => void):(arg1: T1, arg2: T2) => Promise<T3>;
export function promisify<T1, T2, T3> (fn: (arg1: T1, arg2: T2, cb: (err: Error | null, result: T3) => void) => void): (arg1: T1, arg2: T2) => Promise<T3>;
export function promisify (fn: any) {
return function (...args: any[]) {
return new Promise((resolve, reject) => {
+6 -6
View File
@@ -5,11 +5,11 @@ import * as chaiAsPromised from 'chai-as-promised'
use(chaiAsPromised)
class SettingsDrop extends Liquid.Types.Drop {
foo: string = 'FOO'
bar () {
private foo: string = 'FOO'
public bar () {
return 'BAR'
}
liquidMethodMissing (key: string) {
public liquidMethodMissing (key: string) {
return key.toUpperCase()
}
}
@@ -29,10 +29,10 @@ describe('drop', function () {
describe('BlandDrop', function () {
it('should test blank strings', async function () {
const src = `
{% unless settings.fp_heading == blank %}
<h1>{{ settings.fp_heading }}</h1>
{% unless settings.fpHeading == blank %}
<h1>{{ settings.fpHeading }}</h1>
{% endunless %}`
var ctx = { settings: { fp_heading: '' } }
var ctx = { settings: { fpHeading: '' } }
const html = await engine.parseAndRender(src, ctx)
return expect(html).to.match(/^\s+$/)
})
+2 -2
View File
@@ -136,7 +136,7 @@ describe('xhr', () => {
[200, { 'Content-Type': 'text/plain' }, 'foo2'])
return engine.renderFile('foo.html')
})
.then((html:string) => expect(html).to.equal('foo2'))
.then((html: string) => expect(html).to.equal('foo2'))
})
it('should respect cache=true option', () => {
engine = new Liquid({
@@ -153,7 +153,7 @@ describe('xhr', () => {
[200, { 'Content-Type': 'text/plain' }, 'foo2'])
return engine.renderFile('foo.html')
})
.then((html:string) => expect(html).to.equal('foo1'))
.then((html: string) => expect(html).to.equal('foo1'))
})
})
})
+2 -2
View File
@@ -85,7 +85,7 @@ describe('tags/include', function () {
})
it('should support include: with as Liquid Drop', async function () {
class ColorDrop extends Liquid.Types.Drop {
valueOf (): string {
public valueOf (): string {
return 'red!'
}
}
@@ -98,7 +98,7 @@ describe('tags/include', function () {
})
it('should support include: with passed as Liquid Drop', async function () {
class ColorDrop extends Liquid.Types.Drop {
valueOf (): string {
public valueOf (): string {
return 'red!'
}
}
+6 -6
View File
@@ -6,22 +6,22 @@ describe('drop/drop', function () {
before(() => (liquid = new Liquid()))
class CustomDrop extends Liquid.Types.Drop {
name: string = 'NAME'
getName () {
private name: string = 'NAME'
public getName () {
return 'GET NAME'
}
}
class CustomDropWithMethodMissing extends CustomDrop {
liquidMethodMissing (key: string) {
public liquidMethodMissing (key: string) {
return key.toUpperCase()
}
}
class PromiseDrop extends Liquid.Types.Drop {
name = Promise.resolve('NAME')
async getName () {
private name = Promise.resolve('NAME')
public async getName () {
return 'GET NAME'
}
async liquidMethodMissing (key: string) {
public async liquidMethodMissing (key: string) {
return key.toUpperCase()
}
}
+7 -4
View File
@@ -2,17 +2,20 @@ import { isString, forOwn } from '../../src/util/underscore'
import fs from '../../src/fs/node'
import { resolve } from 'path'
type fileDescriptor = { mode: string, content: string }
interface FileDescriptor {
mode: string;
content: string;
}
let files: { [path: string]: fileDescriptor } = {}
let files: { [path: string]: FileDescriptor } = {}
const readFile = fs.readFile
const exists = fs.exists
export function mock (options: { [path: string]: (string | fileDescriptor) }) {
export function mock (options: { [path: string]: (string | FileDescriptor) }) {
forOwn(options, (val, key) => {
files[resolve(key)] = isString(val)
? { mode: '33188', content: val }
: val as fileDescriptor
: val as FileDescriptor
})
fs.readFile = async function (path) {
const file = files[path]
+4 -4
View File
@@ -1,12 +1,12 @@
import * as chai from 'chai'
import { isRange } from '../../../src/parser/lexical'
const expect = chai.expect
const lexical = require('../../../src/parser/lexical')
describe('lexical', function () {
it('should test range literal', function () {
expect(lexical.isRange('(12..32)')).to.equal(true)
expect(lexical.isRange('(12..foo)')).to.equal(true)
expect(lexical.isRange('(foo.bar..foo)')).to.equal(true)
expect(isRange('(12..32)')).to.equal(true)
expect(isRange('(12..foo)')).to.equal(true)
expect(isRange('(foo.bar..foo)')).to.equal(true)
})
})