Module:Template parameter value: Difference between revisions
Jump to navigation
Jump to search
Richardpruen (talk | contribs) m (1 revision imported) |
imported>MSGJ (reverting that last update per our discussion, if anyone needs this functionality then let's discuss again) |
||
Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
local | local _getParameters = require("Module:Transcluder").getParameters | ||
local escapeString = require("Module:String")._escapePattern | |||
local yesno = require("Module:Yesno") | |||
local function getTitle(title) | local function getTitle(title) | ||
Line 11: | Line 10: | ||
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 | |||
local function escapeComments(content) | |||
for comment in string.gmatch(content, "%b<>") do | |||
if string.sub(comment,1,4) == "<!--" and string.sub(comment,-3,-1) == "-->" then | |||
local safeComment = string.gsub("<!--" .. mw.text.nowiki(string.sub(comment,4,-3)) .. "-->", "%%", "%%%%") | |||
content = string.gsub(content, escapeString(comment), safeComment, 1) | |||
end | |||
end | |||
return content | |||
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) | |||
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] | |||
table.insert(parameterTree[key], value) --Insert the initial value into the tree | |||
for subtemplate in string.gmatch(value, "{%b{}}") do --And now check for subvalues | |||
local subparams = getAllParameters(subtemplate) | |||
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 | |||
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 {} | |||
local templateIndex = tonumber(options.templateIndex) or 1 | |||
local parameterIndex = tonumber(options.parameterIndex) or 1 | |||
local ignoreSubtemplates = options.ignoreSubtemplates 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 = escapeComments(title:getContent() or "") | |||
local foundTemplates = 0 | |||
local foundParameters = 0 | |||
for _,template in next,matchAllTemplates(content) do | |||
for _,wantedTemplate in pairs(templates) do | |||
if string.match(template, "^{{%s*"..wantedTemplate.."%s*[|}]") then | |||
foundTemplates = foundTemplates + 1 | |||
if foundTemplates == templateIndex then --Found our wanted template | |||
local value | |||
if ignoreSubtemplates then | |||
value = getParameters(template)[parameter] or "" | |||
else | |||
value = getAllParameters(template)[parameter][parameterIndex] or "" | |||
end | |||
value = string.gsub(value, "</?%a*include%a*>", "") | |||
value = mw.text.trim(value) | |||
return true, value | |||
end | |||
end | |||
end | |||
end | |||
return false, "No valid template found" | |||
end | |||
--Template entry point. Returns an empty string upon failure | |||
function p.main(frame) | function p.main(frame) | ||
local args = require('Module:Arguments').getArgs(frame, { | local args = require('Module:Arguments').getArgs(frame, { | ||
wrappers = 'Template:Template parameter value' | wrappers = 'Template:Template parameter value' | ||
}) | }) | ||
local | local options = { | ||
templateIndex = args[3], | |||
parameterIndex = args[5], | |||
ignoreSubtemplates = yesno(args.ignore_subtemplates or args.ist) or false | |||
} | |||
local success,result = p.getValue(args[1], args[2], args[4], options) | |||
if not success then | |||
return "" | |||
else | |||
return frame:preprocess(result) | |||
local | |||
end | end | ||
end | end | ||
--Potentially useful module entry points | |||
p.matchAllTemplates = matchAllTemplates | |||
p.getParameters = getParameters | |||
p.getAllParameters = getAllParameters | |||
return p | return p |
Latest revision as of 22:39, 26 March 2023
Documentation for this module may be created at Module:Template parameter value/doc
local p = {} local _getParameters = require("Module:Transcluder").getParameters local escapeString = require("Module:String")._escapePattern local yesno = require("Module:Yesno") 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 local function escapeComments(content) for comment in string.gmatch(content, "%b<>") do if string.sub(comment,1,4) == "<!--" and string.sub(comment,-3,-1) == "-->" then local safeComment = string.gsub("<!--" .. mw.text.nowiki(string.sub(comment,4,-3)) .. "-->", "%%", "%%%%") content = string.gsub(content, escapeString(comment), safeComment, 1) end end return content 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) 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] table.insert(parameterTree[key], value) --Insert the initial value into the tree for subtemplate in string.gmatch(value, "{%b{}}") do --And now check for subvalues local subparams = getAllParameters(subtemplate) 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 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 {} local templateIndex = tonumber(options.templateIndex) or 1 local parameterIndex = tonumber(options.parameterIndex) or 1 local ignoreSubtemplates = options.ignoreSubtemplates 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 = escapeComments(title:getContent() or "") local foundTemplates = 0 local foundParameters = 0 for _,template in next,matchAllTemplates(content) do for _,wantedTemplate in pairs(templates) do if string.match(template, "^{{%s*"..wantedTemplate.."%s*[|}]") then foundTemplates = foundTemplates + 1 if foundTemplates == templateIndex then --Found our wanted template local value if ignoreSubtemplates then value = getParameters(template)[parameter] or "" else value = getAllParameters(template)[parameter][parameterIndex] or "" end value = string.gsub(value, "</?%a*include%a*>", "") value = mw.text.trim(value) return true, value 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 = { templateIndex = args[3], parameterIndex = args[5], ignoreSubtemplates = yesno(args.ignore_subtemplates or args.ist) 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