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



The Dream Shrine
194Articles

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

local p = {}
local h = {}

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

local CATEGORY_INVALID_ARGS = "[[Category:"..require("Module:Constants/category/invalidArgs").."]]"
local CATEGORY_PARAM_CAPTION = "[[Category:Infoboxes using captions]]"
local CATEGORY_PARAM_NAME = "[[Category:Infoboxes using the name parameter]]"
local CLASS_TOOLTIP = require("Module:Constants/class/tooltip")
local DEFAULT_IMG_SIZE = "320x320px"

function p.Main(frame)
	local templateName = "Infobox "..frame:getParent():getTitle()
	
	local args, err, categories
	local templateSpec = p.Templates[templateName]
	if templateSpec then
		args, err = utilsArg.parse(frame:getParent().args, templateSpec)
	else
		args = frame:getParent().args
	end
	categories = err and err.categoryText or ""
	
	if args.name and args.name ~= "" then
		categories = categories..CATEGORY_PARAM_NAME
	end
	if args.caption and args.caption ~= "" then
		categories = categories..CATEGORY_PARAM_CAPTION
	end
	
	local styles = frame:extensionTag({
		name = "templatestyles",
		args = { src = "Module:Infobox/Styles.css" }
	})
	
	return styles, categories
end

function p.Image(frame)
	local file = frame.args[1]
	local caption = frame.args[2]
	if file == nil or file == "" then
		return nil
	elseif not utilsString.startsWith(file, "File:") then
		return file
	else
		local image, exists = File.image(file, {
			size = frame.args.size or DEFAULT_IMG_SIZE, -- unclear whether we should even support custom sizing or force them all to 320x320px.
			scale = 10,
		})
		if exists then
			-- Set this image as the article's representative image for things like page previews
			mw.ext.seo.set({
				image = file
			})
		end
		if caption and caption ~= "" then
			local html = mw.html.create("div")
				:addClass("infobox__image-caption")
				:wikitext(caption)
			image = image .. tostring(html)
		end
		return image
	end
end

function p.Games(frame)
	local games = frame.args[1]
	local categories = ""

	games = games and utilsString.trim(games)
	if games == nil or games == "" then
		return nil
	end
	games = utilsString.split(games)

	local gameLinks = utilsTable.map(games, p.link)
	local gameLinks = utilsTable.compact(gameLinks)
	if #gameLinks ~= #games then
		categories = categories..CATEGORY_INVALID_ARGS
	end
	
	if #gameLinks == 1 then
		return gameLinks[1], categories
	else
		local gameList = utilsMarkup.list(gameLinks)
		return gameList, categories
	end
end
function p.link(game)
	if utilsMarkup.containsLink(game) then
		return game
	end
	local game, notes = utilsMarkup.separateMarkup(game)
	local link = Franchise.link(game)
	local properCode = Franchise.code(game)
	if not link then
		h.warn(string.format("Invalid entry <code>%s</code>. See [[Data:Franchise]] for a list of valid entries.", game))
		return nil
	elseif properCode and properCode ~= game then
		h.warn(string.format("<code>%s</code> should be written as <code>%s</code>", game, properCode))
	end
	return link..notes
end

function p.GameBlocks(frame)
	local args = frame:getParent().args
	local blocks, categories = h.parseBlocks(args)
	
	local html = mw.html.create("ul"):addClass("infobox-game-blocks")
	for i, block in ipairs(blocks) do
		local gameText = html
			:tag("li")
			:addClass("infobox-game-blocks__game")
			:tag("span")
				:addClass("infobox-game-blocks__game-text")
		local game = gameText:done()
	
		if blocks.compact then
			gameText:wikitext(Franchise.display(block.game))
			local gameList = game
				:tag("ul")
				:addClass("infobox-game-blocks__game-list")
			for j, listItem in ipairs(block.listItems) do
				gameList
					:tag("li")
					:addClass("infobox-game-blocks__game-list-item")
					:wikitext(listItem)
			end
		else
			html:addClass("infobox-game-blocks--compact")
			gameText
				:tag("span")
					:addClass(CLASS_TOOLTIP)
					:attr("title", Franchise.shortName(block.game))
					:wikitext(block.game)
					:done()
				:wikitext(": ")
			game:wikitext(block.listItems[1])
		end
	end

	return tostring(html), categories
end
function h.parseBlocks(args)
	local categories = ""

	local seenParams = {}
	local blocks = {}
	blocks.compact = false
	for i, game in ipairs(Franchise.enum({ includeSeries = true })) do
		seenParams[game] = true
		local listItems = args[game]
		listItems = listItems and utilsString.trim(listItems)
		listItems = listItems and utilsString.nilIfEmpty(listItems)
		if listItems and string.find(listItems, ", %l") then
			h.warn("Lowercase character detected following comma. Within <code>Template:Infobox Game Blocks</code>, commas are used to separate list items. All list items should be in sentence case. Literal commas can be escaped using {{Template|,}}.")
			categories = categories..CATEGORY_INVALID_ARGS
		end
		if listItems then
			listItems = utilsString.split(listItems, '%s*,%f[^,%d]%s*') -- %f[^,%d] is so we don't split numbers on their thousands separator (e.g., 1,500)
			table.insert(blocks, {
				game = game, 
				listItems = listItems,
			})
		end
		local hasDiv = listItems and listItems[1] and string.find(listItems[1], "<div") -- See [[Minuet of Forest]] "Notes" field, for example
		if listItems and #listItems > 1 or hasDiv then
			blocks.compact = true
		end
		if listItems and listItems[1] and string.find(listItems[1], "plainlist") then
			blocks.compact = true
		end
	end

	for k, v in pairs(args) do
		if not seenParams[k] then
			local errorMessage = string.format("Invalid game <code>%s</code>", k)
			h.warn(errorMessage)
			categories = categories..CATEGORY_INVALID_ARGS
		end
	end
	
	return blocks, categories
end

function p.Title(frame)
	local subpageName = mw.title.getCurrentTitle().subpageText
	local term = Term.fetchTerm(subpageName, "Series")
	return term or utilsString.stripTrailingParentheses(subpageName)
end

function h.warn(msg, ...)
	local utilsError = require("Module:UtilsError")
	local warnMessage = string.format(msg, ...)
	utilsError.warn(warnMessage, {
		includeInstance = false,
	})
end

local templateSpec = function(args)
	local singular = args.singular
	local plural = args.plural
	local params = args.params
	local productionParams = args.productionParams
	local imageSuchAs = args.imageSuchAs

	local spec = {
		format = "block",
		purpose = string.format("[[Guidelines:Articles#Infobox|Infobox]] for [[:Category:%s|%s]].", plural, string.lower(plural)),
		categories = {"Infobox templates"},
		boilerplate = {
			separateRequiredParams = false,	
		},
		paramOrder = {"name", "image", "caption"},
		params = {
			name = {
				desc = "<p>Name to use in the infobox header. Defaults to {{Template|Page Name}}.</p><p>In general, this parameter should be omitted unless the title requires italics.</p>",
				type = "content",
			},
			image = {
				desc = string.format("An image to represent the %s, such as %s.", singular, imageSuchAs),
				type = "wiki-file-name",
			},
			caption = {
				desc = "A caption for the image.",
				type = "content",
			}
		},
	}
	for i, param in ipairs(params or {}) do
		spec.params[param.name] = param
		table.insert(spec.paramOrder, param.name)
	end
	for i, param in ipairs(productionParams or {}) do
		spec.params[param.name] = param
		table.insert(spec.paramOrder, param.name)
	end
	
	return spec
end

local released = {
	name = "released",
	desc = "Release date(s) of the film. Use [[Template:Release]].",
	type = "content",
}

p.Templates = {
	["Infobox Game Blocks"] = {},
	["Infobox Film"] = templateSpec({
		singular = "film",
		plural = "films",
		imageSuchAs = "a release poster or a DVD cover",
		params = {
			{
				name = "director",
				desc = "The director(s) of the film.",
				type = "content",
			},
			{
				name = "producer",
				desc = "The producer(s) of the film.",
				type = "content",
			},
			{
				name = "writer",
				desc = "The writer(s) of the film.",
				type = "content",
			},
			{
				name = "production",
				desc = "The companies producing the film.",
				type = "content",
			},
			{
				name = "distributor",
				desc = "The companies distributing the film.",
				type = "content",
			},
			{
				name = "country",
				desc = "Country or countries of production.",	
			},
			released,
		}
	}),
	["Infobox Television"] = templateSpec({
		singular = "television",
		plural = "television",
		imageSuchAs = "the series' logo or title card",
		params = {
			{
				name = "basedOn",
				type = "string",
				desc = "Comma separated list of [[Data:Franchise|games]] that the series is based on.",
				enum = Franchise.enum(),
				trim = true,
				split = true,
			},
			{
				name = "seasons",
				type = "content",
				desc = "Number of seasons.",
			},
			{
				name = "episodes",
				type = "content",
				desc = "Number of total episodes.",
			},
			{
				name = "company",
				type = "content",
				desc = "Production comapany or companies.",
			},
			{
				name = "distributor",
				type = "content",
				desc = "Distributor(s) of the television series.",
			},
			released,
		}
	})
}

function p.Documentation()
	return {
		Games = {
			desc = "Used by [[:Category:Infobox templates|infobox templates]] to turn comma-separated [[Data:Franchise|game codes]] into lists of games.",
			frameParams = {
				[1] = {
					name = "param",
					desc = "The infobox parameter, usually <code><nowiki>{{{game|}}}</nowiki></code> or <code><nowiki>{{{other|}}}</nowiki></code>.",
				},
			},
			cases = {
				{
					args = {"TLoZ, TAoL, ALttP"},
				},
				{
					args = {"TLoZ (Ran), BoMC, TLoZ (Susumu)"},
				},
				{
					args = {""},
				},
				{
					args = {},
				},
				{
					args = {"invalid game"},
				},
				{
					args = {"OoT, invalid game, TP"},
				},
			}
		},
		Image = {
			desc = "Used by [[:Category:Infobox templates|infobox templates]] to generate an image when [[Template:Media]] is not used.",
			frameParams = {
				[1] = {
					name = "file",
					desc = "The image parameter - a file name.",
				},
				[2] = {
					name = "caption",
					desc = "The caption parameter.",
				},
				size = {
					desc = "Image size in pixels. Sprites are scaled to a maximum of 10 times their original size.",
					default = DEFAULT_IMG_SIZE,
				},
			},
			cases = {
				{
					args = {"File:TWW Great Fairy Figurine Model.png"},
				},
				{
					args = {"File:TWW Great Fairy Figurine Model.png", "Great Fairy Figurine", size = "250px"}
				},
				{
					desc = "Sprites are scaled to a maximum of 10 times their original size.",
					args = {"File:ALttP Apple Sprite.png"},
				},
				{
					desc = "[[Template:Media]] output is rendered as-is",
					args = {"{{Media|Model TWW= TWW Great Fairy Figurine Model.png}}"}
				},
				{
					desc = "Anything other than a file name starting with <code>File:</code> is rendered as-is",
					args = {"{{Plural|Series|Cyber Pico Bloom}} are never seen in-game"},
				},
			},
		},
	}
end

return p