Mudanças entre as edições de "Módulo:Info"
Ir para navegação
Ir para pesquisar
m Etiqueta: Reversão manual |
m (test subskill) |
||
| Linha 15: | Linha 15: | ||
return nil | return nil | ||
end | end | ||
local | local ok, data = pcall(function() | ||
return require("Módulo:" .. charName) | return require("Módulo:" .. charName) | ||
end) | end) | ||
| Linha 23: | Linha 21: | ||
return data | return data | ||
end | end | ||
-- fallback: nomes com espaço vs underscore | |||
charName = charName:gsub(" ", "_") | |||
ok, data = pcall(function() | ok, data = pcall(function() | ||
return require(" | return require("Módulo:" .. charName) | ||
end) | end) | ||
if ok and type(data) == "table" then | if ok and type(data) == "table" then | ||
return data | return data | ||
end | end | ||
return nil | |||
end | |||
-- Coleta objetos JSON em sequência a partir de um texto concatenado (ex.: |subs= com vários {{Subskill}}) | |||
local function collectJsonObjects(s) | |||
s = tostring(s or "") | |||
local out = {} | |||
for chunk in s:gmatch("%b{}") do | |||
table.insert(out, chunk) | |||
end | end | ||
return out | |||
return | |||
end | end | ||
-- resolve personagem a partir de frame/parent (usado por expand/tier/tags/skill) | |||
local function resolveCharFromFrames(frame, a) | local function resolveCharFromFrames(frame, a) | ||
if | a = a or {} | ||
-- tenta parent args.nome | |||
if frame and frame.getParent then | |||
local parent = frame:getParent() | |||
if parent and parent.args then | |||
if parent.args.nome and trim(parent.args.nome) ~= "" then | |||
return trim(parent.args.nome) | |||
end | |||
-- alguns usos guardam em classX (tierX/tagsX) | |||
for k, v in pairs(parent.args) do | |||
if type(k) == "string" and k:match("^class") and trim(v) ~= "" then | |||
return trim(v) | |||
end | |||
end | |||
end | |||
end | end | ||
-- tenta o próprio frame (às vezes vem direto) | |||
if a.nome and trim(a.nome) ~= "" then | if a.nome and trim(a.nome) ~= "" then | ||
return trim(a.nome) | return trim(a.nome) | ||
end | end | ||
if a.char and trim(a.char) ~= "" then | |||
return trim(a.char) | |||
if | |||
end | end | ||
-- título da página | |||
local title = mw.title.getCurrentTitle() | local title = mw.title.getCurrentTitle() | ||
return title and trim(title.text) or "" | return title and trim(title.text) or "" | ||
| Linha 78: | Linha 75: | ||
local COLOR = { | local COLOR = { | ||
debuff = "#ff5252", | debuff = "#ff5252", | ||
ms = "#5bc0de", | |||
hp = "#70d86b", | |||
atk = "#ffd166", | |||
def = "#c0a9ff", | |||
sec = "# | sec = "#ffa07a", | ||
} | } | ||
local function colorize( | -- substitui marcadores {{atk:}}, {{def:}}, {{ms:}}, {{hp:}}, {{sec:}}, {{debuff:}} no texto | ||
if | local function colorize(text) | ||
return "" | text = tostring(text or "") | ||
local patterns = { | |||
{ "atk", COLOR.atk }, | |||
{ "def", COLOR.def }, | |||
{ "ms", COLOR.ms }, | |||
{ "hp", COLOR.hp }, | |||
{ "sec", COLOR.sec }, | |||
{ "debuff",COLOR.debuff}, | |||
} | |||
for _, pair in ipairs(patterns) do | |||
local key, color = pair[1], pair[2] | |||
-- {{key:VALOR}} → <span class="tag key">VALOR</span> | |||
text = text:gsub("{{%s*" .. key .. "%s*:%s*([^}]+)%s*}}", function(val) | |||
return string.format('<span class="tag %s" style="--tag:%s">%s</span>', key, color, trim(val)) | |||
end) | |||
end | |||
return text | |||
end | |||
-- ===== Tier/Tags helpers ===== | |||
local function expandTierFrom(data, lang) | |||
lang = (lang or "pt"):lower() | |||
-- tenta i18n | |||
if data.tier_i18n and data.tier_i18n[lang] then | |||
return tostring(data.tier_i18n[lang]) | |||
end | |||
return tostring(data.tier or "") | |||
end | |||
local function expandTagsFrom(data, lang) | |||
lang = (lang or "pt"):lower() | |||
if data.tags_i18n and data.tags_i18n[lang] and type(data.tags_i18n[lang]) == "table" then | |||
return table.concat(data.tags_i18n[lang], " / ") | |||
end | |||
if type(data.tags) == "table" then | |||
return table.concat(data.tags, " / ") | |||
end | end | ||
return ( | return tostring(data.tags or "") | ||
end | end | ||
-- ===== API ===== | -- ===== API ===== | ||
function p. | -- Tier: {{#invoke:Info|tier|pt|NomeDoPersonagem}} ou {{#invoke:Info|tier|tierNome}} | ||
local | function p.tier(frame) | ||
local | local token = trim(frame.args[1] or "") | ||
local nome = trim(frame.args[2] or (frame:getParent() and frame:getParent().args.nome) or "") | |||
local lang = trim(frame.args.lang or (frame:getParent() and frame:getParent().args.lang) or "pt"):lower() | |||
if token == "" then | |||
return "" | |||
end | |||
local char = "" | |||
if token:lower():sub(1,4) == "tier" then | |||
char = token:match("^tier(.+)$") or "" | |||
else | |||
char = nome | |||
end | |||
if char == "" then | if char == "" then | ||
char = resolveCharFromFrames(frame, | char = resolveCharFromFrames(frame, frame.args) | ||
end | end | ||
local data = requireCharacterModule(char) or {} | local data = requireCharacterModule(char) or {} | ||
return | return expandTierFrom(data, lang) | ||
end | end | ||
function p. | -- Tags: {{#invoke:Info|tags|pt|NomeDoPersonagem}} ou {{#invoke:Info|tags|tagsNome}} | ||
local | function p.tags(frame) | ||
local | local token = trim(frame.args[1] or "") | ||
local nome = trim(frame.args[2] or (frame:getParent() and frame:getParent().args.nome) or "") | |||
local lang = trim(frame.args.lang or (frame:getParent() and frame:getParent().args.lang) or "pt"):lower() | |||
if token == "" then | |||
return "" | |||
end | |||
local char = "" | |||
if token:lower():sub(1,4) == "tags" then | |||
char = token:match("^tags(.+)$") or "" | |||
else | |||
char = nome | |||
end | |||
if char == "" then | if char == "" then | ||
char = resolveCharFromFrames(frame, | char = resolveCharFromFrames(frame, frame.args) | ||
end | end | ||
local data = requireCharacterModule(char) or {} | local data = requireCharacterModule(char) or {} | ||
return expandTagsFrom(data, lang) | |||
end | end | ||
-- Skill | -- Skill principal → serializa objeto consumido pelo Widget/Character | ||
-- Uso: {{#invoke:Info|skill|M=1|icon=...|level=...|energy=...|powerpve=...|powerpvp=...|cooldown=...|video=...|subs=...}} | |||
function p.skill(frame) | function p.skill(frame) | ||
local a = safeArgs(frame) | local a = safeArgs(frame) | ||
| Linha 171: | Linha 216: | ||
powerpvp = nz(a.powerpvp), | powerpvp = nz(a.powerpvp), | ||
cooldown = nz(a.cooldown), | cooldown = nz(a.cooldown), | ||
video = a.video or "" | video = a.video or "", | ||
name = name, -- pode estar vazio caso use outside (não quebra) | |||
} | } | ||
-- inclui a descrição escolhida (se preferir, o Widget usa desc_i18n) | |||
if chosen ~= "" then | if chosen ~= "" then | ||
obj.desc = chosen | obj.desc = chosen | ||
| Linha 187: | Linha 232: | ||
obj.descEs = desc_i18n.es | obj.descEs = desc_i18n.es | ||
obj.descPl = desc_i18n.pl | obj.descPl = desc_i18n.pl | ||
end | |||
-- Subskills: empacota os JSONs vindos via |subs= (cada {{Subskill}} vira um objeto) | |||
do | |||
local subsPacked = a.subs or "" | |||
local subsArr = {} | |||
for _, chunk in ipairs(collectJsonObjects(subsPacked)) do | |||
local ok, sub = pcall(mw.text.jsonDecode, chunk) | |||
if ok and type(sub) == "table" then | |||
table.insert(subsArr, sub) | |||
end | |||
end | |||
if #subsArr > 0 then | |||
obj.subs = subsArr | |||
end | |||
-- Se o módulo do personagem definiu suborder para essa skill (pelo índice M), inclui para a UI respeitar a ordem | |||
if a.M and tonumber(a.M) then | |||
local m = tonumber(a.M) | |||
local order = (data and data.order) or {} | |||
local key = order[m] or "" | |||
local sk = (data and data.skills and data.skills[key]) or {} | |||
if type(sk) == "table" and type(sk.suborder) == "table" then | |||
obj.suborder = sk.suborder | |||
end | |||
end | |||
end | end | ||
return mw.text.jsonEncode(obj) | return mw.text.jsonEncode(obj) | ||
end | end | ||
-- | |||
-- Emote (sem M) | |||
function p.emote(frame) | function p.emote(frame) | ||
local a = safeArgs(frame) | local a = safeArgs(frame) | ||
local obj = { | local obj = { | ||
name = "Emote", | name = "Emote", | ||
icon = (trim(a.icon or "") ~= "" and a.icon or "Nada.png"), | icon = (trim(a.icon or "") ~= "" and a.icon or "Nada.png"), | ||
level = | level = (trim(a.level or "") ~= "" and a.level or "NIVEL"), | ||
video = a.video or "", | video = a.video or "", | ||
} | } | ||
return mw.text.jsonEncode(obj) | return mw.text.jsonEncode(obj) | ||
end | end | ||
-- expandTier | -- Subskill → serializa dados da subskill (nome exato conforme suborder do módulo do personagem) | ||
-- Uso: dentro de |subs= da Skill: | |||
-- {{Subskill|n=Trap Door|icon=...|level=...|video=...|energy=...|powerpve=...|powerpvp=...|cooldown=...}} | |||
function p.subskill(frame) | |||
local a = safeArgs(frame) | |||
local lang = trim((a.lang or (frame:getParent() and frame:getParent().args.lang) or "pt"):lower()) | |||
local n = trim(a.n or "") | |||
if n == "" then | |||
return mw.text.jsonEncode({}) | |||
end | |||
-- Resolve personagem pelo contexto | |||
local char = trim(a.char or (frame:getParent() and frame:getParent().args.nome) or "") | |||
if char == "" then | |||
char = resolveCharFromFrames(frame, a) | |||
end | |||
local data = requireCharacterModule(char) or {} | |||
-- Busca a subskill "n" dentro das skills | |||
local desc_i18n = {} | |||
for _, key in ipairs(data.order or {}) do | |||
local sk = (data.skills or {})[key] | |||
if type(sk) == "table" and type(sk.subskills) == "table" then | |||
local sub = sk.subskills[n] | |||
if sub then | |||
local langs = {"pt","en","es","pl"} | |||
for _, code in ipairs(langs) do | |||
local d = sub.desc and sub.desc[code] | |||
if d and trim(d) ~= "" then | |||
desc_i18n[code] = colorize(d) | |||
end | |||
end | |||
break | |||
end | |||
end | |||
end | |||
local function nz(v) | |||
v = v or "" | |||
return (trim(v) ~= "" and v or nil) | |||
end | |||
local obj = { | |||
name = n, | |||
icon = (trim(a.icon or "") ~= "" and a.icon or "Nada.png"), | |||
level = (trim(a.level or "") ~= "" and a.level or "NIVEL"), | |||
video = a.video or "", | |||
energy = nz(a.energy), | |||
powerpve = nz(a.powerpve), | |||
powerpvp = nz(a.powerpvp), | |||
cooldown = nz(a.cooldown), | |||
} | |||
if next(desc_i18n) ~= nil then | |||
obj.desc_i18n = desc_i18n | |||
obj.descPt = desc_i18n.pt | |||
obj.descEn = desc_i18n.en | |||
obj.descEs = desc_i18n.es | |||
obj.descPl = desc_i18n.pl | |||
end | |||
return mw.text.jsonEncode(obj) | |||
end | |||
-- ===== atalhos “gambiarra” para wikitext simples ===== | |||
-- permitem usar {{#invoke:Info|expandTier|tierKalifa}} e {{#invoke:Info|expandTags|tagsKalifa}} | |||
function p.expandTier(frame) | function p.expandTier(frame) | ||
local token = trim(frame.args[1] or "") | local token = trim(frame.args[1] or "") | ||
| Linha 230: | Linha 357: | ||
end | end | ||
local data = requireCharacterModule(char) or {} | local data = requireCharacterModule(char) or {} | ||
return expandTierFrom(data, (frame.args.lang or "pt")) | |||
end | end | ||
| Linha 240: | Linha 366: | ||
return "" | return "" | ||
end | end | ||
if token:lower():sub(1, | if token:lower():sub(1, 4) ~= "tags" then | ||
return token | return token | ||
end | end | ||
local char = nome ~= "" and nome or token:match("^ | local char = nome ~= "" and nome or token:match("^tags(.+)$") or "" | ||
if char == "" then | if char == "" then | ||
local title = mw.title.getCurrentTitle() | local title = mw.title.getCurrentTitle() | ||
Edição das 03h15min de 14 de setembro de 2025
A documentação para este módulo pode ser criada em Módulo:Info/doc
-- Módulo:Info — resolve metadados e skills (robusto/corrigido + gambiarra expandTier/expandTags)
local p = {}
-- ===== util =====
local function trim(s)
return (tostring(s or ""):gsub("^%s+", ""):gsub("%s+$", ""))
end
local function safeArgs(node)
return (node and node.args) or {}
end
local function requireCharacterModule(charName)
charName = trim(charName)
if charName == "" then
return nil
end
local ok, data = pcall(function()
return require("Módulo:" .. charName)
end)
if ok and type(data) == "table" then
return data
end
-- fallback: nomes com espaço vs underscore
charName = charName:gsub(" ", "_")
ok, data = pcall(function()
return require("Módulo:" .. charName)
end)
if ok and type(data) == "table" then
return data
end
return nil
end
-- Coleta objetos JSON em sequência a partir de um texto concatenado (ex.: |subs= com vários {{Subskill}})
local function collectJsonObjects(s)
s = tostring(s or "")
local out = {}
for chunk in s:gmatch("%b{}") do
table.insert(out, chunk)
end
return out
end
-- resolve personagem a partir de frame/parent (usado por expand/tier/tags/skill)
local function resolveCharFromFrames(frame, a)
a = a or {}
-- tenta parent args.nome
if frame and frame.getParent then
local parent = frame:getParent()
if parent and parent.args then
if parent.args.nome and trim(parent.args.nome) ~= "" then
return trim(parent.args.nome)
end
-- alguns usos guardam em classX (tierX/tagsX)
for k, v in pairs(parent.args) do
if type(k) == "string" and k:match("^class") and trim(v) ~= "" then
return trim(v)
end
end
end
end
-- tenta o próprio frame (às vezes vem direto)
if a.nome and trim(a.nome) ~= "" then
return trim(a.nome)
end
if a.char and trim(a.char) ~= "" then
return trim(a.char)
end
-- título da página
local title = mw.title.getCurrentTitle()
return title and trim(title.text) or ""
end
-- paleta para marcadores
local COLOR = {
debuff = "#ff5252",
ms = "#5bc0de",
hp = "#70d86b",
atk = "#ffd166",
def = "#c0a9ff",
sec = "#ffa07a",
}
-- substitui marcadores {{atk:}}, {{def:}}, {{ms:}}, {{hp:}}, {{sec:}}, {{debuff:}} no texto
local function colorize(text)
text = tostring(text or "")
local patterns = {
{ "atk", COLOR.atk },
{ "def", COLOR.def },
{ "ms", COLOR.ms },
{ "hp", COLOR.hp },
{ "sec", COLOR.sec },
{ "debuff",COLOR.debuff},
}
for _, pair in ipairs(patterns) do
local key, color = pair[1], pair[2]
-- {{key:VALOR}} → <span class="tag key">VALOR</span>
text = text:gsub("{{%s*" .. key .. "%s*:%s*([^}]+)%s*}}", function(val)
return string.format('<span class="tag %s" style="--tag:%s">%s</span>', key, color, trim(val))
end)
end
return text
end
-- ===== Tier/Tags helpers =====
local function expandTierFrom(data, lang)
lang = (lang or "pt"):lower()
-- tenta i18n
if data.tier_i18n and data.tier_i18n[lang] then
return tostring(data.tier_i18n[lang])
end
return tostring(data.tier or "")
end
local function expandTagsFrom(data, lang)
lang = (lang or "pt"):lower()
if data.tags_i18n and data.tags_i18n[lang] and type(data.tags_i18n[lang]) == "table" then
return table.concat(data.tags_i18n[lang], " / ")
end
if type(data.tags) == "table" then
return table.concat(data.tags, " / ")
end
return tostring(data.tags or "")
end
-- ===== API =====
-- Tier: {{#invoke:Info|tier|pt|NomeDoPersonagem}} ou {{#invoke:Info|tier|tierNome}}
function p.tier(frame)
local token = trim(frame.args[1] or "")
local nome = trim(frame.args[2] or (frame:getParent() and frame:getParent().args.nome) or "")
local lang = trim(frame.args.lang or (frame:getParent() and frame:getParent().args.lang) or "pt"):lower()
if token == "" then
return ""
end
local char = ""
if token:lower():sub(1,4) == "tier" then
char = token:match("^tier(.+)$") or ""
else
char = nome
end
if char == "" then
char = resolveCharFromFrames(frame, frame.args)
end
local data = requireCharacterModule(char) or {}
return expandTierFrom(data, lang)
end
-- Tags: {{#invoke:Info|tags|pt|NomeDoPersonagem}} ou {{#invoke:Info|tags|tagsNome}}
function p.tags(frame)
local token = trim(frame.args[1] or "")
local nome = trim(frame.args[2] or (frame:getParent() and frame:getParent().args.nome) or "")
local lang = trim(frame.args.lang or (frame:getParent() and frame:getParent().args.lang) or "pt"):lower()
if token == "" then
return ""
end
local char = ""
if token:lower():sub(1,4) == "tags" then
char = token:match("^tags(.+)$") or ""
else
char = nome
end
if char == "" then
char = resolveCharFromFrames(frame, frame.args)
end
local data = requireCharacterModule(char) or {}
return expandTagsFrom(data, lang)
end
-- Skill principal → serializa objeto consumido pelo Widget/Character
-- Uso: {{#invoke:Info|skill|M=1|icon=...|level=...|energy=...|powerpve=...|powerpvp=...|cooldown=...|video=...|subs=...}}
function p.skill(frame)
local a = safeArgs(frame)
local lang = trim((a.lang or (frame:getParent() and frame:getParent().args.lang) or "pt"):lower())
local char = trim(a.char or (frame:getParent() and frame:getParent().args.nome) or "")
if char == "" then
char = resolveCharFromFrames(frame, a)
end
local data = requireCharacterModule(char) or {}
local name, desc_i18n = nil, {}
if a.M and trim(a.M) ~= "" then
local m = tonumber(a.M) or 0
local order = data.order or {}
local key = order[m] or ""
local sk = (data.skills or {})[key] or {}
name = trim(sk.name or key or "")
-- monta tabela de descrições por idioma (já colorizadas)
if type(sk.desc) == "table" then
local langs = {"pt", "en", "es", "pl"}
for _, code in ipairs(langs) do
local d = sk.desc[code]
if d and trim(d) ~= "" then
desc_i18n[code] = colorize(d)
end
end
elseif sk.desc and trim(sk.desc) ~= "" then
desc_i18n["pt"] = colorize(sk.desc) -- fallback: único texto vira pt
end
end
local function nz(v)
v = v or ""
return (trim(v) ~= "" and v or nil)
end
local chosen = desc_i18n[lang] or desc_i18n["pt"] or ""
local obj = {
icon = (trim(a.icon or "") ~= "" and a.icon or "Nada.png"),
level = (trim(a.level or "") ~= "" and a.level or "NIVEL"),
energy = nz(a.energy),
powerpve = nz(a.powerpve),
powerpvp = nz(a.powerpvp),
cooldown = nz(a.cooldown),
video = a.video or "",
name = name, -- pode estar vazio caso use outside (não quebra)
}
-- inclui a descrição escolhida (se preferir, o Widget usa desc_i18n)
if chosen ~= "" then
obj.desc = chosen
end
-- inclui as variantes para o Character expor como data-desc-*
if next(desc_i18n) ~= nil then
obj.desc_i18n = desc_i18n
obj.descPt = desc_i18n.pt
obj.descEn = desc_i18n.en
obj.descEs = desc_i18n.es
obj.descPl = desc_i18n.pl
end
-- Subskills: empacota os JSONs vindos via |subs= (cada {{Subskill}} vira um objeto)
do
local subsPacked = a.subs or ""
local subsArr = {}
for _, chunk in ipairs(collectJsonObjects(subsPacked)) do
local ok, sub = pcall(mw.text.jsonDecode, chunk)
if ok and type(sub) == "table" then
table.insert(subsArr, sub)
end
end
if #subsArr > 0 then
obj.subs = subsArr
end
-- Se o módulo do personagem definiu suborder para essa skill (pelo índice M), inclui para a UI respeitar a ordem
if a.M and tonumber(a.M) then
local m = tonumber(a.M)
local order = (data and data.order) or {}
local key = order[m] or ""
local sk = (data and data.skills and data.skills[key]) or {}
if type(sk) == "table" and type(sk.suborder) == "table" then
obj.suborder = sk.suborder
end
end
end
return mw.text.jsonEncode(obj)
end
-- Emote (sem M)
function p.emote(frame)
local a = safeArgs(frame)
local obj = {
name = "Emote",
icon = (trim(a.icon or "") ~= "" and a.icon or "Nada.png"),
level = (trim(a.level or "") ~= "" and a.level or "NIVEL"),
video = a.video or "",
}
return mw.text.jsonEncode(obj)
end
-- Subskill → serializa dados da subskill (nome exato conforme suborder do módulo do personagem)
-- Uso: dentro de |subs= da Skill:
-- {{Subskill|n=Trap Door|icon=...|level=...|video=...|energy=...|powerpve=...|powerpvp=...|cooldown=...}}
function p.subskill(frame)
local a = safeArgs(frame)
local lang = trim((a.lang or (frame:getParent() and frame:getParent().args.lang) or "pt"):lower())
local n = trim(a.n or "")
if n == "" then
return mw.text.jsonEncode({})
end
-- Resolve personagem pelo contexto
local char = trim(a.char or (frame:getParent() and frame:getParent().args.nome) or "")
if char == "" then
char = resolveCharFromFrames(frame, a)
end
local data = requireCharacterModule(char) or {}
-- Busca a subskill "n" dentro das skills
local desc_i18n = {}
for _, key in ipairs(data.order or {}) do
local sk = (data.skills or {})[key]
if type(sk) == "table" and type(sk.subskills) == "table" then
local sub = sk.subskills[n]
if sub then
local langs = {"pt","en","es","pl"}
for _, code in ipairs(langs) do
local d = sub.desc and sub.desc[code]
if d and trim(d) ~= "" then
desc_i18n[code] = colorize(d)
end
end
break
end
end
end
local function nz(v)
v = v or ""
return (trim(v) ~= "" and v or nil)
end
local obj = {
name = n,
icon = (trim(a.icon or "") ~= "" and a.icon or "Nada.png"),
level = (trim(a.level or "") ~= "" and a.level or "NIVEL"),
video = a.video or "",
energy = nz(a.energy),
powerpve = nz(a.powerpve),
powerpvp = nz(a.powerpvp),
cooldown = nz(a.cooldown),
}
if next(desc_i18n) ~= nil then
obj.desc_i18n = desc_i18n
obj.descPt = desc_i18n.pt
obj.descEn = desc_i18n.en
obj.descEs = desc_i18n.es
obj.descPl = desc_i18n.pl
end
return mw.text.jsonEncode(obj)
end
-- ===== atalhos “gambiarra” para wikitext simples =====
-- permitem usar {{#invoke:Info|expandTier|tierKalifa}} e {{#invoke:Info|expandTags|tagsKalifa}}
function p.expandTier(frame)
local token = trim(frame.args[1] or "")
local nome = trim(frame.args[2] or (frame:getParent() and frame:getParent().args.nome) or "")
if token == "" then
return ""
end
if token:lower():sub(1, 4) ~= "tier" then
return token
end
local char = nome ~= "" and nome or token:match("^tier(.+)$") or ""
if char == "" then
local title = mw.title.getCurrentTitle()
char = title and trim(title.text) or ""
end
local data = requireCharacterModule(char) or {}
return expandTierFrom(data, (frame.args.lang or "pt"))
end
function p.expandTags(frame)
local token = trim(frame.args[1] or "")
local nome = trim(frame.args[2] or (frame:getParent() and frame:getParent().args.nome) or "")
if token == "" then
return ""
end
if token:lower():sub(1, 4) ~= "tags" then
return token
end
local char = nome ~= "" and nome or token:match("^tags(.+)$") or ""
if char == "" then
local title = mw.title.getCurrentTitle()
char = title and trim(title.text) or ""
end
local data = requireCharacterModule(char) or {}
local arr = (data.tags_i18n and data.tags_i18n.pt) or data.tags
if type(arr) == "table" then
return table.concat(arr, " / ")
end
return trim(arr or "")
end
return p