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

-- There is occasionally a need to cite games not covered by Data:Franchise -- Allowing such games through the use of interwiki links or italics allows us to distinguish invalid Data:Franchise codes from valid input not covered by Data:Franchise if args.game and not gameLink and not utilsMarkup.containsLink(args.game) and not h.hasItalics(args.game) then warn(utilsMarkup.code(args.game) .." is not an entry in Data:Franchise. When referring to a game not covered by Data:Franchise, use an interwiki link or place the title in italics.") 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 result = p.printCitation({		quote = quoteDisplay,		speaker = speakerDisplay,		source = gameDisplay,		sourceComponents = {args.version}, 		localization = args.lang,		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 localization = h.trim(args.localization) local speaker = h.trim(args.speaker) local sourceComponents = args.sourceComponents local fullSource = {args.source} if localization then local lect = Language.getLect(localization) if lect then table.insert(fullSource, lect.name.." localization") end end for i = 1, table.maxn(sourceComponents or {}) do		local sourceComponent = sourceComponents[i] sourceComponent = sourceComponent and h.trim(sourceComponent) if sourceComponents[i] ~= "" then table.insert(fullSource, sourceComponent) end end fullSource = table.concat(fullSource, ", ") 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, fullSource) elseif quote then citation = string.format("%s (%s)", quote, fullSource) elseif speaker then citation = string.format("%s (%s)", speaker, fullSource) else citation = fullSource 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 h.hasItalics(str) return string.find(str, ".*") 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", source = "source", sourceComponents = {"sourceInfo", "sourceInfo"}, },					},				},				{					args = { {							quote = "Quote", source = "source", sourceComponents = {"sourceInfo", nil, "sourceInfo"}, },					}				},				{					args = { {							speaker = "Speaker", source = "source", 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", source = mw.getCurrentFrame:preprocess(""), },					},				},			},		},	} end

function p.Data(frame) local Color = require("Module:Color") local utilsLayout = require("Module:UtilsLayout") local utilsTable = require("Module:UtilsTable")

local columnHeaders = {"Game", "Color", "Character/Interface"} local rows = {} for game, gameDialogueColors in pairs(data.dialogueColors) do		for subjectName, subjectColor in pairs(gameDialogueColors) do			local row = {} if subjectName == "N/A" or subjectName == "default" then subjectName = " "..subjectName.." " else subjectName = Term.link(subjectName, game) end local gameLink = Franchise.link(game) local color = " "..Color.color(subjectColor, subjectColor).." " row.cells = { {					content = gameLink, styles = { ["text-align"] = "center" },				},				{					content = color, styles = { ["text-align"] = "center" },				},				{					content = subjectName, styles = { ["text-align"] = "left" },				},			}			row.game = game row.color = subjectColor row.subject = subjectName table.insert(rows, row) end end -- Sort by game then by color name, then by subject name rows = utilsTable.sortBy(rows, function(row)		local gameKey = string.char(Franchise.canonOrder(row.game) or 0)		local subjectKey = row.subject		if row.subject == "default" then			subjectKey = string.char(1)		elseif row.subject == "N/A" then			subjectKey = string.char(2)		end		local sortKey = gameKey..row.color..subjectKey		return sortKey	end) return utilsLayout.table({		sortable = true,		headers = columnHeaders,		rows = rows,	}) end

return p