|
|
| (41 intermediate revisions by 4 users not shown) |
| Line 1: |
Line 1: |
| | |
| local p = {} | | local p = {} |
| | |
| local lib = require('Module:Feature') | | local lib = require('Module:Feature') |
| | local ne = lib.isNotEmpty |
| local TemplateData = require('Module:TemplateData') | | local TemplateData = require('Module:TemplateData') |
| local Icon = require('Module:Icon') | | local array = require('Module:Array') |
| | | local CentralData = require('Module:CentralData') |
|
| |
|
| local QUALITY_STARS = { | | local allData = CentralData.dataSheets |
| ['1'] = '[[File:Icon 1 Star.png|x16px|link=|alt=Quality 1]]',
| |
| ['2'] = '[[File:Icon 2 Stars.png|x16px|link=|alt=Quality 2]]',
| |
| ['3'] = '[[File:Icon 3 Stars.png|x16px|link=|alt=Quality 3]]',
| |
| ['4'] = '[[File:Icon 4 Stars.png|x16px|link=|alt=Quality 4]]',
| |
| ['5'] = '[[File:Icon 5 Stars.png|x16px|link=|alt=Quality 5]]'
| |
| }
| |
| local MILIASTRA_WONDERLAND_QUALITY_STARS = {
| |
| ['1'] = '[[File:Miliastra 1 Star.png|x16px|link=|alt=Quality 1]]',
| |
| ['2'] = '[[File:Miliastra 2 Star.png|x16px|link=|alt=Quality 2]]',
| |
| ['3'] = '[[File:Miliastra 3 Star.png|x16px|link=|alt=Quality 3]]',
| |
| ['4'] = '[[File:Miliastra 4 Star.png|x16px|link=|alt=Quality 4]]',
| |
| ['5'] = '[[File:Miliastra 5 Star.png|x16px|link=|alt=Quality 5]]'
| |
| }
| |
| local PREFIX_ICONS = {
| |
| ['Instructions: '] = {name='Instructions', type='Item'},
| |
| ['Diagram: '] = {name='Diagram', type='Item'},
| |
| ['Recipe: '] = {name='Recipe', type='Item'},
| |
| ['Formula: '] = {name='Formula', type='Item'},
| |
| ['Blueprint: '] = {name='Furnishing Blueprint', type='Icon'},
| |
| }
| |
|
| |
|
| -- main template/module parameters
| |
| local CARD_ARGS = { | | local CARD_ARGS = { |
| { | | { |
| name='name', alias={1,'character'}, displayName=1, | | name = 'name', |
| status='suggested',
| | alias = 1, |
| label='Name',
| | default = 'Unknown', |
| description='The name of the image (without the prefix or extension).',
| |
| default='Unknown',
| |
| example={'Mora', 'Primogem', 'Amber'},
| |
| },
| |
| {
| |
| name='text', alias=2, displayName=2, | |
| label='Card Text',
| |
| description='The text below the image.',
| |
| default='—',
| |
| displayDefault='"—" for most items; same as Image Name for characters',
| |
| example={'100', 'Lv. 1', 'Set'},
| |
| },
| |
| {
| |
| name='multiline_text', type='1',
| |
| label='Allow Multiple Lines of Card Text',
| |
| trueDescription='allow card text to wrap to a new line if necessary.',
| |
| },
| |
| {
| |
| name='text_size', type='string',
| |
| label='Size of Card Text',
| |
| description='Adds the "card-text-<text_size>" class, including "small", "smaller".',
| |
| },
| |
| {
| |
| name='quality', displayType='number',
| |
| label='Card Quality',
| |
| description='The Quality of the item. For light background, add 10. Use 0 for white version. Use multiple numbers for split rarities.',
| |
| default='0', | |
| displayDefault='determined based on Image Name; "0" if unknown',
| |
| example={'1', '2', '3', '4', '5', '123', '23', '34', '45'},
| |
| },
| |
| {
| |
| name='type', placeholderFor='Module:Icon',
| |
| },
| |
| {
| |
| name='suffix', placeholderFor='Module:Icon',
| |
| },
| |
| {
| |
| name='extension', placeholderFor='Module:Icon',
| |
| },
| |
| {
| |
| name='link', displayType='wiki-page-name',
| |
| label='Card Link',
| |
| description='The page to link to when image or caption text is clicked.',
| |
| displayDefault='same as Image Name',
| |
| defaultFrom='name',
| |
| example={'Mora', 'Dressing Room', 'Shops', 'Amber'},
| |
| }, | | }, |
| { | | { |
| name='link_suffix', | | name = 'label', |
| label='Page Link Suffix', | | alias = {2, 'text', 'count', 'amount', 'x'}, |
| description='Text to append to the Page Link. (Usually used to link to page sections.)',
| |
| default='',
| |
| example='#Trivia',
| |
| }, | | }, |
| { | | { |
| name='nolink', type='1', | | name = 'show_label', |
| label='No Link', | | alias = 'show_text', |
| trueDescription='remove default links from card image, icons, and caption.', | | type = '1', |
| displayDefault='"1" if Image Name is default ("Unknown")',
| |
| }, | | }, |
| { | | { |
| name='icon', displayType='content', | | name = 'quality', |
| label='Icon', | | alias = 'rarity', |
| description='The icon at the top left of the card.', | | default = 'Common', |
| example={'{{Icon/Element|Pyro|25}}', '[[File:Item Primogem.png|25px]]'},
| |
| }, | | }, |
| { | | { |
| name='icon_style', displayType='string', | | name = 'type', |
| label='Icon Style',
| |
| description='The custom style of the icon at the top left of the card. Omit the \'\' used for CSS.',
| |
| example='background: red;',
| |
| }, | | }, |
| { | | { |
| name='icon_right', displayType='content', | | name = 'split', |
| label='Top-Right Icon',
| |
| description='Icon on the top right of the card.',
| |
| example='{{Icon/Element|Pyro|25}}',
| |
| }, | | }, |
| { | | { |
| name='icon_right_style', displayType='string', | | name = 'suffix', |
| label='Top-Right Icon Style',
| | default = '', |
| description='The custom style of the icon at the top right of the card. Omit the \'\' used for CSS.',
| |
| example='background: red;', | |
| }, | | }, |
| { | | { |
| name='icon_bottom_left', displayType='content', | | name = 'image', |
| label='Bottom-Left Icon',
| |
| description='Icon on the bottom left of the card.',
| |
| example='{{Icon/Element|Pyro|25}}',
| |
| }, | | }, |
| { | | { |
| name='icon_bottom_left_style', displayType='string', | | name = 'image_size', |
| label='Bottom-Left Icon Style', | | alias = {'imageSize', 'size'}, |
| description='The custom style of the icon at the bottom left of the card. Omit the \'\' used for CSS.',
| |
| example='background: red;',
| |
| }, | | }, |
| { | | { |
| name='icon_bottom_right', displayType='content', | | name = 'image_ext', |
| label='Bottom-Right Icon',
| | alias = {'imageExt', 'ext', 'extension'}, |
| description='Icon on the bottom right of the card.',
| | default = 'png', |
| example='{{Icon/Element|Pyro|25}}', | |
| }, | | }, |
| { | | { |
| name='icon_bottom_right_style', displayType='string', | | name = 'link', |
| label='Bottom-Right Icon Style',
| |
| description='The custom style of the icon at the bottom right of the card. Omit the \'\' used for CSS.',
| |
| example='background: red;',
| |
| }, | | }, |
| { | | { |
| name='show_caption', type='1', | | name = 'link_suffix', |
| label='Show Caption',
| | default = '', |
| trueDescription='show caption text below the card.', | |
| }, | | }, |
| { | | { |
| name='caption', displayType='string', | | name = 'no_link', |
| label='Caption Text',
| | type = '1', |
| description='The linked caption text that shows below the card.',
| |
| displayDefault='same as Name', | |
| defaultFrom='name',
| |
| example={'Apple', 'Rewards'},
| |
| }, | | }, |
| { | | { |
| name='caption_width', | | name = 'caption', |
| label='Caption Width',
| |
| description='Width of the captions. Set to \'auto\' to automatically increase the caption width to prevent it from wrapping in the middle of words.',
| |
| displayDefault='same as card width (74px, or 40px for mini cards)',
| |
| example={'200px', 'auto'},
| |
| }, | | }, |
| { | | { |
| name='note', displayType='string', | | name = 'show_caption', |
| label='Caption Note',
| | type = '1', |
| description='The unlinked caption text that shows below the linked caption text.',
| |
| example='(Bonus reward)', | |
| }, | | }, |
| { | | { |
| name='refinement', alias='r', displayType='number', | | name = 'caption_width', |
| label='Refinement Rank', | | alias = 'captionWidth', |
| description='The refinement of the weapon. Set to \'1a\' to denote a weapon that cannot be refined.',
| |
| example={'1', '2', '3', '4', '5', '1a'},
| |
| }, | | }, |
| { | | { |
| name='ascension', placeholderFor='Module:Icon', | | name = 'mini', |
| | type = '1', |
| }, | | }, |
| { | | { |
| name='constellation', alias='c', displayType='number', | | name = 'first', |
| label='Constellation Level',
| | type = '1', |
| description='Constellation Level of the Character.',
| |
| example={'0', '1', '2', '3', '4', '5', '6'}, | |
| }, | | }, |
| { | | { |
| name='outfit', placeholderFor='Module:Icon', | | name = 'up', |
| | alias = 'UP', |
| | type = '1', |
| }, | | }, |
| { | | { |
| name='stars', type='1', | | name = 'notice', |
| label='Show Item Stars',
| |
| trueDescription='show the stars of the quality of the item. (Does not work if quality is "0" or split (e.g., "123" or "34").)',
| |
| },
| |
| {
| |
| name='set', type='1',
| |
| label='Show Set Icon',
| |
| displayDefault='"1" if the card type is "Artifact Set"',
| |
| trueDescription='show set icon at the top right corner of the card.',
| |
| },
| |
| {
| |
| name='vol', displayType='number',
| |
| label='Book Volume',
| |
| description='Volume number of the book (for cards that show books). Sets Card Text and Page Link Suffix to point to the given volume.',
| |
| example={'1', '2', '3'},
| |
| },
| |
| {
| |
| name='danger', type='1',
| |
| label='Danger',
| |
| trueDescription='add Warning icon as the Top-Right Icon.',
| |
| },
| |
| {
| |
| name='mini', type='1',
| |
| label='Mini',
| |
| trueDescription='show a smaller card. (Not all parameters apply to mini cards.)',
| |
| },
| |
| {
| |
| name='miliastra_wonderland', type='1',
| |
| label='Miliastra Wonderland',
| |
| trueDescription='Shows styles for Miliastra Wonderland items and cosmetics.',
| |
| },
| |
| {
| |
| name='mobile_list', type='1',
| |
| label='Mobile List Item',
| |
| trueDescription='show Template:Item-like display on mobile',
| |
| }, | | }, |
| } | | } |
| -- add parameters inherited from Icon for the main image, top-left/right icon, and equipped icon
| |
| Icon.addIconArgs(CARD_ARGS, '', '', { -- exclude args already present in CARD_ARGS or that don't apply to the main image
| |
| name=false,
| |
| link=false,
| |
| size=false,
| |
| alt=false,
| |
| })
| |
| Icon.addIconArgs(CARD_ARGS, 'icon_', 'Top-Left Icon ', { -- override to add `element` alias and document automatic icons
| |
| name={
| |
| alias='element',
| |
| description='Name of the icon to display at the top left of the card (without the prefix or extension).',
| |
| displayDefault='element icon for characters; furnishing blueprint/recipe/diagram icon if Name is prefixed accordingly; empty otherwise',
| |
| example={'Furnishing Blueprint', 'Fruit Paste Bait', 'Anemo'}
| |
| },
| |
| })
| |
| Icon.addIconArgs(CARD_ARGS, 'icon_right_', 'Top-Right Icon ', {
| |
| name={
| |
| description='Name of the icon to display at the top right of the card (without the prefix or extension).',
| |
| example={'Furnishing Blueprint', 'Fruit Paste Bait', 'Anemo'}
| |
| },
| |
| })
| |
| Icon.addIconArgs(CARD_ARGS, 'icon_bottom_left_', 'Bottom-Left Icon ', {
| |
| name={
| |
| description='Name of the icon to display at the bottom left of the card (without the prefix or extension).',
| |
| example={'Furnishing Blueprint', 'Fruit Paste Bait', 'Anemo'}
| |
| },
| |
| })
| |
| Icon.addIconArgs(CARD_ARGS, 'icon_bottom_right_', 'Bottom-Right Icon ', {
| |
| name={
| |
| description='Name of the icon to display at the bottom right of the card (without the prefix or extension).',
| |
| example={'Furnishing Blueprint', 'Fruit Paste Bait', 'Anemo'}
| |
| },
| |
| })
| |
| Icon.addIconArgs(CARD_ARGS, 'equipped_', 'Equipped ', { -- overrides to add `equipped`/`e` aliases and change default size
| |
| name={
| |
| alias={'equipped', 'e'},
| |
| description='Name of the weapon or character to display at the top right of the card (or bottom left, if Constellation Level is present; name does not include the prefix or extension).',
| |
| example={'Song of Broken Pines', 'Hu Tao'}
| |
| },
| |
| size={default='30'},
| |
| })
| |
|
| |
|
| |
|
| function p.main(frame) | | function p.main(frame) |
| local args = require('Module:Arguments').getArgs(frame, { | | local args = require('Module:Arguments').getArgs(frame, { |
| parentFirst = true,
| | wrapper = {'Template:Card'}, |
| wrapper = { 'Template:Card' } | | parentOnly = false |
| }) | | }) |
| return p._main(args, frame) | | |
| | return p._main(args) |
| end | | end |
|
| |
|
| -- apply defaults; load and apply data (e.g., quality, character element)
| | local function getDataByName(dataType, dataTable, name) |
| function p._processArgs(args)
| | local data = dataTable[name] |
| local out = TemplateData.processArgs(args, CARD_ARGS) | | |
|
| | if data then |
| -- set defaults that depend on other arguments
| | return data |
| out.defaults.show_caption = lib.isNotEmpty(out.nonDefaults.caption)
| |
| out.defaults.nolink = out.name == out.defaults.name and lib.isEmpty(out.nonDefaults.link)
| |
| if out.vol ~= nil then | |
| out.defaults.text = 'Vol. ' .. out.vol | |
| out.defaults.link_suffix = '#Vol._' .. out.vol
| |
| end | | end |
|
| |
|
| -- handle deprecated caption value | | local normalizedType = tostring(dataType or ''):lower() |
| if tostring(out.caption) == '1' then | | if normalizedType == 'neighbor' or normalizedType == 'neighbors' then |
| out.uses_deprecated_params = true | | return nil |
| out.caption = nil
| |
| out.show_caption = true
| |
| end | | end |
|
| | |
| -- handle nolink | | for quality, names in pairs(dataTable) do |
| out.final_link = out.nolink and '' or (out.link .. out.link_suffix)
| | if type(names) == 'table' then |
|
| | for _, itemName in ipairs(names) do |
| -- build args for main card image
| | if itemName == name then |
| local mainImageArgs = Icon.extractIconArgs(out)
| | return { |
| mainImageArgs.link = out.final_link
| | quality = quality |
| mainImageArgs.size = 74
| | } |
|
| | end |
| -- check for prefixes in `name` that correspond to top-left icons
| | end |
| -- note: priority of icon specification: `icon` arg > `icon_name` arg > prefix of `name` > character element from data
| |
| local baseName, prefix = Icon.stripPrefixes(out.name, PREFIX_ICONS)
| |
| if prefix then
| |
| -- configure icon if none is specified by `icon_name`,
| |
| -- making sure not to change `icon_type` if `icon_name` is explicitly specified
| |
| if out.icon_name == out.defaults.icon_name then
| |
| local prefixIcon = PREFIX_ICONS[prefix]
| |
| out.icon_name = prefixIcon.name
| |
| out.icon_type = prefixIcon.type | |
| end | | end |
| mainImageArgs.name = baseName
| |
| end | | end |
| | | |
| -- create card image and get type/data | | return nil |
| local card_type, data | | end |
| out.image, card_type, data = Icon.createIcon(mainImageArgs) | | |
|
| | function p.getTypeAndData(name, requestedType) |
| -- set defaults based on data
| | local img_type = requestedType or 'Item' |
| if data then
| | local img_data = nil |
| if card_type == 'Character' then | | |
| if out.icon_name == out.defaults.icon_name and data.element ~= 'Adaptive' and lib.isNotEmpty(data.element) then | | for _, v in ipairs(allData) do |
| out.icon_name = data.element | | local dataType = v[1] |
| out.icon_type = 'Element' | | local dataTable = v[2] |
| out.icon_link = '' | | |
| | if lib.isEmpty(requestedType) or dataType == requestedType then |
| | local data = getDataByName(dataType, dataTable, name) |
| | |
| | if data then |
| | img_type = dataType |
| | img_data = data |
| | break |
| end | | end |
| out.element = data.element or out.element
| |
| out.weapon = data.weapon or out.weapon
| |
| out.defaults.text = data.name or out.name
| |
| out.defaults.text_size = data.text_size or out.text_size
| |
| end | | end |
| if card_type == 'Enemy' then | | end |
| if out.icon_name == out.defaults.icon_name and lib.isNotEmpty(data.element) then
| | |
| out.icon_name = data.element
| | return img_type, img_data |
| out.icon_type = 'Element'
| | end |
| out.icon_link = ''
| | |
| end
| | local function normalizeBool(value) |
| out.element = data.element or out.element | | return value == true or value == '1' or value == 1 or value == 'yes' |
| | end |
| | |
| | local function normalizeClassName(value) |
| | return tostring(value or '') |
| | :lower() |
| | :gsub('%s+', '-') |
| | end |
| | |
| | local function normalizeQuality(quality) |
| | quality = tostring(quality or '') |
| | |
| | if quality:find(';', 1, true) then |
| | quality = array._main({ |
| | quality, |
| | ';', |
| | firstItemOnly = 1 |
| | }) |
| | end |
| | |
| | if lib.isEmpty(quality) then |
| | quality = 'Common' |
| | end |
| | |
| | return normalizeClassName(quality) |
| | end |
| | |
| | local function stripLinkPrefix(value) |
| | value = tostring(value or '') |
| | |
| | -- Converts "Luca: Myriad Meadows" to "Myriad Meadows". |
| | return mw.text.trim(value:gsub('^.-:%s*', '', 1)) |
| | end |
| | |
| | local function setCaptionWidth(node, width) |
| | if width == 'auto' or lib.isEmpty(width) then |
| | node:addClass('auto-width') |
| | else |
| | node:css('width', width) |
| | end |
| | end |
| | |
| | -- Generates the second icon for a split card. |
| | local function makeSplitIcon(name, mini) |
| | name = tostring(name or '') |
| | |
| | local size = mini and 74 or 56 |
| | |
| | return '[[File:' .. |
| | lib.sanitizeFileName(name) .. |
| | ' Icon.png|' .. |
| | size .. 'x' .. size .. |
| | 'px|link=' .. |
| | name .. |
| | ']]' |
| | end |
| | |
| | function p._processArgs(args) |
| | local out = TemplateData.processArgs(args, CARD_ARGS) |
| | |
| | -- Basic identity |
| | out.name = out.name or 'Unknown' |
| | out.split = out.split or '' |
| | |
| | -- Use only a manually supplied type for lookup. |
| | local requestedType = out.nonDefaults |
| | and out.nonDefaults.type |
| | or nil |
| | |
| | out.type, out.data = p.getTypeAndData( |
| | out.name, |
| | requestedType |
| | ) |
| | |
| | -- Base name for assets. |
| | -- Removes a trailing disambiguation such as "(Currency)". |
| | out.image_name = out.name--:gsub('%s*%([^()]*%)$', '') |
| | |
| | -- Boolean parameters |
| | out.mini = normalizeBool(out.mini) |
| | out.first = normalizeBool(out.first) |
| | out.up = normalizeBool(out.up) |
| | out.no_link = normalizeBool(out.no_link) |
| | out.show_label = normalizeBool(out.show_label) |
| | out.show_caption = normalizeBool(out.show_caption) |
| | |
| | -- Image defaults |
| | out.suffix = out.suffix or '' |
| | out.image_ext = out.image_ext or 'png' |
| | |
| | if lib.isEmpty(out.image_size) then |
| | out.image_size = out.mini and 48 or 70 |
| | end |
| | |
| | if lib.isEmpty(out.suffix) then |
| | out.suffix = ' Icon' |
| | end |
| | |
| | -- Data-driven defaults |
| | if out.data then |
| | if out.data.name then |
| | out.defaults.label = out.data.name |
| | out.defaults.caption = out.data.name |
| end | | end |
| if card_type == 'Fish' then | | |
| if out.icon_name == out.defaults.icon_name and lib.isNotEmpty(data.bait) then
| | if out.data.title then |
| out.icon_name = data.bait
| | out.defaults.caption = out.data.title |
| out.icon_type = 'Item'
| |
| out.icon_link = ''
| |
| end
| |
| out.prefix = ''
| |
| end | | end |
| if card_type == 'Food' then | | |
| if out.icon_name == out.defaults.icon_name and lib.isNotEmpty(data.effectType) then | | if out.data.quality then |
| out.icon_name = data.effectType | | out.defaults.quality = out.data.quality |
| out.icon_type = 'Icon'
| | |
| out.icon_link = ''
| | if not (out.nonDefaults and out.nonDefaults.quality) then |
| | out.quality = out.data.quality |
| end | | end |
| end
| |
| if card_type == 'Cosmetic Component' or card_type == 'Cosmetic Set' or data.mode == 'Miliastra Wonderland' then
| |
| out.miliastra_wonderland = true
| |
| end
| |
| if data.quality then
| |
| out.defaults.quality = data.quality
| |
| end
| |
| if data.title then
| |
| out.defaults.caption = data.title
| |
| end | | end |
| end | | end |
| | | |
| -- set other defaults based on card type | | -- Quality / rarity |
| if card_type == 'Artifact Set' then | | out.quality = normalizeQuality(out.quality) |
| out.defaults.set = true | | |
| | -- Label handling |
| | if out.show_label then |
| | out.label = out.data |
| | and (out.data.name or out.data.title) |
| | or out.name |
| end | | end |
|
| | |
| -- add top-left icon (if not specified by 'icon' wikitext)
| | if out.label == '0' then |
| if out.icon == out.defaults.icon then | | out.label = nil |
| local iconImage = Icon.createIcon(out, 'icon_')
| |
|
| |
| iconImage.defaults.size = lib.ternary(out.mini, 15, 20)
| |
| -- disable link if nolink is explicitly set, but icon_link is not
| |
| if out.nonDefaults.nolink then
| |
| iconImage.defaults.link = ''
| |
| end
| |
| out.icon = iconImage:buildString() | |
| end | | end |
|
| | |
| -- add top-right icon (if not specified by 'icon_right' wikitext) | | -- Type-specific behavior |
| if out.icon_right == out.defaults.icon_right then | | local lcType = tostring(out.type or ''):lower() |
| local iconImage = Icon.createIcon(out, 'icon_right_') | | |
|
| | if lcType == 'neighbor' then |
| iconImage.defaults.size = lib.ternary(out.mini, 15, 20)
| | if lib.isEmpty(out.label) then |
| -- disable link if nolink is explicitly set, but icon_link is not
| | if out.mini and out.data and out.data.shortName then |
| if out.nonDefaults.nolink then
| | out.label = out.data.shortName |
| iconImage.defaults.link = '' | | elseif not out.mini then |
| | out.label = out.name |
| | end |
| end | | end |
| out.icon_right = iconImage:buildString() | | |
| end
| | if tonumber(out.image_size) then |
|
| | out.image_size = tonumber(out.image_size) + 2 |
| -- add top-right icon (if not specified by 'icon_bottom_left' wikitext)
| |
| if out.icon_bottom_left == out.defaults.icon_bottom_left then
| |
| local iconImage = Icon.createIcon(out, 'icon_bottom_left_')
| |
|
| |
| iconImage.defaults.size = lib.ternary(out.mini, 15, 20)
| |
| -- disable link if nolink is explicitly set, but icon_link is not
| |
| if out.nonDefaults.nolink then
| |
| iconImage.defaults.link = ''
| |
| end | | end |
| out.icon_bottom_left = iconImage:buildString()
| |
| end | | end |
|
| | |
| -- add top-right icon (if not specified by 'icon_bottom_right' wikitext) | | if lcType == 'redirect' then |
| if out.icon_bottom_right == out.defaults.icon_bottom_right then
| | out.defaults.link = stripLinkPrefix(out.name) |
| local iconImage = Icon.createIcon(out, 'icon_bottom_right_') | | |
|
| | if not (out.nonDefaults and out.nonDefaults.link) then |
| iconImage.defaults.size = lib.ternary(out.mini, 10, 20)
| | out.link = stripLinkPrefix(out.name) |
| -- disable link if nolink is explicitly set, but icon_link is not | |
| if out.nonDefaults.nolink then
| |
| iconImage.defaults.link = '' | |
| end | | end |
| out.icon_bottom_right = iconImage:buildString()
| |
| end | | end |
|
| | |
| -- add equipped icon | | -- Caption defaults |
| if lib.isNotEmpty(out.equipped_name) then | | if out.show_caption and lib.isEmpty(out.caption) then |
| local equippedImage, equippedType = Icon.createIcon(out, 'equipped_') | | if out.data then |
| if equippedType == 'Character' then
| | out.caption = out.data.title |
| equippedImage.defaults.size = 50 | | or out.data.name |
| equippedImage.defaults.suffix = 'Side Icon'
| | or out.name |
| equippedImage.defaults.alt = 'Equipped on ' .. equippedImage.alt
| |
| else | | else |
| equippedImage.defaults.alt = 'Equipped with ' .. equippedImage.alt | | out.caption = out.name |
| end | | end |
| if out.nonDefaults.nolink then
| |
| equippedImage.defaults.link = ''
| |
| end
| |
| out.equipped = equippedImage:buildString()
| |
| end | | end |
| | | |
| -- add enemy danger icon
| | -- Link handling |
| if out.danger then | | if out.link == nil then |
| out.icon_right = '[[File:Icon Warning.png|25x25px|link=|alt=Warning icon]]'
| | out.link = lib.ternary( |
| out.icon_right_style = 'top: -8px; right: -10px; z-index: 1'
| | out.name == 'Unknown', |
| | '', |
| | out.name |
| | ) |
| | end |
| | |
| | out.link_suffix = out.link_suffix or '' |
| | out.final_link = out.link .. out.link_suffix |
| | |
| | if out.no_link then |
| | out.final_link = '' |
| end | | end |
|
| |
| return out
| |
| end
| |
|
| |
|
| local function setCaptionWidth(node, width)
| | -- Main image filename |
| if width == 'auto' then | | if ne(out.image) then |
| node:addClass('auto-width') | | out.final_file = out.image |
| else | | else |
| node:css('width', width) | | out.final_file = |
| | lib.sanitizeFileName(out.image_name) .. |
| | out.suffix .. |
| | '.' .. |
| | out.image_ext |
| end | | end |
| | |
| | -- Main image wikitext |
| | local linkPart = out.no_link |
| | and '|link=' |
| | or ('|link=' .. out.final_link) |
| | |
| | out.image_wikitext = table.concat({ |
| | '[[File:', |
| | out.final_file, |
| | '|', |
| | out.image_size, |
| | 'px|alt=', |
| | out.data and (out.data.name or out.data.title) |
| | or out.name, |
| | linkPart, |
| | ']]' |
| | }) |
| | |
| | return out |
| end | | end |
|
| |
|
| function p._main(args, frame) | | function p._main(args) |
| local a = p._processArgs(args) | | local a = p._processArgs(args) |
| | | local isSplit = ne(a.split) |
| local node_container = mw.html.create('div'):addClass('card-container') | | |
| | | -- Outer container |
| | local node_container = mw.html.create('div') |
| | :addClass('card-container') |
| | |
| | if isSplit then |
| | node_container:addClass('card-split-card') |
| | end |
| | |
| if a.mini then | | if a.mini then |
| node_container:addClass('mini-card') | | node_container:addClass('mini-card') |
| end | | end |
|
| | |
| if a.miliastra_wonderland then | | -- Wrapper and body |
| node_container:addClass('miliastra-wonderland')
| |
| end
| |
|
| |
| if a.text and tonumber((tostring(a.text):gsub(',', ''):gsub('[kKmMbBtT%%]$', '')))~=nil then
| |
| local mult = a.text:gsub('^.-([kKmMbBtT%%])$', '%1')
| |
| a.text = lib.thousandsSeparator((tostring(a.text):gsub(',', ''):gsub('[kKmMbBtT%%]$', ''))) .. (mult == a.text and '' or mult)
| |
| end
| |
|
| |
| -- create two wrapper divs for the main card body
| |
| -- (required for CSS positioning and rounded corners, respectively)
| |
| local node_card = node_container:tag('span') | | local node_card = node_container:tag('span') |
| :addClass('card-wrapper') | | :addClass('card-wrapper') |
| :tag('span') | | :tag('span') |
| :addClass('card-body') | | :addClass('card-body') |
| | | |
| local node_image = node_card:tag('span') | | -- Galaxy class on body |
| | if not a.mini and ne(a.galaxy) then |
| | node_card:addClass( |
| | 'card-galaxy-' .. normalizeClassName(a.galaxy) |
| | ) |
| | end |
| | |
| | -- Main image container |
| | local imageContainer = node_card:tag('span') |
| :addClass('card-image-container') | | :addClass('card-image-container') |
| if lib.isNotEmpty(a.quality) then
| | :addClass('card-quality-' .. a.quality) |
| if tonumber(a.quality)==nil then node_image:addClass('card-quality-' .. string.lower(a.quality:gsub('%D', ''):gsub(' ', '%-'))) end | | |
| node_image:addClass('card-quality-' .. string.lower(a.quality:gsub(' ', '%-')))
| | -- Split or regular image |
| end
| | if isSplit then |
| if lib.isNotEmpty(a.weapon) then node_image:addClass('card-weapon-' .. string.lower(a.weapon:gsub(' ', '%-'))) end
| | imageContainer:addClass('card-split-image') |
| if lib.isNotEmpty(a.element) then node_image:addClass('card-element-' .. string.lower(a.element:gsub(' ', '%-'))) end | | |
| node_image:tag('span')
| | -- First item: top-left half |
| :wikitext(a.image:buildString())
| | imageContainer:tag('span') |
| | | :addClass('card-split-half') |
| if lib.isNotEmpty(a.icon) then | | :addClass('card-split-half-a') |
| | :wikitext(a.image_wikitext) |
| | |
| | -- Second item: bottom-right half |
| | imageContainer:tag('span') |
| | :addClass('card-split-half') |
| | :addClass('card-split-half-b') |
| | :wikitext(makeSplitIcon(a.split, a.mini)) |
| | else |
| | imageContainer:wikitext(a.image_wikitext) |
| | end |
| | |
| | -- Notice label |
| | if not a.mini and ne(a.notice) then |
| | node_card:tag('span') |
| | :addClass('card-notice-label') |
| | :wikitext(a.notice) |
| | end |
| | |
| | -- First modifier |
| | if a.first then |
| node_card:tag('span') | | node_card:tag('span') |
| :addClass('card-icon') | | :addClass('card-modifier') |
| :cssText(a.icon_style) | | :addClass('card-modifier-first') |
| :wikitext(a.icon) | | :wikitext( |
| | '[[File:Icon Item First.png|x25px|link=|alt=First]]' |
| | ) |
| end | | end |
|
| | |
| if a.mini then | | -- UP modifier |
| if a.text ~= '—' and tonumber((a.text:gsub(',', ''):gsub('[kKmMbBtT%%]$', ''))) ~= nil then | | if a.up then |
| node_card:tag('span'):addClass('card-text'):wikitext(a.text)
| | node_card:tag('span') |
| end
| | :addClass('card-modifier') |
| if lib.isNotEmpty(a.icon_right) then
| | :addClass('card-modifier-up') |
| node_card:tag('span') | | :wikitext( |
| :addClass('card-icon-right')
| | '[[File:Icon Item UP.png|x25px|link=|alt=UP]]' |
| :cssText(a.icon_right_style)
| | ) |
| :wikitext(a.icon_right)
| | end |
| end
| | |
| else
| | -- Label below the image |
| if a.set then
| | if ne(a.label) then |
| node_card:tag('span')
| | node_container:tag('span') |
| :addClass('card-set-container') | | :addClass('card-label') |
| :tag('span')
| | :wikitext(a.label) |
| :addClass('icon')
| |
| :wikitext('[[File:Set.svg|14px|link=|alt=Artifact set]]')
| |
| end
| |
| if a.stars then
| |
| local starsImage = a.miliastra_wonderland and MILIASTRA_WONDERLAND_QUALITY_STARS[a.quality] or QUALITY_STARS[a.quality]
| |
| if starsImage then
| |
| node_card:tag('span')
| |
| :addClass('card-stars')
| |
| :tag('span')
| |
| :wikitext(starsImage)
| |
| end | |
| end
| |
| if lib.isNotEmpty(a.icon_right) then
| |
| node_card:tag('span')
| |
| :addClass('card-icon-right')
| |
| :cssText(a.icon_right_style)
| |
| :wikitext(a.icon_right)
| |
| end
| |
| if lib.isNotEmpty(a.icon_bottom_left) then
| |
| node_card:tag('span')
| |
| :addClass('card-icon-bottom-left')
| |
| :cssText(a.icon_bottom_left_style)
| |
| :wikitext(a.icon_bottom_left)
| |
| end
| |
| if lib.isNotEmpty(a.icon_bottom_right) then
| |
| node_card:tag('span')
| |
| :addClass('card-icon-bottom-right')
| |
| :cssText(a.icon_bottom_right_style)
| |
| :wikitext(a.icon_bottom_right)
| |
| end | |
| if lib.isNotEmpty(a.equipped) then
| |
| node_card:tag('span')
| |
| :addClass('card-equipped')
| |
| :wikitext(a.equipped)
| |
| end
| |
|
| |
| local node_text = node_card:tag('span')
| |
| :addClass('card-text')
| |
| :addClass('card-font')
| |
| :addClass(a.text_size and 'card-text-' .. a.text_size or '')
| |
| :wikitext(' ', a.text)
| |
| if a.multiline_text then
| |
| node_text:addClass('multi-line') | |
| end
| |
|
| |
| if lib.isNotEmpty(a.refinement) then
| |
| node_card:tag('span')
| |
| :addClass('card-refinement')
| |
| :addClass('refine-' .. a.refinement)
| |
| :wikitext(' R', (a.refinement:gsub('a', ''))) -- extra parens to take only first value returned from gsub
| |
| end
| |
| if lib.isNotEmpty(a.constellation) then
| |
| node_card:tag('span') | |
| :addClass('card-constellation')
| |
| :addClass('constellation-' .. a.constellation)
| |
| :wikitext(' C', a.constellation)
| |
| node_card:addClass('card-with-constellation')
| |
| end
| |
| end | | end |
| | | |
| | | -- Caption |
| if a.show_caption and lib.isNotEmpty(a.caption) then | | -- Split captions are opt-in and use spans instead of list items. |
| | if a.show_caption and isSplit then |
| local node_caption = node_container:tag('span') | | local node_caption = node_container:tag('span') |
| :addClass('card-caption') | | :addClass('card-caption') |
| :wikitext(' ', a.nolink and a.caption or ('[[' .. a.final_link .. '|' .. a.caption .. ']]')) | | :addClass('card-split-caption') |
| | |
| | local list = node_caption:tag('span') |
| | :addClass('card-split-caption-list') |
| | |
| | list:tag('span') |
| | :addClass('card-split-caption-item') |
| | :wikitext('[[' .. a.name .. ']]') |
| | |
| | list:tag('span') |
| | :addClass('card-split-caption-item') |
| | :wikitext('[[' .. a.split .. ']]') |
| | |
| setCaptionWidth(node_caption, a.caption_width) | | setCaptionWidth(node_caption, a.caption_width) |
| end
| | |
| | | elseif a.show_caption and ne(a.caption) then |
| if lib.isNotEmpty(a.note) then
| | local node_caption = node_container:tag('span') |
| local node_note = node_container:tag('span') | |
| :addClass('card-caption') | | :addClass('card-caption') |
| :wikitext(a.note)
| | |
| setCaptionWidth(node_note, a.caption_width)
| | if a.no_link or lib.isEmpty(a.final_link) then |
| end
| | node_caption:wikitext(a.caption) |
|
| | else |
| if a.mobile_list then
| | node_caption:wikitext( |
| if a.text ~= '—' or a.caption or a.note then | | '[[' .. a.final_link .. '|' .. a.caption .. ']]' |
| local node_mobile_text = node_card | | ) |
| :tag('span')
| |
| :addClass('card-mobile-text')
| |
| if a.nolink then
| |
| node_mobile_text:wikitext(' ', a.caption)
| |
| else
| |
| node_mobile_text:wikitext(' [[', a.final_link, '|', a.caption, ']]')
| |
| end
| |
| if tonumber((a.text:gsub(',', ''))) ~= nil then
| |
| node_mobile_text:wikitext(' ×')
| |
| end
| |
| if (a.caption or ''):gsub('­', '') ~= (a.text or ''):gsub('­', '') and a.text ~= '—' then
| |
| node_mobile_text:wikitext(' ', a.text)
| |
| end
| |
| if a.note then | |
| node_mobile_text:wikitext(' (', a.note, ')')
| |
| end
| |
| end | | end |
| end
| | |
|
| | setCaptionWidth(node_caption, a.caption_width) |
| if a.uses_deprecated_params then
| |
| node_container:wikitext('[[Category:Pages Using Deprecated Template Parameters]]')
| |
| end | | end |
|
| |
|
| return node_container | | return tostring(node_container) |
| end | | end |
|
| |
|
| function p.templateData(frame) | | function p.templateData(frame) |
| return TemplateData.templateData(CARD_ARGS, { | | return TemplateData.templateData(CARD_ARGS, { |
| description="This template is used to create an item display that is similar to the items in the Inventory in-game. Text can be shown below the item's image, background and stars can match the quality, refinement, icons, and set can be added.\n\nIf the image name matches an existing Item, then the quality will automatically be set.\n\nIf the image name matches an existing Character of Weapon, then the format will automatically change to match that type item.", | | description = 'Creates an item-style card with image, quality, label, split images, modifiers, and optional data-driven icons.', |
| format='inline' | | format = 'inline' |
| }, frame) | | }, frame) |
| end | | end |