Software /
code /
prosody
File
util/interpolation.lua @ 11906:ba3344926e18
MUC: Add option to include form in registration query
This was originally not done based on my interpretation of XEP-0045. Today's
reading, however, revealed that it actually says the result
> SHOULD contain **at least** a <username/> element
(emphasis mine)
I take this to mean that including a form **is** allowed (and I think this is
sensible). Tigase already includes the form I believe.
I've gated the new behaviour behind a (default off) option, because it hasn't
been tested for compatibility with clients. My primary desire for it is in
Snikket, where the clients will be tested to ensure compatibility with this.
I don't anticipate that (m)any clients would break, so maybe after 0.12 we can
experiment with enabling it by default and eventually remove the option.
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Mon, 15 Nov 2021 16:11:03 +0000 |
parent | 11307:f2e276bb4ef8 |
line wrap: on
line source
-- Simple template language -- -- The new() function takes a pattern and an escape function and returns -- a render() function. Both are required. -- -- The function render() takes a string template and a table of values. -- Sequences like {name} in the template string are substituted -- with values from the table, optionally depending on a modifier -- symbol. -- -- Variants are: -- {name} is substituted for values["name"] and is escaped using the -- second argument to new_render(). To disable the escaping, use {name!}. -- {name.item} can be used to access table items. -- To renter lists of items: {name# item number {idx} is {item} } -- Or key-value pairs: {name% t[ {idx} ] = {item} } -- To show a defaults for missing values {name? sub-template } can be used, -- which renders a sub-template if values["name"] is false-ish. -- {name& sub-template } does the opposite, the sub-template is rendered -- if the selected value is anything but false or nil. local type, tostring = type, tostring; local pairs, ipairs = pairs, ipairs; local s_sub, s_gsub, s_match = string.sub, string.gsub, string.match; local t_concat = table.concat; local function new_render(pat, escape, funcs) -- assert(type(pat) == "string", "bad argument #1 to 'new_render' (string expected)"); -- assert(type(escape) == "function", "bad argument #2 to 'new_render' (function expected)"); local function render(template, values) -- assert(type(template) == "string", "bad argument #1 to 'render' (string expected)"); -- assert(type(values) == "table", "bad argument #2 to 'render' (table expected)"); return (s_gsub(template, pat, function (block) block = s_sub(block, 2, -2); local name, raw, opt, e = s_match(block, "^([%a_][%w_.]*)(!?)(%p?)()"); if not name then return end local value = values[name]; if not value and name:find(".", 2, true) then value = values; for word in name:gmatch"[^.]+" do value = value[word]; if not value then break; end end end if funcs then while opt == '|' do local f; f, raw, opt, e = s_match(block, "^([%a_][%w_.]*)(!?)(%p?)()", e); f = funcs[f]; if value ~= nil and f then value = f(value); end end end if opt == '#' or opt == '%' then if type(value) ~= "table" then return ""; end local iter = opt == '#' and ipairs or pairs; local out, i, subtpl = {}, 1, s_sub(block, e); local subvalues = setmetatable({}, { __index = values }); for idx, item in iter(value) do subvalues.idx = idx; subvalues.item = item; out[i], i = render(subtpl, subvalues), i+1; end return t_concat(out); elseif opt == '&' then if not value then return ""; end return render(s_sub(block, e), values); elseif opt == '~' then if value then return ""; end return render(s_sub(block, e), values); elseif opt == '?' and not value then return render(s_sub(block, e), values); elseif value ~= nil then if type(value) ~= "string" then value = tostring(value); end if raw ~= '!' then return escape(value); end return value; end end)); end return render; end return { new = new_render; };