From 542968e133f4760091da971af2da0cc1e0a09420 Mon Sep 17 00:00:00 2001 From: harttle Date: Sun, 24 Feb 2019 06:26:33 +0800 Subject: [PATCH] refactor: remove unused lexical regexps --- src/liquid-options.ts | 2 +- src/parser/lexical.ts | 43 ------------ src/render/syntax.ts | 15 ++--- src/scope/scope.ts | 3 +- src/template/tag/block-tag.ts | 45 ------------- test/stub/render.ts | 2 +- test/unit/parser/lexical.ts | 119 ---------------------------------- test/unit/render/syntax.ts | 24 ++++--- test/unit/template/value.ts | 9 ++- 9 files changed, 30 insertions(+), 232 deletions(-) delete mode 100644 src/template/tag/block-tag.ts diff --git a/src/liquid-options.ts b/src/liquid-options.ts index 52cb42710..95d667406 100644 --- a/src/liquid-options.ts +++ b/src/liquid-options.ts @@ -33,7 +33,7 @@ export interface LiquidOptions { greedy?: boolean } -export interface NormalizedOptions extends LiquidOptions { +interface NormalizedOptions extends LiquidOptions { root?: string[] } diff --git a/src/parser/lexical.ts b/src/parser/lexical.ts index ce710fefb..9048c3722 100644 --- a/src/parser/lexical.ts +++ b/src/parser/lexical.ts @@ -5,7 +5,6 @@ export const quoted = new RegExp(`${singleQuoted.source}|${doubleQuoted.source}` export const quoteBalanced = new RegExp(`(?:${quoted.source}|[^'"])*`) // basic types -export const integer = /-?\d+/ export const number = /[+-]?(?:\d+\.?\d*|\.?\d+)/ export const bool = /true|false/ @@ -28,20 +27,10 @@ export const hashCapture = new RegExp(`(${identifier.source})\\s*:\\s*(${value.s // full match export const tagLine = new RegExp(`^\\s*(${identifier.source})\\s*([\\s\\S]*?)\\s*$`) -export const literalLine = new RegExp(`^${literal.source}$`, 'i') -export const variableLine = new RegExp(`^${variable.source}$`) export const numberLine = new RegExp(`^${number.source}$`) export const boolLine = new RegExp(`^${bool.source}$`, 'i') export const quotedLine = new RegExp(`^${quoted.source}$`) export const rangeLine = new RegExp(`^${rangeCapture.source}$`) -export const integerLine = new RegExp(`^${integer.source}$`) - -// filter related -export const valueDeclaration = new RegExp(`(?:${identifier.source}\\s*:\\s*)?${value.source}`) -export const valueList = new RegExp(`${valueDeclaration.source}(\\s*,\\s*${valueDeclaration.source})*`) -export const filter = new RegExp(`${identifier.source}(?:\\s*:\\s*${valueList.source})?`, 'g') -export const filterCapture = new RegExp(`(${identifier.source})(?:\\s*:\\s*(${valueList.source}))?`) -export const filterLine = new RegExp(`^${filterCapture.source}$`) export const operators = [ /\s+or\s+/, @@ -49,38 +38,6 @@ export const operators = [ /==|!=|<=|>=|<|>|\s+contains\s+/ ] -export function isInteger (str: string) { - return integerLine.test(str) -} - -export function isLiteral (str: string) { - return literalLine.test(str) -} - export function isRange (str: string) { return rangeLine.test(str) } - -export function isVariable (str: string) { - return variableLine.test(str) -} - -export function matchValue (str: string) { - return value.exec(str) -} - -export function parseLiteral (str: string) { - let res = str.match(numberLine) - if (res) { - return Number(str) - } - res = str.match(boolLine) - if (res) { - return str.toLowerCase() === 'true' - } - res = str.match(quotedLine) - if (res) { - return str.slice(1, -1) - } - throw new TypeError(`cannot parse '${str}' as literal`) -} diff --git a/src/render/syntax.ts b/src/render/syntax.ts index 4ba09331c..bc2fdcfa3 100644 --- a/src/render/syntax.ts +++ b/src/render/syntax.ts @@ -1,7 +1,7 @@ import * as lexical from '../parser/lexical' import assert from '../util/assert' import Scope from 'src/scope/scope' -import { range } from 'src/util/underscore' +import { range, last } from 'src/util/underscore' const operators = { '==': (l: any, r: any) => l === r, @@ -46,15 +46,12 @@ export function evalExp (exp: string, scope: Scope): any { export function evalValue (str: string, scope: Scope) { if (!str) return null str = str.trim() - if (!str) return undefined - if (lexical.isLiteral(str)) { - return lexical.parseLiteral(str) - } - if (lexical.isVariable(str)) { - return scope.get(str) - } - throw new TypeError(`cannot eval '${str}' as value`) + if (str === 'true') return true + if (str === 'false') return false + if (!isNaN(Number(str))) return Number(str) + if ((str[0] === '"' || str[0] === "'") && str[0] === last(str)) return str.slice(1, -1) + return scope.get(str) } export function isTruthy (val: any): boolean { diff --git a/src/scope/scope.ts b/src/scope/scope.ts index 6aaa1a71f..03a7f0ccd 100644 --- a/src/scope/scope.ts +++ b/src/scope/scope.ts @@ -1,6 +1,5 @@ import * as _ from '../util/underscore' import { __assign } from 'tslib' -import * as lexical from '../parser/lexical' import assert from '../util/assert' import { NormalizedFullOptions, applyDefault } from '../liquid-options' import BlockMode from './block-mode' @@ -115,7 +114,7 @@ export default class Scope { j = matchRightBracket(str, i + 1) assert(j !== -1, `unbalanced []: ${str}`) name = str.slice(i + 1, j) - if (!lexical.isInteger(name)) { // foo[bar] vs. foo[1] + if (!/^[+-]?\d+$/.test(name)) { // foo[bar] vs. foo[1] name = String(this.get(name)) } push() diff --git a/src/template/tag/block-tag.ts b/src/template/tag/block-tag.ts deleted file mode 100644 index 656312681..000000000 --- a/src/template/tag/block-tag.ts +++ /dev/null @@ -1,45 +0,0 @@ -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 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(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 = {} - } -} diff --git a/test/stub/render.ts b/test/stub/render.ts index 47ff2d5dd..d7083e8df 100644 --- a/test/stub/render.ts +++ b/test/stub/render.ts @@ -1,7 +1,7 @@ import Liquid from 'src/liquid' import { expect } from 'chai' -export const liquid = new Liquid() +const liquid = new Liquid() export const ctx = { date: new Date(), diff --git a/test/unit/parser/lexical.ts b/test/unit/parser/lexical.ts index bfb0bb325..223d36edf 100644 --- a/test/unit/parser/lexical.ts +++ b/test/unit/parser/lexical.ts @@ -4,128 +4,9 @@ const expect = chai.expect const lexical = require('src/parser/lexical') describe('lexical', function () { - it('should test filter syntax', function () { - expect(lexical.filterLine.test('abs')).to.equal(true) - expect(lexical.filterLine.test('plus:1')).to.equal(true) - expect(lexical.filterLine.test('replace: "a", b')).to.equal(true) - expect(lexical.filterLine.test('foo: a, "b"')).to.equal(true) - expect(lexical.filterLine.test('abs | another')).to.equal(false) - expect(lexical.filterLine.test('join: "," | another')).to.equal(false) - expect(lexical.filterLine.test('obj_test: k1: "v1", k2: "v2"')).to.equal(true) - }) - - it('should test boolean literal', function () { - expect(lexical.isLiteral('true')).to.equal(true) - expect(lexical.isLiteral('TrUE')).to.equal(true) - expect(lexical.isLiteral('false')).to.equal(true) - }) - - it('should test number literal', function () { - expect(lexical.isLiteral('2.3')).to.equal(true) - expect(lexical.isLiteral('.3')).to.equal(true) - expect(lexical.isLiteral('-3.')).to.equal(true) - expect(lexical.isLiteral('23')).to.equal(true) - }) - 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) }) - - it('should test string literal', function () { - expect(lexical.isLiteral('""')).to.equal(true) - expect(lexical.isLiteral('"a\'b"')).to.equal(true) - expect(lexical.isLiteral("''")).to.equal(true) - expect(lexical.isLiteral("'a bcd'")).to.equal(true) - }) - - describe('.isVariable()', function () { - it('should return true for foo', function () { - expect(lexical.isVariable('foo')).to.equal(true) - }) - it('should return true for.bar.foo', function () { - expect(lexical.isVariable('foo.bar.foo')).to.equal(true) - }) - it('should return true for foo[0].b', function () { - expect(lexical.isVariable('foo[0].b')).to.equal(true) - }) - it('should return true for 0a', function () { - expect(lexical.isVariable('0a')).to.equal(true) - }) - it('should return true for foo[a.b]', function () { - expect(lexical.isVariable('foo[a.b]')).to.equal(true) - }) - it('should return true for foo[a.b]', function () { - expect(lexical.isVariable("foo['a[0]']")).to.equal(true) - }) - it('should return true for "var-1"', function () { - expect(lexical.isVariable('var-1')).to.equal(true) - }) - it('should return true for "-var"', function () { - expect(lexical.isVariable('-var')).to.equal(true) - }) - it('should return true for "var-"', function () { - expect(lexical.isVariable('var-')).to.equal(true) - }) - it('should return true for "3-4"', function () { - expect(lexical.isVariable('3-4')).to.equal(true) - }) - }) - - it('should test none literal', function () { - expect(lexical.isLiteral('2a')).to.equal(false) - expect(lexical.isLiteral('"x')).to.equal(false) - expect(lexical.isLiteral('a2')).to.equal(false) - }) - - it('should test none variable', function () { - expect(lexical.isVariable('a.')).to.equal(false) - expect(lexical.isVariable('.b')).to.equal(false) - expect(lexical.isVariable('.')).to.equal(false) - expect(lexical.isVariable('[0][12].bar[0]')).to.equal(false) - }) - - describe('.parseLiteral()', function () { - it('should parse boolean literal', function () { - expect(lexical.parseLiteral('true')).to.equal(true) - expect(lexical.parseLiteral('TrUE')).to.equal(true) - expect(lexical.parseLiteral('false')).to.equal(false) - }) - - it('should parse number literal', function () { - expect(lexical.parseLiteral('2.3')).to.equal(2.3) - expect(lexical.parseLiteral('.32')).to.equal(0.32) - expect(lexical.parseLiteral('-23.')).to.equal(-23) - expect(lexical.parseLiteral('23')).to.equal(23) - }) - - it('should parse string literal', function () { - expect(lexical.parseLiteral('"ab\'c"')).to.equal("ab'c") - }) - - it('should throw if non-literal', function () { - const fn = () => lexical.parseLiteral('a') - expect(fn).to.throw("cannot parse 'a' as literal") - }) - }) - - describe('.matchValue()', function () { - it('should match -5-5', function () { - const match = lexical.matchValue('-5-5') - expect(match && match[0]).to.equal('-5-5') - }) - it('should match 4-3', function () { - const match = lexical.matchValue('4-3') - expect(match && match[0]).to.equal('4-3') - }) - it('should match 4-3', function () { - const match = lexical.matchValue('4-3') - expect(match && match[0]).to.equal('4-3') - }) - it('should match var-1', function () { - const match = lexical.matchValue('var-1') - expect(match && match[0]).to.equal('var-1') - }) - }) }) diff --git a/test/unit/render/syntax.ts b/test/unit/render/syntax.ts index ed87f5d3f..d707159e8 100644 --- a/test/unit/render/syntax.ts +++ b/test/unit/render/syntax.ts @@ -18,22 +18,26 @@ describe('expression', function () { }) describe('.evalValue()', function () { - it('should eval literals', function () { - expect(evalValue('2.3', scope)).to.equal(2.3) - expect(evalValue('"foo"', scope)).to.equal('foo') + it('should eval boolean literal', function () { + expect(evalValue('true', scope)).to.equal(true) + expect(evalValue('TrUE', scope)).to.equal(undefined) + expect(evalValue('false', scope)).to.equal(false) }) - - it('should eval variables', function () { + it('should eval number literal', function () { + expect(evalValue('2.3', scope)).to.equal(2.3) + expect(evalValue('.32', scope)).to.equal(0.32) + expect(evalValue('-23.', scope)).to.equal(-23) expect(evalValue('23', scope)).to.equal(23) + }) + it('should eval literal', function () { + expect(evalValue('"ab\'c"', scope)).to.equal("ab'c") + expect(evalValue("'ab\"c'", scope)).to.equal('ab"c') + }) + it('should eval scope variables', function () { expect(evalValue('one', scope)).to.equal(1) expect(evalValue('has_value?', scope)).to.equal(true) expect(evalValue('x', scope)).to.equal('XXX') }) - - it('should throw if not valid', function () { - const fn = () => evalValue('===', scope) - expect(fn).to.throw("cannot eval '===' as value") - }) }) describe('.isTruthy()', function () { diff --git a/test/unit/template/value.ts b/test/unit/template/value.ts index 5ff44ada9..528580850 100644 --- a/test/unit/template/value.ts +++ b/test/unit/template/value.ts @@ -24,14 +24,19 @@ describe('Value', function () { expect(tpl.filters.length).to.equal(1) expect(tpl.filters[0].args).to.eql([]) }) - + it('should parse "foo | add: "foo" bar, 3"', function () { + const tpl: any = new Value('foo | add: "foo" bar, 3', false) + expect(tpl.initial).to.equal('foo') + expect(tpl.filters.length).to.equal(1) + expect(tpl.filters[0].name).to.eql('add') + expect(tpl.filters[0].args).to.eql(['"foo"', '3']) + }) it('should parse "foo | add: 3, false"', function () { const tpl: any = new Value('foo | add: 3, "foo"', false) expect(tpl.initial).to.equal('foo') expect(tpl.filters.length).to.equal(1) expect(tpl.filters[0].args).to.eql(['3', '"foo"']) }) - it('should parse "foo | add: "|", 3', function () { const tpl: any = new Value('foo | add: "|", 3', false) expect(tpl.initial).to.equal('foo')