util/xtemplate.lua
author Kim Alvefur <zash@zash.se>
Wed, 27 Mar 2024 19:33:11 +0100
changeset 13471 c2a476f4712a
parent 13398 6debd8dd12ab
permissions -rw-r--r--
util.startup: Fix exiting on pidfile trouble prosody.shutdown() relies on prosody.main_thread, which has not been set yet at this point. Doing a clean shutdown might actually be harmful in case it tears down things set up by the conflicting Prosody, such as the very pidfile we were looking at. Thanks again SigmaTel71 for noticing
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
12217
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     1
local s_gsub = string.gsub;
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     2
local s_match = string.match;
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     3
local s_sub = string.sub;
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     4
local t_concat = table.concat;
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     5
12979
d10957394a3c util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12217
diff changeset
     6
local st = require("prosody.util.stanza");
12217
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     7
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     8
local function render(template, root, escape, filters)
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
     9
	escape = escape or st.xml_escape;
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    10
13398
6debd8dd12ab util.xtemplate: Adopt {-path-} syntax to strip preceding and/or trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    11
	return (s_gsub(template, "(%s*)(%b{})(%s*)", function(pre_blank, block, post_blank)
12217
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    12
		local inner = s_sub(block, 2, -2);
13398
6debd8dd12ab util.xtemplate: Adopt {-path-} syntax to strip preceding and/or trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    13
		if inner:sub(1, 1) == "-" then
6debd8dd12ab util.xtemplate: Adopt {-path-} syntax to strip preceding and/or trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    14
			pre_blank = "";
6debd8dd12ab util.xtemplate: Adopt {-path-} syntax to strip preceding and/or trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    15
			inner = inner:sub(2);
6debd8dd12ab util.xtemplate: Adopt {-path-} syntax to strip preceding and/or trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    16
		end
6debd8dd12ab util.xtemplate: Adopt {-path-} syntax to strip preceding and/or trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    17
		if inner:sub(-1, -1) == "-" then
6debd8dd12ab util.xtemplate: Adopt {-path-} syntax to strip preceding and/or trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    18
			post_blank = "";
6debd8dd12ab util.xtemplate: Adopt {-path-} syntax to strip preceding and/or trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    19
			inner = inner:sub(1, -2);
6debd8dd12ab util.xtemplate: Adopt {-path-} syntax to strip preceding and/or trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    20
		end
12217
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    21
		local path, pipe, pos = s_match(inner, "^([^|]+)(|?)()");
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    22
		if not (type(path) == "string") then return end
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    23
		local value
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    24
		if path == "." then
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    25
			value = root;
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    26
		elseif path == "#" then
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    27
			value = root:get_text();
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    28
		else
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    29
			value = root:find(path);
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    30
		end
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    31
		local is_escaped = false;
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    32
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    33
		while pipe == "|" do
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    34
			local func, args, tmpl, p = s_match(inner, "^(%w+)(%b())(%b{})()", pos);
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    35
			if not func then func, args, p = s_match(inner, "^(%w+)(%b())()", pos); end
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    36
			if not func then func, tmpl, p = s_match(inner, "^(%w+)(%b{})()", pos); end
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    37
			if not func then func, p = s_match(inner, "^(%w+)()", pos); end
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    38
			if not func then break end
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    39
			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
    40
			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
    41
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    42
			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
    43
				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
    44
				local ns, name = s_match(args, "^(%b{})(.*)$");
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    45
				if ns then
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    46
					ns = s_sub(ns, 2, -2);
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    47
				else
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    48
					name, ns = args, nil;
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    49
				end
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    50
				if ns == "" then ns = nil; end
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    51
				if name == "" then name = nil; end
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    52
				local out, i = {}, 1;
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    53
				for c in (value):childtags(name, ns) do out[i], i = render(tmpl, c, escape, filters), i + 1; end
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    54
				value = t_concat(out);
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    55
				is_escaped = true;
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    56
			elseif func == "and" and tmpl then
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    57
				local condition = value;
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    58
				if args then condition = root:find(args); end
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    59
				if condition then
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    60
					value = render(tmpl, root, escape, filters);
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    61
					is_escaped = true;
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    62
				end
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    63
			elseif func == "or" and tmpl then
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    64
				local condition = value;
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    65
				if args then condition = root:find(args); end
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    66
				if not condition then
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    67
					value = render(tmpl, root, escape, filters);
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    68
					is_escaped = true;
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    69
				end
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    70
			elseif filters and filters[func] then
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    71
				local f = filters[func];
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    72
				if args == nil then
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    73
					value, is_escaped = f(value, tmpl);
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    74
				else
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    75
					value, is_escaped = f(args, value, tmpl);
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    76
				end
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    77
			else
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    78
				error("No such filter function: " .. func);
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    79
			end
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    80
			pipe, pos = s_match(inner, "^(|?)()", p);
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
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    83
		if type(value) == "string" then
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    84
			if not is_escaped then value = escape(value); end
13398
6debd8dd12ab util.xtemplate: Adopt {-path-} syntax to strip preceding and/or trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    85
			return pre_blank .. value .. post_blank
12217
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    86
		elseif st.is_stanza(value) then
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    87
			value = value:get_text();
13398
6debd8dd12ab util.xtemplate: Adopt {-path-} syntax to strip preceding and/or trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    88
			if value then return pre_blank .. escape(value) .. post_blank end
12217
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    89
		end
13398
6debd8dd12ab util.xtemplate: Adopt {-path-} syntax to strip preceding and/or trailing whitespace
Kim Alvefur <zash@zash.se>
parents: 12979
diff changeset
    90
		return pre_blank .. post_blank
12217
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    91
	end))
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    92
end
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    93
dc9d63166488 util.xtemplate: Yet another string template library
Kim Alvefur <zash@zash.se>
parents:
diff changeset
    94
return { render = render }