Module:Find sources
From Zoophilia Wiki
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