Module:Media: Difference between revisions

From Zelda Wiki, the Zelda encyclopedia
Jump to navigation Jump to search
(Check type rather than canonicity (to allow games like FSAE in infoboxes on pages like Title Screen))
(adding thumbnails)
 
Line 42: Line 42:
category = "Maps",
category = "Maps",
description = "In-game map of an area",
description = "In-game map of an area",
},
{
type = "Thumbnail",
category = "Thumbnails",
description = "In-game images",
},
},
}
}

Latest revision as of 17:48, 30 May 2024


-- This modules serves as the code for Template:Media.
local p = {}
local h = {}

local File = require("Module:File")
local Franchise = require("Module:Franchise")
local utilsLayout = require("Module:UtilsLayout")
local utilsMarkup = require("Module:UtilsMarkup")
local utilsTable = require("Module:UtilsTable")

local CAT_INVALID_ARGS = require("Module:Constants/category/invalidArgs")

-- In the order in which they are to be presented, from left to right
local mediaTypes = {
	{
		type = "Artwork",
		category = "Artwork",
		description = "Official artwork provided by Nintendo",
	},
	{
		type = "Render",
		category = "Renders",
		description =  "Official models provided by Nintendo",
	},
	{
		type = "Model",
		category = "Models",
		description = "In-game models",
	},
	{
		type = "Sprite",
		category = "Sprites",
		description = "In-game sprites or icons",
	},
	{
		type = "Screenshot",
		category = "Screenshots",
		description = "In-game screenshots",
	},
	{
		type = "Map",
		category = "Maps",
		description = "In-game map of an area",
	},
	{
		type = "Thumbnail",
		category = "Thumbnails",
		description = "In-game images",
	},
}

-- Template:Media
function p.Main(frame)
	local args = frame:getParent().args
	return p.main(args)
end

function p.main(args)
	local remainingArgs = utilsTable.clone(args)
	local categories = {}
	local games = {}
	local typeTabs = {}
	local typeTabWithLatestRelease = 1
	local latestReleaseOverall = ""
	local fileCount = 0
	local latestImagePerType = {}
	
	for _, mediaType in ipairs(mediaTypes) do
		local gameTabs = {}
		local defaultGameTab = 1
		local latestReleaseForType = ""
		
		for i, game in ipairs(Franchise.enum({ includeSeries = true, includeGroups = true })) do
			local key = mediaType.type .. " " .. game
			remainingArgs[key] = nil
			
			local file = args[key]
			if file ~= nil and file ~= "" then
				fileCount = fileCount + 1
				table.insert(games, game)
				local img, exists
				if utilsMarkup.containsLink(file) or file ~= mw.text.killMarkers(file) then -- if user specified markup, simply render the markup as-is.
					img = file
					exists = true
				else
					if not string.find(file, "^File:") then
						h.warn(string.format("Invalid filename <code>%s</code>. Filenames must start with <code>File:</code>.", file))
						table.insert(categories, CAT_INVALID_ARGS)
						file = "File:"..file
					end
					img, exists = File.image(file, {
						size = "320x320px",
						scale = mediaType.type == "Sprite" and 10 or nil, -- For sprites, scale to a maximum of 10x its original size. Only done for sprites due to scaling being somewhat expensive.
						isPixelArt = mediaType.type == "Sprite" or Franchise.graphics(game) == "2D"
					})
				end
				table.insert(gameTabs, {
					label = game,
					content = img,
					tooltip = Franchise.shortName(game)
				})
				if not exists and mw.title.getCurrentTitle().nsText ~= "User" then
					table.insert(categories, "Articles lacking files")
					table.insert(categories, "Articles lacking " .. string.lower(mediaType.category))
					table.insert(categories, string.format("%s articles lacking files", Franchise.shortName(game)))
				end
				local release = Franchise.releaseDate(game)
				-- empty string here means an unreleased game. This ensures the unreleased is sorted last.
				-- the 'i' is appended to ensure that multiple unreleased games are sorted in canon order.
				if release == "" then
					 release = "unreleased"..i
				end
				if exists and release and release > latestReleaseForType then
					latestReleaseForType = release
					defaultGameTab = #gameTabs
					latestImagePerType[#typeTabs + 1] = file
				end
				if exists and release and release > latestReleaseOverall then
					latestReleaseOverall = release
					typeTabWithLatestRelease = #typeTabs + 1
				end
			end
		end
		if #gameTabs > 0 then
			table.insert(typeTabs, {
				label = mediaType.type,
				tooltip = mediaType.description,
				gameTabs = gameTabs,
				defaultGameTab = defaultGameTab,
			})
		end
	end
	
	remainingArgs["defaultTypeTab"] = nil
	local defaultTypeTab = utilsTable.findIndex(typeTabs, function(typeTab)
		return typeTab.label == args.defaultTypeTab
	end)
	defaultTypeTab = defaultTypeTab or typeTabWithLatestRelease

	local invalidKeys = utilsTable.keys(remainingArgs)
	if #invalidKeys > 0 then
		local msg = string.format("The following keys use an invalid media type or game code: <code>%s</code><p>For a list of valid types, see [[Template:Media]]. For a list of valid games, see [[Module:Franchise]].</p>", utilsTable.print(invalidKeys))
		h.warn(msg)
		table.insert(categories, CAT_INVALID_ARGS)
	end
	
	local mainGames, otherGames = utilsTable.partition(games, function(game)
		local gameType = Franchise.type(game)
		return gameType == "main" or gameType == "remake"
	end)
	if #mainGames > 0 and #otherGames > 0 then 
		otherGames = utilsTable.map(otherGames, utilsMarkup.code)
		otherGames = mw.text.listToText(otherGames)
		h.warn("Entries for %s should be moved from the infobox to the Gallery section. As per [[Template:Media#Guidelines]], infoboxes should not mix main series games with other games.", otherGames)
		table.insert(categories, CAT_INVALID_ARGS)
	end
	
	local content
	if #typeTabs == 1 and #typeTabs[1].gameTabs == 1 then
		content = typeTabs[1].gameTabs[1].content
	else
		for i, typeTab in ipairs(typeTabs) do
			typeTab.content = utilsLayout.tabs(typeTab.gameTabs, {
				default = typeTab.defaultGameTab,
				align = "center",
				tabOptions = {
					position = "bottom",
					columns = 5,
				},
				contentOptions = {
					alignVertical = "center",
					fixedHeight = true,
				}
			})
		end
		content = utilsLayout.tabs(typeTabs, {
			default = defaultTypeTab,
			align = "center",
			tabOptions = {
				columns = 4,
			},
		})
	end
	
	local pageImage = latestImagePerType[defaultTypeTab]
	if pageImage then
		-- Set the file under the default type and game tab as the article's representative image for page previews
		mw.ext.seo.set({
			image = pageImage
		})
	end
	
	return content .. utilsMarkup.categories(categories)
end

function h.warn(msg, ...)
	local utilsError = require("Module:UtilsError")
	local warnMessage = string.format(msg, ...)
	utilsError.warn(warnMessage)
end

return p