Module:Hatnote: Difference between revisions

From the Croc Wiki, the Croc encyclopedia
Jump to navigationJump to search
Content added Content deleted
(merge rellink into hatnote, use an options table to pass options to the hatnote function, and add a tracking category for errors)
m (57 revisions imported from wikipedia:Module:Hatnote)
 
(38 intermediate revisions by 10 users not shown)
Line 3: Line 3:
-- --
-- --
-- This module produces hatnote links and links to related articles. It --
-- This module produces hatnote links and links to related articles. It --
-- implements the {{rellink}} and {{hatnote}} meta-templates, and includes --
-- implements the {{hatnote}} and {{format link}} meta-templates and includes --
-- helper functions for other Lua modules to format hatnote links. --
-- helper functions for other Lua hatnote modules. --
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------


local libraryUtil = require('libraryUtil')
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local checkType = libraryUtil.checkType
local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg
local mArguments -- lazily initialise [[Module:Arguments]]
local mArguments -- lazily initialise [[Module:Arguments]]
local yesno -- lazily initialise [[Module:Yesno]]
local formatLink -- lazily initialise [[Module:Format link]] ._formatLink


local p = {}
local p = {}
Line 16: Line 19:
-- Helper functions
-- Helper functions
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

local curNs = mw.title.getCurrentTitle().namespace
p.missingTargetCat =
--Default missing target category, exported for use in related modules
((curNs == 0) or (curNs == 14)) and
'Articles with hatnote templates targeting a nonexistent page' or nil


local function getArgs(frame)
local function getArgs(frame)
Line 29: Line 38:
end
end


function p._findNamespaceId(link, removeColon)
function p.findNamespaceId(link, removeColon)
-- Finds the namespace id (namespace number) of a link or a pagename. This
-- 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
-- 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
-- are trimmed from the start of the link by default. To skip colon
-- trimming, set the removeColon parameter to true.
-- trimming, set the removeColon parameter to false.
checkType('_findNamespaceId', 1, link, 'string')
checkType('findNamespaceId', 1, link, 'string')
checkType('_findNamespaceId', 2, removeColon, 'boolean', true)
checkType('findNamespaceId', 2, removeColon, 'boolean', true)
if removeColon ~= false then
if removeColon ~= false then
link = removeInitialColon(link)
link = removeInitialColon(link)
Line 49: Line 58:
end
end


function p.makeWikitextError(msg, helpLink, addTrackingCategory, title)
function p._formatPages(...)
-- Formats a list of pages using formatLink and returns it as an array. Nil
-- Formats an error message to be returned to wikitext. If
-- addTrackingCategory is not false after being returned from
-- values are not allowed.
-- [[Module:Yesno]], and if we are not on a talk page, a tracking category
local pages = {...}
-- is added.
local ret = {}
checkType('makeWikitextError', 1, msg, 'string')
for i, page in ipairs(pages) do
checkType('makeWikitextError', 2, helpLink, 'string', true)
ret[i] = p._formatLink(page)
yesno = require('Module:Yesno')
title = title or mw.title.getCurrentTitle()
-- Make the help link text.
local helpText
if helpLink then
helpText = ' ([[' .. helpLink .. '|help]])'
else
helpText = ''
end
end
-- Make the category text.
return ret
local category
end
if not title.isTalkPage -- Don't categorise talk pages

and title.namespace ~= 2 -- Don't categorise userspace
function p._formatPageTables(...)
and yesno(addTrackingCategory) ~= false -- Allow opting out
-- Takes a list of page/display tables and returns it as a list of
then
-- formatted links. Nil values are not allowed.
category = 'Hatnote templates with errors'
local pages = {...}
category = mw.ustring.format(
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)
-- Formats an error message to be returned to wikitext.
checkType('_makeWikitextError', 1, msg, 'string')
local errorCategory = 'Hatnote templates with errors'
local errorCategoryLink = errorCategory
and string.format(
'[[%s:%s]]',
'[[%s:%s]]',
mw.site.namespaces[14].name,
mw.site.namespaces[14].name,
category
errorCategory
)
)
else
or ''
category = ''
return string.format(
end
'<strong class="error">Error: %s.</strong>%s',
return mw.ustring.format(
'<strong class="error">Error: %s%s.</strong>%s',
msg,
msg,
helpText,
errorCategoryLink
category
)
)
end
end


function p.disambiguate(page, disambiguator)
--------------------------------------------------------------------------------
-- Formats a page title with a disambiguation parenthetical,
-- Format link
-- i.e. "Example" → "Example (disambiguation)".
--
checkType('disambiguate', 1, page, 'string')
-- Makes a wikilink from the given link and display values. Links are escaped
checkType('disambiguate', 2, disambiguator, 'string', true)
-- with colons if necessary, and links to sections are detected and displayed
disambiguator = disambiguator or 'disambiguation'
-- with " § " as a separator rather than the standard MediaWiki "#".
return mw.ustring.format('%s (%s)', page, disambiguator)
--------------------------------------------------------------------------------

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
end


Line 150: Line 115:
local args = getArgs(frame)
local args = getArgs(frame)
local s = args[1]
local s = args[1]
local options = {}
if not s then
if not s then
return p._makeWikitextError('no text specified')
return p.makeWikitextError(
'no text specified',
'Template:Hatnote#Errors',
args.category
)
end
end
return p._hatnote(s, {
options.extraclasses = args.extraclasses
options.selfref = args.selfref
extraclasses = args.extraclasses,
selfref = args.selfref
return p._hatnote(s, options)
})
end
end


Line 162: Line 131:
checkType('_hatnote', 1, s, 'string')
checkType('_hatnote', 1, s, 'string')
checkType('_hatnote', 2, options, 'table', true)
checkType('_hatnote', 2, options, 'table', true)
options = options or {}
local classes = {'rellink'}
local extraclasses = options.extraclasses
local inline = options.inline
local hatnote = mw.html.create(inline == 1 and 'span' or 'div')
local selfref = options.selfref
if type(extraclasses) == 'string' then
local extraclasses
if type(options.extraclasses) == 'string' then
classes[#classes + 1] = extraclasses
extraclasses = options.extraclasses
end
end

if selfref then
hatnote
classes[#classes + 1] = 'selfref'
:attr('role', 'note')
end
:addClass(inline == 1 and 'hatnote-inline' or 'hatnote')
return string.format(
:addClass('navigation-not-searchable')
'<div class="%s">%s</div>',
:addClass(extraclasses)
table.concat(classes, ' '),
:addClass(options.selfref and 'selfref')
s
:wikitext(s)
)
return mw.getCurrentFrame():extensionTag{
name = 'templatestyles', args = { src = 'Module:Hatnote/styles.css' }
} .. tostring(hatnote)
end
end



Latest revision as of 01:26, January 30, 2022

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 {{hatnote}} and {{format link}} meta-templates and includes --
-- helper functions for other Lua hatnote modules.                            --
--------------------------------------------------------------------------------

local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg
local mArguments -- lazily initialise [[Module:Arguments]]
local yesno -- lazily initialise [[Module:Yesno]]
local formatLink -- lazily initialise [[Module:Format link]] ._formatLink

local p = {}

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

local curNs = mw.title.getCurrentTitle().namespace
p.missingTargetCat =
	--Default missing target category, exported for use in related modules
	((curNs ==  0) or (curNs == 14)) and
	'Articles with hatnote templates targeting a nonexistent page' or nil

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 false.
	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.makeWikitextError(msg, helpLink, addTrackingCategory, title)
	-- Formats an error message to be returned to wikitext. If
	-- addTrackingCategory is not false after being returned from
	-- [[Module:Yesno]], and if we are not on a talk page, a tracking category
	-- is added.
	checkType('makeWikitextError', 1, msg, 'string')
	checkType('makeWikitextError', 2, helpLink, 'string', true)
	yesno = require('Module:Yesno')
	title = title or mw.title.getCurrentTitle()
	-- Make the help link text.
	local helpText
	if helpLink then
		helpText = ' ([[' .. helpLink .. '|help]])'
	else
		helpText = ''
	end
	-- Make the category text.
	local category
	if not title.isTalkPage -- Don't categorise talk pages
		and title.namespace ~= 2 -- Don't categorise userspace
		and yesno(addTrackingCategory) ~= false -- Allow opting out
	then
		category = 'Hatnote templates with errors'
		category = mw.ustring.format(
			'[[%s:%s]]',
			mw.site.namespaces[14].name,
			category
		)
	else
		category = ''
	end
	return mw.ustring.format(
		'<strong class="error">Error: %s%s.</strong>%s',
		msg,
		helpText,
		category
	)
end

function p.disambiguate(page, disambiguator)
	-- Formats a page title with a disambiguation parenthetical,
	-- i.e. "Example" → "Example (disambiguation)".
	checkType('disambiguate', 1, page, 'string')
	checkType('disambiguate', 2, disambiguator, 'string', true)
	disambiguator = disambiguator or 'disambiguation'
	return mw.ustring.format('%s (%s)', page, disambiguator)
end

--------------------------------------------------------------------------------
-- Hatnote
--
-- Produces standard hatnote text. Implements the {{hatnote}} template.
--------------------------------------------------------------------------------

function p.hatnote(frame)
	local args = getArgs(frame)
	local s = args[1]
	if not s then
		return p.makeWikitextError(
			'no text specified',
			'Template:Hatnote#Errors',
			args.category
		)
	end
	return p._hatnote(s, {
		extraclasses = args.extraclasses,
		selfref = args.selfref
	})
end

function p._hatnote(s, options)
	checkType('_hatnote', 1, s, 'string')
	checkType('_hatnote', 2, options, 'table', true)
	options = options or {}
	local inline = options.inline
	local hatnote = mw.html.create(inline == 1 and 'span' or 'div')
	local extraclasses
	if type(options.extraclasses) == 'string' then
		extraclasses = options.extraclasses
	end

	hatnote
		:attr('role', 'note')
		:addClass(inline == 1 and 'hatnote-inline' or 'hatnote')
		:addClass('navigation-not-searchable')
		:addClass(extraclasses)
		:addClass(options.selfref and 'selfref')
		:wikitext(s)
	
	return mw.getCurrentFrame():extensionTag{
		name = 'templatestyles', args = { src = 'Module:Hatnote/styles.css' }
	} .. tostring(hatnote)
end

return p