Module:Wikidata table/sandbox explained
local p =
local debugging = false
local sep = ", " -- separator for multiple values of same property, changed from "
"local sep2 = "
" -- separator for values of different propertieslocal maxrefs = 3 -- maximum number of references displayed for each statement
-- Internationalisation
local currentlang = mw.language.getContentLanguage
local i18n =
local months = local mnths = for idx, val in ipairs(months) do mnths[idx] = val:sub(1,3)end
-- makeOrdinal needs to be internationalised along with the above i18n-- takes cardinal number as a numeric and returns the ordinal as a string-- we need three exceptions in English for 1st, 2nd, 3rd, 21st, .. 31st, etc.-------------------------------------------------------------------------------p.makeOrdinal = function(cardinal) local card = tonumber(cardinal) if not card then return cardinal end local ordsuffix = i18n.ordinal.default if card % 10
1 then ordsuffix = i18n.ordinal[1] elseif card % 10
2 then ordsuffix = i18n.ordinal[2] elseif card % 10
3 then ordsuffix = i18n.ordinal[3] end -- In English, 1, 21, 31, etc. use 'st', but 11, 111, etc. use 'th' -- similarly for 12 and 13, etc. if (card % 100
11) or (card % 100
12) or (card % 100
13) then ordsuffix = i18n.ordinal.default end return card .. ordsuffixend
local unitsymbol =
-- prefixes for particular qualifierslocal prefix =
-- external ids which have a formatter url (P1630)local formaturl =
-- date format default to dmylocal df = "dmy"
-- fallbacks for common properties:-- property-to-fallback-from = "property-to-fallback-to"local fallback =
local statedIDs = -- error messageslocal function errmsg(txt) if debugging then return "Error: " .. txt else return nil endend
-- formats the first character of linked item to uppercaselocal function ucf(lnk) local tbl = mw.text.split(lnk, "|", true) local ret if tbl[2] then -- piped link tbl[2] = tbl[2]:gsub("^(%l)", mw.ustring.upper) ret = table.concat(tbl, "|") elseif lnk:sub(1,2)
"frameless |text-top |10px |alt=" .. i18n.editonwikidata .. "|link=https://www.wikidata.org/wiki/" .. entityID if langcode ~= "" then icon = icon .. "?uselang=" .. langcode end if propertyID ~= "" then icon = icon .. "#" .. propertyID end icon = icon .. "|" .. i18n.editonwikidata .. "]]" return iconend
-- takes a statement tuple supplied from Wikidata and returns any referencesfunction p._getrefs(statement, qid) if not statement.references then return nil end local rtbl = local frm = mw.getCurrentFrame for idx, ref in ipairs(statement.references) do if ref.snaks.P854 then -- reference url local url = ref.snaks.P854[1].datavalue.value if ref.snaks.P1476 then -- title (monolingual text) local title for idx1, titles in ipairs(ref.snaks.P1476) do if titles.datavalue.value.language
currentlang then title = titles.datavalue.value.text local website = "" if ref.snaks.P248 then local rqid = ref.snaks.P248[1].datavalue.value.id local label = mw.wikibase.label(rqid,currentlang) if label then local sitelink = mw.wikibase.sitelink(rqid) if sitelink then website = "" .. label .. "" else website = label end end end local citeweb = frm:expandTemplate local hash = "WD" .. mw.hash.hashValue("crc32", citeweb) rtbl[#rtbl+1] = frm:callParserFunction break end end else local bnf = url:match("https?://data.bnf.fr/ark:/12148/cb([0-9][a-Za-Z0-9]+)") or url:match("https?://catalogue.bnf.fr/ark:/12148/cb([0-9][a-Za-Z0-9]+)") if bnf then rtbl[#rtbl+1] = frm:callParserFunction else local hash = "WD" .. mw.hash.hashValue("crc32", url) rtbl[#rtbl+1] = frm:callParserFunction end end elseif ref.snaks.P248 then local rqid = ref.snaks.P248[1].datavalue.value.id if statedIDs[rqid] then local template = statedIDs[rqid] local propid = mw.wikibase.getBestStatements(rqid,"P1687") propid = propid[1].mainsnak.datavalue.value.id for num, propdata in ipairs(mw.wikibase.getBestStatements(qid, propid)) do local property = propdata.mainsnak.datavalue.value local args = if rqid
"Q547473" then args.title = mw.wikibase.label(qid) end local result = frm:expandTemplate rtbl[#rtbl+1] = frm:callParserFunction end else local citeq = frm:expandTemplate rtbl[#rtbl+1] = frm:callParserFunction end end if #rtbl>=maxrefs then break end -- maximum number of references reached end return table.concat(rtbl)end
-- takes a qid and attempts to return a linked name for it-- otherwise an unlinked name; otherwise the qidfunction p._getLink(qid) local lbl = "" local slink = mw.wikibase.sitelink(qid) local label = mw.wikibase.getLabel(qid) if slink and label then if slink:lower
label:lower then if label:find("^%u") then -- match label's case lbl = "" else lbl = "" end else lbl = "" .. label .. "" end elseif slink then lbl = "" .. slink .. "" elseif label then lbl = label else lbl = qid end return lblend-- entrypoint for #invoke getLinkfunction p.getLink(frame) local qid = (frame.args.qid or ""):upper if qid
"" then return nil end return p._getLink(qid)end
-- takes a snak for a time property and returns the datelocal function _getDate(snak, prec) local retval retval = mw.wikibase.renderSnak(snak) if prec
7 then -- century local num, txt = retval:match("^(%d+)%.(.+)$") retval = p.makeOrdinal(num) .. txt elseif prec
10 then local m, y, e = retval:match("^(%a+) (%d+)(.*)") retval = m:sub(1,3) .. " " .. y .. e elseif prec
11 then local d, m, y, e = retval:match("^(%d+) (%a+) (%d+)(.*)") retval = d .. " " .. m:sub(1,3) .. " " .. y .. e end return retvalend
-- takes a qid and a property id and returns the corresponding values or nil-- maxvals greater than zero sets the maximum number of values to return-- the string quals contains property ids of qualifiers to be returned ('-' is the separator)function p._getWD(qid, pid, maxvals, quals, colunit) maxvals = maxvals or 0 local ret = local sortkey for idx, prop in ipairs(mw.wikibase.getBestStatements(qid, pid)) do local retval if prop.mainsnak.snaktype ~= "value" then break end local dtype = prop.mainsnak.datatype local dval = prop.mainsnak.datavalue.value if dtype
"wikibase-item" then retval = p._getLink(dval.id) elseif dtype
"monolingualtext" then retval = dval.text elseif dtype
"commonsMedia" or dtype
"url" then retval = dval elseif dtype
"external-id" or dtype
"string" then if formaturl[pid] then retval = "[" .. mw.ustring.gsub(formaturl[pid], "$1", dval) .. " " .. dval .. "]" else retval = dval end elseif dtype
"time" then retval = _getDate(prop.mainsnak, dval.precision) if dval.precision
11 and df
"mdy" then local d, m, y, e = retval:match("^(%d+) (%a+) (%d+)(.*)") retval = m .. " " .. d .. ", " .. y .. e end if not sortkey then sortkey = prop.mainsnak.datavalue.value.time end elseif dtype
"quantity" then local amount = tonumber(dval.amount) local unit = string.match(dval.unit, "(Q%d+)") if unit then if unit
colunit then -- unit matches default for this column, so do not display unit retval = amount else if unitsymbol[unit] then if colunit then -- attempt to convert to default unit local unit_label = mw.wikibase.label(unit) or unitsymbol[unit] or '???' local colunit_label = mw.wikibase.label(colunit) or unitsymbol[colunit] or '???' retval = mw.getCurrentFrame:expandTemplate .. mw.getCurrentFrame:expandTemplate else -- show unit and default conversion retval = mw.getCurrentFrame:expandTemplate end else retval = amount .. " " .. mw.wikibase.getLabel(unit) end end else retval = amount end elseif dtype
"globe-coordinate" then local lat = decimalprecision(dval.latitude, dval.precision) local long = decimalprecision(dval.longitude, dval.precision) retval = "
" .. mw.wikibase.formatValue(prop.mainsnak) .. "" else retval = dval end -- get references retval = retval .. (p._getrefs(prop, qid) or "") -- get qualifiers if quals and prop.qualifiers and retval then local qtbl = for qpid in quals:gmatch("P%d+") do if prop.qualifiers[qpid] then for i, qv in ipairs(prop.qualifiers[qpid]) do if qv.snaktype ~= "value" then break end local fqv if qv.datatype
"globe-coordinate" then fqv = mw.wikibase.formatValue(qv) -- linked elseif qv.datatype
"time" then fqv = _getDate(qv, qv.datavalue.value.precision) if qv.datavalue.value.precision
11 then -- trim to month fqv = fqv:match("%d+ (.+)") end else fqv = mw.wikibase.renderSnak(qv) -- plaintext end if fqv and fqv ~= "" then qtbl[#qtbl+1] = (prefix[qpid] or "") .. fqv end end end end if #qtbl > 0 then retval = retval .. "
(" .. table.concat(qtbl, " ") .. ")" end end ret[#ret+1] = retval if maxvals > 0 and #ret >= maxvals then break end end if #ret < 1 then return nil else return table.concat(ret, sep),sortkey endend
-- entrypoint for #invoke getWDfunction p.getWD(frame) local qid = (frame.args.qid or ""):upper if qid
"" then return nil end local pid = (frame.args.pid or ""):upper if pid
"" then return nil end local maxvals = tonumber(frame.args.maxvals) or 0 local quals = (frame.args.quals or ""):upper if quals
"" then quals = nil end return p._getWD(qid, pid, maxvals, quals)end
-- make a single table row, one cell per value passed in args.pids-- each value may be a combination of properties and qualifiersfunction p._makerow(args) local qid = (args.qid or ""):upper:match("Q%d+") -- qid can be nil if we want a row without wikidata -- remove whitespace, uppercase, trap nil args.pids = (args.pids or ""):upper:gsub("%s", "") if args.pids
"" then return errmsg("missing pids") end local summary = (args.summary or "") local linecolor = (args.line or "") local linestyle = if linecolor ~= "" then linestyle = 'style="border-top:solid #' .. linecolor .. ';"' end local rows if summary
"" then rows=1 else rows=2 end local cols = 0 -- collect any parameters c1, c2, etc. as cell replacements; c1+, c2+, etc. as addenda local cellrep, celladd =, for key, value in pairs(args) do local colr = (type(key)
"string") and tonumber(key:match("^[Cc](%d+)$")) if colr then cellrep[colr] = value end local cola = (type(key)
"string") and tonumber(key:match("^[Cc](%d+)%+$")) if cola then celladd[cola] = value end end if args.refname and args.refname ~= "" then local c1 = celladd[1] or "" celladd[1] = c1 .. mw.getCurrentFrame:extensionTag end -- set date format if passed args.df = args.df or "" if args.df ~= "" then df = args.df end -- create the html to return local out = "
" if cellrep[1] and qid then out = out .. cellrep[1] .. createicon(qid) .. " | " elseif not qid then out = out .. (cellrep[1] or " ") .. "" else out = out .. ucf(p._getLink(qid)) .. (celladd[1] or "") .. createicon(qid) .. "" end -- split args.pids at comma separators into sequence of cellpids (each may be like P12+P34/P456-P789) local cellpids = mw.text.split(args.pids, ",+") for c, val in ipairs(cellpids) do cols = cols+1 if cellrep[c+1] then out = out .. '' .. cellrep[c+1] .. ' | ' elseif not qid then out = out .. " | " elseif val
'SD' then local short_description = mw.wikibase.getDescription(qid) if short_description then short_description = currentlang:ucfirst(short_description) else local getShortDescription = require('Module:GetShortDescription').main local sdt = getShortDescription short_description = sdt.explicit or end out = out .. '' .. short_description .. ' | ' else -- separate multiple properties in same cell, sep=+ local ptbl = -- sequence of values for one cell local sortkeyf for propandquals in mw.text.gsplit(val, "+", true) do -- for each property, split off property from qualifiers, sep=/ local pid = mw.text.split(propandquals, "/")[1] local unit = pid:match("%((Q%d+)%)") -- capture unit of quantity if specified pid = pid:match("P%d+") local quals = mw.text.split(propandquals, "/")[2] if pid
"P18" then -- image local img = p._getWD(qid, "P18", 1) if not img and fallback["P18"] then img = p._getWD(qid, fallback["P18"], 1) end if img then ptbl[#ptbl+1] = "" end else local wdval,sortkey = p._getWD(qid, pid, 0, quals, unit) if not wdval and fallback[pid] then wdval,sortkey = p._getWD(qid, fallback[pid], 0, quals, unit) end if not sortkeyf then sortkeyf = sortkey end ptbl[#ptbl+1] = wdval and ucf(wdval) end end -- of loop through multiple properties in same cell if sortkeyf then sortkeyf = 'data-sort-value="' .. mw.ustring.sub(sortkeyf,2) .. '"' else sortkeyf = end out = out .. '
' .. table.concat(ptbl, sep2) .. (celladd[c+1] or "") .. ' | ' end end -- of loop through all of the cells in the row out = out .. "
---|
" if summary ~= "" then out = out .. "
" .. summary .. " |
" end return outend
-- entry point for #invoke makerowfunction p.makerow(frame) local args = for key, value in pairs(frame:getParent.args) do args[key] = value end for key, value in pairs(frame.args) do args[key] = value end local isdoc if args.doc and args.doc
"no" then isdoc = false else isdoc = mw.title.getCurrentTitle:inNamespace(10) end if isdoc then args.qid = args.example return p.doc(args) else return p._makerow(args) endend
function p.convert(frame) local args = frame.args local pargs = frame:getParent.args local input = args[1] or pargs[1] local template = args.template or pargs.template if input
nil then return nil end local resolveEntity = require("Module:ResolveEntityId") local articlelist = mw.text.split(input,"%*%s*") local qidlist = for i,article in ipairs(articlelist) do local rawarticle=string.match(article,'%[%[(.+)%|') or string.match(article,'%[%[(.+)%]%]') if rawarticle then local qid = resolveEntity._id(rawarticle) if qid then qidlist[#qidlist+1] = "" else qidlist[#qidlist+1] = "" end end end return table.concat(qidlist,"\n")end
function p.convert2(frame) local args = frame.args local pargs = frame:getParent.args local input = args[1] or pargs[1] local template = args.template or pargs.template if input
nil then return nil end local qidlist = mw.text.split(input,"%*%s*") local out = "" for i,qid in ipairs(qidlist) do qid = mw.text.trim(qid) out = out .. "\n" end return outend
local function proplink(pid) local out if pid
"P1" then out = "Custom input" else out = mw.getCurrentFrame:expandTemplate end return outend
function p.doc(args) local pids = args.pids local article = args.article local qid = args.qid local documentation = require('Module:Documentation').main pids = (pids or ""):upper:gsub("%s", "") if pids
"" then return errmsg("Missing PIDs") end local pidtable = for c1,val in ipairs(mw.text.split(pids, ",")) do pidtable[c1] = for c2,propandquals in ipairs(mw.text.split(val, "+")) do pidtable[c1][c2] = pidtable[c1][c2].property = mw.text.split(propandquals, "/")[1] pidtable[c1][c2].unit = pidtable[c1][c2].property:match("%((Q%d+)%)") if pidtable[c1][c2].property~='SD' then pidtable[c1][c2].property = pidtable[c1][c2].property:match("P%d+") end local quals = mw.text.split(propandquals, "/")[2] if quals then pidtable[c1][c2].quals = for qpid in quals:gmatch("P%d+") do pidtable[c1][c2].quals[1] = qpid end end end end local function unit(qid) if qid then local unit = mw.wikibase.sitelink(qid) if unit then unit = "" .. unitsymbol[qid] .. "" else unit = unitsymbol[qid] end return " (in " .. unit .. ")" else return "" end end local out = "This template will retrieve certain data from Wikidata for use in a table in an article. It is a wrapper template for function makerow, using predefined properties.\n\n" if article then out = out .. "It was designed for use on " .. article .. " but may also be used on other articles. (Search)\n" end out = out .. "Usage
" out = out .. "The data that is displayed in each column is as follows:" out = out .. '
Column " .. c .. " |
---|
Label | " for c2 = 1,#pidtable[c1] do if pidtable[c1][c2].propert
|