Jump to content

Module:Category main article/sandbox

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Mclay1 (talk | contribs) at 15:40, 5 November 2025 (This should be it.). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
-- This module implements {{Category main article}}.

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 title is Template:Category main article or subpage
local function isTemplateOrSubpage(title)
	local t = type(title) == 'string' and title or (title and title.prefixedText or '')
	return t == 'Template:Category main article'
		or t:match('^Template:Category main article/.+')
end

function p.catMain(frame)
	mTableTools = require('Module:TableTools')
	mArguments = require('Module:Arguments')

	local args = mArguments.getArgs(frame)
	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,
	}

	local thisTitle = mw.title.getCurrentTitle()
	local titleText = thisTitle and thisTitle.prefixedText or ''
	local ns = thisTitle and thisTitle.namespace or nil

	-- Skip tracking categories on template itself
	local isTemplate = isTemplateOrSubpage(titleText)

	-- Generate hatnote text and get first output link and whether autofill was used
	local text, firstLink, usedAutoFill = p._catMain(options, unpack(pages))

	if isTemplate then
		-- On the template itself, 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 #pages == 1 then
		local compareStr = firstLink:gsub('^[^:]*:', '')  -- strip namespace if any
		local catName = (thisTitle and thisTitle.text or ''):gsub('^[^:]*:', '')
		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, ...)
	options = options or {}
	local pages = {...}
	local thisTitle = mw.title.getCurrentTitle()
	local fullTitle = thisTitle and thisTitle.prefixedText or ''
	local thisText = thisTitle and thisTitle.text or (pages[1] or '')

	local isTemplate = isTemplateOrSubpage(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
		-- Resolve a title from the current page text, and follow redirects
		local title = mw.title.new(thisText)

		-- If the title object is non-nil and is a redirect, take the redirect target
		if title and title.isRedirect then
			title = title.redirectTarget
		end

		-- At this point `title` is the mw.title object we want to display
		-- Record the resolved raw title (this is the canonical page name used for comparison)
		firstOutputLink = title and title.text or thisText
		usedAutoFill = true

		-- Build the visible link using _formatLink and ensure redlink categorization is applied
		links[1] = tostring(mFormatLink._formatLink{
			link = firstOutputLink,
			categorizeMissing = not isTemplate and 'Categories with hatnote templates targeting a non-existent page' or nil
		})

		-- treat pages array as resolved for downstream logic
		pages = { firstOutputLink }
	else
		-- Not auto-filled: derive a cleaned-up textual form of the first visible link.
		-- links[1] is something like '[[:Page]]' or '[[:Page|Display]]' or 'Page § ...' etc.
		-- We keep the visible semantics but extract a canonical page text for mismatch detection.
		local visible = links[1]

		-- remove simple bold markers if present and section anchors and outer [[ ]] and any display text after pipe
		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("|.*","")
		pagetype = mw.title.new(page).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 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