Module:epto

local m_tu = require'Module:template utilities'

local function codeWrap(frame, s1, s2, lang) return ' ' ..			'' .. 'Plain text output of ' .. frame:extensionTag({name = 'nowiki', content = s1}) .. ' ' .. -- style="border: 1px solid; background-color: #f8f8f8; padding: 0.5em; " ' ' ..				frame:extensionTag({name = 'syntaxhighlight', args = {lang = lang}, content = s2}) .. ' ' ..		' ' end

local function parse_lua_parameter(str) -- since Scribunto disabled loadstring local t = tonumber(str) if t then return number end if str:match'^".*"$' or str:match"^'.*'$" then return str:sub(2, -2) end t = str:match'^%[(=*)%[.*]%1]$' if t then t = t:len + 3 return str:sub(t, -t) end if str == 'true' then return true end if str == 'false' then return false end if str == 'nil' then return nil end if str:match'^[_%a][_%w%.]*$' then t = _G for id in str:gmatch'.*%f[%.%z]' do			if id:match'^[_%a][_%w]*$' then t = t[id] else error('invalid identifier: ' .. id) end end return t	end t = str:match'^%b{}$' if t then local r, r_count = {}, 0 for item in m_tu.gsplit_ignoring_brackets(t:sub(2, -2), {['{'] = '}'}, ',') do			local key, value = item:match'^%s*%[%s*(.-)%s]%s*=%s*(.-)%s*$' if key and key:len > 0 and value:len > 0 then r[parse_lua_parameter(key)] = parse_lua_parameter(value) else r_count = r_count + 1 r[r_count] = parse_lua_parameter(item:match'^%s*(.-)%s*$') end end return r	end mw.log(str) error('unsupported input: "' .. str .. '"') end

local function push_frame(title_and_args) local frame_this = mw.getCurrentFrame local frame_child = frame_this:newChild(title_and_args) function frame_child:getParent return frame_this end function mw.getCurrentFrame return frame_child end return frame_child end

local function pop_frame local frame_parent = mw.getCurrentFrame:getParent function mw.getCurrentFrame return frame_parent end return frame_parent end

local function mod(frame, mod_name, func_name, extra_mod_args) local s_args = extra_mod_args:match'^%b' if s_args then local func_args = {} local len_func_args = 0 for a in s_args:sub(2, -2):gmatch'(.-)%f[,%z],?' do			len_func_args = len_func_args + 1 if a ~= '' then func_args[len_func_args] = parse_lua_parameter(a) end end return codeWrap(frame, 'require("Module:' .. mod_name .. '").' .. func_name .. s_args, mw.dumpObject(require('Module:' .. mod_name)[func_name](unpack(func_args, 1, len_func_args))), 'lua') else local s_args_invoke = extra_mod_args:sub(1, 1) == '/' and extra_mod_args:gsub('/', '|') or '' return codeWrap(frame, ' with parent template ' .. m_tu.glue_temp{			title = '...',			args = frame.args,		}, tostring(require('Module:' .. mod_name)[func_name](push_frame(m_tu.parse_temp('')))), 'html') end end

local function t_subst_recur(frame, temp_name) local success, s = pcall(frame.callParserFunction, frame, { name = temp_name, args = frame.args }) if not success then success, s = pcall(frame.expandTemplate, frame, { title = temp_name, args = frame.args }) if not success then return m_tu.glue_temp{ title = temp_name, args = frame.args } end end local replacements = {} for p1, p2, s_invoke in m_tu.gfind_bracket(s, m_tu.brackets_temp) do		s_invoke = s_invoke:gsub('^{{subst:', '{{') local mod_name, func_name, mod_args = s_invoke:sub(3, -3):match'^#invoke:(..-)|(..-)%f[%z|](|?.*)' if mod_name then table.insert(replacements, {				p1,				p2,				tostring(require('Module:' .. mod_name)[func_name](push_frame(m_tu.parse_temp('{{Module:' .. mod_name .. mod_args .. '}}').args)))			}) pop_frame else local invoke = m_tu.parse_temp(s_invoke) invoke.title = mw.title.new(invoke.title, "Template") or invoke.title table.insert(replacements, {p1, p2, t_subst_recur(push_frame(invoke), invoke.title.prefixedText)}) pop_frame end end for i = #replacements, 1, -1 do s = s:sub(1, replacements[i][1] - 1) .. replacements[i][3] .. s:sub(replacements[i][2] + 1) end return s end

local function t_subst(frame, temp_name) local t = { title = 'subst:' .. temp_name, args = frame.args } return codeWrap(frame, m_tu.glue_temp(t), t_subst_recur(frame, temp_name), 'html') end

local function t(frame, temp_name) local t = { title = temp_name, args = frame.args } return codeWrap(frame, m_tu.glue_temp(t), frame:expandTemplate(t), 'html') end

return setmetatable({}, {	__index = function(self, str)		local subst = str:match'^subst:'		if subst then str = str:sub(7) end		local mod_name, func_name, extra_mod_args = str:match'^#invoke:(..-)#(..-)%f[%z/(](.*)' if not mod_name then mod_name, func_name, extra_mod_args = str:match'^[Mm]odule:(..-)#(..-)%f[%z/(](.*)'		end		if not mod_name then			mod_name, func_name, extra_mod_args = str:match'^[Mm]od:(..-)#(..-)%f[%z/(](.*)' end if mod_name then return function(frame) return mod(frame, mod_name, func_name, extra_mod_args) end end if mod_name then return function(frame) return mod(mod_name, func_name, frame) end end if subst then return function(frame) return t_subst(frame, str) end else return function(frame) return t(frame, str) end end end, })