Module:Wikidata table: Difference between revisions
Appearance
Content deleted Content added
unwind debug |
add fallback from 'inception' to 'date of official opening' |
||
Line 47: | Line 47: | ||
local df = "y" |
local df = "y" |
||
-- fallbacks for common properties |
-- fallbacks for common properties: |
||
-- property-to-fallback-from = "property-to-fallback-to" |
|||
local fallback = { |
local fallback = { |
||
P276 = "P131", |
P276 = "P131", |
||
P571 = "P1619", |
|||
} |
} |
||
Revision as of 00:16, 14 February 2021
Related pages |
---|
This module creates one or more table rows where the data in each cell is taken from Wikidata.
Usage
Function makerow
This function is under development for use in articles. It creates a single table row from one Wikidata entity using a given set of properties. The first cell is the label for the Wikidata entity and it is marked up as a row-header. An "editonwikidata" icon is appended to the first cell. The table caption, column headings and scopes, etc. should be supplied externally. See the examples for more detail.
{{#invoke:Wikidata table |makerow
|pids= P123, P234+P345, P456, P567/P580-P582, etc. (see below)
|qid = Q12345 (one entity id for the row)
|line = HTML color code for horizontal line applied to top of each row (if required)
|c1 = locally supplied value (overrides value from Wikidata for column 1)
|c2 = locally supplied value (overrides value from Wikidata for column 2)
|cN = locally supplied value (overrides value from Wikidata for column N), etc.
|c1+ = locally supplied value (appends value from Wikidata to column 1)
|c2+ = locally supplied value (appends value from Wikidata to column 2)
|cN+ = locally supplied value (appends value from Wikidata to column N), etc.
}}
Notes
- A table cell can be made up of a combination of multiple properties, qualifiers and references.
- Whitespace is ignored in the list of pids.
- The separator for cell values is the comma
,
. - Within a cell, multiple properties are separated by the plus sign
+
. - Each property can be separated from one or more qualifiers by a forward-slash
/
. - Each qualifier is separated by a hyphen
-
(although any punctuation other than, + /
will work).
Function convert
A convenient function to convert a list of articles into a table.
{{subst:#invoke:Wikidata table | convert
| template = name of template
| 1 = list of articles
}}
For example:
{{subst:#invoke:Wikidata table | convert | template = Wdtable row/dam | 1 =
* [[Aoyama Dam]]
* [[Apporo Dam]]
* [[Ariake Dam]]
}}
produces:
{{Wdtable row/dam|qid=Q113189811<!-- Aoyama Dam -->}} {{Wdtable row/dam|qid=Q113189827<!-- Apporo Dam -->}} {{Wdtable row/dam|qid=Q113189802<!-- Ariake Dam -->}}
See also
- Template:Wdtable row – a wrapper template for
makerow
- Template:Wdtable row/lighthouse – a custom wrapper template for
makerow
, hard-coding the pids for lists of lighthouses - Template:Wikidata list – bot generates Wikidata tables
- Module:Tabular data – shows tabular data from Commons
--[[ Module:Wikidata table --]]
local p = {}
local debugging = true
-- Internationalisation
local i18n = {
filespace = "File",
editonwikidata = "Edit this on Wikidata",
}
local months = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }
local mnths = {}
for idx, val in ipairs(months) do
mnths[idx] = val:sub(1,3)
end
local unitsymbol = {
inch = "in",
foot = "ft",
yard = "yd",
mile = "mi",
["nautical mile"] = "nmi",
metre = "m",
centimetre = "cm",
millimetre = "mm",
kilometre = "km",
}
-- prefixes for particular qualifiers
local prefix = {
P580 = "from ",
P582 = "until ",
}
-- error messages
local function errmsg(txt)
if debugging then
return "Error: " .. txt
else
return nil
end
end
-- date format default to year
local df = "y"
-- fallbacks for common properties:
-- property-to-fallback-from = "property-to-fallback-to"
local fallback = {
P276 = "P131",
P571 = "P1619",
}
-- return a number rounded to a precision
local function decimalprecision(x, prec)
local s = 1
if x < 0 then
x = -x
s = -1
end
-- if prec is not suplied, pick an arbitrary precision
if not tonumber(prec) then prec = 1e-4
elseif prec > 1 then prec = 1
elseif prec < 1e-6 then prec = 1e-6
else prec = 10 ^ math.floor(math.log10(prec))
end
x = math.floor(x / prec + 0.5) * prec * s
-- if it's integral, cast to an integer:
if x == math.floor(x) then x = math.floor(x) end
-- if it's less than 1e-4, it will be in exponent form, so return a string with 6dp
-- 9e-5 becomes 0.000090
if math.abs(x) < 1e-4 then x = string.format("%f", x) end
return x
end
-- creates an icon that links to the relevant Wikidata entity
local function createicon(entityID, propertyID, langcode)
langcode = langcode or ""
if not entityID or entityID == "" then entityID= mw.wikibase.getEntityIdForCurrentPage() end
propertyID = propertyID or ""
local icon = " <span class='penicon autoconfirmed-show'>[["
-- " <span data-bridge-edit-flow='overwrite' class='penicon'>[[" -> enable Wikidata Bridge
.. i18n.filespace
.. ":OOjs UI icon edit-ltr-progressive.svg |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 .. "]]</span>"
return icon
end
-- takes a qid and attempts to return a linked name for it
-- otherwise an unlinked name; otherwise the qid
function 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
lbl = "[[" .. slink .. "]]"
else
lbl = "[[" .. slink .. "|" .. label .. "]]"
end
elseif slink then
lbl = "[[" .. slink .. "]]"
elseif label then
lbl = label
else
lbl = qid
end
return lbl
end
-- entrypoint for #invoke getLink
function p.getLink(frame)
local qid = (frame.args.qid or ""):upper()
if qid == "" then return nil end
return p._getLink()
end
-- takes a qid and a property id and returns the corresponding values or empty string
-- 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)
maxvals = maxvals or 0
local ret = {}
for idx, prop in ipairs(mw.wikibase.getBestStatements(qid, pid)) do
if prop.mainsnak.snaktype ~= "value" then return nil end
local dtype = prop.mainsnak.datatype
local dval = prop.mainsnak.datavalue.value
local retval
if dtype == "wikibase-item" then
retval = p._getLink(dval.id)
elseif dtype == "monlingualtext" then
retval = dval.text
elseif dtype == "commonsMedia" or dtype == "external-id" or dtype == "string" or dtype == "url" then
retval = dval
elseif dtype == "time" then
dval.time = dval.time:gsub("%-00%-00T", "-01-01T")
local era = ""
if dval.time:sub(1,1) == "-" then
era = " BCE"
end
local year, month, day = dval.time:match("[+-](%d*)-(%d*)-(%d*)T")
year, day = tonumber(year), tonumber(day)
month = mnths[tonumber(month)]
if df == "y" then
retval = year .. era
elseif df == "mdy" then
retval = month .. " " .. day .. ", " .. year .. era
else
retval = day .. " " .. month .. " " .. year .. era
end
elseif dtype == "quantity" then
local amount = tonumber(dval.amount)
local unitqid = string.match( dval.unit, "(Q%d+)" )
local unit = mw.wikibase.getLabel(unitqid)
local symbol = unitsymbol[unit]
if symbol then
retval = mw.getCurrentFrame():expandTemplate{ title = "cvt", args = {amount, symbol} }
else
retval = amount .. " " .. unit
end
elseif dtype == "globe-coordinate" then
local lat = decimalprecision(dval.latitude, dval.precision)
local long = decimalprecision(dval.longitude, dval.precision)
retval = mw.getCurrentFrame():expandTemplate{ title="Coord", args={lat, long, format="dms"} }
else
retval = dval
end
if quals and prop.qualifiers and retval then
local qtbl = {}
for qpid in quals:gmatch("P%d+") do
local qval = prop.qualifiers[qpid] and mw.wikibase.formatValue(prop.qualifiers[qpid][1])
if qval then
qtbl[#qtbl+1] = (prefix[qpid] or "") .. qval
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
return table.concat(ret, "<br>")
end
-- entrypoint for #invoke getWD
function 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 multiple table rows, one for each qid in args.qids,
-- with one table cell for each pid in args.pids
function p._makerows(args)
args.qids = (args.qids or ""):upper()
if args.qids == "" then return errmsg("missing qids") end
args.pids = (args.pids or ""):upper()
if args.pids == "" then return errmsg("missing pids") end
local qids, pids = {}, {}
for qid in args.qids:gmatch("Q%d+") do
qids[#qids+1] = qid
end
for pid in args.pids:gmatch("P%d+") do
pids[#pids+1] = pid
end
args.df = args.df or ""
if args.df ~= "" then df = args.df end
local out = ""
for r, qid in ipairs(qids) do
out = out .. "<tr>"
out = out .. "<th scope='row'>" .. p._getLink(qid) .. "</th>"
for c, pid in ipairs(pids) do
if pid == "P18" then -- image
local img = p._getWD(qid, pid, 1)
if img then
out = out .. "<td>[[File:" .. img .. "|120px]]</td>"
end
else
out = out .. "<td>" .. p._getWD(qid, pid, 0) .. "</td>"
end
end
out = out .. "</tr>"
end
return out
end
-- entry point for #invoke makerows
function p.makerows(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
return p._makerows(args)
end
-- make a single table row, one cell per value passed in args.pids
-- each value may be a combination of properties and qualifiers
function p._makerow(args)
local qid = (args.qid or ""):upper():match("Q%d+")
if not qid then return errmsg("missing qid") end
-- remove whitespace, uppercase, trap nil
args.pids = (args.pids or ""):upper():gsub("%s", "")
if args.pids == "" then return errmsg("missing pids") end
-- collect any parameters cr1, cr2, etc. as cell replacements; ca1, ca2, etc. as addenda
local cellrep, celladd = {}, {}
for key, value in pairs(args) do
local col = (type(key) == "string") and tonumber(key:match("^[Cc]r(%d+)$"))
if col then
cellrep[col] = value
end
end
for key, value in pairs(args) do
local col = (type(key) == "string") and tonumber(key:match("^[Cc]a(%d+)$"))
if col then
celladd[col] = value
end
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 = "<tr>"
if cellrep[1] then
out = out .. "<th scope='row'>" .. cellrep[1] .. createicon(qid) .. "</th>"
else
out = out .. "<th scope='row'>" .. p._getLink(qid) .. (celladd[1] or "") .. createicon(qid) .. "</th>"
end
-- split args.pids at comma separators into table of cellpids (may be like P12+P34/P456-P789)
local cellpids = mw.text.split(args.pids, ",+")
for c, val in ipairs(cellpids) do
if cellrep[c+1] then
out = out .. "<td>" .. cellrep[c+1] .. "</td>"
else
-- separate properties from qualifiers with /
local props = mw.text.split(val, "/")[1]
local quals = mw.text.split(val, "/")[2]
local ptbl = {} -- table of property values
for pid in props:gmatch("P%d+", quals) do
if pid == "P18" then -- image
local img = p._getWD(qid, pid, 1)
if img then
ptbl[#ptbl+1] = "[[File:" .. img .. "|120px]]"
end
else
local wdval = p._getWD(qid, pid, 0, quals)
if wdval == "" and fallback[pid] then
wdval = p._getWD(qid, fallback[pid], 0, quals)
end
ptbl[#ptbl+1] = wdval
end
end
out = out .. "<td>" .. table.concat(ptbl, "<br>") .. (celladd[c+1] or "") .. "</td>"
end
end
out = out .. "</tr>"
return out
end
-- entry point for #invoke makerow
function 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
return p._makerow(args)
end
return p