Mudanças entre as edições de "Módulo:I.Utils"

De Wiki Gla
Ir para navegação Ir para pesquisar
(Criou página com '-- Módulo:C.Utils — funções utilitárias compartilhadas local M = {} -- Cache de módulos carregados M._moduleCache = {} -----------------------------------------------...')
 
m
 
(3 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 1: Linha 1:
-- Módulo:C.Utils — funções utilitárias compartilhadas
-- Módulo:I.Utils — funções utilitárias compartilhadas
local M = {}
local M = {}


Linha 5: Linha 5:
M._moduleCache = {}
M._moduleCache = {}


--------------------------------------------------------------------------------
-- ===== Funções básicas =====
-- Utils
--------------------------------------------------------------------------------


function M.trim(s)
function M.trim(s)
Linha 13: Linha 11:
end
end


-- Gera URL pública de arquivo (tenta "Special:" e "Especial:" por compat)
function M.safeArgs(node)
function M.fileURL(name)
     return (node and node.args) or {}
     name = M.trim(name or "")
    if name == "" then
        return ""
    end
    name = name:gsub("^Arquivo:", ""):gsub("^File:", "")
    local t1 = mw.title.new("Special:FilePath/" .. name)
    if t1 then
        local u = t1:fullUrl()
        if u and u ~= "" then
            return u
        end
    end
    local t2 = mw.title.new("Especial:FilePath/" .. name)
    if t2 then
        local u = t2:fullUrl()
        if u and u ~= "" then
            return u
        end
    end
    return ""
end
end


-- Normaliza dimensões (mantém %, px, rem; números viram %)
-- Separa uma sequência de {} (JSONs colados) em uma tabela de chunks
function M.normalizeDim(x)
function M.collectJsonObjects(s)
     x = mw.text.trim(tostring(x or ""))
     s = tostring(s or "")
     if x == "" then
     local out = {}
         return nil
    for chunk in s:gmatch("%b{}") do
         table.insert(out, chunk)
     end
     end
     if x:match("%%$") then
     return out
        return x
    end
    if x:match("^%d+%.?%d*$") then
        return x .. "%"
    end
    return x
end
 
-- Monta string dos atributos (PVE, PvP, Energia, CD), usando '-' quando vazio
function M.makeAttrString(pve, pvp, energy, cd)
    local function nzOrDash(s)
        s = M.trim(s or "")
        return (s ~= "" and s or "-")
    end
    return table.concat({ nzOrDash(pve), nzOrDash(pvp), nzOrDash(energy), nzOrDash(cd) }, ", ")
end
end


-- Carrega o módulo do personagem (Módulo:<Nome>/Modulo/Module) com cache
-- Carrega módulo de personagem com cache
-- Carrega APENAS pelo nome exato passado, sem fallbacks
-- Carrega APENAS pelo nome exato passado, sem fallbacks
function M.requireCharModule(char)
function M.requireCharacterModule(charName)
     char = M.trim(char or "")
     charName = M.trim(charName or "")
     if char == "" then
     if charName == "" then
         return nil
         return nil
     end
     end


     -- Verifica cache primeiro
     -- Verifica cache primeiro
     if M._moduleCache[char] then
     if M._moduleCache[charName] then
         return M._moduleCache[char]
         return M._moduleCache[charName]
     end
     end


    local ok, data
     -- Tenta carregar diretamente
 
     local ok, data = pcall(function()
     -- Tenta Módulo:Nome
         return require("Módulo:" .. charName)
     ok, data = pcall(function()
         return require("Módulo:" .. char)
     end)
     end)
     if ok and type(data) == "table" then
     if ok and type(data) == "table" then
         M._moduleCache[char] = data
         M._moduleCache[charName] = data
         return data
         return data
     end
     end


     -- Tenta com espaços (underscores → espaço)
     -- Tenta com espaços (underscores → espaço)
     local spaced = char:gsub("_", " ")
     local spaced = charName:gsub("_", " ")
     if spaced ~= char then
     if spaced ~= charName then
         ok, data = pcall(function()
         ok, data = pcall(function()
             return require("Módulo:" .. spaced)
             return require("Módulo:" .. spaced)
         end)
         end)
         if ok and type(data) == "table" then
         if ok and type(data) == "table" then
             M._moduleCache[char] = data
             M._moduleCache[charName] = data
             return data
             return data
         end
         end
Linha 98: Linha 60:


     -- Tenta com underscores (espaços → _)
     -- Tenta com underscores (espaços → _)
     local underscored = char:gsub(" ", "_")
     local underscored = charName:gsub(" ", "_")
     if underscored ~= char then
     if underscored ~= charName then
         ok, data = pcall(function()
         ok, data = pcall(function()
             return require("Módulo:" .. underscored)
             return require("Módulo:" .. underscored)
         end)
         end)
         if ok and type(data) == "table" then
         if ok and type(data) == "table" then
             M._moduleCache[char] = data
             M._moduleCache[charName] = data
             return data
             return data
         end
         end
Linha 110: Linha 72:


     -- Fallback: tenta última palavra do nome (ex: "Trafalgar Law" → "Law")
     -- Fallback: tenta última palavra do nome (ex: "Trafalgar Law" → "Law")
     local lastWord = char:match("(%S+)%s*$")
     local lastWord = charName:match("(%S+)%s*$")
     if lastWord and lastWord ~= char then
     if lastWord and lastWord ~= charName then
         ok, data = pcall(function()
         ok, data = pcall(function()
             return require("Módulo:" .. lastWord)
             return require("Módulo:" .. lastWord)
         end)
         end)
         if ok and type(data) == "table" then
         if ok and type(data) == "table" then
             M._moduleCache[char] = data
             M._moduleCache[charName] = data
             return data
             return data
         end
         end
     end
     end


     -- Tenta Modulo:Nome (sem acento)
     return nil
     ok, data = pcall(function()
end
         return require("Modulo:" .. char)
 
     end)
-- Resolve nome do personagem/módulo a partir dos frames (busca recursiva em todos os níveis)
     if ok and type(data) == "table" then
-- Prioridade: |module= > |char= > |nome= > parent frames > título da página (último recurso)
        M._moduleCache[char] = data
function M.resolveCharFromFrames(frame, a)
         return data
    a = a or {}
 
    -- Prioridade 1: parâmetro explícito |module=
     if a.module and M.trim(a.module) ~= "" then
        return M.trim(a.module)
    end
 
    -- Prioridade 2: parâmetro explícito |char=
    if a.char and M.trim(a.char) ~= "" then
         return M.trim(a.char)
    end
 
    -- Prioridade 3: parâmetro |nome=
    if a.nome and M.trim(a.nome) ~= "" then
        return M.trim(a.nome)
     end
 
    -- Prioridade 4: busca recursiva em todos os parent frames (até 10 níveis)
     if frame and frame.getParent then
        local current = frame
        for i = 1, 10 do
            local parent = current:getParent()
            if not parent then break end
            if parent.args then
                -- Primeiro verifica |module= nos pais
                if parent.args.module and M.trim(parent.args.module) ~= "" then
                    return M.trim(parent.args.module)
                end
                if parent.args.nome and M.trim(parent.args.nome) ~= "" then
                    return M.trim(parent.args.nome)
                end
                if parent.args.char and M.trim(parent.args.char) ~= "" then
                    return M.trim(parent.args.char)
                end
            end
            current = parent
         end
     end
     end


     -- Tenta Module:Nome (inglês)
     -- Último recurso: título da página atual
     ok, data = pcall(function()
    -- Só usado se nenhum |module=, |nome= ou |char= foi encontrado
         return require("Module:" .. char)
    local title = mw.title.getCurrentTitle()
     return title and M.trim(title.text) or ""
end
 
-- ===== I18N =====
 
M.I18N = {
    pt = {
        level = "Nível",
        power = "Poder",
        power_pvp = "Poder PvP",
        energy = "Energia",
        energy_cost = "Energia",
        energy_gain = "Energia",
        cooldown = "Recarga"
    },
    en = {
        level = "Level",
        power = "Power",
        power_pvp = "Power PvP",
        energy = "Energy",
        energy_cost = "Energy",
        energy_gain = "Energy",
        cooldown = "Cooldown"
    },
    es = {
        level = "Nivel",
        power = "Poder",
        power_pvp = "Poder PvP",
        energy = "Energía",
        energy_cost = "Energía",
        energy_gain = "Energía",
        cooldown = "Enfriamiento"
    },
    pl = {
        level = "Poziom",
        power = "Moc",
        power_pvp = "Moc PvP",
        energy = "Energia",
        energy_cost = "Energia",
        energy_gain = "Energia",
        cooldown = "Odnawianie"
    }
}
 
-- ===== Cores inline =====
 
M.COLOR = {
    debuff = "#F78181",
    atk = "#FAAC58",
    def = "#2E9AFE",
    ms = "#04B45F",
    hp = "#01DFD7",
    sec = "#F5DA81"
}
 
-- Substitui [atk:], [def:], etc. por spans coloridos
-- Usa [tag:value] em vez de {{tag:value}} para evitar que MediaWiki interprete como predefinição
function M.colorize(txt)
    if not txt or txt == "" then
        return ""
    end
    local result = (tostring(txt):gsub("%[%s*(%a+)%s*:%s*([^%]]+)%s*%]", function(tag, inner)
        tag = tag:lower()
        local hex = M.COLOR[tag] or ""
        if hex == "" then
            return "[" .. tag .. ":" .. inner .. "]"
        end
        return string.format('<span style="color:%s;font-weight:bold;">%s</span>', hex, M.trim(inner))
    end))
    -- Garante negrito em textos com <font color="...">
    result = result:gsub("<font([^>]*)>", function(attrs)
        local lower = attrs:lower()
        if not lower:match("color%s*=") then
            return "<font" .. attrs .. ">"
        end
        if lower:match("font%-weight") then
            return "<font" .. attrs .. ">"
        end
         if attrs:match("style%s*=") then
            local updated = attrs:gsub("style%s*=%s*(['\"])(.-)%1", function(quote, style)
                local styleLower = style:lower()
                if styleLower:find("font%-weight") then
                    return " style=" .. quote .. style .. quote
                end
                local sep = ""
                if style ~= "" and not style:match(";%s*$") then
                    sep = ";"
                end
                return " style=" .. quote .. style .. sep .. "font-weight:bold;" .. quote
            end, 1)
            return "<font" .. updated .. ">"
        end
        return "<font" .. attrs .. ' style="font-weight:bold;">'
     end)
     end)
     if ok and type(data) == "table" then
     return result
        M._moduleCache[char] = data
end
        return data
 
    end
-- ===== Funções auxiliares =====


     return nil
function M.nz(v)
    v = v or ""
     return (M.trim(v) ~= "" and v or nil)
end
end


-- Separa uma sequência de {} (JSONs colados) em uma tabela de chunks
-- Parse flags CSV (normaliza para tokens válidos)
function M.collectJsonObjects(s)
function M.parseFlags(flagsStr)
     s = tostring(s or "")
     local flagsArr = {}
    local out = {}
    if flagsStr and M.trim(flagsStr) ~= "" then
    for chunk in s:gmatch("%b{}") do
        local validFlags = { aggro = true, bridge = true, wall = true, quickcast = true, wallpass = true }
        table.insert(out, chunk)
        local seen = {}
        for token in string.gmatch(M.trim(flagsStr), "[^,]+") do
            local normalized = M.trim(token):lower()
            if validFlags[normalized] and not seen[normalized] then
                table.insert(flagsArr, normalized)
                seen[normalized] = true
            end
        end
     end
     end
     return out
     return flagsArr
end
end


return M
return M

Edição atual tal como às 00h34min de 25 de janeiro de 2026

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

-- Módulo:I.Utils — funções utilitárias compartilhadas
local M = {}

-- Cache de módulos carregados
M._moduleCache = {}

-- ===== Funções básicas =====

function M.trim(s)
    return (tostring(s or ""):gsub("^%s+", ""):gsub("%s+$", ""))
end

function M.safeArgs(node)
    return (node and node.args) or {}
end

-- Separa uma sequência de {} (JSONs colados) em uma tabela de chunks
function M.collectJsonObjects(s)
    s = tostring(s or "")
    local out = {}
    for chunk in s:gmatch("%b{}") do
        table.insert(out, chunk)
    end
    return out
end

-- Carrega módulo de personagem com cache
-- Carrega APENAS pelo nome exato passado, sem fallbacks
function M.requireCharacterModule(charName)
    charName = M.trim(charName or "")
    if charName == "" then
        return nil
    end

    -- Verifica cache primeiro
    if M._moduleCache[charName] then
        return M._moduleCache[charName]
    end

    -- Tenta carregar diretamente
    local ok, data = pcall(function()
        return require("Módulo:" .. charName)
    end)
    if ok and type(data) == "table" then
        M._moduleCache[charName] = data
        return data
    end

    -- Tenta com espaços (underscores → espaço)
    local spaced = charName:gsub("_", " ")
    if spaced ~= charName then
        ok, data = pcall(function()
            return require("Módulo:" .. spaced)
        end)
        if ok and type(data) == "table" then
            M._moduleCache[charName] = data
            return data
        end
    end

    -- Tenta com underscores (espaços → _)
    local underscored = charName:gsub(" ", "_")
    if underscored ~= charName then
        ok, data = pcall(function()
            return require("Módulo:" .. underscored)
        end)
        if ok and type(data) == "table" then
            M._moduleCache[charName] = data
            return data
        end
    end

    -- Fallback: tenta última palavra do nome (ex: "Trafalgar Law" → "Law")
    local lastWord = charName:match("(%S+)%s*$")
    if lastWord and lastWord ~= charName then
        ok, data = pcall(function()
            return require("Módulo:" .. lastWord)
        end)
        if ok and type(data) == "table" then
            M._moduleCache[charName] = data
            return data
        end
    end

    return nil
end

-- Resolve nome do personagem/módulo a partir dos frames (busca recursiva em todos os níveis)
-- Prioridade: |module= > |char= > |nome= > parent frames > título da página (último recurso)
function M.resolveCharFromFrames(frame, a)
    a = a or {}

    -- Prioridade 1: parâmetro explícito |module=
    if a.module and M.trim(a.module) ~= "" then
        return M.trim(a.module)
    end

    -- Prioridade 2: parâmetro explícito |char=
    if a.char and M.trim(a.char) ~= "" then
        return M.trim(a.char)
    end

    -- Prioridade 3: parâmetro |nome=
    if a.nome and M.trim(a.nome) ~= "" then
        return M.trim(a.nome)
    end

    -- Prioridade 4: busca recursiva em todos os parent frames (até 10 níveis)
    if frame and frame.getParent then
        local current = frame
        for i = 1, 10 do
            local parent = current:getParent()
            if not parent then break end
            if parent.args then
                -- Primeiro verifica |module= nos pais
                if parent.args.module and M.trim(parent.args.module) ~= "" then
                    return M.trim(parent.args.module)
                end
                if parent.args.nome and M.trim(parent.args.nome) ~= "" then
                    return M.trim(parent.args.nome)
                end
                if parent.args.char and M.trim(parent.args.char) ~= "" then
                    return M.trim(parent.args.char)
                end
            end
            current = parent
        end
    end

    -- Último recurso: título da página atual
    -- Só usado se nenhum |module=, |nome= ou |char= foi encontrado
    local title = mw.title.getCurrentTitle()
    return title and M.trim(title.text) or ""
end

-- ===== I18N =====

M.I18N = {
    pt = {
        level = "Nível",
        power = "Poder",
        power_pvp = "Poder PvP",
        energy = "Energia",
        energy_cost = "Energia",
        energy_gain = "Energia",
        cooldown = "Recarga"
    },
    en = {
        level = "Level",
        power = "Power",
        power_pvp = "Power PvP",
        energy = "Energy",
        energy_cost = "Energy",
        energy_gain = "Energy",
        cooldown = "Cooldown"
    },
    es = {
        level = "Nivel",
        power = "Poder",
        power_pvp = "Poder PvP",
        energy = "Energía",
        energy_cost = "Energía",
        energy_gain = "Energía",
        cooldown = "Enfriamiento"
    },
    pl = {
        level = "Poziom",
        power = "Moc",
        power_pvp = "Moc PvP",
        energy = "Energia",
        energy_cost = "Energia",
        energy_gain = "Energia",
        cooldown = "Odnawianie"
    }
}

-- ===== Cores inline =====

M.COLOR = {
    debuff = "#F78181",
    atk = "#FAAC58",
    def = "#2E9AFE",
    ms = "#04B45F",
    hp = "#01DFD7",
    sec = "#F5DA81"
}

-- Substitui [atk:], [def:], etc. por spans coloridos
-- Usa [tag:value] em vez de {{tag:value}} para evitar que MediaWiki interprete como predefinição
function M.colorize(txt)
    if not txt or txt == "" then
        return ""
    end
    local result = (tostring(txt):gsub("%[%s*(%a+)%s*:%s*([^%]]+)%s*%]", function(tag, inner)
        tag = tag:lower()
        local hex = M.COLOR[tag] or ""
        if hex == "" then
            return "[" .. tag .. ":" .. inner .. "]"
        end
        return string.format('<span style="color:%s;font-weight:bold;">%s</span>', hex, M.trim(inner))
    end))
    -- Garante negrito em textos com <font color="...">
    result = result:gsub("<font([^>]*)>", function(attrs)
        local lower = attrs:lower()
        if not lower:match("color%s*=") then
            return "<font" .. attrs .. ">"
        end
        if lower:match("font%-weight") then
            return "<font" .. attrs .. ">"
        end
        if attrs:match("style%s*=") then
            local updated = attrs:gsub("style%s*=%s*(['\"])(.-)%1", function(quote, style)
                local styleLower = style:lower()
                if styleLower:find("font%-weight") then
                    return " style=" .. quote .. style .. quote
                end
                local sep = ""
                if style ~= "" and not style:match(";%s*$") then
                    sep = ";"
                end
                return " style=" .. quote .. style .. sep .. "font-weight:bold;" .. quote
            end, 1)
            return "<font" .. updated .. ">"
        end
        return "<font" .. attrs .. ' style="font-weight:bold;">'
    end)
    return result
end

-- ===== Funções auxiliares =====

function M.nz(v)
    v = v or ""
    return (M.trim(v) ~= "" and v or nil)
end

-- Parse flags CSV (normaliza para tokens válidos)
function M.parseFlags(flagsStr)
    local flagsArr = {}
    if flagsStr and M.trim(flagsStr) ~= "" then
        local validFlags = { aggro = true, bridge = true, wall = true, quickcast = true, wallpass = true }
        local seen = {}
        for token in string.gmatch(M.trim(flagsStr), "[^,]+") do
            local normalized = M.trim(token):lower()
            if validFlags[normalized] and not seen[normalized] then
                table.insert(flagsArr, normalized)
                seen[normalized] = true
            end
        end
    end
    return flagsArr
end

return M