From 9f418261e99e967b58365d69d0ed78c0acc6bd7d Mon Sep 17 00:00:00 2001 From: Ivan Shalganov Date: Sun, 8 Dec 2019 01:01:04 +0300 Subject: [PATCH] Bug fixes --- docs/api.md | 26 ++++++---- rockspec/aspect-1.0-0.rockspec | 46 ---------------- rockspec/aspect-1.1-0.rockspec | 47 ----------------- ...t-1.3-0.rockspec => aspect-1.5-0.rockspec} | 6 +-- ...t-1.2-0.rockspec => aspect-git-1.rockspec} | 6 +-- src/aspect/filters.lua | 18 ++++--- src/aspect/funcs.lua | 30 +++++++---- src/aspect/output.lua | 6 ++- src/aspect/tags.lua | 4 +- src/aspect/utils/range.lua | 52 +++++++++++++++++++ 10 files changed, 112 insertions(+), 129 deletions(-) delete mode 100644 rockspec/aspect-1.0-0.rockspec delete mode 100644 rockspec/aspect-1.1-0.rockspec rename rockspec/{aspect-1.3-0.rockspec => aspect-1.5-0.rockspec} (95%) rename rockspec/{aspect-1.2-0.rockspec => aspect-git-1.rockspec} (92%) diff --git a/docs/api.md b/docs/api.md index 7fff378..797323a 100644 --- a/docs/api.md +++ b/docs/api.md @@ -264,19 +264,22 @@ See [aspect.funcs](../src/aspect/funcs.lua) for more examples. Add tests --------- -Add tests `foo` and `bar` +Add tests `foo`, `bar` and `baz` ```lua local tests = require("aspect.tests") -tests.fn.is_foo = function (v) - -- return boolean -end +tests.add('foo', function (__, v) + -- return boolean +end) -tests.args.is_bar = true -- bar tests has expression -tests.fn.is_bar = function (v, expr) - -- return boolean -end +tests.add('bar', function (__, v, arg) + -- return boolean +end, true) + +tests.add('baz', function (__, v, arg) + -- return boolean +end, "quux") ``` Result: @@ -284,6 +287,7 @@ Result: ```twig {{ a is foo }} {{ a is bar(c) }} +{{ a is baz quux(c) }} ``` See [aspect.tests](../src/aspect/tests.lua) for more examples. @@ -291,7 +295,7 @@ See [aspect.tests](../src/aspect/tests.lua) for more examples. Add operators ------------- -For example add bitwise operator `&`: +For example add bitwise operator `&` (using [bitop](http://bitop.luajit.org/) package): ```lua local ops = require("aspect.ast.ops") @@ -301,8 +305,8 @@ local ops = require("aspect.ast.ops") --- Define 'and' bitwise operator. --- @see aspect.ast.op table.insert(ops, { - token = "&", -- token for parser - order = 7, -- operator precedence + token = "&", -- one-symbol-token for parser + order = 7, -- operator precedence (1 - high priority, 14 - low priority) l = "number", -- left operand should be number r = "number", -- right operand should be number out = "number", -- result of the operator is number diff --git a/rockspec/aspect-1.0-0.rockspec b/rockspec/aspect-1.0-0.rockspec deleted file mode 100644 index 8f9f6a7..0000000 --- a/rockspec/aspect-1.0-0.rockspec +++ /dev/null @@ -1,46 +0,0 @@ -package = "aspect" -version = "1.0-0" -source = { - url = "https://github.com/unifire-app/aspect/archive/1.0.zip" -} -description = { - summary = "Aspect is a compiling templating engine for Lua and OpenResty with syntax Twig/Django/Jinja.", - detailed = [[ -* Popular Django syntax compatible with Twig2 and Jinja2 -* Bytecode and lua code caching of compiled templates are available. -* Safe launch of templates in the sandbox. -* Automatic casting of data types when used. -* Designed for highload and big input and output data. -* Detailed error messages make it easy to debug templates. -* Easily extensible: add your own tags, filters, functions, handlers, operators. -* Intuitive behavior. For example, unlike lua, zero, an empty string, csjon.null, and so on, will be false in if-conditions. All of this is extensible. -* Custom behavior with userdata. -* Supports work with OpenResty. - ]], - license = "BSD-3-Clause", -} -dependencies = { - "penlight", - "date", - "lua-cjson" -} -build = { - type = "builtin", - modules = { - ["aspect.config"] = "src/aspect/config.lua", - ["aspect.template"] = "src/aspect/template.lua", - ["aspect.output"] = "src/aspect/output.lua", - ["aspect.compiler"] = "src/aspect/compiler.lua", - ["aspect.tags"] = "src/aspect/tags.lua", - ["aspect.err"] = "src/aspect/err.lua", - ["aspect.filters"] = "src/aspect/filters.lua", - ["aspect.funcs"] = "src/aspect/funcs.lua", - ["aspect.tests"] = "src/aspect/tests.lua", - ["aspect.tokenizer"] = "src/aspect/tokenizer.lua", - ["aspect.utils"] = "src/aspect/utils.lua", - ["aspect.ast"] = "src/aspect/ast.lua", - ["aspect.ast.ops"] = "src/aspect/ast/ops.lua", - ["aspect.utils.batch"] = "src/aspect/utils/batch.lua", - ["aspect.utils.range"] = "src/aspect/utils/range.lua", - } -} \ No newline at end of file diff --git a/rockspec/aspect-1.1-0.rockspec b/rockspec/aspect-1.1-0.rockspec deleted file mode 100644 index ec64acc..0000000 --- a/rockspec/aspect-1.1-0.rockspec +++ /dev/null @@ -1,47 +0,0 @@ -package = "aspect" -version = "1.1-0" -source = { - url = "https://github.com/unifire-app/aspect/archive/1.1.zip" -} -description = { - summary = "Aspect is a compiling templating engine for Lua and OpenResty with syntax Twig/Django/Jinja.", - detailed = [[ -* Popular Django syntax compatible with Twig2 and Jinja2 -* Bytecode and lua code caching of compiled templates are available. -* Safe launch of templates in the sandbox. -* Automatic casting of data types when used. -* Designed for highload and big input and output data. -* Detailed error messages make it easy to debug templates. -* Easily extensible: add your own tags, filters, functions, handlers, operators. -* Intuitive behavior. For example, unlike lua, zero, an empty string, csjon.null, and so on, will be false in if-conditions. All of this is extensible. -* Custom behavior with userdata. -* Supports work with OpenResty. - ]], - license = "BSD-3-Clause", -} -dependencies = { - "penlight", - "date", - "lua-cjson" -} -build = { - type = "builtin", - modules = { - ["aspect.config"] = "src/aspect/config.lua", - ["aspect.template"] = "src/aspect/template.lua", - ["aspect.output"] = "src/aspect/output.lua", - ["aspect.compiler"] = "src/aspect/compiler.lua", - ["aspect.tags"] = "src/aspect/tags.lua", - ["aspect.err"] = "src/aspect/err.lua", - ["aspect.filters"] = "src/aspect/filters.lua", - ["aspect.funcs"] = "src/aspect/funcs.lua", - ["aspect.tests"] = "src/aspect/tests.lua", - ["aspect.tokenizer"] = "src/aspect/tokenizer.lua", - ["aspect.utils"] = "src/aspect/utils.lua", - ["aspect.ast"] = "src/aspect/ast.lua", - ["aspect.ast.ops"] = "src/aspect/ast/ops.lua", - ["aspect.utils.batch"] = "src/aspect/utils/batch.lua", - ["aspect.utils.range"] = "src/aspect/utils/range.lua", - ["aspect.loader.array"] = "src/aspect/loader/array.lua", - } -} \ No newline at end of file diff --git a/rockspec/aspect-1.3-0.rockspec b/rockspec/aspect-1.5-0.rockspec similarity index 95% rename from rockspec/aspect-1.3-0.rockspec rename to rockspec/aspect-1.5-0.rockspec index de07936..efff52c 100644 --- a/rockspec/aspect-1.3-0.rockspec +++ b/rockspec/aspect-1.5-0.rockspec @@ -1,8 +1,8 @@ package = "aspect" -version = "1.3-0" +version = "1.5-0" source = { - url = "https://github.com/unifire-app/aspect/archive/1.3.zip", - dir = "aspect-1.3" + url = "https://github.com/unifire-app/aspect/archive/1.5.zip", + dir = "aspect-1.5" } description = { summary = "Aspect is a compiling templating engine for Lua and OpenResty with syntax Twig/Django/Jinja.", diff --git a/rockspec/aspect-1.2-0.rockspec b/rockspec/aspect-git-1.rockspec similarity index 92% rename from rockspec/aspect-1.2-0.rockspec rename to rockspec/aspect-git-1.rockspec index c06ae68..d60efdc 100644 --- a/rockspec/aspect-1.2-0.rockspec +++ b/rockspec/aspect-git-1.rockspec @@ -1,8 +1,7 @@ package = "aspect" -version = "1.2-0" +version = "git-1" source = { - url = "https://github.com/unifire-app/aspect/archive/1.2.zip", - dir = "aspect-1.2" + url = "https://github.com/unifire-app/aspect/-/archive/master/aspect-master.zip" } description = { summary = "Aspect is a compiling templating engine for Lua and OpenResty with syntax Twig/Django/Jinja.", @@ -28,6 +27,7 @@ dependencies = { build = { type = "builtin", modules = { + ["aspect"] = "src/aspect/init.lua", ["aspect.config"] = "src/aspect/config.lua", ["aspect.template"] = "src/aspect/template.lua", ["aspect.compiler"] = "src/aspect/compiler.lua", diff --git a/src/aspect/filters.lua b/src/aspect/filters.lua index d4bcd51..5286df9 100644 --- a/src/aspect/filters.lua +++ b/src/aspect/filters.lua @@ -239,15 +239,21 @@ end function filters.fn.keys(v) local typ = type(v) if typ == "table" then - if v.__pairs and getmetatable(v).__pairs then - local keys, i = {}, 1 - for k, _ in v:__pairs() do - keys[i] = k + local mt = getmetatable(v) + if mt and mt.__pairs then + local t, i = {}, 1 + for k, _ in mt.__pairs(v) do + t[i] = k i = i + 1 end - return keys + return t else - return tablex.keys(v) + local t, i = {}, 1 + for k, _ in pairs(v) do + t[i] = k + i = i + 1 + end + return t end else return {} diff --git a/src/aspect/funcs.lua b/src/aspect/funcs.lua index cdd4736..1e660af 100644 --- a/src/aspect/funcs.lua +++ b/src/aspect/funcs.lua @@ -10,6 +10,7 @@ local tag_type = config.compiler.tag_type local dump = require("aspect.utils").dump local date = require("date") local utils = require("aspect.utils") +local range = require("aspect.utils.range") local func = { args = {}, @@ -167,24 +168,33 @@ func.args.range = {"from", "to", "step"} --- @param args table function func.fn.range(__, args) if not args.from then - runtime_error(__, "range(): requires 'from' argument") + __:notice("range(): requires 'from' argument") + return {} + --runtime_error(__, "range(): requires 'from' argument") end if not args.to then - runtime_error(__, "range(): requires 'to' argument") + __:notice("range(): requires 'to' argument") + return {} + --runtime_error(__, "range(): requires 'to' argument") end if not args.step or args.step == 0 then args.step = 1 end if args.step > 0 and args.to < args.from then - runtime_error(__, "range(): 'to' less than 'from' with positive step") + __:notice("range(): 'to' less than 'from' with positive step") + return {} + --runtime_error(__, "range(): 'to' less than 'from' with positive step") elseif args.step < 0 and args.to > args.from then - runtime_error(__, "range(): 'to' great than 'from' with negative step") - end - local t = {} - for i = args.from, args.to, args.step do - t[#t+1] = i - end - return t + __:notice("range(): 'to' great than 'from' with negative step") + return {} + --runtime_error(__, "range(): 'to' great than 'from' with negative step") + end + --local t = {} + --for i = args.from, args.to, args.step do + -- t[#t+1] = i + --end + --return t + return range.new(args.from, args.to, args.step) end --- @param __ aspect.output diff --git a/src/aspect/output.lua b/src/aspect/output.lua index 6827fd3..b332f52 100644 --- a/src/aspect/output.lua +++ b/src/aspect/output.lua @@ -335,7 +335,7 @@ function output.i(v) end end - return nil, nil, nil + return next, {}, nil end --- Get 'recursive' value from tables @@ -368,6 +368,10 @@ function output:e(v) end end +function output:notice(msg) + +end + --- Set autoescape function output:autoescape(state) if state == nil then diff --git a/src/aspect/tags.lua b/src/aspect/tags.lua index 5307e59..d76bed5 100644 --- a/src/aspect/tags.lua +++ b/src/aspect/tags.lua @@ -474,9 +474,9 @@ function tags.tag_endfor(compiler) end if tag.key then -- start of 'for' - before[#before + 1] = 'for ' .. tag.key .. ', ' .. tag.value .. ' in __.pairs(' .. tag.from .. ') do' + before[#before + 1] = 'for ' .. tag.key .. ', ' .. tag.value .. ' in __.i(' .. tag.from .. ') do' else - before[#before + 1] = 'for _, ' .. tag.value .. ' in __.pairs(' .. tag.from .. ') do' + before[#before + 1] = 'for _, ' .. tag.value .. ' in __.i(' .. tag.from .. ') do' end if tag.cond then -- start of 'if' before[#before + 1] = tag.cond diff --git a/src/aspect/utils/range.lua b/src/aspect/utils/range.lua index dcbd3f6..ed12d4e 100644 --- a/src/aspect/utils/range.lua +++ b/src/aspect/utils/range.lua @@ -1,4 +1,56 @@ +local setmetatable = setmetatable +local floor = math.floor +local abs = math.abs + +local function iterator(self, k) + local i = self.from + k * self.step + if self.incr then + if i > self.to then + return nil, nil + else + return k + 1, i + end + else + if i < self.to then + return nil, nil + else + return k + 1, i + end + end +end + +local function __pairs(self) + return iterator, self, 0 +end + +local function __count(self) + if self.incr then + return floor(abs((self.to - self.from) / self.step)) + 1 + else + return floor(abs((self.from - self.to) / self.step)) + 1 + end +end + +--- @class aspect.utils.range +--- @field from number +--- @field to number +--- @field step number +--- @field incr boolean local range = {} +local mt = { + __index = range, + __pairs = __pairs, + __count = __count +} + +function range.new(from, to, step) + return setmetatable({ + incr = from < to, + from = from, + to = to, + step = step, + }, mt) +end return range \ No newline at end of file