Module:Taxonbar/sandbox

require('strict')local conf = require( 'Module:Taxonbar/conf' ) --configuration modulelocal TaxonItalics = require( 'Module:TaxonItalics' ) --use a function to conditionally italicize taxon names--[[==========================================================================]]--[[                             Local functions                              ]]--[[==========================================================================]]local function isNilOrEmpty( thing )if thing == nil or thing == '' thenreturn trueendreturn nilendlocal function getIdFromWikidata( item, property )local id = nilif property == 'PWikispecies:$1' thenlocal siteLinks = item.sitelinksif siteLinks thenlocal speciesWiki = item.sitelinks.specieswikiif speciesWiki thenid = speciesWiki.titleendendreturn idelseif item.claims[property] == nil thenreturn idend--[[ this code picks up deprecated values on wikidata; better to use getBestStatementsfor _, statement in pairs( item.claims[property] ) doif statement.mainsnak.datavalue thenid = statement.mainsnak.datavalue.valuebreakendend]]local statements = item:getBestStatements(property)[1] if statements and   statements.mainsnak and   statements.mainsnak.datavalue and   statements.mainsnak.datavalue.valuethenid = statements.mainsnak.datavalue.valueendreturn idendlocal function getLink( property, db, val )local link, returnVal = '', {}returnVal.isError = falseif mw.ustring.find( val, '//' ) thenlink = valelseif type(property) == 'number' and property > 0 thenlocal entityObject = mw.wikibase.getEntity('P'..property)local dataTypeif entityObject then dataType = entityObject.datatypeelse returnVal.isError = true endif dataType == 'external-id' thenlocal formatterURL = nilif property == 3746 or --Wildflowers of Israel   property == 3795 or --Flora of Israel Online   property == 5397    --TierstimmenarchivthenformatterURL = entityObject:getBestStatements('P1630')[2] --use 2nd formatterURL for English versionendif formatterURL == nil then formatterURL = entityObject:getBestStatements('P1630')[1] end --default to [1]if formatterURL thenif formatterURL.mainsnak.datavalue and formatterURL.mainsnak.datavalue.value then --nil check for ABAlink = formatterURL.mainsnak.datavalue.valueendendif db == 'bow' then -- for birds of world which uses eBird identifierlink = 'https://birdsoftheworld.org/bow/species/$1'elseif db == 'fossilworks' then link = 'https://paleobiodb.org/classic/basicTaxonInfo?taxon_no=$1'endelseif dataType == 'url' thenlocal subjectItem = entityObject:getBestStatements('P1629')[1]if subjectItem thenlocal officialWebsite = mw.wikibase.getEntity(subjectItem.mainsnak.datavalue.value.id):getBestStatements('P856')[1]if officialWebsite thenlink = officialWebsite.mainsnak.datavalue.value endendelseif dataType == 'string' thenlocal formatterURL = entityObject:getBestStatements('P1630')[1]if formatterURL thenlink = formatterURL.mainsnak.datavalue.valueelselocal subjectItem = entityObject:getBestStatements('P1629')[1]if subjectItem thenlocal officialWebsite = mw.wikibase.getEntity(subjectItem.mainsnak.datavalue.value.id):getBestStatements('P856')[1]if officialWebsite thenlink = officialWebsite.mainsnak.datavalue.value endendendelsereturnVal.isError = trueendelseif type(property) == 'string' thenlink = propertyend--local valurl = vallocal 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.phpif type(property) == 'number' then--doublecheck language for Wildflowers of Israel IDif 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', '+') endendvalurl = mw.ustring.gsub(valurl,'%%','%%%%')link = mw.ustring.gsub(link, '$1', valurl)endlink = mw.ustring.gsub(link, '^[Hh][Tt][Tt][Pp]([Ss]?)&#58;//', 'http%1://') --fix wikidata URLval = mw.ustring.match(val, '([^=/]*)/?$') --get display name from end of URLif mw.ustring.find( link, '//' ) thenreturnVal.text = '['..link..' '..mw.text.encode(mw.uri.decode(val, 'PATH'),'%[%]')..']'elseif link == '' thenreturnVal.text = valelsereturnVal.text = '<span class="external">[['..link..'|'..val..']]</span>'endreturn returnValendlocal function createRow( id, label, rawValue, link, withUid )if link thenlocal outStr = '*<span style="white-space:nowrap;">'..label..' <span'if withUid then outStr = outStr..' class="uid"' endreturn outStr..'>'..link..'</span></span>\n'elsereturn '* '..mw.text.tag('span', {class='error'}, 'The identifier '..id..' '..rawValue..' is not valid.')..'\n'endendlocal function copyTable(inTable)if type(inTable) ~= 'table' then return inTable endlocal outTable = setmetatable({}, getmetatable(inTable))for key, value in pairs (inTable) do outTable[copyTable(key)] = copyTable(value) endreturn outTableendlocal p = {}--[[==========================================================================]]--[[                                   Main                                   ]]--[[==========================================================================]]function p.authorityControlTaxon( frame )local resolveEntity = require( 'Module:ResolveEntityId' )local whitelist = require( 'Module:Taxonbar/whitelist' ).whitelist --to create acceptableInstanceOf_Strict & acceptableInstanceOf_Alllocal parentArgs = copyTable(frame:getParent().args)local currentTitle = mw.title.getCurrentTitle()local currentEntityId = mw.wikibase.getEntityIdForCurrentPage()local stringArgs = falselocal fromTitleCount, firstRow, rowCount = 1, 0, 0local outString, errors = '', ''local iFroms = 0 --integer size of tFroms, b/c Lualocal tFroms = {} --non-sequential table of unique fromslocal 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]]'', --[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]]'', --[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 species]]'', --[18] placeholder for [[Category:Taxonbars with automatically added monotypic genera]]'', --[19] placeholder for [[Category:Taxonbars of monotypic species missing genera]]'', --[20] placeholder for [[Category:Taxonbars of monotypic genera missing species]]'', --[21] placeholder for [[Category:Taxonbars without primary Wikidata taxon IDs]]'', --[22] placeholder for [[Category:Taxonbars without secondary Wikidata taxon IDs]]'', --[23] placeholder for [[Category:Taxonbars with 20–24 taxon IDs]]'', --[24] placeholder for [[Category:Taxonbars with 25–29 taxon IDs]]'', --[25] placeholder for [[Category:Taxonbars with 30–34 taxon IDs]]'', --[26] placeholder for [[Category:Taxonbars with 35–39 taxon IDs]]'', --[27] placeholder for [[Category:Taxonbars with 40–44 taxon IDs]]'', --[28] placeholder for [[Category:Taxonbars with 45+ taxon IDs]]}local acceptableInstanceOf_Strict = whitelist{ args = { 'strict' } }local acceptableInstanceOf_All = whitelist{ args = { 'all' } }--Assess the page's relationship with Wikidatalocal currentItem = nilif currentTitle.namespace == 10 then --i.e. Module:Taxonbar/sandbox, Template:Taxonbar/doc, etc.if resolveEntity._id(parentArgs['from']) thencurrentItem = mw.wikibase.getEntity(parentArgs['from'])endif currentItem == nil thenif resolveEntity._id(parentArgs['from1']) thencurrentItem = mw.wikibase.getEntity(parentArgs['from1'])endendelseif resolveEntity._id(currentEntityId) thencurrentItem = mw.wikibase.getEntity(currentEntityId)else --currentEntityId == nil/unresolvabletCats[3] = '[[Category:Taxonbar pages requiring a Wikidata item]]'endif currentItem thentCats[4] = '[[Category:Taxonbars on possible non-taxon pages]]' --unset if acceptable foundfor _, instanceOfState in pairs ( currentItem:getBestStatements('P31') ) do --instance oflocal instanceOf = instanceOfState.mainsnak.datavalue.value.idif acceptableInstanceOf_All[instanceOf] thentCats[4] = ''breakendendend--Cleanup argsfor k, v in pairs( frame:getParent().args ) doif type(k) == 'string' then--make args case insensitivelocal lowerk = mw.ustring.lower(k)if isNilOrEmpty( parentArgs[lowerk] ) thenparentArgs[k] = nilparentArgs[lowerk] = vend--remap abc to abc1if mw.ustring.find(lowerk,'%d$') == nil then --if no number at end of paramif isNilOrEmpty( parentArgs[lowerk..'1'] ) thenparentArgs[lowerk] = nillowerk = lowerk..'1'parentArgs[lowerk] = vendendif v and v ~= '' then--remap 'for' to 'title'if mw.ustring.sub(lowerk,1,3) == 'for' thenlocal forTitle = mw.ustring.gsub(lowerk,'^for','title',1)if isNilOrEmpty( parentArgs[forTitle] ) thenparentArgs[lowerk] = nillowerk = forTitleparentArgs[lowerk] = vendend--find highest from or title paramif mw.ustring.sub(lowerk,1,4) == 'from' thenlocal fromNumber = tonumber(mw.ustring.sub(lowerk,5,-1))if fromNumber and fromNumber >= fromTitleCount then fromTitleCount = fromNumber end--look for duplicate froms while we're hereif mw.ustring.find(v, '^Q%d') thenif tFroms[v] thentCats[6] = '[[Category:Taxonbars with duplicate from parameters]]'tFroms[v] = tFroms[v] + 1elsetFroms[v] = 1iFroms = iFroms + 1endif iFroms == 2 thentCats[14] = '[[Category:Taxonbars with multiple manual Wikidata items]]'endendelseif mw.ustring.sub(lowerk,1,5) == 'title' thenlocal titleNumber = tonumber(mw.ustring.sub(lowerk,4,-1))if titleNumber and titleNumber >= fromTitleCount then fromTitleCount = titleNumber endelseif mw.ustring.lower(v) ~= 'no' and  mw.ustring.lower(v) ~= 'yes' thenstringArgs = truetCats[9] = '[[Category:Taxonbars with manual taxon IDs]]'endendend --if type(k) == 'string'end --for--Check for unknown parameters--create knowns list--local acceptableArgs = { from = true, } --master list of l/c acceptable argslocal acceptableArgs = { from = true, format=true} --master list of l/c acceptable args  (adding format for alternative outputs)for _, d in pairs( conf.databases ) doif d[1] ~= 'Wikidata' then --made obsolete by fromacceptableArgs[mw.ustring.lower(d[1])] = trueendendfor _, a in pairs( conf.aliases ) doacceptableArgs[mw.ustring.lower(a[1])] = trueend--create trimmed parents listlocal baseParentArgs = {} --condensed list of l/c parent args w/o trailing #sfor k, _ in pairs( parentArgs ) doif type(k) == 'string' thenlocal lowerk = mw.ustring.lower(k)local base = mw.ustring.gsub(lowerk, '[%d]*$', '')baseParentArgs[base] = trueelseif type(k) == 'number' thentCats[13] = '[[Category:Taxonbars with unnamed parameters|'..k..']]'endend--compare lists and spit out unknownslocal unknownParams = {}for k, _ in pairs( baseParentArgs ) doif acceptableArgs[k] == nil thentCats[12] = '[[Category:Taxonbars with unknown parameters|'..k..']]'unknownParams[#unknownParams + 1] = kendend--warn if unknown(s) presentif #unknownParams > 0 thenlocal plural = 's'local itthem = 'them'if #unknownParams == 1 thenplural = ''itthem = 'it'enderrors = 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 providedif currentItem thenlocal currentBasState = currentItem:getBestStatements('P566')[1] --basionymif currentBasState thenlocal basionymId = currentBasState.mainsnak.datavalue.value.idif basionymId and resolveEntity._id(basionymId) and tFroms[basionymId] == nil then--check that basionym is a strict instance of taxonlocal basionymItem = mw.wikibase.getEntity(basionymId)if basionymItem thenfor _, instanceOfState in pairs ( basionymItem:getBestStatements('P31') ) do --instance oflocal instanceOf = instanceOfState.mainsnak.datavalue.value.idif acceptableInstanceOf_Strict[instanceOf] then--housekeepingtFroms[basionymId] = 1iFroms = iFroms + 1fromTitleCount = fromTitleCount + 1--append basionym & trackparentArgs['from'..fromTitleCount] = basionymIdtCats[15] = '[[Category:Taxonbars with automatically added basionyms]]'breakendendendendendend--Append original combination to arg list, if not already providedif currentItem thenlocal currentOCState = currentItem:getBestStatements('P1403')[1] --original combinationif currentOCState thenlocal orcoId = currentOCState.mainsnak.datavalue.value.idif orcoId and resolveEntity._id(orcoId) and tFroms[orcoId] == nil then--check that orco is a strict instance of taxonlocal orcoItem = mw.wikibase.getEntity(orcoId)if orcoItem thenfor _, instanceOfState in pairs ( orcoItem:getBestStatements('P31') ) do --instance oflocal instanceOf = instanceOfState.mainsnak.datavalue.value.idif acceptableInstanceOf_Strict[instanceOf] then--housekeepingtFroms[orcoId] = 1iFroms = iFroms + 1fromTitleCount = fromTitleCount + 1--append orco & trackparentArgs['from'..fromTitleCount] = orcoIdtCats[16] = '[[Category:Taxonbars with automatically added original combinations]]'breakendendendendendend--Append monotypic genus/species to arg list of monotypic species/genus, if not already providedif currentItem thenfor _, instanceOfState in pairs ( currentItem:getBestStatements('P31') ) do --instance oflocal taxonRank = nillocal parentItem = nillocal parentTaxon = nillocal parentTaxonRank = nillocal parentMonoGenus = nil --holy grail/tbdlocal childItem = nillocal childTaxon = nillocal childTaxonRank = nillocal childMonoSpecies = nil --holy grail/tbdlocal instanceOf = instanceOfState.mainsnak.datavalue.value.idif instanceOf and (instanceOf == 'Q310890' or instanceOf == 'Q47487597') then --monotypic/fossil taxonlocal taxonRankState = currentItem:getBestStatements('P105')[1] --taxon rankif taxonRankState then taxonRank = taxonRankState.mainsnak.datavalue.value.id endif taxonRank and taxonRank == 'Q7432' then --species--is monotypic species; add genuslocal parentTaxonState = currentItem:getBestStatements('P171')[1] --parent taxonif parentTaxonState then parentTaxon = parentTaxonState.mainsnak.datavalue.value.id end--confirm parent taxon rank == genus & monotypicif parentTaxon and resolveEntity._id(parentTaxon) thenparentItem = mw.wikibase.getEntity(parentTaxon)if parentItem thenlocal parentTaxonRankState = parentItem:getBestStatements('P105')[1] --taxon rankif parentTaxonRankState then parentTaxonRank = parentTaxonRankState.mainsnak.datavalue.value.id endif parentTaxonRank and parentTaxonRank == 'Q34740' then --parent == genusfor _, parentInstanceOfState in pairs ( parentItem:getBestStatements('P31') ) do --instance oflocal parentInstanceOf = parentInstanceOfState.mainsnak.datavalue.value.id if parentInstanceOf and  (parentInstanceOf == 'Q310890' or parentInstanceOf == 'Q47487597') then --monotypic/fossil taxonparentMonoGenus = parentTaxon --confirmedbreakendendif parentMonoGenus and tFroms[parentMonoGenus] == nil then--housekeepingtFroms[parentMonoGenus] = 1iFroms = iFroms + 1fromTitleCount = fromTitleCount + 1--append monotypic genus & trackparentArgs['from'..fromTitleCount] = parentMonoGenustCats[18] = '[[Category:Taxonbars with automatically added monotypic genera]]'breakendendendendif parentMonoGenus == nil or tFroms[parentMonoGenus] == nil thentCats[19] = '[[Category:Taxonbars of monotypic species missing genera]]'breakendelseif taxonRank and taxonRank == 'Q34740' then --genus--is monotypic genus; add species--(https://www.wikidata.org/wiki/Wikidata:Property_proposal/child_monotypic_taxon unnecessary thanks to P427!)local childTaxonState = currentItem:getBestStatements('P427')[1] --taxonomic typeif childTaxonState then childTaxon = childTaxonState.mainsnak.datavalue.value.id end--confirm child taxon rank == species & monotypicif childTaxon and resolveEntity._id(childTaxon) thenchildItem = mw.wikibase.getEntity(childTaxon)if childItem thenlocal childTaxonRankState = childItem:getBestStatements('P105')[1] --taxon rankif childTaxonRankState then childTaxonRank = childTaxonRankState.mainsnak.datavalue.value.id endif childTaxonRank and childTaxonRank == 'Q7432' then --child == speciesfor _, childInstanceOfState in pairs ( childItem:getBestStatements('P31') ) do --instance oflocal childInstanceOf = childInstanceOfState.mainsnak.datavalue.value.id if childInstanceOf and  (childInstanceOf == 'Q310890' or childInstanceOf == 'Q47487597') then --monotypic/fossil taxonchildMonoSpecies = childTaxon --confirmedbreakendendif childMonoSpecies and tFroms[childMonoSpecies] == nil then--housekeepingtFroms[childMonoSpecies] = 1iFroms = iFroms + 1fromTitleCount = fromTitleCount + 1--append monotypic species & trackparentArgs['from'..fromTitleCount] = childMonoSpeciestCats[17] = '[[Category:Taxonbars with automatically added monotypic species]]'breakendendendendif childMonoSpecies == nil or tFroms[childMonoSpecies] == nil thentCats[20] = '[[Category:Taxonbars of monotypic genera missing species]]'breakendend --monotype searchesend --monotype handlingend --forend --if currentItem--Setup navboxlocal navboxParams = {name  = 'Taxonbar',bodyclass = 'hlist',listclass = '',groupstyle = 'text-align: left;',}for f = 1, fromTitleCount, 1dolocal elements, title = {}, nil--cleanup parametersif parentArgs['from'..f] == '' then parentArgs['from'..f] = nil endif parentArgs['title'..f] == '' then parentArgs['title'..f] = nil end--remap aliasesfor _, a in pairs( conf.aliases ) dolocal alias, name = mw.ustring.lower(a[1]), mw.ustring.lower(a[2])if parentArgs[alias..f] and parentArgs[name..f] == nil thenparentArgs[name..f] = parentArgs[alias..f]parentArgs[alias..f] = nilendend--Fetch Wikidata itemlocal from = resolveEntity._id(parentArgs['from'..f])local item = mw.wikibase.getEntity(from)local label = nilif type(item) == 'table' thenlocal statements = item:getBestStatements('P225')[1] --taxon nameif statements thenlocal datavalue = statements.mainsnak.datavalueif datavalue thenlabel = datavalue.valueendendlabel = label or item:getLabel()elseif parentArgs['from'..f] thentCats[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 />')endendif label and label ~= '' thentitle = mw.title.new(label)endif title == nil and parentArgs['title'..f] thentitle = mw.title.new(parentArgs['title'..f])endif title == nil and f == 1 thentitle = currentTitleendif title thenif isNilOrEmpty( parentArgs['wikidata'..f] ) and    (title.namespace == 0) thenif parentArgs['from'..f] thenparentArgs['wikidata'..f] = parentArgs['from'..f]elseif item thenparentArgs['wikidata'..f] = item.idendendif title.namespace == 0 or stringArgs then --only in mainspace or if manual overrides existlocal sourceCount = 0for _, params in pairs( conf.databases ) doparams[1] = mw.ustring.lower(params[1])local propId = params[3]--Wikidata fallback if requestedif (item and item.claims) and   (type(propId) == 'string' or (type(propId) == 'number' and propId > 0)) thenlocal wikidataId = getIdFromWikidata( item, 'P'..propId )local v = parentArgs[params[1]..f]if wikidataId thenif isNilOrEmpty(v) thenparentArgs[params[1]..f] = wikidataIdelseif v and v ~= 'no' and v ~= wikidataId thentCats[11] = '[[Category:Taxonbars with manual taxon IDs differing from Wikidata]]'elseif v and v == wikidataId thentCats[10] = '[[Category:Taxonbars with manual taxon IDs identical to Wikidata]]'endendendendif (item and item.claims) and   ( (type(propId) == 'number' and propId < 0)) thenlocal 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 thenparentArgs[params[1]..f] = wikidataIdelseparentArgs[params[1]..f] = nil  -- don't want to use 'yes' as idendendendlocal val = parentArgs[params[1]..f]if val and val ~= '' and mw.ustring.lower(val) ~= 'no' thenif type(propId) == 'number' thenif propId < 0 then propId = -propId end --allow linkif propId > 0 then --linktable.insert( elements, createRow( params[1], params[2]..':', val, getLink( propId, params[1], val ).text, true ) )if params[1] == 'fossilworks' then -- fossilworks being use to link to PBDBif (elements[#elements] == elements[#elements-1]) then -- check if identical PBDB entry already set    --mw.addWarning("item has both Fossilworks and PBDB identifers:" .. val)    elements[#elements] = nil    endendelse --propId == 0; no linktable.insert( elements, createRow( params[1], params[2]..':', val, val, true ) )endelsetable.insert( elements, createRow( params[1], params[2]..':', val, getLink( propId, params[1], val ).text, true ) )endif params[1] ~= 'wikidata' and params[1] ~= 'wikispecies' thensourceCount = sourceCount + 1endendend --forif     sourceCount >= 45 then tCats[28] = '[[Category:Taxonbars with 45+ taxon IDs]]'elseif sourceCount >= 40 then tCats[27] = '[[Category:Taxonbars with 40–44 taxon IDs]]' --endasheselseif sourceCount >= 35 then tCats[26] = '[[Category:Taxonbars with 35–39 taxon IDs]]'elseif sourceCount >= 30 then tCats[25] = '[[Category:Taxonbars with 30–34 taxon IDs]]'elseif sourceCount >= 25 then tCats[24] = '[[Category:Taxonbars with 25–29 taxon IDs]]'elseif sourceCount >= 20 then tCats[23] = '[[Category:Taxonbars with 20–24 taxon IDs]]'end--Generate navbox titleif sourceCount > 0 thenrowCount = rowCount + 1if firstRow == 0 then firstRow = f end--set title from wikidata if it doesn't existif isNilOrEmpty( parentArgs['title'..f] ) thenparentArgs['noTitle'..f] = trueparentArgs['title'..f] = title.textend--if it exists now, set row heading to titleif not isNilOrEmpty( parentArgs['title'..f] ) thennavboxParams['group'..f] = TaxonItalics.italicizeTaxonName(parentArgs['title'..f], false)elsenavboxParams['group'..f] = ''endnavboxParams['list'..f] = table.concat( elements )elseif currentEntityId and (currentEntityId == parentArgs['from'..f] or fromTitleCount == 1) thentCats[21] = '[[Category:Taxonbars without primary Wikidata taxon IDs]]'elsetCats[22] = '[[Category:Taxonbars without secondary Wikidata taxon IDs]]'end--Categorizeif not isNilOrEmpty( parentArgs['from'..f] ) thentCats[1] = '' --blank "missing from" if 'from' existsif parentArgs['from'..f] == currentEntityId thentCats[2] = '' --blank "desynced" if 'from' matches current pageendendif tCats[1] ~= '' thentCats[2] = '' --cannot be "desynced" if no 'from' paramsendend --if title.namespace == 0 or stringArgsend --if title                -- BEGIN test sitelinksif frame:getParent().args.sitelinks then local siteLinks = item.sitelinksif siteLinks thenlocal langlinks = {}local output = "output: "for i,v in pairs (siteLinks) do  --  handle wikispecies and commons first   if string.match( v.site, "specieswiki")  or string.match( v.site, "commonswiki")  then            output = output ..  " | " .. v.site .. ": [[:" .. string.gsub( v.site, "wiki", "") ..  ":" .. v.title .. "]]"      table.insert( langlinks, "\n* " .. v.site .. ": [[:" .. string.gsub( v.site, "wiki", "") ..  ":" .. v.title .. "]]")   endendfor i,v in pairs (siteLinks) do   if 1==2 then                                 -- suppress the non-language wiki matches below   elseif string.match( v.site, "species") then --output = output .. "| SPECIES"   elseif string.match( v.site, "commons") then --output = output .. "| COMMONS"   elseif string.match( v.site, "news") then    --output = output .. "| NEWS"  -- also ruwikinews, etc   elseif string.match( v.site, "quote") then   --output = output .. "| QUOTE" -- also ruwikiquote, plwikiquote, etc   elseif string.match( v.site, "source") then  --output = output .. "| SOURCE" -- also sawikisource   else -- only use language wikipedias      output = output ..  " | " .. v.site .. ": [[:" .. string.gsub( v.site, "wiki", "") ..  ":" .. v.title .. "]]"      table.insert( langlinks, "\n* " .. v.site .. ": [[:" .. string.gsub( v.site, "wiki", "") ..  ":" .. v.title .. "]]")   endend--mw.addWarning( table.concat( langlinks ) )navboxParams['list1'] = table.concat( langlinks )endend-- END test sitelinksend --for f = 1, fromTitleCount, 1if rowCount > 0 thenlocal Navbox = require('Module:Navbox')if rowCount > 1 then--remove duplicates and don't bother moving page title to toplocal rowIDs = {}for f = 1, fromTitleCount, 1doif not isNilOrEmpty( parentArgs['title'..f] ) thenif rowIDs[parentArgs['wikidata'..f]] then --remove duplicatenavboxParams['group'..f] = nilnavboxParams['list'..f] = nilelserowIDs[parentArgs['wikidata'..f]] = trueendendendif parentArgs['title'..2] and parentArgs['title'..2] == currentTitle.text thenif currentItem and parentArgs['from'..2] == currentItem['id'] thentCats[8] = '[[Category:Taxonbars with from2 matching article title & QID]]'elsetCats[7] = '[[Category:Taxonbars with from2 matching article title]]'endend--adjust navbox for number of rowsnavboxParams['title'] = '[[Help:Taxon identifiers|Taxon identifiers]]'if rowCount >= 4 thennavboxParams['navbar'] = 'plain'elsenavboxParams['state'] = 'off'navboxParams['navbar'] = 'off'endelseif parentArgs['noTitle'..firstRow] then --show title & taxon for 1-row taxonbars, per talk--BEGIN sitelist testif frame:getParent().args.sitelinks then -- if using test sitelinks output--navboxParams['group'..firstRow] = 'Interlanguage links'    navboxParams['title'] = 'Interlanguage links'navboxParams['state'] = 'off'navboxParams['navbar'] = 'off'else --END sitelist test code--navboxParams['group'..firstRow] = '[[Help:Taxon identifiers|Taxon identifiers]]' --old version    navboxParams['title'] = '[[Help:Taxon identifiers|Taxon identifiers]]'navboxParams['state'] = 'off'    navboxParams['navbar'] = 'off'    endelsenavboxParams['group'..firstRow] = '[[Help:Taxon identifiers|Taxon identifiers]]<br />'..navboxParams['group'..firstRow]end-- return alternative output if format set to valid valueif parentArgs.format thenlocal alternativeOutput = p.alternativeOutputs (frame, parentArgs, navboxParams, fromTitleCount)if alternativeOutput thenreturn alternativeOutput  -- return the alternative output and doneend  end -- otherwusee proceed as normal to navbox        --return navbox outString = Navbox._navbox(navboxParams)end --if rowCount > 0--Add categoriesif string.sub(currentTitle.subpageText,1,9) == 'testcases' then parentArgs['demo'] = true endif not isNilOrEmpty( parentArgs['demo'] ) thenoutString = outString..mw.text.nowiki(table.concat(tCats))..'<br />'elseif currentTitle.namespace == 0 thenoutString = outString..table.concat(tCats)endreturn outString..errorsend--[[  experimental function to output identifier links without using Navbox      not using outstring and categories/errors--]]function p.alternativeOutputs (frame, parentArgs, navboxParams, fromTitleCount)local output = ""    local format = parentArgs.format    for f = 1, fromTitleCount, 1 doif format == "collapsible" thenoutput = output .. frame:expandTemplate{title="Collapsible list", args= {title=navboxParams["group"..f], [f]="\n" .. navboxParams['list'..f]}}elseif format == "efn" thenlocal styles = frame:extensionTag{name = 'templatestyles', args = { src = 'Template:Hlist/styles.css' } }output = output .. frame:expandTemplate{title="efn",args={ styles .. navboxParams["group"..f] .. ":<div class='hlist inline'>\n" .. navboxParams["list"..f] .. '</div>'}}elseif format == "ref" thenlocal styles = frame:extensionTag{name = 'templatestyles', args = { src = 'Template:Hlist/styles.css' } }local groupname = parentArgs.group or ""output = output .. frame:extensionTag { name="ref", content =  styles .. navboxParams["group"..f] .. ":<div class='hlist inline'>\n" .. navboxParams["list"..f] .. '</div>' , args = { group = groupname }  }elseif format == "list-horizontal" then--local styles = frame:extensionTag{name = 'templatestyles', args = { src = 'Template:Hlist/styles.css' } }output = output .. navboxParams["group"..f] .. ':<div class="hlist inline">\n' .. navboxParams["list"..f] .. '</div>'elseif format == "raw" thenoutput = output .. "\n"..navboxParams["list"..f] elseif format == "list" thenoutput = output .. frame:expandTemplate{title="collapsable list",args= { framestyle = "width:40em;", title="Taxon identifiers for " .. navboxParams["group"..f], [f]= "\n"..navboxParams["list"..f] } }elseif format == "list-h" thenoutput = output .. frame:expandTemplate{title="collapsable list",args= { expand='true', framestyle = "", title=navboxParams["group"..f], '<div style="display:inline;" class="hlist inline">\n' .. navboxParams["list"..f] .. '</div>' } }elseif format == "hidden" then   -- doesn't work in mobileoutput = output .. frame:expandTemplate{title="hidden",args= { style = "width:25em;", header = "Taxon&nbsp;identifiers", [2]= navboxParams["list"..f] } }elseif format == "pseudo-taxonbar" then--local styles = frame:extensionTag{name = 'templatestyles', args = { src = 'Template:Hlist/styles.css' } } output = output .. '<tr><th class="navbox-group" style="width:100px; text-align: left;">' .. navboxParams["group"..f] .. '</th>'                    .. '<td style="text-align:left;><div class="hlist inline">\n' .. navboxParams["list"..f] .. '</div></td></tr>'elseif format == "grid-taxonbar" then output = output .. '<div class="taxonbar-group" style="">'  -- using templatestyles                          .. navboxParams["group"..f] .. '</div>'                        .. '<div class="hlist inline taxonbar-list" style="text-align:left;margin:2px 1px;background-color:rgb(247, 247, 247);" >\n' .. navboxParams["list"..f] .. '</div>'                                          --- backgrond colors: odd= rgb(253, 253, 253) even=rgb(247, 247, 247)elsereturn false -- if no valid formatendend-- now box the pseudo-taxonbarif format == "pseudo-taxonbar"  then  -- first step prototype for non-navbox taxonbarlocal box = '<div class="xnavbox" style="clear:both;font-size: 88%;padding:1px;margin:1em 0; border: 1px solid rgb(162, 169, 177);">'box = box .. '<table style="margin:0"><tr><th class="navbox-title" colspan="2" style="margin:0;">'           ..'<div id="Taxon_identifiers" style="font-size:114%;margin:0 4em">'          .. '[[Help:Taxon_identifiers|Taxon identifiers]]'          .. '</div></th></tr>'output = box .. output .. '</table></div>'endif format == "grid-taxonbar"  thenlocal box = '<div class="taxonbar" style="" >'box = box     .. '<div class="taxonbar-title"  styleXXX="margin:0;">'               ..    '<div id="Taxon_identifiers" style="">' --              ..    '[[Help:Taxon_identifiers|Taxon identifiers]]'              .. '</div></div>'              .. '<div class="taxonbar-grid" styleXX="display:grid;grid-template-columns: auto auto;">'output = box .. output .. '</div></div>'end        return output .. frame:extensionTag('templatestyles', '',  { src="Module:Taxonbar/styles.css" })endfunction p.taxonbar(frame) return p.authorityControlTaxon( frame:newChild{title = frame:getTitle()} ) endreturn p