Module:Find sources: Difference between revisions

From Zoophilia Wiki
Jump to navigationJump to search
meta>Mr. Stradivarius
(don't bother with the template config sanity check - this is probably overkill given that there won't be many template config pages (and that I will probably write them all))
meta>Mr. Stradivarius
(add comments and add a short config section at the top)
Line 1: Line 1:
-- This module implements {{find sources}} and other similar templates, and also
-- This module implements {{find sources}} and other similar templates, and
-- provides a mechanism to easily create new source-finding templates.
-- 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]].


-------------------------------------------------------------------------------
-- Config
-------------------------------------------------------------------------------
-- Define the error message and category to be used if the module is used in
-- the main namespace and the template config doesn't set the
-- isUsedInMainspace key to true. The category is optional; if it is not
-- wanted, set NAMESPACE_ERROR_CATEGORY to nil.
local NAMESPACE_ERROR = 'Error: Please do not use this template in articles.'
local NAMESPACE_ERROR_CATEGORY = 'Pages with templates in the wrong namespace'
-- The separator to be used if no separator is specified in the template
-- config.
local DEFAULT_SEPARATOR = mw.message.new('Dot-separator'):plain()
-------------------------------------------------------------------------------
-- End config
-------------------------------------------------------------------------------
-- Define constants
local ROOT_PAGE = 'Module:Find sources'
local ROOT_PAGE = 'Module:Find sources'
local TEMPLATE_ROOT = ROOT_PAGE .. '/templates/'
local TEMPLATE_ROOT = ROOT_PAGE .. '/templates/' -- for template config modules
local LINK_ROOT = ROOT_PAGE .. '/links/'
local LINK_ROOT = ROOT_PAGE .. '/links/' -- for link config modules


-- Load required modules
local checkType = require('libraryUtil').checkType
local checkType = require('libraryUtil').checkType


Line 17: Line 33:
local function maybeLoadData(page)
local function maybeLoadData(page)
local success, data = pcall(mw.loadData, page)
local success, data = pcall(mw.loadData, page)
if success then
return success and data
return data
else
return nil
end
end
end


Line 34: Line 46:


local function renderSearchString(searchTerms, separator, transformFunc)
local function renderSearchString(searchTerms, separator, transformFunc)
-- This takes a table of search terms and turns it into a search string
-- that can be used in a URL or in a display value. The transformFunc
-- parameter can be used to transform each search term in some way (for
-- example, URL-encoding them).
local searchStrings = {}
local searchStrings = {}
for i, s in ipairs(searchTerms) do
for i, s in ipairs(searchTerms) do
Line 47: Line 63:


local function renderLink(code, searchTerms, display)
local function renderLink(code, searchTerms, display)
-- Renders the external link wikicode for one link, given the link code,
-- a table of search terms, and an optional display value.
-- Get link config.
-- Get link config.
local linkCfg = maybeLoadData(LINK_ROOT .. code)
local linkCfg = maybeLoadData(LINK_ROOT .. code)
Line 66: Line 85:
mw.uri.encode
mw.uri.encode
)
)
url = linkCfg.url or error(string.format(
url = substituteParams(linkCfg.url, searchString)
"no 'url' field found in the link config at [[%s]]",
LINK_ROOT .. code
))
url = substituteParams(url, searchString)
end
end
-- Fetch display.
return string.format('[%s %s]', url, display or linkCfg.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
end


function p._main(template, args)
function p._main(template, args)
-- The main access point from Lua.
checkType('_main', 1, template, 'string')
checkType('_main', 1, template, 'string')
checkType('_main', 2, args, 'table', true)
checkType('_main', 2, args, 'table', true)
Line 100: Line 110:
-- Namespace check.
-- Namespace check.
if not templateCfg.isUsedInMainspace and title.namespace == 0 then
if not templateCfg.isUsedInMainspace and title.namespace == 0 then
return '<strong class="error">' ..
local formatString
'Error: Please do not use this template in articles.' ..
if NAMESPACE_ERROR_CATEGORY then
'</strong>' ..
formatString = '<strong class="error">%s</strong>[[%s:%s]]'
'[[Category:Pages with templates in the wrong namespace]]' ..
else
'[[Category:Find sources multi transclusions with errors]]'
formatString = '<strong class="error">%s</strong>'
end
return string.format(
formatString,
NAMESPACE_ERROR,
mw.site.namespaces[14].name,
NAMESPACE_ERROR_CATEGORY
)
end
end


Line 133: Line 150:
links[i] = renderLink(t.code, searchTerms, t.display)
links[i] = renderLink(t.code, searchTerms, t.display)
end
end
local separator = templateCfg.separator or mw.message.new('Dot-separator'):plain()
local separator = templateCfg.separator or DEFAULT_SEPARATOR
links = table.concat(links, separator)
links = table.concat(links, separator)


Line 149: Line 166:


setmetatable(p, { __index = function(t, template)
setmetatable(p, { __index = function(t, template)
-- The main access point from #invoke.
-- Invocations will look like {{#invoke:Find sources|template name}},
-- where "template name" is a subpage of [[Module:Find sources/templates]].
return function(frame)
return function(frame)
local args = require('Module:Arguments').getArgs(frame, {
local args = require('Module:Arguments').getArgs(frame, {

Revision as of 12:36, 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.

-------------------------------------------------------------------------------
-- Config
-------------------------------------------------------------------------------

-- Define the error message and category to be used if the module is used in
-- the main namespace and the template config doesn't set the
-- isUsedInMainspace key to true. The category is optional; if it is not
-- wanted, set NAMESPACE_ERROR_CATEGORY to nil.
local NAMESPACE_ERROR = 'Error: Please do not use this template in articles.'
local NAMESPACE_ERROR_CATEGORY = 'Pages with templates in the wrong namespace'

-- The separator to be used if no separator is specified in the template
-- config.
local DEFAULT_SEPARATOR = mw.message.new('Dot-separator'):plain()

-------------------------------------------------------------------------------
-- End config
-------------------------------------------------------------------------------

-- Define constants
local ROOT_PAGE = 'Module:Find sources'
local TEMPLATE_ROOT = ROOT_PAGE .. '/templates/' -- for template config modules
local LINK_ROOT = ROOT_PAGE .. '/links/' -- for link config modules

-- Load required modules
local checkType = require('libraryUtil').checkType

local p = {}

local function maybeLoadData(page)
	local success, data = pcall(mw.loadData, page)
	return success and data
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 renderSearchString(searchTerms, separator, transformFunc)
	-- This takes a table of search terms and turns it into a search string
	-- that can be used in a URL or in a display value. The transformFunc
	-- parameter can be used to transform each search term in some way (for
	-- example, URL-encoding them).
	local searchStrings = {}
	for i, s in ipairs(searchTerms) do
		searchStrings[i] = s
	end
	if transformFunc then
		for i, s in ipairs(searchStrings) do
			searchStrings[i] = transformFunc(s)
		end
	end
	return table.concat(searchStrings, separator)
end

local function renderLink(code, searchTerms, display)
	-- Renders the external link wikicode for one link, given the link code,
	-- a table of search terms, and an optional display value.

	-- 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 separator = linkCfg.separator or "+"
		local searchString = renderSearchString(
			searchTerms,
			separator,
			mw.uri.encode
		)
		url = substituteParams(linkCfg.url, searchString)
	end
	
	return string.format('[%s %s]', url, display or linkCfg.display)
end

function p._main(template, args)
	-- The main access point from Lua.
	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

	-- Namespace check.
	if not templateCfg.isUsedInMainspace and title.namespace == 0 then
		local formatString
		if NAMESPACE_ERROR_CATEGORY then
			formatString = '<strong class="error">%s</strong>[[%s:%s]]'
		else
			formatString = '<strong class="error">%s</strong>'
		end
		return string.format(
			formatString,
			NAMESPACE_ERROR,
			mw.site.namespaces[14].name,
			NAMESPACE_ERROR_CATEGORY
		)
	end

	-- Get the search terms from the arguments.
	local searchTerms = {}
	for i, s in ipairs(args) do
		searchTerms[i] = s
	end
	searchTerms[1] = searchTerms[1] or title.subpageText
	searchTerms[1] = '"' .. searchTerms[1] .. '"'

	-- Make the intro link
	local introLink
	if templateCfg.introLink then
		local code = templateCfg.introLink.code
		local display = templateCfg.introLink.display or renderSearchString(
			searchTerms,
			'&nbsp;'
		)
		introLink = renderLink(code, searchTerms, display)
	else
		introLink = ''
	end

	-- Make the other links
	local links = {}
	for i, t in ipairs(templateCfg.links) do
		links[i] = renderLink(t.code, searchTerms, t.display)
	end
	local separator = templateCfg.separator or DEFAULT_SEPARATOR
	links = table.concat(links, separator)

	-- Make the blurb.
	local blurb = substituteParams(templateCfg.blurb, introLink, links)
	local span = mw.html.create('span')
	span
		:addClass('plainlinks')
		:addClass(templateCfg.class)
		:cssText(templateCfg.style)
		:wikitext(blurb)

	return tostring(span)
end

setmetatable(p, { __index = function(t, template)
	-- The main access point from #invoke.
	-- Invocations will look like {{#invoke:Find sources|template name}},
	-- where "template name" is a subpage of [[Module:Find sources/templates]].
	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