Module:Cat main: Difference between revisions

From Linguifex
Jump to navigation Jump to search
(Created page with "-- This module implements {{cat main}}. local mHatnote = require('Module:Hatnote') local yesno = require('Module:Yesno') local mTableTools -- lazily initialise local mArgumen...")
 
No edit summary
 
(One intermediate revision by the same user not shown)
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:Cat main'})
 
-- 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,
}
}
return p._catMain(options, unpack(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 '')


-- Get the links table.
local isTemplate = isTemplateOrModule(fullTitle)
local links = mHatnote.formatPages(...)
 
if not links[1] then
-- Red link detection
local page = mw.title.getCurrentTitle().text
local rawLinks = mFormatLink.formatPages({
links[1] = mHatnote._formatLink{link = page}
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


-- Get the pagetype.
-- Determine pagetype
local pagetype
local pagetype
if yesno(options.article) ~= false then
if options.article ~= nil then
pagetype = 'article'
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 = 'page'
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
Line 49: Line 164:
end
end


-- Get the text.
-- 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 it through to Module:Hatnote.
local hnOptions = {}
hnOptions.selfref = options.selfref
hnOptions.extraclasses = 'relarticle mainarticle'


return mHatnote._hatnote(text, hnOptions)
-- Pass through Module:Hatnote
local hnOptions = { selfref = options.selfref }
text = mHatnote._hatnote(text, hnOptions)
 
return text, firstOutputLink, usedAutoFill
end
end


return p
return p

Latest revision as of 00:26, 29 November 2025



-- 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