author | Matthew Wild <mwild1@gmail.com> |
Mon, 20 Feb 2023 18:10:15 +0000 | |
branch | 0.12 |
changeset 12898 | 0598d822614f |
parent 12217 | dc9d63166488 |
permissions | -rw-r--r-- |
12217
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
1 |
-- render(template, stanza) --> string |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
2 |
-- {path} --> stanza:find(path) |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
3 |
-- {{ns}name/child|each({ns}name){sub-template}} |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
4 |
|
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
5 |
--[[ |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
6 |
template ::= "{" path ("|" name ("(" args ")")? (template)? )* "}" |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
7 |
path ::= defined by util.stanza |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
8 |
name ::= %w+ |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
9 |
args ::= anything with balanced ( ) pairs |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
10 |
]] |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
11 |
|
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
12 |
local s_gsub = string.gsub; |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
13 |
local s_match = string.match; |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
14 |
local s_sub = string.sub; |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
15 |
local t_concat = table.concat; |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
16 |
|
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
17 |
local st = require "util.stanza"; |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
18 |
|
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
19 |
local type escape_t = function (string) : string |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
20 |
local type filter_t = function (string, string | st.stanza_t, string) : string | st.stanza_t, boolean |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
21 |
local type filter_coll = { string : filter_t } |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
22 |
|
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
23 |
local function render(template : string, root : st.stanza_t, escape : escape_t, filters : filter_coll) : string |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
24 |
escape = escape or st.xml_escape; |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
25 |
|
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
26 |
return (s_gsub(template, "%b{}", function(block : string) : string |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
27 |
local inner = s_sub(block, 2, -2); |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
28 |
local path, pipe, pos = s_match(inner, "^([^|]+)(|?)()"); |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
29 |
if not path is string then return end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
30 |
local value : string | st.stanza_t |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
31 |
if path == "." then |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
32 |
value = root; |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
33 |
elseif path == "#" then |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
34 |
value = root:get_text(); |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
35 |
else |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
36 |
value = root:find(path); |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
37 |
end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
38 |
local is_escaped = false; |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
39 |
|
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
40 |
while pipe == "|" do |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
41 |
local func, args, tmpl, p = s_match(inner, "^(%w+)(%b())(%b{})()", pos as integer); |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
42 |
if not func then func, args, p = s_match(inner, "^(%w+)(%b())()", pos as integer); end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
43 |
if not func then func, tmpl, p = s_match(inner, "^(%w+)(%b{})()", pos as integer); end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
44 |
if not func then func, p = s_match(inner, "^(%w+)()", pos as integer); end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
45 |
if not func then break end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
46 |
if tmpl then tmpl = s_sub(tmpl, 2, -2); end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
47 |
if args then args = s_sub(args, 2, -2); end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
48 |
|
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
49 |
if func == "each" and tmpl and st.is_stanza(value) then |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
50 |
if not args then value, args = root, path; end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
51 |
local ns, name = s_match(args, "^(%b{})(.*)$"); |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
52 |
if ns then ns = s_sub(ns, 2, -2); else name, ns = args, nil; end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
53 |
if ns == "" then ns = nil; end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
54 |
if name == "" then name = nil; end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
55 |
local out, i = {}, 1; |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
56 |
for c in (value as st.stanza_t):childtags(name, ns) do |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
57 |
out[i], i = render(tmpl, c, escape, filters), i + 1; |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
58 |
end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
59 |
value = t_concat(out); |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
60 |
is_escaped = true; |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
61 |
elseif func == "and" and tmpl then |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
62 |
local condition = value; |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
63 |
if args then condition = root:find(args); end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
64 |
if condition then |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
65 |
value = render(tmpl, root, escape, filters); |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
66 |
is_escaped = true; |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
67 |
end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
68 |
elseif func == "or" and tmpl then |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
69 |
local condition = value; |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
70 |
if args then condition = root:find(args); end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
71 |
if not condition then |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
72 |
value = render(tmpl, root, escape, filters); |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
73 |
is_escaped = true; |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
74 |
end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
75 |
elseif filters and filters[func] then |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
76 |
local f = filters[func]; |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
77 |
if args == nil then |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
78 |
value, is_escaped = f(value, tmpl); |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
79 |
else |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
80 |
value, is_escaped = f(args, value, tmpl); |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
81 |
end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
82 |
else |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
83 |
error("No such filter function: " .. func); |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
84 |
end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
85 |
pipe, pos = s_match(inner, "^(|?)()", p as integer); |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
86 |
end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
87 |
|
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
88 |
if value is string then |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
89 |
if not is_escaped then value = escape(value); end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
90 |
return value; |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
91 |
elseif st.is_stanza(value) then |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
92 |
value = value:get_text(); |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
93 |
if value then |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
94 |
return escape(value); |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
95 |
end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
96 |
end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
97 |
return ""; |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
98 |
end)); |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
99 |
end |
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
100 |
|
dc9d63166488
util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff
changeset
|
101 |
return { render = render }; |