Module:DynamicCapiunto
Appearance
Documentation for this module may be created at Module:DynamicCapiunto/doc
local capiunto = require 'capiunto'
local p = {}
function p.main(frame)
local args = frame:getParent().args
local qid = args.qid or args[1]
if not qid then
return '<span class="error">Error: No Wikidata QID provided</span>'
end
-- Register the entity association
frame:callParserFunction('#unlinkedwikibase', 'id=' .. qid)
-- Get entity data from UnlinkedWikibase
local entity = mw.ext.UnlinkedWikibase.getEntity(qid)
if not entity then
return '<span class="error">Error: Entity ' .. qid ..
' not found</span>'
end
-- Helper function to get property value from entity
local function getPropertyValue(pid)
if not entity.claims or not entity.claims[pid] then return nil end
local claims = entity.claims[pid]
if not claims or #claims == 0 then return nil end
local claim = claims[1]
if not claim.mainsnak or not claim.mainsnak.datavalue then
return nil
end
return claim.mainsnak.datavalue.value
end
-- Helper function to format different value types
local function formatValue(value, valueType)
if not value then return nil end
if type(value) == 'table' then
-- Handle time values
if value.time then
-- Extract year-month-day from +2023-01-15T00:00:00Z format
local dateStr = value.time
local year, month, day =
dateStr:match('^[+-]?(%d+)-(%d+)-(%d+)')
if year then
local y = tonumber(year)
local m = tonumber(month) or 0
local d = tonumber(day) or 0
-- If month or day are zero/unknown, show only the year
if m == 0 or d == 0 then
return string.format('%04d', y)
end
return string.format('%04d-%02d-%02d', y, m, d)
end
return value.time
-- Handle entity references (Q-IDs)
elseif value.id then
local linkedEntity = mw.ext.UnlinkedWikibase.getEntity(value.id)
if linkedEntity then
local label = (linkedEntity.labels and
linkedEntity.labels.en) and
linkedEntity.labels.en.value or value.id
-- Then prefer an en.wikipedia sitelink (external link)
if linkedEntity.sitelinks and linkedEntity.sitelinks.enwiki and
linkedEntity.sitelinks.enwiki.url then
return
'[' .. linkedEntity.sitelinks.enwiki.url .. ' ' ..
label .. ']'
end
-- Fallback to the English label if available
if linkedEntity.labels and linkedEntity.labels.en then
return label
end
end
return value.id
-- Handle monolingual text
elseif value.text then
return value.text
end
end
return tostring(value)
end
-- Helper to get claim entity id (if the claim is an entity)
local function getClaimEntityId(pid)
local v = getPropertyValue(pid)
if type(v) == 'table' and v.id then return v.id end
return nil
end
-- Helper to get the first claim object for a property
local function getFirstClaimObject(pid)
if not entity.claims or not entity.claims[pid] then return nil end
local claims = entity.claims[pid]
if not claims or #claims == 0 then return nil end
return claims[1]
end
-- Helper to get a qualifier value (prefer English monolingual text for P2096)
local function getQualifierValue(claim, qualPid)
if not claim or not claim.qualifiers or not claim.qualifiers[qualPid] then
return nil
end
local qsnaks = claim.qualifiers[qualPid]
if not qsnaks or #qsnaks == 0 then return nil end
for i, q in ipairs(qsnaks) do
-- Check for valid snak with datavalue
if q and q.snaktype == 'value' and q.datavalue and q.datavalue.value then
local v = q.datavalue.value
if type(v) == 'table' then
-- For monolingual text, prefer English
if v.language and v.language == 'en' and v.text then
return v.text
end
else
return tostring(v)
end
end
end
return nil
end
-- Decide which infobox to render based on instance (P31)
local instanceId = getClaimEntityId('P31')
local infobox
if instanceId == 'Q5' then
-- Person infobox
local personTitle = qid
if entity.labels and entity.labels.en then
personTitle = entity.labels.en.value
end
infobox = capiunto.create({
title = personTitle,
bodyClass = 'infobox vevent',
bodyStyle = 'width: 300px;'
})
-- Add image (P18) with media legend (P2096) as caption
local imageClaim = getFirstClaimObject('P18')
if imageClaim then
local imageVal = imageClaim.mainsnak and
imageClaim.mainsnak.datavalue and
imageClaim.mainsnak.datavalue.value
if imageVal then
local imageStr = tostring(imageVal)
local caption = getQualifierValue(imageClaim, 'P2096')
if caption and caption ~= '' then
infobox:addImage('[[File:' .. imageStr .. '|300px]]',
caption)
else
infobox:addImage('[[File:' .. imageStr .. '|300px]]')
end
end
end
-- Birthplace (P19)
local birthplace = getPropertyValue('P19')
if birthplace then
infobox:addRow('Birthplace', formatValue(birthplace))
end
-- Birthday (P569)
local birthday = getPropertyValue('P569')
if birthday then
infobox:addRow('Birthday', formatValue(birthday))
end
-- Death (P570)
local death = getPropertyValue('P570')
if death then infobox:addRow('Death', formatValue(death)) end
-- Occupation (P106)
local occupation = getPropertyValue('P106')
if occupation then
infobox:addRow('Occupation', formatValue(occupation))
end
return tostring(infobox) .. '\n[[Category:People]]'
else
-- Default: organisation/troupe infobox (existing behavior)
local title = qid
if entity.labels and entity.labels.en then
title = entity.labels.en.value
end
infobox = capiunto.create({
title = title,
bodyClass = 'infobox vevent',
bodyStyle = 'width: 300px;'
})
-- Add official name (P1448)
local officialName = getPropertyValue('P1448')
if officialName then
infobox:addRow('Official Name', formatValue(officialName))
end
end
-- Add logo (P154)
local logo = getPropertyValue('P154')
if logo then
local logoStr = formatValue(logo)
if logoStr then
infobox:addImage('[[File:' .. logoStr .. '|150px]]', 'Logo')
end
end
-- Add image (P18) with media legend (P2096) as caption
local imageClaim = getFirstClaimObject('P18')
if imageClaim then
local imageVal =
imageClaim.mainsnak and imageClaim.mainsnak.datavalue and
imageClaim.mainsnak.datavalue.value
if imageVal then
local imageStr = tostring(imageVal)
local caption = getQualifierValue(imageClaim, 'P2096')
if caption and caption ~= '' then
infobox:addImage('[[File:' .. imageStr .. '|300px]]', caption)
else
infobox:addImage('[[File:' .. imageStr .. '|300px]]')
end
end
end
-- Add headquarters (P159)
local headquarters = getPropertyValue('P159')
if headquarters then
infobox:addRow('Headquarters', formatValue(headquarters))
end
-- Add founding date (P571)
local foundingDate = getPropertyValue('P571')
if foundingDate then
infobox:addRow('Founding Date', formatValue(foundingDate))
end
-- Add dissolution date (P576)
local dissolutionDate = getPropertyValue('P576')
if dissolutionDate then
infobox:addRow('Dissolution Date', formatValue(dissolutionDate))
end
-- Add country (P17)
local country = getPropertyValue('P17')
if country then infobox:addRow('Country', formatValue(country)) end
-- Add parent organization (P749)
local parentOrg = getPropertyValue('P749')
if parentOrg then
infobox:addRow('Parent Organization', formatValue(parentOrg))
end
-- Add official website (P856) as full-width row at bottom
local website = getPropertyValue('P856')
if website then
local websiteStr = formatValue(website)
if websiteStr then
-- Strip http:// or https:// from display text
local displayUrl = websiteStr:gsub('^https?://', '')
infobox:addWikitext(
'<div style="width:100%; text-align:center;">[' .. websiteStr ..
' ' .. displayUrl .. ']</div>')
end
end
return tostring(infobox) ..
'\n[[Category:Clubs, Societies and Institutions]]'
end
return p