Module:Franchise

local p = {} local h = {}

local ListPages = require("Module:List Pages") local utilsArg = require("Module:UtilsArg") local utilsCargo = require("Module:UtilsCargo") local utilsLayout = require("Module:UtilsLayout") local utilsMarkup = require("Module:UtilsMarkup") local utilsString = require("Module:UtilsString") local utilsTable = require("Module:UtilsTable") local utilsVar = require("Module:UtilsVar")

local cache = mw.loadData("Module:Franchise/Cache") local orderCounter = utilsVar.counter("canonOrder")

-- Many templates need "Series" as if it were a game. Since it does not fit into the data model of Data:Franchise, it is manually defined here. local series = { article = "The Legend of Zelda (Series)", shortName = "The Legend of Zelda Series", logo = "File:Zelda Logo TP.png", link = "The Legend of Zelda series", display = "The Legend of Zelda series", canonicity = "canon", }

local PREVIEW_COLUMNS = { common = {"canonOrder", "code", "link", "display", "logo", "releaseDate", "canonicity"}, Game = {"type", "graphics", "family", "remakeOf", "supersededBy"}, Book = {"type", "phraseLink", "authors", "basedOn"}, TV = {"type"}, Compilation = {"titles"}, Group = {"games"}, } PREVIEW_COLUMNS.Game = utilsTable.concat(PREVIEW_COLUMNS.common, PREVIEW_COLUMNS.Game) PREVIEW_COLUMNS.Book = utilsTable.concat(PREVIEW_COLUMNS.common, PREVIEW_COLUMNS.Book) PREVIEW_COLUMNS.TV = utilsTable.concat(PREVIEW_COLUMNS.common, PREVIEW_COLUMNS.TV) PREVIEW_COLUMNS.Compilation = utilsTable.concat(PREVIEW_COLUMNS.common, PREVIEW_COLUMNS.Compilation) PREVIEW_COLUMNS.Group = utilsTable.concat(PREVIEW_COLUMNS.common, PREVIEW_COLUMNS.Group)

-- Template:Franchise/Store * function p.AddToPreview(frame) local entryType = frame.args[1] local args, err = utilsArg.parse(frame:getParent.args, p.Templates["Franchise/Store " .. entryType]) if err then return utilsMarkup.categories(err.categories) end args = utilsTable.merge({}, args, {		entryType = entryType,		link = p.deriveLink(entryType, args),		display = p.deriveDisplay(entryType, args),	}) if entryType == "Game" or entryType == "Book" or entryType == "TV" then args.canonOrder = orderCounter.value else args.canonOrder = "—" end if type == "Book" then args.phraseLink = p.derivePhraseLink(args) end utilsVar.add("rows", args) end function p.StoreOrder(frame) return orderCounter.increment end function p.StoreLink(frame) return p.deriveLink(frame.args[1], frame:getParent.args) end function p.StoreDisplay(frame) return p.deriveDisplay(frame.args[1], frame:getParent.args) end function p.StorePhraseLink(frame) return p.derivePhraseLink(frame:getParent.args) end function p.deriveDisplay(entryType, args) if utilsString.notEmpty(args.display) then return args.display elseif entryType == "Book" then return h.deriveBookFields(args).display else return ("%s"):format(args.shortName) end end function p.deriveLink(entryType, args) if utilsString.notEmpty(args.display) then return args.link elseif entryType == "Book" then return h.deriveBookFields(args).link else return ("%s"):format(args.article, args.shortName) end end function p.derivePhraseLink(args) return h.deriveBookFields(args).phraseLink end

function p.Preview(frame) local rows = utilsVar.get("rows") for _, row in ipairs(rows) do		row.logo = utilsMarkup.link(row.logo) end local rowGroups = utilsTable.groupBy(rows, "entryType") local titles = utilsLayout.table({		sortable = true,		headers = PREVIEW_COLUMNS.common,		rows = utilsTable.map(rows, utilsTable._toArray(PREVIEW_COLUMNS.common, ""))	}) local games = utilsLayout.table({		sortable = true,		headers = PREVIEW_COLUMNS.Game,		rows = utilsTable.map(rowGroups.Game, utilsTable._toArray(PREVIEW_COLUMNS.Game, ""))	}) local books = utilsLayout.table({		sortable = true,		headers = PREVIEW_COLUMNS.Book,		rows = utilsTable.map(rowGroups.Book, utilsTable._toArray(PREVIEW_COLUMNS.Book, ""))	}) local tv = utilsLayout.table({		sortable = true,		headers = PREVIEW_COLUMNS.TV,		rows = utilsTable.map(rowGroups.TV, utilsTable._toArray(PREVIEW_COLUMNS.TV, ""))	}) local compilations = utilsLayout.table({		sortable = true,		headers = PREVIEW_COLUMNS.Compilation,		rows = utilsTable.map(rowGroups.Compilation or {}, utilsTable._toArray(PREVIEW_COLUMNS.Compilation, ""))	}) local groups = utilsLayout.table({		sortable = true,		headers = PREVIEW_COLUMNS.Group,		rows = utilsTable.map(rowGroups.Group or {}, utilsTable._toArray(PREVIEW_COLUMNS.Group, ""))	}) local preview = utilsLayout.tabs({		{			label = "All Titles",			content = titles,		},		{			label = "Games",			content = games,		},		{			label = "Books",			content = books,		},		{			label = "TV Shows",			content = tv,		},		{			label = "Compilations",			content = compilations		},		{			label = "Groups",			content = groups,		}	}, { columns = 15 }) return preview end

function p.UploadField(frame) local rows = utilsVar.get("rows") local groups = utilsTable.groupBy(rows, "entryType") local mainGames, otherGames = utilsTable.partition(groups["Game"], {		canonicity = "canon"	}) local remakes = utilsTable.groupBy(mainGames, "remakeOf") local books = groups["Book"] local tvShows = groups["TV"] local sortedMainGames = {} for _, mainGame in ipairs(utilsTable.reverse(mainGames)) do		if not mainGame.remakeOf then table.insert(sortedMainGames, mainGame) for _, remake in ipairs(remakes[mainGame.code] or {}) do				table.insert(sortedMainGames, remake) end end end local result = "" result = result .. "**|None\n" result = result .. "**Series|The Legend of Zelda Series\n" result = h.append(result, "Main Series", sortedMainGames) result = h.append(result, "Other Games", otherGames) result = h.append(result, "Books, Comics, and Manga", books) result = h.append(result, "TV Shows", tvShows) return utilsMarkup.pre(result) end function h.append(result, title, entries) result = result .. "\n*"..title.."\n" for _, entry in ipairs(entries) do result = result .. string.format("**%s|%s\n", entry.code, entry.shortName) end return result end

function h.deriveBookFields(args) local subtitle, display, link, phraseLink local parens = string.find(args.shortName, "%s%([^)]+%)")	if parens then		subtitle = string.sub(args.shortName, 1, parens - 1)		local descriptor = string.sub(args.shortName, parens)		display = ("%s%s"):format(subtitle, descriptor)		link = ("%s"):format(args.article, display)		local authors = ListPages.main(utilsString.split(args.authors))		phraseLink = ("%s %s by %s"):format(args.article, subtitle, args.type, authors)	else		display = ("%s"):format(args.shortName)		link = ("%s"):format(args.article, args.shortName)		phraseLink = link	end	return {		display = display,		link = link,		phraseLink = phraseLink,	} end

-- QUERIES: ALL

function p.enum(options) if not options then return cache.enum end enum = utilsTable.clone(cache.enum) -- clone the read-only cache item so that we can modify it	if options.includeSeries then table.insert(enum, 1, "Series") end if options.includeCompilations then local codes = utilsTable.map(cache.compilations, "code") enum = utilsTable.concat(codes, enum) end if options.includeGroups then -- insert "groups" so as to not disrupt the release order. This matters for Template:Media (e.g. the Figher page, which uses SSB4) for _, group in ipairs(cache.groups) do			local i = 1 repeat i = i + 1 until i == #enum or p.isCanon(enum[i]) == p.isCanon(group.code) and p.releaseDate(enum[i]) >= p.releaseDate(group.code) table.insert(enum, i, group.code) end end enum.reference = "Data:Franchise" return enum end

function p.article(code) return h.get(code, "article") end

function p.canonicity(code) return h.get(code, "canonicity") end

function p.display(code) return h.get(code, "display") end

function p.isCanon(code) return p.canonicity(code) == "canon" end

function p.link(code) return h.get(code, "link") end

function p.logo(code) return h.get(code, "logo") end

function p.releaseDate(code) return h.get(code, "releaseDate") end

function p.ShortName(frame) local args, err = utilsArg.parse(frame.args, {		params = {			[1] = {				name = "code",				enum = p.enum({ includeSeries = true, includeCompilations = true, includeGroups = true, }),			}		}	})	if err then return utilsMarkup.categories(err.categories) end return p.shortName(args.code) end function p.shortName(code) return h.get(code, "shortName") end

function p.type(code) return h.get(code, "type") end

-- QUERIES: GAMES

function p.enumGames(includeSeries) if includeSeries then local enum = utilsTable.concat({"Series"}, cache.enumGames) enum.reference = "Data:Franchise" return enum end return cache.enumGames end

function p.family(code) return h.get(code, "family") end

function p.graphics(code) return h.get(code, "graphics") end

function p.hasRemakes(code) return utilsTable.hasKey(cache.remakes, string.lower(code)) end

function p.isRemake(code) return p.type(code) == "remake" end

function p.remakes(code) return utilsTable.clone(cache.remakes[string.lower(code)]) or {} end

-- QUERIES: BOOKS

function p.phraseLink(code) return h.get(code, "phraseLink") end

function h.get(code, prop) code = string.lower(code) if code == "series" then return series[prop] end local title = cache.titlesByCode[code] return title and title[prop] end

p.Schemas = { enum = { options = { type = "record", properties = { {					name = "includeSeries", type = "boolean", desc = "If true, then  is included at the very beginning of the list.", },				{					name = "includeCompilations", type = "boolean", desc = "If true, then compilations such as the Goddess Trilogy books are included in the list.", },				{					name = "includeGroups", type = "boolean", desc = "If true, then groups of games such as and  are included in the list.", },			},		},	},	enumGames = { includeSeries = { type = "boolean", desc = "If true, then  is included at the very beginning of the list.", },	} }

p.Templates = { ["Franchise/Store Game"] = { purpose = "Each instance of this template describes an entry in The Legend of Zelda franchise (or a game related to the franchise).", storesData = "Data:Franchise", format = "block", indent = 1, boilerplate = { before = "", },		paramOrder = {"code", "article", "shortName", "logo", "releaseDate", "canonicity", "type", "link", "display", "graphics", "family", "remakeOf", "supersededBy"}, params = { code = { required = true, type = "string", desc = "A string that uniquely identifies the game. Usually an initialism of its subtitle.", trim = true, nilIfEmpty = true, },			article = { required = true, type = "wiki-page-name", desc = "The wiki page for the game.", trim = true, nilIfEmpty = true, },			shortName = { required = true, type = "string", desc = "The name for the game used in categories such as Category:Items in Link's Awakening (Nintendo Switch). Usually the game's subtitle, possibly with a parenthetical disambiguator.", trim = true, nilIfEmpty = true, },			logo = { required = true, type = "wiki-file-name", desc = "Filename for the game's logo. If no such logo is available, use the logo of the associated franchise, or the game's box art.", trim = true, nilIfEmpty = true, },			releaseDate = { type = "date", desc = "The date of the game's initial release in North America, in YYYY-MM-DD format. Leave blank for future games. If not released in North America, use the earliest release date of any region (most likely Japan).", trim = true, nilIfEmpty = true, },			canonicity = { -- required = true, type = "string", enum = {"canon", "ambiguous", "non-canon"}, desc = "The title's canon status.", trim = true, nilIfEmpty = true, },			type = { type = "string", enum = {"main", "remake", "spin-off"}, desc = "Leave blank for cross-overs and cameos. Used to group games on the Main Page.", trim = true, nilIfEmpty = true, },			link = { type = "content", desc = "Wikitext used when linking the game in articles. By default, this is derived from  and  . Should be left blank unless the game's link is a special case (see examples).", trim = true, nilIfEmpty = true, },			display = { type = "content", desc = "Wikitext used when mentioning the game in articles, sans link. By default, this is derived from . Should be left blank unless the game's display text is a special case (see examples).", trim = true, nilIfEmpty = true, },			graphics = { type = "string", enum = {"2D", "3D", "4D"}, desc = 'Indicates whether the game is 2D or 3D. Used by Module:File for image handling, among other things. For live-action games, put down "4D".', -- TODO: more specific trim = true, nilIfEmpty = true, },			family = { type = "string", desc = "Identifies the game as being part of a sub-group in the franchise. Leave blank for canon games. This is used to group certain games on the Main Page", trim = true, nilIfEmpty = true, },			remakeOf = { --enum = p.enum, type = "string", desc = "The code of the game that this game is a remake of, if any.", trim = true, nilIfEmpty = true, },			supersededBy = { --enum = p.enum, type = "string", desc = "The name of the game that supersedes this one in terms of canon.", trim = true, nilIfEmpty = true, },		},		examples = { {				code = "LA", article = "The Legend of Zelda: Link's Awakening", shortName = "Link's Awakening", logo = "File:LA English Logo 2.png", releaseDate = "1993-06-06", canonicity = "canon", type = "main", link = "", display = "", graphics = "2D", family = "", remakeOf = "", supersededBy = "LANS", },			{				code = "LANS", article = "The Legend of Zelda: Link's Awakening (Nintendo Switch)", shortName = "Link's Awakening (Nintendo Switch)", logo = "File:LANS English Logo.png", releaseDate = "2019-09-20", canonicity = "canon", type = "remake", link = "Link's Awakening for Nintendo Switch.", display = "Link's Awakening for Nintendo Switch", graphics = "3D", family = "", remakeOf = "LA", supersededBy = "", },			{				code = "FPTRR", article = "Freshly-Picked Tingle's Rosy Rupeeland", shortName = "Freshly-Picked Tingle's Rosy Rupeeland", logo = "File:TRRLogo.png", releaseDate = "2006-09-02", canonicity = "ambiguous", type = "spin-off", link = "", display = "", graphics = "2D", family = "Tingle", remakeOf = "", supersededBy = "", },			{				code = "Skyrim", article = "The Elder Scrolls V: Skyrim", shortName = "Skyrim", logo = "File:Skyrim Logo.png", releaseDate = "2017-11-17", canonicity = "non-canon", type = "", link = "", display = "", graphics = "3D", family = "", remakeOf = "", supersededBy = "", },		},	},	["Franchise/Store Book"] = { purpose = "Each instance of this template describes a The Legend of Zelda book, comic, or manga.", storesData = "Data:Franchise", format = "block", indent = 1, boilerplate = { before = "", },		paramOrder = {"code", "article", "shortName", "logo", "releaseDate", "canonicity", "type", "link", "display", "phraseLink", "authors", "illustrators", "basedOn"}, params = { code = { required = true, type = "string", desc = "A string that uniquely identifies the book. Usually an initialism of its subtitle.", trim = true, nilIfEmpty = true, },			article = { required = true, type = "wiki-page-name", desc = "The wiki page for the book, comic, or manga.", trim = true, nilIfEmpty = true, },			shortName = { required = true, type = "string", desc = "The name for the book used in categories such as Characters in Majora's Mask (Himekawa). Usually the book's subtitle, possibly with a parenthetical disambiguator of the primary author's last name.", trim = true, nilIfEmpty = true, },			logo = { required = true, type = "wiki-file-name", desc = "Filename for the logo of the book's publisher. If no such logo is available, use the book's cover or an illustration in the front matter.", trim = true, nilIfEmpty = true, },			releaseDate = { type = "date", desc = "The date of the book's initial release in North America, in YYYY-MM-DD format. Leave blank for unreleased books. If not released in North America, use the earliest release date of any region (most likely Japan).", trim = true, nilIfEmpty = true, },			canonicity = { required = true, type = "string", enum = {"canon", "ambiguous", "non-canon"}, desc = "The title's canon status.", trim = true, nilIfEmpty = true, },			type = { type = "string", enum = {"book", "comic", "manga"}, desc = "Identifies the type of book.", trim = true, nilIfEmpty = true, },			link = { type = "content", desc = "Wikitext used when linking the book in article infoboxes (use  for article content). By default, this is derived from   and  . Should be left blank unless the link is a special case.", trim = true, nilIfEmpty = true, },			display = { type = "content", desc = "Wikitext used when mentioning the book in articles, sans link. By default, this is derived from . Should be left blank unless the display text is a special case.", trim = true, nilIfEmpty = true, },			phraseLink = { type = "content", desc = "Wikitext to be used when linking to a book. By default, this is derived from,   and  . Should be left blank unless the link is a special case.", trim = true, nilIfEmpty = true, },			authors = { type = "string", desc = "Comma-separated list of the book's authors.", trim = true, nilIfEmpty = true, },			illustrators = { type = "string", desc = "Comma-separted list of the book's illustrators.", trim = true, nilIfEmpty = true, },			basedOn = { type = "string", --enum = p.enum, desc = "The game that this book is based on.", trim = true, nilIfEmpty = true, },		},		examples = { {				code = "OoT (Himekawa)", article = "The Legend of Zelda: Ocarina of Time (Himekawa)", shortName = "Ocarina of Time (Himekawa)", logo = "File:Viz Media Logo.png", releaseDate = "2008-10-08", canonicity = "non-canon", type = "manga", link = "", display = "", phraseLink = "", authors = "Akira Himekawa", illustrators = "Akira Himekawa", basedOn = "OoT", },			{				code = "LatPoD", article = "Link and the Portal of Doom", shortName = "Link and the Portal of Doom", logo = "File:Scholastic Logo.png", releaseDate = "2006", canonicity = "non-canon", type = "book", link = "", display = "", phraseLink = "", authors = "Tracey West", illustrators = "", basedOn = "", }		}	},	["Franchise/Store TV"] = { purpose = "Each instance of this template describes a The Legend of Zelda-related TV show.", storesData = "Data:Franchise", format = "block", indent = 1, boilerplate = { before = "", },		paramOrder = {"code", "article", "shortName", "logo", "releaseDate", "canonicity", "type", "link", "display"}, params = { code = { required = true, type = "string", desc = "A string that uniquely identifies the TV series. Usually an initialism of its title.", trim = true, nilIfEmpty = true, },			article = { required = true, type = "wiki-page-name", desc = "The wiki page for the TV series.", trim = true, nilIfEmpty = true, },			shortName = { required = true, type = "string", desc = "The name for the TV series used in categories such as Category:The Legend of Zelda TV Series Screenshots.", trim = true, nilIfEmpty = true, },			logo = { required = true, type = "wiki-file-name", desc = "Filename for the TV series' logo. If no such logo is available, use the series' title card.", trim = true, nilIfEmpty = true, },			releaseDate = { type = "date", desc = "The date of the TV series' first air date in North America, in YYYY-MM-DD format. If not released in North America, use the earliest release date of any region (most likely Japan).", trim = true, nilIfEmpty = true, },			canonicity = { required = true, type = "string", enum = {"non-canon"}, desc = "The title's canon status.", trim = true, nilIfEmpty = true, },			type = { type = "string", enum = {"animated"}, desc = "Identifies the type of TV series .", trim = true, nilIfEmpty = true, },			link = { type = "content", desc = "Wikitext used when linking the TV series in articles. By default, this is derived from  and  . Should be left blank unless the link is a special case.", trim = true, nilIfEmpty = true, },			display = { type = "content", desc = "Wikitext used when mentioning the TV series in articles, sans link. By default, this is derived from . Should be left blank unless the display text is a special case.", trim = true, nilIfEmpty = true, },		},		examples = { {				code = "TLoZ (TV Series)", article = "The Legend of Zelda (TV Series)", shortName = "The Legend of Zelda TV Series", logo = "File:TLoZ TV Series Logo.png", releaseDate= "1989-09-08", canonicity = "non-canon", type = "animated", link = "The Legend of Zelda TV series", display = "The Legend of Zelda TV series", },			{				code = "TMoL", article = "The Legend of Zelda: The Misadventures of Link", shortName = "The Misadventures of Link", logo = "File:Misadventures Link logo2.png", releaseDate = "2013-11-01", canonicity = "non-canon", type = "animated", link = "", display = "", },		}	},	["Franchise/Store Compilation"] = { purpose = "Describes Zelda publications that are not franchise entires per se, but rather compilations of information from other franchise entries.", storesData = "Data:Franchise", format = "block", indent = 1, boilerplate = { before = "", },		paramOrder = {"code", "article", "shortName", "logo", "releaseDate", "canonicity", "link", "display", "titles"}, params = { code = { required = true, type = "string", desc = "A string that uniquely identifies the compilation. Usually an initialism of its subtitle.", trim = true, nilIfEmpty = true, },			article = { required = true, type = "wiki-page-name", desc = "The wiki page for the compilation.", trim = true, nilIfEmpty = true, },			shortName = { required = true, type = "string", desc = "The name for the compilation used in article text. Generally its subtitle.", trim = true, nilIfEmpty = true, },			logo = { required = true, type = "wiki-file-name", desc = "Filename for the compilation's logo. If no such logo is available, use its cover.", trim = true, nilIfEmpty = true, },			releaseDate = { type = "date", desc = "The date of the compilation's first publication in North America, in YYYY-MM-DD format. If not released in North America, use the earliest release date of any region (most likely Japan).", trim = true, nilIfEmpty = true, },			canonicity = { required = true, type = "string", enum = {"canon", "ambiguous", "non-canon"}, desc = "The title's canon status.", trim = true, nilIfEmpty = true, },			link = { type = "content", desc = "Wikitext used when linking the compilation in articles. By default, this is derived from  and  . Should be left blank unless the link is a special case.", trim = true, nilIfEmpty = true, },			display = { type = "content", desc = "Wikitext used when mentioning the compilation in articles, sans link. By default, this is derived from . Should be left blank unless the display text is a special case.", trim = true, nilIfEmpty = true, },			titles = { required = true, type = "string", desc = "Comma-separated list of franchise entries covered in the compilation.", trim = true, nilIfEmpty = true, }		},		examples = { {				code = "E", article = "The Legend of Zelda: Encyclopedia", shortName = "Encyclopedia", logo = "File:The Legend of Zelda Encyclopedia Cover.png", releaseDate= "2018-06-19", canonicity = "canon", link = "", display = "", titles = "TLoZ, TAoL, ALttP, LA, LADX, LANS, OoT, OoT3D, MM, MM3D, OoS, OoA, FS, FSAE, TWW, TWWHD, FSA, TMC, TP, TPHD, PH, ST, SS, ALBW, TFH", }		}	},	["Franchise/Store Group"] = { purpose = "Describes a title that represents multiple games. It can be a published collection of games (e.g., ), or a collective term for a pair of games (e.g. ). Not to be confused with Template:Franchise/Store Compilation.", storesData = "Data:Franchise", format = "block", indent = 1, boilerplate = { before = "", },		paramOrder = {"code", "article", "shortName", "logo", "releaseDate", "canonicity", "link", "display", "games"}, params = { code = { required = true, type = "string", desc = "A string that uniquely identifies the game group. Usually an initialism of its subtitle.", trim = true, nilIfEmpty = true, },			article = { required = true, type = "wiki-page-name", desc = "The wiki page for the game group.", trim = true, nilIfEmpty = true, },			shortName = { required = true, type = "string", desc = "The name for the game group used in article text. Generally its subtitle.", trim = true, nilIfEmpty = true, },			logo = { required = true, type = "wiki-file-name", desc = "Filename for the group's logo.", trim = true, nilIfEmpty = true, },			releaseDate = { type = "date", desc = "The date of the group's first publication in North America, in YYYY-MM-DD format. If not released in North America, use the earliest release date of any region (most likely Japan).", trim = true, nilIfEmpty = true, },			canonicity = { required = true, type = "string", enum = {"canon", "ambiguous", "non-canon"}, desc = "The title's canon status.", trim = true, nilIfEmpty = true, },			link = { type = "content", desc = "Wikitext used when linking the group in articles. By default, this is derived from  and  . Should be left blank unless the link is a special case.", trim = true, nilIfEmpty = true, },			display = { type = "content", desc = "Wikitext used when mentioning the group in articles, sans link. By default, this is derived from . Should be left blank unless the display text is a special case.", trim = true, nilIfEmpty = true, },			games = { required = true, type = "string", desc = "Comma-separated list of games included in the group.", trim = true, nilIfEmpty = true, }		},		examples = { {				code = "CE", article = "The Legend of Zelda: Collector's Edition", shortName = "Collector's Edition", logo = "File:CE Logo.png", releaseDate= "2003-11-17", canonicity = "canon", link = "", display = "", games = "TLoZ, TAoL, OoT, MM", },		},	}, }

p.Documentation = { sections = { {			heading = "All Media", section = { enum = { desc = "See also .", params = {"options"}, returns = "An array of all codes in canon order, plus a  key so that it can be used for documentation and validation.", cases = { outputOnly = true, {							snippet = 1, expect = {"TLoZ", "TAoL", "ALttP", "LA", "LADX", "LANS", "OoT", "OoT3D", "MM", "MM3D"}, },						{							snippet = 2, expect = "Data:Franchise", },						{							snippet = "IncludeSeries", desc = "When  is true, then   is the first item in the enum.", expect = {"Series", "TLoZ", "TAoL"}, },						{							snippet = "IncludeCompilations", desc = "When  is true, then books such as  are in the list.", expect = true, },						{							snippet = "IncludeGroups", desc = "When  is true, then collective terms such as  are included in the list.", expect = true, },					},				},				shortName = { params = {"code"}, returns = "Short name for franchise title used in category names. Usually the subtitle.", cases = { {							args = {"LA"}, expect = "Link's Awakening", },						{							args = {"la"}, expect = "Link's Awakening" },						{							args = {"LANS"}, expect = "Link's Awakening (Nintendo Switch)", },						{							args = {"LA (Cagiva)"}, expect = "Link's Awakening (Cagiva)", },						{							args = {"E"}, expect = "Encyclopedia", },						{							args = {"ALttP&FS"}, expect = "A Link to the Past & Four Swords", },						{							args = {"Series"}, expect = "The Legend of Zelda Series" },						{							args = {"fakeGame"}, expect = nil, },					}				},				link = { params = {"code"}, returns = "Formatted link used in infoboxes and so on.", cases = { {							args = {"LA"}, expect = "Link's Awakening", },						{							args = {"la"}, expect = "Link's Awakening", },						{							args = {"LADX"}, expect = "Link's Awakening DX", },						{							args = {"LANS"}, expect = "Link's Awakening for Nintendo Switch", },						{							desc = "For books, comics and manga, see also .", args = {"LA (Cagiva)"}, expect = "Link's Awakening (Cagiva)", },						{							args = {"E"}, expect = "Encyclopedia", },						{							args = {"ALttP&FS"}, expect = "A Link to the Past & Four Swords" },						{							args = {"Series"}, expect = "The Legend of Zelda series" },						{							args = {"fakeGame"}, expect = nil, },					}				},				isCanon = { params = {"code"}, returns = "True if title is canon, else false.", cases = { {							args = {"LANS"}, expect = true, },						{							args = {"lans"}, expect = true, },						{							args = {"CoH"}, expect = false, },						{							args = {"SSBU"}, expect = false, },						{							args = {"E"}, expect = true, },						{							args = {"Series"}, expect = true, },					},				},				display = { params = {"code"}, returns = "Formatted text for the title.", cases = { {							args = {"LA"}, expect = "Link's Awakening", },						{							args = {"la"}, expect = "Link's Awakening", },						{							args = {"LANS"}, expect = "Link's Awakening for Nintendo Switch", },						{							args = {"E"}, expect = "Encyclopedia" },						{							args = {"ALttP&FS"}, expect = "A Link to the Past & Four Swords", },						{							args = {"Series"}, expect = "The Legend of Zelda series" },						{							args = {"fakeGame"}, expect = nil, },					}				},				logo = { params = {"code"}, returns = "Filename for the title's logo.", cases = { {							args = {"LANS"}, expect = "File:LANS English Logo.png", },						{							args = {"lans"}, expect = "File:LANS English Logo.png" },						{							args = {"E"}, expect = "File:The Legend of Zelda Encyclopedia Cover.png" },						{							args = {"Series"}, expect = "File:Zelda Logo TP.png" },						{							args = {"fakeGame"}, expect = nil }					}				},				article = { params = {"code"}, returns = "Wiki article name for the title", cases = { outputOnly = true, {							args = {"LA"}, expect = "The Legend of Zelda: Link's Awakening", },						{							args = {"la"}, expect = "The Legend of Zelda: Link's Awakening", },						{							args = {"LANS"}, expect = "The Legend of Zelda: Link's Awakening (Nintendo Switch)", },						{							args = {"TAoL"}, expect = "Zelda II: The Adventure of Link", },						{							args = {"TLoZ"}, expect = "The Legend of Zelda", },						{							args = {"Series"}, expect = "The Legend of Zelda (Series)", },						{							args = {"E"}, expect = "The Legend of Zelda: Encyclopedia" },						{							args = {"SSB4"}, expect = "Super Smash Bros. for Nintendo 3DS/Wii U", },					},				},				canonicity = { params = {"code"}, returns = "A string:,  , or  .", cases = { outputOnly = true, {							args = {"LA"}, expect = "canon", },						{							args = {"la"}, expect = "canon", },						{							args = {"CoH"}, expect = "ambiguous", },						{							args = {"LA (Cagiva)"}, expect = "non-canon", },						{							args = {"E"}, expect = "canon", },						{							args = {"fake"}, expect = nil, }					},				},				releaseDate = { params = {"code"}, returns = 'The "main" release date for a title.', cases = { outputOnly = true, {							args = {"LA"}, expect = "1993-08-06", },						{							args = {"LANS"}, expect = "2019-09-20", },						{							args = {"LA (Cagiva)"}, expect = "1994-05-01", },						{							args = {"E"}, expect = "2018-06-19", },						{							args = {"ALttP&FS"}, expect = "2002-12-02", },						{							args = {"Series"}, expect = nil },						{							args = {"fakeGame"}, expect = nil, },					},				},			},		},		{			heading = "Games", section = { enumGames = { params = {"includeSeries"}, returns = "An array of all game codes in canon order, plus a  key so that it can be used for documentation and validation.", cases = { outputOnly = true, {							snippet = "1", expect = {"TMC", "TP", "TPHD"}, },						{							snippet = "2", expect = "Data:Franchise", },						{							snippet = "IncludeSeries", desc = "When  is true, then   is the first item in the enum.", expect = {"Series", "TLoZ", "TAoL"}, },					},				},				family = { params = {"code"}, returns = "A grouping name used for certain non-canon games on the Main Page.", cases = { outputOnly = true, {							args = {"OoT"}, expect = "", },						{							args = {"LCT"}, expect = "", },						{							args = {"FPTRR"}, expect = "Tingle", },						{							args = {"HWDE"}, expect = "Hyrule Warriors", },					},				},				graphics = { params = {"code"}, returns = "A string:  or  .", cases = { outputOnly = true, {							args = {"LA"}, expect = "2D", },						{							args = {"la"}, expect = "2D", },						{							args = {"LANS"}, expect = "3D", },						{							args = {"fake"}, expect = nil, },					},				},				hasRemakes = { params = {"code"}, returns = "True if game has at least one remake, remaster, or enhanced port. Else false.", cases = { {							args = {"LA"}, expect = true, },						{							args = {"la"}, expect = true, },						{							args = {"ST"}, expect = false },						{							args = {"fakeGame"}, expect = false, },					},				},				isRemake = { params = {"code"}, returns = "True if game is a remake, remaster, or enhanced port. Else false.", cases = { {							args = {"LANS"}, expect = true, },						{							args = {"lans"}, expect = true, },						{							args = {"LA"}, expect = false, },					},				},				remakes = { params = {"code"}, returns = "List of remakes for a specific game, or a table of all remakes if no game specified", cases = { {							args = {"LA"}, expect = {"LADX", "LANS"}, },						{							args = {"la"}, expect = {"LADX", "LANS"}, },						{							args = {"ST"}, expect = {} },						{							args = {"fake"}, expect = {}, },					},				},			},		},		{			heading = "Books", section = { phraseLink = { params = {"code"}, returns = "Formatted link to page and authors.", cases = { {							args = {"TLoZ (Ran)"}, expect = "The Legend of Zelda manga by Maru Ran", },						{							args = {"tloz (ran)"}, expect = "The Legend of Zelda manga by Maru Ran", },						{							args = {"TLoZAOV"}, expect = "‟The Legend of Zelda„ An Original Version", },						{							args = {"fake"}, expect = nil, },						{							desc = "Compliations such as are not included in this.", args = {"E"}, expect = nil, },					},				},			},		},	}, }

return p