Module:Find sources: Difference between revisions
From Zoophilia Wiki
Jump to navigationJump to search
meta>Mr. Stradivarius start work on a replacement for Template:Find sources multi |
meta>Mr. Stradivarius add sanity checks for template config and link-generating code |
||
Line 10: | Line 10: | ||
local TEMPLATE_ROOT = ROOT_PAGE .. '/templates/' | local TEMPLATE_ROOT = ROOT_PAGE .. '/templates/' | ||
local LINK_ROOT = ROOT_PAGE .. '/links/' | local LINK_ROOT = ROOT_PAGE .. '/links/' | ||
local DEFAULT_SEPARATOR = ', ' | |||
local checkType = require('libraryUtils').checkType | |||
local p = {} | local p = {} | ||
local function | local function maybeLoadData(page) | ||
local success, | local success, data = pcall(mw.loadData, page) | ||
if success then | if success then | ||
return | return data | ||
else | else | ||
return nil | return nil | ||
Line 22: | Line 25: | ||
end | end | ||
local function | local function substituteParams(msg, ...) | ||
local | local params = {...} | ||
if | if params[1] then | ||
return | return mw.message.newRawMessage(msg):params(params):plain() | ||
else | else | ||
return | return msg | ||
end | |||
end | |||
local function renderLink(code, searchStrings, display) | |||
-- Get link config. | |||
local linkCfg = maybeLoadData(LINK_ROOT .. code) | |||
if not linkCfg then | |||
error(string.format( | |||
"invalid link code '%s'; no link config found at [[%s]]", | |||
code, | |||
LINK_ROOT .. code | |||
)) | |||
end | |||
-- Make URL. | |||
local url | |||
do | |||
local firstFormat = linkCfg.firstFormat or '"$1"' | |||
searchStrings[1] = substituteParams(firstFormat, searchStrings[1]) | |||
local separator = linkCfg.separator or "+" | |||
local searchString = table.concat(searchStrings, separator) | |||
url = linkCfg.url or error(string.format( | |||
"no 'url' field found in the link config at [[%s]]", | |||
LINK_ROOT .. code | |||
)) | |||
url = substituteParams(url, searchString) | |||
end | |||
-- Fetch display. | |||
display = display or linkCfg.display or error(string.format( | |||
"no 'display' field found in the link config at [[%s]]", | |||
LINK_ROOT .. code | |||
)) | |||
return string.format('[%s %s]', url, display) | |||
end | |||
local function checkTemplateCfgLinkTable(cfgPage, key, t) | |||
if type(t) ~= 'table' then | |||
error(string.format( | |||
"invalid link table found in key '%s' of template config at [[%s]] " .. | |||
"(expected type table, got type %s)", | |||
key, cfgPage, type(t) | |||
)) | |||
elseif type(t[1]) ~= 'string' then | |||
error(string.format( | |||
"invalid link table found in key '%s' of template config at [[%s]] " .. | |||
"(the first table value must be a string)", | |||
key, cfgPage | |||
)) | |||
elseif t[2] and type(t[2]) ~= 'string' then | |||
error(string.format( | |||
"invalid link table found in key '%s' of template config at [[%s]] " .. | |||
"(if the second table value is specified, it must be a string)", | |||
key, cfgPage | |||
)) | |||
end | end | ||
end | end | ||
function p. | function p._main(template, args) | ||
local | checkType('_main', 1, template, 'string') | ||
checkType('_main', 2, args, 'table', true) | |||
args = args or {} | |||
local title = mw.title.getCurrentTitle() | |||
-- Get the template config. | |||
local templateCfgPage = TEMPLATE_ROOT .. template | |||
local templateCfg = maybeLoadData(templateCfgPage) | |||
if not templateCfg then | if not templateCfg then | ||
error(string.format( | error(string.format( | ||
"invalid template name '%s'; no template config found at [[%s]] | "invalid template name '%s'; no template config found at [[%s]]", | ||
template, | template, templateCfgPage | ||
)) | )) | ||
end | end | ||
-- Template config sanity check. | |||
if templateCfg.introLink then | |||
checkTemplateCfgLinkTable(templateCfgPage, 'introLink', templateCfg.introLink) | |||
end | |||
if type(templateCfg.links) ~= 'table' then | |||
error(string.format( | |||
"type error in the 'links' field of the template config at [[%s]] " .. | |||
"(expected table, got %s)", | |||
templateCfgPage, type(templateCfg.links) | |||
)) | |||
end | |||
for _, t in ipairs(templateCfg.links) do | |||
checkTemplateCfgLinkTable(templateCfgPage, 'links', t) | |||
end | |||
-- Get the search strings from the arguments. | |||
local searchStrings = {} | |||
for i, s in ipairs(args) do | |||
searchStrings[i] = mw.uri.encode(s) | |||
end | |||
searchStrings[1] = searchStrings[1] or title.subpageText | |||
-- Make the intro link | |||
local introLink | |||
if templateCfg.introLink then | |||
local code = templateCfg.introLink[1] | |||
local display = templateCfg.introLink[2] | |||
introLink = renderLink(code, searchStrings, display) | |||
else | |||
introLink = '' | |||
end | |||
-- Make the other links | |||
local links = {} | |||
for i, t in ipairs(templateCfg.links) do | |||
local code = t[1] | |||
local display = t[2] | |||
links[i] = renderLink(code, searchStrings, display) | |||
end | |||
links = table.concat(links, templateCfg.separator or DEFAULT_SEPARATOR) | |||
end | end | ||
Line 47: | Line 153: | ||
wrappers = mw.site.namespaces[10].name .. ':' .. template | wrappers = mw.site.namespaces[10].name .. ':' .. template | ||
}) | }) | ||
return t. | return t._main(template, args) | ||
end | end | ||
end }) | end}) | ||
return p | return p |
Revision as of 07:13, 26 September 2014
Documentation for this module may be created at Module:Find sources/doc
-- This module implements {{find sources}} and other similar templates, and also
-- provides a mechanism to easily create new source-finding templates.
--
-- Template settings are found in subpages of [[Module:Find sources/templates]].
-- Link functions are defined in subpages of [[Module:Find sources/links]].
-- Functions shared between the link modules are stored at
-- [[Module:Find sources/shared]].
local ROOT_PAGE = 'Module:Find sources'
local TEMPLATE_ROOT = ROOT_PAGE .. '/templates/'
local LINK_ROOT = ROOT_PAGE .. '/links/'
local DEFAULT_SEPARATOR = ', '
local checkType = require('libraryUtils').checkType
local p = {}
local function maybeLoadData(page)
local success, data = pcall(mw.loadData, page)
if success then
return data
else
return nil
end
end
local function substituteParams(msg, ...)
local params = {...}
if params[1] then
return mw.message.newRawMessage(msg):params(params):plain()
else
return msg
end
end
local function renderLink(code, searchStrings, display)
-- Get link config.
local linkCfg = maybeLoadData(LINK_ROOT .. code)
if not linkCfg then
error(string.format(
"invalid link code '%s'; no link config found at [[%s]]",
code,
LINK_ROOT .. code
))
end
-- Make URL.
local url
do
local firstFormat = linkCfg.firstFormat or '"$1"'
searchStrings[1] = substituteParams(firstFormat, searchStrings[1])
local separator = linkCfg.separator or "+"
local searchString = table.concat(searchStrings, separator)
url = linkCfg.url or error(string.format(
"no 'url' field found in the link config at [[%s]]",
LINK_ROOT .. code
))
url = substituteParams(url, searchString)
end
-- Fetch display.
display = display or linkCfg.display or error(string.format(
"no 'display' field found in the link config at [[%s]]",
LINK_ROOT .. code
))
return string.format('[%s %s]', url, display)
end
local function checkTemplateCfgLinkTable(cfgPage, key, t)
if type(t) ~= 'table' then
error(string.format(
"invalid link table found in key '%s' of template config at [[%s]] " ..
"(expected type table, got type %s)",
key, cfgPage, type(t)
))
elseif type(t[1]) ~= 'string' then
error(string.format(
"invalid link table found in key '%s' of template config at [[%s]] " ..
"(the first table value must be a string)",
key, cfgPage
))
elseif t[2] and type(t[2]) ~= 'string' then
error(string.format(
"invalid link table found in key '%s' of template config at [[%s]] " ..
"(if the second table value is specified, it must be a string)",
key, cfgPage
))
end
end
function p._main(template, args)
checkType('_main', 1, template, 'string')
checkType('_main', 2, args, 'table', true)
args = args or {}
local title = mw.title.getCurrentTitle()
-- Get the template config.
local templateCfgPage = TEMPLATE_ROOT .. template
local templateCfg = maybeLoadData(templateCfgPage)
if not templateCfg then
error(string.format(
"invalid template name '%s'; no template config found at [[%s]]",
template, templateCfgPage
))
end
-- Template config sanity check.
if templateCfg.introLink then
checkTemplateCfgLinkTable(templateCfgPage, 'introLink', templateCfg.introLink)
end
if type(templateCfg.links) ~= 'table' then
error(string.format(
"type error in the 'links' field of the template config at [[%s]] " ..
"(expected table, got %s)",
templateCfgPage, type(templateCfg.links)
))
end
for _, t in ipairs(templateCfg.links) do
checkTemplateCfgLinkTable(templateCfgPage, 'links', t)
end
-- Get the search strings from the arguments.
local searchStrings = {}
for i, s in ipairs(args) do
searchStrings[i] = mw.uri.encode(s)
end
searchStrings[1] = searchStrings[1] or title.subpageText
-- Make the intro link
local introLink
if templateCfg.introLink then
local code = templateCfg.introLink[1]
local display = templateCfg.introLink[2]
introLink = renderLink(code, searchStrings, display)
else
introLink = ''
end
-- Make the other links
local links = {}
for i, t in ipairs(templateCfg.links) do
local code = t[1]
local display = t[2]
links[i] = renderLink(code, searchStrings, display)
end
links = table.concat(links, templateCfg.separator or DEFAULT_SEPARATOR)
end
setmetatable(p, { __index = function(t, template)
return function(frame)
local args = require('Module:Arguments').getArgs(frame, {
wrappers = mw.site.namespaces[10].name .. ':' .. template
})
return t._main(template, args)
end
end})
return p