chore: rename filters to snake style, #487

BREAKING CHANGE: keys in `<liquidjs>.filters` are now in snake case (instead of camel case), identical to that in Liquid template.
This commit is contained in:
Jun Yang
2022-11-27 14:04:00 +08:00
parent 907c4dea06
commit ff112a4750
38 changed files with 119 additions and 125 deletions
+5
View File
@@ -37,6 +37,11 @@
"@typescript-eslint/no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": false }]
},
"overrides": [{
"files": ["**/filters/*.ts"],
"rules": {
"camelcase": "off"
}
}, {
"files": ["**/*.js", "**/*.mjs"],
"rules": {
"@typescript-eslint/no-var-requires": "off"
-7
View File
@@ -1,7 +0,0 @@
export * from './html'
export * from './math'
export * from './url'
export * from './array'
export * from './date'
export * from './misc'
export * from './string'
-4
View File
@@ -1,4 +0,0 @@
import { stringify } from '../../util/underscore'
export const urlDecode = (x: string) => stringify(x).split('+').map(decodeURIComponent).join(' ')
export const urlEncode = (x: string) => stringify(x).split(' ').map(encodeURIComponent).join('+')
@@ -1,9 +1,9 @@
import { argumentsToValue, toValue, stringify, caseInsensitiveCompare, isArray, isNil, last as arrayLast, hasOwnProperty } from '../../util/underscore'
import { toArray } from '../../util/collection'
import { isTruthy } from '../../render/boolean'
import { FilterImpl } from '../../template/filter/filter-impl'
import { Scope } from '../../context/scope'
import { isComparable } from '../../drop/comparable'
import { argumentsToValue, toValue, stringify, caseInsensitiveCompare, isArray, isNil, last as arrayLast, hasOwnProperty } from '../util/underscore'
import { toArray } from '../util/collection'
import { isTruthy } from '../render/boolean'
import { FilterImpl } from '../template/filter/filter-impl'
import { Scope } from '../context/scope'
import { isComparable } from '../drop/comparable'
export const join = argumentsToValue((v: any[], arg: string) => toArray(v).join(arg === undefined ? ' ' : arg))
export const last = argumentsToValue((v: any) => isArray(v) ? arrayLast(v) : '')
@@ -25,7 +25,7 @@ export function * sort<T> (this: FilterImpl, arr: T[], property?: string): Itera
}).map(tuple => tuple[0])
}
export function sortNatural<T> (input: T[], property?: string) {
export function sort_natural<T> (input: T[], property?: string) {
input = toValue(input)
const propertyString = stringify(property)
const compare = property === undefined
@@ -1,8 +1,8 @@
import strftime from '../../util/strftime'
import { LiquidDate } from '../../util/liquid-date'
import { toValue, stringify, isString, isNumber } from '../../util/underscore'
import { FilterImpl } from '../../template/filter/filter-impl'
import { TimezoneDate } from '../../util/timezone-date'
import strftime from '../util/strftime'
import { LiquidDate } from '../util/liquid-date'
import { toValue, stringify, isString, isNumber } from '../util/underscore'
import { FilterImpl } from '../template/filter/filter-impl'
import { TimezoneDate } from '../util/timezone-date'
export function date (this: FilterImpl, v: string | Date, format: string, timeZoneOffset?: number) {
const opts = this.context.opts
@@ -1,4 +1,4 @@
import { stringify } from '../../util/underscore'
import { stringify } from '../util/underscore'
const escapeMap = {
'&': '&amp;',
@@ -23,14 +23,14 @@ function unescape (str: string) {
return stringify(str).replace(/&(amp|lt|gt|#34|#39);/g, m => unescapeMap[m])
}
export function escapeOnce (str: string) {
export function escape_once (str: string) {
return escape(unescape(stringify(str)))
}
export function newlineToBr (v: string) {
export function newline_to_br (v: string) {
return stringify(v).replace(/\n/g, '<br />\n')
}
export function stripHtml (v: string) {
export function strip_html (v: string) {
return stringify(v).replace(/<script.*?<\/script>|<!--.*?-->|<style.*?<\/style>|<.*?>/g, '')
}
+19
View File
@@ -0,0 +1,19 @@
import * as htmlFilters from './html'
import * as mathFilters from './math'
import * as urlFilters from './url'
import * as arrayFilters from './array'
import * as dateFilters from './date'
import * as stringFilters from './string'
import { Default, json } from './misc'
import { FilterImplOptions } from '../template/filter/filter-impl-options'
export const filters: { [key: string]: FilterImplOptions } = {
...htmlFilters,
...mathFilters,
...urlFilters,
...arrayFilters,
...dateFilters,
...stringFilters,
json,
default: Default
}
@@ -1,10 +1,10 @@
import { toValue, argumentsToValue } from '../../util/underscore'
import { toValue, argumentsToValue } from '../util/underscore'
export const abs = argumentsToValue(Math.abs)
export const atLeast = argumentsToValue(Math.max)
export const atMost = argumentsToValue(Math.min)
export const at_least = argumentsToValue(Math.max)
export const at_most = argumentsToValue(Math.min)
export const ceil = argumentsToValue(Math.ceil)
export const dividedBy = argumentsToValue((dividend: number, divisor: number, integerArithmetic = false) => integerArithmetic ? Math.floor(dividend / divisor) : dividend / divisor)
export const divided_by = argumentsToValue((dividend: number, divisor: number, integerArithmetic = false) => integerArithmetic ? Math.floor(dividend / divisor) : dividend / divisor)
export const floor = argumentsToValue(Math.floor)
export const minus = argumentsToValue((v: number, arg: number) => v - arg)
export const modulo = argumentsToValue((v: number, arg: number) => v % arg)
@@ -1,6 +1,6 @@
import { isFalsy } from '../../render/boolean'
import { identify, isArray, isString, toValue } from '../../util/underscore'
import { FilterImpl } from '../../template/filter/filter-impl'
import { isFalsy } from '../render/boolean'
import { identify, isArray, isString, toValue } from '../util/underscore'
import { FilterImpl } from '../template/filter/filter-impl'
export function Default<T1 extends boolean, T2> (this: FilterImpl, value: T1, defaultValue: T2, ...args: Array<[string, any]>): T1 | T2 {
value = toValue(value)
@@ -3,8 +3,8 @@
*
* * prefer stringify() to String() since `undefined`, `null` should eval ''
*/
import { escapeRegExp, stringify } from '../../util/underscore'
import { assert } from '../../util/assert'
import { escapeRegExp, stringify } from '../util/underscore'
import { assert } from '../util/assert'
export function append (v: string, arg: string) {
assert(arguments.length === 2, 'append expect 2 arguments')
@@ -36,7 +36,7 @@ export function remove (v: string, arg: string) {
return stringify(v).split(String(arg)).join('')
}
export function removeFirst (v: string, l: string) {
export function remove_first (v: string, l: string) {
return stringify(v).replace(String(l), '')
}
@@ -66,7 +66,7 @@ export function strip (v: string, chars?: string) {
return stringify(v).trim()
}
export function stripNewlines (v: string) {
export function strip_newlines (v: string) {
return stringify(v).replace(/\n/g, '')
}
@@ -79,7 +79,7 @@ export function replace (v: string, pattern: string, replacement: string) {
return stringify(v).split(String(pattern)).join(replacement)
}
export function replaceFirst (v: string, arg1: string, arg2: string) {
export function replace_first (v: string, arg1: string, arg2: string) {
return stringify(v).replace(String(arg1), arg2)
}
+4
View File
@@ -0,0 +1,4 @@
import { stringify } from '../util/underscore'
export const url_decode = (x: string) => stringify(x).split('+').map(decodeURIComponent).join(' ')
export const url_encode = (x: string) => stringify(x).split(' ').map(encodeURIComponent).join('+')
+4 -9
View File
@@ -1,17 +1,12 @@
import { snakeCase, forOwn, isArray, isString, isFunction } from './util/underscore'
import { isArray, isString, isFunction } from './util/underscore'
import { LiquidCache } from './cache/cache'
import { LRU } from './cache/lru'
import { FS } from './fs/fs'
import * as fs from './fs/node'
import { defaultOperators, Operators } from './render/operator'
import { createTrie, Trie } from './util/operator-trie'
import * as builtinFilters from './builtin/filters'
import { assert, FilterImplOptions } from './types'
const filters = new Map()
forOwn(builtinFilters, (conf: FilterImplOptions, name: string) => {
filters.set(snakeCase(name), conf)
})
import { filters } from './filters'
import { assert } from './types'
type OutputEscape = (value: any) => string
type OutputEscapeOption = 'escape' | 'json' | OutputEscape
@@ -198,7 +193,7 @@ export function normalize (options: LiquidOptions): NormalizedFullOptions {
function getOutputEscapeFunction (nameOrFunction: OutputEscapeOption) {
if (isString(nameOrFunction)) {
const filterImpl = filters.get(nameOrFunction)
const filterImpl = filters[nameOrFunction]
assert(isFunction(filterImpl), `filter "${nameOrFunction}" not found`)
return filterImpl
} else {
+5 -5
View File
@@ -1,13 +1,13 @@
import { Context } from './context/context'
import { forOwn, snakeCase } from './util/underscore'
import { forOwn } from './util/underscore'
import { Template } from './template/template'
import { LookupType } from './fs/loader'
import { Render } from './render/render'
import Parser from './parser/parser'
import { TagImplOptions } from './template/tag/tag-impl-options'
import { Value } from './template/value'
import builtinTags from './builtin/tags'
import * as builtinFilters from './builtin/filters'
import { tags } from './tags'
import { filters } from './filters'
import { TagMap } from './template/tag/tag-map'
import { FilterMap } from './template/filter/filter-map'
import { LiquidOptions, normalizeDirectoryList, NormalizedFullOptions, normalize, RenderOptions } from './liquid-options'
@@ -32,8 +32,8 @@ export class Liquid {
this.filters = new FilterMap(this.options.strictFilters, this)
this.tags = new TagMap()
forOwn(builtinTags, (conf: TagImplOptions, name: string) => this.registerTag(snakeCase(name), conf))
forOwn(builtinFilters, (handler: FilterImplOptions, name: string) => this.registerFilter(snakeCase(name), handler))
forOwn(tags, (conf: TagImplOptions, name: string) => this.registerTag(name, conf))
forOwn(filters, (handler: FilterImplOptions, name: string) => this.registerFilter(name, handler))
}
public parse (html: string, filepath?: string): Template[] {
return this.parser.parse(html, filepath)
@@ -1,4 +1,4 @@
import { Value, Tokenizer, assert, TagImplOptions, TagToken, Context } from '../../types'
import { Value, Tokenizer, assert, TagImplOptions, TagToken, Context } from '../types'
export default {
parse: function (token: TagToken) {
@@ -1,6 +1,6 @@
import BlockMode from '../../context/block-mode'
import { BlockDrop } from '../../drop/block-drop'
import { TagToken, TopLevelToken, Template, Context, TagImpl, Emitter } from '../../types'
import BlockMode from '../context/block-mode'
import { BlockDrop } from '../drop/block-drop'
import { TagToken, TopLevelToken, Template, Context, TagImpl, Emitter } from '../types'
export default {
parse (this: TagImpl, token: TagToken, remainTokens: TopLevelToken[]) {
@@ -1,4 +1,4 @@
import { Emitter, Context } from '../../types'
import { Emitter, Context } from '../types'
export default {
render: function (ctx: Context, emitter: Emitter) {
@@ -1,5 +1,5 @@
import { Tokenizer, assert, Template, Context, TagImplOptions, TagToken, TopLevelToken } from '../../types'
import { evalQuotedToken } from '../../render/expression'
import { Tokenizer, assert, Template, Context, TagImplOptions, TagToken, TopLevelToken } from '../types'
import { evalQuotedToken } from '../render/expression'
export default {
parse: function (tagToken: TagToken, remainTokens: TopLevelToken[]) {
@@ -1,5 +1,5 @@
import { toValue, _evalToken, Value, Emitter, TagToken, TopLevelToken, Context, Template, TagImplOptions, ParseStream } from '../../types'
import { Tokenizer } from '../../parser/tokenizer'
import { toValue, _evalToken, Value, Emitter, TagToken, TopLevelToken, Context, Template, TagImplOptions, ParseStream } from '../types'
import { Tokenizer } from '../parser/tokenizer'
export default {
parse: function (tagToken: TagToken, remainTokens: TopLevelToken[]) {
@@ -1,6 +1,6 @@
import { TagToken } from '../../tokens/tag-token'
import { TopLevelToken } from '../../tokens/toplevel-token'
import { TagImplOptions } from '../../template/tag/tag-impl-options'
import { TagToken } from '../tokens/tag-token'
import { TopLevelToken } from '../tokens/toplevel-token'
import { TagImplOptions } from '../template/tag/tag-impl-options'
export default {
parse: function (tagToken: TagToken, remainTokens: TopLevelToken[]) {
@@ -1,4 +1,4 @@
import { Emitter, Context } from '../../types'
import { Emitter, Context } from '../types'
export default {
render: function (ctx: Context, emitter: Emitter) {
@@ -1,6 +1,6 @@
import { assert } from '../../util/assert'
import { _evalToken, Emitter, TagToken, Context, TagImplOptions } from '../../types'
import { Tokenizer } from '../../parser/tokenizer'
import { assert } from '../util/assert'
import { _evalToken, Emitter, TagToken, Context, TagImplOptions } from '../types'
import { Tokenizer } from '../parser/tokenizer'
export default {
parse: function (tagToken: TagToken) {
@@ -1,5 +1,5 @@
import { Tokenizer, Emitter, TagToken, Context, TagImplOptions } from '../../types'
import { isNumber, stringify } from '../../util/underscore'
import { Tokenizer, Emitter, TagToken, Context, TagImplOptions } from '../types'
import { isNumber, stringify } from '../util/underscore'
export default {
parse: function (token: TagToken) {
@@ -1,6 +1,6 @@
import { Value } from '../../template/value'
import { Emitter } from '../../emitters/emitter'
import { TagImplOptions, TagToken, Context } from '../../types'
import { Value } from '../template/value'
import { Emitter } from '../emitters/emitter'
import { TagImplOptions, TagToken, Context } from '../types'
export default {
parse: function (token: TagToken) {
+4 -4
View File
@@ -1,7 +1,7 @@
import { assert, Tokenizer, _evalToken, Emitter, TagToken, TopLevelToken, Context, Template, TagImplOptions, ParseStream } from '../../types'
import { toEnumerable } from '../../util/collection'
import { ForloopDrop } from '../../drop/forloop-drop'
import { Hash, HashValue } from '../../template/tag/hash'
import { assert, Tokenizer, _evalToken, Emitter, TagToken, TopLevelToken, Context, Template, TagImplOptions, ParseStream } from '../types'
import { toEnumerable } from '../util/collection'
import { ForloopDrop } from '../drop/forloop-drop'
import { Hash, HashValue } from '../template/tag/hash'
const MODIFIERS = ['offset', 'limit', 'reversed']
+1 -1
View File
@@ -1,4 +1,4 @@
import { Value, Emitter, isTruthy, TagToken, TopLevelToken, Context, Template, TagImplOptions } from '../../types'
import { Value, Emitter, isTruthy, TagToken, TopLevelToken, Context, Template, TagImplOptions } from '../types'
export default {
parse: function (tagToken: TagToken, remainTokens: TopLevelToken[]) {
@@ -1,5 +1,5 @@
import { assert, Tokenizer, _evalToken, Hash, Emitter, TagToken, Context, TagImplOptions } from '../../types'
import BlockMode from '../../context/block-mode'
import { assert, Tokenizer, _evalToken, Hash, Emitter, TagToken, Context, TagImplOptions } from '../types'
import BlockMode from '../context/block-mode'
import { parseFilePath, renderFilePath } from './render'
export default {
@@ -1,5 +1,5 @@
import { isNumber, stringify } from '../../util/underscore'
import { Tokenizer, Emitter, TagToken, Context, TagImplOptions } from '../../types'
import { isNumber, stringify } from '../util/underscore'
import { Tokenizer, Emitter, TagToken, Context, TagImplOptions } from '../types'
export default {
parse: function (token: TagToken) {
@@ -19,10 +19,8 @@ import Continue from './continue'
import echo from './echo'
import liquid from './liquid'
import inlineComment from './inline-comment'
import { TagImplOptions } from '../../template/tag/tag-impl-options'
import { TagImplOptions } from '../template/tag/tag-impl-options'
const tags: { [key: string]: TagImplOptions } = {
export const tags: { [key: string]: TagImplOptions } = {
assign, 'for': For, capture, 'case': Case, comment, include, render, decrement, increment, cycle, 'if': If, layout, block, raw, tablerow, unless, 'break': Break, 'continue': Continue, echo, liquid, '#': inlineComment
}
export default tags
@@ -1,6 +1,6 @@
import { TagToken } from '../../tokens/tag-token'
import { TopLevelToken } from '../../tokens/toplevel-token'
import { TagImplOptions } from '../../template/tag/tag-impl-options'
import { TagToken } from '../tokens/tag-token'
import { TopLevelToken } from '../tokens/toplevel-token'
import { TagImplOptions } from '../template/tag/tag-impl-options'
export default {
parse: function (tagToken: TagToken, remainTokens: TopLevelToken[]) {
@@ -1,7 +1,7 @@
import { assert, Tokenizer, Emitter, Hash, TagToken, TopLevelToken, Context, TagImplOptions } from '../../types'
import BlockMode from '../../context/block-mode'
import { assert, Tokenizer, Emitter, Hash, TagToken, TopLevelToken, Context, TagImplOptions } from '../types'
import BlockMode from '../context/block-mode'
import { parseFilePath, renderFilePath } from './render'
import { BlankDrop } from '../../drop/blank-drop'
import { BlankDrop } from '../drop/blank-drop'
export default {
parseFilePath,
@@ -1,6 +1,6 @@
import { Emitter } from '../../emitters/emitter'
import { TagImplOptions, TagToken, Context } from '../../types'
import { Tokenizer } from '../../parser/tokenizer'
import { Emitter } from '../emitters/emitter'
import { TagImplOptions, TagToken, Context } from '../types'
import { Tokenizer } from '../parser/tokenizer'
export default {
parse: function (token: TagToken) {
+1 -1
View File
@@ -1,4 +1,4 @@
import { TagToken, TopLevelToken, TagImplOptions } from '../../types'
import { TagToken, TopLevelToken, TagImplOptions } from '../types'
export default {
parse: function (tagToken: TagToken, remainTokens: TopLevelToken[]) {
@@ -1,9 +1,9 @@
import { __assign } from 'tslib'
import { assert } from '../../util/assert'
import { ForloopDrop } from '../../drop/forloop-drop'
import { toEnumerable } from '../../util/collection'
import { Liquid } from '../../liquid'
import { Token, Template, evalQuotedToken, TypeGuards, Tokenizer, _evalToken, Hash, Emitter, TagToken, Context, TagImplOptions } from '../../types'
import { assert } from '../util/assert'
import { ForloopDrop } from '../drop/forloop-drop'
import { toEnumerable } from '../util/collection'
import { Liquid } from '../liquid'
import { Token, Template, evalQuotedToken, TypeGuards, Tokenizer, _evalToken, Hash, Emitter, TagToken, Context, TagImplOptions } from '../types'
export default {
parseFilePath,
@@ -1,7 +1,7 @@
import { toEnumerable } from '../../util/collection'
import { assert, _evalToken, Emitter, Hash, TagToken, TopLevelToken, Context, Template, TagImplOptions, ParseStream } from '../../types'
import { TablerowloopDrop } from '../../drop/tablerowloop-drop'
import { Tokenizer } from '../../parser/tokenizer'
import { toEnumerable } from '../util/collection'
import { assert, _evalToken, Emitter, Hash, TagToken, TopLevelToken, Context, Template, TagImplOptions, ParseStream } from '../types'
import { TablerowloopDrop } from '../drop/tablerowloop-drop'
import { Tokenizer } from '../parser/tokenizer'
export default {
parse: function (tagToken: TagToken, remainTokens: TopLevelToken[]) {
@@ -1,4 +1,4 @@
import { Value, TopLevelToken, Template, Emitter, isTruthy, isFalsy, Context, TagImplOptions, TagToken } from '../../types'
import { Value, TopLevelToken, Template, Emitter, isTruthy, isFalsy, Context, TagImplOptions, TagToken } from '../types'
export default {
parse: function (tagToken: TagToken, remainTokens: TopLevelToken[]) {
+2 -2
View File
@@ -27,6 +27,6 @@ export { defaultOperators, Operators } from './render/operator'
export { createTrie, Trie } from './util/operator-trie'
export { toValue } from './util/underscore'
export { TimezoneDate } from './util/timezone-date'
export * as filters from './builtin/filters'
export * as tags from './builtin/tags'
export { filters } from './filters'
export { tags } from './tags'
export { defaultOptions } from './liquid-options'
-7
View File
@@ -137,13 +137,6 @@ export function identify<T> (val: T): T {
return val
}
export function snakeCase (str: string) {
return str.replace(
/(\w?)([A-Z])/g,
(_, a, b) => (a ? a + '_' : '') + b.toLowerCase()
)
}
export function changeCase (str: string): string {
const hasLowerCase = [...str].some(ch => ch >= 'a' && ch <= 'z')
return hasLowerCase ? str.toUpperCase() : str.toLowerCase()
-9
View File
@@ -7,15 +7,6 @@ const expect = chai.expect
chai.use(sinonChai)
describe('util/underscore', function () {
describe('.camel2snake()', function () {
it('should convert camelCase to snakeCase', function () {
expect(_.snakeCase('fooBarCoo')).to.equal('foo_bar_coo')
})
it('should convert empty string to empty string', function () {
expect(_.snakeCase('')).to.equal('')
})
})
describe('.isString()', function () {
it('should return true for literal string', function () {
expect(_.isString('foo')).to.be.true