پودمان:Template parameter value: تفاوت میان نسخه‌ها

از ویکی تراث
جز (مراجعة واحدة)
(بدون تفاوت)

نسخهٔ ‏۴ اوت ۲۰۲۳، ساعت ۱۴:۰۶


local p = {}
local _getParameters = require("Module:Transcluder").getParameters
local yesno = require("Module:Yesno")
local PrepareText = require("Module:Wikitext Parsing").PrepareText

local function getTitle(title)
	local success, titleObj = pcall(mw.title.new, title)
	if success then return titleObj
	else return nil end
end

--string.gmatch will check the largest block it can without re-scanning whats inside, but we need whats inside
local function matchAllTemplates(str)
	local matches = {}
	for template in string.gmatch(str, "{%b{}}") do
		table.insert(matches, template)
		local innerContent = string.sub(template, 3, -3)
		for _,subtemplate in next,matchAllTemplates(innerContent) do
			table.insert(matches, subtemplate)
		end
	end
	return matches
end

--Transcluder's getParameters, but force all keys to be a string (helps with template inputs)
local function getParameters(template)
	local parameters, text, paramOrder = _getParameters(template)
	local newParams = {}
	for key,value in next,parameters do
		newParams[tostring(key)] = value
	end
	local newParamOrder = {}
	for index,key in next,paramOrder do
		newParamOrder[index] = tostring(key)
	end
	return newParams, text, newParamOrder
end

-- Returns a table containing parameters and a table with the order in which each of their values were found.
-- Since this considers all subtemplates, a single parameter is expected to have multiple values.
-- E.g. {{ABC|X={{DEF|X=Value|Y=Other value}}{{ABC|X=Yes}}|Y=P}}
-- Would return {X={"{{DEF|X=Value|Y=Other value}}", "Value", "Yes"}, Y={"Other value", "P"}}
local function getAllParameters(template, ignore_blank, only_subtemplates)
	local parameterTree = setmetatable({}, {
		__index = function(self,key)
			rawset(self,key,{})
			return rawget(self,key)
		end
	})
	local params, _, paramOrder = getParameters(template)
	for _,key in ipairs(paramOrder) do
		local value = params[key]
		if not ignore_blank or value ~= "" then
			if not only_subtemplates then
				table.insert(parameterTree[key], value) --Insert the initial value into the tree
			end
			for subtemplate in string.gmatch(value, "{%b{}}") do --And now check for subvalues
				local subparams = getAllParameters(subtemplate, ignore_blank)
				for subkey,subset in next,subparams do
					for _,subvalue in ipairs(subset) do
						table.insert(parameterTree[subkey], subvalue) --And add any we find to our tree
					end
				end
			end
		end
	end
	return parameterTree
end

--Primary module entry point. Returns a success boolean and either the result or why it failed
function p.getValue(page, templates, parameter, options)
	if not (templates and parameter) then --Required parameters
		return false, "Missing required parameters 'templates' and 'parameter'"
	end
	parameter = tostring(parameter) --Force consistency
	options = options or {}
	
	--mix of camelCase and under_score is kept for backwards compatability
	local template_index = tonumber(options.templateIndex or options.template_index) or 1
	local parameter_index = tonumber(options.parameterIndex or options.parameter_index) or 1
	local ignore_subtemplates = options.ignoreSubtemplates or options.ignore_subtemplates or false
	local only_subtemplates = options.onlySubtemplates or options.only_subtemplates or false
	local ignore_blank = options.ignoreBlank or options.ignore_blank or false
	if type(templates) == "string" then
		templates = mw.text.split(templates, ", ?")
	end
	
	local title = getTitle(page)
	if title == nil then
		return false, "Requested title doesn't exist"
	end
	local content = PrepareText(title:getContent() or "")
	
	local foundTemplates = 0
	for _,template in next,matchAllTemplates(content) do
		for _,wantedTemplate in pairs(templates) do
			local firstLetter = string.sub(wantedTemplate, 1, 1)
			local firstUpper, firstLower = firstLetter:upper(), firstLetter:lower()
			if firstUpper ~= firstLower then
				wantedTemplate = "[" .. firstUpper .. firstLower .. "]" .. string.sub(wantedTemplate, 2)
			end
			if string.match(template, "^{{%s*"..wantedTemplate.."%s*[|}]") then
				foundTemplates = foundTemplates + 1
				if foundTemplates == template_index then --Found our wanted template
					local value
					if ignore_subtemplates then
						value = getParameters(template)[parameter] or ""
					else
						local params = getAllParameters(template, ignore_blank, only_subtemplates)
						value = params[parameter][parameter_index] or ""
					end

					value = string.gsub(value, "</?%a*include%a*>", "")
					value = mw.text.trim(value)
					return true, mw.text.decode(value) --due to PrepareText
				end
			end
		end
	end

	return false, "No valid template found"
end

--Template entry point. Returns an empty string upon failure
function p.main(frame)
	local args = require('Module:Arguments').getArgs(frame, {
		wrappers = 'Template:Template parameter value'
	})
	local options = {
		template_index = args[3],
		parameter_index = args[5],
		ignore_subtemplates = yesno(args.ignore_subtemplates or args.ist) or false,
		only_subtemplates = yesno(args.only_subtemplates) or false,
		ignore_blank = yesno(args.ignore_blank) or false,
	}
	local success, result = p.getValue(args[1], args[2], args[4], options)
	if not success then
		return ""
	else
		return frame:preprocess(result)
	end
end

--Potentially useful module entry points
p.matchAllTemplates = matchAllTemplates
p.getParameters = getParameters
p.getAllParameters = getAllParameters

return p