-- This module implements {{cat main}}.
local mHatnote = require('Module:Hatnote')
local mFormatLink = require('Module:Format link')
local yesno = require('Module:Yesno')
local mTableTools -- lazily initialise
local mArguments -- lazily initialise
local p = {}
-- Helper: true if the page is in Template: or Module: namespace
local function isTemplateOrModule(title)
local t = (type(title) == 'string' and title) or (title and title.prefixedText) or ''
if t == '' then
return false
end
local ok, tt = pcall(mw.title.new, t)
if not ok or not tt then
return false
end
local ns = tt.namespace
return ns == 10 or ns == 828
end
function p.catMain(frame)
mTableTools = require('Module:TableTools')
mArguments = require('Module:Arguments')
-- Grab args
local args = mArguments.getArgs(frame, {wrappers = 'Template:Category main article'})
local pages = mTableTools.compressSparseArray(args)
if #pages == 0 and args[1] then
pages = { args[1] }
end
local options = {
article = args.article,
selfref = args.selfref,
_rawPages = pages,
}
-- Determine the outer page (the page using the template)
local thisTitle = frame and frame.getParent and frame:getParent() and frame:getParent().title or mw.title.getCurrentTitle()
local titleText = thisTitle and thisTitle.prefixedText or ''
local ns = thisTitle and thisTitle.namespace or nil
-- Skip tracking categories on template/module pages
local isTemplate = isTemplateOrModule(titleText)
-- Remember original arg count
local origCount = #pages
-- Generate hatnote text
local text, firstLink, usedAutoFill = p._catMain(options, thisTitle, unpack(pages))
if isTemplate then
-- On templates/modules, just return the hatnote (no tracking categories)
return text
end
-- Add tracking categories
local cats = {}
-- Wrong namespace detection (Article, Draft)
if ns == 0 or ns == 118 then
table.insert(cats, '[[Category:Articles using category hatnotes]]')
end
-- Title mismatch detection
if firstLink and (origCount == 1 or (origCount == 0 and usedAutoFill)) then
local function normalizeTitle(s)
return (s or ''):gsub('^%s+', ''):gsub('%s+$', ''):gsub('^[^:]*:', ''):gsub('%s+', ' ')
end
local compareStr
if usedAutoFill then
compareStr = normalizeTitle(firstLink)
else
local raw = (options._rawPages and options._rawPages[1]) or firstLink
compareStr = normalizeTitle(raw:gsub("|.*", ""))
end
local catName = normalizeTitle(thisTitle and thisTitle.text or '')
if compareStr ~= catName then
table.insert(cats, '[[Category:Category main article does not match category title]]')
end
end
if #cats > 0 then
text = text .. '\n' .. table.concat(cats, '\n')
end
return text
end
function p._catMain(options, thisTitle, ...)
options = options or {}
local pages = {...}
thisTitle = thisTitle or mw.title.getCurrentTitle()
local fullTitle = thisTitle and thisTitle.prefixedText or ''
local thisText = thisTitle and thisTitle.text or (pages[1] or '')
local isTemplate = isTemplateOrModule(fullTitle)
-- Red link detection
local rawLinks = mFormatLink.formatPages({
categorizeMissing = not isTemplate and 'Categories with hatnote templates targeting a non-existent page' or nil
}, pages)
-- Convert to plain strings
local links = {}
for i, link in ipairs(rawLinks or {}) do
links[i] = tostring(link)
end
-- Auto-fill if empty
local firstOutputLink = nil
local usedAutoFill = false
if not links[1] or links[1] == '' then
local title = mw.title.new(thisText)
if title and title.isRedirect then
title = title.redirectTarget
end
firstOutputLink = title and title.text or thisText
usedAutoFill = true
links[1] = tostring(mFormatLink._formatLink{
link = firstOutputLink,
categorizeMissing = not isTemplate and 'Categories with hatnote templates targeting a non-existent page' or nil
})
pages = { firstOutputLink }
else
local visible = links[1]
visible = visible:gsub("^'''", ""):gsub("'''$", "")
visible = visible:gsub("%[%[", ""):gsub("%]%]", "")
visible = visible:gsub("|.*$", "")
visible = visible:gsub("#.*$", "")
firstOutputLink = visible
usedAutoFill = false
end
-- Bold links
for i, link in ipairs(links) do
links[i] = string.format("'''%s'''", link)
end
-- Determine pagetype
local pagetype
if options.article ~= nil then
pagetype = yesno(options.article) ~= false and 'article' or 'page'
elseif pages and pages[1] then
local page = pages[1]:gsub("|.*","")
local tt = mw.title.new(page)
pagetype = tt and tt.namespace == 0 and "article" or "page"
else
pagetype = "article"
end
-- Work out whether we need to be singular or plural
local stringToFormat
if #links > 1 then
stringToFormat = 'The main %ss for this [[Help:Categories|category]] are %s.'
else
stringToFormat = 'The main %s for this [[Help:Categories|category]] is %s.'
end
-- Build hatnote text
local text = string.format(
stringToFormat,
pagetype,
mw.text.listToText(links)
)
-- Pass through Module:Hatnote
local hnOptions = { selfref = options.selfref }
text = mHatnote._hatnote(text, hnOptions)
return text, firstOutputLink, usedAutoFill
end
return p