Module:Labelled list hatnote: Difference between revisions
(Created page with "-------------------------------------------------------------------------------- -- Labelled list -- -- -- -- This module does the core work of creating a hatnote composed of a list -- -- prefixed by a colon-terminated label, i.e. "LABEL: [andList of pages]", -- -- for {{see also}} and similar templates....") |
m (1 revision imported) |
||
(One intermediate revision by one other user not shown) | |||
Line 10: | Line 10: | ||
local mHatlist = require('Module:Hatnote list') | local mHatlist = require('Module:Hatnote list') | ||
local mArguments --initialize lazily | local mArguments --initialize lazily | ||
local yesno --initialize lazily | |||
local p = {} | local p = {} | ||
Line 18: | Line 19: | ||
prefixes = {'label', 'label ', 'l'}, | prefixes = {'label', 'label ', 'l'}, | ||
template = 'Module:Labelled list hatnote' | template = 'Module:Labelled list hatnote' | ||
} | |||
-- Localizable message strings | |||
local msg = { | |||
errorSuffix = '#Errors', | |||
noInputWarning = 'no page names specified', | |||
noOutputWarning = | |||
"'''[[%s]] — no output: none of the target pages exist.'''" | |||
} | } | ||
Line 26: | Line 35: | ||
-- They each have numbers auto-appended, e.g. 'label1', 'label 1', & 'l1' | -- They each have numbers auto-appended, e.g. 'label1', 'label 1', & 'l1' | ||
prefixes = prefixes or defaults.prefixes | prefixes = prefixes or defaults.prefixes | ||
local | local indices = {} | ||
local sparsePages = {} | |||
for k, v in pairs(args) do | for k, v in pairs(args) do | ||
if type(k) == 'number' then | if type(k) == 'number' then | ||
indices[#indices + 1] = k | |||
local display | local display | ||
for i = 1, #prefixes do | for i = 1, #prefixes do | ||
Line 34: | Line 45: | ||
if display then break end | if display then break end | ||
end | end | ||
sparsePages[k] = display and | |||
string.format('%s|%s', string.gsub(v, '|.*$', ''), display) or v | string.format('%s|%s', string.gsub(v, '|.*$', ''), display) or v | ||
end | end | ||
end | end | ||
table.sort(indices) | |||
local pages = {} | |||
for k, v in ipairs(indices) do pages[#pages + 1] = sparsePages[v] end | |||
return pages | return pages | ||
end | |||
--Helper function to get a page target from a processed page string | |||
--e.g. "Page|Label" → "Page" or "Target" → "Target" | |||
local function getTarget(pagename) | |||
local pipe = string.find(pagename, '|') | |||
return string.sub(pagename, 0, pipe and pipe - 1 or nil) | |||
end | end | ||
Line 49: | Line 69: | ||
function p.labelledList (frame) | function p.labelledList (frame) | ||
mArguments = require('Module:Arguments') | mArguments = require('Module:Arguments') | ||
yesno = require('Module:Yesno') | |||
local labels = {frame.args[1] or defaults.label} | local labels = {frame.args[1] or defaults.label} | ||
labels[2] = frame.args[2] or labels[1] | labels[2] = frame.args[2] or labels[1] | ||
Line 57: | Line 78: | ||
local pages = p.preprocessDisplays(args) | local pages = p.preprocessDisplays(args) | ||
local options = { | local options = { | ||
category = yesno(args.category), | |||
extraclasses = frame.args.extraclasses, | extraclasses = frame.args.extraclasses, | ||
ifexists = yesno(frame.args.ifexists), | |||
selfref = frame.args.selfref or args.selfref, | namespace = frame.args.namespace or args.namespace, | ||
selfref = yesno(frame.args.selfref or args.selfref), | |||
template = template | template = template | ||
} | } | ||
Line 66: | Line 89: | ||
function p._labelledList (pages, labels, options) | function p._labelledList (pages, labels, options) | ||
if options.ifexists then | |||
for k = #pages, 1, -1 do --iterate backwards to allow smooth removals | |||
local v = pages[k] | |||
local title = mw.title.new(getTarget(v), namespace) | |||
if (v == '') or title == nil or not title.exists then | |||
table.remove(pages, k) | |||
end | |||
end | |||
end | |||
labels = labels or {} | labels = labels or {} | ||
label = (#pages == 1 and labels[1] or labels[2]) or defaults.label | label = (#pages == 1 and labels[1] or labels[2]) or defaults.label | ||
for k, v in pairs(pages) do | for k, v in pairs(pages) do | ||
Line 83: | Line 108: | ||
(labels[4] or labels[2] or defaults.label) | (labels[4] or labels[2] or defaults.label) | ||
) or defaults.label | ) or defaults.label | ||
end | |||
end | |||
if #pages == 0 then | |||
if options.ifexists then | |||
mw.addWarning( | |||
string.format( | |||
msg.noOutputWarning, options.template or defaults.template | |||
) | |||
) | |||
return '' | |||
else | |||
return mHatnote.makeWikitextError( | |||
msg.noInputWarning, | |||
(options.template or defaults.template) .. msg.errorSuffix, | |||
options.category | |||
) | |||
end | end | ||
end | end |
Latest revision as of 14:05, 11 June 2022
This module is subject to page protection. It is a highly visible module in use by a very large number of pages, or is substituted very frequently. Because vandalism or mistakes would affect many pages, and even trivial editing might cause substantial load on the servers, it is protected from editing. |
This Lua module is used in MediaWiki:Wantedpages-summary, and on approximately 506,000 pages, or roughly 24199% of all pages. Changes to it can cause immediate changes to the Stiles.casa Wiki user interface. To avoid major disruption and server load, any changes should be tested in the module's /sandbox or /testcases subpages, or in your own Module:Labelled list hatnote. The tested changes can be added to this page in a single edit. Please discuss changes on the talk page before implementing them. |
This module depends on the following other modules: |
Usage
labelledList
Invoking the labelledList()
function is enough to implement most such templates:
{{#invoke:Labelled list hatnote|labelledList|Universal label}}
or
{{#invoke:Labelled list hatnote|labelledList|Singular label|Plural label}}
For example, providing "See also" instead of "Universal label" duplicates the functionality of {{see also}}, while providing "Main article" and "Main articles" instead of "Singular label" and "Plural label" duplicates the (article namespace) functionality of {{main}}.
If third and fourth labels are provided, they'll be used in the case where any of the target pages are outside the article namespace, so e.g. {{main}} can be implemented thus:
{{#invoke:Labelled list hatnote|labelledList|Main article|Main articles|Main page|Main pages}}
preprocessDisplays
The preprocessDisplays()
function takes a raw list of arguments and combines in any display arguments. For example, {{see also|1|l1=One}}
initially has the arguments table {'1', ['l1'] = 'One'}
; this table would combine those into the table {'1|One'}
. It overrides manual piping (e.g. {{see also|1{{!}}2|l1=One}}
→ {'1|One'}
) and compresses sparse arrays if a parameter is skipped or left empty.
local mLabelledList = require('Module:Labelled list hatnote')
local pages = mLabelledList.preprocessDisplays(args)
_labelledList
For modules that need to modify the functionality slightly while still using it, _labelledList()
provides some flexibility. It takes three parameters:
- A pages list, preferably preprocessed and compressed by
preprocessDisplays
- A labels table, where the first item is the singular or universal label, and the second either a plural label or a copy of the first.
- An options table, preferably containing:
- a
template
string with the full title of the template. Defaults to the title of this module. - a
category
string (or nil) as taken bymakeWikitextError
from Module:Hatnote, to optionally disable error categories - a
selfref
string (or nil) as taken by_hatnote
to enable the selfref option
- a
local mLabelledList = require('Module:Labelled list hatnote')
return mLabelledList._labelledList(pages, labels, options)
Errors
This module causes templates based on it to produce an error message if no page names are provided as template parameters. Normally, these should lead back to "Errors" sections in the documentation of those templates. However, if those templates use a module with _labelledList()
and don't provide a template
item in their options table, that error defaults to leading back here. The error can be solved by providing at least one valid page-name parameter to the template in question; the problem in the template can be fixed by providing some value to the template
item of the _labelledList()
options
table.
--------------------------------------------------------------------------------
-- Labelled list --
-- --
-- This module does the core work of creating a hatnote composed of a list --
-- prefixed by a colon-terminated label, i.e. "LABEL: [andList of pages]", --
-- for {{see also}} and similar templates. --
--------------------------------------------------------------------------------
local mHatnote = require('Module:Hatnote')
local mHatlist = require('Module:Hatnote list')
local mArguments --initialize lazily
local yesno --initialize lazily
local p = {}
-- Defaults global to this module
local defaults = {
label = 'See also', --Final fallback for label argument
labelForm = '%s: %s',
prefixes = {'label', 'label ', 'l'},
template = 'Module:Labelled list hatnote'
}
-- Localizable message strings
local msg = {
errorSuffix = '#Errors',
noInputWarning = 'no page names specified',
noOutputWarning =
"'''[[%s]] — no output: none of the target pages exist.'''"
}
-- Helper function that pre-combines display parameters into page arguments.
-- Also compresses sparse arrays, as a desirable side-effect.
function p.preprocessDisplays (args, prefixes)
-- Prefixes specify which parameters, in order, to check for display options
-- They each have numbers auto-appended, e.g. 'label1', 'label 1', & 'l1'
prefixes = prefixes or defaults.prefixes
local indices = {}
local sparsePages = {}
for k, v in pairs(args) do
if type(k) == 'number' then
indices[#indices + 1] = k
local display
for i = 1, #prefixes do
display = args[prefixes[i] .. k]
if display then break end
end
sparsePages[k] = display and
string.format('%s|%s', string.gsub(v, '|.*$', ''), display) or v
end
end
table.sort(indices)
local pages = {}
for k, v in ipairs(indices) do pages[#pages + 1] = sparsePages[v] end
return pages
end
--Helper function to get a page target from a processed page string
--e.g. "Page|Label" → "Page" or "Target" → "Target"
local function getTarget(pagename)
local pipe = string.find(pagename, '|')
return string.sub(pagename, 0, pipe and pipe - 1 or nil)
end
-- Produces a labelled pages-list hatnote.
-- The main frame (template definition) takes 1 or 2 arguments, for a singular
-- and (optionally) plural label respectively:
-- * {{#invoke:Labelled list hatnote|labelledList|Singular label|Plural label}}
-- The resulting template takes pagename & label parameters normally.
function p.labelledList (frame)
mArguments = require('Module:Arguments')
yesno = require('Module:Yesno')
local labels = {frame.args[1] or defaults.label}
labels[2] = frame.args[2] or labels[1]
labels[3] = frame.args[3] --no defaulting
labels[4] = frame.args[4] --no defaulting
local template = frame:getParent():getTitle()
local args = mArguments.getArgs(frame, {parentOnly = true})
local pages = p.preprocessDisplays(args)
local options = {
category = yesno(args.category),
extraclasses = frame.args.extraclasses,
ifexists = yesno(frame.args.ifexists),
namespace = frame.args.namespace or args.namespace,
selfref = yesno(frame.args.selfref or args.selfref),
template = template
}
return p._labelledList(pages, labels, options)
end
function p._labelledList (pages, labels, options)
if options.ifexists then
for k = #pages, 1, -1 do --iterate backwards to allow smooth removals
local v = pages[k]
local title = mw.title.new(getTarget(v), namespace)
if (v == '') or title == nil or not title.exists then
table.remove(pages, k)
end
end
end
labels = labels or {}
label = (#pages == 1 and labels[1] or labels[2]) or defaults.label
for k, v in pairs(pages) do
if mHatnote.findNamespaceId(v) ~= 0 then
label =
(
#pages == 1 and
(labels[3] or labels[1] or defaults.label) or
(labels[4] or labels[2] or defaults.label)
) or defaults.label
end
end
if #pages == 0 then
if options.ifexists then
mw.addWarning(
string.format(
msg.noOutputWarning, options.template or defaults.template
)
)
return ''
else
return mHatnote.makeWikitextError(
msg.noInputWarning,
(options.template or defaults.template) .. msg.errorSuffix,
options.category
)
end
end
local text = string.format(
options.labelForm or defaults.labelForm,
label,
mHatlist.andList(pages, true)
)
local hnOptions = {
extraclasses = options.extraclasses,
selfref = options.selfref
}
return mHatnote._hatnote(text, hnOptions)
end
return p