Module:Infobox television: Difference between revisions
From The Goon Show Depository
m (1 revision imported) |
No edit summary |
||
(9 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
require("strict") | -- require("strict") | ||
--- @module | --- @module | ||
Line 16: | Line 16: | ||
unnecessary_title_parameter = "[[Category:Pages using infobox television with unnecessary name parameter]]", | unnecessary_title_parameter = "[[Category:Pages using infobox television with unnecessary name parameter]]", | ||
unlinked_values = "[[Category:Pages using infobox television with unlinked values|%s]]", | unlinked_values = "[[Category:Pages using infobox television with unlinked values|%s]]", | ||
temp = "[[Category:Temp infobox television tracking category|%s]]", | |||
} | } | ||
Line 183: | Line 184: | ||
--- Infobox parameters checked: | --- Infobox parameters checked: | ||
--- - |image_alt= and |alt= | --- - |image_alt= and |alt= | ||
--- - |image_size= and |image_upright= | |||
--- - |based_on= and |inspired_by= | --- - |based_on= and |inspired_by= | ||
--- - |screenplay= and |teleplay= | --- - |screenplay= and |teleplay= | ||
Line 220: | Line 222: | ||
local parameters = { | local parameters = { | ||
{"image_alt", "alt"}, | {"image_alt", "alt"}, | ||
{"image_size", "image_upright"}, | |||
{"based_on", "inspired_by"}, | {"based_on", "inspired_by"}, | ||
{"screenplay", "teleplay"}, | {"screenplay", "teleplay"}, | ||
Line 390: | Line 393: | ||
end | end | ||
--- Returns a maintenance category if | --- Returns a maintenance category if num_episodes uses: | ||
--- " | --- - "as of" as text | ||
--- - A date template | |||
--- | --- | ||
--- Infobox parameters checked: | --- Infobox parameters checked: | ||
--- - |num_episodes= | |||
--- | |||
--- @param num_episodes string | |||
--- @return string | |||
local function does_num_episodes_have_extraneous_text(num_episodes) | |||
if not num_episodes then | |||
return "" | |||
end | |||
if string.find(string.lower(num_episodes), "as of") | |||
or string.find(num_episodes, "dtstart") | |||
or string.find(num_episodes, "episode%-counter") then | |||
return string.format(maintenance_categories.incorrectly_formatted, "num_episodes") | |||
end | |||
return "" | |||
end | |||
--- Returns a maintenance category if |based_on uses a generic word instead | |||
--- of the title of the original work: | |||
--- "book" | |||
--- "novel" | |||
--- | |||
--- Infobox parameters checked: | |||
--- - |based_on= | |||
--- | |||
--- @param num_episodes string | |||
--- @return string | |||
local function is_based_on_used_correctly(based_on) | |||
if not based_on then | |||
return "" | |||
end | |||
local generic_titles = { | |||
"book", | |||
"novel", | |||
} | |||
-- Remove content enclosed by double single quotes (''text'') | |||
local stripped_text = based_on:gsub("''[^']*''", "") | |||
-- Remove content enclosed by double quotes ("text") | |||
stripped_text = based_on:gsub('"[^"]*"', "") | |||
-- Remove content enclosed by double square brackets ([[text]]) | |||
stripped_text = based_on:gsub("%[%[.-%]%]", "") | |||
-- Convert to lowercase to ensure case-insensitive matching | |||
stripped_text = stripped_text:lower() | |||
for _, word in pairs(generic_titles) do | |||
if string.find(stripped_text, word) then | |||
return string.format(maintenance_categories.incorrectly_formatted, "based_on") | |||
end | |||
end | |||
return "" | |||
end | |||
--- Checks if a string is in the exceptions list. | |||
--- | |||
--- @param str string | |||
--- @return boolean | |||
local function is_in_credit_exceptions(str) | |||
local exceptions = { | |||
"Aulsondro \"Novelist\" Hamilton", | |||
-- Booker can be a last name. | |||
"Booker", | |||
"Jack Trevor Story", | |||
} | |||
for _, exception in ipairs(exceptions) do | |||
if string.find(str, exception) then | |||
return true | |||
end | |||
end | |||
return false | |||
end | |||
--- Returns a maintenance category if a credit information entered is from the following list: | |||
--- "assistant", associate", "co-", "executive", "line producer", "on-line", "prod%.", "supervising" | |||
--- "book", "manuscript", "novel", "script", "screenplay", "story", "teleplay" | |||
--- TODO: "lyric" and "dialogue" should be either supported or removed. | |||
--- These credits have their own unique parameters that should be used instead. | |||
--- | |||
--- Infobox parameters checked: | |||
--- - |director= | |||
--- - |editor= | --- - |editor= | ||
--- - |executive_producer= | --- - |executive_producer= | ||
--- - |producer= | --- - |producer= | ||
--- - |screenplay= | |||
--- - |story= | |||
--- - |teleplay= | |||
--- - |writer= | |||
--- | --- | ||
--- @param args table | --- @param args table | ||
--- @return string | --- @return string | ||
local function is_credit_used_correctly(args) | local function is_credit_used_correctly(args) | ||
local | local credits_list = { | ||
local invalid_credits = {"assistant", "associate", "co%-", "executive", "line producer", "on%-line", "supervising"} | "director", | ||
"editor", | |||
"executive_producer", | |||
"producer", | |||
"screenplay", | |||
"story", | |||
"teleplay", | |||
"writer", | |||
} | |||
local credits = {} | |||
for _, value in pairs(credits_list) do | |||
credits[value] = args[value] | |||
end | |||
local invalid_credits = { | |||
"assistant", | |||
"associate", | |||
"book", | |||
"co%-", | |||
"executive", | |||
"line producer", | |||
"manuscript", | |||
"novel", | |||
"on%-line", | |||
"prod%.", | |||
"supervising", | |||
"script", | |||
"screenplay", | |||
"story", | |||
"teleplay", | |||
"lyric", -- temp | |||
"dialogue", -- temp | |||
} | |||
local delink = require("Module:Delink")._delink | local delink = require("Module:Delink")._delink | ||
for key, credit in pairs(credits) do | for key, credit in pairs(credits) do | ||
for _, invalid_credit in pairs(invalid_credits) do | for _, invalid_credit in pairs(invalid_credits) do | ||
if string.find(string.lower( | local pattern = "%f[%a]" .. invalid_credit | ||
return string.format(maintenance_categories.incorrectly_formatted, key) | credit = delink{credit} | ||
if string.find(string.lower(credit), pattern) and not is_in_credit_exceptions(credit) then | |||
if invalid_credit == "lyric" or invalid_credit == "dialogue" then | |||
return string.format(maintenance_categories.temp, invalid_credit) | |||
else | |||
return string.format(maintenance_categories.incorrectly_formatted, key) | |||
end | |||
end | end | ||
end | end | ||
Line 523: | Line 656: | ||
end | end | ||
--- Returns a maintenance category if the |image= value includes the "File:" or "Image:" prefix. | --- Returns a maintenance category if the |image= value includes the "File:" | ||
--- or "Image:" prefix, or if it is a URL. | |||
--- | --- | ||
--- Infobox parameters checked: | --- Infobox parameters checked: | ||
Line 535: | Line 669: | ||
end | end | ||
local invalid_strings = { | |||
"file:", | |||
"image:", | |||
"http:", | |||
"https:", | |||
} | |||
image = string.lower(image) | |||
for _, invalid in ipairs(invalid_strings) do | |||
if string.find(image, invalid) then | |||
return string.format(maintenance_categories.incorrectly_formatted, "image") | |||
end | |||
end | end | ||
Line 774: | Line 918: | ||
table.insert(categories, is_image_size_using_px(args.image_size)) | table.insert(categories, is_image_size_using_px(args.image_size)) | ||
--table.insert(categories, is_alt_name_in_italics(args.alt_name)) | --table.insert(categories, is_alt_name_in_italics(args.alt_name)) | ||
table.insert(categories, are_values_linked_or_formatted(args)) | -- table.insert(categories, are_values_linked_or_formatted(args)) -- commenting out for now | ||
table.insert(categories, is_country_name_valid(args.country)) | table.insert(categories, is_country_name_valid(args.country)) | ||
table.insert(categories, has_flag_icon(args)) | table.insert(categories, has_flag_icon(args)) | ||
table.insert(categories, is_credit_used_correctly(args)) | table.insert(categories, is_credit_used_correctly(args)) | ||
table.insert(categories, is_based_on_used_correctly(args.based_on)) | |||
table.insert(categories, does_num_episodes_have_extraneous_text(args.num_episodes)) | |||
table.insert(categories, are_exclusive_parameter_sets_used(args)) | table.insert(categories, are_exclusive_parameter_sets_used(args)) | ||
local release_categories = is_release_information_formatted_correctly(args) | local release_categories = is_release_information_formatted_correctly(args) |
Latest revision as of 18:49, 21 August 2024
-- require("strict")
--- @module
local p = {}
local maintenance_categories = {
alt_name = "[[Category:Pages using infobox television with incorrectly formatted values|%s]]",
dates_incorrectly_formatted = "[[Category:Pages using infobox television with nonstandard dates]]",
dates_missing = "[[Category:Pages using infobox television with missing dates]]",
flag_icon = "[[Category:Pages using infobox television with flag icon]]",
image_values_without_an_image = "[[Category:Pages using infobox television with image-related values without an image]]",
incorrectly_formatted = "[[Category:Pages using infobox television with incorrectly formatted values|%s]]",
manual_display_title = "[[Category:Pages using infobox television with unnecessary manual displaytitle]]",
manual_display_title_temp_tracking = "[[Category:Pages using infobox television with manual displaytitle]]",
non_matching_title = "[[Category:Pages using infobox television with non-matching title]]",
unnecessary_title_parameter = "[[Category:Pages using infobox television with unnecessary name parameter]]",
unlinked_values = "[[Category:Pages using infobox television with unlinked values|%s]]",
temp = "[[Category:Temp infobox television tracking category|%s]]",
}
local number_of_network_sets = 7
--- Returns a table consisting of the title's title parts.
---
--- The return table's properties:
--- - title - The title.
--- - disambiguation - the disambiguation text without parentheses.
---
--- Note: could potentially be moved to an outside module for other template and module uses.
---
--- @param text string
--- @return table<string, string | nil>
local function get_title_parts(text)
local title, disambiguation = string.match(text, "^(.+) (%b())$")
if not title or type(title) ~= "string" then
title = text
end
---@type table<string, string | nil>
local title_parts = {title = --[[---@not number | nil]] title, disambiguation = nil}
if not disambiguation or type(disambiguation) ~= "string" then
return title_parts
end
-- Remove outside parentheses from names which use parentheses as part of the name such as "episode (Randall and Hopkirk (Deceased))".
disambiguation = string.sub(--[[---@not number | nil]] disambiguation, 2, -2)
title_parts.disambiguation = --[[---@not number]] disambiguation
return title_parts
end
--- Returns a maintenance category if the italic_title value is not "no".
---
--- Infobox parameters checked:
--- - |italic_title=
---
--- @param args table
--- @return string
local function is_italic_title_valid_value(args)
if args.italic_title and args.italic_title ~= "no" then
return string.format(maintenance_categories.incorrectly_formatted, "italic_title")
end
return ""
end
--- Returns a maintenance category if the start_date value is set to a future date.
---
--- Infobox parameters checked:
--- - |first_aired[1-number_of_network_sets]=
--- - |released[1-number_of_network_sets]=
---
--- @param args table
--- @return string
local function is_start_date_in_the_future(start_date)
-- Extract the date from the start_date.
local date_pattern = ".*<span[^>]*>(.-)</span>"
local extracted_date = start_date:match(date_pattern)
-- Parse the date components
local year, month, day = extracted_date:match("(%d+)-(%d+)-(%d+)")
-- Create a table with the parsed date components
local date_table = {
year = tonumber(year) or 0,
month = tonumber(month) or 0,
day = tonumber(day) or 0,
hour = 0, -- Assuming 00:00:00 for simplicity
min = 0,
sec = 0
}
-- Convert the date table to a Unix timestamp
local start_date_timestamp = os.time(date_table)
-- Get the current date components.
local current_date = os.date("*t")
-- Set the time components to zero.
current_date.hour = 0
current_date.min = 0
current_date.sec = 0
-- Convert the date components into a timestamp.
local current_timestamp = os.time(current_date)
--local extracted_date_timestamp = os.time(extracted_date)
-- The infobox does not allow for future dates.
mw.log("current_timestamp: " .. current_timestamp)
mw.log("start_date_timestamp: " .. extracted_date)
if current_timestamp < start_date_timestamp then
return maintenance_categories.dates_incorrectly_formatted
end
return ""
end
--- Returns a maintenance category if the dates are not formatted correctly with
--- {{Start date}} and {{End date}} templates.
---
--- Infobox parameters checked:
--- - |first_aired[1-number_of_network_sets]=
--- - |released[1-number_of_network_sets]=
--- - |last_aired[1-number_of_network_sets]=
---
--- Note: all_tests is meant only for /testcases testing.
---
--- @param all_tests string Testing conditional value.
--- @param released string The start date value.
--- @param first_aired string The start date value.
--- @param last_aired string The end date value.
--- @return string
local function are_dates_formatted_correctly(all_tests, released, first_aired, last_aired)
-- To keep /testcases clean, this is set so only what is test is shown.
if all_tests == "no" then
return ""
end
-- Config parameters
local first_aired_future = "Upcoming"
local last_aired_current = "present"
local start_date_class = "itvstart"
local end_date_class = "itvend"
local film_date_class = "film%-date"
local start_date = released or first_aired
-- A start date should always be set.
if not start_date then
return maintenance_categories.dates_missing
end
-- Validate the start date is formmated using {{Start date}} and not any other template, including {{Film date}}, or uses the word "Upcoming".
if start_date and (string.find(start_date, film_date_class) or not string.find(start_date, start_date_class) and start_date ~= first_aired_future) then
return maintenance_categories.dates_incorrectly_formatted
end
-- An end date should always be set if the show or film wasn't released all at once.
if first_aired and first_aired ~= first_aired_future and not last_aired then
return maintenance_categories.dates_missing
end
-- Validate the end date is formmated using {{End date}} and not any other template, or uses the word "present".
if last_aired and (not string.find(last_aired, end_date_class) and last_aired ~= last_aired_current) then
return maintenance_categories.dates_incorrectly_formatted
end
-- Only one date should be used per field.
if (start_date and select(2, string.gsub(start_date, start_date_class, "")) > 1) or (last_aired and select(2, string.gsub(last_aired, end_date_class, "")) > 1) then
return maintenance_categories.dates_incorrectly_formatted
end
-- Check if start date is set to a future date.
if start_date ~= first_aired_future then
return is_start_date_in_the_future(start_date)
end
return ""
end
--- Returns a maintenance category if exclusive parameter sets are used.
---
--- Infobox parameters checked:
--- - |image_alt= and |alt=
--- - |image_size= and |image_upright=
--- - |based_on= and |inspired_by=
--- - |screenplay= and |teleplay=
--- - |presenter= and |host=
--- - |narrator=, |narrated= and |announcer=
--- - |theme_music_composer= and |music=
--- - |open_theme= and |opentheme=
--- - |end_theme= and |endtheme=
--- - |released[1-number_of_network_sets]= and |first_aired[1-number_of_network_sets]=
--- - |released[1-number_of_network_sets]= and |last_aired[1-number_of_network_sets]=
--- - |network[1-number_of_network_sets]= and |channel[1-number_of_network_sets]=
---
--- The function currently checks if the network and channel parameters both have values.
---
--- @param args table
--- @param args table
--- @return string
local function _are_exclusive_parameter_sets_used(args, parameters)
for _, set in ipairs(parameters) do
if (args[set[1]] and args[set[2]]) or (args[set[1]] and args[set[3]]) or (args[set[2]] and args[set[3]]) then
return string.format(maintenance_categories.incorrectly_formatted, "-duplicate")
end
end
return ""
end
--- Returns a maintenance category if exclusive parameter sets are used.
--- Create a set parameters to check.
--- Does not include release information related parameters which are sent from
--- a different function due to their numbered variations.
--- See _are_exclusive_parameter_sets_used() for more details.
---
--- @param args table
--- @return string
local function are_exclusive_parameter_sets_used(args)
local parameters = {
{"image_alt", "alt"},
{"image_size", "image_upright"},
{"based_on", "inspired_by"},
{"screenplay", "teleplay"},
{"presenter", "host"},
{"narrator", "narrated", "announcer"},
{"theme_music_composer", "music"},
{"open_theme", "opentheme"},
{"end_theme", "endtheme"},
}
return _are_exclusive_parameter_sets_used(args, parameters)
end
--- Returns a maintenance category if the values are unlinked.
---
--- Infobox parameters checked:
--- - |network[1-number_of_network_sets]=
--- - |channel[1-number_of_network_sets]=
---
--- The function currently checks if a value is unlinked.
---
--- @param args table
--- @return string
local function are_values_unlinked(args)
for key, value in pairs(args) do
-- Check whether the values are linked.
if value and not string.find(value, "%[%[.*%]%]") then
return string.format(maintenance_categories.unlinked_values, key)
end
end
return ""
end
--- Returns a maintenance category if the dates are not formatted correctly
--- and using "Original", "Revival" or italics to denote a split in the date range.
---
--- Infobox parameters checked:
--- - |first_aired[1-number_of_network_sets]=
--- - |released[1-number_of_network_sets]=
--- - |last_aired[1-number_of_network_sets]=
--- - |network[1-number_of_network_sets]=
--- - |channel[1-number_of_network_sets]=
---
--- @param args table
--- @return string
local function does_release_information_have_extraneous_text(args)
for k, v in pairs(args) do
if string.find(string.lower(v), "original") and not string.find(string.lower(v), "aboriginal") or
string.find(string.lower(v), "revival") or
string.find(v, "''") then
return string.format(maintenance_categories.incorrectly_formatted, k)
end
end
return ""
end
--- Returns a maintenance category if the release information:
---- Is not formatted correctly
---- Has extraneous text
---- Dates don't use correct mark up
---
--- Infobox parameters checked:
--- - |first_aired[1-number_of_network_sets]=
--- - |released[1-number_of_network_sets]=
--- - |last_aired[1-number_of_network_sets]=
--- - |network[1-number_of_network_sets]=
--- - |channel[1-number_of_network_sets]=
---
--- @param args table
--- @return string
local function is_release_information_formatted_correctly(args)
local release_information = {"first_aired", "released", "last_aired", "network", "channel"}
local categories = {}
for i = 1, number_of_network_sets do
local num = ""
if i > 1 then
num = i
end
local numbered_args = {}
for _, v in pairs(release_information) do
numbered_args[v .. num] = args[v .. num]
end
-- If current table is empty, break current cycle.
if next(numbered_args) then
table.insert(categories, does_release_information_have_extraneous_text(numbered_args))
table.insert(categories, are_values_unlinked({network = args["network" .. num], channel = args["channel" .. num]}))
table.insert(categories, _are_exclusive_parameter_sets_used(args, {{"network" .. num, "channel" .. num}, {"released" .. num, "first_aired" .. num}, {"released" .. num, "last_aired" .. num}}))
table.insert(categories, are_dates_formatted_correctly(args.all_tests, args["released" .. num], args["first_aired" .. num], args["last_aired" .. num]))
end
end
return categories
end
--- Returns a maintenance category if a {{Italic title}} or {{DISPLAYTITLE}} template is used.
--- Checks also for the following {{Italic title}} redirects:
---- Italic
---- Italics
---- Italictitle
---- Italics title
---
--- Testing parameters:
--- - |page_test= - a real Wikipedia page to read the content of the page.
---
--- Infobox parameters checked:
--- - |italic_title=
---
--- @param args table
--- @return string
local function has_display_title(args)
--TODO: when testing below is done uncomment code
--if args.italic_title then
-- return ""
--end
local article
if args.page_test then
article = mw.title.new(args.page_test)
else
article = mw.title.getCurrentTitle()
end
local page_text = article:getContent()
if not page_text then
return ""
end
if (string.find(page_text, "{{[Ii]talics?%s?title}}") or string.find(page_text, "{{[Ii]talics?}}")) and not string.match(page_text, "{{[Ii]talic title|all=yes}}")then
return maintenance_categories.manual_display_title
end
local display_title = string.match(page_text, "{{DISPLAYTITLE:(.*)}}")
local article_title = article.text
--TODO: currently does not work
--local display_title_no_namespace = string.gsub(display_title, article.nsText .. ":", "")
--local display_title_no_italics = string.sub(display_title_no_namespace, 3, string.len(display_title_no_namespace) - 2)
if display_title then
-- if article_title == display_title or article_title == display_title_no_italics then
if article_title == display_title or article_title == string.sub(display_title, 3, string.len(display_title) - 2) then
return maintenance_categories.manual_display_title
elseif string.find(display_title, "<sub>") or string.find(display_title, "<sup>") then
-- TODO: This is valid. Will remove when done with cleanup.
return ""
else
-- TODO: remove when done checking results.
return maintenance_categories.manual_display_title_temp_tracking
end
end
return ""
end
--- Returns a maintenance category if a flag icon is used.
---
--- All the infobox values are checked.
---
--- @param args table
--- @return string
local function has_flag_icon(args)
for _, v in pairs(args) do
if string.find(v, "flagicon") then
return maintenance_categories.flag_icon
end
end
return ""
end
--- Returns a maintenance category if num_episodes uses:
--- - "as of" as text
--- - A date template
---
--- Infobox parameters checked:
--- - |num_episodes=
---
--- @param num_episodes string
--- @return string
local function does_num_episodes_have_extraneous_text(num_episodes)
if not num_episodes then
return ""
end
if string.find(string.lower(num_episodes), "as of")
or string.find(num_episodes, "dtstart")
or string.find(num_episodes, "episode%-counter") then
return string.format(maintenance_categories.incorrectly_formatted, "num_episodes")
end
return ""
end
--- Returns a maintenance category if |based_on uses a generic word instead
--- of the title of the original work:
--- "book"
--- "novel"
---
--- Infobox parameters checked:
--- - |based_on=
---
--- @param num_episodes string
--- @return string
local function is_based_on_used_correctly(based_on)
if not based_on then
return ""
end
local generic_titles = {
"book",
"novel",
}
-- Remove content enclosed by double single quotes (''text'')
local stripped_text = based_on:gsub("''[^']*''", "")
-- Remove content enclosed by double quotes ("text")
stripped_text = based_on:gsub('"[^"]*"', "")
-- Remove content enclosed by double square brackets ([[text]])
stripped_text = based_on:gsub("%[%[.-%]%]", "")
-- Convert to lowercase to ensure case-insensitive matching
stripped_text = stripped_text:lower()
for _, word in pairs(generic_titles) do
if string.find(stripped_text, word) then
return string.format(maintenance_categories.incorrectly_formatted, "based_on")
end
end
return ""
end
--- Checks if a string is in the exceptions list.
---
--- @param str string
--- @return boolean
local function is_in_credit_exceptions(str)
local exceptions = {
"Aulsondro \"Novelist\" Hamilton",
-- Booker can be a last name.
"Booker",
"Jack Trevor Story",
}
for _, exception in ipairs(exceptions) do
if string.find(str, exception) then
return true
end
end
return false
end
--- Returns a maintenance category if a credit information entered is from the following list:
--- "assistant", associate", "co-", "executive", "line producer", "on-line", "prod%.", "supervising"
--- "book", "manuscript", "novel", "script", "screenplay", "story", "teleplay"
--- TODO: "lyric" and "dialogue" should be either supported or removed.
--- These credits have their own unique parameters that should be used instead.
---
--- Infobox parameters checked:
--- - |director=
--- - |editor=
--- - |executive_producer=
--- - |producer=
--- - |screenplay=
--- - |story=
--- - |teleplay=
--- - |writer=
---
--- @param args table
--- @return string
local function is_credit_used_correctly(args)
local credits_list = {
"director",
"editor",
"executive_producer",
"producer",
"screenplay",
"story",
"teleplay",
"writer",
}
local credits = {}
for _, value in pairs(credits_list) do
credits[value] = args[value]
end
local invalid_credits = {
"assistant",
"associate",
"book",
"co%-",
"executive",
"line producer",
"manuscript",
"novel",
"on%-line",
"prod%.",
"supervising",
"script",
"screenplay",
"story",
"teleplay",
"lyric", -- temp
"dialogue", -- temp
}
local delink = require("Module:Delink")._delink
for key, credit in pairs(credits) do
for _, invalid_credit in pairs(invalid_credits) do
local pattern = "%f[%a]" .. invalid_credit
credit = delink{credit}
if string.find(string.lower(credit), pattern) and not is_in_credit_exceptions(credit) then
if invalid_credit == "lyric" or invalid_credit == "dialogue" then
return string.format(maintenance_categories.temp, invalid_credit)
else
return string.format(maintenance_categories.incorrectly_formatted, key)
end
end
end
end
return ""
end
--- Returns a maintenance category if the country information entered is from the following list:
--- U.S.A, USA, U.S., US, UK, U.K.
---
--- Infobox parameters checked:
--- - |country=
---
--- @param country string
--- @return string
local function is_country_name_valid(country)
if not country then
return ""
end
local args = {"U.S", "US", "UK", "U.K."}
for _, v in pairs(args) do
if string.find(country, v) then
return string.format(maintenance_categories.incorrectly_formatted, "country")
end
end
return ""
end
--- Returns a maintenance category if the values are linked or formatted.
---
--- Infobox parameters checked:
--- - |language=
---
--- The function currently checks if the following values are present:
--- - ] - links.
---
--- @param args table
--- @return string
local function are_values_linked_or_formatted(args)
local parameters = {language = args.language}
for key, value in pairs(parameters) do
for _, bad_value in pairs({"]"}) do
if string.find(value, bad_value, 1, true) then
return string.format(maintenance_categories.incorrectly_formatted, key)
end
end
end
return ""
end
-- Splits a string and returns a table.
--
-- @param str string
-- @return table
local function split(str)
local sep = "\n"
local result = {}
local regex = ("([^%s]+)"):format(sep)
for each in str:gmatch(regex) do
table.insert(result, each)
end
return result
end
-- Returns a string value clean from various list syntax.
--
-- @param str string
-- @return string
local function clean_list_syntax(str)
str = string.gsub(str, "\127[^\127]*UNIQ%-%-(%a+)%-%x+%-QINU[^\127]*\127", "") -- Remove all strip-markers.
str = string.gsub(string.gsub(str, "%<%/? *div[^%>]*%>", ""), "%<%/? *span[^%>]*%>", "") -- Removes div and span tags.
str = string.gsub(str, "%<%/? *ul[^%>]*%>", "") -- Remove list tags.
str = string.gsub(str, "%<%/? *li[^%>]*%>", "\n") -- Remove list tags. Replace with new line.
str = string.gsub(str, "</? *br */?>", "\n") -- Replace <br /> (and variants) with new line.
str = string.gsub(str, "\n\n", "\n") -- Replace double new line with a single new line.
str = string.gsub(str, "*", "") -- Remove asterisks.
return str
end
--- Returns a maintenance category if:
---- When alt_name= is a list of values, and not all entries are in italics.
---- When alt_name= is a single value and is in italics.
----- This is because the template automatically handles the italics and when also manually added,
----- results in 4 apostrophes which produce a bold title instead.
---
--- Infobox parameters checked:
--- - |alt_name=
---
--- @param alt_name string
--- @return string
local function is_alt_name_in_italics(alt_name)
if not alt_name then
return ""
end
local detect_singular = require("Module:Detect singular")._main
local args = {alt_name, ["no_and"] = "1", ["no_comma"] = "1"}
local is_singular = detect_singular(args)
if is_singular > 1 then
local alt_names = clean_list_syntax(alt_name)
alt_names = split(alt_names)
for _, name in ipairs(alt_names) do
if not string.find(name, "''") then
return string.format(maintenance_categories.alt_name, "alt_name")
end
end
else
if string.find(alt_name, "''") then
return string.format(maintenance_categories.alt_name, "alt_name")
end
end
return ""
end
--- Returns a maintenance category if the |image= value includes the "File:"
--- or "Image:" prefix, or if it is a URL.
---
--- Infobox parameters checked:
--- - |image=
---
--- @param image string
--- @return string
local function is_image_using_incorrect_syntax(image)
if not image then
return ""
end
local invalid_strings = {
"file:",
"image:",
"http:",
"https:",
}
image = string.lower(image)
for _, invalid in ipairs(invalid_strings) do
if string.find(image, invalid) then
return string.format(maintenance_categories.incorrectly_formatted, "image")
end
end
return ""
end
--- Returns a maintenance category if the |image_size= value includes "px".
---
--- Infobox parameters checked:
--- - |image_size=
---
--- @param image_size string
--- @return string
local function is_image_size_using_px(image_size)
if image_size and string.find(image_size, "px") then
return string.format(maintenance_categories.incorrectly_formatted, "image_size")
end
return ""
end
--- Returns a maintenance category if there is no image file while image auxiliary values are present.
---
--- Infobox parameters checked:
--- - |image=
--- - |image_size=
--- - |image_upright=
--- - |image_alt=
--- - |alt=
--- - |caption=
---
--- @param args table
--- @return string
local function are_image_auxiliary_values_used_for_no_image(args)
if args.image then
return ""
end
if args.image_size or args.image_upright or args.image_alt or args.alt or args.caption then
return maintenance_categories.image_values_without_an_image
end
return ""
end
--- Returns the display title text used in either the {{DISPLAYTITLE}} or {{Italic title}} templates.
---
--- @param page_text string
--- @param article_title string
--- @return string | nil
local function get_display_title_text(page_text, article_title)
if not page_text then
return nil
end
local title_modification = string.match(page_text, "{{DISPLAYTITLE:(.-)}}")
if title_modification and type(title_modification) == "string" then
local title_parts = get_title_parts(title_modification)
return string.gsub(title_parts.title, "'", "")
end
title_modification = string.match(page_text, "{{[Ii]talic title|all=yes}}")
if title_modification and type(title_modification) == "string" then
return article_title
end
return nil
end
--- Returns the title used in the {{Lowercase title}} template and an optional maintenance category.
---
--- @param page_text string
--- @param args table
--- @param article_title string
--- @param title_parts table
--- @param return_category boolean
--- @return string | nil
local function get_lowercase_template_status(page_text, args, article_title, title_parts, return_category)
if not page_text then
return nil
end
local lowercase_template = string.match(page_text, "{{[Ll]owercase title.-}}")
if not lowercase_template then
return nil
end
local lowercase_title
if string.find(lowercase_template, "|force=") then
lowercase_title = string.gsub(article_title,"^%u", string.lower)
else
lowercase_title = string.gsub(title_parts.title,"^%u", string.lower)
end
if return_category and args.name then
if args.name == lowercase_title then
return maintenance_categories.unnecessary_title_parameter
else
return maintenance_categories.non_matching_title
end
return ""
end
return lowercase_title
end
--- Returns the title used in the {{Correct title}} template and an optional maintenance category.
---
--- @param page_text string
--- @param args table
--- @param return_category boolean
--- @return string | nil
local function get_correct_title_value(page_text, args, return_category)
if not page_text then
return nil
end
local correct_title_template_pattern = "{{[Cc]orrect title|title=(.*)|reason=.-}}"
local correct_title = string.match(page_text, correct_title_template_pattern)
if not correct_title then
correct_title_template_pattern = "{{[Cc]orrect title|(.*)|reason=.-}}"
correct_title = string.match(page_text, correct_title_template_pattern)
end
if not correct_title and type(correct_title) ~= "string" then
return nil
end
local correct_title_title_parts = get_title_parts(correct_title)
if return_category and args.name then
if args.name == correct_title or args.name == correct_title_title_parts.title then
return maintenance_categories.unnecessary_title_parameter
else
return maintenance_categories.non_matching_title
end
end
return correct_title
end
--- Returns a maintenance category if the infobox title is equal to the article title.
---
--- Infobox parameters checked:
--- - |name=
---
--- The function currently checks if the infobox title is equal to the article title while ignoring styling such as:
--- - Nowrap spans.
--- - Line breaks.
---
--- A return value can be one of three options:
--- - The value of maintenance_categories.non_matching_title - when the args.title does not match the article title.
--- - The value of maintenance_categories.unnecessary_title_parameter - when the args.title matches the article title.
--- - An empty string - when args.name isn't used or the args.name uses an allowed modification
--- (such as a nowrap template) while the rest of the args.name matches the article title.
---
--- Testing parameters:
--- - |page_test= - a real Wikipedia page to read the content of the page.
--- - |page_title_test= - the title of the page being checked.
---
--- @param frame table
--- @param args table
--- @return string
local function is_infobox_title_equal_to_article_title(frame, args)
if not args.name then
return ""
end
local page_text
if args.page_test then
page_text = mw.title.new(args.page_test):getContent()
else
page_text = mw.title.getCurrentTitle():getContent()
end
-- Check if the article is using a {{Correct title}} template.
local correct_title = get_correct_title_value(page_text, args, true)
if correct_title then
return correct_title
end
local article_title = args.page_title_test
if not args.page_title_test then
article_title = mw.title.getCurrentTitle().text
end
-- Remove disambiguation.
local title_parts = get_title_parts(article_title)
-- Check if the article is using a {{Lowercase title}} template.
local lowercase_title = get_lowercase_template_status(page_text, args, article_title, title_parts, true)
if lowercase_title then
return lowercase_title
end
-- Remove nowrap span.
if string.find(args.name, "nowrap") then
local title = frame:expandTemplate{title = "Strip tags", args = {args.name}}
if title == article_title or title == title_parts.title then
return ""
end
return maintenance_categories.non_matching_title
end
-- Remove line breaks and additional spaces as a result.
if string.find(args.name, "<br%s?/?>") then
local title, _ = string.gsub(args.name, "<br%s?/?>", "")
title, _ = string.gsub(title, " ", " ")
if title == article_title or title == title_parts.title then
return ""
end
return maintenance_categories.non_matching_title
end
if args.name == article_title or args.name == title_parts.title then
return maintenance_categories.unnecessary_title_parameter
end
-- Article and infobox titles do not match.
return maintenance_categories.non_matching_title
end
--- Returns the relevant maintenance categories based on the {{Infobox television}} values validated.
---
--- @param frame table
--- @return string
function p.validate_values(frame)
local getArgs = require("Module:Arguments").getArgs
local args = getArgs(frame)
local categories = {}
table.insert(categories, is_infobox_title_equal_to_article_title(frame, args))
table.insert(categories, has_display_title(args))
table.insert(categories, are_image_auxiliary_values_used_for_no_image(args))
table.insert(categories, is_image_using_incorrect_syntax(args.image))
table.insert(categories, is_image_size_using_px(args.image_size))
--table.insert(categories, is_alt_name_in_italics(args.alt_name))
-- table.insert(categories, are_values_linked_or_formatted(args)) -- commenting out for now
table.insert(categories, is_country_name_valid(args.country))
table.insert(categories, has_flag_icon(args))
table.insert(categories, is_credit_used_correctly(args))
table.insert(categories, is_based_on_used_correctly(args.based_on))
table.insert(categories, does_num_episodes_have_extraneous_text(args.num_episodes))
table.insert(categories, are_exclusive_parameter_sets_used(args))
local release_categories = is_release_information_formatted_correctly(args)
for _, v in ipairs(release_categories) do
table.insert(categories, v)
end
table.insert(categories, is_italic_title_valid_value(args))
return table.concat(categories, "")
end
--- Returns the text used for the |above= field of the infobox.
---
--- Infobox parameters checked:
--- - |name=
---
--- Testing parameters:
--- - |page_test= - a real Wikipedia page to read the content of the page.
--- - |page_title_test= - the title of the page being checked.
---
--- @param frame table
--- @return string
function p.above_title(frame)
local getArgs = require("Module:Arguments").getArgs
local args = getArgs(frame)
local page
if args.page_test then
page = mw.title.new(args.page_test)
else
page = mw.title.getCurrentTitle()
end
local page_text = page:getContent()
local article_title = args.page_title_test
if not args.page_title_test then
article_title = page.text
end
local title_format = "''%s''"
local correct_title = get_correct_title_value(page_text, args, false)
if correct_title then
return string.format(title_format, correct_title)
end
local title_parts = get_title_parts(article_title)
local lowercase_title = get_lowercase_template_status(page_text, args, article_title, title_parts, false)
if lowercase_title then
return string.format(title_format, lowercase_title)
end
if args.italic_title then
local title_modification = get_display_title_text(page_text, article_title)
if title_modification then
return string.format(title_format, title_modification)
end
end
if args.name then
return string.format(title_format, args.name)
end
return string.format(title_format, title_parts.title)
end
return p