Module:BiologyList

From Wikimedia Commons, the free media repository
Jump to: navigation, search
Lua
CodeDiscussionEditHistoryNo test API DocumentationSubpagesLinksTestsResultsSandbox All modules

Module:BiologyList (talk · edit · hist · links · doc · subpages · tests / results · sandbox · all modules)


Usage
This module is mainly used to display lists of taxa. It is also used by other biology templates as helper.
Functions and their usage
How to improve and test this module
  1. develop your modification in Module:BiologyList/sandbox, the sandbox of this module
    which is used in the sandbox templates {{Subspecies/sandbox}}, {{Species/sandbox}}, {{Species2/sandbox}}, {{Genera/sandbox}}, {{Genera2/sandbox}}, {{Taxa/sandbox}}, {{SimpleTaxa/sandbox}}
  2. verify your changes in {{Subspecies/testcases}}, {{Species/testcases}}, {{Species2/testcases}}, {{Genera/testcases}}, {{Genera2/testcases}}, {{Taxa/testcases}}, {{SimpleTaxa/testcases}}
  3. verify your changes in Module_talk:BiologyList/sandbox/testcases
  4. if needed improve the testcases Module:BiologyList/sandbox/testcases
  5. report your modifications in Module:BiologyList
  6. verify again your changes in {{Subspecies/testcases}}, {{Species/testcases}}, {{Species2/testcases}}, {{Genera/testcases}}, {{Genera2/testcases}}, {{Taxa/testcases}}, {{SimpleTaxa/testcases}}
  7. verify again your changes in Module_talk:BiologyList/testcases
  8. if needed improve the testcases Module:BiologyList/testcases
See also

Code

local _common=require('Module:Biology')

local _prefixes = {
	'Species of ',
	'Genera of ',
	'Subtribes of ',
	'Tribes of ',
	'Subfamilies of ',
	'Families of '
}

-- getTaxonNameOutOfTitle() returns 'Canistrum' out of 'Canistrum (Bromeliaceae)' and 'Bromeliaceae' out of 'Genera of Bromeliaceae'
--    parameter title can be nil in which case calling article's pagename is used
-- Warning: for this function cannot distinguish a subgenus (like 'Canistrum (subgenus)') from a disambiguated taxon 'Canistrum (Bromeliaceae)'.
--          So calling this function on a subgenus returns the genus. This behavior is not too problematic as genus are just above their subgenus.
function getTaxonNameOutOfTitle(title)
	if string.isNilOrEmpty(title) then
		-- Usage: from getTaxonNameForUrl() when {{Taxasource}} is called without param name=
		title = mw.title.getCurrentTitle().text
	else
		-- Usage: from testcase with different titles
		title = mw.text.trim(title)
	end
	local start = string.find(title,' (',1,true)
	if start then
		title = mw.text.trim(string.sub(title,1,start-1))
	end
	for index, prefix in pairs(_prefixes) do
		if string.sub(title,1,string.len(prefix))==prefix then
			title = mw.text.trim(string.sub(title,string.len(prefix)))
		end
	end
	return title
end

function getTaxonNameForUrl(taxonNameOrNilForTitle, urlFormatOrNil)
	local taxonName
	if string.isNilOrEmpty(taxonNameOrNilForTitle) then
		-- parameter name= is NOT provided to new {{Taxasource}} => use current title trunked
		taxonName = getTaxonNameOutOfTitle(Nil)
	else
		-- parameter name= is provided to new {{Taxasource}} => use it without modifications
		taxonName = taxonNameOrNilForTitle
	end
	if string.isNilOrEmpty(urlFormatOrNil) then
		-- https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual/fr#mw.uri.encode
		-- "QUERY" encode les espaces en utilisant "+", "PATH" les encode en utilisant "%20" et "WIKI" les encode en utilisant "_".
		urlFormatOrNil = 'QUERY'
	end
	return mw.uri.encode(taxonName, urlFormatOrNil)
end

function getSourceLink(source, taxonNameOrNil)
	if source=='adw' then
		return '[http://animaldiversity.ummz.umich.edu/site/search?category=Classification&SearchableText=' .. getTaxonNameForUrl(taxonNameOrNil) .. ' Animal Diversity Web (ADW)]'
	elseif source=='afd' then
		return '[http://www.environment.gov.au/biodiversity/abrs/online-resources/fauna/afd/taxa/' .. getTaxonNameForUrl(taxonNameOrNil) .. '/checklist#selected Australian Faunal Directory (AFD)]'
	elseif source=='algaebase' then
		return '[http://www.algaebase.org/ AlgaeBASE]'
	elseif source=='amphibiaweb' then
		return '[http://amphibiaweb.org/ Amphibiaweb]'
	elseif source=='animalbase' then
		return '[http://www.animalbase.uni-goettingen.de/zooweb/servlet/AnimalBase/search AnimalBase]'
	elseif source=='aou' then
		return '[http://www.aou.org/checklist/north/full.php AOU]'
	elseif source=='apg' then
		return '[[:en:APG system|APG]]'
	elseif source=='apgii' or source=='apg ii' then
		return '[[APG II|APG II]]'
	elseif source=='apgiii' or source=='apg iii' then
		return '[[APG III|APG III]]'
	elseif source=='apni' then
		return '[http://www.anbg.gov.au/cgi-bin/apni APNI]'
	elseif source=='apwebsite' then
		return '[[APWebsite]]'
	elseif source=='asw' then
		return '[http://research.amnh.org/vz/herpetology/amphibia/index.php ASW]'
	elseif source=='avibase' then
		return '[http://avibase.bsc-eoc.org/avibase.jsp Avibase]'
	elseif source=='baltimore' then
		return '[[:en:Baltimore classification|Baltimore classification]]'
	elseif source=='biolib' then
		return '[http://www.biolib.cz/en/main/ BioLib]'
	elseif source=='bouchet&rocroi2005' then
		return '[[:en:Taxonomy of the Gastropoda (Bouchet & Rocroi, 2005)|Bouchet & Rocroi (2005)]]'
	elseif source=='butmoth' then
		return '[http://www.nhm.ac.uk/research-curation/research/projects/butmoth/index.html ButMoth]'
	elseif source=='catalogueoflife' then
		return '[http://www.catalogueoflife.org/col/search/all/key/' .. getTaxonNameForUrl(taxonNameOrNil) .. ' Catalogue of Life]'
	elseif source=='chase2003' then
		return '[http://www.orchids.co.in/dna-data-orchidaceae.shtm Chase (2003)]'
	elseif source=='cites' then
		return '[[:en:CITES|CITES]]'
	elseif source=='cronquist' then
		return '[[Cronquist System|Cronquist]]'
	elseif source=='de' then
		return '[[:de:' .. getTaxonNameForUrl(taxonNameOrNil, 'WIKI') .. '|de.wikipedia]]'
	elseif source=='discoverlife' then
		return '[http://www.discoverlife.org/mp/20q?search=' .. getTaxonNameForUrl(taxonNameOrNil) .. ' DiscoverLife]'
	elseif source=='dmitriev' then
		return '[http://dmitriev.speciesfile.org Dmitriev Species File]'
	elseif source=='doris' then
		return '[http://doris.ffessm.fr/fiches_liste_recherche.asp?touslesmots=' .. getTaxonNameForUrl(taxonNameOrNil) .. ' DORIS]'
	elseif source=='efloras' then
		return '[http://www.efloras.org eFloras.org]'
	elseif source=='emonocot' then
		return '[http://www.e-monocot.org/search?query=' .. getTaxonNameForUrl(taxonNameOrNil) .. ' eMonocot]'
	elseif source=='en' then
		return '[[:en:' .. getTaxonNameForUrl(taxonNameOrNil, 'WIKI') .. '|en.wikipedia]]'
	elseif source=='eol' then
		return '[http://www.eol.org/ EOL]'
	elseif source=='es' then
		return '[[:en:' .. getTaxonNameForUrl(taxonNameOrNil, 'WIKI') .. '|es.wikipedia]]'
	elseif source=='faunaeur' then
		return '[http://www.faunaeur.org Fauna Europaea]'
	elseif source=='fishbase' then
		return '[http://www.fishBase.org FishBase]'
	elseif source=='funet' then
		return '[http://www.nic.funet.fi/cgi-bin/life/goto?taxon=' .. getTaxonNameForUrl(taxonNameOrNil) .. ' Funet]'
	elseif source=='fungorum' then
		return '[http://www.indexfungorum.org Index Fungorum]'
	elseif source=='fr' then
		return '[[:fr:' .. getTaxonNameForUrl(taxonNameOrNil, 'WIKI') .. '|fr.wikipedia]]'
	elseif source=='gbif' then
		return '[http://data.gbif.org/welcome.htm GBIF]'
	elseif source=='generaorchidacearum2014' then
		return '[http://www.kew.org/science-conservation/research-data/science-directory/projects/genera-orchidacearum Genera Orchidacearum, Volume 1 - 6 (1999-2014)]'
	elseif source=='goffinet et al.' then
		return '[http://bryology.uconn.edu/classification-2/#' .. getTaxonNameForUrl(taxonNameOrNil) .. " Goffinet ''et al.'']"
	elseif source=='grin' then
		return '[http://www.ars-grin.gov/npgs/aboutgrin.html GRIN]'
	elseif source=='hbw' then
		return "[[:en:Handbook of the Birds of the World|''Handbook of the Birds of the World'']]"
	elseif source=='ioc2.2' then
		return '[[:en:International Ornithological Congress|IOC classification 2.2]]'
	elseif source=='ioc2.3' then
		return '[[:en:International Ornithological Congress|IOC classification 2.3]]'
	elseif source=='ioc2.4' then
		return '[[:en:International Ornithological Congress|IOC classification 2.4]]'
	elseif source=='ioc2.5' then
		return '[[:en:International Ornithological Congress|IOC classification 2.5]]'
	elseif source=='ioc2.6' then
		return '[[:en:International Ornithological Congress|IOC classification 2.6]]'
	elseif source=='ioc2.7' then
		return '[[:en:International Ornithological Congress|IOC classification 2.7]]'
	elseif source=='ioc2.8' then
		return '[[:en:International Ornithological Congress|IOC classification 2.8]]'
	elseif source=='ioc2.9' then
		return '[[:en:International Ornithological Congress|IOC classification 2.9]]'
	elseif source=='ioc2.10' then
		return '[[:en:International Ornithological Congress|IOC classification 2.10]]'
	elseif source=='ioc2.11' then
		return '[[:en:International Ornithological Congress|IOC classification 2.11]]'
	elseif source=='ioc3.1' then
		return '[[:en:International Ornithological Congress|IOC classification 3.1]]'
	elseif source=='ioc3.2' then
		return '[[:en:International Ornithological Congress|IOC classification 3.2]]'
	elseif source=='ioc3.3' then
		return '[[:en:International Ornithological Congress|IOC classification 3.3]]'
	elseif source=='ioc3.4' then
		return '[[:en:International Ornithological Congress|IOC classification 3.4]]'
	elseif source=='ioc3.5' then
		return '[[:en:International Ornithological Congress|IOC classification 3.5]]'
	elseif source=='ioc4.1' then
		return '[[:en:International Ornithological Congress|IOC classification 4.1]]'
	elseif source=='ioc4.2' then
		return '[[:en:International Ornithological Congress|IOC classification 4.2]]'
	elseif source=='ioc4.3' then
		return '[[:en:International Ornithological Congress|IOC classification 4.3]]'
	elseif source=='ioc4.4' then
		return '[[:en:International Ornithological Congress|IOC classification 4.4]]'
	elseif source=='ioc5.1' then
		return '[[:en:International Ornithological Congress|IOC classification 5.1]]'
	elseif source=='ioc5.2' then
		return '[[:en:International Ornithological Congress|IOC classification 5.2]]'
	elseif source=='ioc5.3' then
		return '[[:en:International Ornithological Congress|IOC classification 5.3]]'
	elseif source=='ioc5.4' then
		return '[[:en:International Ornithological Congress|IOC classification 5.4]]'
	elseif source=='ioc6.1' then
		return '[[:en:International Ornithological Congress|IOC classification 6.1]]'
	elseif source=='ioc6.2' then
		return '[[:en:International Ornithological Congress|IOC classification 6.2]]'
	elseif source=='ioc6.3' then
		return '[[:en:International Ornithological Congress|IOC classification 6.3]]'
	elseif source=='ioc' then
		return '[[:en:International Ornithological Congress|IOC classification]]'
	elseif source=='ion' then
		return '[http://www.organismnames.com/query.htm?Submit.x=10&Submit.y=9&searchType=simple&q=' .. getTaxonNameForUrl(taxonNameOrNil) .. ' ION]'
	elseif source=='ipni' then
		return '[http://www.ipni.org/index.html IPNI]'
	elseif source=='it' then
		return '[[:it:' .. getTaxonNameForUrl(taxonNameOrNil, 'WIKI') .. '|it.wikipedia]]'
	elseif source=='itis' then
		return '[http://www.itis.gov ITIS]'
	elseif source=='iucn' then
		return '[http://www.iucnredlist.org/search/quick?x=0&y=0&species=true&subspecies=true&stocks=false&text=' .. getTaxonNameForUrl(taxonNameOrNil) .. ' IUCN]'
	elseif source=='jboyd' then
		return "[http://jboyd.net/Taxo/ ''A Taxonomy in Flux'' (JBoyd.net)]"
	elseif source=='jörger et al. (2010)' then
		return "[[:en:Heterobranchia#2010_taxonomy|Jörger ''et al.'' (2010)]]"
	elseif source=='kew vascular plant' then
		return "[http://data.kew.org/cgi-bin/vpfg1992/genlist.pl?' .. getTaxonNameForUrl(taxonNameOrNil) .. ' Kew Gardens 'Vascular Plant']"
	elseif source=='kew world checklist' then
		return '[http://apps.kew.org/wcsp/qsearch.do?page=quickSearch&plantName=' .. getTaxonNameForUrl(taxonNameOrNil) .. " Kew Gardens 'World Checklist']"
	elseif source=='lepindex' then
		return '[http://www.nhm.ac.uk/research-curation/research/projects/lepindex/search/ Lepidoptera Names Index]'
	elseif source=='luther2008' then
		return '[[:en:Harry E. Luther|Harry E. Luther, 2008]]'
	elseif source=='nakano&ozawa2007' then
		return '[[:en:Patellogastropoda#2007_taxonomy|Nakano & Ozawa (2007)]]'
	elseif source=='malaquias et al. 2009' then
		return "[[:en:Cephalaspidea#2009 taxonomy|Malaquias ''et al.'' (2009)]]"
	elseif source=='msw' then
		return '[http://www.bucknell.edu/msw3/search.asp?s=' .. getTaxonNameForUrl(taxonNameOrNil) .. ' Mammal Species of the World]'
	elseif source=='mycobank' then
		return '[http://www.mycobank.org MycoBank]'
	elseif source=='nam' then
		return '[http://www.mnh.si.edu/mna North American Mammals]'
	elseif source=='ncbi' then
		return '[http://www.ncbi.nlm.nih.gov/Taxonomy NCBI]'
	elseif source=='nelson, j.s. 2006' then
		return '[[Template:Taxonavigation/Nelson, J.S. 2006 Fishes of the world|Nelson, J.S. 2006 Fishes of the world]]'
	elseif source=='reptiledb' then
		return '[http://reptile-database.reptarium.cz/ ReptileDB]'
	elseif source=='rushforth conifers' then
		return "Keith D. Rushforth ''Conifers''"
	elseif source=='sibley' then
		return '[[Template:Taxonavigation/Sibley-Ahlquist taxonomy|Sibley-Ahlquist]]{{Incorrect biology template usage|sortkey=Source}}'
	elseif source=='smith' then
		return '[[Smith System]]'
	elseif source=='species' then
		return '[[:species:' .. getTaxonNameForUrl(taxonNameOrNil, 'WIKI') .. '|Wikispecies]]'
	elseif source=='sv' then
		return '[[:sv:' .. getTaxonNameForUrl(taxonNameOrNil, 'WIKI') .. '|sv.wikipedia]]'
-- Start SpeciesFile
	elseif source=='aphidsf' then
		return '[http://aphid.speciesfile.org Aphid Species File]'
	elseif source=='arthropodasf' then
		return '[http://arthropoda.speciesfile.org Arthropoda Species File]'
	elseif source=='blattodeasf' then
		return '[http://blattodea.speciesfile.org Blattodea Species File]'
	elseif source=='cockroachsf' then
		return '[http://cockroach.speciesfile.org Cockroach Species File]'
	elseif source=='coleorrhynchasf' then
		return '[http://coleorrhyncha.speciesfile.org Coleorrhyncha Species File]'
	elseif source=='coreoideasf' then
		return '[http://coreoidea.speciesfile.org Coreoidea Species File]'
	elseif source=='dermapterasf' then
		return '[http://dermaptera.speciesfile.org Dermaptera Species File]'
	elseif source=='embiopterasf' then
		return '[http://embioptera.speciesfile.org Embioptera Species File]'
	elseif source=='grylloblattodeasf' then
		return '[http://grylloblattodea.speciesfile.org Grylloblattodea Species File]'
	elseif source=='mantodeasf' then
		return '[http://mantodea.speciesfile.org Mantodea Species File]'
	elseif source=='orthopterasf' then
		return '[http://orthoptera.speciesfile.org Orthoptera Species File]'
	elseif source=='paraneopterasf' then
		return '[http://paraneoptera.speciesfile.org Paraneoptera Species File]'
	elseif source=='phasmidasf' then
		return '[http://phasmida.speciesfile.org Phasmida Species File]'
	elseif source=='plecopterasf' then
		return '[http://plecoptera.speciesfile.org Plecoptera Species File]'
	elseif source=='polyneopterasf' then
		return '[http://polyneoptera.speciesfile.org Polyneoptera Species File]'
	elseif source=='psocodeasf' then
		return '[http://psocodea.speciesfile.org Psocodea Species File]'
	elseif source=='orthopterasf' then
		return '[http://orthoptera.speciesfile.org Orthoptera Species File]'
	elseif source=='zorapterasf' then
		return '[http://zoraptera.speciesfile.org Zoraptera Species File]'
-- End SpeciesFile
	elseif source=='strasburger' then
		return '[[Strasburger]]'
	elseif source=='theastereaeworkinggroup' then
		return '[http://msb.unm.edu/divisions/herbarium/research/astereae-working-group/genera.html The Astereae Working Group]'
	elseif source=='theplantlist' then
		return '[http://www.theplantlist.org/tpl1.1/search?q=' .. getTaxonNameForUrl(taxonNameOrNil) .. ' The Plant List]'
	elseif source=='ttdb' then
		return '[http://turbellaria.umaine.edu/turb2.php?action=5&sys=' .. getTaxonNameForUrl(taxonNameOrNil) .. ' Turbellarian Taxonomic Database]'
	elseif source=='tolweb' then
		return '[http://tolweb.org/' .. getTaxonNameForUrl(taxonNameOrNil) .. ' TOLweb]'
	elseif source=='tpdb' then
		return '[http://paleodb.org TPDB]'
	elseif source=='tropicos' then
		return '[http://www.tropicos.org/NameSearch.aspx?exact=true&commonname=&name=' .. getTaxonNameForUrl(taxonNameOrNil) .. ' Tropicos]'
	elseif source=='ubio' then
		return '[http://www.ubio.org/browser/search.php?search_all=' .. getTaxonNameForUrl(taxonNameOrNil) .. ' uBIO]'
	elseif source=='weston&barker (2006)' then
		return '[http://www.rbgsyd.nsw.gov.au/__data/assets/pdf_file/0009/80856/Tel11Wes314.pdf Weston and Barker (2006)]'
	elseif source=='wrms' or source=='worms' then
		return '[http://www.marinespecies.org/aphia.php?p=taxlist&tName=' .. getTaxonNameForUrl(taxonNameOrNil) .. ' WoRMS]'
	elseif source=='wsc' then
		return '[http://research.amnh.org/iz/spiders/catalog World Spider Catalog]'
	elseif source=='?' then
		return 'undetermined source'
	else
		_common.addDebug('getSourceLink', "Unknown source '" .. source .. "'")
		return source .. _common.incorrectBiologyTemplateUsage('Source', "(Unknown source '" .. source .. "')", 'Taxasource')
	end
end

function addSourceLinks(allsources, taxonNameOrNil, sources)
	if not string.isNilOrEmpty(sources) then
		sources = mw.text.split(sources, " & ", true) -- true for plaintext
		for index, source in pairs(sources) do
			source = mw.text.trim(source)
			source = string.lower(source)
			table.insert(allsources, {source, getSourceLink(source, taxonNameOrNil)})
		end
	end
end

function getSourceLinks(args)
	local allsources = {}
	local taxonNameOrNil = args.name

	local links = ''

	for argNameOrIndex, argValue in pairs(args) do
		if type(argNameOrIndex) == 'string' then
			-- named argument pair: taxon=Amphiprion, ref=MyRef
			if string.startsWith(argNameOrIndex, 'ref') then
				table.insert(allsources, {'zzzz' .. argNameOrIndex, argValue})
			elseif argNameOrIndex == 'name' then
				-- already assigned in taxonNameOrNil
			else
				-- Not managed => error
				_common.addDebug('getSourceLinks', "Unmanaged parameter '" .. argNameOrIndex .. "' passed to Taxasource")
				links = links .. _common.incorrectBiologyTemplateUsage('Source', "Unmanaged parameter '" .. argNameOrIndex .. "' passed to Taxasource", 'Taxasource')
			end
		else
			-- normal argument pair: 1=ADW, 2=fishbase
			addSourceLinks(allsources, taxonNameOrNil, argValue)
		end
	end

	table.sort(allsources, function(t1,t2) return t1[1] < t2[1] end)

	for index, sourceAndLink in pairs(allsources) do
		if string.len(links)>0 then
			links = links .. '&nbsp;&&nbsp;'
		end
		links = links .. sourceAndLink[2]
	end
	return links
end

-- formatList() is used by Templates SimpleTaxa, Taxa, Genera, Genera2, Species, Species2, Subspecies, Minerals to display a list of taxon
function formatList(options)
	if not options then
		return "options is nul"
	end
	local italic = string.isTrue(options['italic'])

	local extinctCross = '†'
	if italic then
		extinctCross = "</i>†<i>"
	end

	local avoidFirstParamCount = options['avoidFirstParamCount']
	if avoidFirstParamCount then
		avoidFirstParamCount = tonumber(avoidFirstParamCount,10)
	end

	local link = options['link']
	if not link then
		link = 'true'
	end
	link = string.isTrue(link)
	
	local nameprefix = options['nameprefix']
	if link then
		local linkPrefix = '[[:Category:'
		if options['linkto'] and options['linkto'] == 'gallery' then
			linkPrefix = '[['
		end
		if string.isNilOrEmpty(nameprefix) then
			nameprefix = linkPrefix
		else
			nameprefix = linkPrefix .. nameprefix .. ' '
		end
	else
		nameprefix = nil
	end
	
	local displayprefix = options['displayprefix']
	if string.isNilOrEmpty(displayprefix) then
		displayprefix = ''
	else
		displayprefix = displayprefix .. ' '
	end
	if link then
		displayprefix = '|' .. displayprefix
	else
		--displayprefix = displayprefix
	end

	local formatedList = nil
	for index = 1, 1602 do
		local indexStr = tostring(index)
		local name = string.trimOrNullify(options[indexStr])
		if not name then
			return formatedList
		end
		if name == 'STOP' then
			-- Needed by {{Invalid taxon category redirect}}
			return formatedList
		end
		if avoidFirstParamCount and index <= avoidFirstParamCount then
			-- First parameter of Template:Taxa and Template:SimpleTaxa is rank that we want to avoid
			-- First 2 parameters of Template:Species and Template:Species is genus cut in 2 that we want to avoid
			-- First 3 parameters of Template:Subspecies is species cut in 3
		else
			-- Manage extinct sign
			local namee = options['†' .. indexStr]
			local extinct = false
			if not string.isNilOrEmpty(namee) then
				-- Extinct sign 1 (deprecated + no more possible): coming from old template: |†2={{{{{{3}}}|}}}| where {{{{3}}}==Eohiodon and {{{{{{3}}}|}}}=='†'
				extinct = true
			else
				namee = options[name]
				if namee and string.find(namee,'†',1,true) then
					-- Extinct sign 2 (deprecated): coming from Module:Arguments: |Eohiodon=†|
					extinct = true
					options[name] = nil -- To avoid interpretation by Disambiguation
				elseif string.find(name,'†',1,true) then
					-- Extinct sign 3: |Eohiodon†| or |†Eohiodon|
					extinct = true
					name = string.gsub(name, '†', '', 5)
				end
			end

			-- Manage note
			local notepos = string.find(name,'note:',1,true)
			local note=''
			if notepos then
				note = ' ' .. mw.text.trim(string.sub(name,notepos+5))
				name = mw.text.trim(string.sub(name,1,notepos-1))
			end

			-- Manage disambiguation
			local displayName = name
			local disambiguated = false
			-- Disambiguation 1: '|Ibicella|Ibicella=Ibicella (Martyniaceae)|'
			local namedisamb = options[name]
			if not string.isNilOrEmpty(namedisamb) then
				if not string.find(string.lower(namedisamb),string.lower(name),1,true) then
					-- Disambiguation 1bis: Ibicella|Ibicella=(Martyniaceae) so name=Ibicella, namedisamb=(Martyniaceae)
					namedisamb = name .. ' ' .. namedisamb
				end
				name = namedisamb
				displayName = name
				disambiguated = true
			end
			-- Disambiguation 2: '|Ibicella (Martyniaceae)|'
			-- Warning, it will manage  Disambiguation 1 if parentheses are involved
			local parenthesisStart = string.find(displayName,' (',1,true)
   	 		if parenthesisStart then
				local parenthesisEnd = string.find(displayName,')',parenthesisStart,true)
				if parenthesisEnd then
					displayName = string.sub(displayName,1,parenthesisStart-1) .. '<small>' .. string.sub(displayName,parenthesisStart,parenthesisEnd) .. '</small>' .. string.sub(displayName,parenthesisEnd+1)
					disambiguated = true
				end
			end
			-- Disambiguation 3 (deprecated): '|Ibicella|d2=(Martyniaceae)|'
			if not disambiguated then
				local named = options['d' .. indexStr]
				if not string.isNilOrEmpty(named) then
					name = name .. ' ' .. named
					displayName = displayName .. ' <small>' .. named .. '</small>'
				end
			end

			if name == '...' then
				formatedList = formatedList .. '...<small> (incomplete list)</small>'
			else
				if formatedList then
					formatedList = formatedList .. ', '
				else
					formatedList = ''
				end
				-- Detect too small entries
				if string.len(name) <= 1 then
					formatedList = formatedList .. _common.incorrectBiologyTemplateUsage('Taxa', "Too short taxonName/epithet '" .. name .. "' :", 'Taxa')
				elseif string.startsWith(name, 'X ') then
					formatedList = formatedList .. _common.incorrectBiologyTemplateUsage('Taxa', "Incorrect taxonName/epithet '" .. name .. "' containing X instead of ×:", 'Taxa')
				elseif string.startsWith(name, 'x ') then
					formatedList = formatedList .. _common.incorrectBiologyTemplateUsage('Taxa', "Incorrect taxonName/epithet '" .. name .. "' containing x instead of ×:", 'Taxa')
				elseif string.startsWith(name, '×') and not string.startsWith(name, '× ') then
					formatedList = formatedList .. _common.incorrectBiologyTemplateUsage('Taxa', "Incorrect taxonName/epithet '" .. name .. "' having × without space:", 'Taxa')
				end
				if extinct then
					formatedList = formatedList .. extinctCross
				end
				--displayName='<taxon> <small><disamb></small>'
				if link then
					-- nameprefix=   '[[:Category:<genus> <species> ' (ssp list) or '[[<genus> <species> ' (ssp list) or '[[:Category:<genus> ' (sp list) or '[[<genus> ' (sp list) or '[[:Category:' (taxa/genus list) or '[[' (taxa/genus list)
					-- displayprefix='|<G>. <S>.'                     (ssp list)                                      or '|<G>. '               (sp list)                           or '|'            (taxa/genus list)
					formatedList = formatedList .. nameprefix .. name .. displayprefix .. displayName .. ']]'
				else
					-- displayprefix='<G>. <S>. '                     (ssp list)                                      or '<G>. '                (sp list)                           or ''             (taxa/genus list)
					formatedList = formatedList .. displayprefix .. displayName
				end
				formatedList = formatedList .. note
			end
		end
	end
	return formatedList
end

-- suppressNothospeciesX() is used by Template:Kew_list to transform "Cattleya × ballantiniana" in "Cattleya ballantiniana"
function suppressNothospeciesX(text)
	if not text then
		return ''
	end
	text = string.gsub(text, '×', ' ', 5)
	text = string.gsub(text, '  ', ' ', 5)
	text = string.gsub(text, '  ', ' ', 5)
	text = string.gsub(text, '  ', ' ', 5)
	return mw.text.trim(text)
end

-- isEmptyOrNumeric() is used by Template:IPNI if first parameter is empty or a year number
-- returns '1' for true, '' for false to be used with {{#if:
function isEmptyOrNumeric(text)
	if not text then
		return true
	end
	if string.len(text) == 0 then
		return true
	end
	if tonumber(text,10) == nil then
		return false
	else
		return true
	end
end

-- checkDate() verifies that the passed date is in the format 'YYYY-MM-DD' like '2012-12-31'
-- return '' if yes
-- return error message + category if not in correct format
function internalCheckDate(mydate)
	local pattern = '(%d+)%-(%d+)%-(%d+)'
	local format = ". Format: 'YYYY-MM-DD' like '2012-12-31'"
	local yearStr, monthStr, dayStr = mydate:match(pattern)
	if not yearStr or not monthStr or not dayStr then
		return 'Incorrect date ' .. mydate .. format
	end
	local year = tonumber(yearStr)
	local month = tonumber(monthStr)
	local day = tonumber(dayStr)
	if not year or not month or not day then
		return 'Incorrect date ' .. mydate .. format
	end
	if year < 2005 or year > 2050 then 
		return 'Incorrect year ' .. year .. ' in date ' .. mydate .. format
	end
	if month < 1 or month > 12 then 
		return 'Incorrect month ' .. month .. ' in date ' .. mydate .. format
	end
	if day < 0 or day > 31 then 
		return 'Incorrect day ' .. day .. ' in date ' .. mydate .. format
	end
	_common.addDebug('checkDate', 'Perfect date: year=' .. year .. ' month=' .. month .. ' day=' .. day)
	return nil
end

-- checkDate() verifies that the passed date is in the format 'YYYY-MM-DD' like '2012-12-31'
-- return '' if yes
-- return error message + category if not in correct format
function checkDate(mydate, templateNameForDoc, ignoreNamespace)
	local error = internalCheckDate(mydate)
	if error then
		return _common.incorrectBiologyTemplateUsage('Date', error, templateNameForDoc, ignoreNamespace)
	else
		return ''
	end
end

local p = {}
local getArgs = require('Module:Arguments').getArgs

-- public version of getTaxonNameOutOfTitle()
-- No more used except in testcases
function p.getTaxonNameOutOfTitle(frame)
	-- parameter only provided in testcases
	return getTaxonNameOutOfTitle(frame.args['1'])
end

function p.getSourceLinks(frame)
	local args = getArgs(frame)
	return getSourceLinks(args) .. _common.getDebug('<BR/>Debug:<BR/>')
end

-- public version of  formatList
-- Used by: {{SimpleTaxa}}, {{Taxa}}, {{Genera}}, {{Genera2}}, {{Species}}, {{Species2}}, {{Subspecies}}, {{Minerals}}
function p.formatList(frame)
	local args = getArgs(frame)

	if not string.isNilOrEmpty(args['accessdate']) then
		_common.addDebug('formatList', 'accessdate=' .. args['accessdate'])
	end
	local formatedList = formatList(args)
	if formatedList then
		local italic = string.isTrue(frame.args['italic'])
		if italic then
			formatedList = "<i>" .. formatedList .. "</i>"
		end
	else
		formatedList = ''
	end
	-- Now add debug traces if activated
	formatedList = formatedList .. _common.getDebug('\n<BR/>Debug:<BR/>')
	return formatedList
end

-- public version of suppressNothospeciesX()
-- Used by: Template:IPNI, Template:Kew_list
function p.suppressNothospeciesX(frame)
	return suppressNothospeciesX(frame.args['1'])
end

-- public version of isEmptyOrNumeric().
-- Used by Template:IPNI
function p.isEmptyOrNumeric(frame)
	if isEmptyOrNumeric(frame.args['1']) then
		return '1'
	else
		return ''
	end
end

-- public version of checkDate()
-- Used by: Template:TaxasourceAndDate/CheckDate
function p.checkDate(frame)
	local mydate = frame.args['1']
	if string.isNilOrEmpty(mydate) then
		 return ''
	end
	local templateNameForDoc = frame.args.templateNameForDoc
	local ignoreNamespace = frame.args.ignoreNamespace
	if string.isNilOrEmpty(templateNameForDoc) then
		 templateNameForDoc = 'TaxasourceAndDate'
	end
	return checkDate(mydate, templateNameForDoc, ignoreNamespace)
end

function p.testcase_getSourceLink(frame)
	-- testcase (return nowiki string when normal function returns wiki syntax)
	return mw.text.nowiki(getSourceLink(frame.args['1'], frame.args['2']))
end

function p.testcase_getSourceLinks(frame)
	-- testcase (return nowiki string when normal function returns wiki syntax)
	return mw.text.nowiki(getSourceLinks(frame.args))
end

function p.testcase_formatList(frame)
	-- testcase (return nowiki string when normal function returns wiki syntax)
	return mw.text.nowiki(p.formatList(frame))
end

function p.testcase_checkDate(frame)
	-- testcase (return nowiki string when normal function returns wiki syntax)
	return mw.text.nowiki(p.checkDate(frame)) .. _common.getDebug('Debug: ')
end

return p