Module:FileInfo

local p = {} local h = {}

local Data = mw.loadData("Module:FileInfo/Data")

local Franchise = require("Module:Franchise") local utilsArg = require("Module:UtilsArg") local utilsTable = require("Module:UtilsTable")

-- Template:FileInfo function p.StoreWidth(frame) return mw.title.getCurrentTitle.file.width end function p.StoreHeight(frame) return mw.title.getCurrentTitle.file.height end

function p.Main(frame) local args, err = utilsArg.parse(frame:getParent.args, p.Templates.FileInfo) local categories = err and err.categoryText or "" local result = h.printFileInfoTable(args) categories = categories..h.categories(args.type, args.game, args.subject)

return result, categories end function h.printFileInfoTable(args) local gameDisplay if args.game then local gameLogo = Franchise.logo(args.game) local gameImage = gameLogo and utilsPage.exists(gameLogo) and utilsMarkup.file(gameLogo, { size = "130x130px" }) local gameLink = Franchise.link(args.game) local gameText = gameLink and string.format("This is a file pertaining to %s.", gameLink) if gameImage and gameText then gameDisplay = gameImage .. " " .. gameText elseif gameText then gameDisplay = gameText else gameDisplay = "" end end local typeName = args.type typeName = typeName and h.toTitleCase(typeName) local type = typeName and Data.types[typeName] type = type and type.category

local license if args.licensing and utilsTable.includes(data.licenses, args.licensing) then license = mw.getCurrentFrame:expandTemplate({			title = "FileInfo/" .. args.licensing,			args = {				trademark = args.trademark			}		}) else license = mw.getCurrentFrame:expandTemplate({ title = "FileInfo/Unsure" }) end

local html = mw.html.create("table"):addClass("wikitable fileinfo") h.row(html, "Summary", args.summary) h.row(html, "Type", type) h.row(html, "Source", args.source) h.row(html, "Game", gameDisplay) h.row(html, "Licensing", license, {		rowspan = args.trademark and "2" or "1" 	}) h.row(html, "Trademark", args.trademark and mw.getCurrentFrame:expandTemplate({ title = "FileInfo/Trademark" })) return tostring(html) end function h.row(html, field, value, attributes) if value then return html :tag("tr") :tag("th") :wikitext(field) :done :tag("td") :wikitext(value) :done :done end end

function h.categories(type, game, subjects) local gameName = game and Franchise.shortName(game) local typeName = args.type typeName = typeName and h.toTitleCase(typeName) local typeCat = typeName and Data.typesByKey[typeName] and Data.typesByKey[typeName].category local categories = "" if typeCat and not typeCat.nogame and gameName and game ~= "Series" then categories = categories..string.format("", gameName, typeCat) elseif typeCat then categories = categories..string.format("", typeCat) elseif gameCat then categories = categories..string.format("", gameName) end if subjects then categories = categories..h.subjectCategories(subjects, game) end if typeName == "Sprite" and string.find(mw.title.getCurrentTitle.text, ".gif") then categories = categories.."" end if not game then -- not necessarily invalid but worth tracking categories = categories.."" end return categories end function h.subjectCategories(subjects) local categories = "" for i, subject in ipairs(subjects) do		local term, errCategories = Term.fetchTerm(subject, "Series") if not term then local utilsError = require("Module:UtilsError") local utilsMarkup = require("Module:UtilsMarkup") utilsError.warn(string.format("subject  is not a valid term", subject)) categories = categoires..utilsMarkup.categories(errCategories) end term = string.gsub(term, "#", "") -- strip # from term because categories can't have them in their name -- only add subject-based categories if they already exist, to avoid spamming Special:WantedCategories if utilsPage.exists("Category:Images of "..category) then categories = caetgories.."" end end end

-- Support types written in lower case or Title Case -- Previously only the former was supported but editors had a tendency to use the latter -- Which is understandable because the type category is in title case, Template:Media is in title case, -- and all other fields in FileInfo are in title case or sentence case -- We may eventually decide to support only Title Case but that would mean -- running a text-replace on the thousands of file pages using lowercase function h.toTitleCase(type) return string.gsub(" "..type, "%W%l", string.upper):sub(2) end

function p.Schemas return { Data = { type = "record", required = true, properties = { {					name = "types", required = true, type = "map", desc = "Defines file types, associating a type name to a wiki category.", keys = { type = "string"}, keyPlaceholder = "type name", values = { type = "record", properties = { {								name = "category", required = true, type = "string", desc = "The name of a subcategory of Category:Files by Type.", },							{								name = "nogame", type = "boolean", desc = "If, indicates that images of this type di not apply to any particular entry in the Zelda franchise and therefore its category should not be subdivided by game.", },						},					},				},				{					name = "licenses", required = true, type = "array", items = { type = "string" }, desc = "A list of licenses supported by Template:FileInfo. Each license must have a subpage under Template:FileInfo/Licenses.", },			},		}	} end

function p.Data(frame) local result = "" result = result .. "\n==Types==\n" result = result .. h.typeTable result = result .. "\n==Licenses==\n" result = result .. h.licenseTable return result end function h.typeTable local utilsLayout = require("Module:UtilsLayout") local utilsString = require("Module:UtilsString") local gameTypes = {} local conceptTypes = {} local otherTypes = {} for typeName, type in pairs(Data.types) do		type = utilsTable.merge({}, type, {			name = typeName		}) if utilsString.startsWith(type.name, "Concept") then table.insert(conceptTypes, type) elseif type.nogame then table.insert(otherTypes, type) else table.insert(gameTypes, type) end end gameTypes = utilsTable.sortBy(gameTypes, "name") conceptTypes = utilsTable.sortBy(conceptTypes, "name") otherTypes = utilsTable.sortBy(otherTypes, "name") local types = utilsTable.concat(gameTypes, conceptTypes, otherTypes)

local dataRows = utilsTable.map(types, function(type)		local typeCode = " "		local typeCategory = "Category:"..type.category..""		return {typeCode, typeCategory}	end) table.insert(dataRows, 1, {		{			header = true,			colspan = 2,			content = "Game Types"		}	}) table.insert(dataRows, #gameTypes + 2, {		{			header = true,			colspan = 2,			content = "Concept Types",		}	}) table.insert(dataRows, #gameTypes + #conceptTypes + 3, {		{			header = true,			colspan = 2,			content = "Non-Game Types",		}	}) return utilsLayout.table({		headers = {"Type", "Category"},		rows = dataRows,	}) end function h.licenseTable local utilsLayout = require("Module:UtilsLayout")

return utilsLayout.table({		sortable = {1},		headers = {"License", "Template", "Output"},		rows = utilsTable.map(Data.licenses, function(license) local licenseCode = " " local template = "FileInfo/"..license local templateLink = "Template:"..template.."" local templateOutput = mw.getCurrentFrame:expandTemplate({title = template}) return {licenseCode, templateLink, templateOutput} end)	}) end

p.Templates = { FileInfo = { purpose = "Displays, categorizes, and stores file information. See Guidelines:Files for further guidance.", format = "block", paramOrder = {"summary", "type", "source", "game", "licensing", "subject", "trademark"}, boilerplate = { tabs = { {					label = "Zelda-Related Files", params = {"summary", "type", "source", "game", "licensing", "subject"}, },				{					label = "Other Files", params = {"summary", "type", "source", "licensing"}, },				{					label = "All Parameters", params = {"summary", "type", "source", "game", "licensing", "subject", "trademark"}, },			},		},		params = { summary = { --required = true, type = "content", desc = "A short description of the file.", trim = true, nilIfEmpty = true, },			type = { required = "Category:Files Lacking Type", type = "string", desc = "The type of file, which determines how it is categorized.", enum = utilsTable.merge({ reference = "Module:FileInfo/Data" }, utilsTable.keys(Data.types)), trim = true, nilIfEmpty = true, },			source = { required = "Category:Files Lacking Sources", type = "string", desc = "The original source of the file. It may be in the form of a URL or author recognition. Template:Source exists for this purpose.", trim = true, nilIfEmpty = true, },			subject = { type = "string", desc = "Wiki article names of all the subjects depicted in the file. A comma-separated list.", split = true, trim = true, nilIfEmpty = true, },			game = { --required = true, type = "string", desc = "A valid code for a game, book, comic, manga, or TV show (or ).", enum = Franchise.enum({ 					includeSeries = true,					includeGroups = true,				}), trim = true, nilIfEmpty = true, },			licensing = { required = "Category:Unlicensed Files", type = "string", desc = "The copyright licensing for the file. For the vast majority of files,  is the correct value here.", enum = utilsTable.merge({ reference = "Module:FileInfo/Data" }, utilsTable.keys(Data.licenses)), trim = true, nilIfEmpty = true, },			trademark = { type = "boolean", desc = "Enter any text to add a trademark notice to the licensing. Use on all trademarks (usually denoted by an ® or ™ symbol).", trim = true, nilIfEmpty = true, }		},		examples = { {				summary = "LADX:", subject = "Animal Village, Rabbit", type = "map", source = "", game = "LADX", licensing = "Copyright", },			{				summary = "The Timeline", source = "", type = "print", game = "Series", licensing = "Copyright" },			{				summary = "Nintendo's current logo.", type = "logo", source = "", licensing = "PD-Simple", trademark = "yes", },			{				summary = "File missing required info" },		},	}, }

return p