At this time we request this module/template not be used on taxon pages until the module is implemented by {{Taxonbar}} through community consensus. The goal is to soon implement this Lua code to replace the existing {{Taxonbar}} template. Parameters and databases are set by Module:Taxonbar/conf.

For testcases use: {{Taxonbar/sandbox2 | from=QID}} View testcases at Template:Taxonbar/testcases

Taxon Example:

தொகு
Scarlet macaw (Ara macao)

{{Taxonbar/sandbox2 | from=Q243761}}

Result: வார்ப்புரு:Taxonbar/sandbox2

Purge server cache

Rhododendron maximum வார்ப்புரு:Taxonbar/sandbox2 Asclepias syriaca வார்ப்புரு:Taxonbar/sandbox2 Peach (Prunus persica) வார்ப்புரு:Taxonbar/sandbox2 Puma_(genus) வார்ப்புரு:Taxonbar/sandbox2 Dog (Canis lupus familiaris) வார்ப்புரு:Taxonbar/sandbox2 Eastern bluebird (Sialia sialis) வார்ப்புரு:Taxonbar/sandbox2 Honey bee (Apis) வார்ப்புரு:Taxonbar/sandbox2 Western honey bee (Apis mellifera) வார்ப்புரு:Taxonbar/sandbox2 Clipper butterfly (Parthenos sylvia) வார்ப்புரு:Taxonbar/sandbox2 Turkey tail (Trametes versicolor) வார்ப்புரு:Taxonbar/sandbox2 Button/portobello mushroom (Agaricus bisporus) வார்ப்புரு:Taxonbar/sandbox2

Wikidata taxon identifiers

தொகு
Parameter Database Property ID
APDB APDB p2036
AlgeaBase AlgaeBase p1348
Araneae Araneae p3594
ARKive ARKive p2833
Avibase Avibase p2026
BacDive BacDive p2946
BHL BHL p687
BioLib BioLib p838
BugGuide BugGuide p2464
ButMoth ButMoth p3060
Conifers Conifers.org 1940
eBird eBird p3444
EoL EoL p830
FaunaEuropaea Fauna Europaea p1895
FishBase FishBase p938
FloraBase FloraBase p3101
Fossilworks Fossilworks p842
FNA FNA p1727
FoAO FoAO p3100
FoC FoC p1747
Fungorum Fungorum p1391
GBIF GBIF p846
GrassBase GrassBase p1832
GRIN GRIN p1421
IBC IBC p3099
ICTV ICTV p1076
iNaturalist iNaturalist p3151
IPNI IPNI p961
IPNI2 IPNI author p586
ITIS ITIS p815
IUCN IUCN p227
LepIndex LepIndex p3064
LPSN LPSN p1991
MSW MSW p956
MycoBank MycoBank p962
NCBI NCBI p685
Panartic Panartic Flora p2434
Plantarium Plantarium p3102
PlantList Plant List p1070
PLANTS PLANTS p1772
Plazi Plazi p1992
Species+ Species+ p2040
SPRAT SPRAT p2455
Tropicos Tropicos p960
USDAPLANTS PLANTS p1772
VASCAN VASCAN p1745
Watson Watson & Dallwitz p1761
WCSP WCSP p3591
WoRMS WoRMS p850
WSC WSC p3288
Xeno-canto Xeno-canto p2426
ZooBank ZooBank p1746
Parameter Database Property URL/Interwiki link
eMonocot eMonocot http://e-monocot.org/taxon/urn:kew.org:wcs:taxon:$1
emonocotfamily eMonocot http://e-monocot.org/taxon/urn:kew.org:wcs:family:$1
uBio uBio http://www.ubio.org/browser/details.php?namebankID=$1
WSC species World Spider Catalog http://www.wsc.nmbe.ch/search?sFamily=&fMt=begin&sGenus=&gMt=begin&sSpecies=&sMt=begin&mMt=exact&multiPurpose=slsid&sMulti=$1
WSC genus World Spider Catalog http://www.wsc.nmbe.ch/search?sFamily=&fMt=begin&sGenus=&gMt=begin&sSpecies=&sMt=begin&mMt=exact&multiPurpose=glsid&sMulti=$1
WSC family World Spider Catalog http://www.wsc.nmbe.ch/search?sFamily=&fMt=begin&sGenus=&gMt=begin&sSpecies=&sMt=begin&mMt=exact&multiPurpose=flsid&sMulti=$1
Wikispecies Wikispecies Wikispecies:$1

Module editing — to-do list

தொகு
  • Improve documentation
  • Add parameters to remove individual identifiers from taxonbar. This could help the box from becoming two lines when one line is desired. Can be suppressed by setting equal to no (e.g. |eol=no). Should we suppress if set to blank (e.g. |eol=)?
  • Add support for parameters currently supported by {{Taxonbar}}. Someone want to double-check Module:Taxonbar/conf that we got them all?
  • Add documentation for grinurl=.
  • Continue to add support for new, useful parameters.
  • Add tracking for entries not on Wikidata? Suggest differences be resolved?
  • Program Module:Taxonbar to create it's own documentation table of parameters.
  • Program Module:Taxonbar to support disabled(hidden) databases which can shown when called.
  • Switch {{Taxonbar}} to Module:Taxonbar when it's ready and meets all needs.



require('strict')

local conf = require( 'Module:Taxonbar/conf' ) --configuration module
local TaxonItalics = require( 'Module:TaxonItalics' ) --use a function to conditionally italicize taxon names

--[[==========================================================================]]
--[[                             Local functions                              ]]
--[[==========================================================================]]

local function isNilOrEmpty( thing )
	if thing == nil or thing == '' then
		return true
	end
	return nil
end

local function getIdFromWikidata( item, property )
	local id = nil
	if property == 'PWikispecies:$1' then
		local siteLinks = item.sitelinks
		if siteLinks then
			local speciesWiki = item.sitelinks.specieswiki
			if speciesWiki then
				id = speciesWiki.title
			end
		end
		return id
	elseif item.claims[property] == nil then
		return id
	end
	--[[ this code picks up deprecated values on wikidata; better to use getBestStatements
	for _, statement in pairs( item.claims[property] ) do
		if statement.mainsnak.datavalue then
			id = statement.mainsnak.datavalue.value
			break
		end
	end
	]]
	local statements = item:getBestStatements(property)[1] 
	if statements and
	   statements.mainsnak and
	   statements.mainsnak.datavalue and
	   statements.mainsnak.datavalue.value
	then
		id = statements.mainsnak.datavalue.value
	end

	return id
end

local function getLink( property, db, val )
	local link, returnVal = '', {}
	
	returnVal.isError = false
	
	if mw.ustring.find( val, '//' ) then
		link = val
	else
		if type(property) == 'number' and property > 0 then
			local entityObject = mw.wikibase.getEntity('P'..property)
			local dataType
			
			if entityObject then dataType = entityObject.datatype
			else returnVal.isError = true end
			
			if dataType == 'external-id' then
				local formatterURL = nil
				if property == 3746 or --Wildflowers of Israel
				   property == 3795 or --Flora of Israel Online
				   property == 5397    --Tierstimmenarchiv
				then
					formatterURL = entityObject:getBestStatements('P1630')[2] --use 2nd formatterURL for English version
				end
				if formatterURL == nil then formatterURL = entityObject:getBestStatements('P1630')[1] end --default to [1]
				if formatterURL then
					if formatterURL.mainsnak.datavalue and formatterURL.mainsnak.datavalue.value then --nil check for ABA
						link = formatterURL.mainsnak.datavalue.value
					end
				end
				if db == 'bow' then -- for birds of world which uses eBird identifier
					link = 'https://birdsoftheworld.org/bow/species/$1'
				end
			elseif dataType == 'url' then
				local subjectItem = entityObject:getBestStatements('P1629')[1]
				if subjectItem then
					local officialWebsite = mw.wikibase.getEntity(subjectItem.mainsnak.datavalue.value.id):getBestStatements('P856')[1]
					if officialWebsite then	link = officialWebsite.mainsnak.datavalue.value end
				end
			elseif dataType == 'string' then
				local formatterURL = entityObject:getBestStatements('P1630')[1]
				if formatterURL then
					link = formatterURL.mainsnak.datavalue.value
				else
					local subjectItem = entityObject:getBestStatements('P1629')[1]
					if subjectItem then
						local officialWebsite = mw.wikibase.getEntity(subjectItem.mainsnak.datavalue.value.id):getBestStatements('P856')[1]
						if officialWebsite then	link = officialWebsite.mainsnak.datavalue.value end
					end
				end
			else
				returnVal.isError = true
			end
		elseif type(property) == 'string' then
			link = property
		end
		
		--local valurl = val
		local valurl = mw.uri.encode( val, 'PATH' )
		valurl = string.gsub (valurl, '%%2F', '/') --escape '/' (e.g. issue with P5354); see wikidata T128078 and https://gerrit.wikimedia.org/r/c/mediawiki/extensions/Wikibase/+/664820/3/lib/includes/PropertyInfoSnakUrlExpander.php
		
		if type(property) == 'number' then
			--doublecheck language for Wildflowers of Israel ID
			if property == 3746 then link = mw.ustring.gsub(link, '/hebrew/', '/english/') end
			--format spaces in PfaF binomials, e.g. "Elaeagnus x ebbingei"
			if property == 4301 then valurl = mw.ustring.gsub(valurl, '%%20', '+') end
		end
		valurl = mw.ustring.gsub(valurl,'%%','%%%%')
		link = mw.ustring.gsub(link, '$1', valurl)
	end
	
	link = mw.ustring.gsub(link, '^[Hh][Tt][Tt][Pp]([Ss]?)://', 'http%1://') --fix wikidata URL
	val = mw.ustring.match(val, '([^=/]*)/?$') --get display name from end of URL
	if mw.ustring.find( link, '//' ) then
		returnVal.text = '['..link..' '..mw.text.encode(mw.uri.decode(val, 'PATH'),'%[%]')..']'
	elseif link == '' then
		returnVal.text = val
	else
		returnVal.text = '<span class="external">[['..link..'|'..val..']]</span>'
	end
	return returnVal
end

local function createRow( id, label, rawValue, link, withUid )
	if link then
		local outStr = '*<span style="white-space:nowrap;">'..label..' <span'
		if withUid then outStr = outStr..' class="uid"' end
		return outStr..'>'..link..'</span></span>\n'
	else
		return '* '..mw.text.tag('span', {class='error'}, 'The identifier '..id..' '..rawValue..' is not valid.')..'\n'
	end
end

local function copyTable(inTable)
	if type(inTable) ~= 'table' then return inTable end
	local outTable = setmetatable({}, getmetatable(inTable))
	for key, value in pairs (inTable) do outTable[copyTable(key)] = copyTable(value) end
	return outTable
end

local p = {}

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

function p.authorityControlTaxon( frame )
	local resolveEntity = require( 'Module:ResolveEntityId' )
	local parentArgs = copyTable(frame:getParent().args)
	local currentTitle = mw.title.getCurrentTitle()
	local currentEntityId = mw.wikibase.getEntityIdForCurrentPage()
	
	local stringArgs = false
	local fromTitleCount, firstRow, rowCount = 1, 0, 0
	local outString, errors = '', ''
	local iFroms = 0 --integer size of tFroms, b/c Lua
	local tFroms = {} --non-sequential table of unique froms
	local tCats = {
		'[[Category:Taxonbars without from parameter]]',
		'[[Category:Taxonbars desynced from Wikidata]]',
		'', -- [3] placeholder for [[Category:Taxonbar pages requiring a Wikidata item]]
		'', -- [4] placeholder for [[Category:Taxonbars on possible non-taxon pages]]
		'', -- [5] placeholder for [[Category:Taxonbars with invalid from parameters]]
		'', -- [6] placeholder for [[Category:Taxonbars with duplicate from parameters]]
		'', -- [7] placeholder for [[Category:Taxonbars with from2 matching article title]]
		'', -- [8] placeholder for [[Category:Taxonbars with from2 matching article title & QID]]
		'', -- [9] placeholder for [[Category:Taxonbars with manual taxon IDs]] --renamed 'using' -> 'with'
		'', --[10] placeholder for [[Category:Taxonbars with manual taxon IDs identical to Wikidata]]
		'', --[11] placeholder for [[Category:Taxonbars with manual taxon IDs differing from Wikidata]]
		'', --[12] placeholder for [[Category:Taxonbars with unknown parameters]]
		'', --[13] placeholder for [[Category:Taxonbars with unnamed parameters]]
		'', --[14] placeholder for [[Category:Taxonbars with multiple manual Wikidata items]] --renamed 'using' -> 'with'
		'', --[15] placeholder for [[Category:Taxonbars with automatically added basionyms]]
		'', --[16] placeholder for [[Category:Taxonbars with automatically added original combinations]]
		'', --[17] placeholder for [[Category:Taxonbars with automatically added monotypic genera]]
		'', --[18] placeholder for [[Category:Taxonbars of monotypic species missing genera]]
		'', --[19] placeholder for [[Category:Taxonbars without primary Wikidata taxon IDs]]
		'', --[20] placeholder for [[Category:Taxonbars without secondary Wikidata taxon IDs]]
		'', --[21] placeholder for [[Category:Taxonbars with 20–24 taxon IDs]]
		'', --[22] placeholder for [[Category:Taxonbars with 25–29 taxon IDs]]
		'', --[23] placeholder for [[Category:Taxonbars with 30–34 taxon IDs]]
		'', --[24] placeholder for [[Category:Taxonbars with 35–39 taxon IDs]]
		'', --[25] placeholder for [[Category:Taxonbars with 40–44 taxon IDs]] --renamed '40+' -> '40–44'
		'', --[26] placeholder for [[Category:Taxonbars with 45+ taxon IDs]] --new
	}
	local acceptableInstanceOf_Strict = {
		['Q16521'] = 'taxon',                      --strict
		['Q310890'] = 'monotypic taxon',           --strict
		['Q98961713'] = 'extinct taxon',           --strict
		['Q2568288'] = 'ichnotaxon',               --strict
		['Q23038290'] = 'fossil taxon',            --strict
		['Q47487597'] = 'monotypic fossil taxon',  --strict
	}
	local acceptableInstanceOf_All = {
		['Q16521'] = 'taxon',                      --strict
		['Q310890'] = 'monotypic taxon',           --strict
		['Q98961713'] = 'extinct taxon',           --strict
		['Q2568288'] = 'ichnotaxon',               --strict
		['Q23038290'] = 'fossil taxon',            --strict
		['Q47487597'] = 'monotypic fossil taxon',  --strict
		['Q42621'] = 'hybrid',                     --lax
		['Q235536'] = 'incertae sedis',            --lax
		['Q713623'] = 'clade',                     --lax
		['Q848328'] = 'serotype',                  --lax
		['Q857968'] = 'candidatus',                --lax
		['Q17487588'] = 'unavailable combination', --lax
	}
	
	--Assess the page's relationship with Wikidata
	local currentItem = nil
	if currentTitle.namespace == 10 then --i.e. Module:Taxonbar/sandbox, Template:Taxonbar/doc, etc.
		if resolveEntity._id(parentArgs['from']) then
			currentItem = mw.wikibase.getEntity(parentArgs['from'])
		end
		if currentItem == nil then
			if resolveEntity._id(parentArgs['from1']) then
				currentItem = mw.wikibase.getEntity(parentArgs['from1'])
			end
		end
	elseif resolveEntity._id(currentEntityId) then
		currentItem = mw.wikibase.getEntity(currentEntityId)
	else --currentEntityId == nil/unresolvable
		tCats[3] = '[[Category:Taxonbar pages requiring a Wikidata item]]'
	end
	if currentItem then
		tCats[4] = '[[Category:Taxonbars on possible non-taxon pages]]' --unset if acceptable found
		for _, instanceOfState in pairs ( currentItem:getBestStatements('P31') ) do --instance of
			local instanceOf = instanceOfState.mainsnak.datavalue.value.id
			if acceptableInstanceOf_All[instanceOf] then
				tCats[4] = ''
				break
			end
		end
	end
	
	--Cleanup args
	for k, v in pairs( frame:getParent().args ) do
		if type(k) == 'string' then
			--make args case insensitive
			local lowerk = mw.ustring.lower(k)
			if isNilOrEmpty( parentArgs[lowerk] ) then
				parentArgs[k] = nil
				parentArgs[lowerk] = v
			end
			--remap abc to abc1
			if mw.ustring.find(lowerk,'%d$') == nil then --if no number at end of param
				if isNilOrEmpty( parentArgs[lowerk..'1'] ) then
					parentArgs[lowerk] = nil
					lowerk = lowerk..'1'
					parentArgs[lowerk] = v
				end
			end
			if v and v ~= '' then
				--remap 'for' to 'title'
				if mw.ustring.sub(lowerk,1,3) == 'for' then
					local forTitle = mw.ustring.gsub(lowerk,'^for','title',1)
					if isNilOrEmpty( parentArgs[forTitle] ) then
						parentArgs[lowerk] = nil
						lowerk = forTitle
						parentArgs[lowerk] = v
					end
				end
				--find highest from or title param
				if mw.ustring.sub(lowerk,1,4) == 'from' then
					local fromNumber = tonumber(mw.ustring.sub(lowerk,5,-1))
					if fromNumber and fromNumber >= fromTitleCount then fromTitleCount = fromNumber end
					--look for duplicate froms while we're here
					if mw.ustring.find(v, '^Q%d') then
						if tFroms[v] then
							tCats[6] = '[[Category:Taxonbars with duplicate from parameters]]'
							tFroms[v] = tFroms[v] + 1
						else
							tFroms[v] = 1
							iFroms = iFroms + 1
						end
						if iFroms == 2 then
							tCats[14] = '[[Category:Taxonbars with multiple manual Wikidata items]]'
						end
					end
				elseif mw.ustring.sub(lowerk,1,5) == 'title' then
					local titleNumber = tonumber(mw.ustring.sub(lowerk,4,-1))
					if titleNumber and titleNumber >= fromTitleCount then fromTitleCount = titleNumber end
				elseif mw.ustring.lower(v) ~= 'no' then
					stringArgs = true
					tCats[9] = '[[Category:Taxonbars with manual taxon IDs]]'
				end
			end
		end --if type(k) == 'string'
	end --for
	
	--Check for unknown parameters
	--create knowns list
	local acceptableArgs = { from = true, } --master list of l/c acceptable args
	for _, d in pairs( conf.databases ) do
		if d[1] ~= 'Wikidata' then --made obsolete by from
			acceptableArgs[mw.ustring.lower(d[1])] = true
		end
	end
	for _, a in pairs( conf.aliases ) do
		acceptableArgs[mw.ustring.lower(a[1])] = true
	end
	--create trimmed parents list
	local baseParentArgs = {} --condensed list of l/c parent args w/o trailing #s
	for k, _ in pairs( parentArgs ) do
		if type(k) == 'string' then
			local lowerk = mw.ustring.lower(k)
			local base = mw.ustring.gsub(lowerk, '[%d]*$', '')
			baseParentArgs[base] = true
		elseif type(k) == 'number' then
			tCats[13] = '[[Category:Taxonbars with unnamed parameters|'..k..']]'
		end
	end
	--compare lists and spit out unknowns
	local unknownParams = {}
	for k, _ in pairs( baseParentArgs ) do
		if acceptableArgs[k] == nil then
			tCats[12] = '[[Category:Taxonbars with unknown parameters|'..k..']]'
			unknownParams[#unknownParams + 1] = k
		end
	end
	--warn if unknown(s) present
	if #unknownParams > 0 then
		local plural = 's'
		local itthem = 'them'
		if #unknownParams == 1 then
			plural = ''
			itthem = 'it'
		end
		errors = errors..require('Module:If preview')._warning({
			mw.ustring.format(
				'Unknown parameter%s <code>%s</code>. Please correct %s or consider adding %s to Wikidata.',
				plural,
				table.concat(unknownParams, '</code>, <code>'),
				itthem,
				itthem
			)
		})
	end
	
	--Append basionym to arg list, if not already provided
	if currentItem then
		local currentBasState = currentItem:getBestStatements('P566')[1] --basionym
		if currentBasState then
			local basionymId = currentBasState.mainsnak.datavalue.value.id
			if basionymId and resolveEntity._id(basionymId) and tFroms[basionymId] == nil then
				--check that basionym is a strict instance of taxon
				local basionymItem = mw.wikibase.getEntity(basionymId)
				if basionymItem then
					for _, instanceOfState in pairs ( basionymItem:getBestStatements('P31') ) do --instance of
						local instanceOf = instanceOfState.mainsnak.datavalue.value.id
						if acceptableInstanceOf_Strict[instanceOf] then
							--housekeeping
							tFroms[basionymId] = 1
							iFroms = iFroms + 1
							fromTitleCount = fromTitleCount + 1
							--append basionym & track
							parentArgs['from'..fromTitleCount] = basionymId
							tCats[15] = '[[Category:Taxonbars with automatically added basionyms]]'
							break
	end	end	end	end	end	end
	
	--Append original combination to arg list, if not already provided
	if currentItem then
		local currentOCState = currentItem:getBestStatements('P1403')[1] --original combination
		if currentOCState then
			local orcoId = currentOCState.mainsnak.datavalue.value.id
			if orcoId and resolveEntity._id(orcoId) and tFroms[orcoId] == nil then
				--check that orco is a strict instance of taxon
				local orcoItem = mw.wikibase.getEntity(orcoId)
				if orcoItem then
					for _, instanceOfState in pairs ( orcoItem:getBestStatements('P31') ) do --instance of
						local instanceOf = instanceOfState.mainsnak.datavalue.value.id
						if acceptableInstanceOf_Strict[instanceOf] then
							--housekeeping
							tFroms[orcoId] = 1
							iFroms = iFroms + 1
							fromTitleCount = fromTitleCount + 1
							--append orco & track
							parentArgs['from'..fromTitleCount] = orcoId
							tCats[16] = '[[Category:Taxonbars with automatically added original combinations]]'
							break
	end	end	end	end	end	end
	
	--Append monotypic genus/species to arg list of monotypic species/genus, if not already provided
	if currentItem then
		for _, instanceOfState in pairs ( currentItem:getBestStatements('P31') ) do --instance of
			local taxonRank = nil
			local parentItem = nil
			local parentTaxon = nil
			local parentTaxonRank = nil
			local parentMonoGenus = nil --holy grail/tbd
			local instanceOf = instanceOfState.mainsnak.datavalue.value.id
			if instanceOf and (instanceOf == 'Q310890' or instanceOf == 'Q47487597') then --monotypic/fossil taxon
				local taxonRankState = currentItem:getBestStatements('P105')[1] --taxon rank
				if taxonRankState then taxonRank = taxonRankState.mainsnak.datavalue.value.id end
				
				if taxonRank and taxonRank == 'Q7432' then --species
					--is monotypic species; add genus
					local parentTaxonState = currentItem:getBestStatements('P171')[1] --parent taxon
					if parentTaxonState then parentTaxon = parentTaxonState.mainsnak.datavalue.value.id end
					--confirm parent taxon rank == genus & monotypic
					if parentTaxon and resolveEntity._id(parentTaxon) then
						parentItem = mw.wikibase.getEntity(parentTaxon)
						if parentItem then
							local parentTaxonRankState = parentItem:getBestStatements('P105')[1] --taxon rank
							if parentTaxonRankState then parentTaxonRank = parentTaxonRankState.mainsnak.datavalue.value.id end
							if parentTaxonRank and parentTaxonRank == 'Q34740' then --parent == genus
								for _, parentInstanceOfState in pairs ( parentItem:getBestStatements('P31') ) do --instance of
									local parentInstanceOf = parentInstanceOfState.mainsnak.datavalue.value.id 
									if parentInstanceOf and
									  (parentInstanceOf == 'Q310890' or parentInstanceOf == 'Q47487597') then --monotypic/fossil taxon
										parentMonoGenus = parentTaxon --confirmed
										break
									end
								end
								if parentMonoGenus and tFroms[parentMonoGenus] == nil then
									--housekeeping
									tFroms[parentMonoGenus] = 1
									iFroms = iFroms + 1
									fromTitleCount = fromTitleCount + 1
									--append monotypic genus & track
									parentArgs['from'..fromTitleCount] = parentMonoGenus
									tCats[17] = '[[Category:Taxonbars with automatically added monotypic genera]]'
									break
								end
							end
						end
					end
					if parentMonoGenus == nil or tFroms[parentMonoGenus] == nil then
						tCats[18] = '[[Category:Taxonbars of monotypic species missing genera]]'
						break
					end
				elseif taxonRank and taxonRank == 'Q34740' then --genus
					--TODO:
					--is monotypic genus; add species (no way to easily find these (yet?))
					--...
				end
				
			end
		end --for
	end --if currentItem
	
	--Setup navbox
	local navboxParams = {
		name  = 'Taxonbar',
		bodyclass = 'hlist',
		listclass = '',
		groupstyle = 'text-align: left;',
	}
	
	for f = 1, fromTitleCount, 1
	do
		local elements, title = {}, nil
		--cleanup parameters
		if parentArgs['from'..f] == '' then parentArgs['from'..f] = nil end
		if parentArgs['title'..f] == '' then parentArgs['title'..f] = nil end
		--remap aliases
		for _, a in pairs( conf.aliases ) do
			local alias, name = mw.ustring.lower(a[1]), mw.ustring.lower(a[2])
			if parentArgs[alias..f] and parentArgs[name..f] == nil then
				parentArgs[name..f] = parentArgs[alias..f]
				parentArgs[alias..f] = nil
			end
		end
		--Fetch Wikidata item
		local from = resolveEntity._id(parentArgs['from'..f])
		local item = mw.wikibase.getEntity(from)
		local label = nil
		if type(item) == 'table' then
			local statements = item:getBestStatements('P225')[1] --taxon name
			if statements then
				local datavalue = statements.mainsnak.datavalue
				if datavalue then
					label = datavalue.value
				end
			end
			label = label or item:getLabel()
		else
			if parentArgs['from'..f] then
				tCats[1] = ''
				tCats[5] = '[[Category:Taxonbars with invalid from parameters]]'
				errors = errors..mw.text.tag('strong', {class='error'}, 'Error: "'..
				         parentArgs['from'..f]..'" is not a valid Wikidata entity ID.<br />')				
			end
		end
		if label and label ~= '' then
			title = mw.title.new(label)
		end
		if title == nil and parentArgs['title'..f] then
			title = mw.title.new(parentArgs['title'..f])
		end
		if title == nil and f == 1 then
			title = currentTitle
		end
		
		if title then
			if isNilOrEmpty( parentArgs['wikidata'..f] ) and 
			   (title.namespace == 0) then
				if parentArgs['from'..f] then
					parentArgs['wikidata'..f] = parentArgs['from'..f]
				elseif item then
					parentArgs['wikidata'..f] = item.id
				end
			end
			if title.namespace == 0 or stringArgs then --only in mainspace or if manual overrides exist
				local sourceCount = 0
				for _, params in pairs( conf.databases ) do
					params[1] = mw.ustring.lower(params[1])
					local propId = params[3]
					--Wikidata fallback if requested
					if (item and item.claims) and
					   (type(propId) == 'string' or (type(propId) == 'number' and propId > 0)) then
						local wikidataId = getIdFromWikidata( item, 'P'..propId )
						local v = parentArgs[params[1]..f]
						if wikidataId then
							if isNilOrEmpty(v) then
								parentArgs[params[1]..f] = wikidataId
							else
								if v and v ~= 'no' and v ~= wikidataId then
									tCats[11] = '[[Category:Taxonbars with manual taxon IDs differing from Wikidata]]'
								elseif v and v == wikidataId then
									tCats[10] = '[[Category:Taxonbars with manual taxon IDs identical to Wikidata]]'
								end
							end
						end
					end
					if (item and item.claims) and
					   ( (type(propId) == 'number' and propId < 0)) then
						local wikidataId = getIdFromWikidata( item, 'P'..-propId )
						--mw.addWarning ("propId=" .. tostring(propId) .. "; wikidata=" .. tostring(wikidataId))
						local v = parentArgs[params[1]..f]
						if v == 'yes' then
					    	if wikidataId then
								parentArgs[params[1]..f] = wikidataId
							else
								parentArgs[params[1]..f] = nil  -- don't want to use 'yes' as id
							end
						end
					end
					local val = parentArgs[params[1]..f]
					if val and val ~= '' and mw.ustring.lower(val) ~= 'no' then
						if type(propId) == 'number' then
							if propId < 0 then propId = -propId end --allow link
							if propId > 0 then --link
								table.insert( elements, createRow( params[1], params[2]..':', val, getLink( propId, params[1], val ).text, true ) )
							else --propId == 0; no link
								table.insert( elements, createRow( params[1], params[2]..':', val, val, true ) )
							end
						else
							table.insert( elements, createRow( params[1], params[2]..':', val, getLink( propId, params[1], val ).text, true ) )
						end
						if params[1] ~= 'wikidata' and params[1] ~= 'wikispecies' then
							sourceCount = sourceCount + 1
						end
					end
				end --for
				
				if     sourceCount >= 45 then tCats[26] = '[[Category:Taxonbars with 45+ taxon IDs]]'
				elseif sourceCount >= 40 then tCats[25] = '[[Category:Taxonbars with 40–44 taxon IDs]]' --endashes
				elseif sourceCount >= 35 then tCats[24] = '[[Category:Taxonbars with 35–39 taxon IDs]]'
				elseif sourceCount >= 30 then tCats[23] = '[[Category:Taxonbars with 30–34 taxon IDs]]'
				elseif sourceCount >= 25 then tCats[22] = '[[Category:Taxonbars with 25–29 taxon IDs]]'
				elseif sourceCount >= 20 then tCats[21] = '[[Category:Taxonbars with 20–24 taxon IDs]]'
				end
				
				--Generate navbox title
				if sourceCount > 0 then
					rowCount = rowCount + 1
					if firstRow == 0 then firstRow = f end
					--set title from wikidata if it doesn't exist
					if isNilOrEmpty( parentArgs['title'..f] ) then
						parentArgs['noTitle'..f] = true
						parentArgs['title'..f] = title.text
					end
					--if it exists now, set row heading to title
					if not isNilOrEmpty( parentArgs['title'..f] ) then
						navboxParams['group'..f] = TaxonItalics.italicizeTaxonName(parentArgs['title'..f], false)
					else
						navboxParams['group'..f] = ''
					end
					navboxParams['list'..f] = table.concat( elements )
				elseif currentEntityId and (currentEntityId == parentArgs['from'..f] or fromTitleCount == 1) then
					tCats[19] = '[[Category:Taxonbars without primary Wikidata taxon IDs]]'
				else
					tCats[20] = '[[Category:Taxonbars without secondary Wikidata taxon IDs]]'
				end
				
				--Categorize
				if not isNilOrEmpty( parentArgs['from'..f] ) then
					tCats[1] = '' --blank "missing from" if 'from' exists
					if parentArgs['from'..f] == currentEntityId then
						tCats[2] = '' --blank "desynced" if 'from' matches current page
					end
				end
				if tCats[1] ~= '' then
					tCats[2] = '' --cannot be "desynced" if no 'from' params
				end
			end --if title.namespace == 0 or stringArgs
		end --if title
	end --for f = 1, fromTitleCount, 1
	
	if rowCount > 0 then
		local Navbox = require('Module:Navbox')
		if rowCount > 1 then
			--remove duplicates and don't bother moving page title to top
			local rowIDs = {}
			for f = 1,fromTitleCount,1
			do
				if not isNilOrEmpty( parentArgs['title'..f] ) then
					if rowIDs[parentArgs['wikidata'..f]] then --remove duplicate
						navboxParams['group'..f] = nil
						navboxParams['list'..f] = nil
					else
						rowIDs[parentArgs['wikidata'..f]] = true
					end
				end
			end
			if parentArgs['title'..2] and parentArgs['title'..2] == currentTitle.text then
				if currentItem and parentArgs['from'..2] == currentItem['id'] then
					tCats[8] = '[[Category:Taxonbars with from2 matching article title & QID]]'
				else
					tCats[7] = '[[Category:Taxonbars with from2 matching article title]]'
				end
			end
			--adjust navbox for number of rows
			navboxParams['title'] = '[[:en:Help:Taxon identifiers|உயிரின வகைப்பாட்டு<br/>இனங்காட்டிகள்]]'
			if rowCount >= 4 then
				navboxParams['navbar'] = 'plain'
			else
				navboxParams['state'] = 'off'
				navboxParams['navbar'] = 'off'
			end
		elseif parentArgs['noTitle'..firstRow] then
			navboxParams['group'..firstRow] = '[[:en:Help:Taxon identifiers|உயிரின வகைப்பாட்டு<br/>இனங்காட்டிகள்]]'
		else
			navboxParams['group'..firstRow] = '[[:en:Help:Taxon identifiers|உயிரின வகைப்பாட்டு<br/>இனங்காட்டிகள்]]<br />'..navboxParams['group'..firstRow]
		end
		
		--return navbox
		outString = Navbox._navbox(navboxParams)
	end --if rowCount > 0
	
	--Add categories
	if string.sub(currentTitle.subpageText,1,9) == 'testcases' then parentArgs['demo'] = true end
	if not isNilOrEmpty( parentArgs['demo'] ) then
		outString = outString..mw.text.nowiki(table.concat(tCats))..'<br />'
	elseif currentTitle.namespace == 0 then
		outString = outString..table.concat(tCats)
	end
	
	return outString..errors
end

return p
"https://ta.wikipedia.org/w/index.php?title=Module:Taxonbar&oldid=3705087" இலிருந்து மீள்விக்கப்பட்டது