Module:Icon: Difference between revisions

From Honkai: Nexus Anima Wiki
Jump to navigation Jump to search
Valaerys (talk | contribs)
Created page with "-- Module copied from the Genshin Impact wiki -- Revision as of 4-29-2023 --- A library that other modules can use to create icon images with automatic prefix/suffix settings for items, characters, and weapons. -- (Other icon types must have their types/suffixes specified manually.) -- -- '''Note:''' this module is (currently) NOT related to Template:Icon. -- -- @script Icon local TemplateData = require('Module:TemplateData') local p = {} -- icon arg defaults..."
 
Valaerys (talk | contribs)
No edit summary
Line 33: Line 33:
label='File Prefix',
label='File Prefix',
description='The file prefix to prepend to {labelPrefix}Name.',
description='The file prefix to prepend to {labelPrefix}Name.',
example={'Item', 'Light Cone', 'Character', 'Icon'}
example={'Item', 'Nexus Strand', 'Relic', 'Icon'}
},
},
{name='suffix', displayDefault='determined based on {labelPrefix}Name/{labelPrefix}Type',
{name='suffix', displayDefault='determined based on {labelPrefix}Name/{labelPrefix}Type',
Line 158: Line 158:
local ALL_DATA = {-- list of {type, data} in the order that untyped items should get checked
local ALL_DATA = {-- list of {type, data} in the order that untyped items should get checked
{'Character', mw.loadData('Module:Card/characters')},
{'Character', mw.loadData('Module:Card/characters')},
{'Anima', mw.loadData('Module:Card/animas')},
{'Relic', mw.loadData('Module:Card/relics')},
{'Nexus Strand', mw.loadData('Module:Card/nexusstrands')},
{'Item', mw.loadData('Module:Card/items')} -- Always leave this one as the last in this list
{'Item', mw.loadData('Module:Card/items')} -- Always leave this one as the last in this list
}
}
Line 302: Line 305:
     The main entry point for other modules.
     The main entry point for other modules.
     Creates and returns an Image object with the given arguments.
     Creates and returns an Image object with the given arguments.
     Infers `args.type` if `args.name` matches a known item/character/Light Cone.
     Infers `args.type` if `args.name` matches a known item/character/relic.
     @param {table} args Table containing the arguments:
     @param {table} args Table containing the arguments:
     @param[opt] {string} args.name The name of the image.
     @param[opt] {string} args.name The name of the image.
Line 352: Line 355:
      
      
     -- set defaults and load data based on type
     -- set defaults and load data based on type
     if image_type == 'Character' or image_type == 'Currency Wars Character' then
     if image_type == 'Character' then
image.prefix = 'Character'
image.defaults.suffix = 'Character Icon'
image.defaults.suffix = 'Icon'
     elseif image_type == 'Anima' then
     elseif image_type == 'Element' then
image.defaults.suffix = 'Anima Icon'
image.prefix = 'Type'
elseif image_type == 'Item' then
elseif image_type == 'Consumable' then
image.prefix = 'Item'
image.prefix = 'Item'
elseif image_type == 'Relic' then
elseif image_type == 'Relic' then
image.prefix = 'Item'
image.prefix = 'Relic'
elseif image_type == 'Profile Picture' then
elseif image_type == 'Nexus Strand' then
image.prefix = 'Profile Picture'
image.prefix = 'Nexus Strand'
image.link = image.name
image.name = image.name:gsub(' %(Profile Picture%)', '')
elseif image_type == 'Enemy' or image_type == 'Aether Enemy' then
image.prefix = 'Icon Enemy'
image.link = (data and data.link) or image.name
image.defaults.suffix = ''
end
end
return image, image_type, data
return image, image_type, data

Revision as of 22:52, 14 July 2026

This module is used by {{Card}}.


-- Module copied from the Genshin Impact wiki
-- Revision as of 4-29-2023

--- A library that other modules can use to create icon images with automatic prefix/suffix settings for items, characters, and weapons.
--  (Other icon types must have their types/suffixes specified manually.)
--
--  '''Note:''' this module is (currently) NOT related to [[Template:Icon]].
--
--  @script Icon

local TemplateData = require('Module:TemplateData')

local p = {}

-- icon arg defaults for template data
-- uses list format to ensure that the order is the same when added to another list of args using `p.addIconArgs`
local ICON_ARGS = {
	{name='name',
		label='Name',
		description='The name of the {labelPrefix}image.',
		example={'Fire'}
	},
	{name='link', displayType='wiki-page-name', defaultFrom='name',
		label='Link',
		description='The page that the {labelPrefix}image links to.'
	},
	{name='extension', alias='ext', default='png',
		label='File Extension',
		description='The file extension for the {labelPrefix}image.',
		example={'png', 'jpg', 'jpeg', 'gif'},
	},
	{name='type', displayDefault='determined based on {labelPrefix}Name; \'Item\' if unknown',
		label='File Prefix',
		description='The file prefix to prepend to {labelPrefix}Name.',
		example={'Item', 'Nexus Strand', 'Relic', 'Icon'}
	},
	{name='suffix', displayDefault='determined based on {labelPrefix}Name/{labelPrefix}Type',
		label='File Suffix',
		description='The file suffix to append to {labelPrefix}Name.',
		example={'Icon', 'Thumb', '2nd', 'White'}
	},
	{name='size', default='20',
		label='Size',
		description='The height and width of the {labelPrefix}image in pixels. A single number will be used for both height and width; to specify them separately, use "wxh" format.',
		example={'20', '20x10', '20x', 'x20'}
	},
	{name='alt', defaultFrom='name', displayDefault='determined based on {labelPrefix}Name',
		label='Alt Text',
		description='The alt text of the {labelPrefix}image.',
	},
	{name='class', default='', displayDefault='N/A',
		label='Additional Classes',
		description='Additional CSS classes to apply to the resulting img element.',
	}
}

--- Returns a table version of the input.
--  @param v A table or an item that belongs in a table.
--  @return {table}
local function ensureTable(v)
	if type(v) == 'table' then return v end
	return {v}
end

--- A special constant that can be used as a value in the `overrides` parameter for `addIconArgs`
--  to disable the given base config or TemplateData key.
p.EXCLUDE = {};

--- Copy entries from b into a, excluding values that are `p.EXCLUDE`.
--  @param {table} a Table to insert into.
--  @param {table} b Table to copy from.
local function copyTable(a, b)
	for k, v in pairs(b) do 
		if v == p.EXCLUDE then
			v = nil
		end
		a[k] = v
	end
end

--- A function that other modules can use to append Icon arguments to their template data.
--  @param {TemplateData#ArgumentConfigList} base The template data to append to.
--         If any configs have a `name` that matches an Icon argument's (with `namePrefix`)
--         and a property `placeholderFor` set to `'Module:Icon'`, then the
--         corresponding Icon argument will replace it instead of being appended.
--         (This allows argument order to be changed for [[Module:TemplateData]]'s
--         documentation generation.)
--  @param {string} namePrefix A string to prepend to all parameter names.
--  @param {string} labelPrefix A string to prepend to all parameter labels
--    (the names displayed in documentation).
--  @param {TemplateData#ArgumentConfigMap} overrides A table of overrides to configure the template data.
--    Keys should be parameter names, and values are tables of TemplateData
--    configuration objects to merge with the default configuration.
--    These configuration objects can use @{Icon.EXCLUDE} as values to disable
--    the corresponding default configuration key (e.g., to disable a default value
--    or alias without adding a new one).
function p.addIconArgs(baseConfigs, namePrefix, labelPrefix, overrides)
	-- preprocessing: save position of each placeholder config
	local argLocations = {}
	for i, config in ipairs(baseConfigs) do
		if config.placeholderFor == 'Module:Icon' then
			argLocations[config.name] = i
		end
	end
	
	-- main loop: prepend namePrefix and labelPrefix where needed
	-- and add configs to baseConfigs
	for _, config in ipairs(ICON_ARGS) do
		local override = overrides[config.name]
		if override ~= false and override ~= p.EXCLUDE then
			local c = {}
			copyTable(c, config)
			c.name = namePrefix .. c.name
			c.label = labelPrefix .. c.label
			if c.defaultFrom then
				c.defaultFrom = namePrefix .. c.defaultFrom
			end
			if c.alias then
				local aliases = {}
				for _, a in ipairs(ensureTable(c.alias)) do
					table.insert(aliases, namePrefix .. a)
				end
				c.alias = aliases
			end
			
			if override then
				copyTable(c, override)
			end
			
			if c.description then
				c.description = c.description:gsub('{labelPrefix}', labelPrefix)
			end
			if c.displayDefault then
				c.displayDefault = c.displayDefault:gsub('{labelPrefix}', labelPrefix)
			end
			
			local placeholderIndex = argLocations[c.name]
			if placeholderIndex then
				baseConfigs[placeholderIndex] = c
			else
				table.insert(baseConfigs, c)
			end
		end
	end
end

local function extendTable(base, extra)
	out = {}
	setmetatable(out, {
		__index = function(t, key)
			local val = base[key]
			if val ~= nil then return val else return extra[key] end
		end
	})
	return out
end
--local characters = mw.loadData('Module:Card/items')
local ALL_DATA = {-- list of {type, data} in the order that untyped items should get checked
	{'Character', mw.loadData('Module:Card/characters')},
	{'Anima', mw.loadData('Module:Card/animas')},
	{'Relic', mw.loadData('Module:Card/relics')},
	{'Nexus Strand', mw.loadData('Module:Card/nexusstrands')},
	{'Item', mw.loadData('Module:Card/items')} -- Always leave this one as the last in this list
}

--- A basic image type with filename prefix/suffix support.
--  Extends @{TemplateData#TableWithDefaults} with image-related properties,
--  allowing default property values to be customized after creation.
--
--  Image objects are created by @{Icon.createIcon}.
--  Use @{Image:buildString} to convert to wikitext.
--  @type Image
local IMAGE_ARGS = {
	size = {default=''},
	name = {default='', alias=1},
	prefix = {default=''},
	prefixSeparator = {default=' '},
	suffix = {default=''},
	suffixSeparator = {default=' '},
	extension = {default='png', alias='ext'},
	link = {defaultFrom='name'},
	alt = {defaultFrom='name'},
	class = {default=''},
}

local function buildImageFullPrefix(img)
	local prefix = img.prefix
	if prefix ~= '' then
		return prefix .. img.prefixSeparator
	end
	return ''
end
local function buildImageFullSuffix(img)
	local suffix = img.suffix
	if suffix ~= '' then
		return img.suffixSeparator .. suffix
	end
	return ''
end
local function buildImageFilename(img)
	if img.name == '' then return '' end
	return 'File:' .. buildImageFullPrefix(img) .. img.name .. buildImageFullSuffix(img) .. '.' .. img.extension
end
local function buildImageSizeString(img)
	local size = img.size
	if size == nil or size == '' then
		return ''
	end
	size = tostring(size)
	if size:find('x', 1, true) then
		return size .. 'px'
	end
	return size .. 'x' .. size .. 'px'
end
--[[
Returns wikitext that will display this image.
@return {string} Wikitext
@function Image:buildString
--]]
local function buildImageString(img)
	local filename = buildImageFilename(img)
	if filename == '' then return '' end
	return '[[' .. filename .. '|' .. buildImageSizeString(img) .. '|link=' .. img.link .. '|alt=' .. img.alt .. '|class=' .. img.class .. ']]'
end

--[[
Creates an `Image` object with the given properties.
@param {table} args A table of `Image` properties that to assign to the new `Image`.
@see @{Image} for property documentation
@return {Image} The new `Image` object.
@constructor
--]]
local function createImage(args)
	local out
	if type(args) == 'table' then
		out = TemplateData.processArgs(args, IMAGE_ARGS, {preserveDefaults=true})
	else
		out = {name = args}
	end
	-- add buildString function to image directly, not to image.nonDefaults
	
	rawset(out, 'buildString', buildImageString)
	return out
end

--- The name of the image. Used to determine filename.
--  @property {string} Image.name

--- Maximum image size using wiki image syntax.
--  Unlike regular wiki image syntax, a single number specifies both height and width.
--  @property {string} Image.size

--- Image file prefix.
--  @property {string} Image.prefix

--- Appended to `prefix` if `prefix` is not empty. Defaults to a single space.
--  @property[opt] {string} Image.prefixSeparator

--- Image file suffix.
--  @property {string} Image.suffix

--- Prepended to `suffix` if `suffix` is not empty. Defaults to a single space.
--  @property {string} Image.suffixSeparator

--- Image file extension. (Alias: `ext`.)
--  @property {string} Image.extension

--- Image link. Also sets title (hover tooltip). Defaults to `name`.
--  @property {string} Image.link

--- Image alt text. Defaults to `name`.
--  @property {string} Image.alt


--- A helper function for other modules to get icon args with a prefix from the given table.
--  @param {table} args A table containing icon args (and probably other args).
--  @param {string} prefix Prefix for keys to use when looking up entries from `args`.
--    If not specified, no prefix is used.
--  @return {table} A table containing only the extracted args, with the prefix removed from its keys.
function p.extractIconArgs(args, prefix)
	prefix = prefix or ''
	local out = TemplateData.createObjectWithDefaults()
	for _, config in pairs(ICON_ARGS) do
		out.defaults[config.name] = args.defaults[prefix .. config.name]
		out.nonDefaults[config.name] = args.nonDefaults[prefix .. config.name]
	end
	return out
end

--- A helper function that removes one of the given prefixes from the given string.
--  @param {string} str The string from which to strip a prefix
--  @param {table} prefixes A table whose keys are the possible prefixes to strip from `str`
--  @return {string} The string with the prefix removed.
--  @return[opt] {string} The prefix that was removed, or `nil` if no prefix was found.
function p.stripPrefixes(str, prefixes)
	for prefix, _ in pairs(prefixes) do
		if string.sub(str, 1, string.len(prefix)) == prefix then
			return string.sub(str, string.len(prefix) + 1), prefix
		end
	end
	return str
end

--[[
    The main entry point for other modules.
    Creates and returns an Image object with the given arguments.
    Infers `args.type` if `args.name` matches a known item/character/relic.
    @param {table} args Table containing the arguments:
    @param[opt] {string} args.name The name of the image.
                         Used to determine file name and set the default link and alt text.
                         If not specified, the output `Image` will produce empty wikitext.
    @param[opt] {string} args.link Image link. Also sets title (hover tooltip).
                         Defaults to `name`.
    @param[opt] {string} args.extension (alias: `ext`) Image file extension.
                         Defaults to 'png'.
    @param[opt] {string} args.type Image type. Used to determine file prefix and default file suffix.
                         If not specified, type will be inferred if `args.name`
                         is a known item; otherwise, defaults to 'Item'.
    @param[opt] {string} args.suffix File suffix override.
    @param[opt] {string} args.size Maximum image size using wiki image syntax.
                         Unlike regular wiki image syntax, specifying a single number will
                         set both height and width.
    @param[opt] {string} args.alt Image alt text. Defaults to `args.name`.
    @param[opt] {string} args.outfit Character outfit. Only applies to character images.
    @param[opt] {string} prefix Prefix to use when looking up arguments in `args`.
    @return {Image} The image for given arguments.
      Use `Image:buildString()` to get the wikitext for the image.
    @return {string} The image type.
    @return {TableWithDefaults} Associated data for given item (e.g., rarity, display name).
--]]
function p.createIcon(args, prefix)
	if prefix then
		args = p.extractIconArgs(args, prefix)
	end
	args = TemplateData.processArgs(args, ICON_ARGS, {preserveDefaults=true})
	--local baseName, prefix = p.stripPrefixes(args.name or '', FOOD_PREFIXES)
	-- for now, there are no items that need special prefixes
	local baseName = args.name or ''
	local prefix = ''
	
	-- determine type by checking for data
	local image_type, data
	for i, v in ipairs(ALL_DATA) do
		image_type = v[1]
		if args.type == nil or args.type == image_type then
			data = v[2][baseName]
			if (not data) then data = v[2][baseName .. ' (' .. image_type .. ')'] end
			if data then break end
		end
	end
	image_type = args.type or image_type -- in case args.type isn't in ALL_DATA (e.g., Enemy, Wildlife)
	
	local image = createImage(args)
	image.prefix = image_type
    
    -- set defaults and load data based on type
    if image_type == 'Character' then
		image.defaults.suffix = 'Character Icon'
    elseif image_type == 'Anima' then
		image.defaults.suffix = 'Anima Icon'
	elseif image_type == 'Item' then
		image.prefix = 'Item'
	elseif image_type == 'Relic' then
		image.prefix = 'Relic'
	elseif image_type == 'Nexus Strand' then
		image.prefix = 'Nexus Strand'
	end
	return image, image_type, data
end

return p