Module:translations/multi-nowiki



local export = {}

local parent_frame = mw.getCurrentFrame()
local frame_factory = parent_frame:newChild{}

local function getNilParent(self)
	return nil
end

frame_factory.getParent = getNilParent

local function newCallbackParserValue(callback)
	local value = {}
	local cache
	function value:expand()
		if not cache then
			cache = callback()
		end
		return cache
	end
	return value
end

local function getArgument(self, opt)
	local name
	if type(opt) == "table" then
		name = opt.name
	else
		name = opt
	end

	return newCallbackParserValue(
		function ()
			return self.args[name]
		end
		)
end

local function getTitle(self)
	return self.title
end

local function newChild(self, opt)
	if type( opt ) ~= "table" then
		error("frame:newChild: the first parameter must be a table", 2)
	end
	
	local title, args
	if opt.title == nil then
		title = self.title
	else
		title = tostring(opt.title)
	end
	if opt.args == nil then
		args = {}
	elseif type(opt.args) ~= "table" then
		error("frame:newChild: args must be a table", 2)
	end
	
	local parent = self
	local child = frame_factory:newChild{}
	
	child.title = title
	child.args = args
	
	child.getArgument = getArgument
	child.newChild = newChild
	child.getTitle = getTitle
	child.preparse = true
	
	function child:getParent()
		return parent
	end
	
	return child
end

parent_frame.title = parent_frame:getTitle()
parent_frame.getArgument = getArgument
parent_frame.getParent = getNilParent
parent_frame.newChild = newChild
parent_frame.getTitle = getTitle
parent_frame.preparse = true

local child_frame = parent_frame:newChild{}

local template_functions = {}

template_functions["t"] = function(args)
	parent_frame.args = args
	child_frame.args = {}
	return require "Module:translations".show(child_frame)
end

template_functions["t+"] = function(args)
	parent_frame.args = args
	child_frame.args = {interwiki = "tpos"}
	return require "Module:translations".show(child_frame)
end

function make_module_args(template_args)
	-- We do this unconditionally because a valid module invocation always has
	-- a function name (which looks like argument 1 of a template) so we always
	-- need to shift down arguments.
	local new_args = require "Module:table".shallowcopy(template_args)
	for k, v in pairs(template_args) do
		local old_k = k
		k = tonumber(k)
		if k and require "Module:table".isPositiveInteger(k) then
			new_args[old_k] = nil
			if k > 1 then
				new_args[k - 1] = v
			end
		end
	end
	return new_args
end

function export.expand(frame)
	local args
	if mw.title.getCurrentTitle().nsText == "Module" then
		args = frame.args
	else
		args = frame:getParent().args
	end
	local text = mw.text.unstripNoWiki(args[1])
	text = mw.text.trim(text)
	local parse_template
	local function expand(text)
		return text:gsub(
			"%b{}",
			function(maybe_template)
				if maybe_template:sub(2, 2) == "{" and maybe_template:sub(-2, -2) == "}" then
					parse_template = parse_template or require("Module:template parser").parseTemplate
					local template_name, template_args = parse_template(maybe_template)
					-- Technically substitution syntax is more lax, but this gets
					-- most cases.
					template_name = template_name:gsub("^subst:", "")
					-- Same for module invocation syntax.
					local module_name = template_name:match "^#invoke:(.+)"
					if module_name then
						local function_name = template_args[1]
						if function_name then
							parent_frame.args = {}
							child_frame.args = make_module_args(template_args)
							return require("Module:" .. module_name)[function_name](child_frame)
						end
					end
					local new_template_args = {}
					for k, v in pairs(template_args) do
						new_template_args[k] = expand(v)
					end
					if template_functions[template_name] then
						return template_functions[template_name](new_template_args)
					else
						return frame:expandTemplate { title = template_name, args = new_template_args }
					end
				end
			end)
	end
	-- Strip off extra return value.
	return (expand(text))
end

return export