Skip to content

Commit

Permalink
Optimize code space; fix docs
Browse files Browse the repository at this point in the history
  • Loading branch information
bzick committed Apr 6, 2020
1 parent d33f074 commit 93dcd76
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 96 deletions.
23 changes: 23 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,22 @@ aspect:display("dashboard.tpl", {
})
```

## Render result

```lua
local output, err = aspect:display(template, vars)
```

- `output` is `aspect.output` object and contains rendering information, even if the rendering failed.
If you use `aspect:render` method `output` contains rendered string:
```lua
local output, err = aspect:render(template, vars)
if not err then
io.write(tostring(output))
end
```
- `err` is `aspect.error` object and contains error information. `nil` if no errors.

Rendering Templates
-------------------

Expand Down Expand Up @@ -442,3 +458,10 @@ end
```twig
{{ data.raw|e("csv") }}
```

## Iterator

The `Aspect` implements custom iterators as in Lua 5.2 - through the metatable and `__pairs()` function.
Works for all lua/luajit versions.

For example see [range iterator](../src/aspect/utils/range.lua).
49 changes: 0 additions & 49 deletions rockspec/aspect-1.6-1.rockspec

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package = "aspect"
version = "1.6-0"
version = "1.9-0"
source = {
url = "https://github.com/unifire-app/aspect/archive/1.6.zip",
dir = "aspect-1.6"
url = "https://github.com/unifire-app/aspect/archive/1.9.zip",
dir = "aspect-1.9"
}
description = {
summary = "Aspect is a compiling templating engine for Lua and OpenResty with syntax Twig/Django/Jinja.",
summary = "Aspect is a compiling templating engine for Lua and OpenResty with syntax Twig/Jinja/Liquid.",
detailed = [[
* Well known: The most popular Django-like syntax is used - Twig compatible and Jinja like.
* Well known: The most popular Liquid-like syntax is used - Twig compatible and Jinja like.
* Fast: Aspect compiles templates down to plain optimized Lua code.
Moreover, Lua code compiles into bytecode - the fastest representation of a template.
* Secure: Aspect has a sandbox mode to evaluate all template code.
Expand Down Expand Up @@ -45,5 +45,7 @@ build = {
["aspect.utils.batch"] = "src/aspect/utils/batch.lua",
["aspect.utils.range"] = "src/aspect/utils/range.lua",
["aspect.loader.array"] = "src/aspect/loader/array.lua",
["aspect.loader.array"] = "src/aspect/loader/filesystem.lua",
["aspect.loader.array"] = "src/aspect/loader/resty.lua",
}
}
22 changes: 12 additions & 10 deletions rockspec/aspect-git-1.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ source = {
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.
* Well known: The most popular Liquid-like syntax is used - Twig compatible and Jinja like.
* Fast: Aspect compiles templates down to plain optimized Lua code.
Moreover, Lua code compiles into bytecode - the fastest representation of a template.
* Secure: Aspect has a sandbox mode to evaluate all template code.
This allows Aspect to be used as a template language for applications where users may modify the template design.
* Flexible: Aspect is powered by a flexible lexer and parser.
This allows the developer to define their own custom tags, filters, functions and operators, and to create their own DSL.
* Comfortable: Aspect allows you to process userdata data.
More intuitive behavior with special values such as a empty string, number zero and so on.
* Memory-safe: The template is built in such a way as to save maximum memory when it is executed, even if the iterator provides a lot of data.
]],
license = "BSD-3-Clause",
}
Expand Down Expand Up @@ -44,5 +44,7 @@ build = {
["aspect.utils.batch"] = "src/aspect/utils/batch.lua",
["aspect.utils.range"] = "src/aspect/utils/range.lua",
["aspect.loader.array"] = "src/aspect/loader/array.lua",
["aspect.loader.array"] = "src/aspect/loader/filesystem.lua",
["aspect.loader.array"] = "src/aspect/loader/resty.lua",
}
}
21 changes: 6 additions & 15 deletions src/aspect/compiler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -895,28 +895,19 @@ end
--- @param name string the tag name
--- @param code_space table|nil for lua code
--- @return aspect.tag
function compiler:push_tag(name, code_space, code_space_name, var_space, push_state)
function compiler:push_tag(name, code_space, code_space_name, var_space)
self.idx = self.idx + 1
if push_state == nil then
push_state = true
end
--- @type aspect.tag
local tag = {
id = self.idx,
name = name,
line = self.line,
push_state = push_state
line = self.line
}
if code_space then
insert(self.code, code_space)
if not code_space_name then
code_space_name = "nil"
else
code_space_name = quote_string(code_space_name)
end
tag.code_space_name = code_space_name
if push_state then
code_space[#code_space + 1] = "__:push_state(_self, " .. self.line .. ", " .. code_space_name .. ")"
if code_space_name then
tag.code_space_name = code_space_name
code_space[#code_space + 1] = "__:push_state(_self, " .. self.line .. ", " .. quote_string(code_space_name) .. ")"
end
self.prev_line = self.line
tag.code_space_no = #self.code
Expand Down Expand Up @@ -973,7 +964,7 @@ function compiler:pop_tag(name)
compiler_error(nil, "compiler", "invalid code space layer in the tag " .. name)
else
local prev = remove(self.code)
if tag.push_state then
if tag.code_space_name then
prev[#prev + 1] = "__:pop_state()"
end
end
Expand Down
4 changes: 4 additions & 0 deletions src/aspect/output.lua
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ function output:set_print(p, size)
self.size = size
end

--- Push new state to call stack
--- @param view aspect.view
--- @param line number
--- @param scope_name string
function output:push_state(view, line, scope_name)
if #self.stack > self.opts.stack_size then
runtime_error(self, "Call stack overflow (maximum " .. self.opts.stack_size .. ")")
Expand Down
2 changes: 1 addition & 1 deletion src/aspect/tags.lua
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ function tags.tag_for(compiler, tok)
compiler_error(tok, "syntax", "expecting variable name")
end
end
local tag = compiler:push_tag('for', {}, nil, nil, false)
local tag = compiler:push_tag('for', {})
from = compiler:parse_expression(tok:require("in"):next())
tag.has_loop = false
tag.from = from
Expand Down
2 changes: 1 addition & 1 deletion src/aspect/template.lua
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ local _ = {}
--- @field bytecode_load fun(name: string, tpl: aspect.template):string
--- @field bytecode_save fun(name: string, bytecode: string, tpl: aspect.template)
local template = {
_VERSION = "1.8",
_VERSION = "1.9",
_NAME = "aspect",
}
local mt = { __index = template }
Expand Down
44 changes: 29 additions & 15 deletions src/aspect/utils/range.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,26 @@ local setmetatable = setmetatable
local floor = math.floor
local abs = math.abs

local function iterator(self, k)
--- Range iterator
--- @class aspect.utils.range
--- @field from number
--- @field to number
--- @field step number
--- @field incr boolean
local range = {}

--- Magic function for {{ for }} tag
--- @return fun iterator (see range.__iterate)
--- @return table context object
--- @return number initial key value
function range:__pairs()
return self.__iterate, self, 0
end

--- Iterator
--- @return number the key
--- @return number the value
function range:__iterate(k)
local i = self.from + k * self.step
if self.incr then
if i > self.to then
Expand All @@ -19,30 +38,26 @@ local function iterator(self, k)
end
end

local function __pairs(self)
return iterator, self, 0
end

local function __count(self)
--- Magic function for calculating the number of iterations (elements)
--- @return number count of iterations/elements
function range:__count()
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
__pairs = range.__pairs,
__count = range.__count
}

--- Range constructor
--- @param from number
--- @param to number
--- @param step number
function range.new(from, to, step)
return setmetatable({
incr = from < to,
Expand All @@ -52,5 +67,4 @@ function range.new(from, to, step)
}, mt)
end


return range

0 comments on commit 93dcd76

Please sign in to comment.