require('strict')
local p = local title = mw.title.getCurrentTitlelocal namespace = title.namespacelocal testcases = (string.sub(title.subpageText,1,9)
----Category functions --
function p.getCatForId(id) local catName = if namespace
2 and not title.isSubpage then catName = 'User pages with '..id..' identifiers' else catName = 'Miscellaneous pages with '..id..' identifiers' end return ''..p.redCatLink(catName)end
function p.redCatLink(catName) --catName
false and mw.title.new(catName, 14).exists
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
----Property formatting functions --
-- If a link has a suitable entry in the global inter-wiki prefix table at, 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 ''..(label or 'Auckland')..''..p.getCatForId('AAG')end
function p.acmLink(id, label) --P864's format regex: \d (e.g. 12345678901) if not id:match('^%d%d%d%d%d%d%d%d%d%d%d$') then return false end return ''..(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 (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 ''..(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 ''..(label or 'South Australia')..''..p.getCatForId('AGSA')end
function p.autoresuyLink(id, label) --P2558's format regex: [1-9]\d (e.g. 12345) if not id:match('^[1-9]%d?%d?%d?%d?$') then return false end return ''..(label or 'Uruguay')..''..p.getCatForId('autores.uy')end
function p.awrLink(id, label) --P4186's format regex: (([A-Z]\d)|([A-Z]\d))[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 ''..(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 ''..(label or 'BALaT (Belgium)')..''..p.getCatForId('BALaT') --no https as of 9/2019end
function p.bibsysLink(id, label) --P1015's format regex: [1-9]\d* or [1-9](\d|\d) (e.g. 1234567890123) --TODO: follow up @ 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 ''..(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 ''..(label or 'Bildindex (Germany)')..''..p.getCatForId('Bildindex')end
function p.bncLink(id, label) --P1890's format regex: \d (e.g. 123456789) if not id:match('^%d%d%d%d%d%d%d%d%d$') then return false end return ''..(label or 'Chile')..''..p.getCatForId('BNC')end
function p.bneLink(id, label) --P950's format regex: (XX|FF|a)\d|(bima|bimo|bica|bis[eo]|bivi|Mise|Mimo|Mima)\d (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 ''..(label or 'Spain')..''..p.getCatForId('BNE') --no https as of 9/2019end
function p.bnfLink(id, label) --P268's format regex: \d[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 '' .. (label or 'France')..' (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?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 ''..(label or 'International Plant Names Index')..''..p.getCatForId('Botanist')end
function p.bpnLink(id, label) --P651's format regex: \d (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 ''..(label or 'Netherlands')..''..p.getCatForId('BPN') --no https as of 9/2019end
function p.canticLink(id, label) --P1273's format regex: a\d[0-9x] (e.g. a10640745) if not id:match('^a%d%d%d%d%d%d%d[%dx]$') then return false end return ''..(label or 'Catalonia')..''..p.getCatForId('CANTIC') --no https as of 10/2019end
function p.ciniiLink(id, label) --P271's format regex: DA\d[\dX] (e.g. DA12345678) if not id:match('^DA%d%d%d%d%d%d%d[%dX]$') then return false end return ''..(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 ''..(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 ''..(label or 'Australian Artists')..''..p.getCatForId('DAAO')end
function p.dblpLink(id, label) --P2456's format regex: \d /\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 ''..(label or 'DBLP (computer science)')..''..p.getCatForId('DBLP')end
function p.dibLink(id, label) --P6829's format regex: a\d\d?(-[A-D])? (e.g. a1953) if not id:match('^a%d%d%d%d%d?%-?[A-D]?$') then return false end return ''..(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 ''..(label or 'Scientific illustrators')..''..p.getCatForId('DSI')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 ''..(label or 'New Zealand Artists')..''..p.getCatForId('FNZA')end
function p.gndLink(id, label) --P227's format regex: 1[012]?\d[0-9X]|[47]\d-\d|[1-9]\d-[0-9X]|3\d[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 ''..(label or 'Germany')..''..p.getCatForId('GND')end
function p.hdsLink(id, label) --P902's format regex: \d (e.g. 050123) if not id:match('^%d%d%d%d%d%d$') then return false end return ''..(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 ''..(label or 'World Athletics')..''..p.getCatForId('IAAF')end
function p.iccuLink(id, label) --P396's format regex: IT\\ICCU\\(\d|\D\D[\D\d]\D\\\d) (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 ''..(label or 'Italy')..''..p.getCatForId('ICCU')endfunction p.iciaLink(id, label) --P1736's format regex: \d+ (e.g. 1) if not id:match('^%d+$') then return false end return ''..(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 ''..(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 ''..(label or 'ISNI')..''..p.getCatForId('ISNI')end
function p.jocondeLink(id, label) --P347's format regex: [\-0-9A-Za-z] (e.g. 12345678901) local regex = '^'..string.rep('[%-0-9A-Za-z]', 11)..'$' if not id:match(regex) then return false end return ''..(label or 'Joconde (France)')..''..p.getCatForId('Joconde')end
function p.kulturnavLink(id, label) --P1248's format regex: [0-9a-f]\-[0-9a-f]\-[0-9a-f]\-[0-9a-f]\-[0-9a-f] (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 ''..(label or 'KulturNav (Norway)')..''..p.getCatForId('KULTURNAV') --no https as of 9/2019end
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 ''..(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 ''..(label or 'Lexicon Istoric Retic (Switzerland)')..''..p.getCatForId('LIR') --no https as of 9/2019end
function p.lnbLink(id, label) --P1368's format regex: \d (e.g. 123456789) if not id:match('^%d%d%d%d%d%d%d%d%d$') then return false end return ''..(label or 'Latvia')..''..p.getCatForId('LNB')end
function p.leonoreLink(id, label) --P640's format regex: LH/\d/\d|19800035/\d/\d(Bis)?|C/0/\d (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 ''..(label or 'Léonore (France)')..''..p.getCatForId('Léonore') --no https as of 9/2019end
function p.maLink(id, label) --P6366's format regex: [1-9]\d (e.g. 1498221862) if not id:match('^[1-9]%d%d%d%d%d?%d?%d?%d?%d?$') then return false end return ''..(label or 'Microsoft Academic')..''..p.getCatForId('MA')end
function p.mbaLink(id, label) --P434's format regex: [0-9a-f]-[0-9a-f]-[0-9a-f]-[0-9a-f]-[0-9a-f] (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 category name if label then return '['..url..' '..label..']'..cat else return 'MusikBrainz [' .. url .. ' artist]' .. cat endend
function p.mbareaLink(id, label) --P982's format regex: [0-9a-f]-[0-9a-f]-[0-9a-f]-[0-9a-f]-[0-9a-f] (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 category name if label then return '['..url..' '..label..']'..cat else return 'MusikBrainz [' .. url .. ' area]' .. cat endend
function p.mbiLink(id, label) --P1330's format regex: [0-9a-f]-[0-9a-f]-[0-9a-f]-[0-9a-f]-[0-9a-f] (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 category name if label then return '['..url..' '..label..']'..cat else return 'MusikBrainz [' .. url .. ' instrument]' .. cat endend
function p.mblLink(id, label) --P966's format regex: [0-9a-f]-[0-9a-f]-[0-9a-f]-[0-9a-f]-[0-9a-f] (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 category name if label then return '['..url..' '..label..']'..cat else return 'MusikBrainz [' .. url .. ' label]' .. cat endend
function p.mbpLink(id, label) --P1004's format regex: [0-9a-f]-[0-9a-f]-[0-9a-f]-[0-9a-f]-[0-9a-f] (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 category name if label then return '['..url..' '..label..']'..cat else return 'MusikBrainz [' .. url .. ' place]' .. cat endend
function p.mbrgLink(id, label) --P436's format regex: [0-9a-f]-[0-9a-f]-[0-9a-f]-[0-9a-f]-[0-9a-f] (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 category name if label then return '['..url..' '..label..']'..cat else return 'MusikBrainz [' .. url .. ' release group]' .. cat endend
function p.mbsLink(id, label) --P1407's format regex: [0-9a-f]-[0-9a-f]-[0-9a-f]-[0-9a-f]-[0-9a-f] (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 category name if label then return '['..url..' '..label..']'..cat else return 'MusikBrainz [' .. url .. ' series]' .. cat endend
function p.mbwLink(id, label) --P435's format regex: [0-9a-f]-[0-9a-f]-[0-9a-f]-[0-9a-f]-[0-9a-f] (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 category name if label then return '['..url..' '..label..']'..cat else return 'MusikBrainz [' .. url .. ' work]' .. cat endend
function p.mgpLink(id, label) --P549's format regex: \d (e.g. 123456) if not id:match('^%d%d?%d?%d?%d?%d?$') then return false end return ''..(label or 'Mathematics Genealogy Project')..''..p.getCatForId('MGP')end
function p.naraLink(id, label) --P1225's format regex: ^([1-9]\d)$ (e.g. 123456789) if not id:match('^[1-9]%d?%d?%d?%d?%d?%d?%d?%d?$') then return false end return ''..(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 ''..(label or 'Taiwan')..''..p.getCatForId('NCL') --no https as of 9/2019end
function p.ndlLink(id, label) --P349's format regex: 0?\d (e.g. 012345678) if not id:match('^0?%d%d%d%d%d%d%d%d$') then return false end return ''..(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 ''..(label or 'Victoria')..''..p.getCatForId('NGV')end
function p.nkcLink(id, label) --P691's format regex: [a-z][0-9] (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 ''..(label or 'Czech Republic')..''..p.getCatForId('NKC')end
function p.nlaLink(id, label) --P409's format regex: [1-9][0-9] (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 ''..(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 ''..(label or 'Greece')..''..p.getCatForId('NLG')end
function p.nliLink(id, label) --P949's format regex: \d (e.g. 123456789) if not id:match('^%d%d%d%d%d%d%d%d%d$') then return false end return ''..(label or 'Israel')..''..p.getCatForId('NLI')end
function p.nlkLink(id, label) --P5034's format regex: KA.(19|20). (e.g. KAC201501465) if not id:match('^KA.19.......$') and not id:match('^KA.20.......$') then return false end return ''..(label or 'Korea')..''..p.getCatForId('NLK')end
function p.nlpLink(id, label) --P1695's format regex: 9810[0-9]\d* or A[0-9][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 ''..(label or 'Poland')..''..p.getCatForId('NLP')end
function p.nlrLink(id, label) --P1003's format regex: \d (e.g. 123456789) if not id:match('^%d%d%d%d%d%d%d%d%d$') then return false end return ''..(label or 'Romania')..''..p.getCatForId('NLR')end
function p.nskLink(id, label) --P1375's format regex: \d (e.g. 123456789) if not id:match('^%d%d%d%d%d%d%d%d%d$') then return false end return ''..(label or 'Croatia')..''..p.getCatForId('NSK') --no https as of 9/2019end
function p.ntaLink(id, label) --P1006's format regex: \d[\dX] (e.g. 12345678X) if not id:match('^%d%d%d%d%d%d%d%d[%dX]$') then return false end return ''..(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 ''..(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 ''..(label or 'Photographers\' Identities')..''..p.getCatForId('PIC')end
function p.plwabnLink(id, label) --P7293's format regex: 981[0-9]05606 (e.g. 9810696457305606) if not id:match('^981%d%d%d%d%d%d%d%d05606*$') then return false end return ''..(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 ''..(label or 'Publons (researchers)')..''..p.getCatForId('Publons')end
function p.ridLink(id, label) --P1053's format regex: [A-Z]-\d-(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 ''..(label or 'ResearcherID')..''..p.getCatForId('RID')end
function p.reroLink(id, label) --P3065's format regex: 0[1-2]-[A-Z0-9] (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 ''..(label or 'RERO (Switzerland)')..''..p.getCatForId('RERO')end
function p.rkdartistsLink(id, label) --P650's format regex: [1-9]\d (e.g. 123456) if not id:match('^[1-9]%d?%d?%d?%d?%d?$') then return false end return ''..(label or 'RKD Artists (Netherlands)')..''..p.getCatForId('RKDartists')end
function p.rkdidLink(id, label) --P350's format regex: [1-9]\d (e.g. 123456) if not id:match('^[1-9]%d?%d?%d?%d?%d?$') then return false end return ''..(label or 'RKD ID (Netherlands)')..''..p.getCatForId('RKDID')end
function p.rslLink(id, label) --P947's format regex: \d (e.g. 123456789) if not id:match('^%d%d?%d?%d?%d?%d?%d?%d?%d?$') then return false end return ''..(label or 'Russia')..''..p.getCatForId('RSL') --no https as of 9/2019end
function p.selibrLink(id, label) --P906's format regex: [1-9]\d (e.g. 123456) if not id:match('^[1-9]%d%d%d%d%d?$') then return false end return ''..(label or 'Sweden')..''..p.getCatForId('SELIBR')end
function p.sikartLink(id, label) --P781's format regex: \d (e.g. 123456789) if not id:match('^%d%d%d%d%d%d%d%d?%d?$') then return false end return ''..(label or 'SIKART (Switzerland)')..''..p.getCatForId('SIKART') --no https as of 9/2019end
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 ''..(label or 'Social Networks and Archival Context')..''..p.getCatForId('SNAC-ID')end
function p.sudocLink(id, label) --P269's format regex: (\d[\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 ''..(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 ''..(label or 'Semantic Scholar')..''..p.getCatForId('Semantic Scholar author') --special category nameend
function p.ta98Link(id, label) --P1323's format regex: A\d\.\d\.\d\.\d[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 ''..(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 ''..(label or 'Encyclopedia of Islam')..''..p.getCatForId('TDVİA')end
function p.teLink(id, label) --P1693's format regex: E[1-8]\.\d\.\d\.\d\.\d\.\d\.\d (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
'7' then if #e2
function p.tepapaLink(id, label) --P3544's format regex: \d+ (e.g. 1) if not id:match('^%d+$') then return false end return ''..(label or 'Te Papa (New Zealand)')..''..p.getCatForId('TePapa')end
function p.thLink(id, label) --P1694's format regex: H\d\.\d\.\d\.\d\.\d (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 ''..(label or 'Terminologia Histologica')..''..p.getCatForId('TH')end
function p.tlsLink(id, label) id = id:gsub(' +', '_') --P1362's format regex: \p[\p{L}\d_',\.\-\(\)\*/–] (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 ''..(label or 'Theaterlexikon (Switzerland)')..''..p.getCatForId('TLS') --no https as of 9/2019end
function p.troveLink(id, label) --P1315's format regex: [1-9]\d (e.g. 12345678) if not id:match('^[1-9]%d%d%d%d%d%d?%d?$') then return false end return ''..(label or 'Trove (Australia)')..''..p.getCatForId('Trove')end
function p.ukparlLink(id, label) --P6213's format regex: [a-zA-Z\d] (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 ''..(label or 'UK Parliament')..''..p.getCatForId('UKPARL')end
function p.ulanLink(id, label) --P245's format regex: 500\d (e.g. 500123456) if not id:match('^500%d%d%d%d%d%d$') then return false end return ''..(label or 'Artist Names (Getty)')..''..p.getCatForId('ULAN')end
function p.uscongressLink(id, label) --P1157's format regex: [A-Z]00[01]\d (e.g. A000123) if not id:match('^[A-Z]00[01]%d%d%d$') then return false end return ''..(label or 'US Congress')..''..p.getCatForId('USCongress') --no https as of 9/2019end
function p.vcbaLink(id, label) --P8034's format regex: \d\/[1-9]\d (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 ''..(label or 'Vatican')..''..p.getCatForId('VcBA')end
function p.viafLink(id, label) --P214's format regex: [1-9]\d(\d|\d) (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 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 ''..id..'' to ''..id..''. return ''..(label or 'VIAF')..''..p.getCatForId('VIAF')end
--
function p.append(str, c, length) while str:len < length do str = c .. str end return strend
--Returns the ISNI check digit isni must be a string where the 15 first elements are digits, e.g. 0000000066534145function 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
--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-identifierfunction p.validateIsni(id) --P213 (ISNI) format regex: [0-9] [0-9] [0-9] [0-9][0-9X] (e.g. 0000-0000-6653-4145) --P496 (ORCID) format regex: 0000-000(1-[5-9]|2-[0-9]|3-[0-4])\d-\d[\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 idend
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] (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 falseend
----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 idsend
function p.matchesWikidataRequirements(itemId, reqs) for _, group in ipairs(reqs) do local property = 'P'..group[1] local qid = group[2] local statements = mw.wikibase.getBestStatements(itemId, property) if statements then for _, statement in ipairs(statements) do if statement.mainsnak.datavalue then if statement.mainsnak.datavalue.value['numeric-id']
-- Creates a human-readable standalone wikitable version of p.conf, and tracking categories with page counts, for use in the documentationfunction p.docConfTable(frame) local wikiTable = '
Parameter\n'.. ' | Section\n'.. ' | Appears as\n'.. ' | Wikidata property\n'.. ' | Tracking categories and page counts\n'.. ' | -\n'.. '! '.. 'Articles\n'.. ' | '.. 'User pages\n'.. '! '.. 'Misc. pages\n'.. ' | '..'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, link if param "WORLDCATID" then -- WorldCat is special appearsAs = "WorldCat" link = "WorldCat Identities (identifier)" elseif conf.prefix then appearsAs = conf.prefix link = conf.link or param .. ' (identifier)' else appearsAs = conf[3](conf[5]) link = conf.link or param .. ' (identifier)' end local category = conf.category or param local args = local wpl = frame:expandTemplate --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'.. ' | '..param..''.. ' | '..section.. ' | '..appearsAs.. ' | data-sort-value='..pid..' | '..wpl.. ' | '..articleCount..''.. ' | '.. userCount..''.. ' | '.. miscCount..''.. ' | '.. faultyCount..'' end --append derivative WorldCat cats local wcd = 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 = "WorldCat (via Library of Congress)" else appearsAs = "WorldCat (via VIAF)" end wikiTable = wikiTable..'\n'.. ' | -\n'.. ' | '..'—'.. ' | General'.. ' | '..appearsAs.. ' | data-sort-value='..w..' | '..'—'.. ' | '..articleCount..''.. ' | —'.. ' | —'.. ' | —' end return require("Module:Suppress categories").main(wikiTable)..'\n |
---|
----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.
-- Check that the Wikidata item has this property-->value before adding itlocal reqs =
-- Parameter format: -- 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 itselfp.conf =
-- Legitimate aliases to p.conf, for convenience-- Format: p.aliases =
-- Deprecated aliases to p.conf; tracked in -- Format: p.deprecated =
----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]
) 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]
) and parentArgs[dep] then parentArgs[param] = parentArgs[dep] if namespace
nil or val
and (namespace
then local bMatch = false for _, wd in pairs(wikidataIds) do if val
false then differentOnWDCat = '' end end end end end if iMatches > 0 and iMatches
'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
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, ''PATH')..' WorldCat', nil, false)) --Validation? worldcatCat = p.getCatForId('WORLDCATID') elseif worldcatId
0 then worldcatCat = '' 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, 'WorldCat (via Library of Congress)', nil, false)) if namespace
then --if WORLDCATID suppressed suppressedIdCat = '' end local Navbox = require('Module:Navbox') local elementsCat = if rct
"General" or sect