Module:Cite

From Zelda Wiki, the Zelda encyclopedia
Jump to navigation Jump to search
This is the main module for the following templates: In addition, this module exports the following functions.

color

color(quote, source, game)

Given a valid game and character (source), this function applies the main color used for that character's dialogue in-game.

Returns

  • The colored text

Examples

#InputOutputResultStatus
1
color(
  "Only the true ruler of the Twili can destroy the Mirror of Twilight.",
  "Midna",
  "TPHD"
)
'<span class="zw-color" style="color:#64b1b3">Only the true ruler of the Twili can destroy the Mirror of Twilight.</span>'
Only the true ruler of the Twili can destroy the Mirror of Twilight.
Green check.svg
Not all characters have a unique color.
2
color("Tingle, Tingle! Kooloo-Limpah!", "Tingle", "MM")
"Tingle, Tingle! Kooloo-Limpah!"
Tingle, Tingle! Kooloo-Limpah!
Green check.svg

printCitation

printCitation(args)

For use by other citation modules to ensure consitent citation formatting wiki-wide.

Returns

  • A formatted citation.

Examples

#InputResult
3
printCitation({
  quote = "Quote",
  source = "source",
  speaker = "Speaker",
  sourceComponents = {"sourceInfo", "sourceInfo"},
})
"Quote" — Speaker (source, sourceInfo, sourceInfo)
4
printCitation({
  quote = "Quote",
  source = "source",
  sourceComponents = {"sourceInfo", [3] = "sourceInfo"},
})
"Quote" (source, sourceInfo, sourceInfo)
5
printCitation({
  speaker = "Speaker",
  source = "source",
  sourceComponents = {"sourceInfo", "sourceInfo", "sourceInfo"},
})
Speaker (source, sourceInfo, sourceInfo, sourceInfo)
6
printCitation({
  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"},
})
"De oplossing voor de graftombe van Gamelon is als volgt" (The solution to the tomb of Gamelon is as follows) (CD Interactief vol. 2 no. 11, HUB Uitgevers)
7
printCitation({
  source = "''[[The Legend of Zelda: Four Swords Adventures|Four Swords Adventures]]''",
  romanization = "Sūpā Piggu",
  quote = "{{H|TWW|スーパーピッグ}}",
  speaker = "[[Sign]]",
  translation = "Super Pig",
})
"スーパーピッグ" (Super Pig) — Sign (Four Swords Adventures)

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 = "[[Category:"..require("Module:Constants/category/invalidArgs").."]]"

-- 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 .. "[[Category:Articles citing games with remakes]]"
	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([["<i>%s</i>"]], quote)
	end
	if quote and translation and romanization then
		local tooltipClass = require("Module:Constants/class/tooltip")
		quote = quote..string.format([[ (<span class="%s" title="Romanized: %s"><i>%s</i></span>)]], tooltipClass, romanization, translation)
	elseif quote and translation then
		quote = quote..string.format([[ (<i>%s</i></span>)]], 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 = '<span class="zw-color" style="color:#64b1b3">Only the true ruler of the Twili can destroy the Mirror of Twilight.</span>',
				},
				{
					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 = "{{H|TWW|スーパーピッグ}}",
							speaker = "[[Sign]]",
							translation = "Super Pig",
							romanization = "Sūpā Piggu",
							source = mw.getCurrentFrame():preprocess("{{FSA}}"),
						},
					},
				},
			},
		},
	}
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 = "<kbd>"..subjectName.."</kbd>"
			else
				subjectName = Term.link(subjectName, game)
			end
			local gameLink = Franchise.link(game)
			local color = "<kbd>"..Color.color(subjectColor, subjectColor).."</kbd>"
			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