diff --git a/lib/liquid.lua b/lib/liquid.lua index cb13510..12c964a 100644 --- a/lib/liquid.lua +++ b/lib/liquid.lua @@ -2777,33 +2777,52 @@ function FilterSet:find_filter( filter_name ) return self.filterset[filter_name] end end + +local function is_iterator(o) + local mt = getmetatable(o) + + return mt and mt.__ipairs +end + +local function iterator(o) + if type(o) == 'table' or is_iterator(o) then + return o + else + return { o } + end +end + --=== array filter begin local function join( a, b) -- body - return Interpreter:safe_concat(a, b) + return Interpreter:safe_concat(iterator(a), b or ' ') end local function first( a ) -- body - return a[1] + return iterator(a)[1] +end +local function size( a ) + -- body + return(#iterator(a)) end local function last( a ) -- body - return a[#a] + return iterator(a)[size(a)] end local function concat( a, b) -- body local temp = {} - for i,v in ipairs(a) do + for i,v in ipairs(iterator(a)) do table.insert(temp, v) end - for i,v in ipairs(b) do + for i,v in ipairs(iterator(b)) do table.insert(temp, v) end return temp end local function index( a, b) -- body - return a[(b + 1)] + return iterator(a)[(b + 1)] end local function map( a, map_field) -- body @@ -2816,20 +2835,18 @@ end local function reverse( a ) -- body local temp = {} - local num = #a + local it = iterator(a) + local num = size(a) for k = num, 1, -1 do - table.insert(temp, a[k]) + table.insert(temp, it[k]) end return temp end -local function size( a ) - -- body - return(#a) -end + local function sort( a, sort_field) -- body local t = {} - for i,v in ipairs(a) do + for i,v in ipairs(iterator(a)) do table.insert(t, v) end if not sort_field then @@ -2845,7 +2862,7 @@ local function uniq( a ) -- body local t = {} local result = {} - for i,v in ipairs(a) do + for i,v in ipairs(iterator(a)) do local k = cjson.encode(v) if not t[k] then t[k] = true diff --git a/t/array_filters.t b/t/array_filters.t index 3d52a4e..1de8760 100644 --- a/t/array_filters.t +++ b/t/array_filters.t @@ -7,10 +7,11 @@ plan tests => repeat_each() * (3 * blocks()); my $pwd = cwd(); -our $HttpConfig = qq{ +our $HttpConfig = qq| lua_package_path "$pwd/lib/?.lua;;;"; lua_package_cpath "/usr/local/openresty/lualib/?.so;;"; -}; + init_by_lua_block { Liquid = require 'liquid' } +|; no_long_string(); @@ -264,3 +265,170 @@ GET /t --- no_error_log [error] + + +=== TEST 11: 'join' filter works on strings +--- http_config eval: $::HttpConfig +--- config + location /t { + content_by_lua_block { + ngx.say( Liquid.Template:parse([[ + {{- str | join: ' - ' -}} + ]]):render(Liquid.InterpreterContext:new({ str = "string" })) ) + } + } +--- request +GET /t +--- response_body +string +--- no_error_log +[error] + +=== TEST 12: 'first' filter works strings +--- http_config eval: $::HttpConfig +--- config + location /t { + content_by_lua_block { + ngx.say( Liquid.Template:parse([[ + {{- str | first -}} + ]]):render(Liquid.InterpreterContext:new({ str = "string" })) ) + } + } +--- request +GET /t +--- response_body +string +--- no_error_log +[error] + + + +=== TEST 13: 'last' filter works on strings +--- http_config eval: $::HttpConfig +--- config + location /t { + content_by_lua_block { + ngx.say( Liquid.Template:parse([[ + {{- str | last -}} + ]]):render( Liquid.InterpreterContext:new({ str = "string" })) ) + } + } +--- request +GET /t +--- response_body +string +--- no_error_log +[error] + +=== TEST 14: 'concat' filter works on strings +--- http_config eval: $::HttpConfig +--- config + location /t { + content_by_lua_block { + ngx.say( Liquid.Template:parse([[ + {%- assign a = "string" | concat:(1..3) -%} + {%- assign b = "string" | concat: "another" -%} + {%- for k in a %} {{k}} {%- endfor -%} + {%- for k in b %} {{k}} {%- endfor -%} + ]]):render()) + } + } +--- request +GET /t +--- response_body + string 1 2 3 string another +--- no_error_log +[error] + +=== TEST 5: 'index' filter works on strings +--- http_config eval: $::HttpConfig +--- config + location /t { + content_by_lua_block { + ngx.say( Liquid.Template:parse([[ + {{- "string"| index: 0 -}} + ]]):render() ) + } + } +--- request +GET /t +--- response_body +string +--- no_error_log +[error] + + +=== TEST 16: 'reverse' filter works on strings +--- http_config eval: $::HttpConfig +--- config + location /t { + content_by_lua_block { + ngx.say( Liquid.Template:parse([[ + {{- "string" | reverse | join -}} + ]]):render() ) + } + } +--- request +GET /t +--- response_body +string +--- no_error_log +[error] + + + +=== TEST 17: 'size' filter works on strings +--- http_config eval: $::HttpConfig +--- config + location /t { + content_by_lua_block { + ngx.say( Liquid.Template:parse([[ + {{- "string" | size -}} + ]]):render() ) + } + } +--- request +GET /t +--- response_body +1 +--- no_error_log +[error] + + + +=== TEST 18: 'sort' filter works on strings +--- http_config eval: $::HttpConfig +--- config + location /t { + content_by_lua_block { + ngx.say( Liquid.Template:parse([[ + {{- "string" | sort | join -}} + ]]):render() ) + } + } +--- request +GET /t +--- response_body +string + +--- no_error_log +[error] + + + +=== TEST 19: 'uniq' filter works on strings +--- http_config eval: $::HttpConfig +--- config + location /t { + content_by_lua_block { + ngx.say( Liquid.Template:parse([[ + {{- "string" | uniq | join -}} + ]]):render() ) + } + } +--- request +GET /t +--- response_body +string +--- no_error_log +[error]