Module:UserLinks/shared

    From TestWiki

    Documentation for this module may be created at Module:UserLinks/shared/doc

    -- This module stores functions that are shared between [[Module:UserLinks]]
    -- and [[Module:UserLinks/extra]].
    
    -- Load data and define often-used variables
    local cfg = mw.loadData('Module:UserLinks/config')
    local namespaces = mw.site.namespaces
    
    -- Lazily initialise modules that we may or may not need
    local mCategoryHandler
    
    -- Define namespaces for which links need to be escaped with the colon trick.
    -- See [[w:en:Help:Colon trick]].
    local colonNamespaces = {
    	[6] = true, -- File
    	[14] = true, -- Category
    }
    
    local p = {}
    
    function p.maybeLoadModule(s)
    	-- Attempts to load the module s. If it succeeds, returns the module;
    	-- otherwise, returns false.
    	local success, mdl = pcall(require, s)
    	if success then
    		return mdl
    	else
    		return false
    	end
    end
    
    function p.raiseError(message, section, level)
    	-- Raises an error using the Lua error function. The error message is
    	-- designed to be caught with pcall and then passed to p.makeWikitextError.
    	-- The section, if specified, is the section name on a help page that gives
    	-- help to users about that particular error.
    	if section then
    		message = message .. '|' .. section
    	end
    	if not level or level == 0 then
    		level = 0
    	else
    		level = level + 1
    	end
    	error(message, level)
    end
    
    local localBlacklist = {
    	'/[sS]andbox$', -- Don't categorise sandboxes
    	'/[tT]est ?cases$', -- Don't categorise test case pages
    }
    
    local function currentTitleMatchesLocalBlacklist()
    	-- Return true if the current title matches any of the patterns in the
    	-- local blacklist table. Otherwise return false.
    	local title = mw.title.getCurrentTitle().prefixedText
    	for i, pattern in ipairs(localBlacklist) do
    		if title:find(pattern) then
    			return true
    		end
    	end
    	return false
    end
    
    function p.makeWikitextError(encodedMessage, demo)
    	local errorMessage, section = mw.ustring.match(encodedMessage, '^(.-)|(.*)$')
    	errorMessage = errorMessage or encodedMessage
    	
    	-- If not a demo, get the error category link and pass it through
    	-- [[Module:Category handler]]'s blacklist.
    	local category
    	if not demo then
    		category = string.format(
    			'[[%s:%s]]',
    			namespaces[14].name,
    			p.message('error-config-category')
    		)
    		mCategoryHandler = p.maybeLoadModule('Module:Category handler')
    		if mCategoryHandler then
    			-- Categorise all namespaces, but not blacklisted pages.
    			category = mCategoryHandler.main{all = category}
    		end
    		if category and currentTitleMatchesLocalBlacklist() then
    			category = nil
    		end
    	end
    	category = category or ''
    	
    	-- Format the error message and the section link.
    	local formattedError
    	if section then
    		formattedError = p.message(
    			'error-config-message-help',
    			errorMessage,
    			section
    		)
    	else
    		formattedError = p.message(
    			'error-config-message-nohelp',
    			errorMessage
    		)
    	end
    
    	-- Return the error message and the category inside html error tags.
    	return string.format(
    		'<strong class="error">%s</strong>%s',
    		formattedError,
    		category
    	)
    end
    
    local function formatPage(interwiki, namespace, page)
    	-- Formats an interwiki, a namespace and a page into a wikilink-ready
    	-- string. The interwiki and namespace are optional. If a namespace is
    	-- specified, it should be a valid key to mw.site.namespaces. The page
    	-- parameter is required.
    	local ret = {}
    	interwiki = interwiki or ''
    	if interwiki ~= '' or colonNamespaces[namespace] then
    		ret[#ret + 1] = ':'
    	end
    	ret[#ret + 1] = interwiki
    	if interwiki ~= '' then
    		ret[#ret + 1] = ':'
    	end
    	if namespace then
    		local nsTable = namespaces[namespace]
    		if not nsTable then
    			error('"' .. tostring(namespace) .. '" is not a valid namespace key', 2)
    		end
    		ret[#ret + 1] = nsTable.name
    		if namespace ~= 0 then
    			ret[#ret + 1] = ':'
    		end
    	end
    	ret[#ret + 1] = page
    	return table.concat(ret)
    end
    
    local function formatDisplay(s)
    	-- Replaces spaces in a string with "&nbsp;" to make sure they don't wrap.
    	-- Don't replace anything if we are substing, as we generally don't want
    	-- to use "&nbsp;" in that case.
    	if mw.isSubsting() then
    		return s
    	else
    		return s:gsub(' ', '&nbsp;')
    	end
    end
    
    function p.makeWikilink(interwiki, namespace, page, display)
    	-- Creates a wikilink. The interwiki, namespace and display parameters are
    	-- optional. If a namespace parameter is specified it must be a valid key
    	-- to mw.site.namespaces.
    	local formattedPage = formatPage(interwiki, namespace, page)
    	if display then
    		display = formatDisplay(display)
    		return string.format('[[%s|%s]]', formattedPage, display)
    	else
    		return string.format('[[%s]]', formattedPage)
    	end
    end
    
    local function formatUrlLink(url, display)
    	-- Formats a URL link with an optional display parameter.
    	if display then
    		display = formatDisplay(display)
    		return string.format('[%s %s]', url, display)
    	else
    		return string.format('[%s]', url)
    	end
    end
    
    function p.makeUrlLink(s, display)
    	-- Makes a URL link with an optional display parameter. The first input
    	-- may be any valid input to mw.uri.new.
    	local url = mw.uri.new(s)
    	url = tostring(url)
    	return formatUrlLink(url, display)
    end
    
    function p.makeFullUrlLink(interwiki, namespace, page, query, display)
    	-- Makes a link to the full URL of a page. The interwiki, namespace, query
    	-- and display parameters are optional. If a namespace parameter is
    	-- specified it must be a valid key to mw.site.namespaces. The query
    	-- parameter can be a string or a table as specified in the mw.uri library.
    	local formattedPage = formatPage(interwiki, namespace, page)
    	local url = mw.uri.fullUrl(formattedPage, query)
    	url = tostring(url)
    	return formatUrlLink(url, display)
    end
    
    function p.message(key, ...)
    	-- Returns the message with the given key from [[Module:UserLinks/config]].
    	-- Extra parameters are substituted in the message for keys $1, $2, $3, etc.
    	local msg = cfg[key]
    	if not msg then
    		p.raiseError(
    			'No message found with key "' .. tostring(key) .. '"',
    			'No message found',
    			2
    		)
    	end
    	local noArgs = select('#', ...)
    	if noArgs < 1 then
    		return msg
    	else
    		local msg = mw.message.newRawMessage(msg, ...)
    		return msg:plain()
    	end
    end
    
    return p