Module:Wikidata table

local p = {}

local debugging = false
local current_page =  mw.title.getCurrentTitle()

local sep = ", " -- separator for multiple values of same property, changed from "<br>"
local sep2 = "<br>" -- separator for values of different properties
local maxrefs = 3 -- maximum number of references displayed for each statement

-- Internationalisation

local currentlang = mw.language.getContentLanguage()

local i18n = {
	filespace = "File",
	editonwikidata = "Edit this on Wikidata",
	ordinal = {
		[1] = "st",
		[2] = "nd",
		[3] = "rd",
		["default"] = "th"
	},
}

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

-- 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 .. ordsuffix
end

local unitsymbol = {
	Q218593 = "in",
	Q3710 = "ft",
	Q482798 = "yd",
	Q253276 = "mi",
	Q93318 = "nmi",
	Q11573 = "m",
	Q174728 = "cm",
	Q174789 = "mm",
	Q828224 = "km",
	Q81292 = "acres",
	Q35852 = "ha",
	Q712226 = "km2"
}

-- prefixes for particular qualifiers
local prefix = {
	P580 = "from ",
	P582 = "until ",
}

-- external ids which have a formatter url (P1630)
local formaturl = {
	P3563 = "https://wikidata-externalid-url.toolforge.org/?url=https%3A%2F%2Fmsi.nga.mil%2FqueryResults%3Fpublications%2Fngalol%2Flights-buoys%3Fvolume%3D%251%26featureNumber%3D%252%26includeRemovals%3Dfalse%26output%3Dhtml&exp=(%5Cd%7B3%7D)-(.*)&id=$1", -- NGA number
	P613 = "http://nearby.org.uk/coord.cgi?p=$1", -- OS grid reference
	P373 = "https://commons.wikimedia.org/wiki/Category:$1", -- Commons category
	P11235 = "http://damnet.or.jp/cgi-bin/binranA/enAll.cgi?db4=$1", -- Dams in Japan
	P11627 = "https://www.ibiblio.org/lighthouse/$1.htm", -- Lighthouse Directory
	P815 = "https://www.itis.gov/servlet/SingleRpt/SingleRpt?search_topic=TSN&search_value=$1" -- Integrated Taxonomic Information System
}

-- date format default to dmy
local df = "dmy"

-- fallbacks for common properties:
-- property-to-fallback-from = "property-to-fallback-to"
local fallback = {
	P276 = "P131",
	P571 = "P1619",
	P729 = "P1619",
	P4755 = "P296",
	P18 = "P8592"
}

local statedIDs = {
	Q36578 = {"GND", name=1},
	Q547473 = {"MacTutor", name="id"},
	Q19938912 = {"BNF", name=1},
	Q6973052 = {"National Heritage List for England", name="num"},
	Q19842847 = {"Historic Scotland listed building number", name=1}
}
-- error messages
local function errmsg(txt)
	if debugging then
		return "Error: " .. txt
	else
		return nil
	end
end

-- formats the first character of linked item to uppercase
local 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) == "[[" then -- unpiped link
		ret = lnk:gsub("^(%[%[%l)", mw.ustring.upper)
	else -- unlinked
		ret = lnk:gsub("^(%l)", mw.ustring.upper)
	end
	return ret
end
-- entrypoint for invoke
function p.ucf(frame)
	return ucf(frame.args.text or "")
end

-- 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 = "&nbsp;<span class='penicon autoconfirmed-show'>[["
	-- "&nbsp;<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

-- lookup nestedIndex in outer table
-- Example:  fetchNested(foo,{'bar','baz','quux'}) will return
--     foo.bar and foo.bar.baz and foo.bar.baz.quux
local function fetchNested(outer,nestedIndex)
    if not outer or type(outer) ~= 'table' or not nestedIndex or type(nestedIndex) ~= 'table' then
        return nil
    end
    local current = outer
    for _, indx in ipairs(nestedIndex) do
        current = current[indx]
        if not current then
            return current
        end
    end
    return current
end

-- takes a statement tuple supplied from Wikidata and returns any references
function 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
        local url = fetchNested(ref,{"snaks","P854",1,"datavalue","value"})
		if url then -- reference url
            local titleProp = fetchNested(ref,{"snaks","P1476"})
			if titleProp then -- title (monolingual text)
				local title
				for idx1, titles in ipairs(titleProp) do
					if fetchNested(titles,{"datavalue","value","language"}) == currentlang then
						title = fetchNested(titles,{"datavalue","value","text"})
						local website = ""
                        local rqid = fetchNested(ref,{"snaks","P248",1,"datavalue","value","id"})
						if rqid then
							local label = mw.wikibase.label(rqid,currentlang)
							if label then
								local sitelink = mw.wikibase.sitelink(rqid)
								if sitelink then
									website = "[[" .. sitelink .. "|" .. label .. "]]"
								else
									website = label
								end
							end
						end
						local citeweb = frm:expandTemplate{ title = "Cite web", args = { url=url, title=title, website=website} }
						local hash = "WD" .. mw.hash.hashValue("crc32", citeweb)
						rtbl[#rtbl+1] = frm:callParserFunction{ name = "#tag:ref", args = { citeweb, name=hash } }
						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{ name = "#tag:ref", args = { frm:expandTemplate{title="BNF",args={bnf}}, name="bnf"..bnf} }
				else
					local hash = "WD" .. mw.hash.hashValue("crc32", url)
					rtbl[#rtbl+1] = frm:callParserFunction{ name = "#tag:ref", args = { url, name=hash } }
				end
			end
		else
			local rqid = fetchNested(ref,{"snaks","P248",1,"datavalue","value","id"})
			if rqid and statedIDs[rqid] then
				local template = statedIDs[rqid]
				local propid = mw.wikibase.getBestStatements(rqid,"P1687")
				propid = fetchNested(propid,{1,"mainsnak","datavalue","value","id"})
                if propid then
				    for num, propdata in ipairs(mw.wikibase.getBestStatements(qid, propid)) do
					    local property = fetchNested(propdata,{"mainsnak","datavalue","value"})
					    local args = {[template.name] = property}
					    if rqid == "Q547473" then
						    args.title = mw.wikibase.label(qid)
					    end
					    local result = frm:expandTemplate{title=template[1],args=args}
					    rtbl[#rtbl+1] = frm:callParserFunction{ name = "#tag:ref", args = { result, name=qid .. propid .. num} }
				    end
                end
			elseif rqid then
				local citeq = frm:expandTemplate{ title = "Cite Q", args = { rqid } }
				rtbl[#rtbl+1] = frm:callParserFunction{ name = "#tag:ref", args = { citeq, name=rqid } }
			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 qid
function p._getLink(qid, ShowRedLinks)
	local lbl, link = "", true
	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 = slink:gsub("^(%l)", mw.ustring.upper)
			else
				lbl = slink:gsub("^(%u)", mw.ustring.lower)
			end
		else
			lbl = slink .. "|" .. label
		end
	elseif slink then
		lbl = slink
	elseif label then
		lbl = label
		link = ShowRedLinks -- add link if ShowRedLinks set to true
	else
		lbl = qid
		link = false
	end
	return link and ('[[' .. lbl .. ']]') or lbl
end
-- entrypoint for #invoke getLink
function p.getLink(frame)
	local qid = (frame.args.qid or ""):upper()
	if qid == "" then return nil end
	local ShowRedLinks = frame.args.ShowRedLinks and true or false
	return p._getLink(qid, ShowRedLinks)
end

-- takes a snak for a time property and returns the date
local 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 retval
end

-- 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 fetchNested(prop,{"mainsnak","snaktype"}) ~= "value" then
			break
		end
		local dtype = fetchNested(prop,{"mainsnak","datatype"})
		local dval = fetchNested(prop,{"mainsnak","datavalue","value"})
		if dtype == "wikibase-item" then
            retval = fetchNested(dval,{"id"}) 
			retval = retval and p._getLink(retval)
		elseif dtype == "monolingualtext" then
			retval = fetchNested(dval,{"text"})
		elseif dtype == "commonsMedia" or dtype == "url" then
			retval = dval
		elseif dtype == "external-id" or dtype == "string" then
            dval = dval or ""
			if formaturl[pid] then
				retval = "[" .. mw.ustring.gsub(formaturl[pid], "$1", dval) .. " " .. dval .. "]"
			else
				retval = dval
			end
		elseif dtype == "time" then
            local date = fetchNested(prop,{"mainsnak"})
            local precision = fetchNested(dval,{"precision"})
			retval = _getDate(date, precision)
			if 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 = fetchNested(prop,{"mainsnak","datavalue","value","time"})
			end
		elseif dtype == "quantity" then
			local amount = tonumber(fetchNested(dval,{"amount"}))
			local unit = string.match(fetchNested(dval,{"unit"}) or "", "(Q%d+)" )
			if unit then
				if unit == colunit then -- unit matches default for this column, so do not display unit
					retval = amount
				else
					if amount and 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{ title = "cvt", args = {
								amount,
								unitsymbol[unit],
								unitsymbol[colunit],
								disp='number'}
							} .. mw.getCurrentFrame():expandTemplate{
								title="efn",
								args = {
									name = string.format(
										'Converted%s%s',
										unitsymbol[unit],
										unitsymbol[colunit]
									),
									[1] = string.format(
										'Change in units: quantity in %s has been automatically converted to %s for uniformity.',
										unit_label,
										colunit_label
									)
								}
							}
						else -- show unit and default conversion
							retval = mw.getCurrentFrame():expandTemplate{ title = "cvt", args = {amount, unitsymbol[unit]} }
						end
					else
						retval = (amount or "")  .. " " .. mw.wikibase.getLabel(unit)
					end
				end
			else
				retval = amount
			end
		elseif dtype == "globe-coordinate" then
            local precision = fetchNested(dval,{"precision"})
			local lat = fetchNested(dval,{"latitude"})
            local long = fetchNested(dval,{"longitude"})
            lat = lat and decimalprecision(lat, precision)
            long = long and decimalprecision(long, precision)
			retval = "<span style='font-size:90%;'>"
			.. mw.wikibase.formatValue(fetchNested(prop,{"mainsnak"}))
			.. "</span>"
		else
			retval = dval
		end
		-- get references
		retval = (retval or "") .. (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
					local qtbl2 = {}
					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
                            local precision = fetchNested(qv,{"datavalue","value","precision"})
							fqv = _getDate(qv, precision)
							if precision == 11 then -- trim to month
								fqv = fqv:match("%d+ (.+)")
							end
						else
							fqv = mw.wikibase.renderSnak(qv) -- plaintext
						end
						if fqv and fqv ~= "" then
							table.insert(qtbl2, (prefix[qpid] or "") .. fqv)
						end
					end
					table.insert(qtbl, table.concat(qtbl2, ' & ')) -- use ampersand to separate qualifiers of the same type
				end
			end
			if #qtbl > 0 then
				retval = retval .. "<span style='font-size:90%;'> (" .. table.concat(qtbl, ", ") .. ")</span>" -- use comma to separate qualifiers of different type
			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
	end
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 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+")
	-- 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{name = 'ref', args = {name = args.refname}}
	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 " .. linestyle .."><th scope='row' rowspan=" .. rows .. ">"
	if cellrep[1] and qid then
		out = out .. cellrep[1] .. createicon(qid) .. "</th>"
	elseif not qid then
		out = out .. (cellrep[1] or " ") .. "</th>"
	else
		out = out .. ucf(p._getLink(qid, args.ShowRedLinks and true or false)) .. (celladd[1] or "") .. createicon(qid) .. "</th>"
	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 .. '<td>' .. cellrep[c+1] .. '</td>'
		elseif not qid then
			out = out .. "<td></td>"
		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{name = mw.wikibase.sitelink(qid)}
				short_description = sdt.explicit or ''
			end
			out = out .. '<td style="text-align:center;">' .. short_description .. '</td>'
		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] = "[[File:" .. img .. "|100px]]"
					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 .. '<td ' .. sortkeyf .. 'style="text-align:center;">' .. table.concat(ptbl, sep2) .. (celladd[c+1] or "") .. '</td>'
		end
	end -- of loop through all of the cells in the row
	out = out .. "</tr>"
	if summary ~= "" then
		out = out .. "<tr><td colspan=".. cols .. ">" .. summary .. "</td></tr>"
	end
	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
	local isdoc
	if args.doc and args.doc=="no" then
		isdoc = false
	else
		isdoc = current_page:inNamespace(10)
	end
	if isdoc then
		args.qid = args.example
		return p.doc(args)
	else
		return p._makerow(args)
	end
end

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] = "{{" .. template .. "|qid=" .. qid.."<!-- "..rawarticle.." -->}}"
	 		else
	 			qidlist[#qidlist+1] = "{{" .. template .. "|qid=|c1="..rawarticle.."}}"
	 		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 .. "{{" .. template .. "|qid=" .. qid
		local label = mw.wikibase.getLabel(qid)
		if label then
			out = out .. "<!-- " .. label .. " -->"
		end
		out = out .. "}}\n"
	end
	return out
end

local function proplink(pid)
	local out
	if pid == "P1" then
		out = "Custom input"
	else
		out = mw.getCurrentFrame():expandTemplate{ title = 'Wikidata entity link', args = {pid} }
	end
	return out
end

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 = "[[" .. unit .. "|" .. unitsymbol[qid] .. "]]"
			else
				unit = unitsymbol[qid]
			end
			return " (in " .. unit .. ")"
		else
			return ""
		end
	end
	local base_page = current_page.subpageText=='sandbox' and current_page.basePageTitle.fullText or current_page.fullText
	local out = {'This template will retrieve certain data from [[Wikidata]] for use in a table in an article. '
		.. 'It is a wrapper template for [[Module:Wikidata table]] function <i>makerow</i>, using predefined properties.\n\n'
		.. (article and 'It was designed for use on [[' .. article .. ']] but may also be used on other articles. ([[Special:WhatLinksHere/' .. base_page .. '|Search]])\n' or '')
		.. '<h3>Usage</h3>'
		.. 'The data that is displayed in each column is as follows:<table class="wikitable"><tr>'
	}
	for c = 1,#pidtable+1 do
		table.insert(out, '<th>Column ' .. c .. '</th>')
	end
	table.insert(out, '</tr><tr><td>Label</td>')
	for c1 = 1,#pidtable do
		table.insert(out, '<td>')
		for c2 = 1,#pidtable[c1] do
			if pidtable[c1][c2].property=='SD' then
				table.insert(out, 'Short description')
			else
				table.insert(out, proplink(pidtable[c1][c2].property) .. unit(pidtable[c1][c2].unit))
				if pidtable[c1][c2].quals then
					table.insert(out, ' qualified by ')
					for c3 = 1,#pidtable[c1][c2].quals do
						table.insert(out, proplink(pidtable[c1][c2].quals[c3]))
					end
				end
			end
			table.insert(out, '<br>')
		end
		table.insert(out, '</td>')
	end
	table.insert(out, '</tr></table>')
	if qid then
		local sitelink = mw.wikibase.getSitelink(qid)
		table.insert(out, '<h3>Example</h3>The Wikidata QID for '
			.. (sitelink and '[['..sitelink..']]' or mw.wikibase.getLabel(qid))
			.. ' is [[:d:Special:EntityPage/' .. qid .. '|' .. qid .. ']]. Typing the following:<br>'
			.. '<code>{{' .. current_page.text .. '|qid=' .. qid .. '}}</code><br>produces'
			.. '<table class="wikitable"><tr><th>Name</th>'
		)
		for c = 1,#pidtable do
			local proplabel
			if pidtable[c][1].property == "P1" then
				proplabel = "Column " .. c+1
			elseif pidtable[c][1].property=='SD' then
				proplabel = 'Short description'
			else
				proplabel = currentlang:ucfirst(mw.wikibase.getLabel(pidtable[c][1].property)) .. unit(pidtable[c][1].unit)
			end
			table.insert(out, '<th>' .. proplabel .. '</th>')
		end
		table.insert(out, '</tr>' .. p._makerow(args) .. '</table>')
	end
	table.insert(out, '<h3>Notes</h3>\n'
		.. '* The table caption, column headings, etc. need to be added manually.\n'
		.. '* Please be careful about making changes to this template, as corresponding changes will need to be made to the column headings on '
	)
	table.insert(out,
		(article and '[['..article..']] and any other ' or 'any ')
		.. 'article using it. ([[Special:WhatLinksHere/' .. base_page .. '|Search]])\n'
		.. '<h3>Overriding columns</h3>'
		.. 'It is possible to override or append to data values obtained from Wikidata in any column in the table.\n'
		.. '* To completely override column <i>n</i> with some custom content, use parameter <code>cn=</code>\n'
		.. '*: For example, to replace column 5 with the number 1957 use <code>c5=1957</code>\n'
		.. '* To append some custom content to the end of column <i>n</i> use parameter <code>cn+=</code>\n'
		.. '*: For example, to add a footnote to column 6 use <code>c6+={{efn|This value is approximate.}}</code>\n'
		.. '<h3>Add named reference</h3>'
		.. 'If you [[Help:List-defined references|define references in a list]] then you can cite one of these by using the parameter <code>refname</code>. This will add a reference to column 1 directly after the label.\n'
		.. 'For example you can define a reference called Smith1 by using <pre><references>\n<ref name="Smith1">reference</ref>\n</references></pre>\n'
		.. "Then use <code>refname=Smith1</code>"
		.. (qid and '<h3>References</h3>'..mw.getCurrentFrame():expandTemplate{title='Reflist'} or '')
		.. (current_page.subpageText~='sandbox' and '[[Category:Wikidata table row templates|' .. current_page.subpageText .. ']]' or '')
		.. '<h3>TemplateData</h3>'
	)
	local td = '{"params": {"qid": {"label": "QID",	"description": "Enter the Wikidata QID, which is a number beginning with Q. You can also add the name of the item as an HTML comment.","example": "'
		.. 	(qid and qid..'<!-- '..mw.wikibase.getLabel(qid)..' -->' or 'Q1234567')
		.. '","type": "string","suggested": true}'
		.. ',"refname": {"label": "Add named reference","description": "Add a named reference defined in a list","type": "string","example": "ref1"}'
		.. ',"c1": {"label": "Override label","description": "Override the label (column 1) with this value","type": "content"}'
		.. ',"c1+": {"label": "Append to label","description": "Append this content to the label (column 1)","type": "content"}'
	for c = 1,#pidtable do
		if pidtable[c][1].property == "P1" then
			td = td .. ',"c' .. c+1 .. '": {"label": "Define column ' .. c+1 .. '","description": "Define column ' .. c+1 .. ' with this content","type": "content"}'
		elseif pidtable[c][1].property~='SD' then
			local label = mw.wikibase.getLabel(pidtable[c][1].property)
			td = td .. ',"c' .. c+1 .. '": {"label": "Override ' .. label .. '","description": "Override the ' .. label .. ' (column ' .. c+1 .. ') with this content","type": "content"}'
				.. ',"c' .. c+1 .. '+": {"label": "Append to ' .. label .. '","description": "Append this content to the ' .. label .. ' (column ' .. c+1 .. ')","type": "content"}'
		end
	end
	td = td .. '},"description": "This template reads some data from Wikidata while also allowing an editor to override or append their own content.","format": "inline"}'
	return documentation{content = table.concat(out) .. mw.getCurrentFrame():extensionTag{ name = 'templatedata', content = td}}
end

return p

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.