Jump to content

Module:ⵜⴰⴼⵍⵓⵖⵎⵉⵙⵜ ⵓⴳⴳⵉⴷ

ⵙⴳ ⵡⵉⴽⵉⴱⵉⴷⵢⴰ
local p = {}

-- Helper function to trim whitespace from a string
local function trimWhitespace(s)
    if type(s) ~= 'string' then return '' end
    return s:match('^%s*(.-)%s*$') or ''
end

-- Retrieve arguments from the frame and its parent
local function getArgs(frame)
    local args = {}
    local parent = frame:getParent()

    if parent and parent.args then
        for k, v in pairs(parent.args) do
            args[k] = trimWhitespace(v)
        end
    end

    for k, v in pairs(frame.args) do
        args[k] = trimWhitespace(v)
    end

    return args
end

-- Format date according to local conventions
local function formatDate(dateString)
    if not dateString or type(dateString) ~= 'string' then return dateString end

    -- Parse Wikidata date (format: "+YYYY-MM-DDT00:00:00Z")
    local year, month, day = dateString:match('^%+(%d%d%d%d)%-(%d%d)%-(%d%d)')
    if not year then return dateString end

    -- Use mw.language to format date according to local conventions
    local lang = mw.getContentLanguage()
    local timestamp

    if day and day ~= "00" and month and month ~= "00" then
        -- Full date available
        timestamp = year .. '-' .. month .. '-' .. day .. 'T00:00:00Z'
    elseif month and month ~= "00" then
        -- Month and year available
        timestamp = year .. '-' .. month .. '-01T00:00:00Z'
    else
        -- Only year available
        timestamp = year .. '-01-01T00:00:00Z'
    end

    -- Format based on available precision
    if day and day ~= "00" and month and month ~= "00" then
        return lang:formatDate('j F Y', timestamp)
    elseif month and month ~= "00" then
        return lang:formatDate('F Y', timestamp)
    else
        return year
    end
end

-- Get the entity object for the current page or specified entityId
local function getEntity(entityId)
    if not mw.wikibase then
        return nil
    end
    
    if not entityId then
        entityId = mw.wikibase.getEntityIdForCurrentPage()
    end
    
    if not entityId then
        return nil
    end
    
    local success, entity = pcall(function()
        return mw.wikibase.getEntity(entityId)
    end)
    
    if success and entity then
        -- Add getBestStatements method to the entity table
        entity.getBestStatements = function(self, propertyId)
            if not self.claims or not self.claims[propertyId] then
                return {}
            end
            
            local statements = {}
            for _, claim in pairs(self.claims[propertyId]) do
                if claim.mainsnak.snaktype == 'value' then
                    table.insert(statements, claim)
                end
            end
            return statements
        end
        
        -- Add formatStatements method (simple version)
        entity.formatStatements = function(self, propertyId)
            local statements = self:getBestStatements(propertyId)
            if #statements > 0 then
                -- Simple formatter that just returns the value
                return {
                    value = self:getBestStatements(propertyId)[1].mainsnak.datavalue.value
                }
            end
            return nil
        end
        
        return entity
    end
    
    return nil
end

-- Make a request to Wikidata for specific properties of an entity, now with interlinking
local function makeRequest(entityId, property)
    local entity = getEntity(entityId)
    if not entity then
        return nil, false
    end

    local statements = entity:getBestStatements(property)
    if #statements > 0 then
        local valuesWithLinks = {} -- To store formatted values, potentially with links

        for _, statement in ipairs(statements) do
            local datavalue = statement.mainsnak.datavalue
            local valueToAdd = nil

            if datavalue.type == 'string' then
                valueToAdd = datavalue.value
            elseif datavalue.type == 'wikibase-entityid' then
                local targetEntityId = datavalue.value.id
                local label = mw.wikibase.getLabel(targetEntityId)
                local sitelink = mw.wikibase.getSitelink(targetEntityId)

                if sitelink then
                    -- Link to the local page if it exists
                    valueToAdd = string.format("[[%s|%s]]", sitelink, label or targetEntityId)
                else
                    -- Link to the Wikidata item if no local page
                    valueToAdd = string.format("[[:d:%s|%s]]", targetEntityId, label or targetEntityId)
                end
            elseif datavalue.type == 'quantity' then
                local amount = tonumber(datavalue.value.amount)
                local lang = mw.getContentLanguage()
                valueToAdd = amount and lang:formatNum(amount) or datavalue.value.amount
            elseif datavalue.type == 'time' then
                valueToAdd = formatDate(datavalue.value.time)
            end

            if valueToAdd then
                table.insert(valuesWithLinks, valueToAdd)
            end
        end
        if #valuesWithLinks > 0 then
            return table.concat(valuesWithLinks, ", "), true
        end
    end
    return nil, false
end


-- Get values from Wikidata for single or multiple properties
local function getWikidataValue(properties, entityId)
    local entity = getEntity(entityId)
    if not entity then
        return nil, false
    end

    -- Handle single property as string or multiple as table
    local propertiesTable = type(properties) == 'table' and properties or {properties}
    local values = {}

    for _, property in ipairs(propertiesTable) do
        local value, found = makeRequest(entityId, property)
        if found then
            table.insert(values, value)
        end
    end

    if #values > 0 then
        return table.concat(values, ", "), true  -- Join multiple values with comma
    end

    return nil, false
end

-- Helper function to check if a value exists and is not empty
local function exists(var)
    return var ~= nil and var ~= ''
end

-- Function to get either a manual parameter or Wikidata values
local function getValueOrWikidata(args, paramName, properties)
    local value = args[paramName]
    local fromWikidata = false

    if value then
        value = trimWhitespace(value)
    end

    if not exists(value) and properties then
        value, fromWikidata = getWikidataValue(properties, args.qid)
    end

    return value, fromWikidata
end

-- Main infobox function
function p.main(frame)
    local args = getArgs(frame)

    local infobox = mw.html.create('table')
    infobox:addClass('infobox')
    infobox:addClass('vcard')
    infobox:css({
        ['border'] = '1px solid #aaa',
        ['background-color'] = '#f9f9f9',
        ['color'] = 'black',
        ['margin-bottom'] = '0.5em',
        ['margin-left'] = '1em',
        ['padding'] = '0.2em',
        ['float'] = 'right',
        ['clear'] = 'right',
        ['font-size'] = '88%',
        ['width'] = '18em',
    })

    -- Header row with person icon
    local headerValue, headerFromWikidata = getValueOrWikidata(args, 'ⵉⵙⵎ', 'P1476')
    local header = infobox:tag('tr')
    local headerCell = header:tag('th')
        :attr('colspan', 2)
        :css({
            ['background-color'] = '#4682B4', -- Steel blue color (changed from #cbd6f6)
            ['color'] = 'white', -- White text color for main title
            ['padding'] = '0.4em',
            ['text-align'] = 'center',
            ['font-weight'] = 'bold',
            ['font-size'] = '120%',
            ['position'] = 'relative', -- Required for absolute positioning of the icon
        })

    -- Header container for the text. Padding prevents long text from overlapping the icon.
    local headerContainer = mw.html.create('div')
        :css({
            ['padding-right'] = '35px', -- Space for the icon
            ['padding-left'] = '35px',  -- Symmetrical space for balance
        })
        :wikitext(headerValue or mw.title.getCurrentTitle().text)
        
    headerCell:node(headerContainer)
    
    -- Icon positioned in the top right corner of the header
    local iconContainer = mw.html.create('div')
        :css({
            ['position'] = 'absolute',
            ['top'] = '5px',
            ['right'] = '5px',
        })
        :wikitext('[[File:Picto_infobox_manwoman.png|40px|alt=ⵜⴰⵢⴽⵓⵏⵜ]]')
        
    headerCell:node(iconContainer)
    
    -- Get entity for image section
    local entity = getEntity(args.qid)
    local entityId = args.qid or mw.wikibase.getEntityIdForCurrentPage() or ''
    
    -- Image (using infoboxperson image style)
    if entity then
        local images = entity:getBestStatements('P18')
        if #images >= 1 then
            local imageRow = infobox:tag('tr')
            local imageCell = imageRow:tag('td')
                :attr('colspan', 2)
                :wikitext('[[File:' .. images[1].mainsnak.datavalue.value .. '|350px|alt=ⵜⴰⵢⴽⵓⵏⵜ]]')
                :css({
                    ['text-align'] = 'center',
                    ['padding'] = '0.5em'
                })
            
            -- Caption from Wikidata (property P2096 - image caption)
            local captions = entity:getBestStatements('P2096')
            if #captions >= 1 then
                local captionRow = infobox:tag('tr')
                local captionCell = captionRow:tag('td')
                    :attr('colspan', 2)
                    :wikitext(captions[1].mainsnak.datavalue.value)
                    :css({
                        ['text-align'] = 'center',
                        ['padding'] = '0.2em',
                        ['font-style'] = 'italic',
                    })
                
                -- Add edit icon if from Wikidata
                if entityId then
                    captionCell:wikitext(captions[1].mainsnak.datavalue.value .. ' ' .. string.format(
                        "[[File:Edit-icon.svg|20px|link=https://www.wikidata.org/wiki/Special:EntityPage/%s#%s|ⵙⵏⴼⵍ ⴳ ⵡⵉⴽⵉⴷⴰⵜⴰ]]",
                        entityId, 'P2096'
                    ))
                end
            end
        end
    end
    
    -- Define sections with property groups
    local sections = {
        {
            title = 'ⵓⵎⵍⴰⵏ ⵓⴷⵎⴰⵡⴰⵏⵏ',
            properties = {
                { 'ⵓⵣⵡⵉⵔ ⵏ ⵡⴰⴷⴷⵓⵔ', 'ⵓⵣⵡⵉⵔ ⵏ ⵡⴰⴷⴷⵓⵔ', 'P1035' },
                { 'ⵉⵙⵎ ⴰⵙⴰⵍⴰⵏ', 'ⵉⵙⵎ ⴰⵙⴰⵍⴰⵏ', 'P1559' },
                { 'ⵓⴹⴼⵉⵕ ⵏ ⵡⴰⴷⴷⵓⵔ', 'ⵓⴹⴼⵉⵕ ⵏ ⵡⴰⴷⴷⵓⵔ', 'P1036' },
                { 'ⵉⵙⵎ ⵏ ⵜⵍⴰⵍⵉⵜ', 'ⵉⵙⵎ ⵏ ⵜⵍⴰⵍⵉⵜ', 'P1477' },
                { 'ⵜⴰⴽⵏⵉⵢⵜ', 'ⵜⴰⴽⵏⵉⵢⵜ', 'P1449' },
                { 'ⵎⴼⴼⵔ ⵉⵙⵎ', 'ⵎⴼⴼⵔ ⵉⵙⵎ', 'P742' },
                { 'ⵉⵙⵎ ⵓⴷⵎⴰⵡⴰⵏ', 'ⵉⵙⵎ ⵓⴷⵎⴰⵡⴰⵏ', 'P735' },
                { 'ⵉⵙⵎⴰⵡⵏ ⵢⴰⴹⵏⵉⵏ', 'ⵉⵙⵎⴰⵡⵏ ⵢⴰⴹⵏⵉⵏ', 'P1559' },
                { 'ⵜⴰⵙⵍⴼⵙⵜ', 'ⵜⴰⵙⵍⴼⵙⵜ', 'P511' },
                { 'ⵉⵜⵜⵓⵙⵎⵎⴰ ⵙ ⵢⵉⵙⵎ', 'ⵉⵜⵜⵓⵙⵙⵎⴰ ⵙ ⵢⵉⵙⵎ', 'P138' },
                { 'ⴰⴷⵖⴰⵔ ⵏ ⵜⵍⴰⵍⵉⵜ', 'ⴰⴷⵖⴰⵔ ⵏ ⵜⵍⴰⵍⵉⵜ', 'P19' },
                { 'ⴰⵙⴰⴽⵓⴷ ⵏ ⵜⵍⴰⵍⵉⵜ', 'ⴰⵙⴰⴽⵓⴷ ⵏ ⵜⵍⴰⵍⵉⵜ', 'P569' },
                { 'ⴰⴷⵖⴰⵔ ⵏ ⵜⵎⵜⵜⴰⵏⵜ', 'ⴰⴷⵖⴰⵔ ⵏ ⵜⵎⵜⵜⴰⵏⵜ', 'P20' },
                { 'ⴰⵙⴰⴽⵓⴷ ⵏ ⵜⵎⵜⵜⴰⵏⵜ', 'ⴰⵙⴰⴽⵓⴷ ⵏ ⵜⵎⵜⵜⴰⵏⵜ', 'P570' },
                { 'ⴰⵙⵔⴰⴳ ⵏ ⵜⵎⵜⵜⴰⵏⵜ', 'ⴰⵙⵔⴰⴳ ⵏ ⵜⵎⵜⵜⴰⵏⵜ', 'P509' },
                { 'ⴰⴷⵖⴰⵔ ⵏ ⵓⵎⴹⴰⵍ', 'ⴰⴷⵖⴰⵔ ⵏ ⵓⵎⴹⴰⵍ', 'P119' },
                { 'ⵉⵙⵎⵍⴰⵏ ⵏ ⵓⴷⵖⴰⵔ ⵏ ⵓⵎⴹⴰⵍ', 'ⵉⵙⵎⵍⴰⵏ ⵏ ⵓⴷⵖⴰⵔ ⵏ ⵓⵎⴹⴰⵍ', 'P625' },
            }
        },
        {
            title = 'ⴰⴷⴷⴰⴷ ⵏ ⵓⵏⵖⵓⴱⵓ',
            properties = {
                { 'ⴰⵙⴰⴽⵓⴷ ⵏ ⵓⵏⵖⵓⴱⵓ', 'ⴰⵙⴰⴽⵓⴷ ⵏ ⵓⵏⵖⵓⴱⵓ', 'P746' },
                { 'ⴰⴷⵖⴰⵔ ⵏ ⵓⵏⵖⵓⴱⵓ', 'ⴰⴷⵖⴰⵔ ⵏ ⵓⵏⵖⵓⴱⵓ', 'P745' },
                { 'ⴰⴷⴷⴰⴷ ⵏ ⵓⵏⵖⵓⴱⵓ', 'ⴰⴷⴷⴰⴷ ⵏ ⵓⵏⵖⵓⴱⵓ', nil },
                { 'ⵜⴰⵡⴰⴼⵉⵜ ⵏ ⵜⴼⴳⴳⴰ', 'ⵜⴰⵡⴰⴼⵉⵜ ⵏ ⵜⴼⴳⴳⴰ', nil },
            }
        },
        {
            title = 'ⵜⴰⵖⵍⴰⵏⵜ ⴷ ⵜⵣⴷⵓⵖⵜ',
            properties = {
                { 'ⵜⴰⵖⵍⴰⵏⵜ', 'ⵜⴰⵖⵍⴰⵏⵜ', 'P27' },
                { 'ⵜⴰⵎⵓⵔⵉ', 'ⵜⴰⵎⵓⵔⵉ', 'P27' },
                { 'ⵜⴰⵣⴷⵓⵖⵜ', 'ⵜⴰⵣⴷⵓⵖⵜ', 'P551' },
                { 'ⵉⵎⵇⵇⵓⵔ ⴳ', 'ⵉⵎⵇⵇⵓⵔ ⴳ', 'P1408' },
                { 'ⴰⵥⵓⵕ', 'ⴰⵥⵓⵕ', 'P172' },
            }
        },
        {
            title = 'ⴰⵙⴳⴷ',
            properties = {
                { 'ⴰⵙⴳⴷ', 'ⴰⵙⴳⴷ', 'P140' },
                { 'ⵜⴰⵎⴰⴳⵔⴰⵡⵜ ⵜⴰⵙⴳⴷⴰⵏⵜ', 'ⵜⴰⵎⴰⴳⵔⴰⵡⵜ ⵜⴰⵙⴳⴷⴰⵏⵜ', 'P140' },
            }
        },
        {
            title = 'ⵜⵓⴷⵔⵜ ⵜⴰⵣⵣⵓⵍⵜ',
            properties = {
                { 'ⵉⴳⵔ ⵏ ⵜⵡⵓⵔⵉ', 'ⵉⴳⵔ ⵏ ⵜⵡⵓⵔⵉ', 'P101' },
                { 'ⵜⴰⵣⵣⵓⵍⵜ', 'ⵜⴰⵣⵣⵓⵍⵜ', 'P106' },
                { 'ⴰⵎⵙⵖⴰⵏ ⴳ', 'ⴰⵎⵙⵖⴰⵏ ⴳ', 'P108' },
                { 'ⴰⴳⵏⵙⴰⵙ', 'ⴰⴳⵏⵙⴰⵙ', 'P1308' },
                { 'ⵉⵙⴳⴳⵯⴰⵙⵏ ⵏ ⵓⵏⵏⵓⵛⵛⴳ', 'ⵉⵙⴳⴳⵯⴰⵙⵏ ⵏ ⵓⵏⵏⵓⵛⵛⴳ', {'P2031', 'P2032'} },
                { 'ⵜⴰⵎⴰⴷⴷⴰⵙⵜ', 'ⵜⴰⵎⴰⴷⴷⴰⵙⵜ', 'P1344' },
                { 'ⴰⴽⴰⴱⴰⵕ ⴰⵙⵔⵜⴰⵏ', 'ⴰⴽⴰⴱⴰⵕ ⴰⵙⵔⵜⴰⵏ', 'P102' },
                { 'ⴰⵎⵓⵙⵙⵓ', 'ⴰⵎⵓⵙⵙⵓ', 'P135' },
                { 'ⵜⵉⵡⵓⵔⵉⵡⵉⵏ ⵉⵜⵜⵢⴰⵡⵙⵙⴰⵏⵏ', 'ⵜⵉⵡⵓⵔⵉⵡⵉⵏ ⵉⵜⵜⵢⴰⵡⵙⵙⴰⵏⵏ', 'P800' },
            }
        },
        {
            title = 'ⵜⴰⵡⵊⴰ',
            properties = {
                { 'ⴰⵔⴳⴰⵣ/ⵜⴰⵎⵟⵟⵓⴹⵜ', 'ⴰⵔⴳⴰⵣ/ⵜⴰⵎⵟⵟⵓⴹⵜ', 'P26' },
                { 'ⴱⴰⴱⴰⵙ', 'ⴱⴰⴱⴰⵙ', 'P22' },
                { 'ⵉⵎⵎⵉⵙ', 'ⵉⵎⵎⵉⵙ', 'P25' },
                { 'ⴳⵎⴰⵙ', 'ⴳⵎⴰⵙ', 'P7' },
                { 'ⵓⵍⵜⵎⴰⵙ', 'ⵓⵍⵜⵎⴰⵙ', 'P9' },
                { 'ⵜⴰⵔⵡⴰ', 'ⵜⴰⵔⵡⴰ', 'P40' },
                { 'ⵉⵎⴰⵔⴰⵡⵏ', 'ⵉⵎⴰⵔⴰⵡⵏ', {'P22', 'P25'} },
                { 'ⵉⵎⴰⵍⴰⴳⵏ', 'ⵉⵎⴰⵍⴰⴳⵏ', 'P1038' },
            }
        },
        {
            title = 'ⵓⵎⵍⴰⵏ ⵏ ⵜⴼⴳⴳⴰ',
            properties = {
                { 'ⵜⵉⵖⵣⵉ', 'ⵜⵉⵖⵣⵉ', 'P2048' },
                { 'ⴰⵙⵜⴰⵍ', 'ⴰⵙⵜⴰⵍ', 'P2067' },
                { 'ⴰⵙⵙⵎⵔⵙ ⵏ ⵓⴼⵓⵙ', 'ⴰⵙⵙⵎⵔⵙ ⵏ ⵓⴼⵓⵙ', 'P552' },
                { 'ⴰⴽⵍⵓ ⵏ ⵡⴰⵣⵣⴰⵔ', 'ⴰⴽⵍⵓ ⵏ ⵡⴰⵣⵣⴰⵔ', 'P1884' },
            }
        },
        {
            title = 'ⴰⵙⵍⵎⴷ',
            properties = {
                { 'ⴰⵙⵍⵎⴷ', 'ⴰⵙⵍⵎⴷ', 'P69' },
                { 'ⵜⵉⵏⵎⵍ ⵜⴰⵢⵎⵎⴰⵜ', 'ⵜⵉⵏⵎⵍ ⵜⴰⵢⵎⵎⴰⵜ', 'P69' },
                { 'ⴰⵙⵍⴽⵉⵏ ⴰⵙⴷⴰⵡⴰⵏ', 'ⴰⵙⵍⴽⵉⵏ ⴰⵙⴷⴰⵡⴰⵏ', 'P512' },
                { 'ⵉⵥⵍⵉ ⴰⴽⴰⴷⵉⵎⵉ', 'ⵉⵥⵍⵉ ⴰⴽⴰⴷⵉⵎⵉ', 'P812' },
                { 'ⵜⵓⵜⵍⴰⵜⵢ ⵜⴰⵢⵎⵎⴰⵜ', 'ⵜⵓⵜⵍⴰⵜⵢ ⵜⴰⵢⵎⵎⴰⵜ', 'P103' },
                { 'ⵜⵓⵜⵍⴰⵢⵉⵏ ⵢⴰⴹⵏⵉⵏ', 'ⵜⵓⵜⵍⴰⵢⵉⵏ ⵢⴰⴹⵏⵉⵏ', 'P1412' },
            }
        },
        {
            title = 'ⵓⵎⵍⴰⵏ ⵉⵏⴱⴽⴰⴹⵏ',
            properties = {
                { 'ⴰⴷⵖⴰⵔ ⵏ ⵡⴰⵎⵎⴰⵥ', 'ⴰⴷⵖⴰⵔ ⵏ ⵡⴰⵎⵎⴰⵥ', 'P2632' },
                { 'ⴰⵙⴰⴽⵓⴷ ⵏ ⵡⴰⵎⵎⴰⵥ', 'ⴰⵙⴰⴽⵓⴷ ⵏ ⵡⴰⵎⵎⴰⵥ', 'P3025' },
                { 'ⵜⵓⵔⴷⴰⵢⵜ ⵜⴰⵏⴱⴽⴰⴹⵜ', 'ⵜⵓⵔⴷⴰⵢⵜ ⵜⴰⵏⴱⴽⴰⴹⵜ', 'P1595' },
                { 'ⵜⴰⵎⴰⵔⵔⵓⵜ ⵜⴰⵏⴱⴽⴰⴹⵜ', 'ⵜⴰⵎⴰⵔⵔⵓⵜ ⵜⴰⵏⴱⴽⴰⴹⵜ', 'P2102' },
            }
        },
        {
            title = 'ⵜⵉⵔⵙⵓⵜⵉⵏ',
            properties = {
                { 'ⵜⴰⵔⵙⵓⵜ', 'ⵜⴰⵔⵙⵓⵜ', 'P39' },
                { 'ⵜⵓⴷⴷⴰⵎⴰ ⵏ ⵜⵔⵙⵓⵜ', 'ⵜⵓⴷⴷⴰⵎⴰ ⵏ ⵜⵔⵙⵓⵜ', 'P580' },
                { 'ⵜⵉⴳⵉⵔⴰ ⵏ ⵜⵔⵙⵓⵜ', 'ⵜⵉⴳⵉⵔⴰ ⵏ ⵜⵔⵙⵓⵜ', 'P582' },
                { 'ⵉⵣⵡⴰⵔ ⵜ', 'ⵉⵣⵡⴰⵔ ⵜ', 'P1365' },
                { 'ⵉⴹⴼⴰⵕ ⵜ', 'ⵉⴹⴼⴰⵕ ⵜ', 'P1366' },
            }
        },
        {
            title = 'ⵉⵙⵉⵜⵏ ⵉⵎⴰⴷⴷⵓⴷⵏ',
            properties = {
                { 'ⴰⵙⵉⵜ ⴰⵎⴰⴷⴷⵓⴷ', 'ⴰⵙⵉⵜ ⴰⵎⴰⴷⴷⵓⴷ', 'P856' },
                { 'ⴰⴱⵍⵓⴳ ⴰⵎⴰⴷⴷⵓⴷ', 'ⴰⴱⵍⵓⴳ ⴰⵎⴰⴷⴷⵓⴷ', nil },
            }
        },
        {
            title = 'ⵜⵉⵙⵎⵖⵓⵔⵉⵏ',
            properties = {
                { 'ⵜⵉⵙⵎⵖⵓⵔⵉⵏ', 'ⵜⵉⵙⵎⵖⵓⵔⵉⵏ', 'P166' },
            }
        },
        {
            title = 'ⴰⵙⴳⵎⴹ',
            properties = {}
        }
    }

    -- Loop through sections and add them only if there are values for properties
    for _, section in ipairs(sections) do
        local hasContent = false
        local sectionContent = mw.html.create('')

        -- For regular property sections
        for _, prop in ipairs(section.properties) do
            local displayName, paramName, properties = unpack(prop)
            local value, fromWikidata = getValueOrWikidata(args, paramName, properties)

            if exists(value) then
                hasContent = true
                local row = sectionContent:tag('tr')
                row:tag('th')
                    :wikitext(displayName)
                    :css({
                        ['background-color'] = '#f1f1f1',
                        ['padding'] = '0.2em',
                        ['text-align'] = 'left',
                        ['font-weight'] = 'bold',
                    })

                local contentCell = row:tag('td')
                    :css({
                        ['padding'] = '0.2em',
                    })

                if fromWikidata then
                    -- Add Wikidata edit icons for each property
                    local editLinks = {}
                    for _, pId in ipairs(type(properties) == 'table' and properties or {properties}) do
                        if pId then
                            table.insert(editLinks, string.format(
                                "[[File:Edit-icon.svg|20px|link=https://www.wikidata.org/wiki/Special:EntityPage/%s#%s|ⵙⵏⴼⵍ ⴳ ⵡⵉⴽⵉⴷⴰⵜⴰ]]",
                                entityId, pId
                            ))
                        end
                    end
                    contentCell:wikitext(value .. ' ' .. table.concat(editLinks, ' '))
                else
                    contentCell:wikitext(value)
                end
            end
        end

        -- Special handling for signature section
        if section.title == 'ⴰⵙⴳⵎⴹ' then
            local hasSignature = false
            local signatureContent = mw.html.create('')
            
            if entity then
                local signatures = entity:getBestStatements('P109')  -- Get ALL signature statements
                
                if #signatures > 0 then
                    hasSignature = true
                    
                    -- Display all signatures
                    for _, signatureStatement in ipairs(signatures) do
                        if signatureStatement.mainsnak.snaktype == 'value' then
                            local signatureFile = signatureStatement.mainsnak.datavalue.value
                            
                            -- Add signature image
                            local signatureRow = signatureContent:tag('tr')
                            signatureRow:tag('td')
                                :attr('colspan', 2)
                                :wikitext(string.format('[[File:%s|%s|%s]]',
                                    signatureFile,
                                    args.signature_size or '200px',
                                    args.signature_alt or ''))
                                :css({
                                    ['text-align'] = 'center',
                                    ['padding'] = '0.5em'
                                })
                        end
                    end
                    
                    -- Add Wikidata edit icon for signatures
                    local editRow = signatureContent:tag('tr')
                    local editCell = editRow:tag('td')
                        :attr('colspan', 2)
                        :css({
                            ['text-align'] = 'center',
                            ['padding'] = '0.2em',
                            ['font-size'] = '85%',
                        })
                    editCell:wikitext(string.format(
                        "[[File:Edit-icon.svg|20px|link=https://www.wikidata.org/wiki/Special:EntityPage/%s#%s|ⵙⵏⴼⵍ ⴳ ⵡⵉⴽⵉⴷⴰⵜⴰ]]",
                        entityId, 'P109'
                    ))
                end
            end

            -- Also check for manual signature parameter
            local manualSignature = args['ⴰⵙⴳⵎⴹ'] or args['signature']
            if manualSignature and not hasSignature then
                hasSignature = true
                local signatureRow = signatureContent:tag('tr')
                signatureRow:tag('td')
                    :attr('colspan', 2)
                    :wikitext(string.format('[[File:%s|%s|%s]]',
                        manualSignature,
                        args.signature_size or '200px',
                        args.signature_alt or ''))
                    :css({
                        ['text-align'] = 'center',
                        ['padding'] = '0.5em'
                    })
            end

            -- Add caption if available
            local signatureCaption = args['ⴰⴳⵍⴰⵎ ⵏ ⵓⵙⴳⵎⴹ'] or args['signature_caption']
            if signatureCaption and hasSignature then
                local captionRow = signatureContent:tag('tr')
                local captionCell = captionRow:tag('td')
                    :attr('colspan', 2)
                    :css({
                        ['text-align'] = 'center',
                        ['padding'] = '0.2em',
                        ['font-style'] = 'italic',
                    })
                captionCell:wikitext(signatureCaption)
            end
            
            if hasSignature then
                hasContent = true
                -- Add the signature content to the section content
                sectionContent:node(signatureContent)
            end
        end

        -- Add section if there's content
        if hasContent then
            -- Add section title first
            infobox:tag('tr')
                :tag('th')
                :attr('colspan', 2)
                :wikitext(section.title)
                :css({
                    ['background-color'] = '#4682B4', -- Steel blue color
                    ['color'] = 'white', -- White text color for section titles
                    ['padding'] = '0.4em',
                    ['text-align'] = 'center',
                    ['font-weight'] = 'bold',
                })
            -- Then add the section content (which includes signatures for the signature section)
            infobox:node(sectionContent)
        end
    end

    -- Add footnotes if provided
    if exists(args.footnotes) then
        infobox:tag('tr')
            :tag('td')
            :attr('colspan', 2)
            :wikitext(args.footnotes)
            :css({
                ['padding'] = '0.2em',
                ['font-size'] = '85%',
            })
    end

    -- Add dashed line separator before the edit footer
    local separatorRow = infobox:tag('tr')
    local separatorCell = separatorRow:tag('td')
        :attr('colspan', 2)
        :css({
            ['padding'] = '0',
            ['border-top'] = '2px dashed #4682B4', -- Steel blue color
        })
    separatorCell:tag('div')
        :css({
            ['height'] = '1px',
            ['background-color'] = 'transparent',
        })

    -- Add edit footer
    local currentTitle = mw.title.getCurrentTitle()
    local editSourceUrl = currentTitle:fullUrl({action='edit', section='0'})
    local editVisualUrl = currentTitle:fullUrl({veaction='edit'})
    local templateDocUrl = mw.title.new('ⴰⵍⴱⵓⴹ:ⵜⴰⴼⵍⵓⵖⵎⵉⵙⵜ ⵓⴳⴳⵉⴷ'):fullUrl()

    local footerRow = infobox:tag('tr')
    local footerCell = footerRow:tag('td')
        :attr('colspan', 2)
        :css({
            ['padding'] = '0.2em',
            ['font-size'] = '85%',
            ['text-align'] = 'left',
            ['background-color'] = '#f8f8f8',
        })

    -- Footer container
    local footerContainer = mw.html.create('div')
        :css({
            ['display'] = 'flex',
            ['justify-content'] = 'space-between',
            ['align-items'] = 'center',
        })

    -- Left side: Edit links
    local editLinksSpan = footerContainer:tag('span')
        :addClass('plainlinks')
    
    -- Add Wikidata item link if entityId exists
    if entityId and entityId ~= '' then
        local wikidataUrl = 'https://www.wikidata.org/wiki/Special:EntityPage/' .. entityId
        editLinksSpan:wikitext('[' .. editSourceUrl .. '<span style="color:;">ⵙⵏⴼⵍ ⴰⵙⴰⴳⵎ</span>] - [' ..
                              editVisualUrl .. '<span style="color:;">ⵙⵏⴼⵍ</span>] - [' ..
                              wikidataUrl .. '<span style="color:;">ⵡⵉⴽⵉⴷⴰⵜⴰ</span>]')
    else
        editLinksSpan:wikitext('[' .. editSourceUrl .. '<span style="color:;">ⵙⵏⴼⵍ ⴰⵙⴰⴳⵎ</span>] - [' ..
                              editVisualUrl .. '<span style="color:;">ⵙⵏⴼⵍ</span>]')
    end

    -- Right side: Info icon
    footerContainer:tag('span')
        :css({
            ['float'] = 'right',
            ['margin-left'] = '5px',
        })
        :wikitext('[[file:Info Simple.svg|18px|ⵥⵕ ⵓⴳⴳⴰⵔ ⵅⴼ ⵡⴰⵍⴱⵓⴹ ⴰⴷ |link=' .. templateDocUrl .. ']]')

    footerCell:node(footerContainer)

    return tostring(infobox)
end

return p