• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

bungle/lua-resty-template: Templating Engine (HTML) for Lua and OpenResty.

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称(OpenSource Name):

bungle/lua-resty-template

开源软件地址(OpenSource Url):

https://github.com/bungle/lua-resty-template

开源编程语言(OpenSource Language):

Lua 99.9%

开源软件介绍(OpenSource Introduction):

lua-resty-template

lua-resty-template is a compiling (1) (HTML) templating engine for Lua and OpenResty.

(1) with compilation we mean that templates are translated to Lua functions that you may call or string.dump as a binary bytecode blobs to disk that can be later utilized with lua-resty-template or basic load and loadfile standard Lua functions (see also Template Precompilation). Although, generally you don't need to do that as lua-resty-template handles this behind the scenes.

Hello World with lua-resty-template

local template = require "resty.template"      -- OR
local template = require "resty.template.safe" -- return nil, err on errors

-- Using template.new
local view = template.new "view.html"
view.message = "Hello, World!"
view:render()
-- Using template.render
template.render("view.html", { message = "Hello, World!" })
view.html
<!DOCTYPE html>
<html>
<body>
  <h1>{{message}}</h1>
</body>
</html>
Output
<!DOCTYPE html>
<html>
<body>
  <h1>Hello, World!</h1>
</body>
</html>

The same can be done with inline template string:

-- Using template string
template.render([[
<!DOCTYPE html>
<html>
<body>
  <h1>{{message}}</h1>
</body>
</html>]], { message = "Hello, World!" })

Contents

Template Syntax

You may use the following tags in templates:

  • {{expression}}, writes result of expression - html escaped
  • {*expression*}, writes result of expression
  • {% lua code %}, executes Lua code
  • {(template)}, includes template file, you may also supply context for include file {(file.html, { message = "Hello, World" } )} (NOTE: you cannot use comma (,) in file.html, in that case use {["file,with,comma"]} instead)
  • {[expression]}, includes expression file (the result of expression), you may also supply context for include file {["file.html", { message = "Hello, World" } ]}
  • {-block-}...{-block-}, wraps inside of a {-block-} to a value stored in a blocks table with a key block (in this case), see using blocks. Don't use predefined block names verbatim and raw.
  • {-verbatim-}...{-verbatim-} and {-raw-}...{-raw-} are predefined blocks whose inside is not processed by the lua-resty-template but the content is outputted as is.
  • {# comments #} everything between {# and #} is considered to be commented out (i.e. not outputted or executed)

From templates you may access everything in context table, and everything in template table. In templates you can also access context and template by prefixing keys.

<h1>{{message}}</h1> == <h1>{{context.message}}</h1>
Short Escaping Syntax

If you don't want a particular template tag to be processed you may escape the starting tag with backslash \:

<h1>\{{message}}</h1>

This will output (instead of evaluating the message):

<h1>{{message}}</h1>

If you want to add backslash char just before template tag, you need to escape that as well:

<h1>\\{{message}}</h1>

This will output:

<h1>\[message-variables-content-here]</h1>
A Word About Complex Keys in Context Table

Say you have this kind of a context table:

local ctx = {["foo:bar"] = "foobar"}

And you want to render the ctx["foo:bar"]'s value foobar in your template. You have to specify it explicitly by referencing the context in your template:

{# {*["foo:bar"]*} won't work, you need to use: #}
{*context["foo:bar"]*}

Or altogether:

template.render([[
{*context["foo:bar"]*}
]], {["foo:bar"] = "foobar"})
A Word About HTML Escaping

Only strings are escaped, functions are called without arguments (recursively) and results are returned as is, other types are tostringified. nils and ngx.nulls are converted to empty strings "".

Escaped HTML characters:

  • & becomes &amp;
  • < becomes &lt;
  • > becomes &gt;
  • " becomes &quot;
  • ' becomes &#39;
  • / becomes &#47;

Example

Lua
local template = require "resty.template"
template.render("view.html", {
  title   = "Testing lua-resty-template",
  message = "Hello, World!",
  names   = { "James", "Jack", "Anne" },
  jquery  = '<script src="js/jquery.min.js"></script>' 
})
view.html
{(header.html)}
<h1>{{message}}</h1>
<ul>
{% for _, name in ipairs(names) do %}
    <li>{{name}}</li>
{% end %}
</ul>
{(footer.html)}
header.html
<!DOCTYPE html>
<html>
<head>
  <title>{{title}}</title>
  {*jquery*}
</head>
<body>
footer.html
</body>
</html>

Reserved Context Keys and Remarks

It is advised that you do not use these keys in your context tables:

  • ___, holds the compiled template, if set you need to use {{context.___}}
  • context, holds the current context, if set you need to use {{context.context}}
  • echo, holds the echo helper function, if set you need to use {{context.echo}}
  • include, holds the include helper function, if set you need to use {{context.include}}
  • layout, holds the layout by which the view will be decorated, if set you need to use {{context.layout}}
  • blocks, holds the blocks, if set you need to use {{context.blocks}} (see: using blocks)
  • template, holds the template table, if set you need to use {{context.template}}

In addition to that with template.new you should not overwrite:

  • render, the function that renders a view, obviously ;-)

You should also not {(view.html)} recursively:

Lua
template.render "view.html"
view.html
{(view.html)}

You can load templates from "sub-directories" as well with {(syntax)}:

view.html
{(users/list.html)}

Also note that you can provide template either as a file path or as a string. If the file exists, it will be used, otherwise the string is used. See also template.load.

Installation

Just place template.lua and template directory somewhere in your package.path, under resty directory. If you are using OpenResty, the default location would be /usr/local/openresty/lualib/resty.

Using OpenResty Package Manager (opm)

$ opm get bungle/lua-resty-template

Using LuaRocks

$ luarocks install lua-resty-template

LuaRocks repository for lua-resty-template is located at https://luarocks.org/modules/bungle/lua-resty-template.

Nginx / OpenResty Configuration

When lua-resty-template is used in context of Nginx / OpenResty there are a few configuration directives that you need to be aware:

  • template_root (set $template_root /var/www/site/templates)
  • template_location (set $template_location /templates)

If none of these are set in Nginx configuration, ngx.var.document_root (aka root-directive) value is used. If template_location is set, it will be used first, and if the location returns anything but 200 as a status code, we do fallback to either template_root (if defined) or document_root.

With lua-resty-template 2.0 it is possible to override $template_root and $template_location with Lua code:

local template = require "resty.template".new({
  root     = "/templates",
  location = "/templates" 
})
Using document_root

This one tries to load file content with Lua code from html directory (relative to Nginx prefix).

http {
  server {
    location / {
      root html;
      content_by_lua '
        local template = require "resty.template"
        template.render("view.html", { message = "Hello, World!" })
      ';      
    }
  }
}
Using template_root

This one tries to load file content with Lua code from /usr/local/openresty/nginx/html/templates directory.

http {
  server {
    set $template_root /usr/local/openresty/nginx/html/templates;
    location / {
      root html;
      content_by_lua '
        local template = require "resty.template"
        template.render("view.html", { message = "Hello, World!" })
      ';      
    }
  }
}
Using template_location

This one tries to load content with ngx.location.capture from /templates location (in this case this is served with ngx_static module).

http {
  server {
    set $template_location /templates;
    location / {
      root html;
      content_by_lua '
        local template = require "resty.template"
        template.render("view.html", { message = "Hello, World!" })
      ';      
    }
    location /templates {
      internal;
      alias html/templates/;
    }    
  }
}

See also template.load.

Lua API

template.root

You can setup template root by setting this variable which will be looked for template files:

local template = require "resty.template".new({
  root = "/templates"
})
template.render_file("test.html")

This property overrides the one set in Nginx configuration (set $template_root /my-templates;)

template.location

This is what you can use with OpenResty as that will use ngx.location.capture to fetch templates files in non-blocking fashion.

local template = require "resty.template".new({
  location = "/templates"
})
template.render_file("test.html")

This property overrides the one set in Nginx configuration (set $template_location /my-templates;)

table template.new(view, layout)

Creates a new template instance that is used as a (default) context when rendered. A table that gets created has only one method render, but the table also has metatable with __tostring defined. See the example below. Both view and layout arguments can either be strings or file paths, but layout can also be a table created previously with template.new.

With 2.0 the new can also be used without arguments, which creates a new template instance:

local template = require "resty.template".new()

You can also pass a table that is then modified to be a template:

local config = {
  root = "/templates"
}

local template = require "resty.template".new(config)

This is handy as the template created by new does not share the cache with the global template returned by require "resty.template" (this was reported with issue #25).

You can also pass a boolean true or false as a view parameter which means that either safe or un-safe version of template is returned:

local unsafe = require "resty.template"
local safe   = unsafe.new(true)

There is also a default safe implementation available:

local safe = require "resty.template.safe"
-- you can create instance of safe too:
local safe_instance = safe.new()

safe version uses return nil, err Lua error handling pattern and unsafe just throws the errors, which you can catch with pcall, xpcall or coroutine.wrap.

Here are examples of using new with arguments:

local view = template.new"template.html"              -- or
local view = template.new("view.html", "layout.html") -- or
local view = template.new[[<h1>{{message}}</h1>]]     -- or
local view = template.new([[<h1>{{message}}</h1>]], [[
<html>
<body>
  {*view*}
</body>
</html>
]])
Example
local template = require "resty.template"
local view = template.new"view.html"
view.message  = "Hello, World!"
view:render()
-- You may also replace context on render
view:render{ title = "Testing lua-resty-template" }
-- If you want to include view context in  replacement context
view:render(setmetatable({ title = "Testing lua-resty-template" }, { __index = view }))
-- To get rendered template as a string, you can use tostring
local result = tostring(view)

boolean template.caching(boolean or nil)

This function enables or disables template caching, or if no parameters are passed, returns current state of template caching. By default template caching is enabled, but you may want to disable it on development or low-memory situations.

local template = require "resty.template"   
-- Get current state of template caching
local enabled = template.caching()
-- Disable template caching
template.caching(false)
-- Enable template caching
template.caching(true)

Please note that if the template was already cached when compiling a template, the cached version will be returned. You may want to flush cache with template.cache = {} to ensure that your template really gets recompiled.

function, boolean template.compile(view, cache_key, plain)

Parses, compiles and caches (if caching is enabled) a template and returns the compiled template as a function that takes context as a parameter and returns rendered template as a string. Optionally you may pass cache_key that is used as a cache key. If cache key is not provided view wil be used as a cache key. If cache key is no-cache the template cache will not be checked and the resulting function will not be cached. You may also optionally pass plain with a value of true if the view is plain text string (this will skip template.load and binary chunk detection in template.parse phase). If plain is false the template is considered to be a file, and all the issues with file reading are considered as errors. If the plain is set to nil (the default) the template does not consider file reading errors as fatal, and returns back the view (usually the path of the template).

local func = template.compile("template.html")          -- or
local func = template.compile([[<h1>{{message}}</h1>]])
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap