Module:File

From Zelda Wiki, the Zelda encyclopedia
Jump to navigation Jump to search
This module exports the following functions.

image

image(filename, [options])

A higher-level version of utilsMarkup.file with awareness of whether the file exists or not.

Parameters

  • filename
    Filename of the image, with or without the namespace prefix.
  • [options]
    [size]
    Image size in pixels.
    [scale]
    Image scaling factor — the original image size is multitplied by scale. If both scale and size are present, the value which results in the smaller image will be used. By default this uses an expensive parser function.
    [scaleUsingCargo]
    If set to true, then a Cargo query is used to determine the original image size for the scale option above. You can use this to avoid hitting expensive parser function limit. This option has an additional performance cost of roughly 2-5 milliseconds per image.
    [link]
    Name of a page on the wiki or an external URL for the image thumbnail to link to.
    [caption]
    Alt text for the image.
    [notPageImage]
    If true, the image will never appear as the page's representative image in page previews.
    [checkExists=true]

    If set to false then the function skips the file existence check. A red link is returned instead of the 'please upload' placeholder.

    This may be needed to prevent too many expensive parser function calls from occurring on a page.

    [isPixelArt]
    If true the image will be rendered using nearest-neighbor interpolation, which prevents pixel art (sprites, 2D game screenshots) from appearing blurry in thumbnails.

Returns

  • Wikitext rendering an image thumbnail.
  • A boolean — true if the image exists, false otherwise.

Examples

#InputOutputResultStatus
1
image(
  "File:TWW Great Fairy Figurine Model.png",
  {
    size = "100px",
    link = "Great Fairy",
  }
)
"[[File:TWW Great Fairy Figurine Model.png|100px|link=Great Fairy]]"
TWW Great Fairy Figurine Model.png
Green check.svg
true
true
Green check.svg
If file does not exist, show 'click to upload' thumbnail which links to Special:Upload.
2
image(
  "File:TWWHD Great Fairy Figurine Model.png",
  {
    size = "150px",
    link = "Great Fairy",
  }
)
"[[File:No Image Upload.png|150px|link=//zeldawiki.wiki/wiki/Special:Upload?wpDestFile=TWWHD+Great+Fairy+Figurine+Model.png|class=notpageimage]]"
No Image Upload.png
Green check.svg
false
false
Green check.svg
'No image' thumbnail has minimum 100px width, because it is illegible at smaller sizes.
3
image(
  "File:TWWHD Great Fairy Figurine Model.png",
  { size = "64px" }
)
"[[File:No Image Upload.png|100px|link=//zeldawiki.wiki/wiki/Special:Upload?wpDestFile=TWWHD+Great+Fairy+Figurine+Model.png|class=notpageimage]]"
No Image Upload.png
Green check.svg
false
false
Green check.svg
checkExists = false skips the existence check and simply render a red link
4
image(
  "File:TWWHD Great Fairy Figurine Model.png",
  {
    checkExists = false,
    size = "100px",
    link = "Great Fairy",
  }
)
"[[File:TWWHD Great Fairy Figurine Model.png|100px|link=Great Fairy]]"
File:TWWHD Great Fairy Figurine Model.png
Green check.svg
nil
Green check.svg
Scaling factor.
5
image("File:TMC Vaati Sprite.png", { scale = 2 })
"[[File:TMC Vaati Sprite.png|48x56px]]"
TMC Vaati Sprite.png
Green check.svg
true
true
Green check.svg
The isPixelArt options ensures that sprites do not appear blurry.
6
image(
  "File:TMC Vaati Sprite.png",
  {
    scale = 2,
    isPixelArt = true,
  }
)
"[[File:TMC Vaati Sprite.png|48x56px|class=pixel-art]]"
TMC Vaati Sprite.png
Green check.svg
true
true
Green check.svg
Scaling using Cargo instead of an expensive parser function.
7
image(
  "File:TMC Vaati Sprite.png",
  {
    scale = 2,
    isPixelArt = true,
    scaleUsingCargo = true,
  }
)
"[[File:TMC Vaati Sprite.png|48x56px|class=pixel-art]]"
TMC Vaati Sprite.png
Green check.svg
true
true
Green check.svg
If both scale and size are specified, the one resulting in the smaller image is used.
8
image(
  "File:TMC Vaati Sprite.png",
  {
    scale = 2,
    isPixelArt = true,
    size = "80px",
  }
)
"[[File:TMC Vaati Sprite.png|48x56px|class=pixel-art]]"
TMC Vaati Sprite.png
Green check.svg
true
true
Green check.svg
9
image(
  "File:TMC Vaati Sprite.png",
  {
    scale = 10,
    isPixelArt = true,
    size = "80px",
  }
)
"[[File:TMC Vaati Sprite.png|80px|class=pixel-art]]"
TMC Vaati Sprite.png
Green check.svg
true
true
Green check.svg
Applying notpageimage.
10
image(
  "File:TMC Vaati Sprite.png",
  {
    isPixelArt = true,
    notPageImage = true,
  }
)
"[[File:TMC Vaati Sprite.png|class=notpageimage pixel-art]]"
TMC Vaati Sprite.png
Green check.svg
true
true
Green check.svg

gameImage

gameImage(game, subject, type, [options])

A specialized version of image that infers the filename from game, subject, and type.

Parameters

  • game
    A franchise code.
  • subject
  • type
  • [options]
    [size]
    Image size in pixels.
    [scale]
    Image scaling factor — the original image size is multitplied by scale. If both scale and size are present, the value which results in the smaller image will be used. By default this uses an expensive parser function.
    [scaleUsingCargo]
    If set to true, then a Cargo query is used to determine the original image size for the scale option above. You can use this to avoid hitting expensive parser function limit. This option has an additional performance cost of roughly 2-5 milliseconds per image.
    [link]
    Name of a page on the wiki or an external URL for the image thumbnail to link to.
    [caption]
    Alt text for the image.
    [notPageImage]
    If true, the image will never appear as the page's representative image in page previews.
    [checkExists=true]

    If set to false then the function skips the file existence check. A red link is returned instead of the 'please upload' placeholder.

    This may be needed to prevent too many expensive parser function calls from occurring on a page.

Returns

  • A string of wikitext that renders a thumbnail.
  • A boolean — true if the image exists, false otherwise.

Examples

#InputOutputResultStatus
11
gameImage(
  "TWW",
  "Great Fairy Figurine",
  "Model",
  {
    size = "100px",
    link = "Great Fairy",
  }
)
"[[File:TWW Great Fairy Figurine Model.png|100px|link=Great Fairy]]"
TWW Great Fairy Figurine Model.png
Green check.svg
true
true
Green check.svg

icon

icon(game, subject, [options])

Parameters

  • game
    A franchise code.
  • subject
  • [options]
    [size]
    Image size in pixels.
    [scale]
    Image scaling factor — the original image size is multitplied by scale. If both scale and size are present, the value which results in the smaller image will be used. By default this uses an expensive parser function.
    [scaleUsingCargo]
    If set to true, then a Cargo query is used to determine the original image size for the scale option above. You can use this to avoid hitting expensive parser function limit. This option has an additional performance cost of roughly 2-5 milliseconds per image.
    [link]
    Name of a page on the wiki or an external URL for the image thumbnail to link to.
    [caption]
    Alt text for the image.
    [notPageImage]
    If true, the image will never appear as the page's representative image in page previews.
    [checkExists=true]

    If set to false then the function skips the file existence check. A red link is returned instead of the 'please upload' placeholder.

    This may be needed to prevent too many expensive parser function calls from occurring on a page.

Returns

  • An icon thumbnail for the subject in the given game.

Examples

#InputOutputResultStatus
12
icon("LANS", "Pineapple")
"[[File:LANS Pineapple Icon.png|class=pixel-art]]"
LANS Pineapple Icon.png
Green check.svg
13
icon("LADX", "Pineapple")
"[[File:LADX Pineapple Sprite.png|class=pixel-art]]"
LADX Pineapple Sprite.png
Green check.svg

logo(code, options)

Parameters

Returns

  • Given a valid franchise code, returns a logo thumbnail.
  • A boolean indicating whether a logo exists for the game yet.

Examples

#InputOutputResultStatus
14
logo("TWW", { size = "200px" })
"[[File:TWW English Logo.png|200px]]"
TWW English Logo.png
Green check.svg
true
true
Green check.svg
15
logo("SSB4", { size = "200px" })
"[[File:SSB4 Logo.png|200px]]"
SSB4 Logo.png
Green check.svg
true
true
Green check.svg
16
logo("SS (Himekawa)", { size = "200px" })
"[[File:Viz Media Logo.svg|200px]]"
Viz Media Logo.svg
Green check.svg
true
true
Green check.svg
17
logo("TLoZ (Mishouzaki)", { size = "200px" })
"[[File:TLoZ (Mishouzaki) Manga Cover Artwork.png|200px]]"
TLoZ (Mishouzaki) Manga Cover Artwork.png
Green check.svg
true
true
Green check.svg
18
logo("TAoL (Mishouzaki)", { size = "200px" })
"[[File:No Image Upload.png|200px|link=//zeldawiki.wiki/wiki/Special:Upload?wpDestFile=TAoL+%28Mishouzaki%29+Manga+Cover+Artwork.png|class=notpageimage]]"
No Image Upload.png
Green check.svg
false
false
Green check.svg
19
logo("E", { size = "200px" })
"[[File:The Legend of Zelda Encyclopedia Cover.png|200px]]"
The Legend of Zelda Encyclopedia Cover.png
Green check.svg
true
true
Green check.svg
20
logo("TMoL", { size = "200px" })
"[[File:Misadventures Link logo2.png|200px]]"
Misadventures Link logo2.png
Green check.svg
true
true
Green check.svg

local p = {}
local h = {}

local Franchise = require("Module:Franchise")
local utilsCargo = require("Module:UtilsCargo")
local utilsMarkup = require("Module:UtilsMarkup")
local utilsPage = require("Module:UtilsPage")
local utilsString = require("Module:UtilsString")
local utilsTable = require("Module:UtilsTable")

local CARGO_TABLE = "Files" 

-- Various templates
function p.Icon(frame)
	local args = frame.args
	local img = p.icon(args[1], args[2], {
		size = args.size,
	})
	return img
end

-- Utilities
function p.image(filename, options)
	filename = utilsPage.stripNamespace(filename, "File")
	options = options or {}
	local sizeWidth, sizeHeight = p.dimensions(options.size)
	local checkExists = options.checkExists ~= false
	
	-- If the file is a redirect and we are doing an existence check or getting width/height from Cargo, then we need to get the redirectTarget.
	-- This is a somewhat expensive operation to do at scale so we only do it when needed
	local originalFilename = filename
	if checkExists or options.scale then
		local redirectTarget = mw.title.new("File:"..filename).redirectTarget
		redirectTarget = redirectTarget and redirectTarget.text
		if redirectTarget then
			filename = redirectTarget
		end
	end
	
	if checkExists and not utilsPage.exists("File:" .. filename, true) then
		-- We check again with mw.title To work around a bug where moved files are marked non-existant until null-edited
		-- This happens because of how we use Cargo to query for existence to save on expensive parser functions
		local title = mw.title.new(filename, "File")
		if not title.fileExists then
			return h.noimage(filename, sizeWidth, sizeHeight, options), false
		end
	end
	
	if options.scale then
		local file
		if options.scaleUsingCargo then
			results = utilsCargo.query(CARGO_TABLE, "width, height", {
				where = utilsCargo.allOf({
					["_pageName"] = "File:"..filename,
				}),
				limit = 1,
			})
			file = results[1]
		end
		if not file or utilsString.isEmpty(file.width) or utilsString.isEmpty(file.height) then -- if scaleUsingCargo = false or data does not return from Cargo query for some reason, then use the title object (an expensive parser function)
			file = mw.title.new("File:"..filename).file
		end

		local width = math.floor(tonumber(file.width) * options.scale)
		local height = math.floor(tonumber(file.height) * options.scale)
		if (sizeWidth and sizeWidth < width) or (sizeHeight and sizeHeight < height) then
			width = sizeWidth
			height = sizeHeight
		end
		size = ""
		if width then
			size = width
		end
		if height then
			size = size .. "x" .. height
		end
		size = size .. "px"
		options = utilsTable.merge({}, options, {
			size = size,
		})
	end
	local classes = utilsTable.compact({options.notPageImage and "notpageimage", options.isPixelArt and "pixel-art"})
	if #classes > 0 then
		options.class = table.concat(classes, " ")
	end
	return utilsMarkup.file(originalFilename, options), checkExists and true or nil
end
function p.dimensions(size)
	if not size then
		return nil
	end
	local s, e
	s, e = size:find("^[0-9]+")
	local width = s and size:sub(s, e) or ""
	
	s, e = size:find("x[0-9]+")
	local height = s and size:sub(s+1, e) or ""
	
	return tonumber(width), tonumber(height)
end
function h.noimage(filename, sizeWidth, sizeHeight, options)
	local uploadUrl = mw.uri.fullUrl("Special:Upload")
	uploadUrl:extend({
		wpDestFile = filename
	})
	local options = utilsTable.merge({}, options, {
		link = tostring(uploadUrl),
		class = "notpageimage",
	})
	-- Make sure thumbnail for 'no image' is no less than 100x100px
	if (sizeWidth and sizeWidth < 100) or (sizeHeight and sizeHeight < 100) then
		options.size = "100px"
	end
	return utilsMarkup.file("File:No Image Upload.png", options)
end

function p.gameImage(game, subject, type, options)
	options = options or {}
	local parts = utilsTable._filter(utilsString.notEmpty)({game, subject, type})
	local filename = table.concat(parts, " ") .. ".png"
	if Franchise.graphics(game) == "2D" then
		options.isPixelArt = true
	end
	return p.image(filename, options)
end

function p.icon(game, subject, options)
	local type = "Icon"
	if Franchise.graphics(game) == "2D" then
		type = "Sprite"
	end
	options = options or {}
	options.isPixelArt = true
	return p.gameImage(game, subject, type, options)
end

function p.logo(code, options)
	local filename = Franchise.logo(code)
	return p.image(filename, options)
end

function p.Schemas()
	local optionsSchema =  {
		type = "record",
		properties = {
			{
				name = "size",
				type = "string",
				desc = "Image size in pixels.",
			},
			{
				name = "scale",
				type = "number",
				desc = "Image scaling factor — the original image size is multitplied by <code>scale</code>. If both <code>scale</code> and <code>size</code> are present, the value which results in the smaller image will be used. <b>By default this uses an {{Mediawiki|Manual:$wgExpensiveParserFunctionLimit|expensive parser function}}</b>.",
			},
			{
				name = "scaleUsingCargo",
				type = "boolean",
				desc = "If set to true, then a Cargo query is used to determine the original image size for the <code>scale</code> option above. You can use this to avoid hitting expensive parser function limit. This option has an additional performance cost of roughly 2-5 milliseconds per image.",
			},
			{
				name = "link",
				type = "string",
				desc = "Name of a page on the wiki or an external URL for the image thumbnail to link to.",
			},
			{
				name = "caption",
				type = "string",
				desc = "[https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img Alt text] for the image.",
			},
			{
				name = "notPageImage",
				type = "boolean",
				desc = "If true, the image will never appear as the page's representative image in [https://www.mediawiki.org/wiki/Page_Previews page previews].",
			},
			{
				name = "checkExists",
				type = "boolean",
				default = "true",
				desc = "<p>If set to <code>false</code> then the function skips the file existence check. A red link is returned instead of the 'please upload' placeholder.</p><p>This may be needed to prevent [[:Category:Pages with too many expensive parser function calls|too many expensive parser function calls]] from occurring on a page.</p>",
			},
		}
	}
	local franchiseCode = {
		required = true,
		type = "string",
		desc = "A [[Data:Franchise|franchise code]]."
	}
	return {
		image = {
			filename = {
				required = true,
				type = "string",
				desc = "Filename of the image, with or without the namespace prefix.",
			},
			options = {
				type = "record",
				properties = utilsTable.concat(optionsSchema.properties, {
					{
						name = "isPixelArt",
						type = "boolean",
						desc = "If <code>true</code> the image will be rendered using nearest-neighbor interpolation, which prevents pixel art (sprites, 2D game screenshots) from appearing blurry in thumbnails.",
					},
				})
			},
		},
		gameImage = {
			game = franchiseCode,
			subject = {
				type = "string",
				required = true,
			},
			type = {
				type = "string",
				required = true,
				enum = {"", "Artwork", "Icon", "Model", "Render", "Screenshot", "Sprite", "Texture"},
			},
			options = optionsSchema,
		},
		icon = {
			game = franchiseCode,
			subject = {
				type = "string",
				required = true,
			},
			options = optionsSchema,
		},
		logo = {
			code = franchiseCode,
			optons = optionsSchema,
		},
	}
end

function p.Documentation()
	return {
		image = {
			desc = "A higher-level version of [[Module:UtilsMarkup#file|utilsMarkup.file]] with awareness of whether the file exists or not.",
			params = {"filename", "options"},
			returns = {
				"Wikitext rendering an image thumbnail.",
				"A boolean — true if the image exists, false otherwise.",
			},
			cases = {
				{
					args = {"File:TWW Great Fairy Figurine Model.png", { 
						link = "Great Fairy", 
						size = "100px"
					}},
					expect = {"[[File:TWW Great Fairy Figurine Model.png|100px|link=Great Fairy]]", true}
				},
				{
					desc = "If file does not exist, show 'click to upload' thumbnail which links to [[Special:Upload]].",
					args = {"File:TWWHD Great Fairy Figurine Model.png", {
						link = "Great Fairy", 
						size = "150px",
					}},
					expect = {"[[File:No Image Upload.png|150px|link=//zeldawiki.wiki/wiki/Special:Upload?wpDestFile=TWWHD+Great+Fairy+Figurine+Model.png|class=notpageimage]]", false}
				},
				{
					desc = "'No image' thumbnail has minimum 100px width, because it is illegible at smaller sizes.",
					args = {"File:TWWHD Great Fairy Figurine Model.png", {
						size = "64px",
					}},
					expect = {"[[File:No Image Upload.png|100px|link=//zeldawiki.wiki/wiki/Special:Upload?wpDestFile=TWWHD+Great+Fairy+Figurine+Model.png|class=notpageimage]]", false},
				},
				{
					desc = "<code>checkExists = false</code> skips the existence check and simply render a red link",
					args = {"File:TWWHD Great Fairy Figurine Model.png", {
						link = "Great Fairy", 
						size = "100px",
						checkExists = false,
					}},
					expect = {"[[File:TWWHD Great Fairy Figurine Model.png|100px|link=Great Fairy]]", nil}
				},
				{
					desc = "Scaling factor.",
					args = {"File:TMC Vaati Sprite.png", { scale = 2 }},
					expect = {"[[File:TMC Vaati Sprite.png|48x56px]]", true}
				},
				{
					desc = "The <code>isPixelArt</code> options ensures that sprites do not appear blurry.",
					args = {"File:TMC Vaati Sprite.png", { scale = 2, isPixelArt = true }},
					expect = {"[[File:TMC Vaati Sprite.png|48x56px|class=pixel-art]]", true},
				},
				{
					desc = "Scaling using Cargo instead of an expensive parser function.",
					args = {"File:TMC Vaati Sprite.png", { scale = 2, scaleUsingCargo = true, isPixelArt = true }},
					expect = {"[[File:TMC Vaati Sprite.png|48x56px|class=pixel-art]]", true},
				},
				{
					desc = "If both <code>scale</code> and <code>size</code> are specified, the one resulting in the smaller image is used.",
					args = {"File:TMC Vaati Sprite.png", { scale = 2, size = "80px", isPixelArt = true }},
					expect = {"[[File:TMC Vaati Sprite.png|48x56px|class=pixel-art]]", true},
				},
				{
					args = {"File:TMC Vaati Sprite.png", { scale = 10, size = "80px", isPixelArt = true }},
					expect = {"[[File:TMC Vaati Sprite.png|80px|class=pixel-art]]", true},
				},
				{
					desc = "Applying <code>notpageimage</code>.",
					args = {"File:TMC Vaati Sprite.png", { notPageImage=true, isPixelArt = true }},
					expect = {"[[File:TMC Vaati Sprite.png|class=notpageimage pixel-art]]", true},
				},
			},
		},
		gameImage = {
			desc = "A specialized version of [[Module:File#image|image]] that infers the filename from game, subject, and type.",
			params = {"game", "subject", "type", "options"},
			returns = {
				"A <code>string</code> of wikitext that renders a thumbnail.",
				"A boolean — true if the image exists, false otherwise.",
			},
			cases = {
				{
					args = {"TWW", "Great Fairy Figurine", "Model", { 
						link = "Great Fairy", 
						size = "100px"
					}},
					expect = {"[[File:TWW Great Fairy Figurine Model.png|100px|link=Great Fairy]]", true}
				},
			}
		},
		icon = {
			params = {"game", "subject", "options"},
			returns = "An icon thumbnail for the subject in the given game.",
			cases = {
				{
					args = {"LANS", "Pineapple"},
					expect = "[[File:LANS Pineapple Icon.png|class=pixel-art]]"
				},
				{
					args = {"LADX", "Pineapple"},
					expect = "[[File:LADX Pineapple Sprite.png|class=pixel-art]]"
				},
			}
		},
		logo = {
			params = {"code", "options"},
			returns = {
				"Given a valid [[Data:Franchise|franchise code]], returns a logo thumbnail.",
				"A boolean indicating whether a logo exists for the game yet.",
			},
			cases = {
				{
					args = {"TWW", { size = "200px" }},
					expect = {"[[File:TWW English Logo.png|200px]]", true}
				},
				{
					args = {"SSB4", { size = "200px" }},
					expect = {"[[File:SSB4 Logo.png|200px]]", true},
				},
				{
					args = {"SS (Himekawa)", { size = "200px" }},
					expect = {"[[File:Viz Media Logo.svg|200px]]", true}
				},
				{
					args = {"TLoZ (Mishouzaki)", { size = "200px" }},
					expect = {"[[File:TLoZ (Mishouzaki) Manga Cover Artwork.png|200px]]", true},
				},
				{
					args = {"TAoL (Mishouzaki)", { size = "200px" }},
					expect = {"[[File:No Image Upload.png|200px|link=//zeldawiki.wiki/wiki/Special:Upload?wpDestFile=TAoL+%28Mishouzaki%29+Manga+Cover+Artwork.png|class=notpageimage]]", false},
				},
				{
					args = {"E", { size = "200px" }},
					expect = {"[[File:The Legend of Zelda Encyclopedia Cover.png|200px]]", true},
				},
				{
					args = {"TMoL", { size = "200px" }},
					expect = {"[[File:Misadventures Link logo2.png|200px]]", true},
				},
			}
		}
	}
end

return p