require('Module:No globals')  local conf = require( 'Module:Taxonbar/conf' ) --configuration module local TaxonItalics = require( 'Module:TaxonItalics' ) --use a function from Module:TaxonItalics to italicize a taxon name  --========================================================================== --                             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 	for _, statement in pairs( item.claims[property] ) do 		if statement.mainsnak.datavalue then 			id = statement.mainsnak.datavalue.value 			break 		end 	end 	return id end  local function getLink( property, 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 			elseif dataType == 'url' then 				local subjectItem = entityObject:getBestStatements('P1629')[1] 				if subjectItem then 					local officialWebsite = mw.wikibase.getEntity(subjectItem.mainsnak.datavalue.value.id):getBestStatements('P856')[1] 					if officialWebsite then	link = officialWebsite.mainsnak.datavalue.value end 				end 			elseif dataType == 'string' then 				local formatterURL = entityObject:getBestStatements('P1630')[1] 				if formatterURL then 					link = formatterURL.mainsnak.datavalue.value 				else 					local subjectItem = entityObject:getBestStatements('P1629')[1] 					if subjectItem then 						local officialWebsite = mw.wikibase.getEntity(subjectItem.mainsnak.datavalue.value.id):getBestStatements('P856')[1] 						if officialWebsite then	link = officialWebsite.mainsnak.datavalue.value end 					end 				end 			else 				returnVal.isError = true 			end 		elseif type(property) == 'string' then 			link = property 		end 		 		local valurl = val 		if mw.ustring.find( link, 'antweb.org' ) then valurl = mw.ustring.gsub(valurl, ' ', '%%20') end 		if type(property) == 'number' then 			--doublecheck language for Wildflowers of Israel ID 			if property == 3746 then link = mw.ustring.gsub(link, '/hebrew/', '/english/') end 			--format spaces in PfaF binomials, e.g. "Elaeagnus x ebbingei" 			if property == 4301 then valurl = mw.ustring.gsub(valurl, ' ', '+') end 			--format spaces in FoAO2 binomials, e.g. "Scaevola basedowii" 			if property == 6756 then valurl = mw.ustring.gsub(valurl, ' ', '+') end 		end 		valurl = mw.ustring.gsub(valurl,'%%','%%%%') 		link = mw.ustring.gsub(link, '$1', valurl) 	end 	 	link = mw.ustring.gsub(link, '^[Hh][Tt][Tt][Pp]([Ss]?)://', '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 = ''..val..'' 	end 	return returnVal end  local function createRow( id, label, rawValue, link, withUid ) 	if link then 		local outStr = '*' .. label .. ' <span' 		if withUid then outStr = outStr..' class="uid"' end 		return outStr..'>' .. link .. '</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 tFroms = {} --non-sequential table of unique froms 	local iFroms = 0 --integer size of tFroms, b/c Lua 	local categories = { 		'Category:Taxonbars without from parameter', 		'Category:Taxonbars desynced from Wikidata', 		, -- [3] placeholder for Category:Taxonbars using multiple manual Wikidata items 		, -- [4] placeholder for Category:Taxonbars with invalid from parameters 		, -- [5] placeholder for Category:Taxonbars using manual taxon IDs 		, -- [6] placeholder for Category:Taxonbar pages requiring a Wikidata item 		, -- [7] placeholder for Category:Taxonbars without primary Wikidata taxon IDs 		, -- [8] placeholder for Category:Taxonbars without secondary Wikidata taxon IDs 		, -- [9] placeholder for Category:Taxonbars with duplicate from parameters 		, --[10] placeholder for Category:Taxonbars with manual taxon IDs differing from Wikidata 		, --[11] placeholder for Category:Taxonbars with manual taxon IDs identical to Wikidata 		, --[12] placeholder for Category:Taxonbars on possible non-taxon pages 		, --[13] placeholder for Category:Taxonbars with automatically added basionyms 		, --[14] placeholder for Category:Taxonbars with automatically added original combinations 		, --[15] placeholder for Category:Taxonbars with automatically added monotypic genera 		, --[16] placeholder for Category:Taxonbars of monotypic species missing genera 		, --[17] placeholder for Category:Taxonbars with unknown parameters 		, --[18] placeholder for Category:Taxonbars with 20–24 taxon IDs 		, --[19] placeholder for Category:Taxonbars with 25–29 taxon IDs 		, --[20] placeholder for Category:Taxonbars with 30–34 taxon IDs 		, --[21] placeholder for Category:Taxonbars with 35–39 taxon IDs 		, --[22] placeholder for Category:Taxonbars with 40+ taxon IDs 	} 	local acceptableInstanceOf_Strict = { 	   ['Q16521'] = 'taxon',                      --strict 	   ['Q310890'] = 'monotypic taxon',           --strict 	   ['Q2568288'] = 'ichnotaxon',               --strict 	   ['Q23038290'] = 'fossil taxon',            --strict 	   ['Q47487597'] = 'monotypic fossil taxon',  --strict 	} 	local acceptableInstanceOf_All = { 	   ['Q16521'] = 'taxon',                      --strict 	   ['Q310890'] = 'monotypic 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 		categories[6] = 'Category:Taxonbar pages requiring a Wikidata item' 	end 	if currentItem then 		categories[12] = '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 				categories[12] =  				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 							categories[9] = 'Category:Taxonbars with duplicate from parameters' 							tFroms[v] = tFroms[v] + 1 						else 							tFroms[v] = 1 							iFroms = iFroms + 1 						end 						if iFroms == 2 then 							categories[3] = 'Category:Taxonbars using 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 					categories[5] = 'Category:Taxonbars using manual taxon IDs' 				end 			end 		end 	end 	 	--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, v in pairs( parentArgs ) do 		if type(k) == 'string' then --ignore unnamed params, which have keys of type 'number' 			local lowerk = mw.ustring.lower(k) 			local base = mw.ustring.gsub(lowerk, '[%d]*$', ) 			baseParentArgs[base] = true 		end 	end 	--compare lists and spit out unknowns 	local unknownParams = {} 	for k, v in pairs( baseParentArgs ) do 		if acceptableArgs[k] == nil then 			categories[17] = '' .. k ..'' 			unknownParams[#unknownParams + 1] = k 		end 	end 	--warn if unknown(s) present 	if #unknownParams > 0 then 		local plural = nil 		local itthem = nil 		if #unknownParams == 1 then 			plural = 			itthem = 'it' 		else 			plural = 's' 			itthem = 'them' 		end 		if frame:preprocess( '' ) ==  then 			errors = errors..''.. 				     'Warning: unknown parameter'..plural..' '..table.concat(unknownParams, ', ')..'.'.. 				     'Please correct '..itthem..' or consider adding '..itthem..' to Wikidata.'.. 				     'This message is only shown in preview.' 		end 	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 							categories[13] = '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 							categories[14] = '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 									categories[15] = 'Category:Taxonbars with automatically added monotypic genera' 									break 								end 							end 						end 					end 					if parentMonoGenus == nil or tFroms[parentMonoGenus] == nil then 						categories[16] = 'Category:Taxonbars of monotypic species missing genera' 						break 					end 				elseif taxonRank and taxonRank == 'Q34740' then --genus 					--is monotypic genus; add species 					--... 				end 				 			end 		end 	end --if currentItem 	 	--Setup navbox 	local navboxParams = { 		name  = '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 				categories[1] =  				categories[4] = '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.')				 			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 									categories[10] = 'Category:Taxonbars with manual taxon IDs differing from Wikidata' 								elseif v and v == wikidataId then 									categories[11] = 'Category:Taxonbars with manual taxon IDs identical to Wikidata' 								end 							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, 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, val ).text, true ) ) 						end 						if params[1] ~= 'wikidata' and params[1] ~= 'wikispecies' then 							sourceCount = sourceCount + 1 						end 					end 				end 				 				if     sourceCount >= 40 then categories[22] = 'Category:Taxonbars with 40+ taxon IDs' 				elseif sourceCount >= 35 then categories[21] = 'Category:Taxonbars with 35–39 taxon IDs' --endashes 				elseif sourceCount >= 30 then categories[20] = 'Category:Taxonbars with 30–34 taxon IDs' 				elseif sourceCount >= 25 then categories[19] = 'Category:Taxonbars with 25–29 taxon IDs' 				elseif sourceCount >= 20 then categories[18] = '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 					categories[7] = 'Category:Taxonbars without primary Wikidata taxon IDs' 				else 					categories[8] = 'Category:Taxonbars without secondary Wikidata taxon IDs' 				end 				 				--Categorize 				if not isNilOrEmpty( parentArgs['from'..f] ) then 					--blank "missing from" if 'from' exists 					categories[1] =  					--blank "desynced" if 'from' matches current page 					if parentArgs['from'..f] == currentEntityId then categories[2] =  end 				end 					--cannot be "desynced" if no 'from' params 				if categories[1] ~=  then categories[2] =  end 			end 		end 	end --for f = 1, fromTitleCount, 1 	 	if rowCount > 0 then 		local Navbox = require('Module:Navbox') 		if rowCount > 1 then 			--remove duplicates and move 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 						if f > firstRow and (parentArgs['title'..f] == currentTitle.text or  						   parentArgs['wikidata'..f] == currentEntityId) then --move item linked to page to top 							if navboxParams['group'..f] and  							   navboxParams['group'..f] ~=  and  							   navboxParams['list'..f] and  							   navboxParams['list'..f] ~= '' then 								local tempGroup, tempList = navboxParams['group'..f], navboxParams['list'..f] 								navboxParams['group'..f], navboxParams['list'..f] = navboxParams['group'..firstRow], navboxParams['list'..firstRow] 								navboxParams['group'..firstRow], navboxParams['list'..firstRow] = tempGroup, tempList 							end 						end 					end 				end 			end 			--adjust navbox for number of rows 			navboxParams['title'] = 'ট্যাক্সন শনাক্তকারী' 			if rowCount >= 4 then 				navboxParams['navbar'] = 'plain' 			else 				navboxParams['state'] = 'off' 				navboxParams['navbar'] = 'off' 			end 		elseif parentArgs['noTitle'..firstRow] then 			navboxParams['group'..firstRow] = 'ট্যাক্সন শনাক্তকারী' 		else 			navboxParams['group'..firstRow] = 'ট্যাক্সন শনাক্তকারী' .. 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(categories)) .. '' 	elseif currentTitle.namespace == 0 then 		outString = outString .. table.concat(categories) 	end 	 	return outString .. errors end  return p