Módulo:Droflax

De Wiki Gla
Revisão de 23h16min de 19 de julho de 2025 por Droflax (discussão | contribs)
Ir para navegação Ir para pesquisar

A documentação para este módulo pode ser criada em Módulo:Droflax/doc

local p = {}

function p.render(frame)
    local args = frame:getParent().args
    local mwHtml = require('mw.html')
    local util = require('libraryUtil')
    
    -- Validación básica
    if not args.nome or args.nome == '' then
        return '<div class="error">Falta el nombre del personaje</div>'
    end

    -- Construir estructura de datos optimizada
    local data = {
        nome = args.nome,
        tier = args.tier or '',
        classe = args.classe or '',
        image = args.image or '',
        habilidades = {},
        skins = {}
    }

    -- Procesar habilidades (1-15) con validación
    for i = 1, 15 do
        if args['hab'..i..'-nome'] and args['hab'..i..'-nome'] ~= '' then
            table.insert(data.habilidades, {
                nome = args['hab'..i..'-nome'],
                icon = args['hab'..i..'-icon'] or '',
                level = tonumber(args['hab'..i..'-level']) or 0,
                desc = args['hab'..i..'-desc'] or '',
                atr = args['hab'..i..'-atr'] or '',
                video = args['hab'..i..'-video'] or ''
            })
        end
    end

    -- Procesar skins (1-5) con validación
    for i = 1, 5 do
        if args['skin'..i..'-image'] and args['skin'..i..'-image'] ~= '' then
            table.insert(data.skins, {
                image = args['skin'..i..'-image'],
                tooltip = (args['skin'..i..'-tooltip'] or ''):gsub('\n', '<br>')
            })
        end
    end

    -- Construir HTML optimizado
    local html = mwHtml.create('div')
        :addClass('personaje-box')
        :addClass('tier-' .. (data.tier:lower() or ''))
        :attr('data-loaded', 'false') -- Para que JS detecte cuando puede actuar
        
    -- Cabecera optimizada
    local header = html:tag('div')
        :addClass('personaje-header')
        
    header:tag('div')
        :addClass('personaje-topbar')
        :wikitext(string.format([[
            <div class="personaje-nome-box">
                <img src="/images/6/63/Franky_ts_medal.png" class="topbar-icon" loading="lazy" width="40" height="40">
                <div class="personaje-nome-category">
                    <div class="nome">%s</div>
                    <div class="classes">%s</div>
                </div>
            </div>
            <div class="topbar-description">%s é um personagem do tier %s.</div>
        ]], data.nome, data.classe, data.nome, data.tier))
        
    -- Tabs con accesibilidad mejorada
    header:tag('div')
        :addClass('personaje-tabs')
        :attr('role', 'tablist')
        :wikitext([[
            <button class="tab-btn" data-tab="arma" role="tab" aria-selected="false">Arma</button>
            <button class="tab-btn active" data-tab="habilidades" role="tab" aria-selected="true">Habilidades</button>
            <button class="tab-btn" data-tab="skins" role="tab" aria-selected="false">Skins</button>
        ]])
    
    -- Imagen principal con optimización
    if data.image ~= '' then
        html:tag('link')
            :attr('rel', 'preload')
            :attr('href', data.image)
            :attr('as', 'image')
            :attr('fetchpriority', 'high')
            :done()
            
        html:tag('img')
            :addClass('art-personaje')
            :attr('src', data.image)
            :attr('alt', data.nome)
            :attr('loading', 'eager')
            :attr('width', '300')
            :attr('height', '300')
            :attr('decoding', 'async')
    end
        
    -- Precarga de recursos importantes con priorización
    if #data.habilidades > 0 then
        -- Precargar primeros 3 iconos de habilidades
        for i = 1, math.min(3, #data.habilidades) do
            if data.habilidades[i].icon ~= '' then
                html:tag('link')
                    :attr('rel', 'preload')
                    :attr('href', data.habilidades[i].icon)
                    :attr('as', 'image')
                    :attr('fetchpriority', 'low')
                    :done()
            end
        end
    end
    
    -- Contenedor de habilidades optimizado
    local habilidadesContainer = html:tag('div')
        :addClass('tab-content')
        :addClass('active')
        :attr('id', 'habilidades')
        :attr('role', 'tabpanel')
        
    local cuadrosContainer = habilidadesContainer:tag('div')
        :addClass('cuadros-container')
    
    for i, hab in ipairs(data.habilidades) do
        local cuadro = cuadrosContainer:tag('div')
            :addClass('cuadro')
            :attr('data-index', i)
            :attr('title', hab.nome)
            :attr('aria-label', hab.nome)
            
        if hab.icon ~= '' then
            cuadro:tag('img')
                :attr('src', hab.icon)
                :attr('alt', hab.nome)
                :attr('loading', 'lazy')
                :attr('width', '40')
                :attr('height', '40')
                :attr('decoding', 'async')
        else
            cuadro:wikitext('<div class="icon-placeholder"></div>')
        end
    end
    
    -- Contenedor de detalles de habilidades
    habilidadesContainer:tag('div')
        :addClass('habilidades-container')
        :wikitext([[
            <div class="habilidades-details">
                <div class="descripcion-container"></div>
            </div>
            <div class="video-container"></div>
        ]])
    
    -- Contenedor de skins optimizado
    local skinsContainer = html:tag('div')
        :addClass('tab-content')
        :attr('id', 'skins')
        :attr('role', 'tabpanel')
    
    if #data.skins > 0 then
        skinsContainer:wikitext([[
            <div class="card-skins">
                <span class="card-skins-title">SKINS & SPOTLIGHTS</span>
                <div class="skins-carousel-wrapper">
                    <button class="skins-arrow left" aria-label="Anterior skin">«</button>
                    <div class="skins-carousel">
        ]])
        
        for _, skin in ipairs(data.skins) do
            skinsContainer:wikitext(string.format([[
                <div class="skin-card" title="%s" aria-label="%s">
                    <img class="skins--imageBanner" src="/images/default-skin-banner.jpg" loading="lazy" width="200" height="80">
                    <img class="skins--imageSkin" src="%s" loading="lazy" width="150" height="150">
                </div>
            ]], skin.tooltip, skin.tooltip, skin.image))
        end
        
        skinsContainer:wikitext([[
                    </div>
                    <button class="skins-arrow right" aria-label="Siguiente skin">»</button>
                </div>
            </div>
        ]])
    end
    
        -- Marcar cuando el contenido está listo para JS
    html:tag('script')
        :wikitext([[
            document.addEventListener('DOMContentLoaded', function() {
                var container = document.querySelector('.personaje-box');
                if (container) {
                    // Activar solo estilos base inmediatamente
                    container.setAttribute('data-styles-ready', 'true');
                    
                    // Precargar recursos secundarios
                    var preloadLinks = [];
                    var skillsData = JSON.parse(document.getElementById('personaje-data-json').textContent);
                    
                    // Precargar videos de habilidades
                    skillsData.habilidades.forEach(function(hab, index) {
                        if (index < 3 && hab.video) {
                            preloadLinks.push('<link rel="preload" href="' + hab.video + '" as="video" fetchpriority="low">');
                        }
                    });
                    
                    // Precargar imágenes de skins
                    skillsData.skins.forEach(function(skin, index) {
                        if (index < 2 && skin.image) {
                            preloadLinks.push('<link rel="preload" href="' + skin.image + '" as="image" fetchpriority="low">');
                        }
                    });
                    
                    document.head.insertAdjacentHTML('beforeend', preloadLinks.join(''));
                }
            });
        ]])
    
    return tostring(html)
end

return p