Jump to content

Module:DYK queue formatting check

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by 216.58.25.209 (talk) at 01:14, 27 March 2025 (add MOS:' and MOS:CQ to detect https://en.wikipedia.org/wiki/Template:Did_you_know_nominations/Gianni_Benvenuti). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
-- This module started out verifying punctuation rules unique to [[WP:DYKMOS]]
-- Then it expanded to include the remaining non-subjective part of
-- [[WP:DYKMOS]] and [[MOS:CQ]] to keep formatting errors from [[WP:MP/E]]

-- To disable this module for YOUR hook, edit it and replace "* ..." with "*..."

-- This module doesn't show up on the main page or prevent promotion,
-- but if a problem arises:
local disableAll = false
-- This module is not [[WP:EXPENSIVE]], but if performance becomes a problem:
local disableTransclusionBasedChecks = false
-- People don't seem to care about [[MOS:SOB]]. [[Special:Diff/1282220073]]
-- could be edited but [[Special:Diff/1281992817]] might be intentional
local disableSeaOfBlueCheck = true

local p = {}
local plainText = require("Module:Plain text")._main
local isDisambiguation = require('Module:Disambiguation').isDisambiguation
local getTargetFromText = require('Module:Redirect').getTargetFromText
local decode = require('Module:DecodeEncode')._decode

-- Checks that look at the destination page of a wikilink
local function check_link(page)
	if disableTransclusionBasedChecks then
		return
	end
	local title = mw.title.new(page)
	local content = title.content
	if not content then
		return "WP:DYKMOS: The hook must not contain redlinks: " .. page
	end
	if getTargetFromText(content) then
		return "WP:DYKMOS: The hook must not contain redirects: " .. page
	end
	if isDisambiguation(content) then
		return "WP:DYKMOS: The hook must not contain links to " ..
		"disambiguation pages: " .. page
	end
end

-- Per-hook checks that may have occasional exceptions
local function check_hook(wikitextLine, expandedLine, hookNumber)
	local byteCount = -1 -- Counting ends at the question mark
	if wikitextLine:find("''%([^)]+%)''") then
		-- The eleven characters in a ''(pictured)'' tag do not count
		byteCount = byteCount - 11
	end
	local boldLinkFound = false
	for wikilink in wikitextLine:gmatch("'''%[%[([^]]+)%]%]") do
		-- Text in boldlinks after the first do not count toward the limit
		if boldLinkFound then
			wikilink = wikilink:gsub("[^|]+|", "", 1)
			byteCount = byteCount - #wikilink
		end
		boldLinkFound = true
	end
	byteCount = byteCount + #expandedLine
	if byteCount > 200 then
		return "WP:DYK200: The hook cannot exceed 200 prose characters. " ..
		"It is currently " .. count .. " characters"
	end
	if hookNumber ~= 1 then
		if wikitextLine:find("''%([^)]+%)''") then
			return "WP:DYKIMG/WP:DYKMOS: Extra ''(pictured)'' or alternative"
		end
	else
		if not expandedLine:find("%([^)]+%)") then
			return "WP:DYKIMG/WP:DYKMOS: Missing ''(pictured)'' or alternative"
		end
		-- Parentheses that are not the media marker are
		-- allowed if "absolutely unavoidable"
	end
	if not disableSeaOfBlueCheck then
		if (string.find(wikitextLine, "%]%] *%[%[")
			or string.find(wikitextLine, "%]%] *'''+ *'''+ *%[%[")) then
			return "WP:DYKMOS/MOS:SEAOFBLUE: Two non-boldlinks or two " ..
			"boldlinks must be kept separate: " .. expandedLine
		end
	end
	if expandedLine:byte(-1) ~= 46 then -- Not an empty hook in prep area
		if not boldLinkFound then
			return "WP:DYKMOS: Every eligible article in the hook should be " ..
			"linked and wrapped in bold markup"
		end
		if expandedLine:byte(-1) ~= 63 then
			return "WP:DYKMOS: A hook should end in a question mark"
		end
	end
	if wikitextLine:find("%.%.%.that") then
		return "WP:DYKMOS The three dots should be followed by a space"
	end
	if mw.ustring.find(expandedLine, ("[“”]")) then
		return 'MOS:CURLY: Use "straight" quotation marks, not “curly” ones'
	end
	if mw.ustring.find(expandedLine, "[‘’]") then
		return "MOS:APOSTROPHE: Use straight apostrophes ('), " ..
		"not curly apostrophes (‘ or ’)"
	end
	-- Only humans can check if {{lang}} and {{transl}} are needed i.e. if
	-- the "non-English and transliterated text" is in "common English usage"
end

-- General checks that should be uncontroversial for the entire page
local function general_checks(content)
	if content:find("[^[]%[//") or content:find("https?://") then
		-- Assuming nobody inserts a [[mw:Help:Links|mailto]] link
		return "WP:DYKMOS: The hook must not contain external links"
	end
	if content:find("|''[^]]+''%]") then
		return "WP:DYKMOS: Markup should go on the outside of the link if " ..
		"possible"
	end
	if content:find("%(''[^)]+''%)") then
		return "WP:DYKMOS: Note that the italics sit outside the parentheses"
	end
	if content:find("%(disambiguation%)") then
		return "WP:DYKMOS: The hook must not contain links to " ..
		"disambiguation pages"
	end
	if (content:find("[^']''%?")
		or content:find("''''%?")
		or content:find("[ ;?]%?")) then
		return "WP:DYKMOS: There should not be a space before the question " ..
		"mark, but if the text directly preceding it is italicized, " ..
		"the {{-?}} tag can offset it."
	end
	if content:find("''s ") then
		return "WP:DYKMOS: Keep the bold / italic (or bold italic) text and " ..
		"the apostrophe distinct using {{`s}}/{{'s}} respectively"
	end
	if (content:find("''''{{`") -- Use {{'}} with bold italic
		or content:find("[^']''{{`") -- Use {{'}} with italic
		or content:find("[^']'''{{'")) then -- Use {{`}} with bold
		-- Adapted from [[Template:Quotation mark templates]]
		return "WP:DYKMOS: {{`}} (or {{`s}}) is for adjacent bold markup; " ..
		"{{'}} (or {{'s}}) is for adjacent italic (or bold italic)"
	end
end

-- Checks to use for queues and complete prep areas
local function check_queue(content)
	if content:find("example-serious%.jpg") then
		return "Image is still \"example-serious.jpg\""
	end
	if content:find("Caption goes here") then
		return "Caption is still \"Caption goes here\""
	end
	for article in content:gmatch("\n%* *%{%{DYK[^\n|]+|([^\n|]+)|") do
		if article == "Example" then
			return "WP:DYKPBI: DYKmake or DYKnom article is still \"Example\""
		end
	end
end

-- Run all checks
-- Useful for the debug console:
-- =p._check("\n* ... that '''''[[Main Page]]''''' test ''(pictured)'' test?\n")
function p._check(content)
	local generalProblem = general_checks(content)
	if generalProblem then
		return generalProblem
	end

	local frame = mw.getCurrentFrame()
	local hookCount = 1
	local foundEmptyHook = false
	-- Counting starts from after the space following the three dots
	-- A missing space in "* ..." = disable this module for that line
	for wikitextLine in content:gmatch("\n%* %.%.%. ([^\n]*)") do
		local expandedLine = plainText(frame:preprocess(wikitextLine), false)
		expandedLine = decode(expandedLine)

		local hookProblem = check_hook(wikitextLine, expandedLine, hookCount)
		if hookProblem then
			return hookProblem .. ": " .. expandedLine
		end
		if expandedLine:byte(-1) == 46 then -- Empty hook in prep area
			foundEmptyHook = true
		end

		for page in wikitextLine:gmatch("%[%[([^]|]+)|?[^]]*%]%]") do
			local linkProblem = check_link(page)
			if linkProblem then
				return linkProblem
			end
		end

		hookCount = hookCount + 1
	end

	if not foundEmptyHook then
		local queueProblem = check_queue(content)
		if queueProblem then
			return queueProblem
		end
	end
end

function p.main(frame)
	if disableAll then
		return
	end

	local message = p._check(mw.title.getCurrentTitle().content)
	if message then
		return require("Module:Error").error{message}
	end
end

return p