Přeskočit na obsah

Modul:Autoritní data

Tato stránka je zamčena
Z Wikipedie, otevřené encyklopedie
Tento modul závisí na dalších modulech:

Modul:Autoritní data je použit jako kostra k vytvoření šablony Autoritní data, její dokumentaci vizte na Šablona:Autoritní data/doc.

Kvůli vysokému počtu výskytů šablony je však potřeba před úpravami současného kódu nejprve důkladně otestovat kód nový. Pro testovací účely můžete využít pískoviště Modul:Autoritní data/pískoviště.

Modul byl převzat z anglické Wikipedie, dokumentaci vizte na en:Module:Authority control.

--
-- Tento modul implementuje {{Autoritní data}}
--

require ('strict')

local p = {}
local title = mw.title.getCurrentTitle()
local namespace = title.namespace
local testcases = (string.sub(title.subpageText,1,9) == 'testcases')

--[[==========================================================================]]
--[[                             Funkce kategorií                             ]]
--[[==========================================================================]]

function p.getCatForId( id )
	local catName = ''
	if namespace == 0 then
		catName = 'Články s identifikátorem ' .. id
	elseif namespace == 2 and not title.isSubpage then
		catName = 'Uživatelské stránky s identifikátorem ' .. id
	else
		catName = 'Ostatní stránky s identifikátorem ' .. id
	end
	catName = 'Monitoring:' .. catName
	return '[[Kategorie:'..catName..']]'..p.redCatLink(catName)
end

function p.redCatLink( catName ) --catName == 'Blah' (not 'Category:Blah', not '[[Category:Blah]]')
	if catName and catName ~= '' and
	   testcases == false and
	   mw.title.new(catName, 14).exists == false
	then
		return '[[Kategorie:Údržba:Nezaložené kategorie autoritní kontroly]]'
	end
	return ''
end

function p.createRow( id, label, rawValues, link, links, withUid, specialCat )
	local catName = 'Údržba:Články s neplatným identifikátorem ' .. (specialCat or id)
	if links then -- all links[] use withUid = false; no check needed
		local row = '*<span class="nowrap">'..label
		local totlen = 0
		for i, l in ipairs( links ) do
			if i == 1 then row = row..' '
			else           row = row..', ' end
			if l then
				row = row..'<span class="uid">'..l..'</span>'
			else
				row = row..'<span class="error">Id '..rawValues[i]..' identifikátoru '..id..' není platné.</span>[[Kategorie:'..catName..']]'..p.redCatLink(catName)
			end
			totlen = totlen + #rawValues[i] + 3 -- 3 chars b/w links
		end
		if totlen > 79 then
			row = string.gsub(row, '"nowrap"', '""') -- avoid [[A–Z Series]]
		end
		return row..'</span>\n'
	elseif link then
		if withUid then
			return '*<span class="nowrap">'..label..' <span class="uid">'..link..'</span></span>\n'
		end
		return '*<span class="nowrap">'..label..' '..link..'</span>\n'
	end
	
	return '* <span class="error">Id '..rawValues..' identifikátoru '..id..' není platné.</span>[[Kategorie:'..catName..']]'..p.redCatLink(catName)..'\n'
end

--[[==========================================================================]]
--[[                      Funkce formátování vlastností                       ]]
--[[==========================================================================]]

-- If a link has a suitable entry in the global inter-wiki prefix table at [[:m:Interwiki_map]], please consider routing through this prefix rather than as external link URL. This will ease future maintenance as necessary updates to the link can be centrally carried out there rather than by updating this module. The "external link" icon would disappear for such entries.

function p.aagLink( id )
	--P3372's format regex: \d+ (e.g. 1)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[https://www.aucklandartgallery.com/explore-art-and-ideas/artist/'..id..'/ '..id..']'..p.getCatForId( 'AAG' )
end

function p.abartpLink( id )
	--P6844's format regex: ([1-2]\d{5}|[1-9]\d{0,4}) (e.g. 19905)
	if not id:match( '^[1-2]%d%d%d%d%d$' ) and
	   not id:match( '^[1-9]%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://cs.isabart.org/person/'..id..' '..id..']'..p.getCatForId( 'AbART osoba' ) --speciální název kategorie
end

function p.abarteLink( id )
	--P6846's format regex: ([1-2]\d{5}|[1-9]\d{0,4}) (e.g. 28605)
	if not id:match( '^[1-2]%d%d%d%d%d$' ) and
	   not id:match( '^[1-9]%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://cs.isabart.org/exhibition/'..id..' '..id..']'..p.getCatForId( 'AbART událost' ) --speciální název kategorie
end

function p.abartgLink( id )
	--P6847's format regex: (1[0-4]\d{3}|[1-9]\d{0,3}) (e.g. 4628)
	if not id:match( '^1[0-4]%d%d%d$' ) and
	   not id:match( '^[1-9]%d?%d?%d?$' ) then
		return false
	end
	return '[https://cs.isabart.org/group/'..id..' '..id..']'..p.getCatForId( 'AbART skupina' ) --speciální název kategorie
end

function p.abartiLink( id )
	--P6848's format regex: [1-9]\d{0,4} (e.g. 1576)
	if not id:match( '^[1-9]%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://cs.isabart.org/institution/'..id..' '..id..']'..p.getCatForId( 'AbART instituce' ) --speciální název kategorie
end

function p.acmLink( id )
	--P864's format regex: \d{11} (e.g. 12345678901)
	if not id:match( '^%d%d%d%d%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[https://dl.acm.org/profile/'..id..' '..id..']'..p.getCatForId( 'ACM-DL' )
end

function p.adbLink( id )
	--P1907's format regex: [a-z][-a-z]+-([1-3]\d|[1-9])\d{0,3} (e.g. barton-sir-edmund-toby-71)
	if not id:match( '^[a-z][-a-z]+-[1-3]%d%d?%d?%d?$' ) and
	   not id:match( '^[a-z][-a-z]+-[1-9]%d?%d?%d?$' ) then
		return false
	end
	return '[http://adb.anu.edu.au/biography/'..id..' '..id..']'..p.getCatForId( 'ADB' )
end

function p.agsaLink( id )
	--P6804's format regex: [1-9]\d* (e.g. 3625)
	if not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[https://www.agsa.sa.gov.au/collection-publications/collection/creators/_/'..id..'/ '..id..']'..p.getCatForId( 'AGSA' )
end

function p.autoresuyLink( id )
	--P2558's format regex: [1-9]\d{0,4} (e.g. 12345)
	if not id:match( '^[1-9]%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://autores.uy/autor/'..id..' '..id..']'..p.getCatForId( 'autores.uy' )
end

function p.awrLink( id )
	--P4186's format regex: (([A-Z]{3}\d{4})|([A-Z]{2}\d{5}))[a-z] (e.g. PR00768b)
	if not id:match( '^[A-Z][A-Z][A-Z]%d%d%d%d[a-z]$' ) and
	   not id:match( '^[A-Z][A-Z]%d%d%d%d%d[a-z]$' ) then
		return false
	end
	return '[http://www.womenaustralia.info/biogs/'..id..'.htm '..id..']'..p.getCatForId( 'AWR' )
end

function p.biblioLink( id )
	--P9037's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	return '[https://biblio.hiu.cas.cz/records/'..id..' '..id..']'..p.getCatForId( 'Biblio' )
end

function p.bibsysLink( id )
	--P1015's format regex: [1-9]\d* or [1-9](\d{0,8}|\d{12}) (e.g. 1234567890123)
	--TODO: follow up @ [[d:Property talk:P1015#Discrepancy between the 2 regex constraints]] or escalate/investigate
	if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?%d?$' ) and
	   not id:match( '^[1-9]%d%d%d%d%d%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[https://authority.bibsys.no/authority/rest/authorities/html/'..id..' '..id..']'..p.getCatForId( 'BIBSYS' )
end

function p.bildLink( id )
	--P12754's format regex: \d+ (e.g. 1)
	if not id:match( '^000%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[https://id.bildindex.de/thing/'..id..' '..id..']'..p.getCatForId( 'Bildindex' )
end

function p.bncLink( id )
	--P1890's format regex: \d{9} (e.g. 123456789)
	if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[http://www.bncatalogo.cl/F?func=direct&local_base=red10&doc_number='..id..' '..id..']'..p.getCatForId( 'BNC' )
end

function p.bneLink( id )
	--P950's format regex: (XX|FF|a)\d{4,7}|(bima|bimo|bica|bis[eo]|bivi|Mise|Mimo|Mima)\d{10} (e.g. XX1234567)
	if not id:match( '^[XF][XF]%d%d%d%d%d?%d?%d?$' ) and
	   not id:match( '^a%d%d%d%d%d?%d?%d?$' ) and
	   not id:match( '^bi[mcsv][aoei]%d%d%d%d%d%d%d%d%d%d$' ) and
	   not id:match( '^Mi[sm][eoa]%d%d%d%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[http://catalogo.bne.es/uhtbin/authoritybrowse.cgi?action=display&authority_id='..id..' '..id..']'..p.getCatForId( 'BNE' ) --no https as of 9/2019
end

function p.bnfLink( id )
	--P268's format regex: \d{8}[0-9bcdfghjkmnpqrstvwxz] (e.g. 123456789)
	if not id:match( '^c?b?%d%d%d%d%d%d%d%d[0-9bcdfghjkmnpqrstvwxz]$' ) then
		return false
	end
	--Add cb prefix if it has been removed
	if not id:match( '^cb.+$' ) then
		id = 'cb'..id
	end
	return '[https://catalogue.bnf.fr/ark:/12148/'..id..' '..id..'] [https://data.bnf.fr/ark:/12148/'..id..' (data)]'..p.getCatForId( 'BNF' )
end

function p.botanistLink( id )
	--P428's format regex: ('t )?(d')?(de )?(la )?(van (der )?)?(Ma?c)?(De)?(Di)?\p{Lu}?C?['\p{Ll}]*([-'. ]*(van )?(y )?(d[ae][nr]?[- ])?(Ma?c)?[\p{Lu}bht]?C?['\p{Ll}]*)*\.? ?f?\.? (e.g. L.)
	--not easily/meaningfully implementable in Lua's regex since "(this)?" is not allowed...
	if not mw.ustring.match( id, "^[%u%l%d%. '-]+$" ) then --better than nothing
		return false
	end
	local id2 = id:gsub(' +', '%%20')
	return '[https://www.ipni.org/ipni/advAuthorSearch.do?find_abbreviation='..id2..' '..id..']'..p.getCatForId( 'Botanist' )
end

function p.bpnLink( id )
	--P651's format regex: \d{6,8} (e.g. 00123456)
	if not id:match( '^%d%d%d%d%d%d%d%d$' ) and --original format regex, changed 8/2019 to
	   not id:match( '^0?%d%d%d%d%d%d%d$' ) and --allow 1-2 leading 0s, allowed by the website
	   not id:match( '^0?0?%d%d%d%d%d%d$' ) then
		return false
	end
	return '[http://www.biografischportaal.nl/persoon/'..id..' '..id..']'..p.getCatForId( 'BPN' ) --no https as of 9/2019
end

function p.canticLink( id )
	--P9984's format regex: 981(0|1)\d{9}06706 (e.g. 981058515460906706)
	if not id:match( '^981[0-1]%d%d%d%d%d%d%d%d%d06706$' ) then
		return false
	end
	return '[https://cantic.bnc.cat/registre/'..id..' '..id..']'..p.getCatForId( 'CANTIC' )
end

function p.ciniiLink( id )
	--P271's format regex: D[AB]\d{7}[\dX] (e.g. DA12345678)
	if not id:match( '^D[AB]%d%d%d%d%d%d%d[%dX]$' ) then
		return false
	end
	return '[https://ci.nii.ac.jp/author/'..id..'?l=en '..id..']'..p.getCatForId( 'CINII' )
end

function p.cwgcLink( id )
	--P1908's format regex: [1-9]\d* (e.g. 75228351)
	if not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[https://www.cwgc.org/find-war-dead/casualty/'..id..'/ '..id..']'..p.getCatForId( 'CWGC' )
end

function p.daaoLink( id )
	--P1707's format regex: [a-z\-]+\d* (e.g. rolf-harris)
	if not id:match( '^[a-z%-]+%d*$' ) then
		return false
	end
	return '[https://www.daao.org.au/bio/'..id..' '..id..']'..p.getCatForId( 'DAAO' )
end

function p.dblpLink( id )
	--P2456's format regex: \d{2,3}\/\d+(-\d+)?[a-zA-Z-]*(-\d+)?|[a-z]\/[0-9A-Za-z]*(-\d+)? (e.g. 89/4185-p)
	if not id:match( '^%d%d%d?%/%d+-?[%d]*[%a]*-?[%d]*$' ) and
	   not id:match( '^[%a]+%/[%w]*-?[%d]*$' ) then
		return false
	end
	return '[https://dblp.org/pid/'..id..' '..id..']'..p.getCatForId( 'DBLP' )
end

function p.dibLink( id )
	--P6829's format regex: 0[01]\d{4}(\.[A-D])? (e.g. 001953)
	if not id:match( '^0[01]%d%d%d%d%.?[A-D]?$' ) then
		return false
	end
	return '[https://doi.org/10.3318/dib.'..id..'.v1 '..id..']'..p.getCatForId( 'DIB' )
end

function p.dsiLink( id )
	--P2349's format regex: [1-9]\d* (e.g. 1538)
	if not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[http://www.uni-stuttgart.de/hi/gnt/dsi2/index.php?table_name=dsi&function=details&where_field=id&where_value='..id..' '..id..']'..p.getCatForId( 'DSI' )
end

function p.fnzaLink( id )
	--P6792's format regex: [1-9]\d* (e.g. 9785)
	if not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[https://findnzartists.org.nz/artist/'..id..'/ '..id..']'..p.getCatForId( 'FNZA' )
end

function p.gndLink( id )
	--P227's format regex: 1[012]?\d{7}[0-9X]|[47]\d{6}-\d|[1-9]\d{0,7}-[0-9X]|3\d{7}[0-9X] (e.g. 4079154-3)
	if not id:match( '^1[0123]?%d%d%d%d%d%d%d[0-9X]$' ) and
	   not id:match( '^[47]%d%d%d%d%d%d%-%d$' ) and
	   not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?%-[0-9X]$' ) and
	   not id:match( '^3%d%d%d%d%d%d%d[0-9X]$' ) then
		return false
	end
	return '[https://d-nb.info/gnd/'..id..' '..id..']'..p.getCatForId( 'GND' )
end

function p.googleLink( id )
	--P1960's format regex: [-_0-9A-Za-z]{12} (e.g. CUO0vDcAAAAJ)
	if not id:match( '^[%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u][%-_%d%l%u]$' ) then
		return false
	end
	return '[https://scholar.google.com/citations?user='..id..' '..id..']'..p.getCatForId( 'Google Scholar' )
end

function p.hdsLink( id )
	--P902's format regex: \d{6} (e.g. 050123)
	if not id:match( '^%d%d%d%d%d%d$' ) then
		return false
	end
	return '[https://hls-dhs-dss.ch/fr/articles/'..id..' '..id..']'..p.getCatForId( 'HDS' )
end

function p.iaafLink( id )
	--P1146's format regex: [0-9][0-9]* (e.g. 012)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[https://www.iaaf.org/athletes/_/'..id..' '..id..']'..p.getCatForId( 'IAAF' )
end

function p.iciaLink( id )
	--P1736's format regex: \d+ (e.g. 1)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[https://www.imj.org.il/artcenter/newsite/en/?artist='..id..' '..id..']'..p.getCatForId( 'ICIA' )
end

function p.ieuLink( id )
	--P9070's format regex: [A-Z]\\[A-Z]\\[A-Za-z0-9]+ (e.g. K\Y\Kyiv)
	if not id:match( '^[A-Z]\\[A-Z]\\%w+$' ) then
		return false
	end
	return '[http://www.encyclopediaofukraine.com/display.asp?linkpath=pages\\'..id..' '..id..']'..p.getCatForId( 'IEU' )
end

function p.isniLink( id )
	id = p.validateIsni( id ) --e.g. 0000-0000-6653-4145
	if not id then
		return false
	end
	return '[https://isni.org/isni/'..id..' '..id:sub( 1, 4 )..' '..id:sub( 5, 8 )..' '..id:sub( 9, 12 )..' '..id:sub( 13, 16 )..']'..p.getCatForId( 'ISNI' ) --no https as of 9/2019
end

function p.jocondeLink( id )
	--P347's format regex: [\-0-9A-Za-z]{11} (e.g. 12345678901)
	local regex = '^'..string.rep('[%-0-9A-Za-z]', 11)..'$'
	if not id:match( regex ) then
		return false
	end
	return '[https://www.pop.culture.gouv.fr/notice/joconde/'..id..' '..id..']'..p.getCatForId( 'Joconde' )
end

function p.kulturnavLink( id )
	--P1248's format regex: [0-9a-f]{8}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	return '[http://kulturnav.org/'..id..' '..id..']'..p.getCatForId( 'KulturNav' ) --no https as of 9/2019
end

function p.lccnLink( id )
	local parts = p.splitLccn( id ) --e.g. n78039510
	if not parts then
		return false
	end
	local lccnType = parts[1] ~= 'sh' and 'names' or 'subjects'
	id = parts[1] .. parts[2] .. p.append( parts[3], '0', 6 )
	return '[https://id.loc.gov/authorities/'..lccnType..'/'..id..' '..id..']'..p.getCatForId( 'LCCN' )
end

function p.legieLink( id )
	--P9695's format regex: [1-9][0-9]+ (e.g. 13685)
	if not id:match( '^[1-9]%d+$' ) then
		return false
	end
	return '[http://legie100.com/krev-legionare/'..id..'/ '..id..']'..p.getCatForId( 'Legie 100' )
end

function p.lirLink( id )
	--P886's format regex: \d+ (e.g. 1)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[http://www.e-lir.ch/e-LIR___Lexicon.'..id..'.450.0.html '..id..']'..p.getCatForId( 'LIR' ) --no https as of 9/2019
end

function p.lnbLink( id )
	--P1368's format regex: \d{9} (e.g. 123456789)
	if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[https://kopkatalogs.lv/F?func=direct&local_base=lnc10&doc_number='..id..'&P_CON_LNG=ENG '..id..']'..p.getCatForId( 'LNB' )
end

function p.mbaLink( id )
	--P434's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	return '[https://musicbrainz.org/artist/'..id..' '..id..']'..p.getCatForId( 'MusicBrainz' ) --speciální název kategorie
end

function p.mbareaLink( id )
	--P982's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	return '[https://musicbrainz.org/area/'..id..' '..id..']'..p.getCatForId( 'MusicBrainz oblast' ) --speciální název kategorie
end

function p.mbiLink( id )
	--P1330's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	return '[https://musicbrainz.org/instrument/'..id..' '..id..']'..p.getCatForId( 'MusicBrainz hudební nástroj' ) --speciální název kategorie
end

function p.mblLink( id )
	--P966's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	return '[https://musicbrainz.org/label/'..id..' '..id..']'..p.getCatForId( 'MusicBrainz hudební vydavatelství' ) --speciální název kategorie
end

function p.mbpLink( id )
	--P1004's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	return '[https://musicbrainz.org/place/'..id..' '..id..']'..p.getCatForId( 'MusicBrainz místo' ) --speciální název kategorie
end

function p.mbrgLink( id )
	--P436's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	return '[https://musicbrainz.org/release-group/'..id..' '..id..']'..p.getCatForId( 'MusicBrainz skupina vydání alba' ) --speciální název kategorie
end

function p.mbsLink( id )
	--P1407's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	return '[https://musicbrainz.org/series/'..id..' '..id..']'..p.getCatForId( 'MusicBrainz řada' ) --speciální název kategorie
end

function p.mbwLink( id )
	--P435's format regex: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} (e.g. 12345678-1234-1234-1234-1234567890AB)
	if not id:match( '^%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x$' ) then
		return false
	end
	return '[https://musicbrainz.org/work/'..id..' '..id..']'..p.getCatForId( 'MusicBrainz dílo' ) --speciální název kategorie
end

function p.mgpLink( id )
	--P549's format regex: \d{1,6} (e.g. 123456)
	if not id:match( '^%d%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://genealogy.math.ndsu.nodak.edu/id.php?id='..id..' '..id..']'..p.getCatForId( 'MGP' )
end

function p.naraLink( id )
	--P1225's format regex: ^([1-9]\d{0,8})$ (e.g. 123456789)
	if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://catalog.archives.gov/id/'..id..' '..id..']'..p.getCatForId( 'NARA' )
end

function p.nclLink( id )
	--P1048's format regex: \d+ (e.g. 1081436)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[http://aleweb.ncl.edu.tw/F/?func=accref&acc_sequence='..id..'&CON_LNG=ENG '..id..']'..p.getCatForId( 'NCL' ) --no https as of 9/2019
end

function p.ndlLink( id )
	--P349's format regex: (a1|s)?[0-9]?\d{8} (e.g. a1100016921)
	if not id:match( '^a1%d?%d%d%d%d%d%d%d%d' ) and
	   not id:match( '^s?%d?%d%d%d%d%d%d%d%d' ) then
		return false
	end
	return '[https://id.ndl.go.jp/auth/ndlna/'..id..' '..id..']'..p.getCatForId( 'NDL' )
end

function p.ngvLink( id )
	--P2041's format regex: \d+ (e.g. 12354)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[https://www.ngv.vic.gov.au/explore/collection/artist/'..id..'/ '..id..']'..p.getCatForId( 'NGV' )
end

function p.nkcLink( id )
	--P691's format regex: [a-z]{2,4}[0-9]{2,14} (e.g. abcd12345678901234)
	if not id:match( '^[a-z][a-z][a-z]?[a-z]?%d%d%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://aleph.nkp.cz/F/?func=find-c&local_base=aut&ccl_term=ica='..id..' '..id..']'..p.getCatForId( 'NKC' )
end

function p.nlaLink( id )
	--P409's format regex: [1-9][0-9]{0,11} (e.g. 123456789012)
	if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://nla.gov.au/anbd.aut-an'..id..' '..id..']'..p.getCatForId( 'NLA' )
end

function p.nlgLink( id )
	--P3348's format regex: [1-9]\d* (e.g. 1)
	if not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[https://catalogue.nlg.gr/cgi-bin/koha/opac-authoritiesdetail.pl?authid='..id..' '..id..']'..p.getCatForId( 'NLG' )
end

function p.nliLink( id )
	--P8189's format regex: 9870(0|1)\d{8}05171 (e.g. 987007305652505171)
	if not id:match( '^9870[0-1]%d%d%d%d%d%d%d%d05171$' ) then
		return false
	end
	return '[http://olduli.nli.org.il/F/?func=find-b&local_base=NLX10&find_code=UID&request='..id..' '..id..']'..p.getCatForId( 'NLI' )
end

function p.nlkLink( id )
	--P5034's format regex: (KAB|KAC|KSH)([0-9]{4}|[0-9]{4}[a-zA-Z])[0-9]{4,6} (e.g. KAC201501465)
	if not id:match( '^KAB%d%d%d%d%a?%d%d%d%d%d?%d?$' ) and
		not id:match( '^KAC%d%d%d%d%a?%d%d%d%d%d?%d?$' ) and
		not id:match( '^KSH%d%d%d%d%a?%d%d%d%d%d?%d?$' ) then
		return false
	end
	return '[https://librarian.nl.go.kr/LI/contents/L20101000000.do?id='..id..' '..id..']'..p.getCatForId( 'NLK' )
end

function p.nlpLink( id )
	--P1695's format regex: a[0-9]{13} (e.g. a0000001650567)
	if not id:match( '^9810%d+$' ) and                               -- staré, ponecháno kvůli počtu výskytů
	   not id:match( '^A%d%d%d%d%d%d%d[%dX]$' ) and                  -- staré, ponecháno kvůli počtu výskytů
	   not id:match( '^a%d%d%d%d%d%d%d%d%d%d%d%d%d$' ) then
	   return false
	end
	return '[https://dbn.bn.org.pl/descriptor-details/'..id..' '..id..']'..p.getCatForId( 'NLP' )
end

function p.nlrLink( id )
	--P1003's format regex: \d{9} (e.g. 123456789)
	if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[http://aleph.bibnat.ro:8991/F/?func=direct&local_base=NLR10&doc_number='..id..' '..id..']'..p.getCatForId( 'NLR' )
end

function p.nskLink( id )
	--P1375's format regex: \d{9} (e.g. 123456789)
	if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[http://katalog.nsk.hr/F/?func=direct&doc_number='..id..'&local_base=nsk10 '..id..']'..p.getCatForId( 'NSK' ) --no https as of 9/2019
end

function p.ntaLink( id )
	--P1006's format regex: \d{8}[\dX] (e.g. 12345678X)
	if not id:match( '^%d%d%d%d%d%d%d%d[%dX]$' ) then
		return false
	end
	return '[http://data.bibliotheken.nl/id/thes/p'..id..' '..id..']'..p.getCatForId( 'NTA' )
end

function p.orcidLink( id )
	id = p.validateIsni( id ) --e.g. 0000-0002-7398-5483
	if not id then
		return false
	end
	id = id:sub( 1, 4 )..'-'..id:sub( 5, 8 )..'-'..id:sub( 9, 12 )..'-'..id:sub( 13, 16 )
	return '[https://orcid.org/'..id..' '..id..']'..p.getCatForId( 'ORCID' )
end

function p.plwabnLink( id )
	--P7293's format regex: 981[0-9]{8}05606 (e.g. 9810696457305606)
	if not id:match( '^981%d%d%d%d%d%d%d%d05606*$' ) then
		return false
	end
	return '[https://dbn.bn.org.pl/descriptor-details/'..id..' '..id..']'..p.getCatForId( 'PLWABN' )
end

function p.publonsLink( id )
	--P3829's format regex: \d+ (e.g. 654601)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[https://publons.com/author/'..id..'/ '..id..']'..p.getCatForId( 'Publons' )
end

function p.picLink( id )
	--P2750's format regex: [1-9]\d* (e.g. 1)
	if not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[https://pic.nypl.org/constituents/'..id..' '..id..']'..p.getCatForId( 'PIC' )
end

function p.pshLink( id )
	--P1051's format regex: [1-9]\d* (e.g. 1796130)
	if not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[https://psh.techlib.cz/skos/PSH'..id..' '..id..']'..p.getCatForId( 'PSH' )
end

function p.ridLink( id )
	--P1053's format regex: [A-Z]{1,3}-\d{4}-(19|20)\d\d (e.g. AAS-5150-2020)
	if not id:match( '^[A-Z][A-Z]?[A-Z]?%-%d%d%d%d%-19%d%d$' ) and
	   not id:match( '^[A-Z][A-Z]?[A-Z]?%-%d%d%d%d%-20%d%d$' ) then
		return false
	end
	return '[https://www.webofscience.com/wos/author/record/'..id..' '..id..']'..p.getCatForId( 'RID' )
end

function p.rkdartistsLink( id )
	--P650's format regex: [1-9]\d{0,5} (e.g. 123456)
	if not id:match( '^[1-9]%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://rkd.nl/en/explore/artists/'..id..' '..id..']'..p.getCatForId( 'RKDartists' )
end

function p.rkdimagesLink( id )
	--P350's format regex: [1-9]\d{0,5} (e.g. 123456)
	if not id:match( '^[1-9]%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://rkd.nl/nl/explore/images/'..id..' '..id..']'..p.getCatForId( 'RKDimages' )
end

function p.rslLink( id )
	--P947's format regex: \d{1,9} (e.g. 123456789)
	if not id:match( '^%d%d?%d?%d?%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[http://aleph.rsl.ru/F?func=find-b&find_code=SYS&adjacent=Y&local_base=RSL11&request='..id..'&CON_LNG=ENG '..id..']'..p.getCatForId( 'RSL' ) --no https as of 9/2019
end

function p.scopusLink( id )
	--P1153's format regex: [1-9]\d{9,10} (e.g. 35247902700)
	if not id:match( '^[1-9]%d%d%d%d%d%d%d%d%d%d?$' ) then
		return false
	end
	return '[https://www.scopus.com/authid/detail.uri?authorId='..id..' '..id..']'..p.getCatForId( 'Scopus' )
end

function p.iccuLink( id )
	--P396's format regex: \D{2}[A-Z0-3]V\d{6} (e.g. CFIV000163)
	if not id:match( '^%u%u[%u0-3]V%d%d%d%d%d%d$' ) then --legacy: %u used here instead of %D (but the faulty ID cat is empty, out of ~12k uses)
		return false
	end
	return '[https://opac.sbn.it/nome/'..id..' '..id..']'..p.getCatForId( 'ICCU' )
end

function p.selibrLink( id )
	--P906's format regex: [1-9]\d{4,5} (e.g. 123456)
	if not id:match( '^[1-9]%d%d%d%d%d?$' ) then
		return false
	end
	return '[https://libris.kb.se/auth/'..id..' '..id..']'..p.getCatForId( 'SELIBR' )
end

function p.sikartLink( id )
	--P781's format regex: \d{7,9} (e.g. 123456789)
	if not id:match( '^%d%d%d%d%d%d%d%d?%d?$' ) then
		return false
	end
	return '[http://www.sikart.ch/KuenstlerInnen.aspx?id='..id..'&lng=en '..id..']'..p.getCatForId( 'SIKART' ) --no https as of 9/2019
end

function p.snacLink( id )
	--P3430's format regex: \d*[A-Za-z][0-9A-Za-z]* (e.g. A)
	if not id:match( '^%d*[A-Za-z][0-9A-Za-z]*$' ) then
		return false
	end
	return '[https://snaccooperative.org/ark:/99166/'..id..' '..id..']'..p.getCatForId( 'SNAC-ID' )
end

function p.snkLink( id )
	--P9807's format regex: [1-9]\d{0,6} (e.g. 146640)
	if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://autority.snk.sk/cgi-bin/koha/opac-authoritiesdetail.pl?marc=1&authid='..id..' '..id..']'..p.getCatForId( 'SNK' )
end

function p.sudocLink( id )
	--P269's format regex: (\d{8}[\dX]|) (e.g. 026927608)
	if not id:match( '^%d%d%d%d%d%d%d%d[%dxX]$' ) then --legacy: allow lowercase 'x'
		return false
	end
	return '[https://www.idref.fr/'..id..' '..id..']'..p.getCatForId( 'SUDOC' )
end

function p.ta98Link( id )
	--P1323's format regex: A\d{2}\.\d\.\d{2}\.\d{3}[FM]? (e.g. A12.3.45.678)
	if not id:match( '^A%d%d%.%d%.%d%d%.%d%d%d[FM]?$' ) then
		return false
	end
	return '[http://tools.wmflabs.org/wikidata-externalid-url/?p=1323&url_prefix=https:%2F%2Fwww.unifr.ch%2Fifaa%2FPublic%2FEntryPage%2FTA98%20Tree%2FEntity%20TA98%20EN%2F&url_suffix=%20Entity%20TA98%20EN.htm&id='..id..' '..id..']'..p.getCatForId( 'TA98' )
end

function p.tdkivLink( id )
	--P5398's format regex: \d{9} (e.g. 123456789)
	if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[http://aleph.nkp.cz/F/?func=direct&doc_number='..id..'&local_base=KTD '..id..']'..p.getCatForId( 'TDKIV' )
end

function p.tdviaLink( id )
	--P7314's format regex: [0-9a-z/-]+] (e.g. barkan-omer-lutfi)
	if not id:match( '^[%d%l/-]+$' ) then
		return false
	end
	return '[https://islamansiklopedisi.org.tr/'..id..' '..id..']'..p.getCatForId( 'TDVİA' )
end

function p.tepapaLink( id )
	--P3544's format regex: \d+ (e.g. 1)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[https://collections.tepapa.govt.nz/agent/'..id..' '..id..']'..p.getCatForId( 'TePapa' )
end

function p.tlsLink( id )
	id = id:gsub(' +', '_')
	--P1362's format regex: \p{Lu}[\p{L}\d_',\.\-\(\)\*\/–&]{3,89} (e.g. Abcd)
	--Mediawiki page title partial URL so consider validation with mw.title or "[^#<>%[%] {|}]"
	local class = "[%w_',%.%-%(%)%*%/–&]"
	local idlen = mw.ustring.len (id)
	if idlen < 4 or idlen > 90 then
		return false
	end
	local regex = '^%u'..string.rep(class, idlen - 1)..'$'
	if not mw.ustring.match( id, regex ) then
		return false
	end
	return '[http://tls.theaterwissenschaft.ch/wiki/'..id..' '..id..']'..p.getCatForId( 'TLS' ) --no https as of 9/2019
end

function p.troveLink( id )
	--P1315's format regex: [1-9]\d{5,7} (e.g. 12345678)
	if not id:match( '^[1-9]%d%d%d%d%d%d?%d?$' ) then
		return false
	end
	return '[https://trove.nla.gov.au/people/'..id..' '..id..']'..p.getCatForId( 'Trove' )
end

function p.ukparlLink( id )
	--P6213's format regex: [a-zA-Z\d]{8} (e.g. AQUupyiR)
	if not id:match( '^[a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d][a-zA-Z%d]$' ) then
		return false
	end
	return '[https://id.parliament.uk/'..id..' '..id..']'..p.getCatForId( 'UKPARL' )
end

function p.ulanLink( id )
	--P245's format regex: 500\d{6} (e.g. 500123456)
	if not id:match( '^500%d%d%d%d%d%d$' ) then
		return false
	end
	return '[https://www.getty.edu/vow/ULANFullDisplay?find=&role=&nation=&subjectid='..id..' '..id..']'..p.getCatForId( 'ULAN' )
end

function p.uscongressLink( id )
	--P1157's format regex: [A-Z]00[01]\d{3} (e.g. A000123)
	if not id:match( '^[A-Z]00[01]%d%d%d$' ) then
		return false
	end
	return '[http://bioguide.congress.gov/scripts/biodisplay.pl?index='..id..' '..id..']'..p.getCatForId( 'USCongress' ) --no https as of 9/2019
end

function p.vcbaLink( id )
	--P8034's format regex: \d{3}\/[1-9]\d{0,5} (e.g. 494/9793)
	if not id:match( '^%d%d%d/[1-9]%d?%d?%d?%d?%d?$' ) then
		return false
	end
	local id2 = id:gsub('/', '_')
	return '[https://opac.vatlib.it/auth/detail/'..id2..' '..id..']'..p.getCatForId( 'VcBA' )
end

function p.viafLink( id )
	--P214's format regex: [1-9]\d(\d{0,7}|\d{17,20}) (e.g. 123456789, 1234567890123456789012)
	if not id:match( '^[1-9]%d%d?%d?%d?%d?%d?%d?%d?$' ) and
	   not id:match( '^[1-9]%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d?%d?%d?$' ) then
	   return false
	end
	-- If the "VIAF" entry at [[:m:Interwiki map]] would resolve to "https://viaf.org/viaf/$1" (rather than "http://viaf.org/viaf/$1", as it currently still does), the code below could change from '[https://viaf.org/viaf/'..id..' '..id..']' to '[[:VIAF:'..id..'|'..id..']]'.
	return '[https://viaf.org/viaf/'..id..' '..id..']'..p.getCatForId( 'VIAF' )
end

function p.worldcatLink( id )
	if not id:match( '^%w%w%w%w%w%w%w%w%w%w%w%w%w%w%w%w%w%w%w%w%w%w%w%w%w%w$' ) and
	   not id:match( '^[QP][1-9]%d*' ) then
	   return false
	end
	return '[https://id.oclc.org/worldcat/entity/'..id..' '..id..']'..p.getCatForId( 'WorldCat Entities' )
end
	
--[[=========================== Pomocné funkce =============================]]

function p.append(str, c, length)
	while str:len() < length do
		str = c .. str
	end
	return str
end

--Returns the ISNI check digit isni must be a string where the 15 first elements are digits, e.g. 0000000066534145
function p.getIsniCheckDigit( isni )
	local total = 0
	for i = 1, 15 do
		local digit = isni:byte( i ) - 48 --Get integer value
		total = (total + digit) * 2
	end
	local remainder = total % 11
	local result = (12 - remainder) % 11
	if result == 10 then
		return "X"
	end
	return tostring( result )
end

--Validate ISNI (and ORCID) and retuns it as a 16 characters string or returns false if it's invalid
--See http://support.orcid.org/knowledgebase/articles/116780-structure-of-the-orcid-identifier
function p.validateIsni( id )
	--P213 (ISNI) format regex: [0-9]{4} [0-9]{4} [0-9]{4} [0-9]{3}[0-9X] (e.g. 0000-0000-6653-4145)
	--P496 (ORCID) format regex: 0000-000(1-[5-9]|2-[0-9]|3-[0-4])\d{3}-\d{3}[\dX] (e.g. 0000-0002-7398-5483)
	id = id:gsub( '[ %-]', '' ):upper()
	if not id:match( '^%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d[%dX]$' ) then
		return false
	end
	if p.getIsniCheckDigit( id ) ~= string.char( id:byte( 16 ) ) then
		return false
	end
	return id
end

function p.splitLccn( id )
	--P244's format regex: (n|nb|nr|no|ns|sh)([4-9][0-9]|00|20[0-1][0-9])[0-9]{6} (e.g. n78039510)
	if id:match( '^%l%l?%l?%d%d%d%d%d%d%d%d%d?%d?$' ) then
		id = id:gsub( '^(%l+)(%d+)(%d%d%d%d%d%d)$', '%1/%2/%3' )
	end
	if id:match( '^%l%l?%l?/%d%d%d?%d?/%d+$' ) then
		return mw.text.split( id, '/' )
	end
	return false
end

--[[==========================================================================]]
--[[                          Wikidata a dokumentace                          ]]
--[[==========================================================================]]

function p.getIdsFromWikidata( itemId, property )
	local ids = {}
	local statements = mw.wikibase.getBestStatements( itemId, property )
	if statements then
		for _, statement in ipairs( statements ) do
			if statement.mainsnak.datavalue then
				table.insert( ids, statement.mainsnak.datavalue.value )
			end
		end
	end
	return ids
end

function p.matchesWikidataRequirements( itemId, reqs )
	for _, group in ipairs( reqs ) do
		local property = 'P'..group[1]
		local qid = group[2]
		local statements = mw.wikibase.getBestStatements( itemId, property )
		if statements then
			for _, statement in ipairs( statements ) do
				if statement.mainsnak.datavalue then
					if statement.mainsnak.datavalue.value['numeric-id'] == qid then
						return true
	end	end	end	end	end
	return false
end

-- Creates a human-readable standalone wikitable version of p.conf, and tracking categories with page counts, for use in the documentation
function p.docConfTable( frame )
	local wikiTable = '{| class="wikitable sortable"\n'..
					  '! rowspan=2 | Parametr\n'..
					  '! rowspan=2 | Značka\n'..
					  '! rowspan=2; data-sort-type=number | Vlastnost na Wikidatech\n'..
					  '! colspan=4 | Monitorovací kategorie a počet použití v článcích\n'..
					  '|-\n'..
					  '! [[:Kategorie:Monitoring:Články s autoritní kontrolou|'..       'Články]]\n'..
					  '! Uživatelské stránky\n'..
					  '! Ostatní stránky\n'..
					  '! Neplatné ID\n'..
					  '|-\n'
	
	local lang = mw.getContentLanguage()
	for _, conf in pairs( p.conf ) do
		local param, link, pid = conf[1], conf[2], conf[3]
		local category = conf.category or param
		local args = { id = 'f', pid }
		local wpl = frame:expandTemplate{ title = 'Odkaz na vlastnost WD', args = args }
		--cats
		local articleCat = 'Monitoring:Články s identifikátorem ' .. category
		local userCat =    'Monitoring:Uživatelské stránky s identifikátorem ' .. category
		local miscCat =    'Monitoring:Ostatní stránky s identifikátorem '.. category
		local faultyCat =  'Údržba:Články s neplatným identifikátorem ' .. category
		--counts
		local articleCount = lang:formatNum( mw.site.stats.pagesInCategory(articleCat, 'pages') )
		local userCount =    lang:formatNum( mw.site.stats.pagesInCategory(userCat, 'pages') )
		local miscCount =    lang:formatNum( mw.site.stats.pagesInCategory(miscCat, 'pages') )
		local faultyCount =  lang:formatNum( mw.site.stats.pagesInCategory(faultyCat, 'pages') )
		--concat
		wikiTable = wikiTable..'\n'..
					'|-\n'..
					'||'..param..
					'||'..link..
					'||data-sort-value='..pid..'|'..wpl..
					'||style="text-align: right;"|[[:Kategorie:'..articleCat..'|'..articleCount..']]'..
					'||style="text-align: right;"|[[:Kategorie:'..   userCat..'|'..   userCount..']]'..
					'||style="text-align: right;"|[[:Kategorie:'..   miscCat..'|'..   miscCount..']]'..
					'||style="text-align: right;"|[[:Kategorie:'.. faultyCat..'|'.. faultyCount..']]'
	end
	
	return wikiTable..'\n|}'
end

--[[==========================================================================]]
--[[                               Konfigurace                                ]]
--[[==========================================================================]]

-- If a specific "(identifier) redirect" exists for an identifier, please route through this particular redirect rather than linking directly to the target page. This reduces clutter in "What links here" and improves reverse lookup of articles where a manifestation of this particular identifier is used.

-- Check that the Wikidata item has this property-->value before adding it
local reqs = {}

-- Parameter format: { 'parameter name', 'label', propertyId # in Wikidata, formatting/validation function }
p.conf = {
	{ 'AbARTP', '[[Archiv výtvarného umění|AbARTP]]', 6844, p.abartpLink, category = 'AbART osoba' }, --speciální název kategorie
	{ 'AbARTE', '[[Archiv výtvarného umění|AbARTE]]', 6846, p.abarteLink, category = 'AbART událost' }, --speciální název kategorie
	{ 'AbARTG', '[[Archiv výtvarného umění|AbARTG]]', 6847, p.abartgLink, category = 'AbART skupina' }, --speciální název kategorie
	{ 'AbARTI', '[[Archiv výtvarného umění|AbARTI]]', 6848, p.abartiLink, category = 'AbART instituce' }, --speciální název kategorie
	{ 'Biblio', '[[Bibliografie dějin Českých zemí|Biblio]]', 9037, p.biblioLink },
	{ 'Legie 100', '[[Legie 100]]', 9695, p.legieLink },
	{ 'NKC', '[[Národní knihovna České republiky|NKC]]', 691, p.nkcLink },
	{ 'PSH', '[[Polytematický strukturovaný heslář|PSH]]', 1051, p.pshLink },
	{ 'TDKIV', '[[Česká terminologická databáze knihovnictví a informační vědy|TDKIV]]', 5398, p.tdkivLink },
	{ 'AAG', '[[Aucklandská umělecká galerie|AAG]]', 3372, p.aagLink },
	{ 'ACM-DL', '[[Sdružení pro výpočetní techniku|ACM DL]]', 864, p.acmLink },
	{ 'ADB', '[[Australský biografický slovník|ADB]]', 1907, p.adbLink },
	{ 'AGSA', '[[Jihoaustralská umělecká galerie|AGSA]]', 6804, p.agsaLink },
	{ 'autores.uy', '[[autores.uy]]', 2558, p.autoresuyLink },
	{ 'AWR', '[[Australský registr žen|AWR]]', 4186, p.awrLink },
	{ 'BIBSYS', '[[BIBSYS]]', 1015, p.bibsysLink },
	{ 'Bildindex', '[[Bildindex der Kunst und Architektur|Bildindex]]', 12754, p.bildLink },
	{ 'BNC', '[[Národní knihovna Chile|BNC]]', 1890, p.bncLink },
	{ 'BNE', '[[Národní knihovna Španělska|BNE]]', 950, p.bneLink },
	{ 'BNF', '[[Francouzská národní knihovna|BNF]]', 268, p.bnfLink },
	{ 'Botanist', '[[Autor (botanika)|Botanist]]', 428, p.botanistLink },
	{ 'BPN', '[[Biografisch Portaal|BPN]]', 651, p.bpnLink },
	{ 'CANTIC', '[[Katalog jmen a názvů děl Katalánska|CANTIC]]', 9984, p.canticLink },
	{ 'CINII', '[[CiNii]]', 271, p.ciniiLink },
	{ 'CWGC', '[[Komise Britského společenství národů pro válečné hroby|CWGC]]', 1908, p.cwgcLink },
	{ 'DAAO', '[[Slovník australských umělců|DAAO]]', 1707, p.daaoLink },
	{ 'DBLP', '[[Digital Bibliography & Library Project|DBLP]]', 2456, p.dblpLink },
	{ 'DIB', '[[Irský biografický slovník|DIB]]', 6829, p.dibLink },
	{ 'DSI', '[[Stuttgart Database of Scientific Illustrators 1450–1950|DSI]]', 2349, p.dsiLink },
	{ 'FNZA', '[[Find New Zealand Artists|FNZA]]', 6792, p.fnzaLink }, --wd
	{ 'GND', '[[Gemeinsame Normdatei|GND]]', 227, p.gndLink },
	{ 'Google Scholar', '[[Google Scholar]]', 1960, p.googleLink },
	{ 'HDS', '[[Historický lexikon Švýcarska|HDS]]', 902, p.hdsLink },
	{ 'IAAF', '[[Světová atletika|IAAF]]', 1146, p.iaafLink },
	{ 'ICCU', '[[Istituto centrale per il catalogo unico delle biblioteche italiane e per le informazioni bibliografiche|ICCU]]', 396, p.iccuLink },
	{ 'ICIA', '[[Information Center for Israeli Art|ICIA]]', 1736, p.iciaLink },
	{ 'IEU', '[[Internet Encyclopedia of Ukraine|IEU]]', 9070, p.ieuLink },
	{ 'ISNI', '[[Mezinárodní standardní identifikátor jména|ISNI]]', 213, p.isniLink },
	{ 'Joconde', '[[Joconde]]' , 347, p.jocondeLink },
	{ 'KulturNav', '[[KulturNav]]', 1248, p.kulturnavLink },
	{ 'LCCN', '[[Library of Congress Control Number|LCCN]]', 244, p.lccnLink },
	{ 'LIR', '[[Historický lexikon Švýcarska|LIR]]', 886, p.lirLink },
	{ 'LNB', '[[Lotyšská národní knihovna|LNB]]', 1368, p.lnbLink },
	{ 'MBA', '[[MusicBrainz|MBA]]', 434, p.mbaLink, category = 'MusicBrainz' }, --speciální název kategorie
	{ 'MBAREA', '[[MusicBrainz|MBAREA]]', 982, p.mbareaLink, category = 'MusicBrainz oblast' }, --speciální název kategorie
	{ 'MBI', '[[MusicBrainz|MBI]]', 1330, p.mbiLink, category = 'MusicBrainz hudební nástroj' }, --speciální název kategorie
	{ 'MBL', '[[MusicBrainz|MBL]]', 966, p.mblLink, category = 'MusicBrainz hudební vydavatelství' }, --speciální název kategorie
	{ 'MBP', '[[MusicBrainz|MBP]]', 1004, p.mbpLink, category = 'MusicBrainz místo' }, --speciální název kategorie
	{ 'MBRG', '[[MusicBrainz|MBRG]]', 436, p.mbrgLink, category = 'MusicBrainz skupina vydání alba' }, --speciální název kategorie
	{ 'MBS', '[[MusicBrainz|MBS]]', 1407, p.mbsLink, category = 'MusicBrainz řada' }, --speciální název kategorie
	{ 'MBW', '[[MusicBrainz|MBW]]', 435, p.mbwLink, category = 'MusicBrainz dílo' }, --speciální název kategorie
	{ 'MGP', '[[Mathematics Genealogy Project|MGP]]', 549, p.mgpLink },
	{ 'NARA', '[[National Archives and Records Administration|NARA]]', 1225, p.naraLink },
	{ 'NCL', '[[Národní ústřední knihovna Tchaj-wanu|NCL]]', 1048, p.nclLink },
	{ 'NDL', '[[Národní parlamentní knihovna Japonska|NDL]]', 349, p.ndlLink },
	{ 'NGV', '[[Národní galerie Victoria|NGV]]', 2041, p.ngvLink },
	{ 'NLA', '[[Australská národní knihovna|NLA]]', 409, p.nlaLink },
	{ 'NLG', '[[Řecká národní knihovna|NLG]]', 3348, p.nlgLink },
	{ 'NLI', '[[Národní knihovna Izraele|NLI]]', 8189, p.nliLink },
	{ 'NLK', '[[Národní knihovna Koreje|NLK]]', 5034, p.nlkLink },
	{ 'NLP', '[[Polská národní knihovna|NLP]]', 1695, p.nlpLink },
	{ 'NLR', '[[Rumunská národní knihovna|NLR]]', 1003, p.nlrLink },
	{ 'NSK', '[[Národní a univerzitní knihovna v Záhřebu|NSK]]', 1375, p.nskLink },
	{ 'NTA', '[[Nizozemská královská knihovna|NTA]]', 1006, p.ntaLink },
	{ 'ORCID', '[[ORCID]]', 496, p.orcidLink },
	{ 'PIC', '[[New York Public Library|PIC]]', 2750, p.picLink }, --wd
	{ 'PLWABN', '[[Polská národní knihovna|PLWABN]]', 7293, p.plwabnLink },
	{ 'Publons', '[[Publons]]', 3829, p.publonsLink },
	{ 'RID', '[[ResearcherID]]', 1053, p.ridLink },
	{ 'RKDartists', '[[Nizozemský institut dějin umění#Online stránky umělců|RKDartists]]', 650, p.rkdartistsLink },
	{ 'RKDimages', '[[Nizozemský institut dějin umění#Online stránky uměleckých děl|RKDimages]]', 350, p.rkdimagesLink },
	{ 'RSL', '[[Ruská státní knihovna|RSL]]', 947, p.rslLink },
	{ 'Scopus', '[[Scopus (databáze)|Scopus]]', 1153, p.scopusLink },
	{ 'SELIBR', '[[LIBRIS|SELIBR]]', 906, p.selibrLink },
	{ 'SIKART', '[[SIKART]]', 781, p.sikartLink },
	{ 'SNAC-ID', '[[SNAC]]', 3430, p.snacLink },
	{ 'SNK', '[[Slovenská národní knihovna|SNK]]', 9807, p.snkLink },
	{ 'SUDOC', '[[Univerzitní systém dokumentace|SUDOC]]', 269, p.sudocLink },
	{ 'TA98', '[[Terminologia Anatomica|TA98]]', 1323, p.ta98Link },
	{ 'TDVİA', '[[Encyklopedie islámu|TDVİA]]', 7314, p.tdviaLink },
	{ 'TePapa', '[[Te Papa|TePapa]]', 3544, p.tepapaLink },
	{ 'TLS', '[[Theaterlexikon der Schweiz|TLS]]', 1362, p.tlsLink },
	{ 'Trove', '[[Trove]]', 1315, p.troveLink },
	{ 'UKPARL', '[[Parlament Spojeného království|UKPARL]]', 6213, p.ukparlLink },
	{ 'ULAN', '[[Union List of Artist Names|ULAN]]', 245, p.ulanLink },
	{ 'USCongress', '[[Seznam biografií Kongresu Spojených států amerických|US Congress]]', 1157, p.uscongressLink },
	{ 'VcBA', '[[Vatikánská apoštolská knihovna|VcBA]]', 8034, p.vcbaLink },
	{ 'VIAF', '[[Virtual International Authority File|VIAF]]', 214, p.viafLink },
	{ 'WorldCat Entities', '[[WorldCat|WorldCat Entities]]', 10832, p.worldcatLink },
}

-- Legitimate aliases to p.conf, for convenience
-- Format: { 'alias', 'parameter name in p.conf' }
p.aliases = {
	{ 'AUT', 'NKC' }, --Národní autority České republiky -> Národní knihovna České republiky
}

-- Deprecated aliases to p.conf; tracked in [[Category:Wikipedia articles with deprecated authority control identifiers]]
-- Format: { 'deprecated parameter name', 'replacement parameter name in p.conf' }
p.deprecated = {}

--[[==========================================================================]]
--[[                                  Hlavní                                  ]]
--[[==========================================================================]]

function p.authorityControl( frame )
	local parentArgs = frame:getParent().args --WD IDs added here later
	local iParentArgs = 0 --count original/manual parent args only later
	local elements = {} --create/insert rows later
--	local multipleIdCat = '' --vyjmuto kvůli umístění na konci názvu kategorie
	local suppressedIdCat = ''
	local deprecatedIdCat = ''
	local differentOnWDCat = ''
	local sameOnWDCat = ''
	
	--Redirect aliases to proper parameter names
	for _, a in pairs( p.aliases ) do
		local alias, param = a[1], a[2]
		if (parentArgs[param] == nil or parentArgs[param] == '') and parentArgs[alias] then
			parentArgs[param] = parentArgs[alias]
		end
	end
	
	--Redirect deprecated parameters to proper parameter names, and assign tracking cat
	for _, d in pairs( p.deprecated ) do
		local dep, param = d[1], d[2]
		if (parentArgs[param] == nil or parentArgs[param] == '') and parentArgs[dep] then
			parentArgs[param] = parentArgs[dep]
			if namespace == 0 then
				deprecatedIdCat = '[[Kategorie:Údržba:Články se zastaralými identifikátory autoritní kontroly|'..dep..']]'
			end
		end
	end
	
	--Use QID= parameter for testing/example purposes only
	local itemId = nil
	if namespace ~= 0 then
		local qid = parentArgs['qid'] or parentArgs['QID']
		if qid then
			local resolveEntity = require( "Modul:ResolveEntityId" )
			itemId = 'Q'..mw.ustring.gsub(qid, '^[Qq]', '')
			itemId = resolveEntity._id(itemId) --nil if unresolvable
		end
	else
		itemId = mw.wikibase.getEntityIdForCurrentPage()
	end
	
	--Wikidata fallback if available
	if itemId then
		local iMatches = 0
		for _, params in ipairs( p.conf ) do
			if params[3] > 0 then
				local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]]
				if val == nil or val == '' then
					local canUseWikidata = nil
					if reqs[params[1]] then
						--since reqs{} has been nil afaicr, p.matchesWikidataRequirements will never be called
						--TODO: reqs{} doesn't seem useful/necessary; appendage of early WD incorporation?
						canUseWikidata = p.matchesWikidataRequirements( itemId, reqs[params[1]] )
					else
						canUseWikidata = true
					end
					if canUseWikidata then
						local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[3] )
						if wikidataIds[1] then
							if val == '' and (namespace == 0 or testcases) then
								suppressedIdCat = '[[Kategorie:Monitoring:Články s potlačenými identifikátory autoritní kontroly|'..params[1]..']]'
							else
								parentArgs[params[1]] = wikidataIds[1] --add ID from WD
							end
						end
					end
				else
					iParentArgs = iParentArgs + 1
					local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[3] )
					if wikidataIds[1] and differentOnWDCat == '' then
						local bMatch = false
						for _, wd in pairs( wikidataIds ) do
							if val == wd then
								iMatches = iMatches + 1
								bMatch = true
							end
						end
						if bMatch == false then
							differentOnWDCat = '[[Kategorie:Údržba:Články s identifikátory autoritní kontroly, které neodpovídají Wikidatům|'..params[1]..']]'
		end	end	end	end	end
		if iMatches > 0 and iMatches == iParentArgs then
			sameOnWDCat = '[[Kategorie:Monitoring:Články s identifikátory autoritní kontroly, které všechny odpovídají Wikidatům]]'
		end
	end
	
	--Configured rows
	for _, params in ipairs( p.conf ) do
		local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]]
		local tval, tlinks = {}, {} --init tables
		if val and val ~= '' and type(params[4]) == 'function' then
			table.insert( tval, val )
			table.insert( tlinks, params[4]( val ) )
		end
		--collect other unique vals (IDs) from WD, if present
		if itemId and tval[1] then
			local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[3] )
			for _, v in pairs( wikidataIds ) do
				local bnew = true
				for _, w in pairs( tval ) do
					if v == w then bnew = false end
				end
				if bnew then
					table.insert( tval, v )
					table.insert( tlinks, params[4]( v ) )
				end
			end
		end
		--assemble
		if tval[1] then
			table.insert( elements, p.createRow( params[1], params[2]..':', tval, nil, tlinks, true, params.category ) )
--			if tval[2] then
--		    	multipleIdCat = p.getCatForId( 'multiple' ) --vyjmuto
--			end
		end
	end

	local elementsCat = ''
	local rct = #elements
	local MAX_IDENTIFIERS = 30
	if rct == 0 or rct >= MAX_IDENTIFIERS then
		local eCat
		if rct == 0 then
			eCat = 'Monitoring:Autoritní kontrola s 0 identifikátory'
		else
			eCat = 'Monitoring:Autoritní kontrola s ' .. MAX_IDENTIFIERS .. '+ identifikátory'
		end
		elementsCat = '[[Kategorie:'..eCat..']]'..p.redCatLink(eCat)
	end

	local outString = ''
	if rct > 0 then
		local args = { pid = 'identifiers' } -- #target the list of identifiers
		if testcases and itemId then args = { pid = 'identifiers', qid = itemId } end --expensive
		local pencil = frame:expandTemplate{ title = 'Editovat na Wikidatech', args = args }
		local Navbox = require('Modul:Navbox')
		outString = Navbox._navbox( {
			name  = 'Autoritní data',
			navboxclass = 'authority-control',
			bodyclass = 'hlist',
			group1 = '[[Autoritní kontrola|Autoritní data]]' .. pencil,
			list1 = table.concat( elements )
		} )
	end
	
	local auxCats = elementsCat .. suppressedIdCat .. --multipleIdCat vyjmuto
					deprecatedIdCat .. differentOnWDCat .. sameOnWDCat
	if testcases then
		auxCats = mw.ustring.gsub(auxCats, '(%[%[)(Kategorie)', '%1:%2') --for easier checking
	end
	outString = outString .. auxCats
	if namespace ~= 0 then
		outString = mw.ustring.gsub(outString, '(%[%[)(Kategorie:Články podle témat)', '%1:%2') --by definition
	end
	
	return outString
end

return p