Module:Cite

local Color = require("Module:Color") local Franchise = require("Module:Franchise") local Term = require("Module:Term") local utilsArg = require("Module:UtilsArg") local utilsError = require("Module:UtilsError") local utilsMarkup = require("Module:UtilsMarkup") local utilsString = require("Module:UtilsString")

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

local p = {}

function p.Main(frame) local args, err = utilsArg.parse(frame:getParent.args, p.Templates.Cite) local result = p.printGameCitation(args.quote, args.source, args.plural, args.game, args.version) if err then result = result .. utilsMarkup.categories(err.categories) end return result end

function p.printGameCitation(quote, source, plural, game, version) local gameLink = game and Franchise.link(game) local sourceDisplay = source or "" if gameLink and source ~= "N/A" then -- if gameLink is not null here, it means `game` should be a valid term context sourceDisplay = Term.printTerm({			page = source,			game = game,			link = "link",		}, plural, true) end local categories = "" if game and not gameLink and not utilsMarkup.containsLink(game) and mw.title.getCurrentTitle.nsText ~= "MediaWiki" then --MediaWiki is excluded or else this matches MediaWiki:Gadget-EditToolbarButtons.js for some reason utilsError.warn(utilsMarkup.code(mw.dumpObject(game)) .." is neither a valid code nor an interwiki link.") categories = "" end if game and Franchise.hasRemakes(game) then categories = categories .. ""	end local sourceWithContext if version then sourceWithContext = string.format("%s (%s, %s)", sourceDisplay, gameLink or utilsMarkup.italic(game), version) else sourceWithContext = string.format("%s (%s)", sourceDisplay, gameLink or utilsMarkup.italic(game)) end if mw.title.getCurrentTitle.nsText ~= "User" then sourceWithContext = sourceWithContext .. categories end if utilsString.isEmpty(quote) then return sourceWithContext end local quoteDisplay = utilsMarkup.italic(quote) quoteDisplay = p.color(quoteDisplay, source, game)

local result = string.format('"%s" — %s', quoteDisplay, sourceWithContext) return result end

function p.color(quote, source, game) local colorId = data.dialogueColors[game] and data.dialogueColors[game][source or "default"] if colorId then local coloredText, errCategories = Color.color(colorId, quote) return coloredText .. (errCategories or "") else return quote end end

function p.Data -- Performance optimization; importing this at the top with the others adds processing time to Template:Cite -- these dependencies are only needed on Module:Cite/Data/Documentation local utilsLayout = require("Module:UtilsLayout") local utilsTable = require("Module:UtilsTable") local tableRows = {} for _, game in ipairs(Franchise.enumGames) do		local gameColors = data.dialogueColors[game] if gameColors then local colorKeys = utilsTable.keys(gameColors) local sortedColorKeys = utilsTable.sortBy(colorKeys, function(key)				if key == "default" then					return "0" -- show default color first				elseif key == "N/A" then					return "1" -- then show color for N/A (i.e. in-game narration)				else					return key -- then show characters in alphabetical order				end 			end) for i, colorKey in ipairs(sortedColorKeys) do				local row = {} if i == 1 then table.insert(row, {						rowspan = #colorKeys,						content = utilsMarkup.code(utilsMarkup.link(Franchise.article(game), game)),					}) end if colorKey == "default" or colorKey == "N/A" then table.insert(row, utilsMarkup.code(colorKey)) else table.insert(row, utilsMarkup.link(colorKey)) end local colorSample = p.color("The quick brown fox jumps over the lazy dog.", colorKey, game) table.insert(row, colorSample) table.insert(tableRows, row) end end end local wikitable = utilsLayout.table({		caption = "Text Colors",		headers = {"Game", "Character/Source", "Color Sample"},		rows = tableRows,		styles = {			["text-align"] = "center"		},		sortable = true,	}) return wikitable end

p.Templates = { Cite = { purpose = "Citing in-game text. For more information, see Guidelines:References.", format = "inline", paramOrder = {1, 2, "plural", 3, 4}, params = { [1] = {				name = "quote", required = true, type = "content", desc = "The text to cite. Generally speaking, one should quote the latest remake of a game." },			[2] = {				name = "source", required = true, type = "string", desc = "The source of the in-game text. Usually this is a speaking character. For written text, cite the source as being text itself if it has a name, otherwise cite its author. A menu screen can also be a source. If the text corresponds to in-game narration, use . If   is a valid game code, then   is treated as a term subject (unless it's  ).", },			plural = { type = "boolean", desc = "Typing  in this field causes   to be pluralized, if it is a valid term.", canOmit = true, trim = true, nilIfEmpty = true, },			[3] = {				name = "game", required = true, type = "string", desc = "A game code. If no such game exists at Data:Franchise (i.e. any third-party game outside the Zelda franchise), this field will instead be treated as plain wikitext. In this case, an interwiki link must be used." },			[4] = {				name = "version", type = "content", desc = "Can be used to specify a port, game mode, or localization of the game.", canOmit = true, },		},		examples = { {				desc = "A regular citation. Note that  is not to be used when citing American English text, nor when citing a remake.", args = {"Leave these woods and go to the east, where you will find the land protected by the spirit Eldin.", "Faron (Spirit)", "TPHD"}, },			{				desc = "Cited text may be automatically colorized to match the in-game text color, which may change depending on the source. These colors are defined at Module:Cite/Data. Specific words or phrases must be colorized manually using Template:Color.", args = {"An incarnation of my hatred shall ever follow your kind, dooming them to wander a blood-soaked sea of darkness for all time!", "Demise", "SSHD"}, },			{				desc = "Citing a plural term.", args = {"Cryonis Create a pillar of ice from a water surface. Builds ice pillars that are very stable. These pillars can be used as stepping stones or as obstacles. Use Cryonis on an ice pillar to break it.", "Rune", plural = "yes", "BotW"}, },			{				desc = "Invalid terms are marked accordingly.", args = {"Lorem ipsum", "Not a Real Term", "BotW"}, },			{				desc = " is not counted as a term.", args = {"This is but one of the legends of which the people speak...", "N/A", "TWWHD"}, },			{				desc = "Citing menu screens is sometimes necessary.", args = {"Akkala Highlands", "Map", "BotW"}, },			{				desc = "When citing written text which has a valid term, use that term instead of the author's name.", args = {"Today, I told everything to Mikau, the one person whom I didn't want to know about it. At first, I was too embarrassed and too sad to do anything. And with the words that Mikau said at that moment, I felt that all hope had been lost. But please, Mikau, I'm begging you, don't do anything rash.", "Lulu's Diary", "MM3D"}, },			{				desc = "Citing an alternate version/game mode. Citations of outdated game versions are marked with a maintenance category, as they are generally to be avoided.", args = {"Leave these woods and go to the west, where you will find the land protected by the spirit Eldin.", "Faron (Spirit)", "TP", "Wii version"}, },			{				desc = "Citing the Japanese version of a game.", args = {"", "Ganondorf", "TWW", "Japanese version"} },			{				desc = "Citing a non-Zelda game with Zelda references", args = {"Tired of pixies asking you to listen?", "N/A", ""} },			{				desc = "Citing a game that is neither a valid code nor a link is considered an error.", args = {"Bla bla bla", "N/A", "notARealGame"}, },		}	} }

p.Documentation = { color = { desc = "Given a valid game and character (source), this function applies the main color used for that character's dialogue in-game.", params = {"quote", "source", "game"}, returns = "The colored text", cases = { {				args = {"Only the true ruler of the Twili can destroy the Mirror of Twilight.", "Midna", "TPHD"}, expect = ' Only the true ruler of the Twili can destroy the Mirror of Twilight. ',			},			{				desc = "Not all characters have a unique color.", args = {"Tingle, Tingle! Kooloo-Limpah!", "Tingle", "MM"}, expect = "Tingle, Tingle! Kooloo-Limpah!" }		}	} }

p.Schemas = { color = { quote = { required = true, type = "string", desc = "The quote to color", },		game = { required = true, type = "string", desc = "A game code. See Module:Franchise.", },		source = { required = true, type = "string", desc = "The name of the character who speaks the quote.", },	} }

return p