Module:Cite taxon

require('strict')

local p = {} local data = {} local templateArgs = {} -- contains arguments passed to cite web local target = {}       -- short cut to target table, e.g. fishbase, cof, etc

local function firstToUpper(str) return (str:gsub("^%l", string.upper)) end -- define citation template and custom parameters for various sources

--####################### Default functions ########################## data.default = {} -- currently being tested on Avibase, but Fossilworks, Tropicos, FNA and a few others are candidates data.default.id = function (id, source) local title = id local url = source.customArgs['baseURL'] .. (source.customArgs['searchStr'] or "") .. id	return title, url end data.default.error = function return "Minimal requirement is two of id, url and title parameters" end data.default.search = function (search, source) local title = "Search for " .. search local url = source.customArgs['baseURL'] .. source.customArgs['searchString'] .. search .. source.customArgs['searchSuffix'] return title, url end

--[[ handling for ID only (unused, original concept) p.genericIdCitation = function(frame, title, url)

if not templateArgs['id'] then return "no id parameter detected" end templateArgs['url']= target.CustomArgs['baseURL'] .. target.CustomArgs['searchStr'] .. templateArgs['id'] return p.citeWeb(frame, title, url) end]] --####################### FISH ##################################### --======================== Fishbase ================================= data.fishbase = { citationArgs = { ['editor1-last']="Froese", ['editor1-first']="Rainer", ['editor1-link']="Rainer Froese", ['editor2-last']="Pauly", ['editor2-first']="Daniel", --['last-author-amp'] ="yes", ['website'] = "Fishbase", --['publisher'] = "" },	customArgs = { exclude= "order, family,genus, species, subspecies, 1, 2, 3, 4", baseURL = "http://www.fishbase.org/", defaultTitle = "Search FishBase" }, } data.fishbase.species = function(genus, species, subspecies)

local title = genus .. " " .. species local url = data.fishbase.customArgs['baseURL'] .. "summary/SpeciesSummary.php?genusname=" .. genus .. "&speciesname=" .. species if subspecies then url = url .. "+" .. subspecies title = title .. " " .. subspecies end title = "''" .. title .. "''"		return title, url end data.fishbase.genus = function(genus) local title = "Species in genus ''" .. firstToUpper(genus) .. "''"		local url = data.fishbase.customArgs['baseURL'] .. "identification/SpeciesList.php?genus=" .. genus return title, url end data.fishbase.order = function(order) local title = "Order " .. firstToUpper(order) local url = data.fishbase.customArgs['baseURL'] .. "Summary/OrdersSummary.php?order=" .. order return title, url end data.fishbase.family = function(family) local title = "Family " .. firstToUpper(family) local url = data.fishbase.customArgs['baseURL'] .. "Summary/FamilySummary.php?family=" .. family return title, url end data.fishbase.error = function return "No recognised taxon options: order, family, genus, species, subspecies." end data.fishbase.custom = function --TODO decide what to do with default date local version = "April 2006 version" -- Should we have a default (probably not) if templateArgs['month'] then version = templateArgs['month'] end if templateArgs['year'] then version = templateArgs['year'] .. " version" end if templateArgs['month'] then version = templateArgs['month'] .. " " .. version end templateArgs['version'] = version end --================================ Catalog of Fishes ================================================ data.cof = { citationArgs = { --baseURL = "http://researcharchive.calacademy.org/research/ichthyology/catalog/fishcatget.asp?", ['editor1-last']="Eschmeyer", ['editor1-first']="William N.", ['editor1-link']="William N. Eschmeyer", ['editor2-last']="Fricke", ['editor2-first']="Ron", ['editor3-last']="van der Laan", ['editor3-first']="Richard", ['name-list-style'] ="amp", ['website'] = "Catalog of Fishes", ['publisher'] = "California Academy of Sciences" },	customArgs = { exclude= "family,genus,species,genid,spid,id,list,1,2,3", baseURL = "http://researcharchive.calacademy.org/research/ichthyology/catalog/fishcatget.asp?", defaultTitle = "CAS - Eschmeyer's Catalog of Fishes" } } data.cof.species = function(genus, species, subspecies) local taxon = genus .. " " .. species local url = data.cof.customArgs['baseURL'] .. 'tbl=species&genus=' .. genus .. '&species=' .. species local title = "Species related to " .. "''" .. firstToUpper(taxon) .. ""       -- .. "" species synonyms"	    return title, url end data.cof.genus  = function(genus)	    local url = data.cof.customArgs['baseURL'] .. 'tbl=species&genus=' .. genus	    local title = "Species in the genus " .. firstToUpper(genus) .. "''" 	    return title, url end       -- note the family works with subfamilies using &family=SUBFAMILY data.cof.family  = function(family)	    local list = templateArgs['list'] or "genus"	    local url = data.cof.customArgs['baseURL'] .. 'tbl=' .. list .. '&family=' .. family        local title = "Species"        if list == "genus" then  title = "Genera" end         title = title .. ' in the family ' .. firstToUpper(family)          return title, url end data.cof.genid = function(genid)   	    local searchStr =  "genid" .. '=' .. genid        local title =  searchStr        local url = data.cof.customArgs['baseURL'] .. searchStr        return title, url end data.cof.spid = function(spid) local searchStr = "spid" .. '=' .. spid local title = searchStr local url = data.cof.customArgs['baseURL'] .. searchStr return title, url end data.cof.error = function return "Error. No recognised option set by template (need one of family, genus, species (also requires genus), spid, or genid" end --======================Fishes of the World 5===============================	data.fotw5 = {	citeTemplate = "Cite book",	citationArgs = {	   --['website'] = "",		first1 = "Joseph S.", last1 = "Nelson",		first2="Terry C.", last2="Grande",		first3="Mark V. H.", last3="Wilson", 		--work = "Fishes of the World (work)",		title = "Fishes of the World", edition="5th", year = 2016,		publisher ="John Wiley and Sons", location="Hoboken",		isbn = "978-1-118-34233-6", doi="10.1002/9781119174844" ,	},	customArgs = {exclude="gb-page,q,dq,1",	              baseURL = "https://onlinelibrary.wiley.com/doi/book/10.1002/9781119174844", -- online library	              defaultTitle = "Fishes of the World",	              altTitle = "Fishes of the World",               -- wikilinked for when using chapter/section title altURL = "https://sites.google.com/site/fotw5th/", -- classification },	GoogleBooks = { baseURL = "https://books.google.co.uk/books?id=", id = "E-MLDAAAQBAJ", defaultPage = "&pg=PP1" } } data.fotw5.default2 = function(targs) local title = data.fotw5.citationArgs['work'] local url = data.fotw5.customArgs['baseURL'] local chapterParams = { title      = title, ['chapter-url']= data.fotw5.customArgs['googleBooks'] }    --return title, url, chapterParams end

data.BentonVP4 = { citeTemplate = "Cite book", citationArgs = { first1 = "Michael J.", last1 = "Benton", title = "Vertebrate Palaeontology", edition="4th", year = 2014, publisher ="John Wiley & Sons", isbn = "978-1-118-40764-6", },	customArgs = {exclude="gb-page,q,dq,1", --baseURL = "", defaultTitle = "Vertebrate Palaeontology", altTitle = "Vertebrate Palaeontology" -- wikilinked for when using chapter/section title },	GoogleBooks = { baseURL = "https://books.google.co.uk/books?id=", id = "qak-BAAAQBAJ", defaultPage = "&pg=PP1", } }

--====================TODO FishWisePro================================================== data.fishwisepro = { citationArgs = { ['website'] = "FishWisePro",

},	customArgs = {exclude="family,genus,species,1", baseURL = "" } }

-- #################### AMPHIBIA and REPTILES ############################### -- ================= Amphibian Species of the World (ASW6) --Recommended citation: Frost, Darrel R. 2019. Amphibian Species of the World: an Online Reference. Version 6.0 (Date of access). Electronic Database accessible at http://research.amnh.org/herpetology/amphibia/index.html. American Museum of Natural History, New York, USA.   URL for family page: http://research.amnh.org/vz/herpetology/amphibia/Amphibia/Anura/Allophrynidae           baseURL      = http://research.amnh.org/vz/herpetology/amphibia/           suffix       = Amphibia/Anura/Allophrynidae           note: needs the whole hierarchy (except the superfamily which is optional)    Template for main taxonomic listing:     SEARCH http://research.amnh.org/vz/herpetology/amphibia/amphib/basic_search?basic_query=Atelopus&stree=&stree_id=           searchSuffix = amphib/basic_search?basic_query=Atelopus&stree=&stree_id=    SEARCH http://research.amnh.org/vz/herpetology/amphibia/content/search?taxon=Allophryn*&subtree=&subtree_id=&english_name=&author=&year=&country=           searchSuffix = /content/search?taxon=Allophryn*&subtree=&subtree_id=&english_name=&author=&year=&country=           minimul      = /content/search?taxon=Allophryn*&subtree data.ASW6 ={ citationArgs = { website ="Amphibian Species of the World, an Online Reference.", version = "Version 6.0", publisher = "American Museum of Natural History, New York", ['last1']="Frost", ['first1']="Darrel R.", ['author1-link']="Darrel R. Frost", },	customArgs = { exclude = "taxon,species,genus,family, superfamily,1,2,3", baseURL = "http://research.amnh.org/herpetology/amphibia/", defaultSuffix = "index.html", defaultTitle = "ASW Home" } }

data.ASW6.species = function(genus, species, subspecies)

-- search for genus+species local title = "Search for taxon: " .. "''" .. genus .. " " .. species .. "''"		 	--local search = ""?action=names&taxon="" -- old version (pre ASW6) --local search = "amphib/basic_search?basic_query="  -- basic search local search = "content/search?taxon="             -- guided search for taxon name local url = data.ASW6.customArgs['baseURL'] .. search -- .. genus .. '+AND+' .. species .. '&quot;' .. genus .. '+' .. species .. '&quot;' return title, url end data.ASW6.genus = function(genus) return data.ASW6.taxon(genus) -- use genus as alias of taxon end data.ASW6.taxon = function(taxon) local title = "Search for Taxon: " .. taxon local url= data.ASW6.customArgs['baseURL'] .. "content/search?taxon=" .. taxon return title, url end data.ASW6.family = function(family) local order = data.ASW6.checkOrder(family) local url= data.ASW6.customArgs['baseURL'] .. "Amphibia/" .. order .. "/" .. firstToUpper(family) local title = firstToUpper(family) return title, url end data.ASW6.checkOrder = function(family)

local gymnophiona={ "Caeciliidae", "Chikilidae", "Dermophiidae", "Herpelidae", "Ichthyophiidae", "Grandisoniidae", "Indotyphlidae", "Rhinatrematidae", "Scolecomorphidae", "Siphonopidae", "Typhlonectidae" } local caudata = { "Ambystomatidae", "Amphiumidae", "Cryptobranchidae", "Hynobiidae", "Plethodontidae", "Proteidae", "Rhyacotritonidae", "Salamandridae", "Sirenidae" } for k,v in pairs(caudata) do   	if v == family then return "Caudata" end end for k,v in pairs(gymnophiona) do   	if v == family then return "Gymnophiona" end end return "Anura" end

--============================= AmphibiaWeb =================================== --  Citation: AmphibiaWeb. 2019.  University of California, Berkeley, CA, USA. Accessed 27 Sep 2019.       Code:     -- data.amphibiaweb = { citationArgs = { website = "AmphibiaWeb", publisher = "University of California, Berkeley", --['editor1-last']="", ['editor1-first']="", ['editor1-link']="", },   customArgs = { exclude = "taxon,species,genus,family,1,2,3", baseURL = "https://amphibiaweb.org/", defaultSuffix = "taxonomy/AW_FamilyPhylogeny.html", defaultTitle = "AmphibiaWeb Family Taxonomy" } } data.amphibiaweb.species = function (genus, species, subspecies) local title = "''" .. genus .. " " .. species .. "''"		 	--https://amphibiaweb.org/cgi/amphib_query?where-genus=Altiphrynoides&where-species=malcolmi local url = data.amphibiaweb.customArgs['baseURL'] .. "cgi/amphib_query?rel-genus=equals&where-genus=" .. genus .. "&rel-species=equals&where-species=" .. species return title, url end data.amphibiaweb.genus = function (genus) local title = "''" .. genus .. "''"		 	--https://amphibiaweb.org/cgi/amphib_query?where-genus=Altiphrynoides&where-species=malcolmi local url = data.amphibiaweb.customArgs['baseURL'] .. "cgi/amphib_query?rel-genus=equals&where-genus=" .. genus .. "&include_synonymies=Yes&show_photos=Yes" return title, url end data.amphibiaweb.family = function (family)		-- if family use standardised url local url = data.amphibiaweb.customArgs['baseURL'] .. "lists/" .. firstToUpper(templateArgs['family']) .. ".shtml" local title = templateArgs['family'] return title, url end

--=========================== The Reptile Database data.reptileDB = { -- http://reptile-database.reptarium.cz/species?genus=Epacrophis&species=boulengeri -- recommended citation: Uetz, P., Freed, P. & Hošek, J. (eds.) (2019) The Reptile Database, http://www.reptile-database.org, accessed [insert date here] citationArgs = { --website="reptile-database.org", website="The Reptile Database", ['editor1-last']="Uetz", ['editor1-first']="P.", --['editor1-link']="Peter Uetz", ['editor2-last']="Freed", ['editor2-first']="P.", ['editor3-last']="Hošek", ['editor3-first']="J.", --year=2019 },	customArgs = { exclude = "taxon,species,genus,family,1,2,3", baseURL = "http://reptile-database.reptarium.cz/" } }

data.reptileDB.species = function(genus, species) local title = "''" .. genus .. " " .. species .. "''"	   --http://reptile-database.reptarium.cz/species?genus=Loxocemus&species=bicolor local url = data.reptileDB.customArgs['baseURL'] .. "species?genus=" .. genus .. "&species=" .. species return title, url end data.reptileDB.genus = function(genus) local title = "''" .. genus .. "''" 	   --http://reptile-database.reptarium.cz/advanced_search?genus=Malayopython&submit=Search local url = data.reptileDB.customArgs['baseURL'] .. "advanced_search?genus=" .. genus .. "&exact%5B0%5D=taxon&submit=search" return title, url end data.reptileDB.family = function(family) return data.reptileDB.taxon(family) end data.reptileDB.order = function(order) return data.reptileDB.taxon(order) end data.reptileDB.taxon = function(taxon) local title = taxon --http://reptile-database.reptarium.cz/advanced_search?taxon=Viperidae&exact%5B0%5D=taxon&submit=Search local url = data.reptileDB.customArgs['baseURL'] .. "advanced_search?taxon=" .. taxon .. "&exact%5B0%5D=taxon&submit=search" return title, url end

--################################### BIRDS ######################################## --====================Handbook of the Birds of the World Alive (HBW Alive)============== data.HBWalive = { citationArgs = { website="Handbook of the Birds of the World Alive", publisher="Lynx Edicions" },	customArgs = { exclude="order,family,genus,species,taxon,id,1", baseURL = "https://www.hbw.com/", defaultSuffix = "family/home", defaultTitle = "Family | HBW Alive" } } --############################## HBW ALIVE ######################################### -- family and species entries have mix of common name and taxon name so cannot be prempted; -- must use title + url (which uses default functions in this module) data.HBWalive.order = function(order) local title = "Order " .. firstToUpper(order) --https://www.hbw.com/order/struthioniformes local url = target.customArgs['baseURL'] .. "order/" .. order return title, url end

--======================IOC World Bird List==========================	       Gill, F & D Donsker (Eds). 2019. IOC World Bird List (v9.2). doi :  10.14344/IOC.ML.9.2.	        Gill F, D Donsker & P Rasmussen  (Eds). 2020. IOC World Bird List (v10.2). doi :  10.14344/IOC.ML.10.1. data.IOC = { citationArgs = { website="IOC World Bird List", --	version="Version 9.2",                              -- shouldn't default; should be hardcode so it doesn't change ['editor1-last']="Gill", ['editor1-first']="F.",  ['editor1-link']="Frank Gill (ornithologist)", ['editor2-last']="Donsker", ['editor2-first']="D.", ['editor3-last']="Rasmussen", ['editor3-first']="P.",  -- TODO only show from version 10.1 onwards --	doi = "10.14344/IOC.ML.9.2",                         -- this changes by version number and is not a useful part of the cictation publisher="International Ornithological Congress" },	customArgs = { exclude="order,family,genus,species,taxon,id,1", baseURL = "https://www.worldbirdnames.org/", defaultSuffix = "", defaultTitle = "IOC World Bird List: Welcome" }, } data.IOC.version = function local version = templateArgs['version'] local old = false if version then version = string.gsub( version, "[Vv]ersion ", "") local versionNumber = tonumber(version) if versionNumber < 10.1 then old = true end else local Date = require('Module:Date')._Date if Date(templateArgs['access-date']) < Date('1 January 2020') then old = true end end if old then data.IOC.citationArgs['editor3-last'] = nil data.IOC.citationArgs['editor3-first'] = nil end end data.IOC.order = function(order) data.IOC.version local IOCorders = {Struthioniformes='ratites',Rheiformes='ratites',Apterygiformes='ratites',Casuariiformes='ratites',Tinamiformes='ratites',Galliformes='megapodes',Anseriformes='waterfowl',Caprimulgiformes='nightjars',Apodiformes='swifts',Musophagiformes='turacos',Otidiformes='turacos',Cuculiformes='turacos',Mesitornithiformes='turacos',Pterocliformes='turacos',Columbiformes='pigeons',Gruiformes='flufftails',Podicipediformes='grebes',Phoenicopteriformes='grebes',Charadriiformes='sandpipers',Eurypygiformes='loons',Phaethontiformes='loons',Gaviiformes='loons',Sphenisciformes='loons',Procellariiformes='loons',Ciconiiformes='storks',Suliformes='storks',Pelecaniformes='pelicans',Opisthocomiformes='raptors',Accipitriformes='raptors',Strigiformes='owls',Coliiformes='mousebirds',Leptosomiformes='mousebirds',Trogoniformes='mousebirds',Bucerotiformes='mousebirds',Coraciiformes='rollers',Piciformes='woodpeckers',Cariamiformes='falcons',Falconiformes='falcons',Psittaciformes='parrots', Passeriformes='nz_wrens'} -- passeriformes link not very useful

local title = "Order " .. firstToUpper(order) local url = data.IOC.customArgs['baseURL'] .. "/bow/" .. IOCorders[order] return title, url end data.IOC.family = function(family) data.IOC.version local IOCfamilies = { Struthionidae = {"ratites", 4}, Alcippeidae = {"babblers", 24989 } }     -- temporary partial list for testing local title = "Family " .. firstToUpper(family) --https://www.worldbirdnames.org/Family/Struthionidae local url = data.IOC.customArgs['baseURL'] .. "Family/" .. family  -- old version (might be resurrected by IOC) -- https://www.worldbirdnames.org/new/bow/babblers/#1338626516R24989 if IOCfamilies[family] then                                            -- test version local partial list url = data.IOC.customArgs['baseURL'] .. "new/bow/" .. IOCfamilies[family][1] .. "/#1338626516R" .. IOCfamilies[family][2] end return title, url end data.IOC.default = function( title, url) data.IOC.version return title, url end

data.BOW = { citationArgs = { website="Birds of the World Online", --	doi = "", --	['last1']="Winkler", ['first1']="David W.",              -- are these always the authors in version 1? no, perhaps for family page --	['last2']="Billerman", ['first2']="Shawn M.", --	['last3']="Lovette", ['first3']="Irby J.", --	['editor1-last']="Billerman", ['editor1-first']="S. M.",  --['editor1-link']="", --	['editor2-last']="Keeney", ['editor2-first']="B. K.", --	['editor3-last']="Rodewald", ['editor3-first']="P. G.", --   ['editor4-last']="Schulenberg",  ['editor4-first']="T. S.", --   ['version'] = 1,   ['year'] = 2020,                                             -- may not want to default publisher="Cornell Lab of Ornithology, Ithaca, NY." },	customArgs = { exclude="citation,make,order,family,genus,species,taxon,id,1", baseURL = "https://birdsoftheworld.org/bow/species/", defaultSuffix = "", defaultTitle = "Explore Taxonomy" }, } -- function not needed of not adding anything else data.BOW.default2 = function( title, url) --data.BOW.citationArgs['version'] = "Version 1" mw.addWarning("testing BOW.default function") return title, url end -- id works with the default function data.default.id (id, source) data.BOW.id2 = function( id) local url = data.IOC.customArgs['baseURL'] ..id  local title = "BOW id="  .. id end

-- make BOW to parse standard citation,    vesrion 1 (family): Winkler, D. W., S. M. Billerman, and I.J. Lovette (2020). Bulbuls (Pycnonotidae), version 1.0. In Birds of the World                         (S. M. Billerman, B. K. Keeney, P. G. Rodewald, and T. S. Schulenberg, Editors). Cornell Lab of Ornithology, Ithaca, NY, USA.                         https://doi.org/10.2173/bow.pycnon4.01    version 2 (species): Limparungpatthanakij, W. L., L. Fishpool, and J. Tobias (2020). Buff-vented Bulbul (Iole crypta), version 2.0. In Birds of the World                         (S. M. Billerman and B. K. Keeney, Editors). Cornell Lab of Ornithology, Ithaca, NY, USA.                         https://doi.org/10.2173/bow.buvbul1.02 data.BOW.citation = function( value) local citation = templateArgs['citation']

data.BOW.citationArgs['year'] = citation:match ('^%D+(%d%d%d%d)') data.BOW.citationArgs['doi'] = citation:match ('10%.2173/bow%..+')                           -- https://doi.org/10.2173/bow.pycnon4.01 --data.BOW.citationArgs['version'] = citation:match ('version %d%.%d')                       -- version applies to page, not whole BOW local title = citation:match ('%d%d%d%d%)%.(.*, version %d%.%d)');                           -- include version number in title    local suffix = citation:match ('10%.2173/bow%.(.+%d)%.');                                     -- https://doi.org/10.2173/bow.pycnon4.01    local version = "/cur/"                                                                       -- for the current version    version = citation:match ('version (%d%.%d)')                                                 -- for the cited version    local url = data.BOW.customArgs['baseURL']  .. suffix .. '/'  .. version .. '/'     title = title:gsub( '%((%D+) (%D+)%)', "(%1 %2)")    local authors = citation:match ('^(%D+) %(%d%d%d%d%)')    if authors then           -- split authors with modified code from make cite iucn    	local list = {}    	--mw.addWarning ("author string: " .. authors)   	authors = authors:gsub(", and ", ", ")   -- for 3 or more authors    	authors = authors:gsub(" and ", ", ")     -- for 2 editors      	list = mw.text.split (authors, ',');									    -- split the string on the commas into entries in list		if #list == 0 then			mw.addWarning ("Zero length author list. Please report example of BOW citation at Cite BOW template talk page.");			data.BOW.citationArgs['author'] = authors 					        	-- no 'names' of the proper form; return the original as a single |author= parameter		else			for i, name in ipairs (list) do											-- for each author in list 			    if i==1 then                                --note the first name has last name followed by initials after comma, so takes fill first two parts of the split			    	data.BOW.citationArgs['last1'] = name			    elseif i==2 then			    	data.BOW.citationArgs['first1'] = name			    elseif i > 2 then data.BOW.citationArgs['last'..i-1] = name:match ('%s(%a-)$') data.BOW.citationArgs['first'..i-1] = name:match ('(.+)%s%a-$') --data.BOW.citationArgs['author'..i-1] = nil else -- something has gone wrong (use author) data.BOW.citationArgs['author'..i-1] = name end if i>1 and 1==2 then mw.addWarning ("last" .. tostring(i-1) .. "=" .. data.BOW.citationArgs['last'..i-1]) mw.addWarning ("first".. tostring(i-1) .. "=" .. data.BOW.citationArgs['first'..i-1]) end end end end -- now parse editors local editors = citation:match ('In Birds of the World %((.-), Editors?%)' ) -- omit editors as cite web psoitioning is weird if editors then          -- split editors with modified code from make cite iucn local list = {} --mw.addWarning ("editor string: " .. editors) editors = editors:gsub(", and ", ", ")   -- for 3 or more authors editors = editors:gsub(" and ", ", ")    -- for 2 editors list = mw.text.split (editors, ',');									   -- split the string on the commas into entries in list if #list == 0 then mw.addWarning ("problem with editor splitting") data.BOW.citationArgs['editor'] = editors 					       	-- no 'names' of the proper form; return the original as a single |author= parameter else for i, name in ipairs (list) do											-- for each author in list if i>0 then                               --note the editor names are all same format (unlike authors) data.BOW.citationArgs['editor-last'..i] = name:match ('%s(%a-)$') data.BOW.citationArgs['editor-first'..i] = name:match ('(.+)%s%a-$') --data.BOW.citationArgs['editor'..i-1] = nil else -- something has gone wrong (use editor) --			   	data.BOW.citationArgs['editor'..i] = name end if i>0 and 1==2 then mw.addWarning ("editor-last" .. tostring(i) .. "=" .. data.BOW.citationArgs['editor-last'..i]) mw.addWarning ("editor-first".. tostring(i) .. "=" .. data.BOW.citationArgs['editor-first'..i]) end end end end

--if not url then url = data.BOW.customArgs['baseURL'] end --if not title then title = "Title parameter required" end return title, url end

-- basic handling for Taxonomy in Flux website data.tif = { citationArgs = { website="Taxonomy in Flux", ['editor1-last']="Boyd III", ['editor1-first']="John H.",    --['editor1-link']="", },	customArgs = { exclude="order,family,genus,species,taxon,id,1", baseURL = "http://jboyd.net/Taxo/", defaultSuffix = "List.html", defaultTitle = "Taxonomy in Flux" }, } -- - Avibase                  e.g. https://avibase.bsc-eoc.org/species.jsp?avibaseid=9144EF4017F2D8B1 data.avibase = { citationArgs = { website="Avibase", ['editor1-last']="Lepage", ['editor1-first']="Denis",    --['editor1-link']="", },	customArgs = { exclude="order,family,genus,species,taxon,id,1", baseURL = "https://avibase.bsc-eoc.org/", searchStr = "species.jsp?avibaseid=", defaultTitle = "Avibase - The World Bird Database" } } -- use default function data.avibase.id = function (id)   local title = "Avibase id: " .. id	local url = data.avibase.customArgs['baseURL'] .. data.avibase.customArgs['searchStr'] .. id	return title, url end --

-- ============================= IUCN ================================================= -- for species in taxon; for species assessments, us -- https://www.iucnredlist.org/search?query=Murexia&searchType=species -- https://www.iucnredlist.org/search?query=aonyx&searchType=species data.iucn = { citationArgs = { website="IUCN Red List of Threatened Species", --publisher="IUCN" },	customArgs = { exclude="family,genus,species,taxon,id,1", baseURL = "https://www.iucnredlist.org", searchString = "/search?query=", searchSuffix = "&searchType=species", defaultSuffix = "", defaultTitle="IUCN Red List of Threatened Species" }	} data.iucn.genus = function(genus)  return data.iucn.taxon(genus, "TITLE_ITALICS") end data.iucn.family = function(family) return data.iucn.taxon(family) end data.iucn.order = function(order)  return data.iucn.taxon(order) end data.iucn.taxon = function(taxon, titleItalics) local title = firstToUpper(taxon) if titleItalics then title = "''" .. title .. "''" end local url = data.iucn.customArgs['baseURL'] .. data.iucn.customArgs['searchString'] .. taxon .. data.iucn.customArgs['searchSuffix'] return title, url end

-- ============================= ASM Mammal Diversity Database ======================== data.asm = { citationArgs = { website="ASM Mammal Diversity Database", publisher="American Society of Mammalogists" },	customArgs = { exclude="family,genus,species,taxon,id,1,2,3", baseURL = "https://www.mammaldiversity.org/", defaultTitle="ASM Mammal Diversity Database" } }

data.asm.species2 = function(genus, species) -- use species function below -- old url = https://mammaldiversity.org/species-account.php?genus=ursus&species=arctos -- new url = https://www.mammaldiversity.org/explore.html#genus=Dipodomys&species=deserti&id=1001892 (only id required) local title = "''" .. genus .. " " .. species .. "''"	local url = data.asm.customArgs['baseURL'] .. "explore.html#genus=" .. genus .. "&species=" .. species if templateArgs['id'] then url = url .. "&id=" .. templateArgs['id'] end return title, url end data.asm.id = function(id) --local url = data.asm.customArgs['baseURL'] .. "species-account/species-id=" .. templateArgs['id'] -- new format https://www.mammaldiversity.org/explore.html#species-id=1006310 --local url = data.asm.customArgs['baseURL'] .. "explore.html#species-id=" .. id -- templateArgs['id'] -- newer format https://www.mammaldiversity.org/explore.html#genus=Leopardus&species=colocola&id=1005993 (genus and species can be blank) -- newer (Mar 2024) https://www.mammaldiversity.org/taxon/1006020 local title = "Species-id=" .. id local hashString = "genus=&species=&id=" .. id                  -- if id only, requires blank genus and species (superceded by /taxon/link) if templateArgs['genus'] and templateArgs['species'] then title = "''" .. templateArgs['genus'] .. " " .. templateArgs['species'] .. "'' (id=" .. id ..")" hashString = "genus=" .. templateArgs['genus'] .. "&species=" .. templateArgs['species'] .. "&id=" .. id   	end --local url = data.asm.customArgs['baseURL'] .. "explore.html#genus=&species=&id=" .. id -- templateArgs['id'] -- url = data.asm.customArgs['baseURL'] .. "explore.html#" .. hashString local url = data.asm.customArgs['baseURL'] .. "taxon/" .. id

return title, url end data.asm.species = function(genus, species) if templateArgs['id'] then return data.asm.id(templateArgs['id']) -- use the ASM explore page if ID given (as permalink) end if genus and species then -- otherwisee use the treeview page with the species info local title = "''" .. firstToUpper(genus) .. " " .. species .. "''" 		local url = data.asm.customArgs['baseURL'] .. "tree.html#genus=" .. genus .. "&species=" .. species return title, url end end

data.asm.genus = function(genus)  return data.asm.taxon(genus, "genus", "TITLE_ITALICS") end data.asm.family = function(family) return data.asm.taxon(family, "family") end data.asm.order = function(order)  return data.asm.taxon(order, "order") end data.asm.taxon = function(taxon, rank, titleItalics) --https://mammaldiversity.org/#ZmVsaWRhZSZnbG9iYWxfc2VhcmNoPXRydWUmbG9vc2U9dHJ1ZQ --                            Base64.encode(felidae&global_search=true&loose=true) local title = firstToUpper(taxon) if titleItalics then title = "''" .. title .. "''" end local url = data.asm.customArgs['baseURL'] .. "tree.html" if rank then                                              -- no rank if taxon called directly url = url .. "#" .. rank .. "=" .. taxon end return title, url end --############################## Base64 encode and decode (used for ASM##################### local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' -- encoding data.asm.Base64 = {} data.asm.Base64.encode = function(data)   return ((data:gsub('.', function(x) local r,b='',x:byte for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end return r;   end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)        if (#x < 6) then return  end        local c=0        for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end        return b:sub(c+1,c+1)    end)..({ , '==', '=' })[#data%3+1]) end -- decoding data.asm.Base64.decode=function(data)    data = string.gsub(data, '[^'..b..'=]', )    return (data:gsub('.', function(x)        if (x == '=') then return  end        local r,f=,(b:find(x)-1)        for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end        return r;    end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)        if (#x ~= 8) then return  end        local c=0        for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end        return string.char(c)    end)) end --######################## Misc ################################## -- 3 approaches to handling DB:         1) use DB as website and use author for editors (if known)            (a) use via to append WoRMS            (b) use postscript to append WoRMs            (c) use publisher for WoRMS        2) use WoRMS as website and designate DB as author (recommended by WoRMS) CURRENT            (option) add editors [TODO see cite WoRMS for list]            issue: what to do about editors changing (need to use access-date) data.WoRMS = { citationArgs = { author = "WoRMS", website = "World Register of Marine Species", --['via'] = "World Register of Marine Species", --postscript = '&#32;from the World Register of Marine Species.'

},	customArgs = {exclude="id,db,1", baseURL = "http://www.marinespecies.org/aphia.php?", searchStr = "p=taxdetails&id=", defaultTitle="World Register of Marine Species" } } data.WoRMS.id = function(id) -- Two styles        1. http://www.marinespecies.org/aphia.php?p=taxdetails&id=14712            >  WoRMS (2018). Heterobranchia. Accessed at: http://marinespecies.org/aphia.php?p=taxdetails&id=14712 on 2018-11-28          2. http://www.marinespecies.org/aphia.php?p=taxdetails&id=1057249            > MolluscaBase (2018). Ringipleura. Accessed through: World Register of Marine Species at: http://www.marinespecies.org/aphia.php?p=taxdetails&id=1057249 on 2018-11-28 if not templateArgs['id'] then return "no id parameter detected" end local searchStr = "p=taxdetails&id=" .. templateArgs['id'] if templateArgs['db'] then data.WoRMS.db (templateArgs['db']) --else -- WoRMS is primary source (note cite WoRMs uses WoRMS as publisher and the db as the work)   	 templateArgs['via'] = nil    	 templateArgs['postscript'] = nil end --templateArgs['website'] = templateArgs['db'] -- alternative (and use |postscript) --templateArgs['publisher'] = templateArgs['via'] --page WoRMS - World Register of Marine Species - Heterobranchia local title = "WoRMS taxon details: AphiaID " .. id   local url = data.WoRMS.customArgs['baseURL'] .. data.WoRMS.customArgs['searchStr'] .. id   return title, url

end data.WoRMS.default = function if templateArgs['db'] then data.WoRMS.db (templateArgs['db']) end end data.WoRMS.db = function(db)	-- if database hosted by WoRMS

db = string.lower( db ) if db == "world of copepods database" or db == "copepoda" or db == "copepods" or db == "copepod" then templateArgs['author'] = "World of Copepods Database" templateArgs['editor-last1']="Walter"; templateArgs['editor-first1']="T.C." templateArgs['editor-last2']="Boxshall"; templateArgs['editor-first2']="G." -- year ? (2022). 	elseif db == "world amphipoda database" or db == "amphipoda" or db == "amphipod"then templateArgs['author'] = "World Amphipoda Database" templateArgs['editor-last1']="Horton"; templateArgs['editor-first1']="T." templateArgs['editor-last2']="Lowry"; templateArgs['editor-first2']="J." templateArgs['editor-last3']="De Broyer"; templateArgs['editor-first3']="C." templateArgs['display-editors']="etal"; -- full list is about 20 names elseif db == "world isopoda database" or db == "isopoda" or db == "isopod"then templateArgs['author'] = "World Marine, Freshwater and Terrestrial Isopod Crustaceans database" templateArgs['editor-last1']="Boyko"; templateArgs['editor-first1']="C.B." templateArgs['editor-last2']="Bruce"; templateArgs['editor-first2']="N.L." templateArgs['editor-last3']="Hadfield"; templateArgs['editor-first3']="K.A." templateArgs['editor-last4']="Merrin"; templateArgs['editor-first4']="K.L." templateArgs['editor-last5']="Ota."; templateArgs['editor-first5']="Y." templateArgs['editor-last6']="Poore"; templateArgs['editor-first6']="G.C.B." templateArgs['editor-last7']="Taiti"; templateArgs['editor-first7']="S." elseif db == "millibase" or db == "diplopoda" or db == "diplopod"then templateArgs['author'] = "MilliBase" templateArgs['editor-last1']="Sierwald"; templateArgs['editor-first1']="P." templateArgs['editor-last2']="Spelda"; templateArgs['editor-first2']="J." elseif db == "molluscabase" or db == "mollusca" or db == "mollusc" then templateArgs['author'] = "MolluscaBase" else templateArgs['author'] = templateArgs['db'] -- this is recommended by WoRMS end end

-- Species files      -- takes db parameter       --https://db.speciesfile.org/otus/$ID/overview       --https://plecoptera.speciesfile.org/otus/890815/overview

data.speciesfile = { citationArgs = { website  = " Species File", --publisher = "", },	customArgs = {exclude="id,1,2,3,4,5,db", --baseURL = "https://" .. firstToUpper(templateArgs['db'] ) .. ".speciesfile.org/", --searchStr = "otus/", -- defaultSuffix = "/overview", --defaultTitle= " Species File" } } data.speciesfile.id = function(id)                              -- e.g. https://plecoptera.speciesfile.org/otus/890815/overview local db = data.speciesfile.db -- customise for speciesfile local title = firstToUpper(db) .. " Species File id&#61;" .. id -- use entity &#61; for = to avoid missing pipe CS1 warning --local url = data.speciesfile.customArgs['baseURL'] .. data.speciesfile.customArgs['searchStr'] .. id .. data.speciesfile.customArgs['defaultSuffix '] local url = "https://" ..db .. ".speciesfile.org/otus/" .. id .. "/overview" return title, url end data.speciesfile.default = function local db = data.speciesfile.db local title = firstToUpper(db) .. " Species File" local url = "https://" ..db .. ".speciesfile.org/" return title, url end data.speciesfile.db = function local db = string.lower( templateArgs['db'] ) templateArgs['editor-last1']="Hopkins"; templateArgs['editor-first1']="H." if db == "zoraptera" then   -- ed: Hopkins, H. templateArgs['editor-last1']="Hopkins"; templateArgs['editor-first1']="H." elseif db == "dermaptera" then -- eds: Hopkins, H., Haas, F. & Deem, L.S. templateArgs['editor-last1']="Hopkins"; templateArgs['editor-first1']="H." templateArgs['editor-last2']="Johnson"; templateArgs['editor-first2']="K.P." templateArgs['editor-last3']="Smith"; templateArgs['editor-first3']="V.S." elseif db == "plecoptera" then                   -- (eds) DeWalt RE, Hopkins H, Neu-Becker U, and Stueber G templateArgs['editor-last1']="DeWalt"; templateArgs['editor-first1']="R.E." templateArgs['editor-last2']="Hopkins"; templateArgs['editor-first2']="H." templateArgs['editor-last3']="Neu-Becker"; templateArgs['editor-first3']="U." templateArgs['editor-last4']="Stueber"; templateArgs['editor-first4']="G." elseif db == "orthoptera " then --eds: Cigliano, M.M., H. Braun, D.C. Eades & D. Otte. templateArgs['editor-last1']="Cigliano"; templateArgs['editor-first1']="M.M." templateArgs['editor-last2']="Braun"; templateArgs['editor-first2']="H." templateArgs['editor-last3']="Eades"; templateArgs['editor-first3']="D.C." templateArgs['editor-last4']="Otte"; templateArgs['editor-first4']="D." elseif db == "grylloblattodea" then     -- ed: Hopkins, H. templateArgs['editor-last1']="Hopkins"; templateArgs['editor-first1']="H." elseif db == "mantophasmatodea" then     -- ed: Hopkins, H. templateArgs['editor-last1']="Hopkins"; templateArgs['editor-first1']="H." elseif db == "embioptera" then     -- ed: Hopkins, H. templateArgs['editor-last1']="Hopkins"; templateArgs['editor-first1']="H." elseif db == "phasmida" then       -- eds: Brock PD, Büscher TH, Baker E. templateArgs['editor-last1']="Brock"; templateArgs['editor-first1']="P.D." templateArgs['editor-last2']="Büscher"; templateArgs['editor-first2']="T.H." templateArgs['editor-last3']="Baker"; templateArgs['editor-first3']="E." elseif db == "mantodea" then		-- not updated yet elseif db == "cockroach" then      -- ed: Beccaloni, G.W. templateArgs['editor-last1']="Beccaloni"; templateArgs['editor-first1']="G.W." elseif db == "isoptera" then       -- ed: Hopkins, H. templateArgs['editor-last1']="Hopkins"; templateArgs['editor-first1']="H." elseif db == "psocodea" then     --eds: Hopkins, H., Johnson, K.P., & Smith, V.S. templateArgs['editor-last1']="Hopkins"; templateArgs['editor-first1']="H." templateArgs['editor-last2']="Johnson"; templateArgs['editor-first2']="K.P." templateArgs['editor-last3']="Smith"; templateArgs['editor-first3']="V.S." elseif db == "aphid" then        -- ed: Colin FAVRET templateArgs['editor-last1']="Favret"; templateArgs['editor-first1']="Colin" elseif db == "coleorrhyncha" then -- ed: Hopkins, H. templateArgs['editor-last1']="Hopkins"; templateArgs['editor-first1']="H." elseif db == "coreoidea" then -- not updated yet elseif db == "lygaeoidea" then -- eds: Dellapé, Pablo M. & Thomas J. Henry templateArgs['editor-last1']="Dellapé"; templateArgs['editor-first1']="Pablo M." templateArgs['editor-last2']="Henry"; templateArgs['editor-first2']="Thomas J." elseif db == "hoppers" then -- eds: Dmitriev, D.A., Anufriev, G.A., Bartlett, C.R., Blanco-Rodríguez, E., Borodin, Oleg I., Cao, Y.-H., Deitz, L.L., Dietrich, C.H., Dmitrieva, M.O., El-Sonbati, S.A., Evangelista de Souza, O., Gjonov, I.V., Gonçalves, A.C., Hendrix, S., McKamey, S., Kohler, M., Kunz, G., Malenovský, I., Morris, B.O., Novoselova, M., Pinedo-Escatel, J.A., Rakitov, R.A., Rothschild, M.J., Sanborn, A.F., Takiya, D.M., Wallace, M.S., Zahniser, J.N. templateArgs['editor-last1']="Dmitriev"; templateArgs['editor-first1']="D.A." templateArgs['editor-last2']="Anufriev"; templateArgs['editor-first2']="G.A." templateArgs['editor-last3']="Bartlett"; templateArgs['editor-first3']="C.R." templateArgs['display-editors']="etal"; -- full list is about 28 names else --return "Species File database not recognised" end if db == "hoppers" then data.speciesfile.citationArgs['website'] = "World Auchenorrhyncha Database" else data.speciesfile.citationArgs['website'] = firstToUpper(db) .. data.speciesfile.citationArgs['website'] end return db end

-- Lepindex

data.lepindex = { citationArgs = { website  = "The Global Lepidoptera Names Index", ['editor-last1'] = "Beccaloni", ['editor-first1'] = "George", 	['editor-last2'] = "Scoble",   ['editor-first2'] = "Malcolm", ['editor-last3'] = "Kitching", ['editor-first3'] = "Ian",	    ['editor-last4'] = "Simonsen",  ['editor-first4'] = "Thomas", ['editor-last5'] = "Robinson", ['editor-first5'] = "Gaden", 	['editor-last6'] = "Pitkin",    ['editor-first6'] = "Brian", ['editor-last7'] = "Hine",     ['editor-first7'] = "Adrian",	['editor-last8'] = "Lyal",      ['editor-first8'] = "Chris", publisher = "Natural History Museum", },	customArgs = {exclude="id,1,2,3,4,5", baseURL = "https://www.nhm.ac.uk/our-science/data/lepindex/", suffixStr = "detail/?taxonno=", defaultTitle="Lepindex" } } data.lepindex.id = function(id)   -- https://www.nhm.ac.uk/our-science/data/lepindex/detail/?taxonno=51506

local title = "Lepindex id=" .. id   local url = data.lepindex.customArgs['baseURL'] .. data.lepindex.customArgs['suffixStr'] .. id	return title, url end

-- Global Lepidoptra Index data.gli = { --Beccaloni, G., Scoble, M., Kitching, I., Simonsen, T., Robinson, G., Pitkin, B., Hine, A., Lyal, C., Ollerenshaw, J., Wing, P., & Hobern, D. (2024). Global Lepidoptera Index (D. Hobern, Ed.; 1.1.24.171). citationArgs = { website  = "Global Lepidoptera Index", ['last1'] = "Beccaloni",  ['first1'] = "George", ['last2'] = "Scoble",     ['first2'] = "Malcolm", ['last3'] = "Kitching",   ['first3'] = "Ian", ['last4'] = "Simonsen",   ['first4'] = "Thomas", ['last5'] = "Robinson",   ['first5'] = "Gaden", ['last6'] = "Pitkin",     ['first6'] = "Brian", ['last7'] = "Hine",       ['first7'] = "Adrian", ['last8'] = "Lyal",       ['first8'] = "Chris", ['last9'] = "Ollerenshaw", ['first9'] = "Justin", ['last10'] = "Wing",      ['first10'] = "Peter", ['last11'] = "Hobern",    ['first11'] = "Donald", ['editor-last'] = "Hobern", ['editor-first'] = "Donald", publisher = "Natural History Museum", via = "ChecklistBank", },	customArgs = {exclude="id,1,2,3,4,5", baseURL = "https://www.checklistbank.org/dataset/55434/", suffixStr = "taxon/", defaultTitle="Global Lepidoptera Index", defaultURL = "https://www.checklistbank.org/dataset/55434/about", } } data.gli.id = function(id)   -- https://www.checklistbank.org/dataset/55434/taxon/233256 -- https://www.checklistbank.org/dataset/DATASET_ID/taxon/TAXON_ID -- the dataset ID will change with version so need version handling or just use URL

local title = "GLI id=" .. id   local url = data.gli.customArgs['baseURL'] .. data.gli.customArgs['suffixStr'] .. id	return title, url end data.gli.default2 = function local title = "" local url = "" return title, url end

-- ITIS - Integrated Taxonomic Information System         https://www.itis.gov/servlet/SingleRpt/SingleRpt?search_topic=TSN&search_value=95601

data.itis = { citationArgs = { website  = "Integrated Taxonomic Information System", --publisher = "", },	customArgs = {exclude="id,1,2,3,4,5", baseURL = "https://www.itis.gov/", searchStr = "servlet/SingleRpt/SingleRpt?search_topic=TSN&search_value=", defaultTitle="Integrated Taxonomic Information System" } } data.itis.id = function(id)

local title = "ITIS id=" .. id   local url = data.itis.customArgs['baseURL'] .. data.itis.customArgs['searchStr'] .. id	return title, url end

-- Catalogue of Life:		Roskov Y., Ower G., Orrell T., Nicolson D., Bailly N., Kirk P.M., Bourgoin T., DeWalt R.E., Decock W., van Nieukerken E.J., Penev L. (eds.) (2020). 		Species 2000 & ITIS Catalogue of Life, 2020-12-01. 		Digital resource at www.catalogueoflife.org. Species 2000: Naturalis, Leiden, the Netherlands. ISSN 2405-8858.		Species 2000 & ITIS Catalogue of Life, 2020-12-01. Digital resource at www.catalogueoflife.org. 		Species 2000: Naturalis, Leiden, the Netherlands. ISSN 2405-8858. data.col = { db      = "col",  -- need rethink this citationArgs = { --author = "Catalogue of Life", --['editor-last1'] = "Roskov",  ['editor-first1'] = "Y.", ['editor-last2'] = "Ower",     ['editor-first2'] = "G.", 	    ['editor-last3'] = "Orrell",   ['editor-first3'] = "T.", ['editor-last4'] = "Nicolson", ['editor-first4'] = "D.", 	    ['editor-last5'] = "Bailly",   ['editor-first5'] = "N.", ['editor-last6'] = "Kirk",     ['editor-first6'] = "P.M.", 	    ['editor-last7'] = "Bourgoin", ['editor-first7'] = "T.", ['editor-last8'] = "DeWalt",   ['editor-first8'] = "R.E.", 	    ['editor-last9'] = "Decock",   ['editor-first9'] = "W.", ['editor-last10'] = "van Nieukerken", ['editor-first10'] = "E.J.", 	    ['editor-last11'] = "Penev", ['editor-first11'] = "L.", --website  = "Catalogue of Life", --website  = "Species 2000 & ITIS Catalogue of Life", -- website  = "Species 2000 & ITIS Catalogue of Life", website  = "Catalogue of Life", publisher = "Species 2000: Leiden, the Netherlands", --others   = "Species 2000 & ITIS"

},	customArgs = {exclude="id,db,1,2,3,4,5,legacy,option", baseURL = "https://www.catalogueoflife.org/data/", searchStr = "browse?taxonKey=", defaultTitle="Catalogue of Life" } } data.col.id = function(id) -- Catalogue of Life       browse option:	https://www.catalogueoflife.org/data/browse?taxonKey=4JQ8            use id for taxoKey        taxon option    https://www.catalogueoflife.org/data/taxon/6HR5M local title = "Catalogue of Life taxonKey " .. id   local url = data.col.customArgs['baseURL'] -- some new CoL are numbers e.g. 64553 in https://www.catalogueoflife.org/data/taxon/64553 if not tonumber(id) and string.find( id,  "^[0-9abcdef]+$" ) then                                            -- if old-style id		local year = "2019"        -- last old-style version available if templateArgs['version'] and string.find( templateArgs['version'], "^%d%d%d%d$" ) then --if version specied year = templateArgs['version'] end if templateArgs['option'] == "browse" then url = "http://www.catalogueoflife.org/annual-checklist/" .. year .. "/browse/tree/id/" .. id		else -- default to option=taxon url = "http://www.catalogueoflife.org/annual-checklist/" .. year .. "/details/species/id/" .. id		end else                                                                                 -- else use current version if templateArgs['option'] == "browse" then url = url .. "browse?taxonKey=" .. id		else -- default to option=taxon url = url .. "taxon/" .. id		end end

return title, url end -- current links				 https://www.catalogueoflife.org/data/search?q=" Chinchilla+chinchilla&type=EXACT	legacy links with redirect	   Species pages:    http://www.catalogueoflife.org/col/details/species/id/12dca9c49741815f82400bb7bff50553	    Species searches: http://www.catalogueoflife.org/col/search/all/key/Dracula+antonii/    old-style links                		  http://www.catalogueoflife.org/col/details/species/id/7539827da517bd6273a4a3836578cb24            		      http://www.catalogueoflife.org/col/search/scientific/genus/Chinchilla/species/chinchilla/match/1/                		  http://www.catalogueoflife.org/col/browse/tree/id/003e480e646d0e7647ab67efc1218197	year specific links        2019              http://www.catalogueoflife.org/annual-checklist/2019/details/species/id/7539827da517bd6273a4a3836578cb24                          http://www.catalogueoflife.org/annual-checklist/2019/search/all/key/Chinchilla+chinchilla/fossil/1/match/1                           http://www.catalogueoflife.org/annual-checklist/2019/search/scientific/genus/Chinchilla/species/chinchilla/match/1/                     ?    http://www.catalogueoflife.org/annual-checklist/2016/browse/tree?6d600f4985f19b1207d41d847424edd0                      ?    http://www.catalogueoflife.org/col/browse/tree/id/003e480e646d0e7647ab67efc1218197        browse            http://www.catalogueoflife.org/annual-checklist/2019/browse/tree/id/003e480e646d0e7647ab67efc1218197 data.col.default = function(mode) -- this handles the old style template with positional parameters (mode unused?) local para1 = templateArgs[2] local para2 = templateArgs[3] local para3 = templateArgs[4] local para4 = templateArgs[5] if para1 then para1 = mw.text.trim(para1) end if para2 then para2 = mw.text.trim(para2) end if para3 then para3 = mw.text.trim(para3) end if para4 then para4 = mw.text.trim(para4) end local title, url if para1 then --local match = "7539827da517bd6273a4a3836578cb24" local match = "^[0-9abcdef]+$" if string.find( para1, match ) then url = "http://www.catalogueoflife.org/col/details/species/id/" .. para1 -- ""Old style id"			--url ="https://www.catalogueoflife.org/data/search?q=" .. para1			if para2 then				title = para2			else				title = "Oldstyle id: " .. para1			end		else

--https://www.catalogueoflife.org/data/search?q=" Chinchilla+chinchilla&type=EXACT			if para1 ~= "" then				url = "https://www.catalogueoflife.org/data/search?q=" .. para1 				title = "" .. para1 				if para2 then					url = url .. "+" .. para2 					title = title .. " " .. para2				end				url = url .. "&type=EXACT"				title = title .. ""			end		end			if para3 then title = title .. " " .. para3 end   -- add authority		if para4 == "nv" then templateArgs['trans-title'] = "synonym" end   -- if nv add [synonym]. Note that this parameter is not used to add COinS metadata 	else		-- no parameter 1	end	return title, url    end

--====================== Fossilworks =======================================

data.fossilworks = { citationArgs = { website="Fossilworks", agency="Gateway to the Paleobiology Database", --publisher="Paleobiology Database", --postscript = 'none', -- postscript = "&#32;from the Paleobiology Database.", -- gives maintenance warning --via="fossilworks.org"  -- an alternative format to using |website= },	customArgs = { exclude = "id,collection,date,1", baseURL = "http://www.fossilworks.org/cgi-bin/", searchStr ="bridge.pl?a=taxonInfo&taxon_no=", defaultTitle = "Fossilworks: Gateway to the Paleobiology Database" }	--id = function(id) return p.genericIdCitation (frame, title, url) } data.fossilworks.id = function(id) -- http://fossilworks.org/cgi-bin/bridge.pl?a=taxonInfo&taxon_no=83087	   if not templateArgs['id'] then return "no id parameter detected" end    local searchStr = "bridge.pl?a=taxonInfo&taxon_no=" .. templateArgs['id']    templateArgs['url']= target.CustomArgs['baseURL'] .. searchStr local title = "PaleoDB taxon number: " .. id   local url = data.fossilworks.customArgs['baseURL'] .. data.fossilworks.customArgs['searchStr'] .. id   return title, url end data.fossilworks.collection = function(collection) -- http://fossilworks.org/bridge.pl?a=collectionSearch&collection_no=20072 local title = "PaleoDB collection number: " .. collection local url = data.fossilworks.customArgs['baseURL'] .. "bridge.pl?a=collectionSearch&collection_no=" .. collection return title, url end data.fossilworks.error = function return "Requires id and title parameters" end

--====================== Paleobiology Database: paleobiodb.org =======================================

data.paleobiodb = { citationArgs = { website="Paleobiology Database" },	customArgs = { exclude = "id,collection,date,1", baseURL = "https://paleobiodb.org/classic/", searchStr ="basicTaxonInfo?taxon_no=", defaultTitle = "Paleobiology Database" }	--id = function(id) return p.genericIdCitation (frame, title, url) } data.paleobiodb.id = function(id) -- https://paleobiodb.org/classic/basicTaxonInfo?taxon_no=22786	   if not templateArgs['id'] then return "no id parameter detected" end local title = "PaleoDB taxon number: " .. id   local url = data.paleobiodb.customArgs['baseURL'] .. data.paleobiodb.customArgs['searchStr'] .. id   return title, url end data.paleobiodb.collection = function(collection) -- https://paleobiodb.org/classic/basicCollectionSearch?collection_no=24193 local title = "PaleoDB collection number: " .. collection local url = data.paleobiodb.customArgs['baseURL'] .. "basicCollectionSearch?collection_no=" .. collection return title, url end data.paleobiodb.error = function return "Requires id and title parameters" end --======================================= PLANTS ========================= -- Plant authorities can end in a period. This is stripped by the citation templates.     This function encloses titles ending in such authorities in double parentheses, i.e. ((title)) local addAuthority = function(formattedTaxonName) if templateArgs['authority'] then local title = formattedTaxonName .. " " .. templateArgs['authority'] return string.gsub( title, "(.*%.)$", "((%1))") -- if authority ends in "." enclose ((title)) to prevent removal end return formattedTaxonName end

--[[ Hassler, Michael (2004 - 2020): World Plants. Synonymic Checklist and Distribution of the World Flora.       Version x.xx; last update xx.xx.xxxx. - www.worldplants.de. Last accessed dd/mm/yyyy.       https://www.worldplants.de/world-plants-complete-list/complete-plant-list#1599996425     Hassler, Michael (2004 - 2020): World Ferns. Synonymic Checklist and Distribution of Ferns and Lycophytes of the World.        Version x.xx; last update xx.xx.xxxx. - www.worldplants.de/ferns/. Last accessed dd/mm/yyyy.       https://www.worldplants.de/world-ferns/ferns-and-lycophytes-list#1599997555

deeplinks: Genus: Helosciadium Species: Helosciadium longipedunculatum Genus: [https://www.worldplants.de?deeplink=Lycopodium-L. Lycopodium] Species: Lycopodium clavatum

--]] data.worldplants = { citationArgs = { last1 = "Hassler", first1 = "Michael", website="World Plants. Synonymic Checklist and Distribution of the World Flora.", --publisher="" },	customArgs = { exclude = "id,authority,family,genus,species,1", baseURL = "https://www.worldplants.de", searchStr ="/world-plants-complete-list/complete-plant-list#", defaultSuffix = "", defaultTitle = "World Plants" } } data.worldplants.genus = function(genus) local title = addAuthority("" .. genus .. "") local genusString = genus if templateArgs['authority'] then genusString = genus .. "-" .. templateArgs['authority'] end local url = data.worldplants.customArgs['baseURL'] .. "?deeplink=" .. genusString return title, url end data.worldplants.species = function(genus, species) local title = addAuthority("" .. genus .. " " .. species .. "") local url = data.worldplants.customArgs['baseURL'] .. "?deeplink=" .. genus .. "-" .. species .. " " .. (templateArgs['authority'] or "") return title, url end --[[ experimental, don't leave live

data.worldplants.taxon = function(taxon) local title = taxon .. " " .. (templateArgs['authority'] or "") local url = data.worldplants.customArgs['baseURL'] .. "?deeplink=" .. taxon return title, url end

data.worldplants.family = function(family) local title = family .. " " .. (templateArgs['authority'] or "") local url = data.worldplants.customArgs['baseURL'] .. "?deeplink=" .. family return title, url end --]] data.worldferns = { citationArgs = { last1 = "Hassler", first1 = "Michael", website="World Ferns. Synonymic Checklist and Distribution of the World Flora.", --publisher="" },	customArgs = { exclude = "id,authority,family,genus,species,1", baseURL = "https://www.worldplants.de/", searchStr ="world-ferns/ferns-and-lycophytes-list?name=", defaultSuffix = "", defaultTitle = "World Ferns" } } data.worldferns.genus = function(genus) local title = addAuthority("" .. genus .. "") local genusString = genus if templateArgs['authority'] then genusString = genus .. "-" .. templateArgs['authority'] end local url = data.worldferns.customArgs['baseURL'] .. data.worldferns.customArgs['searchStr'] .. genusString return title, url end data.worldferns.species = function(genus, species) local title = addAuthority("" .. genus .. " " .. species .. "") local url = data.worldferns.customArgs['baseURL'] .. data.worldferns.customArgs['searchStr'] .. genus .. "-" .. species .. " " .. (templateArgs['authority'] or "") return title, url end

--Plants of the World online	  http://powo.science.kew.org/taxon/urn:lsid:ipni.org:names:30003057-2  -- use id	   http://powo.science.kew.org/?q=Selaginellaceae                        -- use search	   http://powo.science.kew.org/?family=Selaginellaceae                   -- can also use family= [gets same result as q=]	   http://powo.science.kew.org/?genus=Selago                             -- or genus	   http://powo.science.kew.org/?genus=Selago&species=abietina            -- or genus + species	   http://powo.science.kew.org/?genus=Selago&f=accepted_names            -- filter for accepted names	   http://powo.science.kew.org/?genus=Selago&f=genus_f                   -- filter for genus (no species selected)	   http://powo.science.kew.org/?genus=Selago&f=genus_f%2Caccepted_names  -- filter for genus and accepted names	   http://powo.science.kew.org/?page.size=480&f=family_f%2Caccepted_names -- list of accepted families	   -- all these searches get the search result (no apparent way to target the article when unique) data.POWO = { citationArgs = { website="Plants of the World Online", publisher="Royal Botanic Gardens, Kew", --postscript = 'none', },	customArgs = { exclude = "id,authority,family,genus,species,1", baseURL = "http://powo.science.kew.org/taxon/", searchStr ="urn:lsid:ipni.org:names:", defaultSuffix = "", defaultTitle = "Plants of the World Online" }	--id = function(id) return p.genericIdCitation (frame, title, url) } -- http://powo.science.kew.org/taxon/urn:lsid:ipni.org:names:30003057-2 data.POWO.id = function(id) local id = data.POWO.getValidID if not id then return data.POWO.error end local title = id                                                                         -- as default value local url = data.POWO.customArgs['baseURL'] .. data.POWO.customArgs['searchStr'] .. id   return title, url end data.POWO.family = function(family) local title = addAuthority(family) local id = templateArgs['id'] if not id then return data.POWO.error end local url = data.POWO.customArgs['baseURL'] .. data.POWO.customArgs['searchStr'] .. id   return title, url end data.POWO.genus = function(genus) local title = addAuthority("" .. genus .. "") local id = data.POWO.getValidID if not id then return data.POWO.error end local url = data.POWO.customArgs['baseURL'] .. data.POWO.customArgs['searchStr'] .. id   return title, url end data.POWO.species = function(genus,species) local title = addAuthority("" .. genus .. " " .. species .. "") local id = data.POWO.getValidID if not id then return data.POWO.error end local url = data.POWO.customArgs['baseURL'] .. data.POWO.customArgs['searchStr'] ..id   return title, url end data.POWO.getValidID = function local id = templateArgs['id'] if id then return string.gsub( id, "urn:lsid:ipni.org:names:", "") -- don't want this twice end return nil end data.POWO.error = function return ' Requires id and one of title, family, genus or species parameters ' end

--Gouda, E.J., Butcher, D. & Gouda, C.S. (cont.updated) Encyclopaedia of Bromeliads, Version 4. http://bromeliad.nl/encyclopedia/ Utrecht University Botanic Gardens

data.bromeliad = { citationArgs = { last1="Gouda", first1="E.J.", last2="Butcher", first2="D.", last3="Gouda", first3="C.S", website="Encyclopaedia of Bromeliads", version="Version 4", publisher="Utrecht University Botanic Gardens", --postscript = 'none', },	customArgs = { exclude = "id,authority,family,genus,species,list,1", baseURL = "https://bromeliad.nl/", searchStr ="encyclopedia/index.php?find=", defaultSuffix = "", defaultTitle = "Encyclopaedia of Bromeliads, Version 4" }	--id = function(id) return p.genericIdCitation (frame, title, url) } -- https://bromeliad.nl/encyclopedia/index.php?find=Hylaeaicum data.bromeliad.search = function(search)

local title = search                                                                         -- as default value local url = data.bromeliad.customArgs['baseURL'] .. data.bromeliad.customArgs['searchStr'] .. search return title, url end -- http://bromeliad.nl/species/Bromeliaceae data.bromeliad.taxon = function(taxon)

local title = addAuthority(taxon)                                                                         -- as default value local url = data.bromeliad.customArgs['baseURL'] .. "species/" .. taxon return title, url end -- genus data.bromeliad.genus = function(genus)

local title = addAuthority("" .. genus .. "")                                                                         -- as default value local url = data.bromeliad.customArgs['baseURL'] .. "species/" .. genus if templateArgs['list'] == "species" then url = data.bromeliad.customArgs['baseURL'] .. "encyclopedia/brome.php?action=showSpeciesIndex&name=" .. genus .. "&flags=" end return title, url end -- 	 data.bromeliad.species = function(genus, species)

local title = addAuthority("" .. genus .. " " .. species .. "")                                                                         -- as default value local url = data.bromeliad.customArgs['baseURL'] .. "species/" .. genus .. "/" .. species return title, url end

-- https://bromeliad.nl/encyclopedia/brome.php?action=showTaxon&id=10093 data.bromeliad.id = function(id)

local title = id                                                                         -- as default value local url = data.bromeliad.customArgs['baseURL'] .. "encyclopedia/brome.php?action=showTaxon&id=" .. id   return title, url end

--GRIN 	Cite as: USDA, Agricultural Research Service, National Plant Germplasm System. 2021. Germplasm Resources Information Network (GRIN Taxonomy). National Germplasm Resources Laboratory, Beltsville, Maryland.	URL: https://npgsweb.ars-grin.gov/gringlobal/taxon/taxonomyfamily?type=tribe&id=1571. Accessed 27 October 2021. 	Family record: https://npgsweb.ars-grin.gov/gringlobal/taxon/taxonomyfamily?id=440	  Genus list: https://npgsweb.ars-grin.gov/gringlobal/taxon/taxonomygenuslist?id=440&type=family	Subfamily record: https://npgsweb.ars-grin.gov/gringlobal/taxon/taxonomyfamily?type=subfamily&id=1507	   Genus list: https://npgsweb.ars-grin.gov/gringlobal/taxon/taxonomygenuslist?id=3265&type=subfamily	Tribe record: https://npgsweb.ars-grin.gov/gringlobal/taxon/taxonomyfamily?type=tribe&id=1551 (Millettieae)	   Genus list: https://npgsweb.ars-grin.gov/gringlobal/taxon/taxonomygenuslist?id=1551&type=tribe	Subtribe record: https://npgsweb.ars-grin.gov/gringlobal/taxon/taxonomyfamily?type=subtribe&id=1507	   Genus list: https://npgsweb.ars-grin.gov/gringlobal/taxon/taxonomygenuslist?id=1507&type=subtribe	Genus record: https://npgsweb.ars-grin.gov/gringlobal/taxon/taxonomygenus?id=191 (Genus Adenodolichos Harms)	  Species list: https://npgsweb.ars-grin.gov/gringlobal/taxon/taxonomyspecieslist?id=191&type=genus	Species record: https://npgsweb.ars-grin.gov/gringlobal/taxon/taxonomydetail?id=489203 ( Adenodolichos paniculatus) data.GRIN = { citationArgs = { website="Germplasm Resources Information Network (GRIN)", publisher="Agricultural Research Service (ARS), United States Department of Agriculture (USDA)", --postscript = 'none', },	customArgs = { exclude = "id,authority,family,genus,species,1", baseURL = "https://npgsweb.ars-grin.gov/gringlobal", searchStr ="/taxon/taxonomydetail?",                            -- for species record defaultSuffix = "", defaultTitle = "GRIN-Global" }	--id = function(id) return p.genericIdCitation (frame, title, url) } data.GRIN.id = function(id) local title = data.GRIN.customArgs['defaultTitle'] .. ' ' .. id   local url = data.GRIN.customArgs['baseURL'] .. data.GRIN.customArgs['searchStr'] .. id   return title, url end

-- IPNI --→ "Meconopsis Vig." International Plant Names Index (IPNI). Royal Botanic Gardens, Kew. --- 	https://www.ipni.org/n/30149252-2 --- as

data.IPNI = { citationArgs = { website="International Plant Names Index (IPNI)", publisher="Royal Botanic Gardens, Kew", --postscript = 'none', },	customArgs = { exclude = "id,authority,family,genus,species,1", baseURL = "https://www.ipni.org", searchStr ="/n/", defaultSuffix = "", defaultTitle = "IPNI" }	--id = function(id) return p.genericIdCitation (frame, title, url) } data.IPNI.id = function(id) local title = id   local url = data.IPNI.customArgs['baseURL'] .. data.IPNI.customArgs['searchStr'] .. id   return title, url end data.IPNI.species = function(genus, species)  return data.IPNI.taxon(genus .. " " .. species, "TITLE_ITALICS") end data.IPNI.genus = function(genus)  return data.IPNI.taxon(genus, "TITLE_ITALICS") end data.IPNI.taxon = function(taxon, italics) local title = taxon if italics then title = "''" .. title .. "''" end title = addAuthority(title) --	if templateArgs['authority'] then		title = title .. " " .. templateArgs['authority']		title = string.gsub( title, "(.*%.)$", "((%1))") -- if authority ends in "." enclose ((title)) to prevent removal	end local url = data.IPNI.customArgs['baseURL'] .. data.IPNI.customArgs['searchStr'] .. templateArgs['id'] return title, url end

--World Flora Online    	http://www.worldfloraonline.org/taxon/wfo-4000012284  -- id

data.WFO = { citationArgs = { website="World Flora Online", --publisher="Missouri Botanical Gardens", --postscript = 'none', },	customArgs = { exclude = "id,family,genus,species,authority,1", baseURL = "http://www.worldfloraonline.org", searchStr ="/taxon/wfo-",                                      -- not strictly search string defaultSuffix = "", --defaultTitle = "World Flora Online" defaultTitle = "An Online Flora of All Known Plants" }

} data.WFO.id = function(id) -- http://www.worldfloraonline.org/taxon/wfo-4000012284 local title = id   local url = data.WFO.customArgs['baseURL'] .. data.WFO.customArgs['searchStr'] .. id   return title, url end data.WFO.family = function(family) local title = addAuthority(family) local url = data.WFO.customArgs['baseURL'] .. data.WFO.customArgs['searchStr'] .. templateArgs['id'] return title, url end data.WFO.genus = function(genus) local title = addAuthority("" .. genus .. "") local url = data.WFO.customArgs['baseURL'] .. data.WFO.customArgs['searchStr'] .. templateArgs['id'] return title, url end data.WFO.species = function(genus,species) local title = addAuthority("" .. genus .. " " .. species .. "") local url = data.WFO.customArgs['baseURL'] .. data.WFO.customArgs['searchStr'] .. templateArgs['id'] return title, url end data.WFO.error = function return "Requires id and title parameters" end

data.Tropicos = { citationArgs = { website="Tropicos", --publisher="Missouri Botanical Gardens", --postscript = 'none', },	customArgs = { exclude = "id,1", baseURL = "http://legacy.tropicos.org/Name/", searchStr ="", defaultSuffix = "", defaultTitle = "Tropicos" }

} data.Tropicos.id = function(id) -- hhttp://legacy.tropicos.org/Name/100444532 local title = id   local url = data.Tropicos.customArgs['baseURL'] .. data.Tropicos.customArgs['searchStr'] .. id   return title, url end data.Tropicos.error = function return "Requires id and title parameters" end

data.FNA = { citationArgs = { website="Flora of North America", --publisher="http://www.efloras.org", --postscript = 'none', },	customArgs = { exclude = "id,1", baseURL = "http://www.efloras.org/florataxon.aspx", searchStr ="?flora_id=1&taxon_id=", defaultSuffix = "", defaultTitle = "Flora of North America" }	--id = function(id) return p.genericIdCitation (frame, title, url) } data.FNA.id = function(id) -- http://www.efloras.org/florataxon.aspx?flora_id=1&taxon_id=125683 local title = id   local url = data.FNA.customArgs['baseURL'] .. data.FNA.customArgs['searchStr'] .. id   return title, url end data.FNA.error = function return "Requires id and title parameters" end -- ATRP: Australian Tropical Rainforest Plants

data.ATRP = { citationArgs = { website="Australian Tropical Rainforest Plants", publisher="Commonwealth Scientific and Industrial Research Organisation (CSIRO)", version = "Edition 8", year = 2020, --postscript = 'none', last1= "Zich", first1="F. A.", last2= "Hyland", first2= "B. P. M.", ['author2-link']="Bernard Hyland", last3= "Whiffin", first3= "T.", last4= "Kerrigan", first4= "R.A.", --['display-authors']=3, },	customArgs = { exclude = "genus, species,authority, id,1", baseURL = "https://apps.lucidcentral.org/rainforest", searchStr ="/text/entities/", defaultSuffix = ".htm", defaultTitle = "Australian Tropical Rainforest Plants" }	--id = function(id) return p.genericIdCitation (frame, title, url) } data.ATRP.species = function(genus,species) -- https://apps.lucidcentral.org/rainforest/text/entities/buckinghamia_celsissima.htm local title = addAuthority("" .. genus .. " " .. species .. "") --"''" .. genus .. " " .. species .. "''"   local url = data.ATRP.customArgs['baseURL'] .. data.ATRP.customArgs['searchStr'] .. genus .. "_" .. species .. data.ATRP.customArgs['defaultSuffix'] return title, url end data.ATRP.error = function return "Requires genus and species parameters" end

-- ============================= Mosses (Goffinet's site) =================================================-- for species in taxon; for species assessments, us -- https://bryology.uconn.edu/classification/#Hypnanae -- https://bryology.uconn.edu/classification/#Bryales data.goffinet = { citationArgs = { first1="B.", last1="Goffinet", first2="W.R.", last2="Buck", website="Classification of extant moss genera" --publisher="xxx" },	customArgs = { exclude="family,genus,species,taxon,id,1", baseURL = "https://bryology.uconn.edu/classification/", searchString = "#", searchSuffix = "", defaultSuffix = "", defaultTitle="Classification of the Bryophyta" }	} data.goffinet.genus = function(genus)  return data.goffinet.taxon(genus, "GENUS") end data.goffinet.family = function(family) return data.goffinet.taxon(family, "FAMILY") end data.goffinet.order = function(order)  return data.goffinet.taxon(order, "ORDER") end data.goffinet.taxon = function(taxon, rank) local title = firstToUpper(taxon) if rank == "GENUS" then title = "''" .. title .. "''" end if not (rank == "GENUS" or rank == "FAMILY") then -- upper case anchors for orders and above if taxon ~= "Bryanae" and taxon ~= "Hypnanae" and taxon ~= "Bryales" and taxon ~= "Bryidae" then -- check for exceptions (inconsistencies at website) taxon = taxon:upper end end local url = data.goffinet.customArgs['baseURL'] .. data.goffinet.customArgs['searchString'] .. taxon .. data.goffinet.customArgs['searchSuffix'] return title, url end

-- AlgaeBase   (old) taxonomy browser url (Volvox) = https://www.algaebase.org/browse/taxonomy/?id=6898    taxonomy browser url (Volvox) = https://www.algaebase.org/browse/taxonomy/? data.AlgaeBase = { citationArgs = { website="AlgaeBase", ['editor1-last']="Guiry", ['editor1-first']="M.D.", ['editor2-last']="Guiry", ['editor2-first']="G.M.", publisher="National University of Ireland, Galway", },	customArgs = { exclude = "id,1,genus_id,species_id,spid,genid", baseURL = "https://www.algaebase.org/", --searchStr ="browse/taxonomy/?id=", (old) searchStr ="browse/taxonomy/?#", defaultSuffix = "", defaultTitle = "AlgaeBase" } } data.AlgaeBase.id = function(id) -- https://www.algaebase.org/browse/taxonomy/?id=6898 (id for taxonomy page) local title = id   local url = data.AlgaeBase.customArgs['baseURL'] .. data.AlgaeBase.customArgs['searchStr'] .. id   return title, url end data.AlgaeBase.genid = function(genid) -- https://www.algaebase.org/search/genus/detail/?genus_id=43497 (different id for genus page) local title = genid local url = data.AlgaeBase.customArgs['baseURL'] .. "search/genus/detail/?genus_id=" .. genid return title, url end data.AlgaeBase.spid = function(spid) -- https://www.algaebase.org/search/species/detail/?species_id=52713 (id for species page) local title = spid local url = data.AlgaeBase.customArgs['baseURL'] .. "search/species/detail/?species_id=" .. spid return title, url end data.AlgaeBase.error = function return "Requires id and title parameters" end

--================= Viruses ========= data.ictv = { citationArgs = { website="ictv.global", --['editor1-last']="xx", ['editor1-first']="xx", --['editor2-last']="xx", ['editor2-first']="xx", author="International Committee on Taxonomy of Viruses (ICTV)", },	customArgs = { exclude = "id,1", baseURL = "https://ictv.global/taxonomy/", searchStr ="taxondetails?taxnode_id=", defaultSuffix = "", defaultTitle = "Taxonomy Browser" } } data.ictv.id = function(id) -- https://ictv.global/taxonomy/taxondetails?taxnode_id=202308917&taxon_name=Campanilevirus%20YC         (for species Campanilevirus YC)     https://ictv.global/taxonomy/taxondetails?taxnode_id=202308917 (also works with just the id) local title = id   local url = data.ictv.customArgs['baseURL'] .. data.ictv.customArgs['searchStr'] .. id   return title, url end

data.ictv.error = function return "Requires id and title parameters" end --############################## General Functions ########################################

local function getArgs (frame, args) local parents = mw.getCurrentFrame:getParent for k,v in pairs(parents.args) do		--check content if v and v ~= "" then args[k]=v --parents.args[k] end end for k,v in pairs(frame.args) do		--check content if v and v ~= "" then args[k]=v end end end local function initialise(frame, sourceDB) target=sourceDB templateArgs = sourceDB.citationArgs -- get custom arguments for target (fishbase, cof etc	getArgs(frame, templateArgs) -- get template arguments from parent frame and frane	local url = (target.customArgs['baseURL'] or "") .. (target.customArgs['defaultSuffix'] or "")	local title = target.customArgs['defaultTitle'] or ""	return title, url end -- moved up top for scope local function firstToUpper2(str)   return (str:gsub("^%l", string.upper)) end -- clear template arguments that won't be recognised by local function clearCustomArgs	local excludeTable = { 'genus', 'species', 'subspecies', 'family', 'order', 'taxon', 		                   'id', 'search', 'citation', 1, 2, 3, 4 }                          -- add defaults ?	if target.customArgs['exclude'] then		local customTable = mw.text.split (target.customArgs['exclude'] , "%s*,%s*");			for k,v in pairs(customTable) do	    	table.insert (excludeTable, v ) end end for k,v in pairs(excludeTable) do	   	if tonumber (v) then v = tonumber (v) --convert positional parameters (numbers as string) to a number end templateArgs[v]=nil --clear content end end

-- function handling the cite web template p.citeWeb = function(frame, title, url) -- set url and title if not provided (template parameters override above) if not templateArgs['url'] and url then templateArgs['url']= url end if not templateArgs['title'] and title then templateArgs['title'] = title end

clearCustomArgs--blank template parameters not for cite web local citeTemplate = 'cite web'         -- use Template:Cite web unless specified --if target.citeTemplate then citeTemplate = target.citeTemplate end return frame:expandTemplate{ title = citeTemplate, args = templateArgs }

end -- p.CiteBook -- for reasons of consisitency within BioRef/FishRef the title parameter is the section-title of p.citeBook = function(frame, title, url, chapterParams) -- very much a msw3 function --if (1==1) then return templateArgs['title'] end -- set url and title if not provided (template parameters override above) if not templateArgs['url'] and url then templateArgs['url']= url if target.GoogleBooks then templateArgs['url'] = target.GoogleBooks['baseURL'] .. target.GoogleBooks['id'] .. (target.GoogleBooks['defaultPage'] or "&pg=PP1") end end if not templateArgs['title'] and title then --   	templateArgs['title'] = title end if templateArgs['title'] ~= title or templateArgs['taxon-title'] then -- do we have a section title provided templateArgs['section'] = templateArgs['title'] -- chapter/section title passed as title parameter templateArgs['title']  = title -- the work is the book title given in the source data if target.GoogleBooks then templateArgs['section-url'] = target.GoogleBooks['baseURL'] .. target.GoogleBooks['id'] local pageSuffix = target.GoogleBooks['defaultPage'] or "" if templateArgs['page'] or templateArgs['gb-page'] then pageSuffix = "&pg=PT" .. (templateArgs['gb-page'] or templateArgs['page'] ) end local searchStr = "" -- quoted search if templateArgs['q'] then searchStr = "&q=" .. mw.text.encode( templateArgs['q'] ) end -- search #if:|&q=}} if templateArgs['dq'] then searchStr = "&dq=" .. mw.text.encode( templateArgs['dq'] ) end templateArgs['section-url'] = templateArgs['section-url'] .. pageSuffix .. searchStr templateArgs['url'] = nil  -- no need for second link to google books end

-- if the chapter/section is linked, we can link the main book chapter differently if target.customArgs['altTitle'] then -- if we are using a chapter/section, we can wikilink the book title templateArgs['title'] = target.customArgs['altTitle'] -- alternative to allow wikilink elseif target.customArgs['altURL'] then templateArgs['url'] = target.customArgs['altURL'] end

end -- end if using supplied title for chapter/section

clearCustomArgs--blank template parameters not for cite web local citeTemplate = 'cite book'         -- use Template:Cite web unless specified --if target.citeTemplate then citeTemplate = target.citeTemplate end return frame:expandTemplate{ title = citeTemplate, args = templateArgs }

end

-- common function for genus and species local function getGenusSpecies --TODO standardise genus species handling local genus, species, subspecies if (templateArgs['genus'] or templateArgs[2] ) then genus = templateArgs['genus'] or templateArgs[2] genus = firstToUpper(mw.text.trim(genus)) end if (templateArgs['species'] or templateArgs[3] ) then species = templateArgs['species'] or templateArgs[3] species = 	mw.text.trim(species) end if (templateArgs['subspecies'] or templateArgs[4] ) then subspecies = templateArgs['subspecies'] or templateArgs[4] subspecies = 	mw.text.trim(subspecies) end return genus, species, subspecies end

--#################### MSW3  -- uses cite book p.MSW3 = function(frame) local msw = require('Module:FishRef/MSW') initialise(frame, msw.MSW3) return msw.MSW3.main(frame,templateArgs) end p.MSW3merged = function(frame) local data = require('Module:FishRef/MSW') return p._main(frame, data.MSW3) end p.MSW3_standalone = function(frame) local data = require('Module:FishRef/MSW') initialise(frame, data.MSW3) local url = target.CustomArgs['baseURL'] if templateArgs['title'] and templateArgs['id'] then templateArgs['chapter-url']= url .. target.CustomArgs['searchStr'] .. templateArgs['id'] templateArgs['chapter'] = templateArgs['title'] templateArgs['title'] = target.CustomArgs['bookTitle'] if templateArgs['page'] then templateArgs['url'] = target.CustomArgs['googleBooksURL'] .. templateArgs['page'] else --return "Page number for google books required" end elseif templateArgs['order'] then templateArgs['chapter'] = "Order " .. templateArgs['order'] local chapter = target.chapters[templateArgs['order']] for k,v in pairs(chapter) do  -- add chapter specific parameters templateArgs[k] = v    	end templateArgs['chapter-url']= url .. target.CustomArgs['searchStr'] .. templateArgs['id'] templateArgs['url']= target.CustomArgs['googleBooksURL'] .. templateArgs['page'] if templateArgs['pages'] and templateArgs['page'] then templateArgs['page'] = nil end else -- default output templateArgs['url']= target.CustomArgs['googleBooksURL'] .. "1" -- default to book templateArgs['url']= url end -- using cite book clearCustomArgs--blank template parameters not for cite web return frame:expandTemplate{ title = 'cite book', args = templateArgs } end

--########################### Functions for access (using invoke) ##############################################

--================ Fishbase, Catalog of Fishes (cof) ================ p.fishbase   = function(frame) return p._main(frame, data.fishbase) end p.cof        = function(frame) return p._main(frame, data.cof) end p.fotw5      = function(frame) return p._main(frame, data.fotw5) end --=================== ASW6, AmphibiaWeb, ReptileDB p.reptileDB  = function(frame) return p._main(frame, data.reptileDB) end p.ASW6       = function(frame) return p._main(frame, data.ASW6) end p.amphibiaweb = function(frame) return p._main(frame, data.amphibiaweb) end --=========== Birds p.HBWa       = function(frame) return p._main(frame, data.HBWalive) end p.HBWalive   = function(frame) return p._main(frame, data.HBWalive)  end p.IOC        = function(frame) return p._main(frame, data.IOC) end p.BOW        = function(frame) return p._main(frame, data.BOW) end --======= Mammals p.asm        = function(frame) return p._main(frame, data.asm) end --======= Plants p.WFO        = function(frame) return p._main(frame, data.WFO) end p.POWO       = function(frame) return p._main(frame, data.POWO) end -- MSW3 has custom handling (see above) --=========== Other p.fossilworks = function(frame) return p._main(frame, data.fossilworks) end p.worms      = function(frame) return p._main(frame, data.WoRMS) end p.WoRMS      = function(frame) return p._main(frame, data.WoRMS) end p.col        = function(frame) return p._main(frame, data.col) end --fallback = function return "hello" end --######################################################### p.main = function(frame) local source = mw.text.trim(frame.args[1]) --TODO force to lower case and use lower case for all functions above if source == "MSW3" then return p.MSW3(frame) end if source == "ref" or source == "reference" then source = "Reference" end  -- aliases if source == "Reference" then return p.Reference(frame) end if source == "HBWa" then source = "HBWalive" end  -- aliases if source == "powo" then source = "POWO" end  -- aliases if source == "wfo" then source = "WFO" end  -- aliases if source == "mdd" then source = "asm" end  -- aliases --return p[source]['test'] if source == "fishbase"             -- unnecessary? or source == "cof" or source == "fotw5" or source == "Fotw5" or source == "reptileDB" or source == "amphibiaweb" or source == "BOW" or source == "ASW6" or source == "asm" or source == "HBWalive" or source == "HBWa" or source == "fossilworks" or source == "WoRMS" or source == "worms" or source == "POWO" or source == "powo" or source == "WFO" or source == "wfo" or source == "AlgaeBase" -- and so on	   then return p._main(frame,data[source]) else -- 		-- is there a point in the default if it needs the named object/table? return p._main(frame,data[source]) end end p._main = function(frame, source)

--TODO in modular version source will be provided in frame arguments --local source = mw.getCurrentFrame:getParent.args[1] local chapterParams = {} -- used for cite book (only MSW3 at moment) if not source then return "Error: unrecognised source." end local title, url = initialise(frame, source) --taxon related parameters local genus, species, subspecies if source.db ~= "col" then                            -- col legacy uses positional parameters differently genus, species, subspecies = getGenusSpecies end local family = templateArgs['family'] local order = templateArgs['order'] local taxon = templateArgs['taxon'] local id = templateArgs['id']                                      --id related parameters local spid = templateArgs['spid'] or templateArgs['species_id'] local genid = templateArgs['genid'] or templateArgs['genus_id'] local citation = templateArgs['citation'] local collection = templateArgs['collection'] or templateArgs['collection_no'] local search = templateArgs['search'] local mode, value -- the functions if genus and species and source.species then title, url = source.species(genus,species,subspecies) else -- functions with just their own name as parameter if id then mode = "id"; value = id   	elseif taxon then mode = "taxon"; value = taxon elseif order then mode = "order"; value = order elseif family then mode = "family"; value = family elseif genus then mode = "genus"; value = genus elseif spid then mode = "spid"; value = spid elseif genid then mode = "genid"; value = genid elseif search then mode = "search"; value = search elseif citation then mode = "citation"; value = citation elseif collection then mode = "collection"; value = collection else -- no suitable parameter (use default page) if source.default then title, url, chapterParams = source.default(title, url) end end end if mode then if source[mode] then title, url, chapterParams = source[mode](value) elseif data.default[mode] then title, url, chapterParams = data.default[mode](value, source) else if source.error then return source.error end            -- custom error message return "Error: parameter not supported for this source" .. " (" .. mode .. ")" end else -- if no mode then use the default title and url set by initialize end

if source.citeTemplate == "Cite book" then return p.citeBook(frame, title, url, chapterParams) end return p.citeWeb(frame, title, url) end -- End the function.

p.Reference = function(frame) local refs = require('Module:FishRef/refs') getArgs(frame, templateArgs) if templateArgs[2] then local reference = mw.text.trim(templateArgs[2]) if reference ~= "" and refs[reference] then if templateArgs['pages'] then refs[reference] = refs[reference]:gsub("}}", "|pages="..templateArgs['pages'].."}}") refs[reference] = refs[reference]:gsub("|pages=[^|{}%[%]]*(|[^|{}}%[%]]*|pages=)", "%1") end if templateArgs['reftags'] == "yes" then refs[reference] = ' ' end if templateArgs['expand'] and templateArgs['expand']=='no' or templateArgs['raw'] then return refs[reference] else return frame:preprocess(refs[reference]) end else return 'Reference not found: "'	.. templateArgs[2] .. '"' end end return "Reference parameter missing." end -- End the function.

-- All modules end by returning the variable containing its functions to Wikipedia. return p