Module:Hatnote

    From Nonbinary Wiki
    Revision as of 16:16, 29 April 2014 by m>Mr. Stradivarius (make makeWikitextError use Module:Yesno to parse the demo parameter, and remove underscores from all the function names, as that's normally done for private functions, whereas these are public)

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

    --------------------------------------------------------------------------------
    --                              Module:Hatnote                                --
    --                                                                            --
    -- This module produces hatnote links and links to related articles. It       --
    -- implements the {{rellink}} and {{hatnote}} meta-templates, and includes    --
    -- helper functions for other Lua modules to format hatnote links.            --
    --------------------------------------------------------------------------------
    
    local libraryUtil = require('libraryUtil')
    local checkType = libraryUtil.checkType
    local mArguments -- lazily initialise [[Module:Arguments]]
    local yesno -- lazily initialise [[Module:Yesno]]
    
    local p = {}
    
    --------------------------------------------------------------------------------
    -- Helper functions
    --------------------------------------------------------------------------------
    
    local function getArgs(frame)
    	-- Fetches the arguments from the parent frame. Whitespace is trimmed and
    	-- blanks are removed.
    	mArguments = require('Module:Arguments')
    	return mArguments.getArgs(frame, {parentOnly = true})
    end
    
    local function removeInitialColon(s)
    	-- Removes the initial colon from a string, if present.
    	return s:match('^:?(.*)')
    end
    
    function p.findNamespaceId(link, removeColon)
    	-- Finds the namespace id (namespace number) of a link or a pagename. This
    	-- function will not work if the link is enclosed in double brackets. Colons
    	-- are trimmed from the start of the link by default. To skip colon
    	-- trimming, set the removeColon parameter to true.
    	checkType('findNamespaceId', 1, link, 'string')
    	checkType('findNamespaceId', 2, removeColon, 'boolean', true)
    	if removeColon ~= false then
    		link = removeInitialColon(link)
    	end
    	local namespace = link:match('^(.-):')
    	if namespace then
    		local nsTable = mw.site.namespaces[namespace]
    		if nsTable then
    			return nsTable.id
    		end
    	end
    	return 0
    end
    
    function p.formatPages(...)
    	-- Formats a list of pages using formatLink and returns it as an array. Nil
    	-- values are not allowed.
    	local pages = {...}
    	local ret = {}
    	for i, page in ipairs(pages) do
    		ret[i] = p.formatLink(page)
    	end
    	return ret
    end
    
    function p.formatPageTables(...)
    	-- Takes a list of page/display tables and returns it as a list of
    	-- formatted links. Nil values are not allowed.
    	local pages = {...}
    	local links = {}
    	for i, t in ipairs(pages) do
    		checkType('formatPageTables', i, t, 'table')
    		local link = t[1]
    		local display = t[2]
    		links[i] = p.formatLink(link, display)
    	end
    	return links
    end
    
    function p.makeWikitextError(msg, demo)
    	-- Formats an error message to be returned to wikitext. If demo is not nil
    	-- or false, no error category is added.
    	checkType('makeWikitextError', 1, msg, 'string')
    	yesno = require('Module:Yesno')
    	local errorCategory = 'Hatnote templates with errors'
    	local errorCategoryLink
    	if yesno(demo) then
    		errorCategoryLink = string.format(
    			'[[%s:%s]]',
    			mw.site.namespaces[14].name,
    			errorCategory
    		)
    	else
    		errorCategoryLink = ''
    	end
    	return string.format(
    		'<strong class="error">Error: %s.</strong>%s',
    		msg,
    		errorCategoryLink
    	)
    end
    
    --------------------------------------------------------------------------------
    -- Format link
    --
    -- Makes a wikilink from the given link and display values. Links are escaped
    -- with colons if necessary, and links to sections are detected and displayed
    -- with " § " as a separator rather than the standard MediaWiki "#".
    --------------------------------------------------------------------------------
    
    function p.formatLink(frame)
    	local args = getArgs(frame)
    	local link = args[1]
    	local display = args[2]
    	if not link then
    		return p.makeWikitextError('no link specified')
    	end
    	return p.formatLink(link, display)
    end
    
    function p.formatLink(link, display)
    	-- Find whether we need to use the colon trick or not. We need to use the
    	-- colon trick for categories and files, as otherwise category links
    	-- categorise the page and file links display the file.
    	checkType('formatLink', 1, link, 'string')
    	checkType('formatLink', 2, display, 'string', true)
    	link = removeInitialColon(link)
    	local namespace = p.findNamespaceId(link, false)
    	local colon
    	if namespace == 6 or namespace == 14 then
    		colon = ':'
    	else
    		colon = ''
    	end
    
    	-- Find the display value.
    	if not display then
    		local page, section = link:match('^(.-)#(.*)$')
    		if page then
    			display = page .. ' § ' .. section
    		end
    	end
    
    	-- Assemble the link.
    	if display then
    		return string.format('[[%s%s|%s]]', colon, link, display)
    	else
    		return string.format('[[%s%s]]', colon, link)
    	end
    end
    
    --------------------------------------------------------------------------------
    -- Hatnote
    --
    -- Produces standard hatnote text. Implements the {{hatnote}} template.
    --------------------------------------------------------------------------------
    
    function p.hatnote(frame)
    	local args = getArgs(frame)
    	local s = args[1]
    	local options = {}
    	if not s then
    		return p.makeWikitextError('no text specified')
    	end
    	options.extraclasses = args.extraclasses
    	options.selfref = args.selfref
    	return p._hatnote(s, options)
    end
    
    function p._hatnote(s, options)
    	checkType('_hatnote', 1, s, 'string')
    	checkType('_hatnote', 2, options, 'table', true)
    	local classes = {'rellink'}
    	local extraclasses = options.extraclasses
    	local selfref = options.selfref
    	if type(extraclasses) == 'string' then
    		classes[#classes + 1] = extraclasses
    	end
    	if selfref then
    		classes[#classes + 1] = 'selfref'
    	end
    	return string.format(
    		'<div class="%s">%s</div>',
    		table.concat(classes, ' '),
    		s
    	)
    end
    
    return p