| Latest revision |
Your text |
| Line 1: |
Line 1: |
| -- See /doc for docs | | -- see /doc for docs |
|
| |
|
| local p = {} | | local p = {} |
| local utils = require "Module:Abilities/utils" | | local utils = require "Module:Abilities/utils" |
| local lang = require "Module:Lang" | | local lang = require "Module:Lang" |
| local AbilityHints = require "Module:AbilityHints" | | local icon_module = require "Module:Icon" |
| local resource_lookup = mw.loadJsonData("Data:ResourceLookup.json") | | local resource_lookup = mw.loadJsonData("Data:ResourceLookup.json") |
| local dictionary_data = mw.loadJsonData("Data:Dictionary")
| |
|
| |
|
| -- Tab definitions — order here determines display order. | | -- Tab definitions — order here determines display order. |
| -- label_dict_key names the [[Data:Dictionary]] entry holding the tab label; the Notes
| |
| -- tab reuses the existing 'Notes' entry rather than adding a duplicate.
| |
| local TABS = { | | local TABS = { |
| { key = 'notes', label_dict_key = 'Notes' },
| | { key = 'notes', label = 'Notes' }, |
| { key = 'tips', label_dict_key = 'AbilityCardTabTips' },
| | { key = 'interactions', label = 'Interactions' }, |
| { key = 'interactions', label_dict_key = 'AbilityCardTabInteractions' },
| | { key = 'tips', label = 'Tips' }, |
| } | | } |
|
| |
| local SHOW_ALL_DICT_KEY = 'AbilityCardTabShowAll'
| |
|
| |
| -- Tab labels are read from the dictionary directly instead of going through
| |
| -- Module:Dictionary, which appends Template:NeedsTranslationTooltip markup to
| |
| -- anything untranslated. mw.ext.tabber.render HTML-escapes a label and reuses it as a
| |
| -- DOM id, so that markup would show up as literal text in the tab and mangle the
| |
| -- anchor. Untranslated labels therefore fall back to English silently.
| |
| local function tab_label(dict_key)
| |
| local entry = dictionary_data[dict_key]
| |
| if entry == nil then return dict_key end
| |
| return entry[lang.get_lang_code()] or entry.en or dict_key
| |
| end
| |
|
| |
|
| local function get_hero_key(hero_name) | | local function get_hero_key(hero_name) |
| if hero_name == nil or hero_name == '' then return nil end
| | if hero_name == nil or hero_name == '' then return nil end |
| if string.sub(hero_name, 1, 5) == "hero_" then return hero_name end
| | if string.sub(hero_name, 1, 5) == "hero_" then return hero_name end |
| local entry = resource_lookup[hero_name:lower()]
| | local entry = resource_lookup[hero_name:lower()] |
| if entry == nil then return nil end
| | if entry == nil then return nil end |
| return entry.key
| | return entry.key |
| end | | end |
|
| |
|
| local function trim(s) | | local function trim(s) |
| return s:match('^%s*(.-)%s*$')
| | return s:match('^%s*(.-)%s*$') |
| end
| |
| | |
| -- Process content in the Interactions tab to build list of icons to draw in ability hints beside ability card
| |
| local function process_interactions(html, ability_num)
| |
| local manual, idx, seen = {}, 0, {}
| |
| local out = html:gsub('(<div)([^>]*data%-iconbox%-icon="[^"]*"[^>]*)(>)', function(pre, attrs, post)
| |
| local file = attrs:match('data%-iconbox%-icon="([^"]*)"')
| |
| if file and file ~= '' then
| |
| local base = mw.ustring.lower((file:gsub('%.%w+$', '')))
| |
| local entry = resource_lookup[base]
| |
| if entry ~= nil and entry.type == 'item' and not seen[base] then
| |
| seen[base] = true
| |
| idx = idx + 1
| |
| local box_id = 'ai-int-' .. ability_num .. '-' .. idx
| |
| table.insert(manual, {
| |
| file = file,
| |
| title = attrs:match('data%-iconbox%-title="([^"]*)"') or '',
| |
| state = attrs:match('data%-iconbox%-state="([^"]*)"') or 'normal',
| |
| anchor = box_id,
| |
| })
| |
| return pre .. attrs .. ' id="' .. box_id .. '"' .. post
| |
| end
| |
| end
| |
| return pre .. attrs .. post
| |
| end)
| |
| return out, manual
| |
| end | | end |
|
| |
|
| local function build_tabber(wikitext_map, tab_overrides) | | local function build_tabber(wikitext_map) |
| tab_overrides = tab_overrides or {}
| | local filled = {} |
| local filled = {}
| | for _, tab in ipairs(TABS) do |
| for _, tab in ipairs(TABS) do
| | if wikitext_map[tab.key] ~= '' then |
| if wikitext_map[tab.key] ~= '' then
| | table.insert(filled, { key = tab.key, label = tab.label, wikitext = wikitext_map[tab.key] }) |
| local tab_wt = tab_overrides[tab.key]
| | end |
| if tab_wt == nil or tab_wt == '' then tab_wt = wikitext_map[tab.key] end
| | end |
| table.insert(filled, {
| |
| key = tab.key,
| |
| label = tab_label(tab.label_dict_key),
| |
| tab_wt = tab_wt,
| |
| all_wt = wikitext_map[tab.key],
| |
| })
| |
| end
| |
| end
| |
|
| |
|
| if #filled == 0 then
| | if #filled == 0 then |
| return ''
| | return '' |
| end
| | end |
|
| |
|
| local tabs = {}
| | local tabs = {} |
| for _, section in ipairs(filled) do
| | for _, section in ipairs(filled) do |
| table.insert(tabs, {
| | table.insert(tabs, { |
| label = section.label,
| | label = section.label, |
| content = '<div class="ability-details-panel">\n' .. section.tab_wt .. '\n</div>',
| | content = '<div class="ability-details-panel">\n' .. section.wikitext .. '\n</div>', |
| })
| | }) |
| end
| | end |
|
| |
|
| if #filled >= 2 then
| | -- "Show All" tab wraps each section's wikitext in a <div> to give the parser |
| local all_parts = {}
| | -- a fresh block context per section, preventing html mangling. |
| for _, section in ipairs(filled) do
| | if #filled >= 2 then |
| table.insert(all_parts,
| | local all_parts = {} |
| '<div class="ability-details-section-header">' .. section.label .. '</div>'
| | for _, section in ipairs(filled) do |
| .. '<div class="ability-details-section-content">\n' .. section.all_wt .. '\n</div>'
| | table.insert(all_parts, |
| )
| | '<div class="ability-details-section-header">' .. section.label .. '</div>' |
| end
| | .. '<div class="ability-details-section-content">\n' .. section.wikitext .. '\n</div>' |
| table.insert(tabs, {
| | ) |
| label = tab_label(SHOW_ALL_DICT_KEY),
| | end |
| content = '<div class="ability-details-panel">' .. table.concat(all_parts) .. '</div>',
| | table.insert(tabs, { |
| })
| | label = 'Show All', |
| end
| | content = '<div class="ability-details-panel">' .. table.concat(all_parts) .. '</div>', |
| | }) |
| | end |
|
| |
|
| local rendered = mw.ext.tabber.render(tabs)
| | local rendered = mw.ext.tabber.render(tabs) |
| if #filled == 1 then
| | if #filled == 1 then |
| return '<div class="single-tabbed">' .. rendered .. '</div>'
| | return '<div class="single-tabbed">' .. rendered .. '</div>' |
| end
| | end |
| return rendered
| | return rendered |
| end | | end |
|
| |
|
| -- Entry point. Called via {{#invoke:AbilitySection|render}}. | | -- Entry point. Called via {{#invoke:AbilitySection|render}}. |
| function p.render(frame) | | function p.render(frame) |
| local args = frame.args
| | local args = frame.args |
| local hero_name = trim(args.hero_name or '')
| | local hero_name = trim(args.hero_name or '') |
| local ability_num = trim(args.ability_num or '')
| | local ability_num = trim(args.ability_num or '') |
| local notes = trim(args.notes or '')
| | local notes = trim(args.notes or '') |
| local tips = trim(args.tips or '')
| | local interactions = trim(args.interactions or '') |
| local interactions = trim(args.interactions or '')
| | local tips = trim(args.tips or '') |
|
| |
|
| local hero_key = get_hero_key(hero_name)
| | local hero_key = get_hero_key(hero_name) |
| local heading = ''
| | local heading = '' |
| local ability_key = nil
| | if hero_key ~= nil then |
| if hero_key ~= nil then
| | local ability = utils.get_ability_card_data(hero_key, ability_num) |
| local ability = utils.get_ability_card_data(hero_key, ability_num)
| | if ability ~= nil then |
| if ability ~= nil then
| | local ability_name = lang.get_string(ability.Key) |
| ability_key = ability.Key
| | -- Use the English ability key for icon render; icon module indexes by English name |
| local ability_name = lang.get_string(ability.Key)
| | local ability_name_en = lang.get_string(ability.Key, 'en', ability.Key) |
| -- Create a visually hidden H3 heading so the Table of Contents can parse
| | local icon_html = icon_module._render(ability_name_en, { size = '30px', ['icon-only'] = 'true', ['no-link'] = 'true' }) |
| -- the ability name without displaying a redundant title above the card.
| | heading = '<h3 class="ability-name">' .. icon_html .. ' ' .. ability_name .. '</h3>' |
| heading = '<h3 class="ability-name-toc">' .. ability_name .. '</h3>' | |
| end | | end |
| end
| | end |
| | |
| local card = frame:expandTemplate{
| |
| title = 'Ability card v2',
| |
| args = { hero_name = hero_name, ability_num = ability_num, link_name = 'false' }
| |
| }
| |
| | |
| local interactions_ided, manual = interactions, {}
| |
| if interactions ~= '' then
| |
| interactions_ided, manual = process_interactions(interactions, ability_num)
| |
| end
| |
| | |
| local wikitext_map = {
| |
| notes = notes,
| |
| tips = tips,
| |
| interactions = interactions,
| |
| }
| |
| | |
| local tabber = build_tabber(wikitext_map, { interactions = interactions_ided })
| |
|
| |
|
| local hints_col = ''
| | local card = frame:expandTemplate{ |
| if ability_key ~= nil or #manual > 0 then
| | title = 'Ability card v2', |
| hints_col = AbilityHints.get_icons(ability_key, ability_num, manual)
| | args = { hero_name = hero_name, ability_num = ability_num, link_name = 'false' } |
| end
| | } |
|
| |
|
| local details_col = ''
| | local wikitext_map = { |
| if tabber ~= '' then
| | notes = notes, |
| details_col = '<div class="ability-section-details">' .. tabber .. '</div>' | | interactions = interactions, |
| end
| | tips = tips, |
| | } |
|
| |
|
| local card_block = '<div class="ability-section-card">' .. card .. '</div>'
| | local tabber = build_tabber(wikitext_map) |
| local left_col
| | local details_col = '' |
| if hints_col ~= '' then
| | if tabber ~= '' then |
| left_col = '<div class="ability-section-main">' .. card_block .. hints_col .. '</div>'
| | details_col = '<div class="ability-section-details">' .. tabber .. '</div>' |
| else
| | end |
| left_col = card_block
| |
| end
| |
|
| |
|
| local ability_section = '<div class="ability-section">'
| | local ability_section = '<div class="ability-section">' |
| .. left_col
| | .. '<div class="ability-section-card">' .. card .. '</div>' |
| .. details_col
| | .. details_col |
| .. '</div>'
| | .. '</div>' |
|
| |
|
| return '<div class="ability-section-wrapper">'
| | return '<div class="ability-section-wrapper">' |
| .. heading
| | .. heading |
| .. ability_section
| | .. ability_section |
| .. '</div>'
| | .. '</div>' |
| end | | end |
|
| |
|
| return p | | return p |