mirror of
https://github.com/harttle/liquidjs.git
synced 2026-09-17 05:10:40 -07:00
refactor: strictly typed
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
import Token from './token'
|
||||
import { last } from 'src/util/underscore'
|
||||
|
||||
export default class DelimitedToken extends Token {
|
||||
trimLeft: boolean
|
||||
trimRight: boolean
|
||||
constructor (raw, value, pos, input, file, line) {
|
||||
super(raw, pos, input, file, line)
|
||||
constructor (raw: string, value: string, input: string, line: number, pos: number, file?: string) {
|
||||
super(raw, input, line, pos, file)
|
||||
this.trimLeft = value[0] === '-'
|
||||
this.trimRight = value[value.length - 1] === '-'
|
||||
this.trimRight = last(value) === '-'
|
||||
this.value = value
|
||||
.slice(
|
||||
this.trimLeft ? 1 : 0,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import Token from './token'
|
||||
|
||||
export default class HTMLToken extends Token {
|
||||
constructor (str, begin, input, file, line) {
|
||||
super(str, begin, input, file, line)
|
||||
constructor (str: string, input: string, line: number, col: number, file?: string) {
|
||||
super(str, input, line, col, file)
|
||||
this.type = 'html'
|
||||
this.value = str
|
||||
}
|
||||
|
||||
@@ -49,27 +49,27 @@ export const operators = [
|
||||
/==|!=|<=|>=|<|>|\s+contains\s+/
|
||||
]
|
||||
|
||||
export function isInteger (str) {
|
||||
export function isInteger (str: string) {
|
||||
return integerLine.test(str)
|
||||
}
|
||||
|
||||
export function isLiteral (str) {
|
||||
export function isLiteral (str: string) {
|
||||
return literalLine.test(str)
|
||||
}
|
||||
|
||||
export function isRange (str) {
|
||||
export function isRange (str: string) {
|
||||
return rangeLine.test(str)
|
||||
}
|
||||
|
||||
export function isVariable (str) {
|
||||
export function isVariable (str: string) {
|
||||
return variableLine.test(str)
|
||||
}
|
||||
|
||||
export function matchValue (str) {
|
||||
export function matchValue (str: string) {
|
||||
return value.exec(str)
|
||||
}
|
||||
|
||||
export function parseLiteral (str) {
|
||||
export function parseLiteral (str: string) {
|
||||
let res = str.match(numberLine)
|
||||
if (res) {
|
||||
return Number(str)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import DelimitedToken from './delimited-token'
|
||||
|
||||
export default class OutputToken extends DelimitedToken {
|
||||
constructor (raw, value, pos, input, file, line) {
|
||||
super(raw, value, pos, input, file, line)
|
||||
constructor (raw: string, value: string, input: string, line: number, pos: number, file?: string) {
|
||||
super(raw, value, input, line, pos, file)
|
||||
this.type = 'output'
|
||||
}
|
||||
}
|
||||
|
||||
+11
-11
@@ -1,37 +1,37 @@
|
||||
import Token from 'src/parser/token'
|
||||
import ITemplate from 'src/template/itemplate'
|
||||
import TagToken from './tag-token';
|
||||
|
||||
type parseToken = (token: Token, remainTokens: Array<Token>) => ITemplate
|
||||
type eventHandler = ((arg?: Token | ITemplate) => void)
|
||||
type ParseToken = ((token: Token, remainTokens: Array<Token>) => ITemplate)
|
||||
|
||||
export default class ParseStream {
|
||||
private tokens: Array<Token>
|
||||
private handlers: {[key: string]: eventHandler} = {}
|
||||
private stopRequested: boolean
|
||||
private parseToken: parseToken
|
||||
private handlers: {[key: string]: (arg: any) => void} = {}
|
||||
private stopRequested: boolean = false
|
||||
private parseToken: ParseToken
|
||||
|
||||
constructor (tokens: Array<Token>, parseToken: parseToken) {
|
||||
constructor (tokens: Array<Token>, parseToken: ParseToken) {
|
||||
this.tokens = tokens
|
||||
this.parseToken = parseToken
|
||||
}
|
||||
on (name: string, cb: eventHandler) {
|
||||
on<T extends ITemplate | Token | undefined> (name: string, cb: (arg: T) => void): ParseStream {
|
||||
this.handlers[name] = cb
|
||||
return this
|
||||
}
|
||||
trigger (event: string, arg?: Token | ITemplate) {
|
||||
trigger <T extends Token | ITemplate>(event: string, arg?: T) {
|
||||
const h = this.handlers[event]
|
||||
if (typeof h === 'function') {
|
||||
h(arg)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
start () {
|
||||
this.trigger('start')
|
||||
let token
|
||||
let token: Token | undefined
|
||||
while (!this.stopRequested && (token = this.tokens.shift())) {
|
||||
if (this.trigger('token', token)) continue
|
||||
if (token.type === 'tag' &&
|
||||
this.trigger(`tag:${token.name}`, token)) {
|
||||
if (token.type === 'tag' && this.trigger(`tag:${(<TagToken>token).name}`, token)) {
|
||||
continue
|
||||
}
|
||||
const template = this.parseToken(token, this.tokens)
|
||||
|
||||
@@ -7,6 +7,7 @@ import OutputToken from './output-token'
|
||||
import Tag from 'src/template/tag/tag'
|
||||
import Output from 'src/template/output'
|
||||
import HTML from 'src/template/html'
|
||||
import ITemplate from 'src/template/itemplate'
|
||||
|
||||
export default class Parser {
|
||||
liquid: Liquid
|
||||
@@ -16,7 +17,7 @@ export default class Parser {
|
||||
}
|
||||
parse (tokens: Array<Token>) {
|
||||
let token
|
||||
const templates = []
|
||||
const templates: ITemplate[] = []
|
||||
while ((token = tokens.shift())) {
|
||||
templates.push(this.parseToken(token, tokens))
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ import * as lexical from './lexical'
|
||||
export default class TagToken extends DelimitedToken {
|
||||
name: string
|
||||
args: string
|
||||
constructor (raw, value, pos, input, file, line) {
|
||||
super(raw, value, pos, input, file, line)
|
||||
constructor (raw: string, value: string, input: string, line: number, pos: number, file?: string) {
|
||||
super(raw, value, input, line, pos, file)
|
||||
this.type = 'tag'
|
||||
const match = this.value.match(lexical.tagLine)
|
||||
if (!match) {
|
||||
|
||||
+4
-3
@@ -1,15 +1,16 @@
|
||||
export default class Token {
|
||||
type: string
|
||||
type: string = 'notset'
|
||||
line: number
|
||||
col: number
|
||||
raw: string
|
||||
input: string
|
||||
file: string
|
||||
file?: string
|
||||
value: string
|
||||
constructor (raw, col, input, file, line) {
|
||||
constructor (raw: string, input: string, line: number, col: number, file?: string) {
|
||||
this.col = col
|
||||
this.line = line
|
||||
this.raw = raw
|
||||
this.value = raw
|
||||
this.input = input
|
||||
this.file = file
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ export default class Tokenizer {
|
||||
this.options = applyDefault(options)
|
||||
}
|
||||
tokenize (input: string, file?: string) {
|
||||
const tokens = []
|
||||
const tokens: Token[] = []
|
||||
const tagL = this.options.tag_delimiter_left
|
||||
const tagR = this.options.tag_delimiter_right
|
||||
const outputL = this.options.output_delimiter_left
|
||||
@@ -34,7 +34,7 @@ export default class Tokenizer {
|
||||
}
|
||||
if (state === ParseState.HTML) {
|
||||
if (input.substr(p, outputL.length) === outputL) {
|
||||
if (buffer) tokens.push(new HTMLToken(buffer, col, input, file, line))
|
||||
if (buffer) tokens.push(new HTMLToken(buffer, input, line, col, file))
|
||||
buffer = outputL
|
||||
line = curLine
|
||||
col = p - lineBegin + 1
|
||||
@@ -42,7 +42,7 @@ export default class Tokenizer {
|
||||
state = ParseState.OUTPUT
|
||||
continue
|
||||
} else if (input.substr(p, tagL.length) === tagL) {
|
||||
if (buffer) tokens.push(new HTMLToken(buffer, col, input, file, line))
|
||||
if (buffer) tokens.push(new HTMLToken(buffer, input, line, col, file))
|
||||
buffer = tagL
|
||||
line = curLine
|
||||
col = p - lineBegin + 1
|
||||
@@ -52,7 +52,7 @@ export default class Tokenizer {
|
||||
}
|
||||
} else if (state === ParseState.OUTPUT && input.substr(p, outputR.length) === outputR) {
|
||||
buffer += outputR
|
||||
tokens.push(new OutputToken(buffer, buffer.slice(outputL.length, -outputR.length), col, input, file, line))
|
||||
tokens.push(new OutputToken(buffer, buffer.slice(outputL.length, -outputR.length), input, line, col, file))
|
||||
p += outputR.length
|
||||
buffer = ''
|
||||
line = curLine
|
||||
@@ -61,7 +61,7 @@ export default class Tokenizer {
|
||||
continue
|
||||
} else if (input.substr(p, tagR.length) === tagR) {
|
||||
buffer += tagR
|
||||
tokens.push(new TagToken(buffer, buffer.slice(tagL.length, -tagR.length), col, input, file, line))
|
||||
tokens.push(new TagToken(buffer, buffer.slice(tagL.length, -tagR.length), input, line, col, file))
|
||||
p += tagR.length
|
||||
buffer = ''
|
||||
line = curLine
|
||||
@@ -75,11 +75,11 @@ export default class Tokenizer {
|
||||
const t = state === ParseState.OUTPUT ? 'output' : 'tag'
|
||||
const str = buffer.length > 16 ? buffer.slice(0, 13) + '...' : buffer
|
||||
throw new TokenizationError(
|
||||
new Error(`${t} "${str}" not closed`),
|
||||
new Token(buffer, col, input, file, line)
|
||||
`${t} "${str}" not closed`,
|
||||
new Token(buffer, input, line, col, file)
|
||||
)
|
||||
}
|
||||
if (buffer) tokens.push(new HTMLToken(buffer, col, input, file, line))
|
||||
if (buffer) tokens.push(new HTMLToken(buffer, input, line, col, file))
|
||||
|
||||
whiteSpaceCtrl(tokens, this.options)
|
||||
return tokens
|
||||
|
||||
@@ -21,13 +21,13 @@ export default function whiteSpaceCtrl (tokens: Token[], options: NormalizedFull
|
||||
})
|
||||
}
|
||||
|
||||
function shouldTrimLeft (token: DelimitedToken, inRaw: boolean, options) {
|
||||
function shouldTrimLeft (token: DelimitedToken, inRaw: boolean, options: NormalizedFullOptions) {
|
||||
if (inRaw) return false
|
||||
if (token.type === 'tag') return token.trimLeft || options.trim_tag_left
|
||||
if (token.type === 'output') return token.trimLeft || options.trim_output_left
|
||||
}
|
||||
|
||||
function shouldTrimRight (token: DelimitedToken, inRaw: boolean, options) {
|
||||
function shouldTrimRight (token: DelimitedToken, inRaw: boolean, options: NormalizedFullOptions) {
|
||||
if (inRaw) return false
|
||||
if (token.type === 'tag') return token.trimRight || options.trim_tag_right
|
||||
if (token.type === 'output') return token.trimRight || options.trim_output_right
|
||||
|
||||
Reference in New Issue
Block a user