Module:Hatnote: Difference between revisions

From TEPwiki, Urth's Encyclopedia
Jump to navigation Jump to search
Content added Content deleted
(tidy up the code now that we are adding colons to all the links)
m (10 revisions imported from wikipedia:Module:Hatnote)
 
(27 intermediate revisions by 13 users not shown)
Line 9: Line 9:
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 yesno -- lazily initialise [[Module:Yesno]]
local formatLink -- lazily initialise [[Module:Format link]] ._formatLink


local p = {}
local p = {}
Line 30: Line 32:
end
end


function p.formatPages(...)
function p.defaultClasses(inline)
-- Provides the default hatnote classes as a space-separated string; useful
-- Formats a list of pages using formatLink and returns it as an array. Nil
-- for hatnote-manipulation modules like [[Module:Hatnote group]].
-- values are not allowed.
return
local pages = {...}
(inline == 1 and 'hatnote-inline' or 'hatnote') .. ' ' ..
local ret = {}
'navigation-not-searchable'
for i, page in ipairs(pages) do
ret[i] = p._formatLink(page)
end
return ret
end
end


function p.formatPageTables(...)
function p.disambiguate(page, disambiguator)
-- Formats a page title with a disambiguation parenthetical,
-- Takes a list of page/display tables and returns it as a list of
-- i.e. "Example" → "Example (disambiguation)".
-- formatted links. Nil values are not allowed.
checkType('disambiguate', 1, page, 'string')
local pages = {...}
checkType('disambiguate', 2, disambiguator, 'string', true)
local links = {}
disambiguator = disambiguator or 'disambiguation'
for i, t in ipairs(pages) do
return mw.ustring.format('%s (%s)', page, disambiguator)
checkType('formatPageTables', i, t, 'table')
end
local link = t[1]

local display = t[2]
links[i] = p._formatLink(link, display)
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
end
return links
return 0
end
end


function p.makeWikitextError(msg, helpLink, addTrackingCategory)
function p.makeWikitextError(msg, helpLink, addTrackingCategory, title)
-- Formats an error message to be returned to wikitext. If
-- Formats an error message to be returned to wikitext. If
-- addTrackingCategory is not false after being returned from
-- addTrackingCategory is not false after being returned from
Line 63: Line 77:
checkType('makeWikitextError', 2, helpLink, 'string', true)
checkType('makeWikitextError', 2, helpLink, 'string', true)
yesno = require('Module:Yesno')
yesno = require('Module:Yesno')
local title = mw.title.getCurrentTitle()
title = title or mw.title.getCurrentTitle()
-- Make the help link text.
-- Make the help link text.
local helpText
local helpText
Line 73: Line 87:
-- Make the category text.
-- Make the category text.
local category
local category
if not title.isTalkPage and yesno(addTrackingCategory) ~= false then
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 = 'Hatnote templates with errors'
category = string.format(
category = mw.ustring.format(
'[[%s:%s]]',
'[[%s:%s]]',
mw.site.namespaces[14].name,
mw.site.namespaces[14].name,
Line 83: Line 100:
category = ''
category = ''
end
end
return string.format(
return mw.ustring.format(
'<strong class="error">Error: %s%s.</strong>%s',
'<strong class="error">Error: %s%s.</strong>%s',
msg,
msg,
Line 91: Line 108:
end
end


local curNs = mw.title.getCurrentTitle().namespace
--------------------------------------------------------------------------------
p.missingTargetCat =
-- Format link
--Default missing target category, exported for use in related modules
--
((curNs == 0) or (curNs == 14)) and
-- Makes a wikilink from the given link and display values. Links are escaped
'Articles with hatnote templates targeting a nonexistent page' or nil
-- 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 hatnote link}} template.
--------------------------------------------------------------------------------


function p.formatLink(frame)
function p.quote(title)
--Wraps titles in quotation marks. If the title starts/ends with a quotation
local args = getArgs(frame)
--mark, kerns that side as with {{-'}}
local link = args[1]
local display = args[2]
local quotationMarks = {
["'"]=true, ['"']=true, ['“']=true, ["‘"]=true, ['”']=true, ["’"]=true
if not link then
}
return p.makeWikitextError(
local quoteLeft, quoteRight = -- Test if start/end are quotation marks
'no link specified',
quotationMarks[string.sub(title, 1, 1)],
'Template:Format hatnote link#Errors',
quotationMarks[string.sub(title, -1, -1)]
args.category
if quoteLeft or quoteRight then
)
title = mw.html.create("span"):wikitext(title)
end
return p._formatLink(link, display)
end

function p._formatLink(link, display)
checkType('_formatLink', 1, link, 'string')
checkType('_formatLink', 2, display, 'string', true)

-- Remove the initial colon for links where it was specified manually.
link = removeInitialColon(link)

-- Find whether a faux display value has been added with the {{!}} magic
-- word.
if not display then
local prePipe, postPipe = link:match('^(.-)|(.*)$')
link = prePipe or link
display = postPipe
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]]', link, display)
else
return string.format('[[:%s]]', link)
end
end
if quoteLeft then title:css("padding-left", "0.15em") end
if quoteRight then title:css("padding-right", "0.15em") end
return '"' .. tostring(title) .. '"'
end
end


Line 154: Line 140:
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(
return p.makeWikitextError(
Line 162: Line 147:
)
)
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 170: Line 156:
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 = {'hatnote'}
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(p.defaultClasses(inline))
return string.format(
:addClass(extraclasses)
'<div class="%s">%s</div>',
:addClass(options.selfref and 'selfref' or nil)
table.concat(classes, ' '),
s
:wikitext(s)

)
return mw.getCurrentFrame():extensionTag{
name = 'templatestyles', args = { src = 'Module:Hatnote/styles.css' }
} .. tostring(hatnote)
end
end



Latest revision as of 05:35, 15 October 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 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.defaultClasses(inline)
	-- Provides the default hatnote classes as a space-separated string; useful
	-- for hatnote-manipulation modules like [[Module:Hatnote group]].
	return
		(inline == 1 and 'hatnote-inline' or 'hatnote') .. ' ' ..
		'navigation-not-searchable'
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

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

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

function p.quote(title)
	--Wraps titles in quotation marks. If the title starts/ends with a quotation
	--mark, kerns that side as with {{-'}}
	local quotationMarks = {
		["'"]=true, ['"']=true, ['“']=true, ["‘"]=true, ['”']=true, ["’"]=true
	}
	local quoteLeft, quoteRight = -- Test if start/end are quotation marks
		quotationMarks[string.sub(title,  1,  1)],
		quotationMarks[string.sub(title, -1, -1)]
	if quoteLeft or quoteRight then
		title = mw.html.create("span"):wikitext(title)
	end
	if quoteLeft  then title:css("padding-left",  "0.15em") end
	if quoteRight then title:css("padding-right", "0.15em") end
	return '"' .. tostring(title) .. '"'
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(p.defaultClasses(inline))
		:addClass(extraclasses)
		:addClass(options.selfref and 'selfref' or nil)
		:wikitext(s)

	return mw.getCurrentFrame():extensionTag{
		name = 'templatestyles', args = { src = 'Module:Hatnote/styles.css' }
	} .. tostring(hatnote)
end

return p