Dokumentacja dla tego modułu może zostać utworzona pod nazwą Moduł:Umiejętność/opis

local Skill = {}

local getArgs = require('Module:Translate').getArgs
local abilityIcon = require('Module:Filename').ability
local t2a = require('Module:Funkcje').table2array
local esplit = require('Module:Funkcje').esplit
local T = require('Module:Tekstowe')

local function formatTabs(text)
    text = text or ''
    local res = {}
    for i,v in ipairs(mw.text.split(text, '\n\n+')) do
        local dl, dd
        for i,v in ipairs(mw.text.split(v, '\n')) do
            local tab = mw.ustring.match(v, '^;%s*(.-)%s*:?$')
            if tab then
                dl = dl or mw.html.create('dl'):addClass('skill-tabs')
                dl:tag('dt'):wikitext(tab):done()
                dd = dl:tag('dd'):newline()
            else
                v = mw.ustring.gsub(v, '^:', '')
                if dd then
                    dd:wikitext(v):newline()
                else
                    res[#res+1] = v
                end
            end
        end
        if dl then res[#res+1] = tostring(dl) end
    end
    return table.concat(res, '\n')
end
local function formatProgression(text)
    text = text or ''
    local s, e = mw.ustring.find(text, '[0-9][0-9%.,]*%s*/[0-9%.,/%s]*[0-9]')
    while s do
        local str = '<span class="progression">' .. T.progression(mw.ustring.sub(text, s, e)) .. '</span>'
        text = (s-1>1 and mw.ustring.sub(text, 1, s-1) or '') .. str .. mw.ustring.sub(text, e+1)
        s, e = mw.ustring.find(text, '[0-9][0-9%.,]*%s*/[0-9%.,/%s]*[0-9]', s+mw.ustring.len(str))
    end
    return text
end
local function formatHeader(text)
    text = text or ''
    -- Formatowanie poziomów
    text = formatProgression(text)
    -- Małe liczby po przecinach
    text = T.decimals(text)
    -- Kolorowanie nawiasów
    
    local list = T.commaSplit(text)
    for i,v in ipairs(list) do
        list[i] = T.colorTop(v)
    end
    return table.concat(list, ', ')
end
local function formatLabels(text)
    text = text or ''
    return (mw.ustring.gsub(text, '(%*+)%s*([^:^<^>]-):[^\n%s]*', '%1 <strong class="skill-label">%2:</strong> '))
end
local function formatDesc(text)
    text = text or ''
    -- Wyróżnienie list
    text = formatLabels(text)
    -- Małe liczby po przecinach
    text = T.decimals(text)
    -- Kolorowanie nawiasów
    text = T.color(text)
    return text
end
local function formatLevels(text)
    text = mw.text.trim(text or '')
    -- Przygotowanie kart
    text = formatTabs(text)
    -- Wyróżnienie list
    text = formatLabels(text)
    -- Formatowanie poziomów
    text = formatProgression(text)
    -- Małe liczby po przecinach
    text = T.decimals(text)
    -- Kolorowanie nawiasów
    text = T.color(text)
    return text
end
function Skill.formatLevels(frame)
    return formatLevels(frame.args[1])
end
function Skill.formatDesc(frame)
    return formatDesc(frame.args[1])
end
local function makeIcon(file, size)
    size = tonumber(size) or 64
    local icon = mw.title.makeTitle('File', file)
    if icon.fileExists then
        return '[[' .. icon.prefixedText .. '|'..size..'px]]'
    else
        return '[[File:' .. abilityIcon{} .. '|'..size..'px|link=' .. mw.site.server .. '/wiki/Special:Upload?wpDestFile=' .. mw.uri.encode(icon.text) .. ']]'
    end
end
local function makeSkill(opt)
    if opt.name then
        local box = mw.html.create('div')
        
        box:addClass('skill')
           :attr('id', mw.uri.anchorEncode(opt.name))
            
        local header = box:tag('div') :addClass('skill-header')
        
        local h3 = header:tag('h3') :wikitext(opt.name .. ' ')
        if opt.tip then h3:tag('span'):addClass('tip'):wikitext('<small>(' .. opt.tip .. ')</small>') end
        
        local proplist = {}
        if opt.range then
            proplist[#proplist+1] = {
                'Zasięg',
                opt.range
            }
        end
        if opt.cost then
            proplist[#proplist+1] = {
                'Koszt',
                opt.cost
            }
        end
        if opt.cooldown then
            proplist[#proplist+1] = {
                '<span title="Czas odnowienia">Czas</span>',
                opt.cooldown
            }
        end
        if opt.extra1 then
            proplist[#proplist+1] = mw.text.split(opt.extra1, ':')
        end
        if opt.extra2 then
            proplist[#proplist+1] = mw.text.split(opt.extra2, ':')
        end
        
        if #proplist then
            local props = header:tag('div'):addClass('skill-props')
            for i,v in ipairs(proplist) do
                local label, text
                if #v > 1 then label = mw.text.trim(table.remove(v, 1) or '') end
                text = mw.text.trim(table.concat(v, ':') or '')
                
                if text ~= '' then
                    if i > 1 then props:wikitext(' <b>·</b> ') end
                    
                    local e = props:tag('span')
                    e:addClass('infobox-builder-go-to-source-tooltip-text') -- has only nowrap in Mercury
                    if label and label ~= '' then
                        e:tag('strong')
                         :addClass('skill-label')
                         :wikitext(label ..':')
                    end
                    e:wikitext(' ' .. formatHeader(text))
                end
            end
        end
        
        local prev
        for i,v in ipairs(opt.rows) do
            if v.icon or v._k - prev > 1 then
                box:tag('div')
                   :addClass('skill-clear')
            end
            prev = v._k
            if v.icon then
                box:tag('div')
                   :addClass('skill-icon')
                   :wikitext(makeIcon(v.icon, i==1 and 64 or 60))
            end
            local row = box:tag('div'):addClass('skill-row')
            row:tag('div')
               :addClass('skill-desc')
               :newline()
               :wikitext(formatDesc(v.desc))
               :newline()
            if v.levels then
                row:tag('div')
                   :addClass('skill-levels')
                   :newline()
                   :wikitext(formatLevels(v.levels))
                   :newline()
            else
                row:addClass('no-levels')
            end
        end
        --¶
        
        return box
    end
end
local function useTemplate(text, template)
    if not text then return nil end
    if not mw.ustring.find(text, test or '^[%w%s,;]+$') then return text end
    return mw.getCurrentFrame():expandTemplate{ title = template, args = { text } }
end
local function makeDetails(opt)
    if not (opt['aiming'] or opt['dmg'] or opt['spelleffects'] or opt['onhiteffects'] or opt['barriers'] or opt['moreinfo'] or opt['video']) then return nil end
    
    local box = mw.html.create('div'):addClass('skill-more mw-collapsible')
    if not opt['expanded'] then box:addClass('mw-collapsed') end
    local toggle = box:tag('h4')
    toggle:addClass('mw-collapsible-toggle')
          :wikitext('Szczegóły')
          :attr('data-expandtext', 'Pokaż')
          :attr('data-collapsetext', 'Ukryj')
    local content = box:tag('div'):addClass('mw-collapsible-content')
    local frame = mw.getCurrentFrame()
    
    local sec = {}
    sec[#sec+1] = {
        label = 'Celowanie',
        opt['aiming'] or 'Wymagane informacje o celowaniu.',
    }
    if opt['dmg'] then
        sec[#sec+1] = {
            label = 'Obrażenia',
            useTemplate(opt['dmg'], 'Umiejętność/Obrażenia'),
        }
    end
    if opt['aoe'] then
        sec[#sec+1] = {
            label = 'Obszar działania',
            formatLabels(opt['aoe']),
        }
    end
    if opt['spelleffects'] then
        sec[#sec+1] = {
            label = 'Efekty czarów',
            useTemplate(opt['spelleffects'], 'Umiejętność/Efekty czarów'),
        }
    end
    if opt['onhiteffects'] or opt['critical'] or opt['structures'] then
        local s = { label = 'Efekty przy trafieniu' }
        s[#s+1] = useTemplate(opt['onhiteffects'], 'Umiejętność/Efekty przy trafieniu')
        s[#s+1] = useTemplate(opt['critical'], 'Umiejętność/Trafienie krytyczne')
        s[#s+1] = useTemplate(opt['structures'], 'Umiejętność/Struktury')
        sec[#sec+1] = s
    end
    if opt['blocking'] then
        sec[#sec+1] = {
            label = 'Blokowanie',
            useTemplate(opt['blocking'], 'Umiejętność/Blokowanie'),
        }
    end
    if opt['projectile'] or opt['barriers'] then
        local s = { label = 'Pocisk' }
        s[#s+1] = opt['projectile'] and formatLabels(opt['projectile']) or nil
        s[#s+1] = useTemplate(opt['barriers'], 'Umiejętność/Bariery')
        sec[#sec+1] = s
    end
    if opt['shields'] then
        sec[#sec+1] = {
            label = 'Tarcze czarów',
            '* ' .. frame:expandTemplate{ title = 'ei', args = {'Tarcza czarów', 'Tarcze czarów'} } .. ' ' .. opt['shields'],
        }
    end
    if opt['moreinfo'] then
        sec[#sec+1] = {
            label = 'Dodatkowe informacje',
            opt['moreinfo'],
        }
    end
    if opt['video'] then
        sec[#sec+1] = {
            '[[File:' .. opt['video'] .. '|center|520px]]',
        }
    end
    
    for i,v in ipairs(sec) do
        if #sec > 0 then
            local dl = content:tag('dl'):addClass('skill-more-details')
            if v.label then
                dl:tag('dt'):addClass('skill-more-label'):wikitext(v.label)
            end
            for i,v in ipairs(v) do
                if v and v ~= '' then
                    dl:tag('dd')
                      :newline()
                      :wikitext(v)
                      :newline()
                end
            end
        end
    end
    return box
end
local function prepSkills(args)
    local list = {}
    local props = {'champ','name','range','cooldown','cost','extra1','extra2','barriers','aiming','projectile','moreinfo','shields','dmg','spelleffects','onhiteffects','critical','structures','blocking','video','expanded','aoe'}
    
    for no,prefix in ipairs({'f_', 's_'}) do
        if args[prefix..'desc0'] then
            args[prefix..'desc'][1] = args[prefix..'desc0']
            args[prefix..'desc0'] = nil
        end
        if args[prefix..'icon0'] then
            args[prefix..'icon'][1] = args[prefix..'icon0']
            args[prefix..'icon0'] = nil
        end
        if args[prefix..'levels0'] then
            args[prefix..'levels'][1] = args[prefix..'levels0']
            args[prefix..'levels0'] = nil
        end
        
        local obj = {}
        obj.rows = t2a(args:group(prefix..'desc', {prefix..'icon', prefix..'levels'}), true)
            
        if #obj.rows then
            for i,v in ipairs(obj.rows) do
                v['desc'] = v[prefix..'desc']
                v[prefix..'desc'] = nil
                v['levels'] = v[prefix..'levels']
                v[prefix..'levels'] = nil
                v['icon'] = v[prefix..'icon']
                v[prefix..'icon'] = nil
            end
            for i,v in ipairs(props) do
                local k = prefix .. v
                if args[k] and args[k] ~= '' then
                    obj[v] = args[k]
                end
            end
            if not obj.champ and no > 1 then obj.champ = list[1] and list[1].champ or nil end
            if obj.name and #obj.rows > 0 then table.insert(list, obj) end
        end
    end
    return list
end

-- #invokeable
function Skill.create(frame)
    local args = getArgs(frame, {
        translate = {
            f_champ        = 'Bohater',
            f_name         = 'Nazwa',
            f_range        = 'Zasięg',
            f_cost         = 'Koszt',
            f_cooldown     = 'Czas',
            f_extra1       = 'Dodatkowe 1',
            f_extra2       = 'Dodatkowe 2',
            
            f_icon0        = 'Ikona',
            f_desc0        = 'Opis',
            f_levels0      = 'Poziomy',
            f_icon         = 'Ikona #',
            f_desc         = 'Opis #',
            f_levels       = 'Poziomy #',
            
            f_aiming       = 'Celowanie',
            f_aoe          = 'Obszar działania',
            f_projectile   = 'Pocisk',
            f_dmg          = 'Obrażenia',
            f_spelleffects = 'Efekty czarów',
            f_onhiteffects = 'Efekty przy trafieniu',
            f_critical     = 'Trafienie krytyczne',
            f_structures   = 'Struktury',
            f_blocking     = 'Blokowanie',
            f_barriers     = 'Bariery',
            f_shields      = 'Tarcze czarów',
            f_moreinfo     = 'Dodatkowe informacje',
            f_video        = 'Film',
            f_expanded     = 'Rozwinięty',
            
            
            s_champ        = 'Druga/Bohater',
            s_name         = 'Druga/Nazwa',
            s_range        = 'Druga/Zasięg',
            s_cost         = 'Druga/Koszt',
            s_cooldown     = 'Druga/Czas',
            s_extra1       = 'Druga/Dodatkowe 1',
            s_extra2       = 'Druga/Dodatkowe 2',
            
            s_icon0        = 'Druga/Ikona',
            s_desc0        = 'Druga/Opis',
            s_levels0      = 'Druga/Poziomy',
            s_icon         = 'Druga/Ikona #',
            s_desc         = 'Druga/Opis #',
            s_levels       = 'Druga/Poziomy #',
            
            s_aiming       = 'Druga/Celowanie',
            s_aoe          = 'Druga/Obszar działania',
            s_projectile   = 'Druga/Pocisk',
            s_dmg          = 'Druga/Obrażenia',
            s_spelleffects = 'Druga/Efekty czarów',
            s_onhiteffects = 'Druga/Efekty przy trafieniu',
            s_critical     = 'Druga/Trafienie krytyczne',
            s_structures   = 'Druga/Struktury',
            s_blocking     = 'Druga/Blokowanie',
            s_barriers     = 'Druga/Bariery',
            s_shields      = 'Druga/Tarcze czarów',
            s_moreinfo     = 'Druga/Dodatkowe informacje',
            s_video        = 'Druga/Film',
            s_expanded     = 'Druga/Rozwinięty',
        },
        parentFirst = true,
        trim = true,
        removeBlanks = true,
    })
    if not args['f_champ'] then args['f_champ'] = mw.title.getCurrentTitle().rootText end
    
    local skills = prepSkills(args)
    if #skills == 0 then return end
    
    local box = mw.html.create('div'):addClass('skillbox')
    local key = mw.ustring.lower(args[1] or '')
    if key == 'p' or key == 'b' then
        key = 'Bierna'
        box:addClass('skill-passive')
           :attr('id', key)
    elseif key == 'q' or key == 'w' or key == 'e' or key == 'r' then
        box:addClass('skill-'..key)
        key = mw.ustring.upper(key)
        box:attr('id', key)
    end
    
    for i,v in ipairs(skills) do
        v.tip = key
        if v.rows[1].icon == nil then
            v.rows[1].icon = abilityIcon{v.champ, v.name}
        end
        box:node(makeSkill(v))
        box:node(makeDetails(v))
    end
    return box
end
return Skill
Treści społeczności są dostępne na podstawie licencji CC-BY-SA, o ile nie zaznaczono inaczej.