48,355
edits
No edit summary |
No edit summary |
||
| Line 2: | Line 2: | ||
local mHatnote = require('Module:Hatnote') | local mHatnote = require('Module:Hatnote') | ||
local mFormatLink = require('Module:Format link') | |||
local yesno = require('Module:Yesno') | local yesno = require('Module:Yesno') | ||
local mTableTools -- lazily initialise | local mTableTools -- lazily initialise | ||
| Line 7: | Line 8: | ||
local p = {} | 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) | function p.catMain(frame) | ||
mTableTools = require('Module:TableTools') | mTableTools = require('Module:TableTools') | ||
mArguments = require('Module:Arguments') | mArguments = require('Module:Arguments') | ||
local args = mArguments.getArgs(frame, {wrappers = 'Template: | |||
-- Grab args | |||
local args = mArguments.getArgs(frame, {wrappers = 'Template:Category main article'}) | |||
local pages = mTableTools.compressSparseArray(args) | local pages = mTableTools.compressSparseArray(args) | ||
if #pages == 0 and args[1] then | |||
pages = { args[1] } | |||
end | |||
local options = { | local options = { | ||
article = args.article, | article = args.article, | ||
selfref = args.selfref | 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 | end | ||
function p._catMain(options, ...) | function p._catMain(options, thisTitle, ...) | ||
options = options or {} | 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) | ||
local | |||
-- Red link detection | |||
local rawLinks = mFormatLink.formatPages({ | |||
links[ | 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 | 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 | for i, link in ipairs(links) do | ||
links[i] = string.format("'''%s'''", link) | links[i] = string.format("'''%s'''", link) | ||
end | end | ||
-- | -- Determine pagetype | ||
local pagetype | local pagetype | ||
if yesno(options.article) ~= false then | if options.article ~= nil then | ||
pagetype = | 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 | else | ||
pagetype = | pagetype = "article" | ||
end | end | ||
-- Work out whether we need to be singular or plural | -- Work out whether we need to be singular or plural | ||
local stringToFormat | local stringToFormat | ||
if #links > 1 then | if #links > 1 then | ||
stringToFormat = 'The main %ss for this [[ | stringToFormat = 'The main %ss for this [[Help:Categories|category]] are %s.' | ||
else | else | ||
stringToFormat = 'The main %s for this [[ | stringToFormat = 'The main %s for this [[Help:Categories|category]] is %s.' | ||
end | end | ||
-- | -- Build hatnote text | ||
local text = string.format( | local text = string.format( | ||
stringToFormat, | stringToFormat, | ||
| Line 55: | Line 170: | ||
mw.text.listToText(links) | mw.text.listToText(links) | ||
) | ) | ||
-- Pass through Module:Hatnote | |||
local hnOptions = { selfref = options.selfref } | |||
text = mHatnote._hatnote(text, hnOptions) | |||
return text, firstOutputLink, usedAutoFill | |||
end | end | ||
return p | return p | ||