| Latest revision |
Your text |
| Line 1: |
Line 1: |
|
| |
| local p = {} | | local p = {} |
|
| |
| local lib = require('Module:Feature') | | local lib = require('Module:Feature') |
| local ne = lib.isNotEmpty | | local LL = require('Module:Link label')._main |
| local TemplateData = require('Module:TemplateData')
| | local Ilib = require('Module:Icon') |
| local array = require('Module:Array')
| |
| local CentralData = require('Module:CentralData') | |
| | |
| local allData = CentralData.dataSheets
| |
| | |
| local CARD_ARGS = {
| |
| {
| |
| name = 'name',
| |
| alias = 1,
| |
| default = 'Unknown',
| |
| },
| |
| {
| |
| name = 'label',
| |
| alias = {2, 'text', 'count', 'amount', 'x'},
| |
| },
| |
| {
| |
| name = 'show_label',
| |
| alias = 'show_text',
| |
| type = '1',
| |
| },
| |
| {
| |
| name = 'quality',
| |
| alias = 'rarity',
| |
| default = 'Common',
| |
| },
| |
| {
| |
| name = 'type',
| |
| },
| |
| {
| |
| name = 'split',
| |
| },
| |
| {
| |
| name = 'suffix',
| |
| default = '',
| |
| },
| |
| {
| |
| name = 'image',
| |
| },
| |
| {
| |
| name = 'image_size',
| |
| alias = {'imageSize', 'size'},
| |
| },
| |
| {
| |
| name = 'image_ext',
| |
| alias = {'imageExt', 'ext', 'extension'},
| |
| default = 'png',
| |
| },
| |
| {
| |
| name = 'link',
| |
| },
| |
| {
| |
| name = 'link_suffix',
| |
| default = '',
| |
| },
| |
| {
| |
| name = 'no_link',
| |
| type = '1',
| |
| },
| |
| {
| |
| name = 'caption',
| |
| },
| |
| {
| |
| name = 'show_caption',
| |
| type = '1',
| |
| },
| |
| {
| |
| name = 'caption_width',
| |
| alias = 'captionWidth',
| |
| },
| |
| {
| |
| name = 'mini',
| |
| type = '1',
| |
| },
| |
| {
| |
| name = 'first',
| |
| type = '1',
| |
| },
| |
| {
| |
| name = 'up',
| |
| alias = 'UP',
| |
| type = '1',
| |
| },
| |
| {
| |
| name = 'notice',
| |
| },
| |
| }
| |
|
| |
|
| function p.main(frame) | | function p.main(frame) |
| local args = require('Module:Arguments').getArgs(frame, { | | local args = require('Module:Arguments').getArgs(frame, { |
| wrapper = {'Template:Card'}, | | parentFirst = true, |
| parentOnly = false
| | removeBlanks = false, |
| | wrapper = { 'Template:Card' } |
| }) | | }) |
|
| |
| return p._main(args) | | return p._main(args) |
| end | | end |
|
| |
|
| local function getDataByName(dataType, dataTable, name)
| | function p._main(args) |
| local data = dataTable[name] | | local item = args.name or args[1] |
| | | if not item then return mw.html.create() end -- if no input then return blank |
| if data then | | local link = args.nolink and '' or (args.link or item) |
| return data
| | local ext = args.ext or 'png' |
| end | | local amount = args.amount or args.x or args[2] |
| | | local text = args.text or args[3] |
| local normalizedType = tostring(dataType or ''):lower() | | local note = args.note |
| if normalizedType == 'neighbor' or normalizedType == 'neighbors' then | | local nolink = args.nolink or false |
| return nil | | local notext = args.notext or false |
| | local quality = args.quality or args.q |
| | -- mw.logObject(args) |
| | local prefix = args.prefix or '' |
| | local suffix = args.suffix or '' |
| | prefix = prefix:gsub('{space}', ' ') |
| | suffix = suffix:gsub('{space}', ' ') |
| | |
| | local card = mw.html.create():tag('div'):addClass('custom-card noborder') |
| | local card_body = card:tag('div'):addClass('custom-card-body') |
| | local card_image = card_body:tag('div'):addClass('custom-card-image') |
| | local card_caption = card:tag('div'):addClass('custom-card-caption') |
| | |
| | -- main card image |
| | local filename = table.concat({prefix, item, suffix}) |
| | card_image:wikitext('[[File:', filename, '.', ext, '|51px|link=', link, ']]') |
| | |
| | -- quality icon if valid |
| | if quality then |
| | card_body:addClass(' quality-' .. quality) |
| end | | end |
| | | |
| for quality, names in pairs(dataTable) do | | -- amount if any |
| if type(names) == 'table' then | | if lib.isNotEmpty(amount) then |
| for _, itemName in ipairs(names) do
| | amount = tonumber(amount) ~= nil and lib.thousandsSeparator(amount) or amount |
| if itemName == name then
| | card_body:tag('div'):addClass('custom-card-amount'):wikitext(amount) |
| return {
| |
| quality = quality
| |
| }
| |
| end
| |
| end
| |
| end
| |
| end | | end |
| | | |
| return nil | | -- default caption |
| end
| | if args.show_caption then |
| | | card_caption:tag('br') |
| function p.getTypeAndData(name, requestedType)
| | if link == '' then card_caption:wikitext(item) |
| local img_type = requestedType or 'Item'
| | elseif link == item then card_caption:wikitext(LL(item)) |
| local img_data = nil
| | else card_caption:wikitext('[[', link, '|', item, ']]') |
| | |
| for _, v in ipairs(allData) do
| |
| local dataType = v[1] | |
| local dataTable = v[2]
| |
| | |
| 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 | | end |
| end | | end |
| | | |
| return img_type, img_data | | -- append custom text if any |
| end
| | if lib.isNotEmpty(text) then |
| | | card_caption:tag('br') |
| local function normalizeBool(value)
| | card_caption:wikitext(text) |
| 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 | | end |
| | | |
| if lib.isEmpty(quality) then | | -- ending note if any |
| quality = 'Common' | | if lib.isNotEmpty(note) then |
| | card_caption:tag('br') |
| | card_caption:tag('small'):wikitext('(', note, ')') |
| end | | end |
| | | |
| return normalizeClassName(quality)
| | -- mw.logObject(card) -- debug |
| end
| | return card |
| | |
| 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
| |
| | |
| if out.data.title then
| |
| out.defaults.caption = out.data.title
| |
| end
| |
| | |
| if out.data.quality then
| |
| out.defaults.quality = out.data.quality
| |
| | |
| if not (out.nonDefaults and out.nonDefaults.quality) then
| |
| out.quality = out.data.quality
| |
| end
| |
| end
| |
| end
| |
| | |
| -- Quality / rarity
| |
| out.quality = normalizeQuality(out.quality)
| |
| | |
| -- Label handling
| |
| if out.show_label then
| |
| out.label = out.data
| |
| and (out.data.name or out.data.title)
| |
| or out.name
| |
| end
| |
| | |
| if out.label == '0' then
| |
| out.label = nil
| |
| end
| |
| | |
| -- Type-specific behavior
| |
| local lcType = tostring(out.type or ''):lower()
| |
| | |
| if lcType == 'neighbor' then
| |
| if lib.isEmpty(out.label) then
| |
| if out.mini and out.data and out.data.shortName then
| |
| out.label = out.data.shortName
| |
| elseif not out.mini then
| |
| out.label = out.name
| |
| end
| |
| end
| |
| | |
| if tonumber(out.image_size) then
| |
| out.image_size = tonumber(out.image_size) + 2
| |
| end
| |
| end
| |
| | |
| if lcType == 'redirect' then
| |
| out.defaults.link = stripLinkPrefix(out.name)
| |
| | |
| if not (out.nonDefaults and out.nonDefaults.link) then
| |
| out.link = stripLinkPrefix(out.name)
| |
| end
| |
| end
| |
| | |
| -- Caption defaults
| |
| if out.show_caption and lib.isEmpty(out.caption) then
| |
| if out.data then
| |
| out.caption = out.data.title
| |
| or out.data.name
| |
| or out.name
| |
| else
| |
| out.caption = out.name
| |
| end
| |
| end
| |
| | |
| -- Link handling
| |
| if out.link == nil then
| |
| out.link = lib.ternary(
| |
| 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
| |
| | |
| -- Main image filename
| |
| if ne(out.image) then
| |
| out.final_file = out.image
| |
| else
| |
| out.final_file =
| |
| lib.sanitizeFileName(out.image_name) ..
| |
| out.suffix ..
| |
| '.' ..
| |
| out.image_ext
| |
| 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
| |
| | |
| function p._main(args)
| |
| local a = p._processArgs(args)
| |
| local isSplit = ne(a.split)
| |
| | |
| -- 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
| |
| node_container:addClass('mini-card')
| |
| end
| |
| | |
| -- Wrapper and body
| |
| local node_card = node_container:tag('span')
| |
| :addClass('card-wrapper')
| |
| :tag('span')
| |
| :addClass('card-body')
| |
| | |
| -- 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-quality-' .. a.quality)
| |
| | |
| -- Split or regular image
| |
| if isSplit then
| |
| imageContainer:addClass('card-split-image')
| |
| | |
| -- First item: top-left half
| |
| imageContainer:tag('span')
| |
| :addClass('card-split-half')
| |
| :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')
| |
| :addClass('card-modifier')
| |
| :addClass('card-modifier-first')
| |
| :wikitext(
| |
| '[[File:Icon Item First.png|x25px|link=|alt=First]]'
| |
| )
| |
| end
| |
| | |
| -- UP modifier
| |
| if a.up then
| |
| node_card:tag('span')
| |
| :addClass('card-modifier')
| |
| :addClass('card-modifier-up')
| |
| :wikitext(
| |
| '[[File:Icon Item UP.png|x25px|link=|alt=UP]]'
| |
| )
| |
| end
| |
| | |
| -- Label below the image
| |
| if ne(a.label) then
| |
| node_container:tag('span')
| |
| :addClass('card-label')
| |
| :wikitext(a.label)
| |
| end
| |
| | |
| -- Caption
| |
| -- 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')
| |
| :addClass('card-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)
| |
| | |
| elseif a.show_caption and ne(a.caption) then
| |
| local node_caption = node_container:tag('span')
| |
| :addClass('card-caption')
| |
| | |
| if a.no_link or lib.isEmpty(a.final_link) then
| |
| node_caption:wikitext(a.caption)
| |
| else
| |
| node_caption:wikitext(
| |
| '[[' .. a.final_link .. '|' .. a.caption .. ']]'
| |
| )
| |
| end
| |
| | |
| setCaptionWidth(node_caption, a.caption_width)
| |
| end
| |
| | |
| return tostring(node_container) | |
| end
| |
| | |
| function p.templateData(frame)
| |
| return TemplateData.templateData(CARD_ARGS, {
| |
| description = 'Creates an item-style card with image, quality, label, split images, modifiers, and optional data-driven icons.',
| |
| format = 'inline'
| |
| }, frame)
| |
| end
| |
| | |
| function p.syntax(frame)
| |
| return TemplateData.syntax(CARD_ARGS, frame)
| |
| end | | end |
|
| |
|
| return p | | return p |