Anonymous
×
Create a new article
Write your page title here:
We currently have 97 articles on The Dream Shrine. Type your article name above or click on one of the titles below and start writing!



The Dream Shrine

Documentation for this module may be created at Module:Franchise/doc

local p = {}
local h = {}

local utilsString = require("Module:UtilsString")
local utilsTable = require("Module:UtilsTable")

local cache = mw.loadData("Module:Franchise/Cache")

local CATEGORY_INVALID_ARGS = "Category:"..require("Module:Constants/category/invalidArgs")

-- 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)|''The Legend of Zelda'' series]]",
	display = "''The Legend of Zelda'' series",
	canonicity = "canon",
	type = "main",
	code = "Series",
}

function p.Article(frame)
	return h.templateQuery("article", frame)
end
function p.BaseGame(frame)
	return h.templateQuery("baseGame", frame)
end
function p.Display(frame)
	return h.templateQuery("display", frame)
end
function p.Link(frame)
	return h.templateQuery("link", frame)
end
function p.ShortName(frame)
	return h.templateQuery("shortName", frame)
end
function h.templateQuery(fn, frame)
	local args = frame.args
	local game, nowarn = args[1], args.nowarn
	if game == nil or game == "" then
		return "", h.error("No game provided", CATEGORY_INVALID_ARGS, nowarn)
	end
	game = utilsString.trim(game)
	local value = p[fn](game)
	if not value then
		return "", h.error(string.format("Invalid entry <code>%s</code>", game), CATEGORY_INVALID_ARGS, nowarn, "See [[Data:Franchise]] for a list of valid entries.")
	end
	local correctGameCode = p.code(game)
	if game ~= correctGameCode then
		local utilsError = require("Module:UtilsError")
		utilsError.warn(string.format("<code>%s</code> should be written as <code>%s</code>", game, correctGameCode))
		return value, "[["..CATEGORY_INVALID_ARGS.."]]"
	else
		return value
	end
end
function h.error(errorMsg, category, nowarn, additionalWarningInfo)
	local utilsError = require("Module:UtilsError")
	local warnMsg = not nowarn and additionalWarningInfo and (errorMsg.. ". ".. additionalWarningInfo)
	return utilsError.error(errorMsg, warnMsg).."[["..category.."]]"
end

-- [[Guidelines:Main]]
function p.ListTitlesByCanonicity(frame)
	local utilsLayout = require("Module:UtilsLayout")

	local canonicity = frame.args[1]
	local rows = {}
	for i, code in ipairs(p.enum()) do
		if canonicity == p.canonicity(code) then
			local link = p.link(code)
			local releaseDate = p.releaseDate(code)
			table.insert(rows, {link, releaseDate})
		end
	end
	local wikitable = utilsLayout.table({
		sortable = true,
		headers = {"Media", "Release Date"},
		rows = rows,
	})
	return wikitable
end
function p.ListAllTitles(frame)
	local utilsLayout = require("Module:UtilsLayout")
	local canonicityStatuses = {
		["canon"] = "Canon",
		["non-canon"] = "Non-canon",
		["ambiguous"] = "Ambiguously-canon",
	}
	
	local rows = {}
	for i, code in ipairs(p.enum()) do
		local link = p.link(code)
		local releaseDate = p.releaseDate(code)
		local canonicity = p.canonicity(code)
		local canonicityStatus = canonicityStatuses[canonicity]
		local supersededBy = h.get(code, "supersededBy")
		if canonicityStatus and supersededBy ~= nil and supersededBy ~= "" then
			local supersederLink = p.link(supersededBy)
			canonicityStatus = canonicityStatus .. string.format(" <small>(superseded by %s)</small>", supersederLink)
		end
		table.insert(rows, {link, code, releaseDate, canonicityStatus})
	end
	local rows = utilsTable.sortBy(rows, 3) -- sort by release date
	local wikitable = utilsLayout.table({
		sortable = true,
		headers = {"Media", "Abbreviation", "Release Date", "Status"},
		rows = rows,
	})
	return wikitable
end

-- Template:Franchise/Store *
function p.AddToPreview(frame)
	-- Performance optimization
	local utilsArg = require("Module:UtilsArg")
	local utilsVar = require("Module:UtilsVar")
	local utilsMarkup = require("Module:UtilsMarkup")
	local templateData = mw.loadData("Module:Franchise/TemplateData")
	local orderCounter = utilsVar.counter("releaseOrder")
	
	local entryType = frame.args[1]
	local args, err = utilsArg.parse(frame:getParent().args, templateData["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.releaseOrder = orderCounter.value()
	else
		args.releaseOrder = "—"
	end
	if entryType == "Book" then
		args.phraseLink = p.derivePhraseLink(args)
	end
	utilsVar.add("rows", args)
end
function p.StoreOrder(frame)
	-- Performance optimization
	local utilsVar = require("Module:UtilsVar")
	local orderCounter = utilsVar.counter("releaseOrder")
	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 args.display ~= nil and 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 args.display ~= nil and args.display ~= "" then
		return args.link
	elseif entryType == "Book" then
		return h.deriveBookFields(args).link
	else
		return ("''[[%s|%s]]''"):format(args.article, args.shortName)
	end
end
function p.derivePhraseLink(args)
	return h.deriveBookFields(args).phraseLink
end

function p.Preview(frame)
	-- Performance optimization
	local utilsMarkup = require("Module:UtilsMarkup")
	local utilsLayout = require("Module:UtilsLayout")
	local utilsVar = require("Module:UtilsVar")
	
	local previewColumns = {
		common = {"releaseOrder", "code", "link", "display", "logo", "releaseDate", "canonicity"},
		Game = {"type", "graphics", "family", "remakeOf", "supersededBy"},
		Book = {"type", "phraseLink", "publisher", "authors", "basedOn"},
		Nonfiction = {"publisher", "titles"},
		TV = {"type"},
		Group = {"games"},
	}
	previewColumns.Game = utilsTable.concat(previewColumns.common, previewColumns.Game)
	previewColumns.Book = utilsTable.concat(previewColumns.common, previewColumns.Book)
	previewColumns.TV = utilsTable.concat(previewColumns.common, previewColumns.TV)
	previewColumns.Nonfiction = utilsTable.concat(previewColumns.common, previewColumns.Nonfiction)
	previewColumns.Group = utilsTable.concat(previewColumns.common, previewColumns.Group)
	
	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 = previewColumns.common,
		rows = utilsTable.map(rows, utilsTable._toArray(previewColumns.common, ""))
	})
	local games = utilsLayout.table({
		sortable = true,
		headers = previewColumns.Game,
		rows = utilsTable.map(rowGroups.Game, utilsTable._toArray(previewColumns.Game, ""))
	})
	local books = utilsLayout.table({
		sortable = true,
		headers = previewColumns.Book,
		rows = utilsTable.map(rowGroups.Book, utilsTable._toArray(previewColumns.Book, ""))
	})
	local tv = utilsLayout.table({
		sortable = true,
		headers = previewColumns.TV,
		rows = utilsTable.map(rowGroups.TV, utilsTable._toArray(previewColumns.TV, ""))
	})
	local nonfiction = utilsLayout.table({
		sortable = true,
		headers = previewColumns.Nonfiction,
		rows = utilsTable.map(rowGroups.Nonfiction or {}, utilsTable._toArray(previewColumns.Nonfiction, ""))
	})
	local groups = utilsLayout.table({
		sortable = true,
		headers = previewColumns.Group,
		rows = utilsTable.map(rowGroups.Group or {}, utilsTable._toArray(previewColumns.Group, ""))
	})
	local preview = utilsLayout.tabs({
		{
			label = "All Titles",
			content = titles,
		},
		{
			label = "Games",
			content = games,
		},
		{
			label = "Books (fiction)",
			content = books,
		},
		{
			label = "Books (nonfiction)",
			content = nonfiction
		},
		{
			label = "Movies and TV Shows",
			content = tv,
		},
		{
			label = "Groups",
			content = groups,
		}
	}, { columns = 15 })
	return preview
end

function p.UploadField(frame)
	-- Performance optimization
	local utilsMarkup = require("Module:UtilsMarkup")
	local utilsVar = require("Module:UtilsVar")
	
	local rows = utilsVar.get("rows")
	local groups = utilsTable.groupBy(rows, "entryType")
	local mainGames, otherGames = utilsTable.partition(groups["Game"], {
		canonicity = "canon"
	})
	local gamesByBaseGame = utilsTable.groupBy(mainGames, function(game)
		return p.baseGame(game.code)
	end)
	local books = groups["Book"]
	local tvShows = groups["TV"]
	
	local sortedMainGames = {}
	for _, mainGame in ipairs(utilsTable.reverse(mainGames)) do
		for _, game in ipairs(gamesByBaseGame[mainGame.code] or {}) do
			table.insert(sortedMainGames, game)
		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 ListPages = require("Module:List Pages")
	local utilsString = require("Module:UtilsString")

	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|%s]]"):format(args.article, display)
		local authors = ListPages.main(utilsString.split(args.authors))
		phraseLink = ("[[%s|''%s'' %s]] by %s"):format(args.article, subtitle, args.type, authors)
	else
		display = ("''%s''"):format(args.shortName)
		link = ("''[[%s|%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.includeNonfiction then
		local codes = utilsTable.map(cache.nonfiction, "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 Fighter 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]) 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.releaseOrder(code)
	local releaseOrder = h.get(code, "releaseOrder")
	return releaseOrder and tonumber(releaseOrder)
end

function p.code(code)
	return h.get(code, "code")
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(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.baseGame(code)
	local baseGames = h.get(code, "remakeOf")
	if baseGames == nil then -- game not found
		return nil
	elseif baseGames == "" then -- game has no remakes
		return code
	else
		return utilsString.split(baseGames)[1]
	end
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)
	local remakeOf = h.get(code, "remakeOf")
	return remakeOf ~= nil and remakeOf ~= ""
end

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

function p.superseder(code)
	local supersededBy = h.get(code, "supersededBy")
	if supersededBy == "" then
		supersededBy = nil
	end
	return supersededBy
end

-- QUERIES: BOOKS
function p.publisher(code)
	return h.get(code, "publisher")
end

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]
	if not title then
		return nil -- we return nil here to indicate an invalid code
	else
		return title[prop] or "" -- we return "" here to indicate the absence of an optional property on a valid code
	end
end

local nowarnParam = {
	desc = "<p>If present, the template will not issue an [[Module:Error|editor warning]] when <code>game</code> is invalid. Use this when a template needs custom error handling (see examples).</p><p>However, an editor warning will still be issued if a game code is written with incorrect casing (e.g. <code>oot</code> instead of <code>OoT</code>)</p>",
}

function p.Documentation()
	return {
		sections = {
			{
				heading = "Template functions",
				section = {
					Article = {
						frameParams = {
							[1] = {
								name = "game",
								required = true,
								desc = "The code for a game or other entry in [[Data:Franchise]].",
							},
							nowarn = nowarnParam,
						},
						cases = {
							resultOnly = true,
							{
								args = {"OoT"},
							},
							{
								args = {"OoT (Himekawa)"},
							},
							{
								desc = "Error handling",
								args = {"oot"},
							},
							{
								args = {"notAGame"},
							},
							{
								args = {""},
							},
							{
								input = "{{#iferror:{{#invoke:Franchise|Article|invalid game}}|custom error handling}}",
							},
						},
					},
					BaseGame = {
						frameParams = {
							[1] = {
								name = "game",
								required = true,
								desc = "The code for a game entry in [[Data:Franchise]].",
							},
							nowarn = nowarnParam,
						},
						cases = {
							resultOnly = true,
							{
								args = {"TWW"},
							},
							{
								args = {"TWWHD"},
							},
							{
								desc = "Error handling",
								args = {"notAGame"},
							},
							{
								args = {"twwhd"},
							},
							{
								args = {""},
							},
							{
								input = "{{#iferror:{{#invoke:Franchise|BaseGame|invalid game}}|custom error handling}}",
							},
						},
					},
					Display = {
						frameParams = {
							[1] = {
								name = "game",
								required = true,
								desc = "The code for a game or other Zelda-related title defined at [[Data:Franchise]].",
							},
							nowarn = nowarnParam,
						},
						cases = {
							resultOnly = true,
							{
								args = {"LA"},	
							},
							{
								args = {"LANS"},
							},
							{
								args = {"LA (Cagiva)"},
							},
							{
								args = {"invalid game"},
							},
							{
								args = {""},
							},
						},
					},
					Link = {
						frameParams = {
							[1] = {
								name = "game",
								required = true,
								desc = "The code for a game or other Zelda-related title defined at [[Data:Franchise]].",
							},
							nowarn = nowarnParam,
						},
						cases = {
							resultOnly = true,
							{
								args = {"OoT"},
							},
							{
								args = {"OoT (Himekawa)"},
							},
							{
								desc = "Error handling",
								args = {"oot"},
							},
							{
								args = {"notAGame"},
							},
							{
								args = {""},
							},
							{
								input = "{{#iferror:{{#invoke:Franchise|Link|invalid game}}|custom error handling}}",
							},
						},
					},
					ShortName = {
						frameParams = {
							[1] = {
								name = "game",
								required = true,
								desc = "The code for a game or other Zelda-related title defined at [[Data:Franchise]].",
							},
							nowarn = nowarnParam,
						},
						cases = {
							resultOnly = true,
							{
								args = {"OoT"},	
							},
							{
								args = {"OoT (Himekawa)"},
							},
							{
								args = {"E"},
							},
							{
								desc = "Error handling",
								args = {"oot"},
							},
							{
								args = {"notAGame"},
							},
							{
								args = {""},
							},
							{
								desc = "Custom error handling",
								input = "{{#iferror:{{#invoke:Franchise|ShortName|invalid game}}|[[Dodongo]]|[[Dodongo#{{#invoke:Franchise|ShortName|invalid game}}]]}}",
							},
							{
								input = "{{#iferror:{{#invoke:Franchise|ShortName|oot}}|[[Dodongo]]|[[Dodongo#{{#invoke:Franchise|ShortName|oot}}]]}}",
							},
							{
								input = "{{#iferror:{{#invoke:Franchise|ShortName|OoT}}|[[Dodongo]]|[[Dodongo#{{#invoke:Franchise|ShortName|OoT}}]]}}",
							},
						}
					}
				},
			},
			{
				heading = "Module functions - all media",
				section = {
					enum = {
						desc = "See also {{Sect|enumGames}}.",
						params = {"options"},
						returns = "An array of all codes in [[Guidelines:Main#Canon_Order|canon order]], plus a <code>reference</code> key so that it can be used for [[Module:Documentation|documentation]] and [[Module:UtilsArg|validation]].",
						cases = {
							outputOnly = true,
							{
								snippet = 1,
								expect = {"TLoZ", "TAoL", "ALttP", "LA", "LADX", "LANS", "OoT"},
							},
							{
								snippet = 2,
								expect = "[[Data:Franchise]]",
							},
							{
								snippet = "IncludeSeries",
								desc = "When <code>includeSeries</code> is true, then <code>Series</code> is the first item in the enum.",
								expect = {"Series", "TLoZ", "TAoL"},
							},
							{
								snippet = "IncludeNonfiction",
								desc = "When <code>includeNonfiction</code> is true, then books such as {{E}} are in the list.",
								expect = true,
							},
							{
								snippet = "IncludeGroups",
								desc = "When <code>includeGroups</code> is true, then collective terms such as {{ALttP&FS}} are included in the list.",
								expect = true,
							},
						},
					},
					releaseOrder = {
						params = {"code"},
						returns = "Position of the franchise title in the [[Guidelines:Main#Canon Order|Canon Order]].",
						cases = {
							{
								args = {"LA"},
								expect = 4,
							},
							{
								args = {"LADX"},
								expect = 5,
							},
							{
								args = {"Not a Game"},
								expect = nil,
							},
							{
								desc = "Non-ficition books such as {{E}} have no position in the canon order.",
								args = {"E"},
								expect = nil,
							},
						},
					},
					code = {
						params = {"code"},
						returns = "The same code but correctly formatted, or <code>nil</code> if no such code exists",
						cases = {
							outputOnly = true,
							{
								args = {"alttp"},
								expect = "ALttP",
							},
							{
								args = {"fakegame"},
								expect = nil,
							},
						},
					},
					shortName = {
						params = {"code"},
						returns = "Short name for franchise title used in [[:Category:Games|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 = "''[[The Legend of Zelda: Link's Awakening|Link's Awakening]]''",
							},
							{
								args = {"la"},
								expect = "''[[The Legend of Zelda: Link's Awakening|Link's Awakening]]''",
							},
							{
								args = {"LADX"},
								expect = "''[[The Legend of Zelda: Link's Awakening DX|Link's Awakening DX]]''",
							},
							{
								args = {"LANS"},
								expect = "[[The Legend of Zelda: Link's Awakening (Nintendo Switch)|''Link's Awakening'' for Nintendo Switch]]",
							},
							{
								desc = "For books, comics and manga, see also {{Sect|phraseLink}}.",
								args = {"LA (Cagiva)"},
								expect = "[[The Legend of Zelda: Link's Awakening (Cagiva)|''Link's Awakening'' (Cagiva)]]",
							},
							{
								args = {"E"},
								expect = "''[[The Legend of Zelda: Encyclopedia|Encyclopedia]]''",
							},
							{
								args = {"ALttP&FS"},
								expect = "''[[The Legend of Zelda: A Link to the Past & Four Swords|A Link to the Past & Four Swords]]''"
							},
							{
								args = {"Series"},
								expect = "[[The Legend of Zelda (Series)|''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 = {"TWW"},
								expect = "File:TWW English Logo.png",
							},
							{
								args = {"tww"},
								expect = "File:TWW 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: <code>canon</code>, <code>ambiguous</code>, or <code>non-canon</code>.",
						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 = "Module functions - games",
				section = {
					enumGames = {
						params = {"includeSeries"},
						returns = "An array of all game codes in [[Guidelines:Main#Canon_Order|canon order]], plus a <code>reference</code> key so that it can be used for [[Module:Documentation|documentation]] and [[Module:UtilsArg|validation]].",
						cases = {
							outputOnly = true,
							{
								snippet = "1",
								expect = {"TLoZ", "TAoL", "ALttP"},
							},
							{
								snippet = "2",
								expect = "[[Data:Franchise]]",
							},
							{
								snippet = "IncludeSeries",
								desc = "When <code>includeSeries</code> is true, then <code>Series</code> is the first item in the enum.",
								expect = {"Series", "TLoZ", "TAoL"},
							},
						},
					},
					baseGame = {
						params = {"code"},
						returns = "If <code>code</code> is a remake, returns the code for the original game, else returns <code>code</code> as-is.",
						cases = {
							outputOnly = true,
							{
								args = {"LANS"},
								expect = "LA",
							},
							{
								args = {"LA"},
								expect = "LA",
							},
							{
								args = {"fake"},
								expect = nil,
							},
						},
					},
					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: <code>2D</code> or <code>3D</code>.",
						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 = {"LADX"},
								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 = {"LADX"},
								expect = true,
							},
							{
								args = {"LA"},
								expect = false,
							},
							{
								args = {"HWDE"},
								expect = true,
							}
						},
					},
					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 = {"LADX"},
								expect = {"LANS"},
							},
							{
								args = {"ST"},
								expect = {}
							},
							{
								args = {"fake"},
								expect = {},
							},
						},
					},
					superseder = {
						params = {"code"},
						returns = "The game code of the latest canon version of the game corresponding to <code>code</code>",
						cases = {
							{
								args = {"LA"},
								expect = "LANS",
							},
							{
								desc = "<p><code>nil</code> is returned the game has no newer canon versions or does not exist in [[Data:Franchise]].</p><p>FSAE is not returned for FS as it not considered a canon remake.</p>",
								args = {"FS"},
								expect = nil,
							},
							{
								args = {"BotW"},
								expect = nil,
							},
							{
								args = {"notACode"},
								expect = nil,
							},
						},
					},
					type = {
						params = {"code"},
						returns = 'One of: <code>"main"</code>, <code>"remake"</code>, <code>"spin-off"</code>, <code>""</code> (other games)',
						cases = {
							{
								args = {"BotW"},
								expect = "main",
							},
							{
								args = {"HWAoC"},
								expect = "spin-off",
							},
							{
								args = {"SSBU"},
								expect = "",
							},
						},
					},
				},
			},
			{
				heading = "Module functions - books",
				section = {
					publisher = {
						params = {"code"},
						returns = "The book's publisher - in North America if available.",
						cases = {
							{
								args = {"OoT (Himekawa)"},
								expect = "VIZ Media",
							},
							{
								args = {"E"},
								expect = "Dark Horse Books",
							},
						},
					},
					phraseLink = {
						params = {"code"},
						returns = "Formatted link to page and authors.",
						cases = {
							{
								args = {"TLoZ (Ran)"},
								expect = "[[The Legend of Zelda (Ran)|''The Legend of Zelda'' manga]] by [[Maru Ran]]",
							},
							{
								args = {"tloz (ran)"},
								expect = "[[The Legend of Zelda (Ran)|''The Legend of Zelda'' manga]] by [[Maru Ran]]",
							},
							{
								args = {"AOV"},
								expect = "''[[The Legend of Zelda: An Original Version|The Legend of Zelda: An Original Version]]''",
							},
							{
								args = {"fake"},
								expect = nil,
							},
							{
								desc = "Nonfiction books such as {{E}} are not supported by this function.",
								args = {"E"},
								expect = "",
							},
						},
					},
				},
			},
		},
	}
end

return p