Ir para o conteúdo

Módulo:Infobox

Permanently protected module
Origem: Wikipédia, a enciclopédia livre.

local p = {}
local lang = 'pt'

local item = nil -- o elemento Wikidata ligado
local localdata = {}-- guarda parâmetros passados à predefinição
local page = { -- guarda parâmetros da página mostrados na infocaixa
    name = mw.title.getCurrentTitle().prefixedText,
    namespace =     mw.title.getCurrentTitle().namespace
}
local maincolor, secondcolor, thirdcolor = '#E1E1E1', '#E1E1E1', '#000000'
-- o objeto principal a devolver
local infobox = mw.html.create('div')

-- objetos secundários a devolver
local maintenance = '' -- cadeia devolvida com o módulo : cats de monitoramento
local externaltext = '' -- para exemplo com coordenadas no título
-- modules importados
local linguistic = require "Módulo:Linguística"
local wd = require 'Módulo:Wikidata/Testes'
local valueexpl = wd.translate("activate-query")
local mapmod = require "Módulo:Mapa" -- ou Mapa de localização
local CategorizacaoABeAD = require('Módulo:Categorização AD e AB de outras wikis')
local i18n = {
    ['see doc'] = 'Documentação da predefinição',
    ['edit'] = 'editar',
    ['edit code'] = 'editar código-fonte',
    ['edit item'] = 'editar Wikidata',
    ['tracking cat'] = "!Páginas que utilizam dados no Wikidata",
    ['invalid block type'] = "Bloco de dados inválidos dentro do módulo infobox",
    ['default cat'] = "!Monitoramento das infobox",
}

local function addWikidataCat(prop)
    maintenance = maintenance .. wd.addTrackingCat(prop)
end

local function expandQuery(query)
    local value, number -- valor ao devolver, nome dos valores para conceder o rótulo
    if not query.entity then
    query.entity = localdata.item
    end
    if not query.conjtype then
    query.conjtype = 'comma'
    end
    local claims = wd.getClaims(query)
    if (not claims) then
    return nil
    end
    return wd.formatAndCat(query), #claims -- para fazer acordo de plural
end

local function getWikidataValue(params, wikidataparam)
    -- Recuperar o valor Wikidata para o valor, quer no parâmetro "wikidata" ou no parâmetro "property"
    if not localdata.item then
    return nil
    end

    if params.blockers then -- blockers are local parameters that disable the wikidata query
    local blockers = params.blockers
    if (type(blockers) == 'string') then
        blockers = {blockers}
    end
    for i, blocker in ipairs(blockers) do
        if localdata[blocker] then
        return nil
        end
    end
    end

    local v, valnum -- o valor a retornar e o número de valores (para concordância gramatical)
 
    if not wikidataparam then -- por padrão o valor wikidata está no parâmetro "wikidata" mas nas estruturas compostas como "title", existem vários parâmetros wikidata
    wikidataparam = 'wikidata'
    end

    if params[wikidataparam] then
    if type(params[wikidataparam]) == 'function' then
        v, valnum = params[wikidataparam](localdata.item)
    elseif type(params[wikidataparam]) == 'table' then
        v, valnum = expandQuery(params[wikidataparam])
    else
        v, valnum = params[wikidataparam]
    end
    end
    if not v then
    return nil
    end
    v = linguistic.ucfirst(v)
    return v, valnum
end

local function getValue(val, params)
    if type(val) == 'string' then
    return localdata[val]
    elseif type(val) == 'function' then
    return val(localdata, localdata.item, params)
    elseif type(val) == 'table' then
    for i, j in pairs(val) do -- se vários parâmetros possíveis (legado do código antigo), tomar o primeiro não-vazio
        if localdata[j] then
        return localdata[j]
        end
    end
    end
end

local function addMaintenanceCat(cat, sortkey)
    if page.namespace ~= 0 then
    return ''
    end
    if cat then
    maintenance = maintenance .. '[[Category:' .. cat .. '|' .. (sortkey or page.name) .. ']]'
    end
end

function p.separador(params)
    local style = params['estilo separador'] or {}
    style.height = style.height or '2px'
    style['background-color'] = style['background-color'] or maincolor
 
    return mw.html.create('hr'):css( style ) 
end

function p.buildtitle(params)
    local text = getValue(params.value, params) or params.textdefaultvalue or  getWikidataValue(params) or mw.title.getCurrentTitle().text
    local subtext = getValue(params.subtitle) or  getWikidataValue(params, 'wikidatasubtitle') or params.subtitledefaultvalue
    if subtext and (subtext ~= text) then
    text = text .. '<br /><small>' .. subtext .. '</small>'
    end
    local icon = params.icon or ''
    if icon ~= '' and not params.large then
    icon = 'icon ' .. icon
    end
    local class = 'topo padrao' .. icon
 
    -- overwrites with those provided in the module
    local style = {}
    style['background-color'] = maincolor
    style['color'] = thirdcolor
    if params.style then
    for i, j in pairs(params.style) do
        style[i] = j
    end
    end
    local title = mw.html.create('div')
    :addClass(class)
    :css(style)
    :tag('div')
        :wikitext(text)
    :allDone()
    return title
end
p.buildTitle = p.buildtitle

function p.buildnavbox(params)
 
    -- definição do estilo
    local class = "navbox " .. (params.class or '')
    local style = params.style or {}

    if params.separado then -- opções para adicionar uma linha de separação acima
    class = class .. ' bordered'
    style['border-top'] = '1px solid' .. maincolor
    end

    -- ajuste de parâmetros de dados
    params.previousval = params.previousval or params.previousparameter -- nome do parâmetro obsoleto
    params.nextval = params.nextval or params.nextparameter
 
    if params.previousproperty then
    params.previouswikidata = {property = params.previousproperty}
    end
    if params.nextproperty then
    params.nextwikidata = {property = params.nextproperty}
    end
 

    local previousval = getValue(params.previousval, params) or getWikidataValue(params, 'previouswikidata')
    local nextval = getValue(params.nextval, params) or getWikidataValue(params, 'nextwikidata')
 
    local navbox
    if params.inner then -- para quem está dentro de uma tabela
    navbox = mw.html.create('tr'):tag('th'):attr('colspan', 2)
    style['font-weight'] = style['font-weight'] or 'normal'
    else
    navbox = mw.html.create('div')
    end
 
    navbox
    :addClass(class)
    :css(style)
    :tag('div')
        :addClass('prev_bloc')
        :wikitext(previousval)
        :done()
    :tag('div')
        :addClass('next_bloc')
        :wikitext(nextval)
        :done()
    :allDone()
    return navbox
end
p.buildNavbox = p.buildnavbox

function p.buildimages(params)
    local images = {}
    local upright, link, caption, alt, size    -- size is deprecated
    if type(params.imageparameters) == 'string' then
    params.imageparameters = {params.imageparameters}
    end
    if not params.imageparameters then -- se não houver nenhum parâmetro de imagem, continue, talvez haja uma imagem padrão definida no módulo de infobox
    params.imageparameters = {}
    end
    for j, k in ipairs(params.imageparameters) do
    table.insert(images, localdata[k])
    end
    -- Images de Wikidata
    if #images == 0 and localdata.item then
    if params.property then
        params.wikidata = {entity = localdata.item, property = params.property}
    end
    if params.wikidata then
        local wdq = params.wikidata
        wdq.excludespecial = true
        if type(wdq) == 'table' then
        wdq.entity = wdq.entity or localdata.item
        wdq.numval = wdq.numval or params.numval or 1
        images = wd.getClaims(wdq)
        end
        if type(wdq) == 'function' then
        images = params.wikidata()
        if type(images) == 'string' then
            return images
        end --provavelmente é um erro no pedido => mostrar a mensagem
        end
        if (not images) then
        images = {}
        end
        if (#images > 0) and (params.wikidata.property) then
        addWikidataCat(params.wikidata.property)
        end

        if type(images[1]) == 'table' then
        for i, image in pairs(images) do     
            if image.mainsnak.snaktype ~= 'value' then
            return
            end
            if #images == 1 then -- se apenas uma imagem, usamos a legenda (se mais duas imagens, como formatar?)
            caption = wd.getFormattedQualifiers(images[i], {'P2096'}, {isinlang = 'fr'})
            end
            images[i] = image.mainsnak.datavalue.value
        end
        end
    end
    end

    -- Images por defeito
    if #images == 0 then
    if params.maintenancecat then
        addMaintenanceCat(params.maintenancecat, params.sortkey)
    end
    if params.defaultimages then
        images = params.defaultimages
        if type(images) == 'string' then
        images = {images}
        end
        upright = params.defaultimageupright
        caption = params.defaultimagecaption
        link = params.defaultimagelink
        alt = params.defaultimagealt
        if not alt and ( images[1] == 'Padrao.svg' or images[1] == 'Padrao 2.svg' ) then
        alt = 'uma ilustração licenciada gratuita seria bem-vinda'
        end
    end
    end
    if #images == 0 then
    return nil
    end
 
    upright = upright or getValue(params.uprightparameter) or params.defaultupright or "1.2"
    link = link or getValue(params.linkparameter) or params.defaultlink
    caption = caption or getValue(params.captionparameter) or params.defaultcaption
    alt = alt or getValue( params.altparameter) or params.defaultalt

    -- tamanho com "size" (obsoleto)
    size = size or getValue(params.sizeparameter) or params.defaultsize -- deprecated
    if size then
    local numsize = size:gsub('px', '')
    numsize = mw.ustring.gsub(numsize, 'x.*', '')
    numsize = tonumber(numsize)
    if type(numsize) ~= 'number' or numsize > 280 then
        addMaintenanceCat("tamanho da imagem inválido")
    end
    if tonumber(size) then
        size = size .. 'px'
    end
    size = '|' .. size
    else
    size = ''
    end
 
    if tonumber(upright) then
    upright = tostring(tonumber(upright) ) / #images
    end
    if tonumber(size) then
    size = tostring(tonumber(size) ) / #images
    end

    local style = params.style or {padding ='2px 0',}

    -- Imagem da peça

    local imagesString = ''
    for i,image in pairs(images) do
    if image == '-' then
        return
    end
    imagesString = imagesString ..      '[[File:' .. image .. "|" .. size .. '|frameless'
    if alt then
        imagesString = imagesString .. '|alt=' .. alt
    end
    if link then
        imagesString = imagesString .. '|link=' .. link
    end
    if upright then
        imagesString = imagesString .. '|upright=' .. upright
    elseif #images > 1 then
        imagesString = imagesString .. '|upright=' .. ( 1 / #images )
    end
    imagesString = imagesString .. ']]'
    end

    local image = mw.html.create('div')
    :addClass("images")
    :css(style)
    :wikitext(imagesString)

    -- Parte da legenda
    local captionobj
    if caption then
    captionobj = mw.html.create('p')
        :wikitext(caption)
        :css(params.style or {})
        :addClass("caption")
        :done()
    end
 
    -- separador
    local separador
    if params.separador then
    separador = separador(params)
    end
    return mw.html.create('div')
    :node(image)
    :node(captionobj)
    :node(separador)
    :done()
end
p.buildImages = p.buildimages

function p.buildtext(params)
    local class = params.class or ''
    local style = {
    ['text-align'] = 'center',
    ['font-weight'] = 'bold'
    }
    if params.style then
    for i, j in pairs(params.style) do
        style[i] = j
    end
    end
    local text = getValue(params.value, params) or getWikidataValue(params) or params.defaultvalue
    if text == '-' then
    return
    end
    if not text then
    addMaintenanceCat(params.maintenancecat, params.sortkey)
    return nil
    end
    local formattedtext = mw.html.create('p')
    :addClass(class)
    :css(style)
    :wikitext(text)
    :done()
    return formattedtext
end
p.buildText = p.buildtext

function p.buildrow(params)
    local class = params.class or ''
    local style = params.style or {}
    local value, number =  getValue(params.value, params)
    if (value == valueexpl) then
    value = nil
    params.wikidata.expl = false
    end
    if (not value) then
    value, number =        getWikidataValue(params, 'wikidata')
    end
    if (not value) and (params.property) then
    value, number = expandQuery{ property = params.property, ucfirst = params.ucfirst }
    end
    if not value then
    value = params.defaultvalue
    end
    if value == '-' then
    return nil
    end
    if not number then
    number = 0 -- == indéfini
    end

    if not value then
    if params.maintenancecat then
        local maintenancecat = getValue(params.maintenancecat, params)
        addMaintenanceCat(maintenancecat, params.sortkey)
    end
    return nil
    end

    local label = params.label
    if number > 1 and (params.plurallabel) then
    label = params.plurallabel
    elseif number == 1 and (params.singularlabel) then
    label = params.singularlabel
    end
    if type(label) == 'function' then
        label = label(localdata, localdata.item)
    end

    -- format
    local formattedvalue = mw.html.create('div')
    :wikitext('\n' .. value) -- 'Não é necessário quando o valor é uma lista que começa com '*' ou '#'
     
    if (params.hidden == true)then
    formattedvalue
        :attr({class="NavContent", style="display: none; text-align: left;"})
    formattedvalue = mw.html.create('div')
        :attr({class="NavFrame", title="[Mostrar]/[Esconder]", style="border: none; padding: 0;"})
        :node(formattedvalue)
    end
    formattedvalue =  mw.html.create('td')
        :node(formattedvalue)
        :allDone()
 
    local formattedlabel
    if label then
    formattedlabel = mw.html.create('th')
        :attr('scope', 'row')
        :wikitext(label)
        :done()
    end
    local row = mw.html.create('tr')
    :addClass(class)
    :css(style)
    :node(formattedlabel)
    :node(formattedvalue)
    :done()
 
    return row
end
p.buildRow = p.buildrow

function p.buildsuccession(params)
if not params.value then
    return nil
    end
     
    --local style = params.style or {}
    --style['text-align'] = style['text-align'] or 'center'
    --style['color'] = style['color'] or '#000000'
    --style['background-color'] = style['background-color'] or '#F9F9F9'
 
    local rowI = mw.html.create('tr')
 
    local colspan = '2'
    cellI = mw.html.create('td')
        :attr({colspan = colspan})
        :attr({align = 'center'})
 
    local styleT = {}
    styleT['background-color'] = 'transparent'
    styleT['width'] = '100%'
    tabC = mw.html.create('table')
        :attr({cellspacing = '0'})
        :addClass('navigation-not-searchable')
        :css(styleT)
 
    local row = mw.html.create('tr')

    local color = params.color

    local style = {}
    local arrowLeft
    local arrowRight
 
    if color == 'default' then
    style['background-color'] = '#E6E6E6'
    arrowLeft = '[[Ficheiro:Fleche-defaut-gauche.png|13px|alt=Precedente|link=]]'
    arrowRight = '[[Ficheiro:Fleche-defaut-droite.png|13px|alt=Precedente|link=]]'
    else
    style['background-color'] = color
    arrowLeft = '[[Ficheiro:Fleche-defaut-gauche-gris-32.png|13px|alt=Próximo|link=]]'
    arrowRight = '[[Ficheiro:Fleche-defaut-droite-gris-32.png|13px|alt=Próximo|link=]]'
    end
 
    local styleTrans = {}
    styleTrans['background-color'] = '#F9F9F9'
 
    local values = params.value
    local before = values['before']
    local center = values['center']
    local after = values['after']
 
    local widthCell = '44%'
    if center then
    widthCenter = '28%'
    widthCell = '29%'
    end
 
    local formattedbefore
    if before then
    formattedbefore = mw.html.create('td')
        :attr({valign = 'middle'})
        :attr({align = 'left'})
        :attr({width = '5%'})
        :css(style)
        :wikitext(arrowLeft)
        :done()
    row:node(formattedbefore)
    formattedbefore = mw.html.create('td')
        :attr({width = '1%'})
        :css(style)
        :wikitext('')
        :done()
    row:node(formattedbefore)
    formattedbefore = mw.html.create('td')
        :attr({align = 'left'})
        :attr({valign = 'middle'})
        :attr({width = widthCell})
        :css(style)
        :wikitext(before)
        :done()
    row:node(formattedbefore)
    else
    formattedbefore = mw.html.create('td')
        :attr({valign = 'middle'})
        :attr({align = 'left'})
        :attr({width = '5%'})
        :css(styleTrans)
        :wikitext('')
        :done()
    row:node(formattedbefore)
    formattedbefore = mw.html.create('td')
        :attr({width = '1%'})
        :css(styleTrans)
        :wikitext('')
        :done()
    row:node(formattedbefore)
    formattedbefore = mw.html.create('td')
        :attr({align = 'left'})
        :attr({valign = 'middle'})
        :attr({width = widthCell})
        :css(styleTrans)
        :wikitext('')
        :done()
    row:node(formattedbefore)
    end
 
    local formattedcenter
    formattedcenter = mw.html.create('td')
    :attr({width = '1%'})
    :css(styleTrans)
    :wikitext('')
    :done()
    row:node(formattedcenter)
 
    if center then
    formattedcenter = mw.html.create('td')
        :attr({align = 'center'})
        :attr({valign = 'middle'})
        :attr({width = widthCenter})
        :css(style)
        :wikitext(center)
        :done()
    row:node(formattedcenter)
    formattedcenter = mw.html.create('td')
        :attr({width = '1%'})
        :css(styleTrans)
        :wikitext('')
        :done()
    row:node(formattedcenter)
    end
 
    local formattedafter
    if after then
    formattedafter = mw.html.create('td')
        :attr({align = 'right'})
        :attr({valign = 'middle'})
        :attr({width = widthCell})
        :css(style)
        :wikitext(after)
        :done()
    row:node(formattedafter)
    formattedbefore = mw.html.create('td')
        :attr({width = '1%'})
        :css(style)
        :wikitext('')
        :done()
    row:node(formattedbefore)
    formattedafter = mw.html.create('td')
        :attr({align = 'right'})
        :attr({valign = 'middle'})
        :attr({width = '5%'})
        :css(style)
        :wikitext(arrowRight)
        :done()
    row:node(formattedafter)
    else
    formattedafter = mw.html.create('td')
        :attr({align = 'right'})
        :attr({valign = 'middle'})
        :attr({width = widthCell})
        :css(styleTrans)
        :wikitext('')
        :done()
    row:node(formattedafter)
    formattedbefore = mw.html.create('td')
        :attr({width = '1%'})
        :css(styleTrans)
        :wikitext('')
        :done()
    row:node(formattedbefore)
    formattedafter = mw.html.create('td')
        :attr({align = 'right'})
        :attr({valign = 'middle'})
        :attr({width = '5%'})
        :css(styleTrans)
        :wikitext('')
        :done()
    row:node(formattedafter)
    end
 
    row:done()
    tabC:node(row)
    tabC:done()
    cellI:node(tabC)
    cellI:done()
    rowI:node(cellI)
    rowI:allDone()
 
    return rowI
end
p.buildSuccession = p.buildsuccession

function p.buildrow1col(params)
 
    if not params.value then
    return nil
    end
     
    --local style = params.style or {}
    --style['text-align'] = style['text-align'] or 'center'
    --style['color'] = style['color'] or '#000000'
    --style['background-color'] = style['background-color'] or '#F9F9F9'
    local class = params.class
    local rowcolor
    if params.color == 'secondcolor' then
    rowcolor = secondcolor
    else
    rowcolor = params.color
    end
 
    local style = {}
    style['padding'] = '4px'
    style['text-align'] = 'center'
    style['background-color'] = rowcolor or '#F9F9F9'
    style['color'] = '#000000'
 
    local text = params.value

    local colspan ='2'

    local formattedlabel
    formattedlabel = mw.html.create('th')
    :attr({colspan = colspan})
    :css(style)
    :wikitext(text)
    :done()

    local row = mw.html.create('tr')
    :addClass(class)
    :css(style)
    :node(formattedlabel)
    :done()
 
    return row
end
p.buildRow1Col = p.buildrow1col

function p.buildtable(params)
    local tab = mw.html.create('table'):css(params.style or {})

    local rows = params.rows
 
    -- expand parameters so that we have a list of tables
    local i = 1

    while (i <= #rows) do
    local l = rows[i]
    if type(l) == 'function' then
        l = l(localdata, localdata.item)
    end
    if (type(l) == 'table') and (l.type == 'multi') then
        table.remove(rows, i)
        for j, row in ipairs(l.rows) do
        table.insert(rows, i + j - 1, row)
        end
    elseif type(l) == 'nil' then
        table.remove(rows, i)
    elseif type(l) ~= 'table' then
        return error('as linhas da infobox ("rows") devem ser tabelas, e ' .. type(l))
    else
        i = i + 1
    end
    end

    -- CREATE ROW
    local expandedrows = {}
    for k, row in ipairs(rows) do
    local v = p.buildblock(row)
    if v then
        table.insert(expandedrows, v)
    end
    end
    if (#expandedrows == 0) then
    return nil
    end
    rows = expandedrows

    -- ADD TITLE
    local title
    if params.title or params.singulartitle or params.pluraltitle then
    local text
    if #rows > 1 and params.pluraltitle then
        text = params.pluraltitle
    elseif #rows == 1 and params.singulartitle then
        text = params.singulartitle
    else
        text = params.title
    end

    local style = params.titlestyle or {}
    style['text-align'] = style['text-align'] or 'center'
    style['color'] = style['color'] or thirdcolor
    style['background-color'] = style['background-color'] or maincolor

    local colspan ='2'
    title = mw.html.create('caption')
        :attr({colspan = colspan})
        :css(style)
        :wikitext(text)
        :done()
    end
 
    if title then
    tab:node(title)
    end
 
    for i, j in pairs (rows) do
    tab:node(j)
    end
 
    if params.separador then
    local separador = p.separador(params)
    tab:node(separador)
    end
    tab:allDone()
    return tab
end
p.buildTable = p.buildtable

function p.buildinvalidblock(args)
    addMaintenanceCat(defaultcat)
    local text = ''
    if type(args) ~= 'table' then
    text = "Blocos de infobox devem ser tabelas"
    else
    text = i18n["invalid block type"] .. ' : ' .. (args.type or '??')
    end
    return text
end
p.buildInvalidBlock = p.buildinvalidblock

function p.buildmap(params)

    -- configuração de exibição
    local maplist = getValue(params.maps)
    local pointtype = params.pointtype
    local maptype = params.maptype -- escolhe o tipo de mapa mais adequado (alívio, administrativo, etc.) 
    if type(maplist) == 'function' then
    maplist = maplist(localdata, localdata.item)
    end
    local width = tonumber(params.largura) or 280
    if width > 280 then
    addMaintenanceCat("!Erro de infobox - imagem muito grande")
    return 'imagem muito grande, a largura deve ser menor ou igual a 280px'
    end

    -- recuperação dos dados locais
    local pointtable = {}
    local globe = params.globe
    if params.latitude then
    local lat, long
    if type(params.latitude) == 'function' then
        lat, long = params.latitude(localdata, localdata.item), params.longitude(localdata, localdata.item)
    else
        lat, long = localdata[params.latitude], localdata[params.longitude]
    end
    if lat then
        table.insert(pointtable, {latitude = lat, longitude = long})
    end
    end

    -- recuperação dos dados wikidata
    local function processWDval(claim, displayformat)
    if not claim then
        return nil
    end
    local val = wd.formatSnak( claim.mainsnak )
    return {latitude = val.latitude, longitude = val.longitude, globe = val.globe, marker = displayformat.marker}
    end
 
    local function getWDvals(query)
    query.excludespecial = true
    query.numval = query.numval or 1
    query.entity = query.entity or localdata.item
    local claims = wd.getClaims(query)
    if (not claims) then
        return
    end
    for i, claim in ipairs(claims) do
        claim = processWDval(claim, query)
        table.insert(pointtable, claim)
    end
    end
 
    if (#pointtable == 0) and localdata.item and params.wikidata and (params.wikidata ~= '-') then
    for i, query in ipairs(params.wikidata) do
        if type(query) == 'function' then
        query = query()
        end
        if query then
        getWDvals(query)
        end
    end
    end
 
    if (not pointtable) or (#pointtable == 0) then
    return nil
    end
 
    local newparams = {maplist = maplist, pointtype = pointtype, maptype = maptype, width = width, item = localdata.item, pointtable = pointtable, globe = globe, marker=params.marker, default_zoom=params.default_zoom, ids = params.ids, markercolor = params.markercolor, shapecolor = params.shapecolor }
    if params.params and type(params.params) == 'table' then -- parâmetro adicionais
    for i, j in pairs(params.params) do
        newparams[i] = j
    end
    end
    return mapmod.multimap(newparams)
end
p.buildMap = p.buildmap

function p.buildexternaltext(params)
    local value = getValue(params.value)
    if value and (type(value) == 'string') then
    externaltext = externaltext .. value
    end
end
p.buildExternalText = p.buildexternaltext

function p.buildfooter(params)
    if not params then
    params = {}
    end
 
    local class = 'navbar noprint bordered ' .. (params.class or '')
    local style = params.style or {}
    style['border-top'] = style['border-top'] or '1px solid ' .. maincolor
 
    local backlinkstr = '[' .. tostring( mw.uri.fullUrl( page.name, 'veaction=edit&section=0' ) ) .. ' ' .. i18n['edit'] .. ']'
    .. ' - [' .. tostring( mw.uri.fullUrl( page.name, 'action=edit&section=0' ) ) .. ' ' .. i18n['edit code'] .. ']'

    local itemlinkstr
    if localdata.item then
    itemlinkstr = '[[d:' .. localdata.item.id .. '|' .. i18n['edit item'] .. ']]'
    end
    local editstr = backlinkstr
    if itemlinkstr then
    editstr = editstr .. ' - ' .. itemlinkstr
    end
    local editlinkspan =  mw.html.create('span')
    :css({['text-align'] = "left"})
    :addClass('plainlinks')
    :wikitext(editstr)
    :done()
    local doclinkstr = '[[Imagem:Info Simple.svg|12px|link=' .. localdata.templatename .. '|' .. i18n['see doc'] .. ']]'
    -- Se esse link nem sempre funcionar, adicione uma variável para o nome da infobox recuperada pelo quadro
    local doclinkspan = mw.html.create('span')
    :css({['text-align'] = "right"})
    :wikitext(doclinkstr)
    :done()
 
    local footer = mw.html.create('p')
    :addClass(class)
    :css(style)
    :node(editlinkspan)
    :node(doclinkspan)
    return footer
end
p.buildFooter = p.buildfooter

function p.buildblock(block)
    if type(block) == 'function' then
    block = block( localdata )
    end

    local blocktypes = { -- list of functions for block buildings
    ['invalid'] = p.buildinvalidblock,
    ['external text'] = p.buildexternaltext,
    ['footer'] = p.buildfooter,
    ['images'] = p.buildimages,
    ['map']= p.buildmap,
    ['mixed'] = p.buildrow,
    ['navbox'] = p.buildnavbox,
    ['table'] = p.buildtable,
    ['row'] = p.buildrow,
    ['row1col'] = p.buildrow1col,
    ['succession'] = p.buildnavbox,
    ['text'] = p.buildtext,
    ['title'] = p.buildtitle,
    }
    if type(block) ~= 'table' or (not block.type) or (not blocktypes[block.type]) then
    return blocktypes['invalid'](block)
    end
    return blocktypes[block.type](block)
end
p.buildBlock = p.buildblock

function p.build()
 
    localdata = require( 'Módulo:Infobox/Localdata' )
    item = localdata.item

    -- assign rank to the infobox, "secondary" means special formatting like no displaytitle for coordinates
    local infoboxrank = 'main' -- main infobox of the page, with coordinates displayed in title etc.
    if page.namespace ~= 0 then
    infoboxrank = 'secondary'
    end
    -- if infobox is linked to another item: rank = secondary
    if localdata.item then
    local itemlink = mw.wikibase.sitelink(localdata.item.id)
    local pagetitle = mw.title.getCurrentTitle().text
    if (itemlink or '') ~= pagetitle then
        infoboxrank = 'secondary'
    end
    end
    localdata.infoboxrank = infoboxrank

    -- load infobox module page
    local moduledata = require('Módulo:Infobox/' .. localdata.modulename)
    moduledata.name = localdata.modulename
    -- defines main color
    maincolor = localdata['cor infobox'] or localdata['caixa de cor'] or moduledata.maincolor or maincolor
    secondcolor =  moduledata.secondcolor or secondcolor
    thirdcolor =  moduledata.thirdcolor or thirdcolor
    if maincolor:match( '^%x%x%x%x%x%x$' ) or maincolor:match( '^%x%x%x$' ) then
    maincolor = '#' .. maincolor
    end
 
    -- class
    local class = 'infobox_v2'
    if moduledata.class then
    class = class .. ' ' .. moduledata.class
    end
 
    -- style
    local style = moduledata.style or {}
    if not style['max-width'] then
    style['max-width'] = '300px'
    end
 
    -- build infobox
    infobox    :addClass(class)
        :css(style)
    for i, j in pairs( moduledata.parts ) do
    infobox:node( p.buildblock(j) )
    end
    infobox    :node(p.buildfooter(moduledata.footer))
        :done()

    if CategorizacaoABeAD.hasAnyBadge() == '1' then
        maintenance = maintenance .. (CategorizacaoABeAD.badgesCategories())
    end

    return tostring(infobox) .. externaltext, maintenance
end

return p