Module:Wikidata infobox

From Wikipedia

This LUA module is a test intended to create an infobox, consisting of only Wikidata information, especially for smaller wikipedias.

The layout is to be determined by the table at the start of this module. This table should then hold all properties available in a logical sequence and proper sub-groups.

local t= { -- infobox table
 -- { property,  description,            type,       item,       description            },
    { 'P41',    'National flag',        'image',    'Q186516',  'National flag'         },
    { 'P94',    'Coat of arms',         'image',    'Q14659',   'Coat of arms'          },
    { 'P85',    'Anthem',               'item',     'Q23691',   'National anthem'       },
    { 'P299',   'ISO 3166-1 numeric',   'string',   'Q2725758', 'ISO 3166-1 numeric'    },
-- etc
    } -- end of infobox table

This module is not supposed to have any parameters.

Lua error at line 154: Tried to write global getimagevalue.


local Wikidata = require 'Module:Wikidata'
local p = {}

local t= { -- infobox table
    { 'begin',      '',         'Beginning',            '',         'Beginning'                         }, -- first line, do not remove
--  { type,         property,   description,            item,       description,            options },
-- general properities
    { 'image',      'P18',      'Image of the item',    '',         ''                                  },
-- geographical properties
    { 'smallimage', 'P41',      'National flag',        'Q186516',  'National flag'                     },
    { 'smallimage', 'P94',      'Coat of arms',         'Q14659',   'Coat of arms'                      },
    { 'image',      'P242',     'Locator map',          'Q2221906', 'Location'                          },
    { 'group',      '',         'Misc',                 '',         'Start of a group'                  },
    { 'item',       'P85',      'Anthem',               'Q23691',   'National anthem'                   },
    { 'string',     'P299',     'ISO 3166-1 numeric',   'Q2725758', 'ISO 3166-1 numeric'                },
-- person properties
    { 'group',      '',         'Misc',                 '',         ''                                  }, -- group with empty header
    { 'item',       'P19',      'Place of birth',       'Q1322263', 'Place of birth'                    },
    { 'date',       'P569',     'Date of birth',        'Q47223',   'Date of birth'                     },
    { 'item',       'P20',      'Place of death',       '',         'Place of death'                    },
    { 'date',       'P570',     'Date of death',        '',         'Date of death'                     },
-- taxobox properties
    { 'group',      '',         'Misc',                 'Q11398',   'Scientific classification'         }, 
    { 'item',       'P273',     'Domain',               'Q146481',  'Domain'                            },
    { 'item',       'P75',      'Kingdom',              'Q36732',   'Kingdom'                           },
    { 'item',       'P76',      'Phylum',               'Q38348',   'Phylum'                            },
    { 'item',       'P77',      'Class',                'Q37517',   'Class'                             },
    { 'item',       'P70',      'Order',                'Q36602',   'Order'                             },
    { 'item',       'P71',      'Family',               'Q35409',   'Family'                            },
    { 'item',       'P74',      'Genus',                'Q34740',   'Genus'                             },
    { 'item',       'P89',      'Species',              'Q7432',    'Species'                           },
    { 'group',      '',         'Misc',                 'Q36642',   'Binomial nomenclature'             }, 
    { 'item',       'P225',     'Taxon name',           '',         ''                  ,'pattern','<i>$1</i>'   }, -- pattern; italic 
    { 'group',      '',         'Misc',                 '',         ''                                  }, -- group with empty header
    { 'image',      'P181',     'Range map',            '',         'Range map'                         },
-- etc
    { 'group',      '',         'Closing',              '',         'Closing'                           } -- last line, do not remove
    } -- end of infobox table

local colors = {
    ['default'] = '#f0f0f0;',        
    ['P107'] = {                    -- main type GND
        ['Q215627'] = '#aaa;',      -- person
        ['Q43229'] = '#fcfcfc;',    -- organization
--        ['Q1656682'] =            -- event
--        ['Q386724'] =             -- creatve work
--        ['Q1969448'] =            -- term
--        ['Q618123'] =             -- place , geographical feature
--        ['Q11651459']=            -- disambiguation
    },
    ['P75'] = {                     -- biological kingdom
        ['Q10876'] = 'lightgrey',   -- bacteria
        ['Q101274'] = 'khaki',      -- protozoa
        ['Q862296'] = 'burlywood',  -- chromista
        ['Q756'] = 'lightgreen',    -- plantae
        ['Q764'] = 'lightblue',     -- fungi
        ['Q729'] = 'pink',          -- animalia
     },
-- etc
}     
 
local errors = {
    ["entity-not-found"] = "Entity not found.",
    ["infobox-type-invalid"] = "Infobox type invalid on line ",
    }

local layout = { -- infobox table layout
    [1]='<table class="infobox" style="width:20em;">',
    [2]="<tr style='background-color:$1'><td colspan=2><center>'''$2'''</center></td></tr>", -- label
    [4]='<tr><td colspan=2>[[Image:$1|250x250px]]<br><center>$2</center></td></tr>',    -- image
    [7]='<tr><td colspan=2><center><table border=0><tr>',                               -- begin of small image
    [8]='<td>[[Image:$1|125x125px]]<br><center>$2</center></td>',                       -- small image
    [11]='</table></center></td></tr>',                                                 -- end of small image
    [12]='<tr><td>$1</td><td>$2</td></tr>',                                             -- item
    [15]='<tr><td>$1</td><td>$2</td></tr>',                                             -- string
    [16]='<tr><td>$1</td><td>$2</td></tr>',                                             -- date
-- values, coordinates etc
    [90]="<tr style='background-color:$1'><td colspan=2>'''$2'''</td></tr>",            -- group
    [99]='</table>'
    }

local property_type     =1
local property          =2
local property_desc     =3
local item              =4
local item_desc         =5
local prop_option       =6
local prop_option_value =7

local entity = mw.wikibase.getEntityObject()

function p.infobox(frame )
    demo = frame.args.demo
    if not demo then
        if  not entity then
            return '<span class="error">' .. errors["entity-not-found"] .. '</span>'
        end
    end
    local backgroundcolor=getbackgroundcolor(demo)
    local heading = ""
    if demo then 
        heading = "Demo"
    else
       heading = mw.wikibase.label(entity.id)
    end
    local result = layout[1] .. mw.ustring.gsub(mw.ustring.gsub(layout[2],'$1',backgroundcolor),'$2',heading)
    local detail = ''
    local previousgroup = ''
    for line=1, 999 do     -- check all properties
        if t[line] and t[line][property] then
            local propertyid= t[line][property]
            if ( getitemvalue(line, propertyid, demo) ~= '' ) or ( t[line][property] == '' ) then 
                if t[line][property_type] == 'begin' then -- do nothing
-- image
                elseif t[line][property_type] == 'image' then
                    detail = detail .. mw.ustring.gsub(mw.ustring.gsub(layout[4],'$1',getimagevalue(line,propertyid,demo)),'$2',getitem(line))
-- smallimage
                elseif t[line][property_type] == 'smallimage' then
                    if t[line-1][property_type] ~= 'smallimage' then detail = detail .. layout[7] end
                    detail = detail .. mw.ustring.gsub(mw.ustring.gsub(layout[8],'$1',getimagevalue(line,propertyid,demo)),'$2',getitem(line))
                    if t[line+1][property_type] ~= 'smallimage' then detail = detail .. layout[11] end
-- item
                elseif t[line][property_type] == 'item' then
                    detail = detail .. mw.ustring.gsub(mw.ustring.gsub(layout[12],'$1',getitem(line)),'$2',getitemvalue(line,propertyid,demo))
-- string
                elseif t[line][property_type] == 'string' then
                    detail = detail .. mw.ustring.gsub(mw.ustring.gsub(layout[15],'$1',getitem(line)),'$2',getstringvalue(line,propertyid,demo))
-- date
                elseif t[line][property_type] == 'date' then
                    detail = detail .. mw.ustring.gsub(mw.ustring.gsub(layout[16],'$1',getitem(line)),'$2',getdatevalue(line,propertyid,demo))
-- group
                elseif t[line][property_type] == 'group' then
                    if detail ~= "" then
                        result = result .. previousgroup .. detail
                        detail = ""
                    end
                    if t[line][item_desc] ~= '' then
                        previousgroup = mw.ustring.gsub(mw.ustring.gsub(layout[90],'$1',backgroundcolor),'$2',getitem(line) )
                    else
                        previousgroup = ''
                    end
-- others / error
                else
                    return '<span class="error">' .. errors["infobox-type-invalid"] .. line .. ': ' ..
                        ' ' .. t[line][property_type] .. ' ' .. t[line][property] .. '</span>'
                end
            end
        end
    end
    result = result .. layout[99] 
    return result
end

function getimagevalue (line,propertyid,demo)
    if demo then return "Example title.png" end
    if entity.claims[propertyid] and entity.claims[propertyid][0] then
        return entity.claims[propertyid][0].mainsnak.datavalue.value
    else
        return '' 
    end
end

function getitemvalue (line,propertyid,demo)
    if demo then return "[[xxxx]]" end
    local options = getoptions (line,propertyid)
    local text = Wikidata.formatStatements(options)
    if text == '' then return text end
    if mw.ustring.sub(text,1,2) == '[[' then return text
    else return '[[' .. text .. ']]'                        -- return red link
    end
end

function getstringvalue (line,propertyid,demo)
    if demo then return "xxxxxx" end
    local options = getoptions (line,propertyid)
    return Wikidata.formatStatements(options)
end

function getdatevalue (line,propertyid,demo)
    if demo then return "01-01-2001" end
    local options = getoptions (line,propertyid)
    return Wikidata.formatStatements(options)
end

function getoptions (line, propertyid) -- get options for Wikidata.formatStatements from infobox table line
    local options 
    if ( not t[line][prop_option] ) or t[line][prop_option] =='' then
        options = { ["args"] = { ["property"] = propertyid } }
    elseif ( not t[line][prop_option+2] ) or t[line][prop_option+2] =='' then
        options = { ["args"] = { ["property"] = propertyid , [t[line][prop_option]] = t[line][prop_option_value] }}
    elseif ( not t[line][prop_option+4] ) or t[line][prop_option+4] =='' then
        options = { ["args"] = { ["property"] = propertyid , [t[line][prop_option]] = t[line][prop_option_value], 
                                                             [t[line][prop_option+2]] = t[line][prop_option_value+2] }}
    else -- currently maximum of 3 options
        options = { ["args"] = { ["property"] = propertyid , [t[line][prop_option]] = t[line][prop_option_value], 
                                                             [t[line][prop_option+2]] = t[line][prop_option_value+2],
                                                             [t[line][prop_option+4]] = t[line][prop_option_value+4] }}
    end
    return options
end

function getitem (line)
    local label = '' 
    local link = ''
    if t[line][item] ~= '' then
        label = mw.wikibase.label(t[line][item])
        link = mw.wikibase.sitelink(t[line][item])
    end
    if link  == nil then link  = '' end
    if label == nil then label = '' end
    if  link ~= '' then
        if label ~= '' then return '[[' .. link .. '|' .. label .. ']]'
        else                return '[[' .. link .. ']]'
        end
    else
        if label == '' and t[line][property] ~= '' and t[line][item] ~= '' then 
            label = mw.wikibase.label(t[line][property])    -- 1st fallback: get description of the property
            if label == nil then label = '' end
        end
        if label == '' then 
            label = t[line][item_desc]                      -- 2nd fallback: get item description from infobox table
        end
    end
    return label
end

function getbackgroundcolor (demo)
    local color = colors.default
    if demo then return colors.default end
    for c1 in pairs (colors) do
        local c2 = ''    
        if entity.claims[c1] and entity.claims[c1][0] then
            c2 = 'Q' .. entity.claims[c1][0].mainsnak.datavalue.value["numeric-id"]
        end
        if colors[c1][c2] then 
            color = colors[c1][c2]
        end
    end
    return color 
end

function p.listcolors ()
    local label=''
    local result = 'Colors of Wikidata infoboxes<br><table>'
    result = result .. "<tr><td>Default</td><td style='background-color:" .. colors.default .. "'>&nbsp;</td></tr>" 
    for c1 in pairs (colors) do
        if type ( colors[c1] ) == "table" then 
            label= mw.wikibase.label(c1)
            if label == nil then label = c1 end
            result = result .. '<tr><td>' .. label .. "</td>" 
            for c2 in pairs (colors[c1]) do   
                result = result .. "<td style='background-color:" .. colors[c1][c2] .. "'>"
                label= mw.wikibase.label(c2)
                if label == nil then label = c2 end
                result = result .. label .. "</td>" 
            end
            result = result .. '</tr>'
        end
    end
    result = result .. '</table>' 
    return result
end    

return p