Mudanças entre as edições de "Módulo:Droflax"

De Wiki Gla
Ir para navegação Ir para pesquisar
Linha 11: Linha 11:
     end
     end


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


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


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


     -- Construir HTML
     -- Construir HTML optimizado
     local html = mwHtml.create('div')
     local html = mwHtml.create('div')
         :addClass('personaje-box')
         :addClass('personaje-box')
         :addClass('tier-' .. (data.tier:lower() or ''))
         :addClass('tier-' .. (data.tier:lower() or ''))
        :attr('data-loaded', 'false') -- Para que JS detecte cuando puede actuar
          
          
     -- Cabecera
     -- Cabecera optimizada
     local header = html:tag('div')
     local header = html:tag('div')
         :addClass('personaje-header')
         :addClass('personaje-header')
Linha 58: Linha 59:
         :wikitext(string.format([[
         :wikitext(string.format([[
             <div class="personaje-nome-box">
             <div class="personaje-nome-box">
                 <img src="/images/6/63/Franky_ts_medal.png" class="topbar-icon" loading="lazy">
                 <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="personaje-nome-category">
                     <div class="nome">%s</div>
                     <div class="nome">%s</div>
Linha 67: Linha 68:
         ]], data.nome, data.classe, data.nome, data.tier))
         ]], data.nome, data.classe, data.nome, data.tier))
          
          
     -- Tabs
     -- Tabs con accesibilidad mejorada
     header:tag('div')
     header:tag('div')
         :addClass('personaje-tabs')
         :addClass('personaje-tabs')
        :attr('role', 'tablist')
         :wikitext([[
         :wikitext([[
             <button class="tab-btn" data-tab="arma">Arma</button>
             <button class="tab-btn" data-tab="arma" role="tab" aria-selected="false">Arma</button>
             <button class="tab-btn active" data-tab="habilidades">Habilidades</button>
             <button class="tab-btn active" data-tab="habilidades" role="tab" aria-selected="true">Habilidades</button>
             <button class="tab-btn" data-tab="skins">Skins</button>
             <button class="tab-btn" data-tab="skins" role="tab" aria-selected="false">Skins</button>
         ]])
         ]])
      
      
     -- Precargar imagen principal
     -- Imagen principal con optimización
     if data.image ~= '' then
     if data.image ~= '' then
         html:tag('link')
         html:tag('link')
Linha 82: Linha 84:
             :attr('href', data.image)
             :attr('href', data.image)
             :attr('as', 'image')
             :attr('as', 'image')
            :attr('fetchpriority', 'high')
             :done()
             :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
     end
          
          
    html:tag('img')
     -- Precarga de recursos importantes con priorización
        :addClass('art-personaje')
        :attr('src', data.image)
        :attr('alt', data.nome)
        :attr('loading', 'eager')
   
     -- Precarga de recursos importantes
     if #data.habilidades > 0 then
     if #data.habilidades > 0 then
         -- Precargar primeros 3 iconos de habilidades
         -- Precargar primeros 3 iconos de habilidades
Linha 100: Linha 106:
                     :attr('href', data.habilidades[i].icon)
                     :attr('href', data.habilidades[i].icon)
                     :attr('as', 'image')
                     :attr('as', 'image')
                    :attr('fetchpriority', 'low')
                     :done()
                     :done()
             end
             end
        end
       
        -- Precargar primer video
        if data.habilidades[1].video ~= '' then
            html:tag('link')
                :attr('rel', 'preload')
                :attr('href', data.habilidades[1].video)
                :attr('as', 'video')
                :done()
         end
         end
     end
     end
      
      
     -- Contenedor de habilidades
     -- Contenedor de habilidades optimizado
     local habilidadesContainer = html:tag('div')
     local habilidadesContainer = html:tag('div')
         :addClass('tab-content')
         :addClass('tab-content')
         :addClass('active')
         :addClass('active')
         :attr('id', 'habilidades')
         :attr('id', 'habilidades')
        :attr('role', 'tabpanel')
          
          
     local cuadrosContainer = habilidadesContainer:tag('div')
     local cuadrosContainer = habilidadesContainer:tag('div')
Linha 124: Linha 123:
      
      
     for i, hab in ipairs(data.habilidades) do
     for i, hab in ipairs(data.habilidades) do
         cuadrosContainer:tag('div')
         local cuadro = cuadrosContainer:tag('div')
             :addClass('cuadro')
             :addClass('cuadro')
             :attr('data-index', i)
             :attr('data-index', i)
             :attr('title', hab.nome)
             :attr('title', hab.nome)
             :wikitext(string.format(
             :attr('aria-label', hab.nome)
                 '<img src="%s" alt="%s" loading="lazy">',
           
                hab.icon, 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
     end
      
      
Linha 144: Linha 152:
         ]])
         ]])
      
      
     -- Contenedor de skins
     -- Contenedor de skins optimizado
     local skinsContainer = html:tag('div')
     local skinsContainer = html:tag('div')
         :addClass('tab-content')
         :addClass('tab-content')
         :attr('id', 'skins')
         :attr('id', 'skins')
        :attr('role', 'tabpanel')
      
      
     if #data.skins > 0 then
     if #data.skins > 0 then
Linha 154: Linha 163:
                 <span class="card-skins-title">SKINS & SPOTLIGHTS</span>
                 <span class="card-skins-title">SKINS & SPOTLIGHTS</span>
                 <div class="skins-carousel-wrapper">
                 <div class="skins-carousel-wrapper">
                     <button class="skins-arrow left">«</button>
                     <button class="skins-arrow left" aria-label="Anterior skin">«</button>
                     <div class="skins-carousel">
                     <div class="skins-carousel">
         ]])
         ]])
Linha 160: Linha 169:
         for _, skin in ipairs(data.skins) do
         for _, skin in ipairs(data.skins) do
             skinsContainer:wikitext(string.format([[
             skinsContainer:wikitext(string.format([[
                 <div class="skin-card" title="%s">
                 <div class="skin-card" title="%s" aria-label="%s">
                     <img class="skins--imageBanner" src="/images/default-skin-banner.jpg" loading="lazy">
                     <img class="skins--imageBanner" src="/images/default-skin-banner.jpg" loading="lazy" width="200" height="80">
                     <img class="skins--imageSkin" src="%s" loading="lazy">
                     <img class="skins--imageSkin" src="%s" loading="lazy" width="150" height="150">
                 </div>
                 </div>
             ]], skin.tooltip, skin.image))
             ]], skin.tooltip, skin.tooltip, skin.image))
         end
         end
          
          
         skinsContainer:wikitext([[
         skinsContainer:wikitext([[
                     </div>
                     </div>
                     <button class="skins-arrow right">»</button>
                     <button class="skins-arrow right" aria-label="Siguiente skin">»</button>
                 </div>
                 </div>
             </div>
             </div>
Linha 175: Linha 184:
     end
     end
      
      
     -- Incluir datos para JS
     -- Incluir datos para JS de forma segura
     html:tag('script')
     html:tag('script')
         :attr('type', 'application/json')
         :attr('type', 'application/ld+json')
         :attr('id', 'personaje-data-json')
         :attr('id', 'personaje-data-json')
         :wikitext(mw.text.jsonEncode(data))
         :wikitext(mw.text.jsonEncode(data))
Linha 183: Linha 192:
     return tostring(html)
     return tostring(html)
end
end
return p
return p

Edição das 23h12min de 19 de julho de 2025

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
    
    -- Incluir datos para JS de forma segura
    html:tag('script')
        :attr('type', 'application/ld+json')
        :attr('id', 'personaje-data-json')
        :wikitext(mw.text.jsonEncode(data))
    
    return tostring(html)
end

return p