- This is an example of a note.
- This is an example of a note.
Lua backend for Template:AbilitySection. Renders a two-column layout with the ability card on the left and an optional tabbed details panel on the right.
Between the card and the details panel, an interaction-hint rail of small item icons is rendered via Module:AbilityHints (showing how the ability interacts with items — dispellable, reduced, blocked, etc.). When a rail is present, the card and rail are grouped in a .ability-section-main wrapper so the rail always wraps together with the card rather than onto the details' line; abilities with no interactions keep the flat single-card structure.
Only tabs with non-empty content are shown. If two or more tabs have content, a Show All tab is automatically appended that stacks all content in sequence with section headers between them.
The Notes tab is height-constrained with a scrollbar when content overflows (see Template:AbilitySection/styles.css). Other tabs are unconstrained.
If no content params are provided, no details panel is rendered at all — only the ability card (and its hint rail, if any).
p.render(frame)Called via {{#invoke:AbilitySection|render}}.
| Argument | Required | Description |
|---|---|---|
hero_name |
Yes | Passed through to Template:Ability card v2. |
ability_num |
Yes | Passed through to Template:Ability card v2. |
notes |
No | Wikitext for the Notes tab. |
tips |
No | Wikitext for the Tips tab. |
TABSDefines list of possible tabs. Order here determines display order in the tabber.
local TABS = {
{ key = 'notes', label = 'Notes' },
{ key = 'tips', label = 'Tips' },
}
{{AbilitySection
| hero_name = Abrams
| ability_num = 1
| notes =
* This is an example of a note.
| tips =
* This is an example of a tip.
}}
Siphon Life
-- See /doc for docs
local p = {}
local utils = require "Module:Abilities/utils"
local lang = require "Module:Lang"
local icon_module = require "Module:Icon"
local AbilityHints = require "Module:AbilityHints"
local resource_lookup = mw.loadJsonData("Data:ResourceLookup.json")
-- Tab definitions — order here determines display order.
local TABS = {
{ key = 'notes', label = 'Notes' },
{ key = 'tips', label = 'Tips' },
{ key = 'interactions', label = 'Interactions' },
}
local function get_hero_key(hero_name)
if hero_name == nil or hero_name == '' then return nil end
if string.sub(hero_name, 1, 5) == "hero_" then return hero_name end
local entry = resource_lookup[hero_name:lower()]
if entry == nil then return nil end
return entry.key
end
local function trim(s)
return s:match('^%s*(.-)%s*$')
end
local function process_interactions(html, ability_num)
local manual, idx, seen = {}, 0, {}
local out = html:gsub('(<div class="ai%-box)([^>]*)(>)', function(pre, attrs, post)
local file = attrs:match('data%-ai%-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%-ai%-title="([^"]*)"') or '',
disabled = attrs:find('ai%-disabled') ~= nil,
anchor = box_id,
})
return pre .. attrs .. ' id="' .. box_id .. '"' .. post
end
end
return pre .. attrs .. post
end)
return out, manual
end
local function build_tabber(wikitext_map, tab_overrides)
tab_overrides = tab_overrides or {}
local filled = {}
for _, tab in ipairs(TABS) do
if wikitext_map[tab.key] ~= '' then
local tab_wt = tab_overrides[tab.key]
if tab_wt == nil or tab_wt == '' then tab_wt = wikitext_map[tab.key] end
table.insert(filled, {
key = tab.key,
label = tab.label,
tab_wt = tab_wt,
all_wt = wikitext_map[tab.key],
})
end
end
if #filled == 0 then
return ''
end
local tabs = {}
for _, section in ipairs(filled) do
table.insert(tabs, {
label = section.label,
content = '<div class="ability-details-panel">\n' .. section.tab_wt .. '\n</div>',
})
end
if #filled >= 2 then
local all_parts = {}
for _, section in ipairs(filled) do
table.insert(all_parts,
'<div class="ability-details-section-header">' .. section.label .. '</div>'
.. '<div class="ability-details-section-content">\n' .. section.all_wt .. '\n</div>'
)
end
table.insert(tabs, {
label = 'Show All',
content = '<div class="ability-details-panel">' .. table.concat(all_parts) .. '</div>',
})
end
local rendered = mw.ext.tabber.render(tabs)
if #filled == 1 then
return '<div class="single-tabbed">' .. rendered .. '</div>'
end
return rendered
end
-- Entry point. Called via {{#invoke:AbilitySection|render}}.
function p.render(frame)
local args = frame.args
local hero_name = trim(args.hero_name or '')
local ability_num = trim(args.ability_num or '')
local notes = trim(args.notes or '')
local tips = trim(args.tips or '')
local interactions = trim(args.interactions or '')
local hero_key = get_hero_key(hero_name)
local heading = ''
local ability_key = nil
if hero_key ~= nil then
local ability = utils.get_ability_card_data(hero_key, ability_num)
if ability ~= nil then
ability_key = ability.Key
local ability_name = lang.get_string(ability.Key)
-- Use the English ability key for icon render; icon module indexes by English name
local ability_name_en = lang.get_string(ability.Key, 'en', ability.Key)
local icon_html = icon_module._render(ability_name_en, { size = '30px', ['icon-only'] = 'true', ['no-link'] = 'true' })
heading = '<h3 class="ability-name">' .. icon_html .. ' ' .. ability_name .. '</h3>'
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 = ''
if ability_key ~= nil or #manual > 0 then
hints_col = AbilityHints.get_icons(ability_key, ability_num, manual)
end
local details_col = ''
if tabber ~= '' then
details_col = '<div class="ability-section-details">' .. tabber .. '</div>'
end
local card_block = '<div class="ability-section-card">' .. card .. '</div>'
local left_col
if hints_col ~= '' then
left_col = '<div class="ability-section-main">' .. card_block .. hints_col .. '</div>'
else
left_col = card_block
end
local ability_section = '<div class="ability-section">'
.. left_col
.. details_col
.. '</div>'
return '<div class="ability-section-wrapper">'
.. heading
.. ability_section
.. '</div>'
end
return p