Module:Icon: Difference between revisions
From The Petit Planet Wiki
More actions
ReisuDesign (talk | contribs) No edit summary |
ReisuDesign (talk | contribs) No edit summary |
||
| (3 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
-- | --- 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 = {} | local p = {} | ||
function p. | local FOOD_PREFIXES = { | ||
['Suspicious '] = 1, | |||
['Delicious '] = 1, | |||
} | |||
-- 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={'Furnishing Blueprint', 'Fruit Paste Bait', 'Anemo'} | |||
}, | |||
{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', 'Weapon', 'Character', '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, and updated based on {labelPrefix}Character Outfit and {labelPrefix}Weapon Ascension Phase', | |||
label='Alt Text', | |||
description='The alt text of the {labelPrefix}image.', | |||
}, | |||
{name='outfit', alias='o', | |||
label='Character Outfit', | |||
description='Name of the Outfit equipped on the character in the {labelPrefix}image. (Ignored if not a character.)', | |||
example='Sea Breeze Dandelion' | |||
}, | |||
{name='ascension', alias='a', type='number', default=0, | |||
label='Weapon Ascension Phase', | |||
description='Ascension Phase of the weapon in the {labelPrefix}image. (Weapon image changes for ascension 2 or higher. Ignored if not a weapon.)', | |||
example={'1', '2'} | |||
}, | |||
} | |||
--- 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) | |||
-- be defensive: base or extra may be nil | |||
local val | |||
if base ~= nil then | |||
val = base[key] | |||
end | |||
if val ~= nil then | |||
return val | |||
end | |||
if extra ~= nil then | |||
return extra[key] | |||
end | |||
return nil | |||
end | |||
}) | }) | ||
return | return out | ||
end | end | ||
local neighbors = mw.loadData('Module:Card/neighbors') | |||
local ALL_DATA = {-- list of {type, data} in the order that untyped items should get checked | |||
{'Neighbor', neighbors}, | |||
{'Creature', mw.loadData('Module:Card/creatures')}, | |||
{'Dish', mw.loadData('Module:Card/dishes')}, | |||
{'Plant', mw.loadData('Module:Card/plants')}, | |||
{'Furniture', mw.loadData('Module:Card/furnitures')}, | |||
{'Outfit', mw.loadData('Module:Card/outfits')}, | |||
{'Item', extendTable(characters, mw.loadData('Module:Card/items'))} -- allow characters to be items | |||
} | |||
--- 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'}, | |||
} | |||
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 .. ']]' | |||
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 | |||
local | |||
--- 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 | 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. | |||
if | 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 | ||
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/weapon. | |||
@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`, but | |||
also changes with `args.outfit` or `args.ascension`. | |||
@param[opt] {string} args.outfit Character outfit. Only applies to character images. | |||
@param[opt] {number} args.ascension Weapon ascension level. Only applies to weapon 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) | |||
-- | -- determine type by checking for data | ||
if | 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 data then break end | |||
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.suffix = 'Icon' | |||
image.defaults.suffix = 'Icon' | |||
return image, image_type, data | |||
end | end | ||
return p | return p | ||