Module:Format link and Module:Redirect hatnote: Difference between pages

From Frontierpedia, the Microsoft Agent encyclopedia
(Difference between pages)
m (1 revision imported)
 
en>Nihiltres
(Updated from sandbox: Migrated p._quote to Module:Hatnote)
 
Line 1: Line 1:
--------------------------------------------------------------------------------
--[[
-- Format link
-- This module produces a "redirect" hatnote. It looks like this:
--
-- '"X" redirects here. For other uses, see Y.'
-- Makes a wikilink from the given link and display values. Links are escaped
-- It implements the {{redirect}} template.
-- with colons if necessary, and links to sections are detected and displayed
--]]
-- with " § " as a separator rather than the standard MediaWiki "#". Used in
 
-- the {{format link}} template.
local mHatnote = require('Module:Hatnote')
--------------------------------------------------------------------------------
local mHatList = require('Module:Hatnote list')
local mArguments --lazily initialize
local libraryUtil = require('libraryUtil')
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local checkType = libraryUtil.checkType
local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg
local checkTypeMulti = libraryUtil.checkTypeMulti
local mArguments -- lazily initialise [[Module:Arguments]]
local mError -- lazily initialise [[Module:Error]]
local yesno -- lazily initialise [[Module:Yesno]]


local p = {}
local p = {}
Line 20: Line 18:
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------


local function getArgs(frame)
local function getTitle(...)
-- Fetches the arguments from the parent frame. Whitespace is trimmed and
--Calls mw.title.new and returns either a title object, or nil on error
-- blanks are removed.
local success, titleObj = pcall(mw.title.new, ...)
mArguments = require('Module:Arguments')
return success and titleObj or nil
return mArguments.getArgs(frame, {parentOnly = true})
end
 
local function removeInitialColon(s)
-- Removes the initial colon from a string, if present.
return s:match('^:?(.*)')
end
 
local function maybeItalicize(s, shouldItalicize)
-- Italicize s if s is a string and the shouldItalicize parameter is true.
if s and shouldItalicize then
return '<i>' .. s .. '</i>'
else
return s
end
end
 
local function parseLink(link)
-- Parse a link and return a table with the link's components.
-- These components are:
-- - link: the link, stripped of any initial colon (always present)
-- - page: the page name (always present)
-- - section: the page name (may be nil)
-- - display: the display text, if manually entered after a pipe (may be nil)
link = removeInitialColon(link)
 
-- Find whether a faux display value has been added with the {{!}} magic
-- word.
local prePipe, display = link:match('^(.-)|(.*)$')
link = prePipe or link
 
-- Find the page, if it exists.
-- For links like [[#Bar]], the page will be nil.
local preHash, postHash = link:match('^(.-)#(.*)$')
local page
if not preHash then
-- We have a link like [[Foo]].
page = link
elseif preHash ~= '' then
-- We have a link like [[Foo#Bar]].
page = preHash
end
 
-- Find the section, if it exists.
local section
if postHash and postHash ~= '' then
section = postHash
end
return {
link = link,
page = page,
section = section,
display = display,
}
end
 
local function formatDisplay(parsed, options)
-- Formats a display string based on a parsed link table (matching the
-- output of parseLink) and an options table (matching the input options for
-- _formatLink).
local page = maybeItalicize(parsed.page, options.italicizePage)
local section = maybeItalicize(parsed.section, options.italicizeSection)
if (not section) then
return page
elseif (not page) then
return mw.ustring.format('§&nbsp;%s', section)
else
return mw.ustring.format('%s §&nbsp;%s', page, section)
end
end
 
local function missingArgError(target)
mError = require('Module:Error')
return mError.error{message =
'Error: no link or target specified! ([[' .. target .. '#Errors|help]])'
}
end
end


Line 107: Line 28:
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------


function p.formatLink(frame)
function p.redirect(frame)
-- The formatLink export function, for use in templates.
mArguments = require('Module:Arguments')
yesno = require('Module:Yesno')
local args = mArguments.getArgs(frame, {parentOnly=true})
local args = getArgs(frame)
--Get number of redirects
local link = args[1] or args.link
local numRedirects = tonumber(frame.args[1]) or 1
local target = args[3] or args.target
-- Create the options table.
if not (link or target) then
local options = {}
return missingArgError('Template:Format link')
options.selfref = args.selfref
end
return p._redirect(args, numRedirects, options)
 
return p._formatLink{
link = link,
display = args[2] or args.display,
target = target,
italicizePage = yesno(args.italicizepage),
italicizeSection = yesno(args.italicizesection),
categorizeMissing = args.categorizemissing
}
end
end


function p._formatLink(options)
function p._redirect(args, numRedirects, options, currentTitle, redirectTitle, targetTitle)
-- The formatLink export function, for use in modules.
-- Validate the input. Don't bother checking currentTitle, redirectTitle or
checkType('_formatLink', 1, options, 'table')
-- targetTitle, as they are only used in testing.
local function check(key, expectedType) --for brevity
checkType('_redirect', 1, args, 'table')
checkTypeForNamedArg(
checkType('_redirect', 2, numRedirects, 'number', true)
'_formatLink', key, options[key], expectedType or 'string', true
numRedirects = numRedirects or 1
)
checkType('_redirect', 3, options, 'table', true)
options = options or {}
currentTitle = currentTitle or mw.title.getCurrentTitle()
-- Get the table of redirects
local redirect = {}
for i = 1, numRedirects do
-- Return an error if a redirect parameter is missing.
if not args[i] then
return mHatnote.makeWikitextError(
'missing redirect parameter',
'Template:Redirect#Errors',
args.category
)
end
redirect[i] = args[i]
end
end
check('link')
-- Generate the text.
check('display')
local formattedRedirect = {}
check('target')
for k,v in pairs(redirect) do
check('italicizePage', 'boolean')
formattedRedirect[k] = mHatnote.quote(v)
check('italicizeSection', 'boolean')
check('categorizeMissing')
 
-- Normalize link and target and check that at least one is present
if options.link == '' then options.link = nil end
if options.target == '' then options.target = nil end
if not (options.link or options.target) then
return missingArgError('Module:Format link')
end
end
 
local text = {
local parsed = parseLink(options.link)
mHatList.andList(formattedRedirect) .. ' ' .. (#redirect == 1 and 'redirects' or 'redirect') .. ' here.',
local display = options.display or parsed.display
mHatList._forSee(args, #redirect + 1, {title = redirect[1], extratext = args.text})
local catMissing = options.categorizeMissing
}
local category = ''
text = table.concat(text, ' ')
 
-- Functionality for adding categories
-- Find the display text
local categoryTable = {}
if not display then display = formatDisplay(parsed, options) end
local function addCategory(cat)
 
if cat and cat ~= '' then
-- Handle the target option if present
-- Add by index to avoid duplicates
if options.target then
categoryTable[string.format('[[Category:%s]]', cat)] = true
local parsedTarget = parseLink(options.target)
end
parsed.link = parsedTarget.link
parsed.page = parsedTarget.page
end
end
--Generate tracking categories
local mhOptions = {}
local redirTitle
for k,v in pairs(redirect) do
-- We don't need a tracking category if the template invocation has been
-- copied directly from the docs, or if we aren't in main- or category-space.
if not v:find('^REDIRECT%d*$') and v ~= 'TERM' --
and currentTitle.namespace == 0 or currentTitle.namespace == 14
then
redirTitle = redirectTitle or getTitle(v)
if not redirTitle or not redirTitle.exists then
addCategory('Missing redirects')
elseif not redirTitle.isRedirect then
if string.find(redirTitle:getContent(), '#invoke:RfD') then
addCategory('Articles with redirect hatnotes impacted by RfD')
else
addCategory('Articles with redirect hatnotes needing review')
end
else
local target = targetTitle or redirTitle.redirectTarget
if target and target ~= currentTitle then
addCategory('Articles with redirect hatnotes needing review')
end
end
end


-- Test if page exists if a diagnostic category is specified
-- Generate the options to pass to [[Module:Hatnote]].
if catMissing and (mw.ustring.len(catMissing) > 0) then
if currentTitle.namespace == 0 and not mhOptions.selfref
local title = nil
and redirTitle and redirTitle.namespace ~= 0
if parsed.page then title = mw.title.new(parsed.page) end
then
if title and (not title.isExternal) then
-- We are on a mainspace page, and the hatnote starts with something
local success, exists = pcall(function() return title.exists end)
-- like "Wikipedia:Foo redirects here", so automatically label it as
if success and not exists then
-- a self-reference.
category = mw.ustring.format('[[Category:%s]]', catMissing)
mhOptions.selfref = true
end
else
mhOptions.selfref = options.selfref
end
end
end
end
--concatenate all the categories
-- Format the result as a link
local category = ''
if parsed.link == display then
for k,v in pairs(categoryTable) do
return mw.ustring.format('[[:%s]]%s', parsed.link, category)
category = category .. k
else
return mw.ustring.format('[[:%s|%s]]%s', parsed.link, display, category)
end
end
end


--------------------------------------------------------------------------------
return mHatnote._hatnote(text, mhOptions) .. category
-- Derived convenience functions
--------------------------------------------------------------------------------
 
function p.formatPages(options, pages)
-- Formats an array of pages using formatLink and the given options table,
-- and returns it as an array. Nil values are not allowed.
local ret = {}
for i, page in ipairs(pages) do
ret[i] = p._formatLink{
link = page,
categorizeMissing = options.categorizeMissing,
italicizePage = options.italicizePage,
italicizeSection = options.italicizeSection
}
end
return ret
end
end
 
return p
return p

Revision as of 18:21, 5 September 2022

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

--[[
-- This module produces a "redirect" hatnote. It looks like this:
-- '"X" redirects here. For other uses, see Y.'
-- It implements the {{redirect}} template.
--]]

local mHatnote = require('Module:Hatnote')
local mHatList = require('Module:Hatnote list')
local mArguments --lazily initialize
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local checkTypeMulti = libraryUtil.checkTypeMulti

local p = {}

--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------

local function getTitle(...)
	--Calls mw.title.new and returns either a title object, or nil on error
	local success, titleObj = pcall(mw.title.new, ...)
	return success and titleObj or nil
end

--------------------------------------------------------------------------------
-- Main functions
--------------------------------------------------------------------------------

function p.redirect(frame)
	mArguments = require('Module:Arguments')
	local args = mArguments.getArgs(frame, {parentOnly=true})
	--Get number of redirects
	local numRedirects = tonumber(frame.args[1]) or 1
	-- Create the options table.
	local options = {}
	options.selfref = args.selfref
	return p._redirect(args, numRedirects, options)
end

function p._redirect(args, numRedirects, options, currentTitle, redirectTitle, targetTitle)
	-- Validate the input. Don't bother checking currentTitle, redirectTitle or
	-- targetTitle, as they are only used in testing.
	checkType('_redirect', 1, args, 'table')
	checkType('_redirect', 2, numRedirects, 'number', true)
	numRedirects = numRedirects or 1
	checkType('_redirect', 3, options, 'table', true)
	options = options or {}
	currentTitle = currentTitle or mw.title.getCurrentTitle()
	-- Get the table of redirects
	local redirect = {}
	for i = 1, numRedirects do
		-- Return an error if a redirect parameter is missing.
		if not args[i] then
			return mHatnote.makeWikitextError(
				'missing redirect parameter',
				'Template:Redirect#Errors',
				args.category
			)
		end
		redirect[i] = args[i]
	end
	-- Generate the text.
	local formattedRedirect = {}
	for k,v in pairs(redirect) do
		formattedRedirect[k] = mHatnote.quote(v)
	end
	local text = {
		mHatList.andList(formattedRedirect) .. ' ' .. (#redirect == 1 and 'redirects' or 'redirect') .. ' here.',
		mHatList._forSee(args, #redirect + 1, {title = redirect[1], extratext = args.text})
	}
	text = table.concat(text, ' ')
	-- Functionality for adding categories	
	local categoryTable = {}
	local function addCategory(cat)
		if cat and cat ~= '' then
			-- Add by index to avoid duplicates
			categoryTable[string.format('[[Category:%s]]', cat)] = true
		end
	end
	--Generate tracking categories
	local mhOptions = {}
	local redirTitle
	for k,v in pairs(redirect) do
		-- We don't need a tracking category if the template invocation has been
		-- copied directly from the docs, or if we aren't in main- or category-space.
		if not v:find('^REDIRECT%d*$') and v ~= 'TERM' -- 
			and currentTitle.namespace == 0 or currentTitle.namespace == 14
		then
			redirTitle = redirectTitle or getTitle(v)
			if not redirTitle or not redirTitle.exists then
				addCategory('Missing redirects')
			elseif not redirTitle.isRedirect then
				if string.find(redirTitle:getContent(), '#invoke:RfD') then
					addCategory('Articles with redirect hatnotes impacted by RfD')
				else
					addCategory('Articles with redirect hatnotes needing review')
				end
			else
				local target = targetTitle or redirTitle.redirectTarget
				if target and target ~= currentTitle then
					addCategory('Articles with redirect hatnotes needing review')
				end
			end
		end

		-- Generate the options to pass to [[Module:Hatnote]].
		if currentTitle.namespace == 0 and not mhOptions.selfref
			and redirTitle and redirTitle.namespace ~= 0
		then
			-- We are on a mainspace page, and the hatnote starts with something
			-- like "Wikipedia:Foo redirects here", so automatically label it as
			-- a self-reference.
			mhOptions.selfref = true
		else
			mhOptions.selfref = options.selfref
		end
	end
	--concatenate all the categories
	local category = ''
	for k,v in pairs(categoryTable) do
		category = category .. k
	end

	return mHatnote._hatnote(text, mhOptions) .. category
end
 
return p