Модул:Нормативен контрол

Този модул съдържа кода за изпълнение на навигационната лента „Нормативен контрол“ в шаблона {{Нормативен контрол}}.


local p = {}  --[[==========================================================================]] --[[                              Configuration                               ]] --[[==========================================================================]]  --[[ Format: { id = name of the parameter, label = name to be displayed in the navbox (Note: skip if same as id key), property = property id in Wikidata or direct link if no useful property exists, pattern = Lua regex pattern(s) to check if the value string for the given property is in valid format (Note: if multiple patterns exist, consider putting them in a table), } ]]--  local rep = mw.ustring.rep local databases = { 	--COMMON 	{ id = 'AAT', property = 1014, pattern = '300%d%d%d%d%d%d' }, 	{ id = 'ACM-DL', property = 864, pattern = '%d%d%d%d%d%d%d%d%d%d%d' }, 	{ id = 'BALaT', property = 3293, pattern = '%d+' }, 	{ id = 'BGCI', property = 5818, pattern = '%d+' }, 	{ id = 'BIBSYS', property = 1015, pattern = '[1-9]%d*' }, 	{ id = 'Bildindex', property = 2092, pattern = '%d+' }, 	{ id = 'BNE', property = 950, pattern = { 'XX%d%d%d%d%d?%d?%d?', 'a%d%d%d%d%d?%d?%d?', '[bM]im[ao]%d%d%d%d%d%d%d%d%d%d%d', '[bM]ise%d%d%d%d%d%d%d%d%d%d%d', 'bivi%d%d%d%d%d%d%d%d%d%d%d' } }, 	{ id = 'BNed', property = 2187, pattern = '[1-9]%d?%d?%d?%d?%d?' }, 	{ id = 'BNF', property = 268, pattern = '%d?%d%d%d%d%d%d%d%d[0-9bcdfghjkmnpqrstvwxz]' }, 	{ id = 'BNper', property = 2188, pattern = '[1-9]%d?%d?%d?%d?%d?' }, 	{ id = 'BNpub', property = 2189, pattern = '[1-9]%d?%d?%d?' }, 	{ id = 'Botanist', property = 428, pattern = "[%u%l%d%. '-]+" }, 	{ id = 'BPN', property = 651, pattern = '%d%d%d%d%d%d%d?%d?' }, 	{ id = 'CiNii', property = 271, pattern = 'D[AB]%d%d%d%d%d%d%d[%dX]' }, 	{ id = 'CONOR.BG', property = 8849, pattern = '%d+' }, 	{ id = 'DBLP', property = 2456, pattern = { '%d%d%d?/%d+', '%d%d%d?/%d+%-%d+', '[a-z]/[a-zA-Z][0-9A-Za-z]*', '[a-z]/[a-zA-Z][0-9A-Za-z]*%-%d+' } }, 	{ id = 'Dimensions', property = 6178, pattern = '%d+.%d+' }, 	{ id = 'DSI', property = 2349, pattern = '[1-9]%d*' }, 	{ id = 'EBIDAT', property = 9725, pattern = '[1-9]%d?%d?%d?' }, 	{ id = 'Emmy', property = 8381, pattern = '%S+' }, 	{ id = 'Europeana', link = 'Europeana', property = 7704, pattern = { 'place/base/%d+', 'agent/base/%d+', 'concept/base/%d+', 'organisation/base/%d+' } }, 	{ id = 'FAST', property = 2163, pattern = '[1-9]%d?%d?%d?%d?%d?%d?%d?' }, 	{ id = 'GND', property = 227, pattern = { '1[0123]?%d%d%d%d%d%d%d[%dX]', '[47]%d%d%d%d%d%d%-%d', '[1-9]%d?%d?%d?%d?%d?%d?%d?%-[%dX]', '3%d%d%d%d%d%d%d[%dX]' } }, 	{ id = 'Google Scholar', property = 1960, pattern = rep('[A-Za-z%d%-_]', 12) }, 	{ id = 'Grammy', property = 7303, pattern = '%w[%w%-]+%/%d+' }, 	{ id = 'HDS', property = 902, pattern = '%d%d%d%d%d%d' }, 	{ id = 'IAAF', property = 1146, pattern = '%d+' }, 	{ id = 'ICIA', property = 1736, pattern = '%d+' }, 	{ id = 'ISIL', property = 791, pattern = '%D%D?%D?%D?%-[%w%-:/]' .. rep ('[%w%-:/]?', 10) }, 	{ id = 'ISNI', property = 213, pattern = '0000[%s%-]?%d%d%d%d[%s%-]?%d%d%d%d[%s%-]?%d%d%d[%dX]' }, 	{ id = 'J9U', label = 'NLI J9U', property = 8189, pattern = '98' .. rep('%d', 12) .. '5171' }, 	{ id = 'Joconde', property = 347, pattern = rep('[%-%dA-Za-z]', 11) }, 	{ id = 'Koninklijke', property = 1006, pattern = '%d%d%d%d%d%d%d%d[%dX]' }, 	{ id = 'KulturNav', property = 1248, pattern = '%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x' }, 	{ id = 'LCCN', property = 244, pattern = '%l%l?%d?%d?%d?%d?%d%d%d%d%d%d' }, 	{ id = 'LIR', property = 886, pattern = '%d+' }, 	{ id = 'LNB', property = 1368, pattern = rep('%d', 9) }, 	{ id = 'Leonore', label = 'Léonore', property = 11152, pattern = '[1-9]%d*' }, -- transition to Léonore Web ID (P11152) since Léonore ID (P640) is not active anymore 	{ id = 'MBa', property = 434, pattern = '%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x' }, 	{ id = 'MBarea', property = 982, pattern = '%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x' }, 	{ id = 'MBi', property = 1330, pattern = '%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x' }, 	{ id = 'MBl', property = 966, pattern = '%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x' }, 	{ id = 'MBp', property = 1004, pattern = '%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x' }, 	{ id = 'MBrg', property = 436, pattern = '%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x' }, 	{ id = 'MBs', property = 1407, pattern = '%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x' }, 	{ id = 'MBw', property = 435, pattern = '%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x' }, 	{ id = 'MGP', property = 549, pattern = '%d%d?%d?%d?%d?%d?' }, 	{ id = 'NARA', property = 1225, pattern = '[1-9]%d?%d?%d?%d?%d?%d?%d?%d?' }, 	{ id = 'NCL', property = 1048, pattern = '%d+' }, 	{ id = 'NDL', property = 349, pattern = { 'a?1?%d?%d%d%d%d%d%d%d%d', 's?%d?%d%d%d%d%d%d%d%d' } }, 	{ id = 'NEWW', label = 'NEWW Women Writers', property = 2533, pattern = rep('[a-z%d]', 8) .. rep('%-[a-z%d][a-z%d][a-z%d][a-z%d]', 3) .. '%-' .. rep('[a-z%d]', 12) }, 	{ id = 'NKC', property = 691, pattern = '[a-z][a-z][a-z]?[a-z]?%d%d%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?' }, 	{ id = 'NLA', property = 409, pattern = '[1-9]%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?' }, 	{ id = 'NLG', property = 3348, pattern = '[1-9]%d*' }, 	{ id = 'NS', label = 'Народно събрание', property = 11873, pattern = '[1-9]%d*' }, 	{ id = 'NSK', property = 1375, pattern = rep('%d', 9) }, 	{ id = 'OCLC', property = 243, pattern = '%d%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?%d?' }, 	{ id = 'OpenLibrary', label = 'Open Library', property = 648, pattern = 'OL[1-9]%d*[AMW]' }, 	{ id = 'ORCID', property = 496, pattern = '0000%-?000%d%-?%d%d%d%d%-?%d%d%d[%dX]' }, 	{ id = 'PIC', property = 2750, pattern = '[1-9]%d*' }, 	{ id = 'PLWABN', property = 7293, pattern = '98' .. rep('%d', 10) .. '5606' }, 	{ id = 'RID', label = 'Researcher', property = 1053, pattern = { '[A-Z][A-Z]?[A-Z]?%-%d%d%d%d%-19%d%d', '[A-Z][A-Z]?[A-Z]?%-%d%d%d%d%-20%d%d' } }, 	{ id = 'RKDartists', label = 'RKD', property = 650, pattern = '[1-9]%d?%d?%d?%d?%d?' }, 	{ id = 'RKDID', label = 'RKDimages', property = 350, pattern = '[1-9]%d?%d?%d?%d?%d?' }, 	{ id = 'RSL', property = 947, pattern = '%d%d?%d?%d?%d?%d?%d?%d?%d?' }, 	{ id = 'SBN', label = 'ICCU', property = 396, pattern = '%D%D[A-Z0-3]V%d%d%d%d%d%d' }, 	{ id = 'Scopus', property = 1153, pattern = '[1-9]%d%d%d%d%d%d%d%d%d%d?%d?' }, 	{ id = 'SELIBR', label = 'LIBRIS', property = 906, pattern = '[1-9]%d%d%d%d%d?' }, 		{ id = 'LIBRIS', property = 5587, pattern = rep('[a-z%d]', 12) .. '[a-z%d]*' }, --alternative to SELIBR 	{ id = 'SIKART', property = 781, pattern = '%d%d%d%d%d%d%d%d?%d?' }, 	{ id = 'SNAC-ID', label = 'SNAC', property = 3430, pattern = '%d*[A-Za-z][%dA-Za-z]*' }, 	{ id = 'STRAZHA', label = 'Стража', property = 11446, pattern = { 'parl%-groups/[a-z%d-]+', 'parliaments/[a-z%d-]+', 'mps/[a-z%d-]+' } }, 	{ id = 'SUDOC', label = 'IdRef', property = 269, pattern = '%d%d%d%d%d%d%d%d[%dX]' }, 	{ id = 'TA', property = 1323, pattern = 'A%d%d%.%d%.%d%d%.%d%d%d[FM]?' }, 	{ id = 'TLS', property = 1362, pattern = '%u[%S_]+' }, 	{ id = 'ULAN', property = 245, pattern = '500%d%d%d%d%d%d' }, 	{ id = 'USCongress', label = 'US Congress', property = 1157, pattern = '[A-Z]00[01]%d%d%d' }, 	{ id = 'VIAF', property = 214, pattern = { '[1-9]%d' .. rep('%d?', 7), '[1-9]%d?%d?%d?' .. rep('%d', 18) } }, 	{ id = 'WorldCat Entities', label = 'WorldCat', property = 10832, pattern = {'[a-zA-Z%d][a-zA-Z%d]' .. rep('[a-zA-Z%d]?', 26)} }, 		{ id = 'WorldCat Identities', label = 'WorldCat', property = 7859, pattern = { 'viaf%-%d+', 'lccn%-n[a-z]?[%d%-]+' , 'n[cps]%-.+' } }, --deprecated as of March 2023; replaced by "WorldCat Entities" 	{ id = 'ZBMATH', property = 1556, pattern = '[a-z][a-z%-%.%d]*' },  	--TAXA 	{ id = 'ADW', property = 4024 }, 	{ id = 'AFD', property = 6039 }, 	{ id = 'AfroMoths', property = 6093, pattern = rep('[A-Z%d]', 8) }, ---[[AfroMoths]] DNE 	{ id = 'AlgaeBase', property = 1348 }, 	{ id = 'AmphibiaWeb', property = 5036, pattern = '[1-9]%d*' }, 	{ id = 'AntWeb', property = 5299, pattern = { '[A-Z][a-z]+', '[A-Z][a-z]+ [a-z]+', '[A-Z][a-z]+ [a-z]+ [a-z]+' } }, 	{ id = 'AoI', property = 5003, pattern = '%d+' }, ---[[Amphibians of India]] DNE 	{ id = 'AoFP', property = 6159, pattern = '[1-9]%d*' }, ---[[Atlas of Florida Plants]] DNE 	{ id = 'APA', property = 6137, pattern = '[1-9]%d*' }, ---[[Alabama Plant Atlas]] DNE 	{ id = 'APDB', property = 2036, pattern = '%d%d?%d?%d?%d?%d?' }, ---[[African Plant Database]] DNE 	{ id = 'APNI', property = 5984, pattern = '[1-9]%d*' }, 	{ id = 'Araneae', property = 3594, pattern = '[1-9]%d%d?%d?' }, ---[[]] DNE 	{ id = 'ASW', property = 5354, pattern = '[A-Za-z][A-Za-z/%-]*%d?%d?' }, 	{ id = 'Avibase', property = 2026, pattern = { rep('[A-Z%d]', 8), rep('[A-Z%d]', 16) } }, ---[[]] DNE 	{ id = 'BacDive', property = 2946, pattern = '%d%d?%d?%d?%d?%d?' }, 	{ id = 'BAMONA', property = 3398, pattern = { 'species/[^%s/]+', 'taxonomy/[^%s/]+' } }, ---[[Butterflies and Moths of North America]] DNE 	{ id = 'BHL', property = 687, pattern = '[1-9]%d*' }, 	{ id = 'BioLib', property = 838, pattern = '%d%d?%d?%d?%d?%d?%d?' }, ---[[]] DNE 	{ id = 'BirdLife', property = 5257, pattern = '[1-9]%d%d%d%d%d%d%d%d?' }, 	{ id = 'BirdLife-Australia', property = 6040, pattern = '[a-z][a-z%-]*' }, 	{ id = 'BOLD', property = 3606, pattern = '[1-9]%d*' }, 	{ id = 'BugGuide', property = 2464, pattern = '[1-9]%d?%d?%d?%d?%d?%d?' }, 	{ id = 'ButMoth', property = 3060, pattern = '[1-9]%d?%d?%d?%d?%.0' }, 	{ id = 'Calflora', property = 3420, pattern = '%d+' }, ---[[]] DNE 	{ id = 'Cal-IPC', property = 6176, pattern = '[a-z%-]+' }, ---[[California Invasive Plant Council]] DNE 	{ id = 'Center', property = 6003, pattern = '[a-z]+/[A-Za-z_%-]+' }, 	{ id = 'CMS', property = 6033, pattern = { '[a-z][a-z%-]*', '[a-z][a-z%-]*%-%d' } }, 	{ id = 'CNPS', property = 4194, pattern = '[1-9]%d*' }, 	{ id = 'Cockroach Species File', property = 6052, pattern = '[1-9]%d*' }, ---[[]] DNE 	{ id = 'CoL-Taiwan', property = 3088, pattern = '.-%d+.-' }, ---[[]] DNE 	{ id = 'Conifers', property = 1940 }, ---[[]] DNE 	{ id = 'Coreoidea Species File', property = 6053, pattern = '[1-9]%d%d%d%d%d%d' }, ---[[]] DNE 	{ id = 'CzechNDOP', property = 5263, pattern = '[1-9]%d*' }, ---closest match 	{ id = 'DFCA', property = 6115, pattern = '[1-9]%d*' }, ---[[Digital Flora of Central Africa]] DNE 	{ id = 'DORIS', property = 4630, pattern = '[1-9]%d*' }, ---closest match 	{ id = 'Dyntaxa', property = 1939, pattern = '%d%d?%d?%d?%d?%d?%d?' }, ---[[]] DNE 	{ id = 'eBird', property = 3444, pattern = { '[a-z%-][a-z%-][a-z%-]?[a-z%-]?[a-z%-]?[a-z%-]?%d?%d?', '[xy]00%d%d%d' } }, 	{ id = 'Ecocrop', property = 4753, pattern = '%d+' }, ---[[]] DNE 	{ id = 'ECOS', property = 6030, pattern = '[1-9]%d*' }, ---[[Environmental Conservation Online System]] DNE 	{ id = 'EEO', property = 6043, pattern = '[a-z][a-z%-]*' }, ---[[Espèces Envahissantes Outre-mer]] DNE 	{ id = 'EoL', property = 830, pattern = '[1-9]%d?%d?%d?%d?%d?%d?%d?' }, 	{ id = 'EPPO', property = 3031, pattern = rep('[A-Z%d]', 5) .. '[A-Z%d]?' }, 	{ id = 'EUNIS', property = 6177, pattern = '[1-9]%d*' }, 	{ id = 'FaunaEuropaea', label = 'Fauna Europaea', property = 1895, pattern = '%d%d?%d?%d?%d?%d?' }, 	{ id = 'FaunaEuropaeaNew', label = 'Fauna Europaea (2016)', property = 4807, pattern = '%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x' }, 	{ id = 'FEIS', property = 6044 }, ---[[Fire Effects Information System]] DNE 	{ id = 'FishBase', property = 938, pattern = '[1-9]%d?%d?%d?%d?' }, 	{ id = 'FloraBase', property = 3101, pattern = '%d+' }, 	{ id = 'FloraCatalana', property = 5179, pattern = 'VTax[1-9]%d?%d?%d?' }, ---[[]] DNE 	{ id = 'FloraWeb', property = 6094, pattern = '[1-9]%d*' }, ---[[]] DNE 	{ id = 'FLOW', property = 6096, pattern = '[1-9]%d*' }, ---[[Fulgoromorpha Lists On the Web]] DNE 	{ id = 'FNA', property = 1727, pattern = '[1-9]%d%d%d%d%d?%d?%d?%d?%d?' }, 	{ id = 'FoAO', property = 3100, pattern = '%d+' }, 	{ id = 'FoC', property = 1747, pattern = '[1-9]%d%d%d%d%d?%d?%d?%d?%d?' }, 	{ id = 'FOIH', property = 4311, pattern = '[1-9]%d*' }, 	{ id = 'FoIO', property = 3795, pattern = { '[a-zA-Z%d%-]+/?', 'systematics/[a-zA-Z%d%-]+/?' } }, ---[[Flora of Israel Online]] DNE, he.wiki link interferes with display 	{ id = 'Fossilworks', property = 842, pattern = '[1-9]%d?%d?%d?%d?%d?' }, 	{ id = 'Fungorum', property = 1391, pattern = '[1-9]%d?%d?%d?%d?%d?' }, 	{ id = 'GBIF', property = 846, pattern = '[1-9]%d?%d?%d?%d?%d?%d?%d?%d?' }, 	{ id = 'GISD', property = 5626, pattern = '[1-9]%d*' }, ---closest match 	{ id = 'GNAB', property = 4715, pattern = '[a-z][a-z%-]*' }, ---[[Guide to North American Birds]] DNE 	{ id = 'GONIAT', property = 5216, pattern = 'tax' .. rep('%d', 29) }, ---[[]] DNE 	{ id = 'GrassBase', property = 1832, pattern = { 'imp%d%d%d%d%d', 'gen%d%d%d%d%d' } }, 	{ id = 'GRIN', property = 1421 }, 	{ id = 'GTIBMA', label = 'GT IBMA', property = 6054, pattern = '[a-z][a-z%-]*' }, ---[[Groupe de travail Invasions biologiques en milieux aquatiques]] DNE 	{ id = 'Hepaticarum', label = 'Index Hepaticarum', property = 2794, pattern = '%d+' }, ---[[]] DNE 	{ id = 'IBC', property = 3099 }, 	{ id = 'iNaturalist', property = 3151, pattern = '[1-9]%d?%d?%d?%d?%d?%d?' }, 	{ id = 'IPA', property = 6161, pattern = '[1-9]%d*' }, ---[[Invasive Plant Atlas of the United States]] DNE 	{ id = 'IPNI', property = 961, pattern = '[1-9]%d?%d?%d?%d?%d?%d?%d?%-[123]' }, 	{ id = 'IRMNG', property = 5055, pattern = '[1-9]%d?%d?%d?%d?%d?%d?%d?' }, 	{ id = 'ISC', property = 5698, pattern = '[1-9]%d?%d?%d?%d?%d?%d?%d?' }, 	{ id = 'ITIS', property = 815, pattern = '[1-9]%d%d?%d?%d?%d?%d?' }, 	{ id = 'IUCN', property = 627, pattern = '[1-9]%d?%d?%d?%d?%d?%d?%d?%d?' }, 	{ id = 'LepIndex', property = 3064, pattern = '[1-9]%d?%d?%d?%d?%d?%d?' }, 	{ id = 'LoB', property = 5862, pattern = '[1-9]%d*' }, ---[[Catalogue of Lepidoptera of Belgium]] DNE 	{ id = 'LPSN', property = 1991 }, 	{ id = 'Mantodea Species File', property = 6055, pattern = '[1-9]%d*' }, ---[[]] DNE 	{ id = 'MichiganFlora', property = 6103 }, ---[[Michigan Flora]] DNE 	{ id = 'MoBotPF', property = 6034, pattern = '[1-9]%d*' }, 	{ id = 'MoL', property = 6092, pattern = '[A-Z][a-zA-Z_]+' }, ---[[Map of Life]] DNE 	{ id = 'MNHN', property = 6046 }, 	{ id = 'MONA', property = 4758, pattern = { '%d%d%d?%d?%d?', '%d%d%d?%d?%d?.%d' } }, 	{ id = 'MSW', property = 959, pattern = '1%d%d%d%d%d%d%d' }, 	{ id = 'MycoBank', property = 962, pattern = '[1-9]%d?%d?%d?%d?%d?' }, 	{ id = 'NAS', property = 6163, pattern = '[1-9]%d*' }, ---[[Nonindigenous Aquatic Species]] DNE 	{ id = 'NBN', property = 3240, pattern = '[A-Z][A-Z]' .. rep('[A-Z%d]', 14) }, 	{ id = 'NCBI', property = 685, pattern = '[1-9]%d?%d?%d?%d?%d?%d?' }, 	{ id = 'Neotropical', property = 6047 }, 	{ id = 'NOAA', property = 6049, pattern = '[a-z][a-z%-]*' }, 	{ id = 'NSWFlora', property = 3130, pattern = { '[A-Z][a-z]*', '[A-Z][a-z]*~[a-z]*' } }, ---[[New South Wales Flora]] DNE 	{ id = 'NTFlora', property = 5953, pattern = '[1-9]%d*' }, ---inconsistent property name/link 	{ id = 'NZBO', property = 6048, pattern = '[a-z][a-z%-]*' }, ---[[New Zealand Birds Online]] DNE 	{ id = 'NZOR', property = 2752, pattern = '%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x' }, ---[[New Zealand Organisms Register]] DNE 	{ id = 'Oiseaux', property = 6025, pattern = '[a-z][a-z.-]*' }, ---closest match 	{ id = 'Orthoptera Species File', property = 6050, pattern = '[1-9]%d*' }, ---[[]] DNE 	{ id = 'PalDat', property = 4122, pattern = '[A-Z][a-z]*%__?[a-z-]+' }, ---[[Palynological Database]] DNE 	{ id = 'Panartic', label = 'Panartic Flora', property = 2434, pattern = '%d+[a-z]?' }, ---[[]] DNE 	{ id = 'PfaF', property = 4301 }, 	{ id = 'PFI', property = 6114, pattern = '[1-9]%d*' }, ---[[Portal to the Flora of Italy]] DNE 	{ id = 'Phasmida Species File', property = 4855, pattern = '[1-9]%d*' }, ---[[]] DNE 	{ id = 'PPE', property = 6061, pattern = '[a-z][a-z%-/]*[a-z]' }, ---[[Plant Parasites of Europe]] DNE 	{ id = 'Plantarium', property = 3102, pattern = '%d+' }, ---[[]] DNE 	{ id = 'PlantList', label = 'Plant List', property = 1070, pattern = { 'gcc%-%d+', 'ifn%-%d+', 'ild%-%d+', 'kew%-%d+', 'rjp%-%d+', 'tro%-%d+' } }, 	{ id = 'PLANTS', property = 1772, pattern = '[A-Z][A-Z][A-Z][A-Z]?[A-Z]?%d?%d?%d?' }, 	{ id = 'Plazi', property = 1992, pattern = '%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x' }, 	{ id = 'POWO', property = 5037, pattern = 'urn:lsid:ipni%.org:names:[1-9]%d?%d?%d?%d?%d?%d?%d?%-[1234]' }, 	{ id = 'RD', property = 5473, pattern = 'genus=[A-Za-z]+%&species=[a-z%-]+' }, 	{ id = 'SANBI', property = 6056, pattern = '[1-9]%d*%-[1-9]%d*' }, 	{ id = 'SCC', property = 6057, pattern = '[1-9]%d*' }, ---[[Systematic Catalog of Culicidae]] DNE 	{ id = 'SeaLifeBase', property = 6018, pattern = '[1-9]%d*' }, 	{ id = 'SEINet', property = 6209, pattern = '[1-9]%d*' }, ---[[]] DNE 	{ id = 'Soortenregister', property = 3405, pattern = '[1-9]%d*' }, ---closest match 	{ id = 'Species+', property = 2040, pattern = '%d%d?%d?%d?%d?' }, 	{ id = 'SPRAT', property = 2455, pattern = '[1-9]%d*' }, 	{ id = 'Steere', property = 6035, pattern = '[1-9]%d*' }, 	{ id = 'TAXREF', property = 3186, pattern = '%d+' }, ---[[]] DNE 	{ id = 'TelaBotanica', property = 3105, pattern = '%d+' }, 	{ id = 'Titan', property = 4125, pattern = '%d+' }, ---[[]] DNE 	{ id = 'Tree of Life', property = 5221, pattern = { '[1-9]%d*', '%a+' } }, 	{ id = 'Tropicos', property = 960, pattern = '[1-9]%d?%d?%d?%d?%d?%d?%d?%d?' }, 	{ id = 'uBio', property = 4728, pattern = '[1-9]%d*' }, ---[[Universal Biological Indexer and Organizer]] DNE 	{ id = 'VASCAN', property = 1745, pattern = '%d%d?%d?%d?%d?' }, ---[[Vascular Plants of Canada]] DNE 	{ id = 'Verspreidingsatlas', property = 6142, pattern = '[A-Z]?%d+' }, ---[[]] DNE 	{ id = 'VicFlora', property = 5945, pattern = '%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x' }, ---closest match 	{ id = 'Vlinderstichting', property = 3322, pattern = '%d+' }, ---[[]] DNE 	{ id = 'Watson', label = 'Watson & Dallwitz', property = 1761, pattern = '[a-z][a-z][a-z][a-z][a-z][a-z][a-z]?[a-z]?' }, ---[[]] DNE 	{ id = 'WCSP', property = 3591, pattern = '%d%d?%d?%d?%d?%d?%d?' }, 	{ id = 'WikiAves', property = 4664, pattern = '[^%s/%?]+' }, ---[[]] DNE 	{ id = 'Wikispecies', label = 'Уикивидове', property = 'Wikispecies:$1' }, 	{ id = 'WiO', property = 6285, pattern = '[a-z][a-z-]*' }, ---[[Weeds in Ontario]] DNE 	{ id = 'WisFlora', property = 6227, pattern = '[1-9]%d*' }, ---[[Flora of Wisconsin]] DNE 	{ id = 'WoI', property = 3746, pattern = '[1-9]%d?%d?%d?' }, ---[[Wildflowers of Israel]] DNE 	{ id = 'WoRMS', property = 850, pattern = '[1-9]%d?%d?%d?%d?%d?%d?' }, 	{ id = 'WSC', property = 3288, pattern = 'urn:lsid:nmbe%.ch:spider[sgf][pea][nm]?:%d%d%d%d%d?%d?' }, 	{ id = 'Xeno-canto', property = 2426, pattern = '[A-Z][a-z]+%-[a-z][a-z]+' }, 	{ id = 'ZooBank', property = 1746, pattern = rep('[A-Z%d]', 8) .. rep('%-[A-Z%d][A-Z%d][A-Z%d][A-Z%d]', 3) .. '%-' .. rep('[A-Z%d]', 12) }, }  local tCats = { 	'[[Категория:Страници с празен нормативен контрол]]', 	'', --  [2] placeholder for [[Категория:Нормативен контрол с невалидни идентификатори]] 	'', --  [3] placeholder for [[Категория:Нормативен контрол с потиснати идентификатори]] 	'', --  [4] placeholder for [[Категория:Нормативен контрол с ръчно въведени идентификатори]] 	'', --  [5] placeholder for [[Категория:Нормативен контрол с ръчно въведени идентификатори, различаващи се с тези от Уикиданни]] 	'', --  [6] placeholder for [[Категория:Нормативен контрол с ръчно въведени идентификатори, идентични с тези от Уикиданни]] 	'', --  [7] placeholder for [[Категория:Нормативен контрол с повтарящи се стойности на параметри за извикване на Уикиданни]] 	'', --  [8] placeholder for [[Категория:Нормативен контрол с множество ръчно въведени параметри за извикване на Уикиданни]] 	'', --  [9] placeholder for [[Категория:Нормативен контрол с автоматично добавени базионими]] 	'', -- [10] placeholder for [[Категория:Нормативен контрол с автоматично добавени протоними]] 	'', -- [11] placeholder for [[Категория:Нормативен контрол с автоматично добавен монотипен род]] 	'', -- [12] placeholder for [[Категория:Нормативен контрол в монотипен вид с липсващи родове]] }  --[[==========================================================================]] --[[                              Local functions                             ]] --[[==========================================================================]] local function nilOrEmpty(v) 	return not v or v == '' end  local function getLink(property, val, label) 	local link, returnVal = '', {}  	returnVal.isError = false  	if mw.ustring.match(val, '^//') or mw.ustring.match(val, '^[Hh][Tt][Tt][Pp][Ss]?://') then 		link = val 	else 		if type(property) == 'number' and property > 0 then 			local entityObject = mw.wikibase.getEntity('P' .. property) 			local dataType  			if entityObject then 				dataType = entityObject.datatype 			else 				returnVal.isError = true 			end  			if dataType == 'external-id' then 				local formatterURL = nil 				if property == 3746 or --Wildflowers of Israel 				   property == 3795 or --Flora of Israel Online 				   property == 5397 --Tierstimmenarchiv 				then 					formatterURL = entityObject:getBestStatements('P1630')[2] --use 2nd formatterURL for English version 				end 				if not formatterURL then formatterURL = entityObject:getBestStatements('P1630')[1] end --default to [1] 				if formatterURL then 					if formatterURL.mainsnak.datavalue and formatterURL.mainsnak.datavalue.value then --nil check for ABA 						link = formatterURL.mainsnak.datavalue.value 					end 				end 			elseif dataType == 'url' then 				local subjectItem = entityObject:getBestStatements('P1629')[1] 				if subjectItem then 					local officialWebsite = mw.wikibase.getEntity(subjectItem.mainsnak.datavalue.value.id):getBestStatements('P856')[1] 					if officialWebsite then	link = officialWebsite.mainsnak.datavalue.value end 				end 			elseif dataType == 'string' then 				local formatterURL = entityObject:getBestStatements('P1630')[1] 				if formatterURL then 					link = formatterURL.mainsnak.datavalue.value 				else 					local subjectItem = entityObject:getBestStatements('P1629')[1] 					if subjectItem then 						local officialWebsite = mw.wikibase.getEntity(subjectItem.mainsnak.datavalue.value.id):getBestStatements('P856')[1] 						if officialWebsite then	link = officialWebsite.mainsnak.datavalue.value end 					end 				end 			else 				returnVal.isError = true 			end 		elseif type(property) == 'string' then 			link = property 		end  		local valurl = val 		if mw.ustring.find(link, 'antweb.org') then valurl = mw.ustring.gsub(valurl, ' ', '%%20') end 		if type(property) == 'number' then 			--doublecheck language for Wildflowers of Israel ID 			if property == 3746 then link = mw.ustring.gsub(link, '/hebrew/', '/english/') end 			--remove spaces in ISNI 			if property == 213 then valurl = mw.ustring.gsub(valurl, ' ', '') end 			--format spaces in PfaF, e.g. for "Elaeagnus x ebbingei" 			if property == 4301 then valurl = mw.ustring.gsub(valurl, ' ', '+') end 		end 		valurl = mw.ustring.gsub(valurl, '%%', '%%%%') 		link = mw.ustring.gsub(link, '$1', valurl) 	end  	link = mw.ustring.gsub(link, '^[Hh][Tt][Tt][Pp]([Ss]?)&#58;//', 'http%1://') -- fix wikidata URL 	--val = mw.ustring.match(val, '([^=/]*)/?$') -- get display name from end of URL 	if not nilOrEmpty(link) then 		if mw.ustring.find(link, '//') then 			returnVal.text = '[' .. link .. ' ' .. label .. ']' 		else 			returnVal.text = '[[' .. link .. '|' .. label .. ']]' 		end 	end  	return returnVal end  local function getIdFromWikidata(item, property) 	if property == 'PWikispecies:$1' then 		return item:getSitelink('specieswiki') 	else 		local claim = item:getBestStatements(property) 		for i = 1, #claim do 			if claim[i].mainsnak.datavalue then 				return claim[i].mainsnak.datavalue.value 			end 		end 	end end  local function createItem(label, rawValue, link, withUid, validValue, pencil) 	if not link then return nil end 	if not validValue then 		tCats[2] = '[[Категория:Нормативен контрол с невалидни идентификатори]]' 		return '* ' .. label .. ': <abbr title="Невалиден идентификатор" class="error" style="font-size:inherit">' .. rawValue .. '</abbr>' .. pencil .. '\n' 	end 	if withUid then link = '<span class="uid">' .. link .. '</span>' end 	return '* ' .. link .. '\n' end  local function editAtWikidata(qid, pid) 	if not (qid and mw.ustring.match(qid, '^%s*[Qq]?%d+%s*$')) then return '' end 	local link = ':d:' .. mw.ustring.gsub(qid, '^%s*[Qq]?(%d+)%s*$', 'Q%1') .. mw.ustring.gsub(pid or '', '^%s*[Pp]?(%d+)%s*$', '#P%1') 	return '[[Файл:OOjs UI icon edit-ltr-progressive.svg|frameless|text-top|10px|link=' .. link .. '|Редактиране в Уикиданни]]' end  --[[==========================================================================]] --[[                           Documentation table                            ]] --[[==========================================================================]]  -- Creates a human-readable wikitable version of databases function p.doc(frame) 	local wikiTable = '\n{| class="wikitable sortable" style="width:98%; margin:0"' .. 					  '\n|-' .. 					  '\n! style="width:19.6%" | Параметър' .. 					  '\n! style="width:19.6%" | Показване в нав. лента' .. 					  '\n! style="width:19.6%" | Свойство в [[Уикиданни|УД]]' .. 					  '\n! style="width:19.6%" | Валидиране чрез [[Регулярен израз|РИ]]?' .. 					  '\n! style="width:19.6%" | Със свойство за валиден URL в УД?' 	for i = 1, #databases do 		local param = mw.ustring.lower(databases[i].id) 		local label = databases[i].label or databases[i].id 		local property = tonumber(databases[i].property) 		if property then 			property = '[[:d:Property:P' .. property .. '|P' .. property .. ']]' 		else 			property = '—' 		end 		local rxValidation = nilOrEmpty(databases[i].pattern) and 'не' or 'да' 		local validLink = getLink(databases[i].property, '', label).text and 'да' or 'не' 		--concat 		wikiTable = wikiTable .. 					'\n|-' .. 					'\n| ' .. param .. 					'\n| ' .. label .. 					'\n| ' .. property .. 					'\n| ' .. rxValidation .. 					'\n| ' .. validLink 	end 	wikiTable = wikiTable .. '\n|}\n' 	return mw.text.tag('div', { style = 'height:550px; width:99%; overflow:auto; padding:0' }, wikiTable) end  --[[==========================================================================]] --[[                                   Main                                   ]] --[[==========================================================================]]  function p.main(frame) 	local resolveEntity = require('Модул:ResolveEntityId')._id 	local currentTitle = mw.title.getCurrentTitle() 	local namespace = currentTitle.namespace 	local currentId = namespace == 0 and resolveEntity(mw.wikibase.getEntityIdForCurrentPage()) 	local parentArgs = {} 	local fromTitleCount, rowCount = 1, 0 	local outString = '' 	local tFroms = {} --non-sequential table of unique froms 	local iFroms = 0 --integer size of tFroms, b/c Lua  	--Process args 	for k, v in pairs(frame:getParent().args) do 		if type(k) == 'string' then 			--make args case insensitive 			local lowerk = mw.ustring.lower(k) 			parentArgs[lowerk] = v 			--remap abc to abc1 			if not mw.ustring.find(lowerk, '%d$') then --if no number at end of param 				if not parentArgs[lowerk .. '1'] then 					parentArgs[lowerk] = nil 					lowerk = lowerk .. '1' 					parentArgs[lowerk] = v 				end 			end 			--find highest from param 			if mw.ustring.sub(lowerk, 1, 4) == 'from' then 				v = resolveEntity(v) 				if v == currentId then v = nil end 				local fromNumber = tonumber(mw.ustring.sub(lowerk, 5, -1)) 				if fromNumber and fromNumber >= fromTitleCount then fromTitleCount = fromNumber end 				if v then --is valid eid or title 					--look for duplicate froms while we're here 					if tFroms[v] then 						tCats[7] = '[[Категория:Нормативен контрол с повтарящи се стойности на параметри за извикване на Уикиданни]]' 						v = nil 					else 						tFroms[v] = true 						iFroms = iFroms + 1 					end 				end 				parentArgs[lowerk] = v 			end 		end 	end  	if iFroms > 2 then 		tCats[8] = '[[Категория:Нормативен контрол с множество ръчно въведени параметри за извикване на Уикиданни]]' 	end  	--Assess the page's relationship with Wikidata 	local currentItem = nil 	if currentId then 		currentItem = mw.wikibase.getEntity(currentId) 	elseif parentArgs['from1'] then -- optional for pages not connected to WD or not in main namespace (for test purposes) 		currentItem = mw.wikibase.getEntity(parentArgs['from1']) 		parentArgs['from1'] = nil 	end  	if currentItem then --Taxа specific 		local acceptable = { 			['Q16521'] = 'taxon', 			['Q310890'] = 'monotypic taxon', 			['Q2568288'] = 'ichnotaxon', 			['Q23038290'] = 'fossil taxon', 			['Q47487597'] = 'monotypic fossil taxon', 		} --strict 		--Append basionym to arg list, if not already provided 		local currentBasState = currentItem:getBestStatements('P566')[1] --basionym 		if currentBasState then 			local basionymId = currentBasState.mainsnak.datavalue.value.id 			if basionymId and resolveEntity(basionymId) and not tFroms[basionymId] then 				--check that basionym is a strict instance of taxon 				local basionymItem = mw.wikibase.getEntity(basionymId) 				if basionymItem then 					for _, instanceOfState in pairs(basionymItem:getBestStatements('P31')) do --instance of 						local instanceOf = instanceOfState.mainsnak.datavalue.value.id 						if acceptable[instanceOf] then 							fromTitleCount = fromTitleCount + 1 							--append basionym & track 							parentArgs['from' .. fromTitleCount] = basionymId 							tCats[9] = '[[Категория:Нормативен контрол с автоматично добавени базионими]]' 							break 						end 					end 				end 			end 		end 		--Append original combination to arg list, if not already provided 		local currentOCState = currentItem:getBestStatements('P1403')[1] --original combination 		if currentOCState then 			local orcoId = currentOCState.mainsnak.datavalue.value.id 			if orcoId and resolveEntity(orcoId) and not tFroms[orcoId] then 				--check that orco is a strict instance of taxon 				local orcoItem = mw.wikibase.getEntity(orcoId) 				if orcoItem then 					for _, instanceOfState in pairs(orcoItem:getBestStatements('P31')) do --instance of 						local instanceOf = instanceOfState.mainsnak.datavalue.value.id 						if acceptable[instanceOf] then 							fromTitleCount = fromTitleCount + 1 							--append orco & track 							parentArgs['from' .. fromTitleCount] = orcoId 							tCats[10] = '[[Категория:Нормативен контрол с автоматично добавени протоними]]' 							break 						end 					end 				end 			end 		end 		--Append monotypic genus/species to arg list of monotypic species/genus, if not already provided 		for _, instanceOfState in pairs(currentItem:getBestStatements('P31')) do --instance of 			local taxonRank = nil 			local parentItem = nil 			local parentTaxon = nil 			local parentTaxonRank = nil 			local parentMonoGenus = nil --holy grail/tbd 			local instanceOf = instanceOfState.mainsnak.datavalue.value.id 			if instanceOf and (instanceOf == 'Q310890' or instanceOf == 'Q47487597') then --monotypic/fossil taxon 				local taxonRankState = currentItem:getBestStatements('P105')[1] --taxon rank 				if taxonRankState then 					taxonRank = taxonRankState.mainsnak.datavalue.value.id 				end 				if taxonRank and taxonRank == 'Q7432' then --species 					--is monotypic species; add genus 					local parentTaxonState = currentItem:getBestStatements('P171')[1] --parent taxon 					if parentTaxonState then parentTaxon = parentTaxonState.mainsnak.datavalue.value.id end 					--confirm parent taxon rank == genus & monotypic 					if parentTaxon and resolveEntity(parentTaxon) then 						parentItem = mw.wikibase.getEntity(parentTaxon) 						if parentItem then 							local parentTaxonRankState = parentItem:getBestStatements('P105')[1] --taxon rank 							if parentTaxonRankState then parentTaxonRank = parentTaxonRankState.mainsnak.datavalue.value.id end 							if parentTaxonRank and parentTaxonRank == 'Q34740' then --parent == genus 								for _, parentInstanceOfState in pairs(parentItem:getBestStatements('P31')) do --instance of 									local parentInstanceOf = parentInstanceOfState.mainsnak.datavalue.value.id 									if parentInstanceOf and 									  (parentInstanceOf == 'Q310890' or parentInstanceOf == 'Q47487597') then --monotypic/fossil taxon 										parentMonoGenus = parentTaxon --confirmed 										break 									end 								end 								if parentMonoGenus and not tFroms[parentMonoGenus] then 									fromTitleCount = fromTitleCount + 1 									--append monotypic genus & track 									parentArgs['from' .. fromTitleCount] = parentMonoGenus 									tCats[11] = '[[Категория:Нормативен контрол с автоматично добавен монотипен род]]' 									break 								end 							end 						end 					end 					if not (parentMonoGenus or tFroms[parentMonoGenus]) then 						tCats[12] = '[[Категория:Нормативен контрол в монотипен вид с липсващи родове]]' 						break 					end 				--elseif taxonRank and taxonRank == 'Q34740' then --genus 					--is monotypic genus; add species 					--... 				end 			end 		end 	end --if currentItem  	--Setup navbox 	local navboxParams = { 		name = 'Нормативен контрол', 		bodyclass = 'hlist hlist-big plainlinks', 		state = 'off', 		navbar = 'off', 	}  	local currentOnce = true 	for f = 1, fromTitleCount + 1 do 		local elements, fromWikidata = {}, {} 		local title, item = nil, nil 		if currentOnce and not parentArgs['from' .. f] then 			item = currentItem 			title = currentTitle.text 			parentArgs['from' .. f] = item and item.id or title 			currentOnce = false 		end 		if parentArgs['from' .. f] then 			--Fetch Wikidata item 			if not item and parentArgs['from' .. f] ~= title then 				item = mw.wikibase.getEntity(parentArgs['from' .. f]) 			end 			if item then 				local statements = item:getBestStatements('P225') --taxon name 				if statements and statements[1] then 					local datavalue = statements[1].mainsnak.datavalue 					if datavalue then 						title = require('Модул:TaxonItalics').italicizeTaxonName(datavalue.value, false) -- italicize taxon name 					end 				end 				title = title or item:getLabel() or item:getSitelink() or item.id 			end  			if not nilOrEmpty(title) then 				title = mw.title.new(title) 			end  			if title then 				for i = 1, #databases do 					local param = mw.ustring.lower(databases[i].id) 					local label = databases[i].label or databases[i].id 					local propId = databases[i].property 					local pattern = databases[i].pattern 					local val = parentArgs[param .. f] 					--Wikidata fallback if requested 					local wikidataId = item and getIdFromWikidata(item, 'P' .. propId) 					if wikidataId then 						if not val then 							val = wikidataId 							fromWikidata[param .. f] = true 						elseif val == '' then 							tCats[3] = '[[Категория:Нормативен контрол с потиснати идентификатори]]' 						else 							if val ~= wikidataId then 								tCats[5] = '[[Категория:Нормативен контрол с ръчно въведени идентификатори, различаващи се с тези от Уикиданни]]' 							else 								tCats[6] = '[[Категория:Нормативен контрол с ръчно въведени идентификатори, идентични с тези от Уикиданни]]' 							end 						end 					else 						if not nilOrEmpty(val) then 							tCats[4] = '[[Категория:Нормативен контрол с ръчно въведени идентификатори]]' 						end 					end  					if not nilOrEmpty(val) then 						local validValue = false 						if nilOrEmpty(pattern) then 							--non-existent pattern; assume the value is always valid 							validValue = true 						elseif type(pattern) == 'string' then 							if mw.ustring.match(val, '^' .. pattern .. '$') then 								validValue = true 							end 						elseif type(pattern) == 'table' then 							for j = 1, #pattern do 								if mw.ustring.match(val, '^' .. pattern[j] .. '$') then 									validValue = true 								end 							end 						end  						local rowItem = nil 						--skip item creation for WorldCat Identities if there is a WorldCat Entities entry/item 						--or for LIBRIS if there is a SELIBR entry/item 						--or for Wikispecies for the current title/eid 						if not ( 							param == 'worldcat identities' and (parentArgs['worldcat entities' .. f] or fromWikidata['worldcat entities' .. f]) or 							param == 'libris' and (parentArgs['selibr' .. f] or fromWikidata['selibr' .. f]) or 							param == 'wikispecies' and (parentArgs['from' .. f] == mw.wikibase.getEntityIdForCurrentPage() or parentArgs['from' .. f] == currentTitle.text) 						) then 							rowItem = createItem(label, val, getLink(propId, val, label).text, param ~= 'worldcat identities' and param ~= 'wikispecies', validValue, editAtWikidata(fromWikidata[param .. f] and parentArgs['from' .. f], propId)) 						end 						if rowItem then table.insert(elements, rowItem) end 					end 				end  				--Generate navbox row 				if #elements > 0 then 					rowCount = rowCount + 1 					navboxParams['wd-edit' .. rowCount] = editAtWikidata(parentArgs['from' .. f], '#identifiers') 					navboxParams['group' .. rowCount] = mw.ustring.gsub(title.text, '%s+%b()$', '') .. navboxParams['wd-edit' .. rowCount] 					navboxParams['list' .. rowCount] = table.concat(elements) 				end 			end 		end 	end --for f = 1, fromTitleCount  	--adjust navbox for number of rows 	if rowCount > 0 then 		tCats[1] = '' --AC is not empty 		if rowCount == 1 then 			navboxParams['group1'] = 'Нормативен контрол' .. navboxParams['wd-edit1'] 		else 			navboxParams['title'] = 'Нормативен контрол' 			navboxParams['state'] = 'expanded' 		end 		outString = require('Модул:Navbox')._navbox(navboxParams) 	end  	if namespace == 0 or namespace == 2 or namespace == 118 then --tracking categories only in Main, User or Draft NS 		outString = outString .. table.concat(tCats) 		if not nilOrEmpty(parentArgs['demo1']) or not nilOrEmpty(parentArgs['test1']) then 			outString = mw.ustring.gsub(outString, '(%[%[)(Категория:)', '%1:%2') 		end 	end  	return outString end  return p