Dokumentaci tohoto modulu lze vytvořit na stránce Nápověda:Modul:wton

-- Wiki Template Object Notation, a wiki friendly adaptation of a subset of JSON

local module = {}

function module.parse(template_arguments)
	local key
	local last_key
	local value
	local result = {}
	local stack = {}
	for key, value in pairs(template_arguments) do
		if type(key) ~= "number" then
			error("Pojmenované parametry nejsou povoleny")
		end
		if mw.text.trim(value) == "}" then
			result = table.remove(stack)
			if result == nil then
				error("Parametr '}' se používá na nesprávném místě")
			end
			last_key = table.remove(stack)
		else
			local index = string.find(value, "[:{]")
			if index == nil then
				error("Parametr '" .. value .. "' není rozpoznán")
			end
			local control_character = string.sub(value, index, index)
			key = mw.text.trim(string.sub(value, 1, index - 1))
			value = mw.text.trim(string.sub(value, index + 1))
			if control_character == "{" then
				if key == "+" then
					if last_key == nil then
						error("'+' nemůže být prvním parametrem")
					end
					local new_object = {}
					local previous_value = result[last_key]
					if previous_value[1] then
						table.insert(result[last_key], new_object)
					elseif previous_value == "" then
						result[last_key] = {new_object}
					else
						result[last_key] = {previous_value, new_object}
					end
					table.insert(stack, last_key)
					table.insert(stack, result)
					result = new_object
				else
					if result[key] ~= nil then
						error("Klíč '" .. key .. "' je duplikátem")
					end
					local new_object = {}
					result[key] = new_object
					table.insert(stack, key)
					table.insert(stack, result)
					result = new_object
				end
				if value ~= "" then
					result[""] = value
				end
			elseif key == "+" then
				if last_key == nil then
					error("'+' nemůže být prvním parametrem")
				end
				local previous_value = result[last_key]
				if previous_value[1] then
					table.insert(result[last_key], value)
				elseif previous_value == "" then
					result[last_key] = {value}
				else
					result[last_key] = {previous_value, value}
				end
			else
				if result[key] ~= nil then
					error("Klíč '" .. key .. "' je duplikátem")
				end
				last_key = key
			    result[key] = value
			end
		end
	end
	if stack[1] then
		error("Objekt nebyl uzavřen")
	end
	return result
end

function module.parse_validated(frame, schema)
	return module.validate(module.parse(frame:getParent().args), schema)
end

function module.validate(value, schema, path)
	if not path then
		path = ""
	end
	local required_type = schema[1]
	if not required_type then
		if type(value) == "string" then
                        if not schema[""] then
        			error("Parametr '" .. path .. "' má špatný formát (Musí být objekt)")
                        end
                        value = {[""] = value}
		end
		for key, field_value in pairs(value) do
			if not schema[key] then
				error("Parametr '" .. path .. key .. "' je neznamý")
			end
		end
		for key, schema in pairs(schema) do
			value[key] = module.validate(value[key], schema, path .. key .. ":")
		end
	elseif required_type == "list" then
		if not value then
			error("Parametr '" .. path .. "' chybí")
		end
		if type(value) == "string" then
			value = {value}
		elseif type(value) == "table" then
			for key, field_value in pairs(value) do
				if type(key) ~= "number" then
					value = {value}
					break
				end
			end
		end
		for key, field_value in pairs(value) do
			value[key] = module.validate(field_value, schema[2], path .. key .. ":")
		end
	elseif required_type == "option" then
		if value then
			return module.validate(value, schema[2], path)
		end
	elseif required_type == "text" then
		if type(value) ~= "string" then
			if value then
				error("Parametr '" .. path .. "' má špatný formát (Musí být text)")
			end
			error("Parametr '" .. path .. "' chybí")
		end
		if value == "" then
			error("Parametr '" .. path .. "' je prázdný")
		end
	else
		error("Schéma má špatný formát")
	end
	return value
end

return module