Mô đun:Autotaxobox-collapsible

--
This module provides support to the automated taxobox system – the templates
Automatic taxobox, Speciesbox, Subspeciesbox, Infraspeciesbox, etc.

In particular it provides a way of traversing the taxonomic hierarchy encoded
in taxonomy templates (templates with names of the form
"Template:Taxonomy/TAXON_NAME") without causing template expansion depth errors.

local TaxonItalics = require('Module:TaxonItalics') -- use a function from Module:TaxonItalics to italicize a taxon name
local p = {}
local l = {} -- keep internal functions separate
local colour = -- colour for taxobox and taxonomy listings

--
Limit the maximum depth of a taxonomic hierarchy that can be traversed;
avoids excessive processing time and protects against incorrectly set up
hierarchies, e.g. loops.

local MaxSearchLevels = 100

function p.getMaxSearchLevels()
return MaxSearchLevels
end

-- taxoboxColour
Determines the correct colour for a taxobox, by searching up the taxonomic
hierarchy from the supplied taxon for the first taxon (other than
'incertae sedis') that sets a taxobox colour. It is assumed that a valid
taxobox colour is defined using CSS rgb() syntax.
If no taxon that sets a taxobox colour is found, then 'transparent' is
returned unless the taxonomic hierarchy is too deep, when the error colour is
returned.
Usage:
=============================================================================
function p.taxoboxColour(frame)
-- note that colour is global to this function; default is empty string
local currTaxon = frame.args[1] or
local i = 1 -- count levels processed
local searching = currTaxon ~= -- still searching for a colour?
local foundICTaxon = false -- record whether 'incertae sedis' found
while searching and i = i), virus = virus } }
end
-- display greatgreatgrandparent, if it exists
if taxonTable.n >= 5 then
res = res .. frame:expandTemplate{ title = 'Template:Taxobox/showtaxon-collapsible', args = { taxonTable[5], authority = gggParentAuth, fc = tostring(displayN >= 5), virus = virus } }
end
-- display greatgrandparent, if it exists; force the display if an infrataxon is below
if taxonTable.n >= 4 then
local force = tostring(displayN >= 4) or
frame.expandTemplate{ title = 'Template:Infrataxon()', args = { taxonTable[3] } } == 'true' or
frame.expandTemplate{ title = 'Template:Infrataxon()', args = { taxonTable[2] } } == 'true'
res = res .. frame:expandTemplate{ title = 'Template:Taxobox/showtaxon-collapsible', args = { taxonTable[4], authority = ggParentAuth, fc = tostring(force), virus = virus } }
end
-- display grandparent, if it exists; force the display if an infrataxon is below
if taxonTable.n >= 3 then
local force = tostring(displayN >= 3) or
frame.expandTemplate{ title = 'Template:Infrataxon()', args = { taxonTable[2] } } == 'true'
res = res .. frame:expandTemplate{ title = 'Template:Taxobox/showtaxon-collapsible', args = { taxonTable[3], authority = gParentAuth, fc = tostring(force), virus = virus } }
end
-- display parent, if it exists
if taxonTable.n >= 2 then
res = res .. frame:expandTemplate{ title = 'Template:Taxobox/showtaxon-collapsible', args = { taxonTable[2], authority = parentAuth, fc = tostring(displayN >= 2), virus = virus } }
end
-- display target taxon
res = res .. frame:expandTemplate{ title = 'Template:Taxobox/showtaxon-collapsible', args = { taxonTable[1], authority = auth, fc = 'true', format = boldFirst, virus = virus } }
return res
end

-- taxonomyList
Returns the cells of the taxonomy table displayed on the right hand side of
"Template:Taxonomy...." pages.
Usage:
=============================================================================
function p.taxonomyList(frame)
local currTaxon = frame.args[1] or
if currTaxon == then return '| ||ERROR: no taxon supplied\n|-' end
local taxonTable = l.makeTable(frame, currTaxon)
local rankTable = l.getRankTable()
local lastRankVal = 1000000
local orderOk = true
local res =
-- check whether the taxonomy is for viruses; use already determined taxon colour if possible
local virus = 'no'
local taxoColour = colour
if taxoColour == then
taxoColour = frame:expandTemplate{ title = 'Template:Taxobox colour', args = { taxonTable[taxonTable.n - 1] } }
end
if taxoColour == frame:expandTemplate{ title = 'Template:Taxobox colour', args = { 'virus' } } then
virus = 'yes'
end
-- deal first with the top level taxon; if there are no errors, it should be Life/Veterovata/Ichnos, which are
-- not displayed
local taxon = taxonTable[taxonTable.n]
if taxon ~= 'Life' and taxon ~= 'Veterovata' and taxon ~= 'Ichnos' then
local msg = 'Taxonomy template missing'
if mw.title.new('Taxonomy/'..taxon, 'Template').exists then
msg = 'Parent taxon needed'
end
res = res .. '\n|colspan=2|' .. frame:expandTemplate{title = 'Template:Create taxonomy', args = {taxon, msg = msg}} .. '\n|-\n'
end
-- now output the rest of the table
for i = taxonTable.n-1, 1, -1 do
-- check ranks are in right order in the hierarchy
taxon = taxonTable[i]
local ok, rank = l.getTaxonInfoItem(frame, taxon, 'rank')
local currRankVal = rankTable[string.lower(rank)]
if currRankVal then
orderOk = currRankVal no taxon supplied' end
local rank = frame.args[2] or
if rank == then return 'no rank supplied' end
local inHierarchy = true -- still in the taxonomic hierarchy or off the top?
local searching = true -- still searching
while inHierarchy and searching do
local ok, parent = l.getTaxonInfoItem(frame, currTaxon, 'parent')
if ok and parent ~= then
currTaxon = parent
local ok, currRank = l.getTaxonInfoItem(frame, currTaxon, 'rank')
if currRank == rank then
searching = false
end
else
inHierarchy = false
end
end
if inHierarchy and not searching then return currTaxon
else return 'rank not found'
end
end

-- nth
External utility function primarily intended for use in checking and debugging.
Returns the nth level above a taxon in a taxonomic hierarchy, where the taxon
itself is counted as the first level.
Usage:
=============================================================================
function p.nth(frame)
local currTaxon = frame.args[1] or
if currTaxon == then return 'ERROR: no taxon supplied' end
local n = tonumber(frame.args['n'] or 1)
if n > MaxSearchLevels then
return 'Exceeded maximum number of levels allowed (' .. MaxSearchLevels .. ')'
end
local i = 1
local inHierarchy = true -- still in the taxonomic hierarchy or off the top?
while i (?)'
end
else
info = 'Template:Taxonomy/' .. taxon .. --error indicator in code before conversion to Lua
end
return ok, info
end

function l.getTaxonInfoLink(frame, taxon)
local ok, linkText, linkTarget
local link =
ok, linkText = l.getTaxonInfoItem(frame, taxon, 'link_text')
if ok then
ok, linkTarget = l.getTaxonInfoItem(frame, taxon, 'link_target')
if ok then
if linkText == linkTarget then link = linkText
else link = linkTarget .. '|' .. linkText
end
end
end
return ok, link
end

--[[= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Internal utility function to return a table (array) constructed from a
taxonomic hierarchy stored in "Template:Taxonomy/..." templates.
TABLE.n holds the total number of taxa; TABLE[1]..TABLE[TABLE.n] the taxon
names.
The last taxon in the table will either (a) have a taxonomy template but with
no parent given (e.g. 'Life') or (b) not have a taxonomy template.
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =]]
function l.makeTable(frame, currTaxon)
local i = 1
local inHierarchy = true -- still in the taxonomic hierarchy or off the top?
local taxonTable = {}
taxonTable[1] = currTaxon;
while i < MaxSearchLevels and inHierarchy do
local ok, parent = l.getTaxonInfoItem(frame, currTaxon, 'parent')
if ok and parent ~= then
currTaxon = parent
i = i + 1
taxonTable[i] = currTaxon
else
inHierarchy = false -- run off the top of the hierarchy or tried to use non-existent taxonomy template
end
end
taxonTable.n = i
return taxonTable
end

--= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Internal utility function to set up a table of numerical values corresponding
to 'Linnaean' ranks, with upper ranks having higher values. In a valid
taxonomic hierarchy, a lower rank should never have a higher value than a
higher rank. The actual numerical values are arbitrary so long as they are
ordered.
The ranks should correspond to those in Template:Anglicise ranks.
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
function l.getRankTable()
return {
classis = 1400,
cohort = 1100,
divisio = 1500,
domain = 1700,
familia = 800,
forma = 100,
genus = 600,
grandordo = 1005,
['grandordo-mb'] = 1002,
infraclassis = 1397,
infralegio = 1197,
infraordo = 997,
infraphylum = 1497,
infraregnum = 1597,
infratribus = 697,
legio = 1200,
magnordo = 1006,
microphylum = 1495,
micrordo = 995,
mirordo = 1004,
['mirordo-mb'] = 1001,
nanophylum = 1494,
nanordo = 994,
ordo = 1000,
parafamilia = 800,
parvclassis = 1396; -- same as subterclassis
parvordo = 996,
phylum = 1500,
regnum = 1600,
sectio = 500,
--series = 400, used too inconsistently to check
species = 300,
subclassis = 1398,
subcohort = 1098,
subdivisio = 1498,
subfamilia = 798,
subgenus = 598,
sublegio = 1198,
subordo = 998,
subphylum = 1498,
subregnum = 1598,
subsectio = 498,
subspecies = 298,
subterclassis = 1396; -- same as parvclassis
subtribus = 698,
superclassis = 1403,
supercohort = 1103,
superdivisio = 1503,
superdomain = 1703,
superfamilia = 803,
superlegio = 1203,
superordo = 1003,
superphylum = 1503,
superregnum = 1603,
supertribus = 703,
tribus = 700,
varietas = 200,
zoodivisio = 1300,
zoosectio = 900,
zoosubdivisio = 1298,
zoosubsectio = 898,
}
end

return p