Module:Cite

local p = {} local h = {} local data = mw.loadData("Module:Cite/Data")

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

p.Templates = mw.loadData("Module:Cite/TemplateData")

local CAT_INVALID_ARGS = ""

-- We encapsulate Module:Error so that it is only transcluded on pages that actually have errors local function errFn(msg, warn) local utilsError = require("Module:UtilsError") return utilsError.error(msg, warn) end local function warn(msg) local utilsError = require("Module:UtilsError") utilsError.warn(msg) end

function p.Main(frame) local args, err = utilsArg.parse(frame:getParent.args, p.Templates.Cite) local categories = err and err.categoryText or "" local gameLink = args.game and Franchise.link(args.game) local speakerDisplay = args.source or "" if gameLink and args.source and args.source ~= "N/A" then -- if gameLink is not null here, it means `game` should be a valid term context speakerDisplay = Term.printTerm(args.source, args.game, {			link = true,			plural = args.plural,		}) end

if args.game and not gameLink and not utilsMarkup.containsLink(args.game) then warn(utilsMarkup.code(mw.dumpObject(args.game)) .." is neither a valid code nor an interwiki link.") categories = CAT_INVALID_ARGS end if args.game and Franchise.hasRemakes(args.game) then categories = categories .. ""	end local gameDisplay = gameLink or utilsMarkup.italic(args.game) local quoteDisplay = args.quote and p.color(args.quote, args.source, args.game) local localization = nil if args.lang then local lect = Language.getLect(args.lang) localization = lect and (lect.name.." localization") end local result = p.printCitation({		quote = quoteDisplay,		speaker = speakerDisplay,		sourceComponents = {gameDisplay, localization, args.version}, 		translation = args.translation,		romanization = args.romanization,	}) return result, categories end

function p.color(quote, source, game) local Color = require("Module:Color")

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.printCitation(args) local quote = h.trim(args.quote) local translation = h.trim(args.translation) local romanization = h.trim(args.romanization) local speaker = h.trim(args.speaker) local sourceComponents = args.sourceComponents local source = {} for i = 1, table.maxn(sourceComponents) do		local sourceComponent = sourceComponents[i] sourceComponent = sourceComponent and h.trim(sourceComponent) if sourceComponents[i] ~= "" then table.insert(source, sourceComponent) end end source = table.concat(source, ", ") if quote then quote = string.format("%s", quote) end if quote and translation and romanization then local tooltipClass = require("Module:Constants/class/tooltip") quote = quote..string.format( ( %s ), tooltipClass, romanization, translation) elseif quote and translation then quote = quote..string.format( (%s ), translation) end local citation if quote and speaker then citation = string.format("%s — %s (%s)", quote, speaker, source) elseif quote then citation = string.format("%s (%s)", quote, source) elseif speaker then citation = string.format("%s (%s)", speaker, source) else citation = source end return citation end function h.trim(str) str = str and str:gsub("^%s*", "") str = str and str:gsub("%s*$", "") if str == "" then return nil else return str 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 colorsTable = utilsLayout.table({		headers = {"Game", "Character/Source", "Color Sample"},		rows = tableRows,		styles = {			["text-align"] = "center"		},		sortable = true,	}) colorsTable = utilsMarkup.heading(3, utilsMarkup.anchor("colors", "Text Colors"))..colorsTable

return colorsTable end

function p.Documentation return { 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!" }			}		},		printCitation = { desc = "For use by other citation modules to ensure consitent citation formatting wiki-wide.", params = {"args"}, returns = "A formatted citation.", cases = { resultOnly = true, {					args = { {							quote = "Quote", speaker = "Speaker", sourceComponents = {"sourceInfo", "sourceInfo", "sourceInfo"}, },					},				},				{					args = { {							quote = "Quote", sourceComponents = {"sourceInfo", nil, "sourceInfo"}, },					}				},				{					args = { {							speaker = "Speaker", sourceComponents = {"sourceInfo", "sourceInfo", "sourceInfo"}, },					}				},				{					args = { {							quote = "De oplossing voor de graftombe van Gamelon is als volgt", translation = "The solution to the tomb of Gamelon is as follows", sourceComponents = {"CD Interactief vol. 2 no. 11", "HUB Uitgevers"}, },					}				},				{					args = { {							quote = "スーパーピッグ", speaker = "Sign", translation = "Super Pig", romanization = "Sūpā Piggu", sourceComponents = {mw.getCurrentFrame:preprocess("")}, },					},				},			},		},	} end

function p.Schemas return { Data = { type = "record", required = true, properties = { {					name = "books", required = true, desc = "Associates a book code from Data:Franchise to information about the publication of the book in other languages. Used by Template:Cite Book.", type = "map", keyPlaceholder = "bookCode", keys = { type = "string" }, values = { type = "map", keyPlaceholder = "langCode", keys = { type = "string", enum = Language.enum, desc = "A language code from Module:Language/Data.", },						values = { type = "record", properties = { {									name = "display", required = true, type = "string", desc = "The text to display when referring to the book - typically its subtitle.", },								{									name = "publisher", required = true, type = "string", desc = "The book's publisher." },							},						},					},				},				{					name = "dialogueColors", required = true, desc = "Associates game characters to color IDs from Template:Color. Used by Template:Cite to determine the character's default quote text color.", type = "map", keyPlaceholder = "gameCode", keys = { type = "string", desc = "A game code from Data:Franchise.", },					values = { allOf = { {								type = "map", keyPlaceholder = "character", keys = { type = "string", desc = "The name of a character in the game, or the special value . The former should refer to a page on the wiki, using parentheses if necessary. For example, the entry for Wood in  would be  .", },								values = { type = "string" }, },							{								type = "record", properties = { {										name = "default", type = "string", desc = "Sets the default text color for quotes from the given game.", },								},							},						},					},				},			},		},		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.", },		},		printCitation = { args = { type = "record", required = true, properties = { {						name = "quote", type = "string", desc = "The quote to cite.", },					{						name = "speaker", type = "string", desc = "The person speaking the quote.", },					{						name = "sourceComponents", type = "array", items = { type = "string" }, desc = "An array of strings to output as the citation source. The array can be sparse (i.e. have nil entries in the middle)." },				},			},		},	} end

return p