Module:Authority control: Difference between revisions

From Zoophilia Wiki
Jump to navigationJump to search
m (1 revision imported)
m (1 revision imported)
 
(One intermediate revision by one other user not shown)
Line 32: Line 32:
end
end


function p.createRow( id, label, rawValues, link, links, withUid, specialCat )
function p.createRow( id, rawValues, link, links, withUid, specialCat, prefix)
local catName = 'Wikipedia articles with faulty '..(specialCat or id)..' identifiers'
local catName = 'Wikipedia articles with faulty '..(specialCat or id)..' identifiers'
if links then -- all links[] use withUid = false; no check needed
if links then -- all links[] use withUid = false; no check needed
local row = '*<span class="nowrap">'..label
local row = ''
local totlen = 0
if prefix then
row = row .. '*' .. prefix
end
for i, l in ipairs( links ) do
for i, l in ipairs( links ) do
if i == 1 then row = row..' '
if i == 1 and not prefix then row = row..'*'
else          row = row..', ' end
else          row = row..'\n**' end
if l then
if l then
row = row..'<span class="uid">'..l..'</span>'
row = row..'<span class="uid">'..l..'</span>'
Line 45: Line 47:
row = row..'<span class="error">The '..id..' id '..rawValues[i]..' is not valid.</span>[[Category:'..catName..']]'..p.redCatLink(catName)
row = row..'<span class="error">The '..id..' id '..rawValues[i]..' is not valid.</span>[[Category:'..catName..']]'..p.redCatLink(catName)
end
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
end
return row..'</span>\n'
return row..'\n'
elseif link then
elseif link then -- All IDs that have a prefix support multiple identifiers, so prefix is not needed
if withUid then
if withUid then
return '*<span class="nowrap">'..label..' <span class="uid">'..link..'</span></span>\n'
return '*<span class="nowrap"><span class="uid">'..link..'</span></span>\n'
end
end
return '*<span class="nowrap">'..label..' '..link..'</span>\n'
return '*<span class="nowrap">'..link..'</span>\n'
end
end
Line 67: Line 65:
-- 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.
-- 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 )
function p.aagLink( id, label)
--P3372's format regex: \d+ (e.g. 1)
--P3372's format regex: \d+ (e.g. 1)
if not id:match( '^%d+$' ) then
if not id:match( '^%d+$' ) then
return false
return false
end
end
return '[https://www.aucklandartgallery.com/explore-art-and-ideas/artist/'..id..'/ '..id..']'..p.getCatForId( 'AAG' )
return '[https://www.aucklandartgallery.com/explore-art-and-ideas/artist/'..id..'/ '..(label or 'Auckland')..']'..p.getCatForId( 'AAG' )
end
end


function p.acmLink( id )
function p.acmLink( id, label )
--P864's format regex: \d{11} (e.g. 12345678901)
--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
if not id:match( '^%d%d%d%d%d%d%d%d%d%d%d$' ) then
return false
return false
end
end
return '[https://dl.acm.org/profile/'..id..' '..id..']'..p.getCatForId( 'ACM-DL' )
return '[https://dl.acm.org/profile/'..id..' '..(label or 'Association for Computing Machinery')..']'..p.getCatForId( 'ACM-DL' )
end
end


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


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


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


function p.awrLink( id )
function p.awrLink( id, label )
--P4186's format regex: (([A-Z]{3}\d{4})|([A-Z]{2}\d{5}))[a-z] (e.g. PR00768b)
--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
if not id:match( '^[A-Z][A-Z][A-Z]%d%d%d%d[a-z]$' ) and
Line 114: Line 112:
return false
return false
end
end
return '[http://www.womenaustralia.info/biogs/'..id..'.htm '..id..']'..p.getCatForId( 'AWR' )
return '[http://www.womenaustralia.info/biogs/'..id..'.htm '..(label or 'Australian Women\'s Register')..']'..p.getCatForId( 'AWR' )
end
end


function p.balatLink( id )
function p.balatLink( id, label )
--P3293's format regex: \d+ (e.g. 1)
--P3293's format regex: \d+ (e.g. 1)
if not id:match( '^%d+$' ) then
if not id:match( '^%d+$' ) then
return false
return false
end
end
return '[http://balat.kikirpa.be/object/104257'..id..' '..id..']'..p.getCatForId( 'BALaT' ) --no https as of 9/2019
return '[http://balat.kikirpa.be/object/104257'..id..' '..(label or 'BALaT (Belgium)')..']'..p.getCatForId( 'BALaT' ) --no https as of 9/2019
end
end


function p.bibsysLink( id )
function p.bibsysLink( id, label )
--P1015's format regex: [1-9]\d* or [1-9](\d{0,8}|\d{12}) (e.g. 1234567890123)
--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
--TODO: follow up @ [[d:Property talk:P1015#Discrepancy between the 2 regex constraints]] or escalate/investigate
Line 132: Line 130:
return false
return false
end
end
return '[https://authority.bibsys.no/authority/rest/authorities/html/'..id..' '..id..']'..p.getCatForId( 'BIBSYS' )
return '[https://authority.bibsys.no/authority/rest/authorities/html/'..id..' '..(label or 'Norway')..']'..p.getCatForId( 'BIBSYS' )
end
end


function p.bildLink( id )
function p.bildLink( id, label )
--P2092's format regex: \d+ (e.g. 1)
--P2092's format regex: \d+ (e.g. 1)
if not id:match( '^%d+$' ) then
if not id:match( '^%d+$' ) then
return false
return false
end
end
return '[https://www.bildindex.de/document/obj'..id..' '..id..']'..p.getCatForId( 'Bildindex' )
return '[https://www.bildindex.de/document/obj'..id..' '..(label or 'Bildindex (Germany)')..']'..p.getCatForId( 'Bildindex' )
end
end


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


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


function p.bnfLink( id )
function p.bnfLink( id, label )
--P268's format regex: \d{8}[0-9bcdfghjkmnpqrstvwxz] (e.g. 123456789)
--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
if not id:match( '^c?b?%d%d%d%d%d%d%d%d[0-9bcdfghjkmnpqrstvwxz]$' ) then
Line 171: Line 169:
id = 'cb'..id
id = 'cb'..id
end
end
return '[https://catalogue.bnf.fr/ark:/12148/'..id..' '..id..'] [https://data.bnf.fr/ark:/12148/'..id..' (data)]'..p.getCatForId( 'BNF' )
return '[https://catalogue.bnf.fr/ark:/12148/'..id..' ' .. (label or 'France')..'] [https://data.bnf.fr/ark:/12148/'..id..' (data)]'..p.getCatForId( 'BNF' )
end
end


function p.botanistLink( id )
function p.botanistLink( id, label )
--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.)
--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...
--not easily/meaningfully implementable in Lua's regex since "(this)?" is not allowed...
Line 180: Line 178:
return false
return false
end
end
local id2 = id:gsub(' +', '%%20')
id = id:gsub(' +', '%%20')
return '[https://www.ipni.org/ipni/advAuthorSearch.do?find_abbreviation='..id2..' '..id..']'..p.getCatForId( 'Botanist' )
return '[https://www.ipni.org/ipni/advAuthorSearch.do?find_abbreviation='..id..' '..(label or 'International Plant Names Index')..']'..p.getCatForId( 'Botanist' )
end
end


function p.bpnLink( id )
function p.bpnLink( id, label )
--P651's format regex: \d{6,8} (e.g. 00123456)
--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
if not id:match( '^%d%d%d%d%d%d%d%d$' ) and --original format regex, changed 8/2019 to
Line 191: Line 189:
return false
return false
end
end
return '[http://www.biografischportaal.nl/en/persoon/'..id..' '..id..']'..p.getCatForId( 'BPN' ) --no https as of 9/2019
return '[http://www.biografischportaal.nl/en/persoon/'..id..' '..(label or 'Netherlands')..']'..p.getCatForId( 'BPN' ) --no https as of 9/2019
end
end


function p.canticLink( id )
function p.canticLink( id, label )
--P1273's format regex: a\d{7}[0-9x] (e.g. a10640745)
--P1273's format regex: a\d{7}[0-9x] (e.g. a10640745)
if not id:match( '^a%d%d%d%d%d%d%d[%dx]$' ) then
if not id:match( '^a%d%d%d%d%d%d%d[%dx]$' ) then
return false
return false
end
end
return '[http://cantic.bnc.cat/registres/CUCId/'..id..' '..id..']'..p.getCatForId( 'CANTIC' ) --no https as of 10/2019
return '[http://cantic.bnc.cat/registres/CUCId/'..id..' '..(label or 'Catalonia')..']'..p.getCatForId( 'CANTIC' ) --no https as of 10/2019
end
end


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


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


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


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


function p.dibLink( id )
function p.dibLink( id, label )
--P6829's format regex: a\d{4}\d?(-[A-D])? (e.g. a1953)
--P6829's format regex: a\d{4}\d?(-[A-D])? (e.g. a1953)
if not id:match( '^a%d%d%d%d%d?%-?[A-D]?$' ) then
if not id:match( '^a%d%d%d%d%d?%-?[A-D]?$' ) then
return false
return false
end
end
return '[https://dib.cambridge.org/viewReadPage.do?articleId='..id..' '..id..']'..p.getCatForId( 'DIB' )
return '[https://dib.cambridge.org/viewReadPage.do?articleId='..id..' '..(label or 'Ireland')..']'..p.getCatForId( 'DIB' )
end
end


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


function p.fastLink( id )
function p.fastLink( id, label )
--P2163's format regex: [1-9]\d{0,7} (e.g. 1916996)
--P2163's format regex: [1-9]\d{0,7} (e.g. 1916996)
if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?$' ) then
if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?$' ) then
return false
return false
end
end
return '[http://id.worldcat.org/fast/'..id..'/ '..id..']'..p.getCatForId( 'FAST' )
return '[http://id.worldcat.org/fast/'..id..'/ '..(label or 'Faceted Application of Subject Terminology')..']'..p.getCatForId( 'FAST' )
end
end


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


function p.gndLink( id )
function p.gndLink( id, label )
--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)
--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[012]?%d%d%d%d%d%d%d[0-9X]$' ) and
if not id:match( '^1[012]?%d%d%d%d%d%d%d[0-9X]$' ) and
Line 277: Line 276:
return false
return false
end
end
return '[https://d-nb.info/gnd/'..id..' '..id..']'..p.getCatForId( 'GND' )
return '[https://d-nb.info/gnd/'..id..' '..(label or 'Integrated Authority File')..']'..p.getCatForId( 'GND' )
end
end


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


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


function p.iciaLink( id )
 
function p.iccuLink( id, label )
--P396's format regex: IT\\ICCU\\(\d{10}|\D\D[\D\d]\D\\\d{6}) (e.g. IT\ICCU\CFIV\000163)
if not id:match( '^IT\\ICCU\\%d%d%d%d%d%d%d%d%d%d$' ) and
  not id:match( '^IT\\ICCU\\%u%u[%u%d]%u\\%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/opacsbn/opac/iccu/scheda_authority.jsp?bid='..id..' '..(label or 'Italy')..']'..p.getCatForId( 'ICCU' )
end
function p.iciaLink( id, label )
--P1736's format regex: \d+ (e.g. 1)
--P1736's format regex: \d+ (e.g. 1)
if not id:match( '^%d+$' ) then
if not id:match( '^%d+$' ) then
return false
return false
end
end
return '[https://www.imj.org.il/artcenter/newsite/en/?artist='..id..' '..id..']'..p.getCatForId( 'ICIA' )
return '[https://www.imj.org.il/artcenter/newsite/en/?artist='..id..' '..(label or 'ICIA (Israel)')..']'..p.getCatForId( 'ICIA' )
end
end


function p.ieuLink( id )
function p.ieuLink( id, label )
--P9070's format regex: [A-Z]\\[A-Z]\\[A-Za-z0-9]+ (e.g. K\Y\Kyiv)
--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
if not id:match( '^[A-Z]\\[A-Z]\\%w+$' ) then
return false
return false
end
end
return '[http://www.encyclopediaofukraine.com/display.asp?linkpath=pages\\'..id..' '..id..']'..p.getCatForId( 'IEU' )
return '[http://www.encyclopediaofukraine.com/display.asp?linkpath=pages\\'..id..' '..(label or 'Internet Encyclopedia of Ukraine')..']'..p.getCatForId( 'IEU' )
end
end


function p.isniLink( id )
function p.isniLink( id, label )
id = p.validateIsni( id ) --e.g. 0000-0000-6653-4145
id = p.validateIsni( id ) --e.g. 0000-0000-6653-4145
if not id then
if not id then
return false
return false
end
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
return '[https://isni.org/isni/'..id..' '..(label or 'ISNI')..']'..p.getCatForId( 'ISNI' )
end
end


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


function p.kulturnavLink( id )
function p.kulturnavLink( id, label )
--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)
--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
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
return false
end
end
return '[http://kulturnav.org/'..id..' '..id..']'..p.getCatForId( 'KULTURNAV' ) --no https as of 9/2019
return '[http://kulturnav.org/'..id..' '..(label or 'KulturNav (Norway)')..']'..p.getCatForId( 'KULTURNAV' ) --no https as of 9/2019
end
end


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


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


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


function p.leonoreLink( id )
function p.leonoreLink( id, label )
--P640's format regex: LH/\d{1,4}/\d{1,3}|19800035/\d{1,4}/\d{1,5}(Bis)?|C/0/\d{1,2} (e.g. LH/2064/18)
--P640's format regex: LH/\d{1,4}/\d{1,3}|19800035/\d{1,4}/\d{1,5}(Bis)?|C/0/\d{1,2} (e.g. LH/2064/18)
if not id:match( '^LH/%d%d?%d?%d?/%d%d?%d?$' ) and            --IDs from      LH/1/1 to        LH/2794/54 (legionaries)
if not id:match( '^LH/%d%d?%d?%d?/%d%d?%d?$' ) and            --IDs from      LH/1/1 to        LH/2794/54 (legionaries)
Line 370: Line 378:
return false
return false
end
end
return '[http://www.culture.gouv.fr/public/mistral/leonore_fr?ACTION=CHERCHER&FIELD_1=COTE&VALUE_1='..id..' '..id..']'..p.getCatForId( 'Léonore' ) --no https as of 9/2019
return '[http://www.culture.gouv.fr/public/mistral/leonore_fr?ACTION=CHERCHER&FIELD_1=COTE&VALUE_1='..id..' '..(label or 'Léonore (France)')..']'..p.getCatForId( 'Léonore' ) --no https as of 9/2019
end
end


function p.maLink( id )
function p.maLink( id, label )
--P6366's format regex: [1-9]\d{4,9} (e.g. 1498221862)
--P6366's format regex: [1-9]\d{4,9} (e.g. 1498221862)
if not id:match( '^[1-9]%d%d%d%d%d?%d?%d?%d?%d?$' ) then
if not id:match( '^[1-9]%d%d%d%d%d?%d?%d?%d?%d?$' ) then
return false
return false
end
end
return '[https://academic.microsoft.com/v2/detail/'..id..' '..id..']'..p.getCatForId( 'MA' )
return '[https://academic.microsoft.com/v2/detail/'..id..' '..(label or 'Microsoft Academic')..']'..p.getCatForId( 'MA' )
end
end


function p.mbaLink( id )
function p.mbaLink( id, label )
--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)
--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
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
return false
end
end
return '[https://musicbrainz.org/artist/'..id..' '..id..']'..p.getCatForId( 'MusicBrainz' ) --special cat name
local url = 'https://musicbrainz.org/artist/'..id
local cat = p.getCatForId( 'MusicBrainz' )--special cat name
if label then
return '['..url..' '..label..']'..cat
else
return '[[MBA (identifier)|MusicBrainz]] [' .. url .. ' artist]' .. cat
end
end
end


function p.mbareaLink( id )
function p.mbareaLink( id, label )
--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)
--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
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
return false
end
end
return '[https://musicbrainz.org/area/'..id..' '..id..']'..p.getCatForId( 'MusicBrainz area' ) --special cat name
local url = 'https://musicbrainz.org/area/'..id
local cat = p.getCatForId( 'MusicBrainz area' )--special cat name
if label then
return '['..url..' '..label..']'..cat
else
return '[[MBAREA (identifier)|MusicBrainz]] [' .. url .. ' area]' .. cat
end
end
end


function p.mbiLink( id )
function p.mbiLink( id, label )
--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)
--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
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
return false
end
end
return '[https://musicbrainz.org/instrument/'..id..' '..id..']'..p.getCatForId( 'MusicBrainz instrument' ) --special cat name
local url = 'https://musicbrainz.org/instrument/'..id
local cat = p.getCatForId( 'MusicBrainz instrument' )--special cat name
if label then
return '['..url..' '..label..']'..cat
else
return '[[MBI (identifier)|MusicBrainz]] [' .. url .. ' instrument]' .. cat
end
end
end


function p.mblLink( id )
function p.mblLink( id, label )
--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)
--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
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
return false
end
end
return '[https://musicbrainz.org/label/'..id..' '..id..']'..p.getCatForId( 'MusicBrainz label' ) --special cat name
local url = 'https://musicbrainz.org/label/'..id
local cat = p.getCatForId( 'MusicBrainz label' )--special cat name
if label then
return '['..url..' '..label..']'..cat
else
return '[[MBL (identifier)|MusicBrainz]] [' .. url .. ' label]' .. cat
end
end
end


function p.mbpLink( id )
function p.mbpLink( id, label )
--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)
--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
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
return false
end
end
return '[https://musicbrainz.org/place/'..id..' '..id..']'..p.getCatForId( 'MusicBrainz place' ) --special cat name
local url = 'https://musicbrainz.org/place/'..id
local cat = p.getCatForId( 'MusicBrainz place' )--special cat name
if label then
return '['..url..' '..label..']'..cat
else
return '[[MBP (identifier)|MusicBrainz]] [' .. url .. ' place]' .. cat
end
end
end


function p.mbrgLink( id )
function p.mbrgLink( id, label )
--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)
--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
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
return false
end
end
return '[https://musicbrainz.org/release-group/'..id..' '..id..']'..p.getCatForId( 'MusicBrainz release group' ) --special cat name
local url = 'https://musicbrainz.org/release-group/'..id
local cat = p.getCatForId( 'MusicBrainz release group' )--special cat name
if label then
return '['..url..' '..label..']'..cat
else
return '[[MBRG (identifier)|MusicBrainz]] [' .. url .. ' release group]' .. cat
end
end
end


function p.mbsLink( id )
function p.mbsLink( id, label )
--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)
--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
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
return false
end
end
return '[https://musicbrainz.org/series/'..id..' '..id..']'..p.getCatForId( 'MusicBrainz series' ) --special cat name
local url = 'https://musicbrainz.org/series/'..id
local cat = p.getCatForId( 'MusicBrainz series' )--special cat name
if label then
return '['..url..' '..label..']'..cat
else
return '[[MBS (identifier)|MusicBrainz]] [' .. url .. ' series]' .. cat
end
end
end


function p.mbwLink( id )
function p.mbwLink( id, label )
--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)
--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
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
return false
end
end
return '[https://musicbrainz.org/work/'..id..' '..id..']'..p.getCatForId( 'MusicBrainz work' ) --special cat name
local url = 'https://musicbrainz.org/work/'..id
local cat = p.getCatForId( 'MusicBrainz work' )--special cat name
if label then
return '['..url..' '..label..']'..cat
else
return '[[MBW (identifier)|MusicBrainz]] [' .. url .. ' work]' .. cat
end
end
end


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


function p.naraLink( id )
function p.naraLink( id, label )
--P1225's format regex: ^([1-9]\d{0,8})$ (e.g. 123456789)
--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
if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?%d?$' ) then
return false
return false
end
end
return '[https://catalog.archives.gov/id/'..id..' '..id..']'..p.getCatForId( 'NARA' )
return '[https://catalog.archives.gov/id/'..id..' '..(label or 'National Archives (US)')..']'..p.getCatForId( 'NARA' )
end
end


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


function p.ndlLink( id )
function p.ndlLink( id, label )
--P349's format regex: 0?\d{8} (e.g. 012345678)
--P349's format regex: 0?\d{8} (e.g. 012345678)
if not id:match( '^0?%d%d%d%d%d%d%d%d$' ) then
if not id:match( '^0?%d%d%d%d%d%d%d%d$' ) then
return false
return false
end
end
return '[https://id.ndl.go.jp/auth/ndlna/'..id..' '..id..']'..p.getCatForId( 'NDL' )
return '[https://id.ndl.go.jp/auth/ndlna/'..id..' '..(label or 'Japan')..']'..p.getCatForId( 'NDL' )
end
end


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


function p.nkcLink( id )
function p.nkcLink( id, label )
--P691's format regex: [a-z]{2,4}[0-9]{2,14} (e.g. abcd12345678901234)
--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
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
return false
end
end
return '[https://aleph.nkp.cz/F/?func=find-c&local_base=aut&ccl_term=ica='..id..'&CON_LNG=ENG '..id..']'..p.getCatForId( 'NKC' )
return '[https://aleph.nkp.cz/F/?func=find-c&local_base=aut&ccl_term=ica='..id..'&CON_LNG=ENG '..(label or 'Czech Republic')..']'..p.getCatForId( 'NKC' )
end
end


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


function p.nlgLink( id )
function p.nlgLink( id, label )
--P3348's format regex: [1-9]\d* (e.g. 1)
--P3348's format regex: [1-9]\d* (e.g. 1)
if not id:match( '^[1-9]%d*$' ) then
if not id:match( '^[1-9]%d*$' ) then
return false
return false
end
end
return '[https://data.nlg.gr/resource/authority/record'..id..' '..id..']'..p.getCatForId( 'NLG' )
return '[https://data.nlg.gr/resource/authority/record'..id..' '..(label or 'Greece')..']'..p.getCatForId( 'NLG' )
end
end


function p.nliLink( id )
function p.nliLink( id, label )
--P949's format regex: \d{9} (e.g. 123456789)
--P949's format regex: \d{9} (e.g. 123456789)
if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then
if not id:match( '^%d%d%d%d%d%d%d%d%d$' ) then
return false
return false
end
end
return '[http://uli.nli.org.il/F/?func=direct&doc_number='..id..'&local_base=nlx10'..' '..id..']'..p.getCatForId( 'NLI' )
return '[http://uli.nli.org.il/F/?func=direct&doc_number='..id..'&local_base=nlx10'..' '..(label or 'Israel')..']'..p.getCatForId( 'NLI' )
end
end


function p.nlkLink( id )
function p.nlkLink( id, label )
--P5034's format regex: KA.(19|20).{7} (e.g. KAC201501465)
--P5034's format regex: KA.(19|20).{7} (e.g. KAC201501465)
if not id:match( '^KA.19.......$' ) and
if not id:match( '^KA.19.......$' ) and
Line 523: Line 580:
return false
return false
end
end
return '[https://nl.go.kr/authorities/resource/'..id..' '..id..']'..p.getCatForId( 'NLK' )
return '[https://nl.go.kr/authorities/resource/'..id..' '..(label or 'Korea')..']'..p.getCatForId( 'NLK' )
end
end


function p.nlpLink( id )
function p.nlpLink( id, label )
--P1695's format regex: 9810[0-9]\d* or A[0-9]{7}[0-9X] (e.g. 9810123456789012345 or A10414836)
--P1695's format regex: 9810[0-9]\d* or A[0-9]{7}[0-9X] (e.g. 9810123456789012345 or A10414836)
if not id:match( '^9810%d+$' ) and
if not id:match( '^9810%d+$' ) and
Line 532: Line 589:
return false
return false
end
end
return '[https://tools.wmflabs.org/wikidata-externalid-url?p=1695&id='..id..' '..id..']'..p.getCatForId( 'NLP' )
return '[https://tools.wmflabs.org/wikidata-externalid-url?p=1695&id='..id..' '..(label or 'Poland')..']'..p.getCatForId( 'NLP' )
end
end


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


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


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


function p.orcidLink( id )
function p.orcidLink( id, label )
id = p.validateIsni( id ) --e.g. 0000-0002-7398-5483
id = p.validateIsni( id ) --e.g. 0000-0002-7398-5483
if not id then
if not id then
Line 565: Line 622:
end
end
id = id:sub( 1, 4 )..'-'..id:sub( 5, 8 )..'-'..id:sub( 9, 12 )..'-'..id:sub( 13, 16 )
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' )
return '[https://orcid.org/'..id..' '..(label or 'ORCID')..']'..p.getCatForId( 'ORCID' )
end
end


function p.plwabnLink( id )
function p.picLink( id, label )
--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..' '..(label or 'Photographers\' Identities')..']'..p.getCatForId( 'PIC' )
end
 
function p.plwabnLink( id, label )
--P7293's format regex: 981[0-9]{8}05606 (e.g. 9810696457305606)
--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
if not id:match( '^981%d%d%d%d%d%d%d%d05606*$' ) then
return false
return false
end
end
return '[http://mak.bn.org.pl/cgi-bin/KHW/makwww.exe?BM=1&NU=1&IM=4&WI='..id..' '..id..']'..p.getCatForId( 'PLWABN' )
return '[http://mak.bn.org.pl/cgi-bin/KHW/makwww.exe?BM=1&NU=1&IM=4&WI='..id..' '..(label or 'Poland')..']'..p.getCatForId( 'PLWABN' )
end
end


function p.publonsLink( id )
function p.publonsLink( id, label )
--P3829's format regex: \d+ (e.g. 654601)
--P3829's format regex: \d+ (e.g. 654601)
if not id:match( '^%d+$' ) then
if not id:match( '^%d+$' ) then
return false
return false
end
end
return '[https://publons.com/author/'..id..'/ '..id..']'..p.getCatForId( 'Publons' )
return '[https://publons.com/author/'..id..'/ '..(label or 'Publons (researchers)')..']'..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
end


function p.ridLink( id )
function p.ridLink( id, label )
--P1053's format regex: [A-Z]{1,3}-\d{4}-(19|20)\d\d (e.g. AAS-5150-2020)
--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
if not id:match( '^[A-Z][A-Z]?[A-Z]?%-%d%d%d%d%-19%d%d$' ) and
Line 598: Line 655:
return false
return false
end
end
return '[https://www.researcherid.com/rid/'..id..' '..id..']'..p.getCatForId( 'RID' )
return '[https://www.researcherid.com/rid/'..id..' '..(label or 'ResearcherID')..']'..p.getCatForId( 'RID' )
end
end


function p.rismLink( id )
function p.rismLink( id, label )
--P5504's format regex: (pe|ks)?\[1-9]d* (e.g. pe30006410)
--P5504's format regex: (pe|ks)?\[1-9]d* (e.g. pe30006410)
if not id:match( '^pe[1-9]%d*$' ) and --99% start with 'pe'
if not id:match( '^pe[1-9]%d*$' ) and --99% start with 'pe'
Line 608: Line 665:
return false
return false
end
end
return '[https://opac.rism.info/search?id='..id..' '..id..']'..p.getCatForId( 'RISM' )
return '[https://opac.rism.info/search?id='..id..' '..(label or 'RISM (France)')..']'..p.getCatForId( 'RISM' )
end
end


function p.reroLink( id )
function p.reroLink( id, label )
--P3065's format regex: 0[1-2]-[A-Z0-9]{1,10} (e.g. 02-A012345678)
--P3065's format regex: 0[1-2]-[A-Z0-9]{1,10} (e.g. 02-A012345678)
if not id:match( '^0[1-2]%-[A-Z%d][A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?$' ) then
if not id:match( '^0[1-2]%-[A-Z%d][A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?$' ) then
return false
return false
end
end
return '[http://data.rero.ch/'..id..' '..id..']'..p.getCatForId( 'RERO' )
return '[http://data.rero.ch/'..id..' '..(label or 'RERO (Switzerland)')..']'..p.getCatForId( 'RERO' )
end
end


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


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


function p.rslLink( id )
function p.rslLink( id, label )
--P947's format regex: \d{1,9} (e.g. 123456789)
--P947's format regex: \d{1,9} (e.g. 123456789)
if not id:match( '^%d%d?%d?%d?%d?%d?%d?%d?%d?$' ) then
if not id:match( '^%d%d?%d?%d?%d?%d?%d?%d?%d?$' ) then
return false
return false
end
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
return '[http://aleph.rsl.ru/F?func=find-b&find_code=SYS&adjacent=Y&local_base=RSL11&request='..id..'&CON_LNG=ENG '..(label or 'Russia')..']'..p.getCatForId( 'RSL' ) --no https as of 9/2019
end
 
function p.iccuLink( id )
--P396's format regex: IT\\ICCU\\(\d{10}|\D\D[\D\d]\D\\\d{6}) (e.g. IT\ICCU\CFIV\000163)
if not id:match( '^IT\\ICCU\\%d%d%d%d%d%d%d%d%d%d$' ) and
  not id:match( '^IT\\ICCU\\%u%u[%u%d]%u\\%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/opacsbn/opac/iccu/scheda_authority.jsp?bid='..id..' '..id..']'..p.getCatForId( 'ICCU' )
end
end


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


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


function p.snacLink( id )
function p.snacLink( id, label )
--P3430's format regex: \d*[A-Za-z][0-9A-Za-z]* (e.g. A)
--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
if not id:match( '^%d*[A-Za-z][0-9A-Za-z]*$' ) then
return false
return false
end
end
return '[https://snaccooperative.org/ark:/99166/'..id..' '..id..']'..p.getCatForId( 'SNAC-ID' )
return '[https://snaccooperative.org/ark:/99166/'..id..' '..(label or 'Social Networks and Archival Context')..']'..p.getCatForId( 'SNAC-ID' )
end
end


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


function p.s2authoridLink( id )
function p.s2authoridLink( id, label )
--P4012's format regex: [1-9]\d* (e.g. 1796130)
--P4012's format regex: [1-9]\d* (e.g. 1796130)
if not id:match( '^[1-9]%d*$' ) then
if not id:match( '^[1-9]%d*$' ) then
return false
return false
end
end
return '[https://www.semanticscholar.org/author/'..id..' '..id..']'..p.getCatForId( 'Semantic Scholar author' ) --special cat name
return '[https://www.semanticscholar.org/author/'..id..' '..(label or 'Semantic Scholar')..']'..p.getCatForId( 'Semantic Scholar author' ) --special cat name
end
end


function p.ta98Link( id )
function p.ta98Link( id, label )
--P1323's format regex: A\d{2}\.\d\.\d{2}\.\d{3}[FM]? (e.g. A12.3.45.678)
--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
if not id:match( '^A%d%d%.%d%.%d%d%.%d%d%d[FM]?$' ) then
return false
return false
end
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' )
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..' '..(label or 'Terminologia Anatomica')..']'..p.getCatForId( 'TA98' )
end
end


function p.tdviaLink( id )
function p.tdviaLink( id, label )
--P7314's format regex: [a-z/-]+] (e.g. barkan-omer-lutfi)
--P7314's format regex: [a-z/-]+] (e.g. barkan-omer-lutfi)
if not id:match( '^[a-z/-]+$' ) then
if not id:match( '^[a-z/-]+$' ) then
return false
return false
end
end
return '[https://islamansiklopedisi.org.tr/'..id..' '..id..']'..p.getCatForId( 'TDVİA' )
return '[https://islamansiklopedisi.org.tr/'..id..' '..(label or 'Encyclopedia of Islam')..']'..p.getCatForId( 'TDVİA' )
end
end


function p.teLink( id )
function p.teLink( id, label )
--P1693's format regex: E[1-8]\.\d{1,2}\.\d{1,2}\.\d{1,2}\.\d{1}\.\d{1}\.\d{1,3} (e.g. E1.23.45.67.8.9.0)
--P1693's format regex: E[1-8]\.\d{1,2}\.\d{1,2}\.\d{1,2}\.\d{1}\.\d{1}\.\d{1,3} (e.g. E1.23.45.67.8.9.0)
local e1, e2 = id:match( '^E([1-8])%.(%d%d?)%.%d%d?%.%d%d?%.%d%.%d%.%d%d?%d?$' )
local e1, e2 = id:match( '^E([1-8])%.(%d%d?)%.%d%d?%.%d%d?%.%d%.%d%.%d%d?%d?$' )
Line 719: Line 767:
TEnum = TEnum..e2
TEnum = TEnum..e2
end
end
return '[http://www.unifr.ch/ifaa/Public/EntryPage/ViewTE/'..TEnum..'.html '..id..']'..p.getCatForId( 'TE' )
return '[http://www.unifr.ch/ifaa/Public/EntryPage/ViewTE/'..TEnum..'.html '..(label or 'Terminologia Embryologica')..']'..p.getCatForId( 'TE' )
end
end


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


function p.thLink( id )
function p.thLink( id, label )
--P1694's format regex: H\d\.\d{2}\.\d{2}\.\d\.\d{5} (e.g. H1.23.45.6.78901)
--P1694's format regex: H\d\.\d{2}\.\d{2}\.\d\.\d{5} (e.g. H1.23.45.6.78901)
local h1, h2 = id:match( '^H(%d)%.(%d%d)%.%d%d%.%d%.%d%d%d%d%d$' )
local h1, h2 = id:match( '^H(%d)%.(%d%d)%.%d%d%.%d%.%d%d%d%d%d$' )
Line 737: Line 785:
end
end
local THnum = 'THh'..h1..h2 --no formatter URL in WD, probably due to this complexity
local THnum = 'THh'..h1..h2 --no formatter URL in WD, probably due to this complexity
return '[http://www.unifr.ch/ifaa/Public/EntryPage/ViewTH/'..THnum..'.html '..id..']'..p.getCatForId( 'TH' )
return '[http://www.unifr.ch/ifaa/Public/EntryPage/ViewTH/'..THnum..'.html '..(label or 'Terminologia Histologica')..']'..p.getCatForId( 'TH' )
end
end


function p.tlsLink( id )
function p.tlsLink( id, label )
local id2 = id:gsub(' +', '_')
id = id:gsub(' +', '_')
--P1362's format regex: \p{Lu}[\p{L}\d_',\.\-\(\)\*/–]{3,59} (e.g. Abcd)
--P1362's format regex: \p{Lu}[\p{L}\d_',\.\-\(\)\*/–]{3,59} (e.g. Abcd)
local class = "[%a%d_',%.%-%(%)%*/–]"
local class = "[%a%d_',%.%-%(%)%*/–]"
local regex = "^%u"..string.rep(class, 3)..string.rep(class.."?", 56).."$"
local regex = "^%u"..string.rep(class, 3)..string.rep(class.."?", 56).."$"
if not mw.ustring.match( id2, regex ) then
if not mw.ustring.match( id, regex ) then
return false
return false
end
end
return '[http://tls.theaterwissenschaft.ch/wiki/'..id2..' '..id..']'..p.getCatForId( 'TLS' ) --no https as of 9/2019
return '[http://tls.theaterwissenschaft.ch/wiki/'..id..' '..(label or 'Theaterlexikon (Switzerland)')..']'..p.getCatForId( 'TLS' ) --no https as of 9/2019
end
end


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


function p.ukparlLink( id )
function p.ukparlLink( id, label )
--P6213's format regex: [a-zA-Z\d]{8} (e.g. AQUupyiR)
--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
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
return false
end
end
return '[https://id.parliament.uk/'..id..' '..id..']'..p.getCatForId( 'UKPARL' )
return '[https://id.parliament.uk/'..id..' '..(label or 'UK Parliament')..']'..p.getCatForId( 'UKPARL' )
end
end


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


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


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


function p.viafLink( id )
function p.viafLink( id, label )
--P214's format regex: [1-9]\d(\d{0,7}|\d{17,20}) (e.g. 123456789, 1234567890123456789012)
--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
if not id:match( '^[1-9]%d%d?%d?%d?%d?%d?%d?%d?$' ) and
Line 799: Line 847:
end
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..']]'.
-- 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' )
return '[https://viaf.org/viaf/'..id..' '..(label or 'VIAF')..']'..p.getCatForId( 'VIAF' )
end
end


Line 873: Line 921:
local wikiTable = '{| class="wikitable sortable"\n'..
local wikiTable = '{| class="wikitable sortable"\n'..
  '! rowspan=2 | Parameter\n'..
  '! rowspan=2 | Parameter\n'..
  '! rowspan=2 | Label\n'..
  '! rowspan=2 | Section\n'..
  '! rowspan=2 | Appears as\n'..
  '! rowspan=2; data-sort-type=number | Wikidata property\n'..
  '! rowspan=2; data-sort-type=number | Wikidata property\n'..
  '! colspan=4 | Tracking categories and page counts\n'..
  '! colspan=4 | Tracking categories and page counts\n'..
Line 882: Line 931:
  '! [[:Category:Wikipedia articles with faulty authority control information|'..'Faulty IDs]]\n'..
  '! [[:Category:Wikipedia articles with faulty authority control information|'..'Faulty IDs]]\n'..
  '|-\n'
  '|-\n'
local lang = mw.getContentLanguage()
local lang = mw.getContentLanguage()
for _, conf in pairs( p.conf ) do
for _, conf in pairs( p.conf ) do
local param, link, pid = conf[1], conf[2], conf[3]
local param, pid, section = conf[1], conf[2], conf[4]
local appearsAs
if param == "WORLDCATID" then
-- WorldCat is special
appearsAs = "[https://www.worldcat.org/identities/lccn-n78039510 WorldCat]"
elseif conf.prefix then
appearsAs = conf.prefix
else
appearsAs = conf[3](conf[5])
end
local link = conf.link or param .. ' (identifier)'
local category = conf.category or param
local category = conf.category or param
local args = { id = 'f', pid }
local args = { id = 'f', pid }
Line 899: Line 957:
local miscCount =    lang:formatNum( mw.site.stats.pagesInCategory(miscCat, 'pages') )
local miscCount =    lang:formatNum( mw.site.stats.pagesInCategory(miscCat, 'pages') )
local faultyCount =  lang:formatNum( mw.site.stats.pagesInCategory(faultyCat, 'pages') )
local faultyCount =  lang:formatNum( mw.site.stats.pagesInCategory(faultyCat, 'pages') )
--concat
--concat
wikiTable = wikiTable..'\n'..
wikiTable = wikiTable..'\n'..
'|-\n'..
'|-\n'..
'||'..param..
'||[['..link..'|'..param..']]'..
'||'..link..
'||'..section..
'||'..appearsAs..
'||data-sort-value='..pid..'|'..wpl..
'||data-sort-value='..pid..'|'..wpl..
'||style="text-align: right;"|[[:Category:'..articleCat..'|'..articleCount..']]'..
'||style="text-align: right;"|[[:Category:'..articleCat..'|'..articleCount..']]'..
Line 916: Line 976:
local articleCat = 'Wikipedia articles with '..w..' identifiers'
local articleCat = 'Wikipedia articles with '..w..' identifiers'
local articleCount = lang:formatNum( mw.site.stats.pagesInCategory(articleCat, 'pages') )
local articleCount = lang:formatNum( mw.site.stats.pagesInCategory(articleCat, 'pages') )
local appearsAs
if w == "WorldCat-LCCN" then
appearsAs = "[https://www.worldcat.org/identities/lccn-n79-113947 WorldCat (via Library of Congress)]"
else
appearsAs = "[https://www.worldcat.org/identities/containsVIAFID/12345789 WorldCat (via VIAF)]"
end
wikiTable = wikiTable..'\n'..
wikiTable = wikiTable..'\n'..
'|-\n'..
'|-\n'..
'||'..'—'..
'||'..'—'..
'||'..w..
'||General'..
'||'..appearsAs..
'||data-sort-value='..w..'|'..'—'..
'||data-sort-value='..w..'|'..'—'..
'||style="text-align: right;"|[[:Category:'..articleCat..'|'..articleCount..']]'..
'||style="text-align: right;"|[[:Category:'..articleCat..'|'..articleCount..']]'..
Line 927: Line 994:
end
end
return wikiTable..'\n|}'
return require("Module:Suppress categories").main(wikiTable)..'\n|}'
end
end


Line 936: Line 1,003:
-- 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.
-- 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.


-- Parameter format: { 'parameter name', 'label', propertyId # in Wikidata, formatting/validation function }
 
-- Parameter format: { 'parameter name', propertyId # in Wikidata, formatting/validation function, section, example ID for documentation }
-- Optional named parameters: `link` to override the link in the documentation (defaults to parameter + (identifer)),
-- category to override the ID in category names (defaults to parameter),
-- prefix to include a prefix (usually a wikilink explaining what the identifier is) before the external link itself
p.conf = {
p.conf = {
{ 'AAG', '[[AAG (identifier)|AAG]]', 3372, p.aagLink },
{ 'AAG', 3372, p.aagLink, "Art galleries and museums", "1"},
{ 'ACM-DL', '[[ACM DL (identifier)|ACM DL]]', 864, p.acmLink },
{ 'ACM-DL', 864, p.acmLink, "Scientific databases", "12345678901", link="ACM DL (identifier)"},
{ 'ADB', '[[ADB (identifier)|ADB]]', 1907, p.adbLink },
{ 'ADB', 1907, p.adbLink,"Biographical dictionaries", "barton-sir-edmund-toby-71"},
{ 'AGSA', '[[AGSA (identifier)|AGSA]]', 6804, p.agsaLink },
{ 'AGSA', 6804, p.agsaLink, "Art galleries and museums", "3625"},
{ 'autores.uy', '[[autores.uy (identifier)|autores.uy]]', 2558, p.autoresuyLink },
{ 'autores.uy', 2558, p.autoresuyLink, "Biographical dictionaries", "12345"},
{ 'AWR', '[[AWR (identifier)|AWR]]', 4186, p.awrLink },
{ 'AWR', 4182, p.awrLink, "Biographical dictionaries", "PR00768b"},
{ 'BALaT', '[[BALaT (identifier)|BALaT]]', 3293, p.balatLink },
{ 'BALaT', 3293, p.balatLink, "Art research institutes", "1"},
{ 'BIBSYS', '[[BIBSYS (identifier)|BIBSYS]]', 1015, p.bibsysLink },
{ 'BIBSYS', 1015, p.bibsysLink, "National libraries", "1234567890123"},
{ 'Bildindex', '[[Bildindex (identifier)|Bildindex]]', 2092, p.bildLink },
{ 'Bildindex', 2092, p.bildLink, "Art research institutes", "1"},
{ 'BNC', '[[BNC (identifier)|BNC]]', 1890, p.bncLink },
{ 'BNC', 1890, p.bncLink, "National libraries", "123456789"},
{ 'BNE', '[[BNE (identifier)|BNE]]', 950, p.bneLink },
{ 'BNE', 950, p.bneLink, "National libraries", "XX1234567"},
{ 'BNF', '[[BNF (identifier)|BNF]]', 268, p.bnfLink },
{ 'BNF', 268, p.bnfLink, "National libraries", "123456789"},
{ 'Botanist', '[[Botanist (identifier)|Botanist]]', 428, p.botanistLink },
{ 'Botanist', 428, p.botanistLink , "Scientific databases", "L."},
{ 'BPN', '[[BPN (identifier)|BPN]]', 651, p.bpnLink },
{ 'BPN', 651, p.bpnLink , "Biographical dictionaries", "12345678"},
{ 'CANTIC', '[[CANTIC (identifier)|CANTIC]]', 1273, p.canticLink },
{ 'CANTIC', 1273, p.canticLink, "National libraries", "a12345678"},
{ 'CINII', '[[CiNii (identifier)|CiNii]]', 271, p.ciniiLink },
{ 'CINII', 271, p.ciniiLink, "Scientific databases", "DA12345678", link = "CiNii (identifier)"},
{ 'CWGC', '[[CWGC (identifier)|CWGC]]', 1908, p.cwgcLink },
{ 'CWGC', 1908, p.cwgcLink, "Other", "1234567"},
{ 'DAAO', '[[DAAO (identifier)|DAAO]]', 1707, p.daaoLink },
{ 'DAAO', 1707, p.daaoLink, "Art research institutes", "rolf-harris"},
{ 'DBLP', '[[DBLP (identifier)|DBLP]]', 2456, p.dblpLink },
{ 'DBLP', 2456, p.dblpLink, "Scientific databases", "123/123"},
{ 'DIB', '[[DIB (identifier)|DIB]]', 6829, p.dibLink },
{ 'DIB', 6829, p.dibLink, "Biographical dictionaries", "a1234"},
{ 'DSI', '[[DSI (identifier)|DSI]]', 2349, p.dsiLink },
{ 'DSI', 2349, p.dsiLink, "Art research institutes", "1538"},
{ 'FAST', '[[FAST (identifier)|FAST]]', 2163, p.fastLink },
{ 'FAST', 2163, p.fastLink, "Other", "1"},
{ 'FNZA', '[[FNZA (identifier)|FNZA]]', 6792, p.fnzaLink },
{ 'FNZA', 6792, p.fnzaLink, "Art research institutes", "12"},
{ 'GND', '[[GND (identifier)|GND]]', 227, p.gndLink },
{ 'GND', 227, p.gndLink, "General", "4079154-3"},
{ 'HDS', '[[HDS (identifier)|HDS]]', 902, p.hdsLink },
{ 'HDS', 902, p.hdsLink, "Other", "050123"},
{ 'IAAF', '[[IAAF (identifier)|IAAF]]', 1146, p.iaafLink },
{ 'IAAF', 1146, p.iaafLink, "Other", "123"},
{ 'ICCU', '[[ICCU (identifier)|ICCU]]', 396, p.iccuLink }, --formerly SBN
{ 'ICCU', 396, p.iccuLink, "National libraries", "IT\\ICCU\\CFIV\\000163"}, --formerly SBN
{ 'ICIA', '[[ICIA (identifier)|ICIA]]', 1736, p.iciaLink },
{ 'ICIA', 1736, p.iciaLink, "Art research institutes", "1"},
{ 'IEU', '[[IEU (identifier)|IEU]]', 9070, p.ieuLink },
{ 'IEU', 9070, p.ieuLink, "Other", "N\\A\\NationalAcademyofArtandArchitecture"},
{ 'ISNI', '[[ISNI (identifier)|ISNI]]', 213, p.isniLink },
{ 'ISNI', 213, p.isniLink, "General", "0000-0000-6653-4145", prefix = '[[ISNI (identifier)|ISNI]]'},
{ 'Joconde', '[[Joconde (identifier)|Joconde]]' , 347, p.jocondeLink },
{ 'Joconde', 347, p.jocondeLink, "Art research institutes", "12345678901"},
{ 'KULTURNAV', '[[KulturNav (identifier)|KulturNav]]', 1248, p.kulturnavLink },
{ 'KULTURNAV', 1248, p.kulturnavLink, "Art research institutes", "12345678-1234-1234-1234-1234567890AB", link="KulturNav (identifier)"},
{ 'LCCN', '[[LCCN (identifier)|LCCN]]', 244, p.lccnLink },
{ 'LCCN', 244, p.lccnLink, "National libraries", "n78039510"},
{ 'LIR', '[[LIR (identifier)|LIR]]', 886, p.lirLink },
{ 'LIR', 886, p.lirLink, "Other", "1"},
{ 'LNB', '[[LNB (identifier)|LNB]]', 1368, p.lnbLink },
{ 'LNB', 1368, p.lnbLink, "National libraries", "123456789"},
{ 'Léonore', '[[Léonore (identifier)|Léonore]]', 640, p.leonoreLink },
{ 'Léonore', 640, p.leonoreLink, "Other", "LH/1/1", prefix = "[[Léonore (identifier)|Léonore (France)]]"},
{ 'MA', '[[MA (identifier)|MA]]', 6366, p.maLink },
{ 'MA', 6366, p.maLink, "Other", "123456789"},
{ 'MBA', '[[MBA (identifier)|MBA]]', 434, p.mbaLink, category = 'MusicBrainz' }, --special cat name
{ 'MBA', 434, p.mbaLink, "Other", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz'}, --special cat name
{ 'MBAREA', '[[MBAREA (identifier)|MBAREA]]', 982, p.mbareaLink, category = 'MusicBrainz area' }, --special cat name
{ 'MBAREA', 982, p.mbareaLink, "Other", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz area' }, --special cat name
{ 'MBI', '[[MBI (identifier)|MBI]]', 1330, p.mbiLink, category = 'MusicBrainz instrument' }, --special cat name
{ 'MBI', 1330, p.mbiLink, "Other", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz instrument' }, --special cat name
{ 'MBL', '[[MBL (identifier)|MBL]]', 966, p.mblLink, category = 'MusicBrainz label' }, --special cat name
{ 'MBL', 966, p.mblLink, "Other", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz label' }, --special cat name
{ 'MBP', '[[MBP (identifier)|MBP]]', 1004, p.mbpLink, category = 'MusicBrainz place' }, --special cat name
{ 'MBP', 1004, p.mbpLink, "Other", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz place' }, --special cat name
{ 'MBRG', '[[MBRG (identifier)|MBRG]]', 436, p.mbrgLink, category = 'MusicBrainz release group' }, --special cat name
{ 'MBRG', 436, p.mbrgLink, "Other", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz release group' }, --special cat name
{ 'MBS', '[[MBS (identifier)|MBS]]', 1407, p.mbsLink, category = 'MusicBrainz series' }, --special cat name
{ 'MBS', 1407, p.mbsLink, "Other", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz series' }, --special cat name
{ 'MBW', '[[MBW (identifier)|MBW]] work', 435, p.mbwLink, category = 'MusicBrainz work' }, --special cat name
{ 'MBW', 435, p.mbwLink, "Other", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz work' }, --special cat name
{ 'MGP', '[[MGP (identifier)|MGP]]', 549, p.mgpLink },
{ 'MGP', 549, p.mgpLink, "Scientific databases", "123456"},
{ 'NARA', '[[NARA (identifier)|NARA]]', 1225, p.naraLink },
{ 'NARA', 1225, p.naraLink, "Other", "12345678"},
{ 'NCL', '[[NCL (identifier)|NBL]]', 1048, p.nclLink },
{ 'NCL', 1048, p.nclLink, "National libraries", "1081436"},
{ 'NDL', '[[NDL (identifier)|NDL]]', 349, p.ndlLink },
{ 'NDL', 349, p.ndlLink, "National libraries", "012345678"},
{ 'NGV', '[[NGV (identifier)|NGV]]', 2041, p.ngvLink },
{ 'NGV', 2041, p.ngvLink, "Art galleries and museums", "12354"},
{ 'NKC', '[[NKC (identifier)|NKC]]', 691, p.nkcLink },
{ 'NKC', 691, p.nkcLink, "National libraries", "abcd12345678901234"},
{ 'NLA', '[[NLA (identifier)|NLA]]', 409, p.nlaLink },
{ 'NLA', 409, p.nlaLink, "National libraries", "123456789012"},
{ 'NLG', '[[NLG (identifier)|NLG]]', 3348, p.nlgLink },
{ 'NLG', 3348, p.nlgLink, "National libraries", "12345678"},
{ 'NLI', '[[NLI (identifier)|NLI]]', 949, p.nliLink },
{ 'NLI', 949, p.nliLink, "National libraries", "123456789"},
{ 'NLK', '[[NLK (identifier)|NLK]]', 5034, p.nlkLink },
{ 'NLK', 5034, p.nlkLink, "National libraries", "KAB197000000"},
{ 'NLP', '[[NLP (identifier)|NLP]]', 1695, p.nlpLink },
{ 'NLP', 1695, p.nlpLink, "National libraries", "9810123456789012345"},
{ 'NLR', '[[NLR (identifier)|NLR]]', 1003, p.nlrLink },
{ 'NLR', 1003, p.nlrLink, "National libraries", "123456789"},
{ 'NSK', '[[NSK (identifier)|NSK]]', 1375, p.nskLink },
{ 'NSK', 1375, p.nskLink, "National libraries", "123456789"},
{ 'NTA', '[[NTA (identifier)|NTA]]', 1006, p.ntaLink },
{ 'NTA', 1006, p.ntaLink, "National libraries", "12345678X"},
{ 'ORCID', '[[ORCID (identifier)|ORCID]]', 496, p.orcidLink },
{ 'ORCID', 496, p.orcidLink, "General", "0000-0002-7398-5483", prefix = '[[ORCID (identifier)|ORCID]]'},
{ 'PIC', '[[PIC (identifier)|PIC]]', 2750, p.picLink },
{ 'PIC', 2750, p.picLink, "Art research institutes", "1"},
{ 'PLWABN', '[[PLWABN (identifier)|PLWABN]]', 7293, p.plwabnLink },
{ 'PLWABN', 7293, p.plwabnLink, "National libraries", "9812345678905606"},
{ 'Publons', '[[Publons (identifier)|Publons]]', 3829, p.publonsLink },
{ 'Publons', 3829, p.publonsLink, "Scientific databases", "2776255"},
{ 'RERO', '[[RERO (identifier)|RERO]]', 3065, p.reroLink },
{ 'RID', 1053, p.ridLink, "Scientific databases", "A-1234-1934"},
{ 'RID', '[[RID (identifier)|ResearcherID]]', 1053, p.ridLink },
{ 'RISM', 5504, p.rismLink, "Other", "pe1",  prefix = '[[RISM (identifier)|RISM (France)]]'},
{ 'RISM', '[[RISM (identifier)|RISM]]', 5504, p.rismLink },
{ 'RERO', 3065, p.reroLink, "Other", "02-A012345678", prefix = '[[RERO (identifier)|RERO (Switzerland)]]'},
{ 'RKDartists', '[[RKDartists (identifier)|RKD]]', 650, p.rkdartistsLink },
{ 'RKDartists', 650, p.rkdartistsLink, "Art research institutes", "123456"},
{ 'RKDID', '[[RKDID (identifier)|RKDimages ID]]', 350, p.rkdidLink },
{ 'RKDID', 350, p.rkdidLink, "Art research institutes", "123456"},
{ 'RSL', '[[RSL (identifier)|RSL]]', 947, p.rslLink },
{ 'RSL', 947, p.rslLink, "National libraries", "123456789"},
{ 'SELIBR', '[[SELIBR (identifier)|SELIBR]]', 906, p.selibrLink },
{ 'SELIBR', 906, p.selibrLink, "National libraries", "123456"},
{ 'SIKART', '[[SIKART (identifier)|SIKART]]', 781, p.sikartLink },
{ 'SIKART', 781, p.sikartLink, "Art research institutes", '123456789'},
{ 'SNAC-ID', '[[SNAC-ID (identifier)|SNAC]]', 3430, p.snacLink },
{ 'SNAC-ID', 3430, p.snacLink, "Other", "A"},
{ 'SUDOC', '[[SUDOC (identifier)|SUDOC]]', 269, p.sudocLink },
{ 'SUDOC', 269, p.sudocLink, "Other", "026927608", prefix = '[[SUDOC (identifier)|SUDOC (France)]]'},
{ 'S2AuthorId', '[[S2AuthorId (identifier)|S2AuthorId]]', 4012, p.s2authoridLink, category = 'Semantic Scholar author' }, --special cat name
{ 'S2AuthorId', 4012, p.s2authoridLink, "Scientific databases", "1796130", category = 'Semantic Scholar author' }, --special cat name
{ 'TA98', '[[TA98 (identifier)|TA98]]', 1323, p.ta98Link },
{ 'TA98', 1323, p.ta98Link, "Scientific databases", "A12.3.45.678"},
{ 'TDVİA', '[[TDVİA (identifier)|TDVİA]]', 7314, p.tdviaLink },
{ 'TDVİA', 7314, p.tdviaLink, "Other", "asim-b-behdele"},
{ 'TE', '[[TE (identifier)|TE]]', 1693, p.teLink },
{ 'TE', 1693, p.teLink, "Scientific databases", "E1.23.45.67.8.9.0"},
{ 'TePapa', '[[TePapa (identifier)|TePapa]]', 3544, p.tepapaLink },
{ 'TePapa', 3544, p.tepapaLink, "Art galleries and museums", "1"},
{ 'TH', '[[TH (identifier)|TH]]', 1694, p.thLink },
{ 'TH', 1694, p.thLink, "Scientific databases", "H1.23.45.6.78901"},
{ 'TLS', '[[TLS (identifier)|TLS]]', 1362, p.tlsLink },
{ 'TLS', 1362, p.tlsLink, "Other", "Abcd"},
{ 'Trove', '[[Trove (identifier)|Trove]]', 1315, p.troveLink }, --formerly NLA-person
{ 'Trove', 1315, p.troveLink, "Other", "12345678", prefix = '[[Trove (identifier)|Trove (Australia)]]'}, --formerly NLA-person
{ 'UKPARL', '[[UKPARL (identifier)|UKPARL]]', 6213, p.ukparlLink },
{ 'UKPARL', 6213, p.ukparlLink, "Other", "AQUupyiR"},
{ 'ULAN', '[[ULAN (identifier)|ULAN]]', 245, p.ulanLink },
{ 'ULAN', 245, p.ulanLink, "Art research institutes", "500123456"},
{ 'USCongress', '[[US Congress (identifier)|US Congress]]', 1157, p.uscongressLink },
{ 'USCongress', 1157, p.uscongressLink, "Other", "A000123", link = "US Congress (identifier)"},
{ 'VcBA', '[[VcBA (identifier)|VcBA]]', 8034, p.vcbaLink },
{ 'VcBA', 8034, p.vcbaLink, "National libraries", "494/9793"},
{ 'VIAF', '[[VIAF (identifier)|VIAF]]', 214, p.viafLink },
{ 'VIAF', 214, p.viafLink, "General", "123456789", prefix = "[[VIAF (identifier)|VIAF]]"},
{ 'WORLDCATID', '[[WorldCat Identities (identifier)|WorldCat Identities]]', 7859, nil },
{ 'WORLDCATID', 7859, nil, "General", nil, link = "WorldCat Identities (identifier)"},
}
}


Line 1,062: Line 1,133:
local parentArgs = frame:getParent().args --WD IDs added here later
local parentArgs = frame:getParent().args --WD IDs added here later
local iParentArgs = 0 --count original/manual parent args only later
local iParentArgs = 0 --count original/manual parent args only later
local elements = {} --create/insert rows later
local worldcatCat = ''
local worldcatCat = ''
local multipleIdCat = ''
local multipleIdCat = ''
Line 1,105: Line 1,175:
local iMatches = 0
local iMatches = 0
for _, params in ipairs( p.conf ) do
for _, params in ipairs( p.conf ) do
if params[3] > 0 then
if params[2] > 0 then
local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]]
local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]]
if val == nil or val == '' then
if val == nil or val == '' then
local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[3] )
local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[2] )
if wikidataIds[1] then
if wikidataIds[1] then
if val == '' and (namespace == 0 or testcases) then
if val == '' and (namespace == 0 or testcases) then
Line 1,118: Line 1,188:
else
else
iParentArgs = iParentArgs + 1
iParentArgs = iParentArgs + 1
local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[3] )
local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[2] )
if wikidataIds[1] and differentOnWDCat == '' then
if wikidataIds[1] and differentOnWDCat == '' then
local bMatch = false
local bMatch = false
Line 1,134: Line 1,204:
end
end
end
end
--Configured rows
--Configured rows
local rct = 0
local rct = 0
local sectionOrder = {"General","National libraries","Art galleries and museums",
  "Art research institutes","Biographical dictionaries","Scientific databases",
  "Other"}
local sections = {
["General"] = {},
["National libraries"] = {},
["Art galleries and museums"] = {},
["Art research institutes"] = {},
["Biographical dictionaries"] = {},
["Scientific databases"] = {},
["Other"] = {}
}
-- Don't show NLP is PLWABN is present, since they both go to the National Library of Poland
-- and the library has deprecated NLP IDs in favor of PLWABN IDs
if parentArgs.PLWABN or parentArgs.plwabn then
parentArgs.NLP = ''
parentArgs.nlp = ''
end
for _, params in ipairs( p.conf ) do
for _, params in ipairs( p.conf ) do
local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]]
local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]]
local tval, tlinks = {}, {} --init tables
local tval, tlinks = {}, {} --init tables
if val and val ~= '' and type(params[4]) == 'function' then
if val and val ~= '' and type(params[3]) == 'function' then
table.insert( tval, val )
table.insert( tval, val )
table.insert( tlinks, params[4]( val ) )
if params.prefix then
table.insert( tlinks, params[3]( val, "1" ) )
else
table.insert( tlinks, params[3]( val ) )
end
end
end
--collect other unique vals (IDs) from WD, if present
--collect other unique vals (IDs) from WD, if present
if itemId and tval[1] then
if itemId and tval[1] then
local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[3] )
local nextIdVal = 2
local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[2] )
for _, v in pairs( wikidataIds ) do
for _, v in pairs( wikidataIds ) do
local bnew = true
local bnew = true
Line 1,154: Line 1,246:
if bnew then
if bnew then
table.insert( tval, v )
table.insert( tval, v )
table.insert( tlinks, params[4]( v ) )
table.insert( tlinks, params[3]( v, tostring(nextIdVal) ) )
nextIdVal = nextIdVal + 1
end
end
end
end
Line 1,160: Line 1,253:
--assemble
--assemble
if tval[1] then
if tval[1] then
table.insert( elements, p.createRow( params[1], params[2]..':', tval, nil, tlinks, true, params.category ) )
table.insert( sections[params[4]], p.createRow( params[1], tval, nil, tlinks, true, params.category, params.prefix) )
rct = rct + 1
rct = rct + 1
if tval[2] then
if tval[2] then
Line 1,166: Line 1,259:
end
end
end
end
end
end
Line 1,171: Line 1,265:
local worldcatId = parentArgs['worldcatid'] or parentArgs['WORLDCATID']
local worldcatId = parentArgs['worldcatid'] or parentArgs['WORLDCATID']
if worldcatId and worldcatId ~= '' then --if WORLDCATID present & unsuppressed
if worldcatId and worldcatId ~= '' then --if WORLDCATID present & unsuppressed
table.insert( elements, p.createRow( 'WORLDCATID', '', worldcatId, '[[WorldCat Identities (identifier)|WorldCat Identities]]: [https://www.worldcat.org/identities/'..mw.uri.encode(worldcatId, 'PATH')..' '..worldcatId..']', nil, false ) ) --Validation?
table.insert( sections["General"], p.createRow( 'WORLDCATID', worldcatId, '[https://www.worldcat.org/identities/'..mw.uri.encode(worldcatId, 'PATH')..' WorldCat]', nil, false ) ) --Validation?
worldcatCat = p.getCatForId( 'WORLDCATID' )
worldcatCat = p.getCatForId( 'WORLDCATID' )
elseif worldcatId == nil then --if WORLDCATID absent but unsuppressed
elseif worldcatId == nil then --if WORLDCATID absent but unsuppressed
Line 1,177: Line 1,271:
local lccnId = parentArgs['lccn'] or parentArgs['LCCN']
local lccnId = parentArgs['lccn'] or parentArgs['LCCN']
if viafId and viafId ~= '' and p.viafLink( viafId ) then --VIAF must be present, unsuppressed, & validated
if viafId and viafId ~= '' and p.viafLink( viafId ) then --VIAF must be present, unsuppressed, & validated
table.insert( elements, p.createRow( 'VIAF', '', viafId, '[[WorldCat Identities (identifier)|WorldCat Identities]] (via VIAF): [https://www.worldcat.org/identities/containsVIAFID/'..viafId..' '..viafId..']', nil, false ) )
table.insert( sections["General"], p.createRow( 'VIAF', viafId, '[https://www.worldcat.org/identities/containsVIAFID/'..viafId..' WorldCat (via VIAF)]', nil, false ) )
if namespace == 0 then  
if namespace == 0 then  
worldcatCat = '[[Category:Wikipedia articles with WorldCat-VIAF identifiers]]'
worldcatCat = '[[Category:Wikipedia articles with WorldCat-VIAF identifiers]]'
Line 1,185: Line 1,279:
if lccnParts and lccnParts[1] ~= 'sh' then
if lccnParts and lccnParts[1] ~= 'sh' then
local lccnIdFmtd = lccnParts[1]..lccnParts[2]..'-'..lccnParts[3]
local lccnIdFmtd = lccnParts[1]..lccnParts[2]..'-'..lccnParts[3]
table.insert( elements, p.createRow( 'LCCN', '', lccnId, '[[WorldCat Identities (identifier)|WorldCat Identities]] (via LCCN): [https://www.worldcat.org/identities/lccn-'..lccnIdFmtd..' '..lccnIdFmtd..']', nil, false ) )
table.insert( sections["General"], p.createRow( 'LCCN', lccnId, '[https://www.worldcat.org/identities/lccn-'..lccnIdFmtd..' WorldCat (via Library of Congress)]', nil, false ) )
if namespace == 0 then
if namespace == 0 then
worldcatCat = '[[Category:Wikipedia articles with WorldCat-LCCN identifiers]]'
worldcatCat = '[[Category:Wikipedia articles with WorldCat-LCCN identifiers]]'
Line 1,203: Line 1,297:
local outString = ''
local outString = ''
if #elements > 0 then
if rct > 0 then
local sectionID = 1
local args = { pid = 'identifiers' } -- #target the list of identifiers
local args = { pid = 'identifiers' } -- #target the list of identifiers
if testcases and itemId then args = { pid = 'identifiers', qid = itemId } end --expensive
if testcases and itemId then args = { pid = 'identifiers', qid = itemId } end --expensive
local pencil = frame:expandTemplate{ title = 'EditAtWikidata', args = args}
local pencil = frame:expandTemplate{ title = 'EditAtWikidata', args = args}
outString = Navbox._navbox( {
local navboxArgs = {
name  = 'Authority control',
name  = 'Authority control',
navboxclass = 'authority-control',
navboxclass = 'authority-control',
bodyclass = 'hlist',
bodyclass = 'hlist',
group1 = '[[Help:Authority control|Authority control]]'..pencil,
state = parentArgs.state or 'autocollapse',
list1 = table.concat( elements )
navbar = 'off'
} )
}
for _, sectName in ipairs(sectionOrder) do
if #sections[sectName] ~= 0 then
navboxArgs["group" .. sectionID] = sectName
navboxArgs["list" .. sectionID] = table.concat(sections[sectName])
sectionID = sectionID + 1
end
end
if navboxArgs.group2 then
if rct >= 4 then
navboxArgs.title = "[[Help:Authority control|Authority control]]" .. pencil
else
navboxArgs.border = "child"
navboxArgs = {
group1 = "[[Help:Authority control|Authority control]]" .. pencil,
list1 = Navbox._navbox(navboxArgs)
}
end
else
local sect = navboxArgs.group1
if sect == "General" or sect == "Other" then
-- Just say "Authority control" with no label if only general or only other IDs are present
-- since "general" is redundant and "other" is silly when there's nothing to contrast it with
navboxArgs.group1 = "[[Help:Authority control|Authority control]]" .. pencil
else
navboxArgs.group1 = "[[Help:Authority control|Authority control: " .. sect .. "]] " .. pencil
end
end
outString = Navbox._navbox(navboxArgs)
end
end

Latest revision as of 23:01, 14 June 2021

Documentation for this module may be created at Module:Authority control/doc

require('Module:No globals')

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

--[[==========================================================================]]
--[[                            Category functions                            ]]
--[[==========================================================================]]

function p.getCatForId( id )
	local catName = ''
	if namespace == 0 then
		catName = 'Wikipedia articles with '..id..' identifiers'
	elseif namespace == 2 and not title.isSubpage then
		catName = 'User pages with '..id..' identifiers'
	else
		catName = 'Miscellaneous pages with '..id..' identifiers'
	end
	return '[[Category:'..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 '[[Category:Pages with red-linked authority control categories]]'
	end
	return ''
end

function p.createRow( id, rawValues, link, links, withUid, specialCat, prefix)
	local catName = 'Wikipedia articles with faulty '..(specialCat or id)..' identifiers'
	if links then -- all links[] use withUid = false; no check needed
		local row = ''
		if prefix then 
			row = row .. '*' .. prefix
		end
		for i, l in ipairs( links ) do
			if i == 1 and not prefix then row = row..'*'
			else           row = row..'\n**' end
			if l then
				row = row..'<span class="uid">'..l..'</span>'
			else
				row = row..'<span class="error">The '..id..' id '..rawValues[i]..' is not valid.</span>[[Category:'..catName..']]'..p.redCatLink(catName)
			end
		end
		return row..'\n'
	elseif link then -- All IDs that have a prefix support multiple identifiers, so prefix is not needed
		if withUid then
			return '*<span class="nowrap"><span class="uid">'..link..'</span></span>\n'
		end
		return '*<span class="nowrap">'..link..'</span>\n'
	end
	
	return '* <span class="error">The '..id..' id '..rawValues..' is not valid.</span>[[Category:'..catName..']]'..p.redCatLink(catName)..'\n'
end

--[[==========================================================================]]
--[[                      Property formatting functions                       ]]
--[[==========================================================================]]

-- 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, label)
	--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..'/ '..(label or 'Auckland')..']'..p.getCatForId( 'AAG' )
end

function p.acmLink( id, label )
	--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..' '..(label or 'Association for Computing Machinery')..']'..p.getCatForId( 'ACM-DL' )
end

function p.adbLink( id, label )
	--P1907's format regex: [a-z][-a-z]+-([1-2]\d|[1-9])\d{0,3} (e.g. barton-sir-edmund-toby-71)
	if not id:match( '^[a-z][-a-z]+-[1-2]%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..' '..(label or 'Australia')..']'..p.getCatForId( 'ADB' )
end

function p.agsaLink( id, label )
	--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..'/ '..(label or 'South Australia')..']'..p.getCatForId( 'AGSA' )
end

function p.autoresuyLink( id, label )
	--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..' '..(label or 'Uruguay')..']'..p.getCatForId( 'autores.uy' )
end

function p.awrLink( id, label )
	--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 '..(label or 'Australian Women\'s Register')..']'..p.getCatForId( 'AWR' )
end

function p.balatLink( id, label )
	--P3293's format regex: \d+ (e.g. 1)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[http://balat.kikirpa.be/object/104257'..id..' '..(label or 'BALaT (Belgium)')..']'..p.getCatForId( 'BALaT' ) --no https as of 9/2019
end

function p.bibsysLink( id, label )
	--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..' '..(label or 'Norway')..']'..p.getCatForId( 'BIBSYS' )
end

function p.bildLink( id, label )
	--P2092's format regex: \d+ (e.g. 1)
	if not id:match( '^%d+$' ) then
		return false
	end
	return '[https://www.bildindex.de/document/obj'..id..' '..(label or 'Bildindex (Germany)')..']'..p.getCatForId( 'Bildindex' )
end

function p.bncLink( id, label )
	--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..' '..(label or 'Chile')..']'..p.getCatForId( 'BNC' )
end

function p.bneLink( id, label )
	--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..' '..(label or 'Spain')..']'..p.getCatForId( 'BNE' ) --no https as of 9/2019
end

function p.bnfLink( id, label )
	--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..' ' .. (label or 'France')..'] [https://data.bnf.fr/ark:/12148/'..id..' (data)]'..p.getCatForId( 'BNF' )
end

function p.botanistLink( id, label )
	--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
	id = id:gsub(' +', '%%20')
	return '[https://www.ipni.org/ipni/advAuthorSearch.do?find_abbreviation='..id..' '..(label or 'International Plant Names Index')..']'..p.getCatForId( 'Botanist' )
end

function p.bpnLink( id, label )
	--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/en/persoon/'..id..' '..(label or 'Netherlands')..']'..p.getCatForId( 'BPN' ) --no https as of 9/2019
end

function p.canticLink( id, label )
	--P1273's format regex: a\d{7}[0-9x] (e.g. a10640745)
	if not id:match( '^a%d%d%d%d%d%d%d[%dx]$' ) then
		return false
	end
	return '[http://cantic.bnc.cat/registres/CUCId/'..id..' '..(label or 'Catalonia')..']'..p.getCatForId( 'CANTIC' ) --no https as of 10/2019
end

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

function p.cwgcLink( id, label )
	--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..'/ '..(label or 'Commonwealth War Graves Commission')..']'..p.getCatForId( 'CWGC' )
end

function p.daaoLink( id, label )
	--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..' '..(label or 'Australian Artists')..']'..p.getCatForId( 'DAAO' )
end

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

function p.dibLink( id, label )
	--P6829's format regex: a\d{4}\d?(-[A-D])? (e.g. a1953)
	if not id:match( '^a%d%d%d%d%d?%-?[A-D]?$' ) then
		return false
	end
	return '[https://dib.cambridge.org/viewReadPage.do?articleId='..id..' '..(label or 'Ireland')..']'..p.getCatForId( 'DIB' )
end

function p.dsiLink( id, label )
	--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..' '..(label or 'Scientific illustrators')..']'..p.getCatForId( 'DSI' )
end

function p.fastLink( id, label )
	--P2163's format regex: [1-9]\d{0,7} (e.g. 1916996)
	if not id:match( '^[1-9]%d?%d?%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[http://id.worldcat.org/fast/'..id..'/ '..(label or 'Faceted Application of Subject Terminology')..']'..p.getCatForId( 'FAST' )
end


function p.fnzaLink( id, label )
	--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..'/ '..(label or 'New Zealand Artists')..']'..p.getCatForId( 'FNZA' )
end

function p.gndLink( id, label )
	--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[012]?%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..' '..(label or 'Integrated Authority File')..']'..p.getCatForId( 'GND' )
end

function p.hdsLink( id, label )
	--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..' '..(label or 'Historical Dictionary of Switzerland')..']'..p.getCatForId( 'HDS' )
end

function p.iaafLink( id, label )
	--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..' '..(label or 'World Athletics')..']'..p.getCatForId( 'IAAF' )
end


function p.iccuLink( id, label )
	--P396's format regex: IT\\ICCU\\(\d{10}|\D\D[\D\d]\D\\\d{6}) (e.g. IT\ICCU\CFIV\000163)
	if not id:match( '^IT\\ICCU\\%d%d%d%d%d%d%d%d%d%d$' ) and
	   not id:match( '^IT\\ICCU\\%u%u[%u%d]%u\\%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/opacsbn/opac/iccu/scheda_authority.jsp?bid='..id..' '..(label or 'Italy')..']'..p.getCatForId( 'ICCU' )
end
function p.iciaLink( id, label )
	--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..' '..(label or 'ICIA (Israel)')..']'..p.getCatForId( 'ICIA' )
end

function p.ieuLink( id, label )
	--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..' '..(label or 'Internet Encyclopedia of Ukraine')..']'..p.getCatForId( 'IEU' )
end

function p.isniLink( id, label )
	id = p.validateIsni( id ) --e.g. 0000-0000-6653-4145
	if not id then
		return false
	end
	return '[https://isni.org/isni/'..id..' '..(label or 'ISNI')..']'..p.getCatForId( 'ISNI' )
end

function p.jocondeLink( id, label )
	--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..' '..(label or 'Joconde (France)')..']'..p.getCatForId( 'Joconde' )
end

function p.kulturnavLink( id, label )
	--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..' '..(label or 'KulturNav (Norway)')..']'..p.getCatForId( 'KULTURNAV' ) --no https as of 9/2019
end

function p.lccnLink( id, label )
	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..' '..(label or 'United States')..']'..p.getCatForId( 'LCCN' )
end

function p.lirLink( id, label )
	--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 '..(label or 'Lexicon Istoric Retic (Switzerland)')..']'..p.getCatForId( 'LIR' ) --no https as of 9/2019
end

function p.lnbLink( id, label )
	--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 '..(label or 'Latvia')..']'..p.getCatForId( 'LNB' )
end

function p.leonoreLink( id, label )
	--P640's format regex: LH/\d{1,4}/\d{1,3}|19800035/\d{1,4}/\d{1,5}(Bis)?|C/0/\d{1,2} (e.g. LH/2064/18)
	if not id:match( '^LH/%d%d?%d?%d?/%d%d?%d?$' ) and             --IDs from       LH/1/1 to         LH/2794/54 (legionaries)
	   not id:match( '^19800035/%d%d?%d?%d?/%d%d?%d?%d?%d?$' ) and --IDs from 19800035/1/1 to 19800035/385/51670 (legionnaires who died 1954-1977 & some who died < 1954)
	   not id:match( '^C/0/%d%d?$' ) then                          --IDs from        C/0/1 to             C/0/84 (84 famous legionaries)
		return false
	end
	return '[http://www.culture.gouv.fr/public/mistral/leonore_fr?ACTION=CHERCHER&FIELD_1=COTE&VALUE_1='..id..' '..(label or 'Léonore (France)')..']'..p.getCatForId( 'Léonore' ) --no https as of 9/2019
end

function p.maLink( id, label )
	--P6366's format regex: [1-9]\d{4,9} (e.g. 1498221862)
	if not id:match( '^[1-9]%d%d%d%d%d?%d?%d?%d?%d?$' ) then
		return false
	end
	return '[https://academic.microsoft.com/v2/detail/'..id..' '..(label or 'Microsoft Academic')..']'..p.getCatForId( 'MA' )
end

function p.mbaLink( id, label )
	--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
	local url = 'https://musicbrainz.org/artist/'..id
	local cat = p.getCatForId( 'MusicBrainz' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBA (identifier)|MusicBrainz]] [' .. url .. ' artist]' .. cat
	end
end

function p.mbareaLink( id, label )
	--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
	local url = 'https://musicbrainz.org/area/'..id
	local cat = p.getCatForId( 'MusicBrainz area' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBAREA (identifier)|MusicBrainz]] [' .. url .. ' area]' .. cat
	end
end

function p.mbiLink( id, label )
	--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
	local url = 'https://musicbrainz.org/instrument/'..id
	local cat = p.getCatForId( 'MusicBrainz instrument' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBI (identifier)|MusicBrainz]] [' .. url .. ' instrument]' .. cat
	end
end

function p.mblLink( id, label )
	--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
	local url = 'https://musicbrainz.org/label/'..id
	local cat = p.getCatForId( 'MusicBrainz label' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBL (identifier)|MusicBrainz]] [' .. url .. ' label]' .. cat
	end
end

function p.mbpLink( id, label )
	--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
	local url = 'https://musicbrainz.org/place/'..id
	local cat = p.getCatForId( 'MusicBrainz place' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBP (identifier)|MusicBrainz]] [' .. url .. ' place]' .. cat
	end
end

function p.mbrgLink( id, label )
	--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
	local url = 'https://musicbrainz.org/release-group/'..id
	local cat = p.getCatForId( 'MusicBrainz release group' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBRG (identifier)|MusicBrainz]] [' .. url .. ' release group]' .. cat
	end
end

function p.mbsLink( id, label )
	--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
	local url = 'https://musicbrainz.org/series/'..id
	local cat = p.getCatForId( 'MusicBrainz series' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBS (identifier)|MusicBrainz]] [' .. url .. ' series]' .. cat
	end
end

function p.mbwLink( id, label )
	--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
	
	local url = 'https://musicbrainz.org/work/'..id
	local cat = p.getCatForId( 'MusicBrainz work' )--special cat name
	if label then
		return '['..url..' '..label..']'..cat	
	else
		return '[[MBW (identifier)|MusicBrainz]] [' .. url .. ' work]' .. cat
	end
end

function p.mgpLink( id, label )
	--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..' '..(label or 'Mathematics Genealogy Project')..']'..p.getCatForId( 'MGP' )
end

function p.naraLink( id, label )
	--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..' '..(label or 'National Archives (US)')..']'..p.getCatForId( 'NARA' )
end

function p.nclLink( id, label )
	--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 '..(label or 'Taiwan')..']'..p.getCatForId( 'NCL' ) --no https as of 9/2019
end

function p.ndlLink( id, label )
	--P349's format regex: 0?\d{8} (e.g. 012345678)
	if not id:match( '^0?%d%d%d%d%d%d%d%d$' ) then
		return false
	end
	return '[https://id.ndl.go.jp/auth/ndlna/'..id..' '..(label or 'Japan')..']'..p.getCatForId( 'NDL' )
end

function p.ngvLink( id, label )
	--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..'/ '..(label or 'Victoria')..']'..p.getCatForId( 'NGV' )
end

function p.nkcLink( id, label )
	--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..'&CON_LNG=ENG '..(label or 'Czech Republic')..']'..p.getCatForId( 'NKC' )
end

function p.nlaLink( id, label )
	--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..' '..(label or 'Australia')..']'..p.getCatForId( 'NLA' )
end

function p.nlgLink( id, label )
	--P3348's format regex: [1-9]\d* (e.g. 1)
	if not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[https://data.nlg.gr/resource/authority/record'..id..' '..(label or 'Greece')..']'..p.getCatForId( 'NLG' )
end

function p.nliLink( id, label )
	--P949'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://uli.nli.org.il/F/?func=direct&doc_number='..id..'&local_base=nlx10'..' '..(label or 'Israel')..']'..p.getCatForId( 'NLI' )
end

function p.nlkLink( id, label )
	--P5034's format regex: KA.(19|20).{7} (e.g. KAC201501465)
	if not id:match( '^KA.19.......$' ) and
	   not id:match( '^KA.20.......$' ) then
		return false
	end
	return '[https://nl.go.kr/authorities/resource/'..id..' '..(label or 'Korea')..']'..p.getCatForId( 'NLK' )
end

function p.nlpLink( id, label )
	--P1695's format regex: 9810[0-9]\d* or A[0-9]{7}[0-9X] (e.g. 9810123456789012345 or A10414836)
	if not id:match( '^9810%d+$' ) and
	   not id:match( '^A%d%d%d%d%d%d%d[%dX]$' ) then
		return false
	end
	return '[https://tools.wmflabs.org/wikidata-externalid-url?p=1695&id='..id..' '..(label or 'Poland')..']'..p.getCatForId( 'NLP' )
end

function p.nlrLink( id, label )
	--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..' '..(label or 'Romania')..']'..p.getCatForId( 'NLR' )
end

function p.nskLink( id, label )
	--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 '..(label or 'Croatia')..']'..p.getCatForId( 'NSK' ) --no https as of 9/2019
end

function p.ntaLink( id, label )
	--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..' '..(label or 'Netherlands')..']'..p.getCatForId( 'NTA' )
end

function p.orcidLink( id, label )
	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..' '..(label or 'ORCID')..']'..p.getCatForId( 'ORCID' )
end

function p.picLink( id, label )
	--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..' '..(label or 'Photographers\' Identities')..']'..p.getCatForId( 'PIC' )
end

function p.plwabnLink( id, label )
	--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 '[http://mak.bn.org.pl/cgi-bin/KHW/makwww.exe?BM=1&NU=1&IM=4&WI='..id..' '..(label or 'Poland')..']'..p.getCatForId( 'PLWABN' )
end

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

function p.ridLink( id, label )
	--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.researcherid.com/rid/'..id..' '..(label or 'ResearcherID')..']'..p.getCatForId( 'RID' )
end

function p.rismLink( id, label )
	--P5504's format regex: (pe|ks)?\[1-9]d* (e.g. pe30006410)
	if not id:match( '^pe[1-9]%d*$' ) and --99% start with 'pe'
	   not id:match( '^ks[1-9]%d*$' ) and
	   not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[https://opac.rism.info/search?id='..id..' '..(label or 'RISM (France)')..']'..p.getCatForId( 'RISM' )
end

function p.reroLink( id, label )
	--P3065's format regex: 0[1-2]-[A-Z0-9]{1,10} (e.g. 02-A012345678)
	if not id:match( '^0[1-2]%-[A-Z%d][A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?[A-Z%d]?$' ) then
		return false
	end
	return '[http://data.rero.ch/'..id..' '..(label or 'RERO (Switzerland)')..']'..p.getCatForId( 'RERO' )
end

function p.rkdartistsLink( id, label )
	--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..' '..(label or 'RKD Artists (Netherlands)')..']'..p.getCatForId( 'RKDartists' )
end

function p.rkdidLink( id, label )
	--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..' '..(label or 'RKD ID (Netherlands)')..']'..p.getCatForId( 'RKDID' )
end

function p.rslLink( id, label )
	--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 '..(label or 'Russia')..']'..p.getCatForId( 'RSL' ) --no https as of 9/2019
end

function p.selibrLink( id, label )
	--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..' '..(label or 'Sweden')..']'..p.getCatForId( 'SELIBR' )
end

function p.sikartLink( id, label )
	--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 '..(label or 'SIKART (Switzerland)')..']'..p.getCatForId( 'SIKART' ) --no https as of 9/2019
end

function p.snacLink( id, label )
	--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..' '..(label or 'Social Networks and Archival Context')..']'..p.getCatForId( 'SNAC-ID' )
end

function p.sudocLink( id, label )
	--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..' '..(label or 'SUDOC (France)')..']'..p.getCatForId( 'SUDOC' )
end

function p.s2authoridLink( id, label )
	--P4012's format regex: [1-9]\d* (e.g. 1796130)
	if not id:match( '^[1-9]%d*$' ) then
		return false
	end
	return '[https://www.semanticscholar.org/author/'..id..' '..(label or 'Semantic Scholar')..']'..p.getCatForId( 'Semantic Scholar author' ) --special cat name
end

function p.ta98Link( id, label )
	--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..' '..(label or 'Terminologia Anatomica')..']'..p.getCatForId( 'TA98' )
end

function p.tdviaLink( id, label )
	--P7314's format regex: [a-z/-]+] (e.g. barkan-omer-lutfi)
	if not id:match( '^[a-z/-]+$' ) then
		return false
	end
	return '[https://islamansiklopedisi.org.tr/'..id..' '..(label or 'Encyclopedia of Islam')..']'..p.getCatForId( 'TDVİA' )
end

function p.teLink( id, label )
	--P1693's format regex: E[1-8]\.\d{1,2}\.\d{1,2}\.\d{1,2}\.\d{1}\.\d{1}\.\d{1,3} (e.g. E1.23.45.67.8.9.0)
	local e1, e2 = id:match( '^E([1-8])%.(%d%d?)%.%d%d?%.%d%d?%.%d%.%d%.%d%d?%d?$' )
	if not e1 then
		return false
	end
	local TEnum = 'TEe0'..e1 --no formatter URL in WD, probably due to this complexity
	if e1 == '5' or e1 == '7' then
		if #e2 == 1 then e2 = '0'..e2 end
		TEnum = TEnum..e2
	end
	return '[http://www.unifr.ch/ifaa/Public/EntryPage/ViewTE/'..TEnum..'.html '..(label or 'Terminologia Embryologica')..']'..p.getCatForId( 'TE' )
end

function p.tepapaLink( id, label )
	--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..' '..(label or 'Te Papa (New Zealand)')..']'..p.getCatForId( 'TePapa' )
end

function p.thLink( id, label )
	--P1694's format regex: H\d\.\d{2}\.\d{2}\.\d\.\d{5} (e.g. H1.23.45.6.78901)
	local h1, h2 = id:match( '^H(%d)%.(%d%d)%.%d%d%.%d%.%d%d%d%d%d$' )
	if not h1 then
		return false
	end
	local THnum = 'THh'..h1..h2 --no formatter URL in WD, probably due to this complexity
	return '[http://www.unifr.ch/ifaa/Public/EntryPage/ViewTH/'..THnum..'.html '..(label or 'Terminologia Histologica')..']'..p.getCatForId( 'TH' )
end

function p.tlsLink( id, label )
	id = id:gsub(' +', '_')
	--P1362's format regex: \p{Lu}[\p{L}\d_',\.\-\(\)\*/–]{3,59} (e.g. Abcd)
	local class = "[%a%d_',%.%-%(%)%*/–]"
	local regex = "^%u"..string.rep(class, 3)..string.rep(class.."?", 56).."$"
	if not mw.ustring.match( id, regex ) then
		return false
	end
	return '[http://tls.theaterwissenschaft.ch/wiki/'..id..' '..(label or 'Theaterlexikon (Switzerland)')..']'..p.getCatForId( 'TLS' ) --no https as of 9/2019
end

function p.troveLink( id, label )
	--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..' '..(label or 'Trove (Australia)')..']'..p.getCatForId( 'Trove' )
end

function p.ukparlLink( id, label )
	--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..' '..(label or 'UK Parliament')..']'..p.getCatForId( 'UKPARL' )
end

function p.ulanLink( id, label )
	--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..' '..(label or 'Artist Names (Getty)')..']'..p.getCatForId( 'ULAN' )
end

function p.uscongressLink( id, label )
	--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..' '..(label or 'US Congress')..']'..p.getCatForId( 'USCongress' ) --no https as of 9/2019
end

function p.vcbaLink( id, label )
	--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
	id = id:gsub('\/', '_')
	return '[https://opac.vatlib.it/auth/detail/'..id..' '..(label or 'Vatican')..']'..p.getCatForId( 'VcBA' )
end

function p.viafLink( id, label )
	--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..' '..(label or 'VIAF')..']'..p.getCatForId( 'VIAF' )
end

--[[=========================== Helper functions =============================]]

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 & documentation functions                    ]]
--[[==========================================================================]]

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

-- 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 | Parameter\n'..
					  '! rowspan=2 | Section\n'..
					  '! rowspan=2 | Appears as\n'..
					  '! rowspan=2; data-sort-type=number | Wikidata property\n'..
					  '! colspan=4 | Tracking categories and page counts\n'..
					  '|-\n'..
					  '! [[:Category:Wikipedia articles with authority control information|'..       'Articles]]\n'..
					  '! [[:Category:User pages with authority control information|'..               'User pages]]\n'..
					  '! [[:Category:Miscellaneous pages with authority control information|'..      'Misc. pages]]\n'..
					  '! [[:Category:Wikipedia articles with faulty authority control information|'..'Faulty IDs]]\n'..
					  '|-\n'
	local lang = mw.getContentLanguage()
	for _, conf in pairs( p.conf ) do
		local param, pid, section = conf[1], conf[2], conf[4]
		local appearsAs
		if param == "WORLDCATID" then
			-- WorldCat is special
			appearsAs = "[https://www.worldcat.org/identities/lccn-n78039510 WorldCat]"
		elseif conf.prefix then
			appearsAs = conf.prefix
		else
			appearsAs = conf[3](conf[5])
		end
		local link = conf.link or param .. ' (identifier)'
		local category = conf.category or param
		local args = { id = 'f', pid }
		local wpl = frame:expandTemplate{ title = 'Wikidata property link', args = args }
		--cats
		local articleCat = 'Wikipedia articles with '..category..' identifiers'
		local userCat =    'User pages with '..category..' identifiers'
		local miscCat =    'Miscellaneous pages with '..category..' identifiers'
		local faultyCat =  'Wikipedia articles with faulty '..category..' identifiers'
		--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'..
					'||[['..link..'|'..param..']]'..
					'||'..section..
					'||'..appearsAs..
					'||data-sort-value='..pid..'|'..wpl..
					'||style="text-align: right;"|[[:Category:'..articleCat..'|'..articleCount..']]'..
					'||style="text-align: right;"|[[:Category:'..   userCat..'|'..   userCount..']]'..
					'||style="text-align: right;"|[[:Category:'..   miscCat..'|'..   miscCount..']]'..
					'||style="text-align: right;"|[[:Category:'.. faultyCat..'|'.. faultyCount..']]'
	end
	
	--append derivative WorldCat cats
	local wcd = { 'WorldCat-LCCN', 'WorldCat-VIAF' }
	for _, w in pairs(wcd) do
		local articleCat = 'Wikipedia articles with '..w..' identifiers'
		local articleCount = lang:formatNum( mw.site.stats.pagesInCategory(articleCat, 'pages') )
		local appearsAs 
		if w == "WorldCat-LCCN" then
			appearsAs = "[https://www.worldcat.org/identities/lccn-n79-113947 WorldCat (via Library of Congress)]"
		else
			appearsAs = "[https://www.worldcat.org/identities/containsVIAFID/12345789 WorldCat (via VIAF)]"
		end
		wikiTable = wikiTable..'\n'..
					'|-\n'..
					'||'..'—'..
					'||General'..
					'||'..appearsAs..
					'||data-sort-value='..w..'|'..'—'..
					'||style="text-align: right;"|[[:Category:'..articleCat..'|'..articleCount..']]'..
					'||style="text-align: right;"|—'..
					'||style="text-align: right;"|—'..
					'||style="text-align: right;"|—'
	end
	
	return require("Module:Suppress categories").main(wikiTable)..'\n|}'
end

--[[==========================================================================]]
--[[                              Configuration                               ]]
--[[==========================================================================]]

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


-- Parameter format: { 'parameter name', propertyId # in Wikidata, formatting/validation function, section, example ID for documentation }
-- Optional named parameters: `link` to override the link in the documentation (defaults to parameter + (identifer)),
-- category to override the ID in category names (defaults to parameter),
-- prefix to include a prefix (usually a wikilink explaining what the identifier is) before the external link itself
p.conf = {
	{ 'AAG', 3372, p.aagLink, "Art galleries and museums", "1"},
	{ 'ACM-DL', 864, p.acmLink, "Scientific databases", "12345678901", link="ACM DL (identifier)"},
	{ 'ADB', 1907, p.adbLink,"Biographical dictionaries", "barton-sir-edmund-toby-71"},
	{ 'AGSA', 6804, p.agsaLink, "Art galleries and museums", "3625"},
	{ 'autores.uy', 2558, p.autoresuyLink, "Biographical dictionaries", "12345"},
	{ 'AWR', 4182, p.awrLink, "Biographical dictionaries", "PR00768b"},
	{ 'BALaT', 3293, p.balatLink, "Art research institutes", "1"},
	{ 'BIBSYS', 1015, p.bibsysLink, "National libraries", "1234567890123"},
	{ 'Bildindex', 2092, p.bildLink, "Art research institutes", "1"},
	{ 'BNC', 1890, p.bncLink, "National libraries", "123456789"},
	{ 'BNE', 950, p.bneLink, "National libraries", "XX1234567"},
	{ 'BNF', 268, p.bnfLink, "National libraries", "123456789"},
	{ 'Botanist', 428, p.botanistLink , "Scientific databases", "L."},
	{ 'BPN', 651, p.bpnLink , "Biographical dictionaries", "12345678"},
	{ 'CANTIC', 1273, p.canticLink, "National libraries", "a12345678"},
	{ 'CINII', 271, p.ciniiLink, "Scientific databases", "DA12345678", link = "CiNii (identifier)"},
	{ 'CWGC', 1908, p.cwgcLink, "Other", "1234567"},
	{ 'DAAO', 1707, p.daaoLink, "Art research institutes", "rolf-harris"},
	{ 'DBLP', 2456, p.dblpLink, "Scientific databases", "123/123"},
	{ 'DIB',  6829, p.dibLink, "Biographical dictionaries", "a1234"},
	{ 'DSI', 2349, p.dsiLink, "Art research institutes", "1538"},
	{ 'FAST', 2163, p.fastLink, "Other", "1"},
	{ 'FNZA', 6792, p.fnzaLink, "Art research institutes", "12"},
	{ 'GND', 227, p.gndLink, "General", "4079154-3"},
	{ 'HDS', 902, p.hdsLink, "Other", "050123"},
	{ 'IAAF', 1146, p.iaafLink, "Other", "123"},
	{ 'ICCU', 396, p.iccuLink, "National libraries", "IT\\ICCU\\CFIV\\000163"}, --formerly SBN
	{ 'ICIA', 1736, p.iciaLink, "Art research institutes", "1"},
	{ 'IEU', 9070, p.ieuLink, "Other", "N\\A\\NationalAcademyofArtandArchitecture"},
	{ 'ISNI', 213, p.isniLink, "General", "0000-0000-6653-4145", prefix = '[[ISNI (identifier)|ISNI]]'},
	{ 'Joconde', 347, p.jocondeLink, "Art research institutes", "12345678901"},
	{ 'KULTURNAV', 1248, p.kulturnavLink, "Art research institutes", "12345678-1234-1234-1234-1234567890AB", link="KulturNav (identifier)"},
	{ 'LCCN', 244, p.lccnLink, "National libraries", "n78039510"},
	{ 'LIR', 886, p.lirLink, "Other", "1"},
	{ 'LNB', 1368, p.lnbLink, "National libraries", "123456789"},
	{ 'Léonore', 640, p.leonoreLink, "Other", "LH/1/1", prefix = "[[Léonore (identifier)|Léonore (France)]]"},
	{ 'MA', 6366, p.maLink, "Other", "123456789"},
	{ 'MBA', 434, p.mbaLink, "Other", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz'}, --special cat name
	{ 'MBAREA', 982, p.mbareaLink, "Other", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz area' }, --special cat name
	{ 'MBI', 1330, p.mbiLink, "Other", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz instrument' }, --special cat name
	{ 'MBL', 966, p.mblLink, "Other", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz label' }, --special cat name
	{ 'MBP', 1004, p.mbpLink, "Other", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz place' }, --special cat name
	{ 'MBRG', 436, p.mbrgLink, "Other", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz release group' }, --special cat name
	{ 'MBS', 1407, p.mbsLink, "Other", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz series' }, --special cat name
	{ 'MBW',  435, p.mbwLink, "Other", "12345678-1234-1234-1234-1234567890AB", category = 'MusicBrainz work' }, --special cat name
	{ 'MGP', 549, p.mgpLink, "Scientific databases", "123456"},
	{ 'NARA', 1225, p.naraLink, "Other", "12345678"},
	{ 'NCL', 1048, p.nclLink, "National libraries", "1081436"},
	{ 'NDL', 349, p.ndlLink, "National libraries", "012345678"},
	{ 'NGV', 2041, p.ngvLink, "Art galleries and museums", "12354"},
	{ 'NKC', 691, p.nkcLink, "National libraries", "abcd12345678901234"},
	{ 'NLA', 409, p.nlaLink, "National libraries", "123456789012"},
	{ 'NLG', 3348, p.nlgLink, "National libraries", "12345678"},
	{ 'NLI', 949, p.nliLink, "National libraries", "123456789"},
	{ 'NLK', 5034, p.nlkLink, "National libraries", "KAB197000000"},
	{ 'NLP', 1695, p.nlpLink, "National libraries", "9810123456789012345"},
	{ 'NLR', 1003, p.nlrLink, "National libraries", "123456789"},
	{ 'NSK', 1375, p.nskLink, "National libraries", "123456789"},
	{ 'NTA', 1006, p.ntaLink, "National libraries", "12345678X"},
	{ 'ORCID', 496, p.orcidLink, "General", "0000-0002-7398-5483", prefix = '[[ORCID (identifier)|ORCID]]'},
	{ 'PIC', 2750, p.picLink, "Art research institutes", "1"},
	{ 'PLWABN',  7293, p.plwabnLink, "National libraries", "9812345678905606"},
	{ 'Publons', 3829, p.publonsLink, "Scientific databases", "2776255"},
	{ 'RID', 1053, p.ridLink, "Scientific databases", "A-1234-1934"},
	{ 'RISM', 5504, p.rismLink, "Other", "pe1",  prefix = '[[RISM (identifier)|RISM (France)]]'},
	{ 'RERO', 3065, p.reroLink, "Other", "02-A012345678", prefix = '[[RERO (identifier)|RERO (Switzerland)]]'},
	{ 'RKDartists', 650, p.rkdartistsLink, "Art research institutes", "123456"},
	{ 'RKDID', 350, p.rkdidLink, "Art research institutes", "123456"},
	{ 'RSL', 947, p.rslLink, "National libraries", "123456789"},
	{ 'SELIBR', 906, p.selibrLink, "National libraries", "123456"},
	{ 'SIKART', 781, p.sikartLink, "Art research institutes", '123456789'},
	{ 'SNAC-ID', 3430, p.snacLink, "Other", "A"},
	{ 'SUDOC', 269, p.sudocLink, "Other", "026927608", prefix = '[[SUDOC (identifier)|SUDOC (France)]]'},
	{ 'S2AuthorId', 4012, p.s2authoridLink, "Scientific databases", "1796130", category = 'Semantic Scholar author' }, --special cat name
	{ 'TA98', 1323, p.ta98Link, "Scientific databases", "A12.3.45.678"},
	{ 'TDVİA', 7314, p.tdviaLink, "Other", "asim-b-behdele"},
	{ 'TE', 1693, p.teLink, "Scientific databases", "E1.23.45.67.8.9.0"},
	{ 'TePapa', 3544, p.tepapaLink, "Art galleries and museums", "1"},
	{ 'TH', 1694, p.thLink, "Scientific databases", "H1.23.45.6.78901"},
	{ 'TLS',  1362, p.tlsLink, "Other", "Abcd"},
	{ 'Trove', 1315, p.troveLink, "Other", "12345678", prefix = '[[Trove (identifier)|Trove (Australia)]]'}, --formerly NLA-person
	{ 'UKPARL', 6213, p.ukparlLink, "Other", "AQUupyiR"},
	{ 'ULAN', 245, p.ulanLink, "Art research institutes", "500123456"},
	{ 'USCongress', 1157, p.uscongressLink, "Other", "A000123", link = "US Congress (identifier)"},
	{ 'VcBA', 8034, p.vcbaLink, "National libraries", "494/9793"},
	{ 'VIAF', 214, p.viafLink, "General", "123456789", prefix = "[[VIAF (identifier)|VIAF]]"},
	{ 'WORLDCATID', 7859, nil, "General", nil, link = "WorldCat Identities (identifier)"},
}

-- Legitimate aliases to p.conf, for convenience
-- Format: { 'alias', 'parameter name in p.conf' }
p.aliases = {
	{ 'DNB', 'GND' }, --Deutsche Nationalbibliothek -> Gemeinsame Normdatei
	{ 'Leonore', 'Léonore' }, --alias name without diacritics
	{ 'leonore', 'Léonore' }, --lowercase variant without diacritics
	{ 'MusicBrainz', 'MBA' },
	{ 'MusicBrainz artist', 'MBA' },
	{ 'MusicBrainz label', 'MBL' },
	{ 'MusicBrainz release group', 'MBRG' },
	{ 'MusicBrainz work', 'MBW' },
	{ 'SBN', 'ICCU' }, --SBN alias to be deprecated at a later stage
	{ 'TDVIA', 'TDVİA' }, --alias name without diacritics
	{ 'tdvia', 'TDVİA' }, --lowercase variant without diacritics
}

-- 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 = {
	{ 'GKD', 'GND' },
	{ 'PND', 'GND' },
	{ 'RLS', 'RSL' },	
	{ 'SWD', 'GND' },
	{ 'NARA-organization', 'NARA' },
	{ 'NARA-person', 'NARA' },
}

--[[==========================================================================]]
--[[                                   Main                                   ]]
--[[==========================================================================]]

function p.authorityControl( frame )
	local resolveEntity = require( "Module:ResolveEntityId" )
	local parentArgs = frame:getParent().args --WD IDs added here later
	local iParentArgs = 0 --count original/manual parent args only later
	local worldcatCat = ''
	local multipleIdCat = ''
	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 = '[[Category:Wikipedia articles with deprecated authority control identifiers|'..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
			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[2] > 0 then
				local val = parentArgs[mw.ustring.lower(params[1])] or parentArgs[params[1]]
				if val == nil or val == '' then
					local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[2] )
					if wikidataIds[1] then
						if val == '' and (namespace == 0 or testcases) then
							suppressedIdCat = '[[Category:Wikipedia articles with suppressed authority control identifiers|'..params[1]..']]'
						else
							parentArgs[params[1]] = wikidataIds[1] --add ID from WD
						end
					end
				else
					iParentArgs = iParentArgs + 1
					local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[2] )
					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 = '[[Category:Pages using authority control with parameters different on Wikidata|'..params[1]..']]'
		end	end	end	end	end
		if iMatches > 0 and iMatches == iParentArgs then
			sameOnWDCat = '[[Category:Pages using authority control with parameters all matching Wikidata]]'
		end
	end
	--Configured rows
	local rct = 0
	local sectionOrder = {"General","National libraries","Art galleries and museums",
						  "Art research institutes","Biographical dictionaries","Scientific databases",
						  "Other"}
	local sections = {
		["General"] = {},
		["National libraries"] = {},
		["Art galleries and museums"] = {},
		["Art research institutes"] = {},
		["Biographical dictionaries"] = {},
		["Scientific databases"] = {},
		["Other"] = {}
	}
	-- Don't show NLP is PLWABN is present, since they both go to the National Library of Poland
	-- and the library has deprecated NLP IDs in favor of PLWABN IDs
	if parentArgs.PLWABN or parentArgs.plwabn then
		parentArgs.NLP = ''
		parentArgs.nlp = ''
	end
	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[3]) == 'function' then
			table.insert( tval, val )
			if params.prefix then 
				table.insert( tlinks, params[3]( val, "1" ) )
			else
				table.insert( tlinks, params[3]( val ) )
			end
		end
		--collect other unique vals (IDs) from WD, if present
		if itemId and tval[1] then
			local nextIdVal = 2
			local wikidataIds = p.getIdsFromWikidata( itemId, 'P'..params[2] )
			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[3]( v, tostring(nextIdVal) ) )
					nextIdVal = nextIdVal + 1
				end
			end
		end
		--assemble
		if tval[1] then
			table.insert( sections[params[4]], p.createRow( params[1], tval, nil, tlinks, true, params.category, params.prefix) )
			rct = rct + 1
			if tval[2] then
				multipleIdCat = p.getCatForId( 'multiple' )
			end
		end

	end
	
	--WorldCat
	local worldcatId = parentArgs['worldcatid'] or parentArgs['WORLDCATID']
	if worldcatId and worldcatId ~= '' then --if WORLDCATID present & unsuppressed
		table.insert( sections["General"], p.createRow( 'WORLDCATID', worldcatId, '[https://www.worldcat.org/identities/'..mw.uri.encode(worldcatId, 'PATH')..' WorldCat]', nil, false ) ) --Validation?
		worldcatCat = p.getCatForId( 'WORLDCATID' )
	elseif worldcatId == nil then --if WORLDCATID absent but unsuppressed
		local viafId = parentArgs['viaf'] or parentArgs['VIAF']
		local lccnId = parentArgs['lccn'] or parentArgs['LCCN']
		if viafId and viafId ~= '' and p.viafLink( viafId ) then --VIAF must be present, unsuppressed, & validated
			table.insert( sections["General"], p.createRow( 'VIAF', viafId, '[https://www.worldcat.org/identities/containsVIAFID/'..viafId..' WorldCat (via VIAF)]', nil, false ) )
			if namespace == 0 then 
				worldcatCat = '[[Category:Wikipedia articles with WorldCat-VIAF identifiers]]'
			end
		elseif lccnId and lccnId ~= '' and p.lccnLink( lccnId ) then --LCCN must be present, unsuppressed, & validated
			local lccnParts = p.splitLccn( lccnId )
			if lccnParts and lccnParts[1] ~= 'sh' then
				local lccnIdFmtd = lccnParts[1]..lccnParts[2]..'-'..lccnParts[3]
				table.insert( sections["General"], p.createRow( 'LCCN', lccnId, '[https://www.worldcat.org/identities/lccn-'..lccnIdFmtd..' WorldCat (via Library of Congress)]', nil, false ) )
				if namespace == 0 then
					worldcatCat = '[[Category:Wikipedia articles with WorldCat-LCCN identifiers]]'
				end
			end
		end
	elseif worldcatId == '' then --if WORLDCATID suppressed
		suppressedIdCat = '[[Category:Wikipedia articles with suppressed authority control identifiers|WORLDCATID]]'
	end
	
	local Navbox = require('Module:Navbox')
	local elementsCat = ''
	if rct == 0 or rct >= 25 then
		local eCat = 'AC with '..rct..' elements'
		elementsCat  = '[[Category:'..eCat..']]'..p.redCatLink(eCat)
	end
	
	local outString = ''
	if rct > 0 then
		local sectionID = 1
		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 = 'EditAtWikidata', args = args}
		local navboxArgs = {
			name  = 'Authority control',
			navboxclass = 'authority-control',
			bodyclass = 'hlist',
			state = parentArgs.state or 'autocollapse',
			navbar = 'off'
		}
		for _, sectName in ipairs(sectionOrder) do
			if #sections[sectName] ~= 0 then
				navboxArgs["group" .. sectionID] = sectName
				navboxArgs["list" .. sectionID] = table.concat(sections[sectName])
				sectionID = sectionID + 1
			end
		end
		if navboxArgs.group2 then
			if rct >= 4 then 
				navboxArgs.title = "[[Help:Authority control|Authority control]]" .. pencil
			else
				navboxArgs.border = "child"
				navboxArgs = {
					group1 = "[[Help:Authority control|Authority control]]" .. pencil,
					list1 = Navbox._navbox(navboxArgs)
				}
			end
		else
			local sect = navboxArgs.group1
			if sect == "General" or sect == "Other" then
				-- Just say "Authority control" with no label if only general or only other IDs are present
				-- since "general" is redundant and "other" is silly when there's nothing to contrast it with
				navboxArgs.group1 = "[[Help:Authority control|Authority control]]" .. pencil
			else 
				navboxArgs.group1 = "[[Help:Authority control|Authority control: " .. sect .. "]] " .. pencil
			end
		end
		outString = Navbox._navbox(navboxArgs)
	end
	
	local auxCats = worldcatCat .. elementsCat .. multipleIdCat .. suppressedIdCat .. 
					deprecatedIdCat .. differentOnWDCat .. sameOnWDCat
	if testcases then
		auxCats = mw.ustring.gsub(auxCats, '(%[%[)(Category)', '%1:%2') --for easier checking
	end
	outString = outString .. auxCats
	if namespace ~= 0 then
		outString = mw.ustring.gsub(outString, '(%[%[)(Category:Wikipedia articles)', '%1:%2') --by definition
	end
	
	return outString
end

return p