Jump to content

Module:Biota infobox

Permanently protected module
From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Jts1882 (talk | contribs) at 16:33, 9 January 2019 (use color_as for manual taxonomies). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

require('Module:No globals')
-- All Lua modules on Wikipedia must begin by defining a variable that will hold their
-- externally accessible functions. They can have any name and may also hold data.
local p = {}


local data = require( 'Module:Biota infobox/data' ) -- contains the taxon ranks in order
local autotaxa = require("Module:Autotaxobox")

local parent = mw.getCurrentFrame():getParent()
--[[TODO some preliminary processing of arguments
      could check for empty strings and remove from list, but what if using as flag (e.g. "|parent=")
      want to check for alternatives, e.g. "regnum authority" or "regnum_authority" (replace space with underscore)
      e.g. param = mw.ustring.gsub(param, "_", " ");
--]]
function p.preprocessArgs(frame)                       --TODO test fully
	
	--local params = parent.args                       -- TODO how to do without full list of parameters
	local params = { 'image upright', 'image caption', 'type genus'	}

	for k,v in pairs(params) do
		if parent.args[v] then -- and mw.ustring.match(parent.args[v], " ") then
			   --params[v] = string.gsub(params[v], ".+(%s).+", "%_");
			   local u = string.gsub(v, "%s+", "_");  -- v = "param name" --> u = "param_name"
			   parent.args[u] = parent.args[v]
		end
	end
end
------------------------------------------------------------------------------------------------
-- handle specific requirements of different options: manual, auto, speciesbox etc
function p.specialTaxoboxOptions(frame)
  
    -- "the automated taxobox first looks for the taxonomy template that matches the supplied |taxon= parameter "
    --       "(or, if none is supplied, the article's title, ignoring any parenthetical expressions). "
    if not parent.args['taxon'] or  parent.args['taxon'] == "" then
    	 parent.args['taxon'] = parent.args['name'] or tostring( mw.title.getCurrentTitle())
    	 --TODO strip name of parenthetical terms off page title
    end
   -- parent.args['parent'] = parent.args['taxon'] -- cannot set here as speciesbox uses parent to override genus as parent
    
    --[[ possible extra option: use genus and species to set parent 
	if parent.args['genus'] and parent.args['species'] then
	    parent.args['taxon'] = parent.args['genus'] .. ' ' .. parent.args['species']
	    parent.args['parent'] = parent.args['genus']
	end
	--]]

    parent.args['display_taxa']  = parent.args['display_parents'] or 1  -- confusing change of parameter name 
   
   local extinct = ""
   --if  parent.args['extinct']  then extinct = "†" end
   if  parent.args['extinct']  then extinct = frame:expandTemplate{ title = 'extinct' } end -- use template to get tooltip
    
    -- ------------------------variables for SPECIESBOX, SUBSPECIESBOX and INFRASPECIESBOX------------------------------
    -- setup for speciesbox (including set binomial)
	if parent.args['auto'] == "speciesbox" then

        -- string handling testing on "Panthera leo" speciesbox
        --parent.args['genus'] = string.match(parent.args['taxon'] , "^(%a+)%s" ) -- Panthera
        --parent.args['species'] = string.gsub(parent.args['taxon'] , "^(%a+)%s" , "") -- leo and reference
        --parent.args['species'] = string.match(parent.args['taxon'] , "%s(%a+)$" ) -- leo and reference
        --parent.args['species'] = string.match(parent.args['taxon'] , "%s(%a+)." ) -- leo without reference
       -- mw.text.split( s, pattern, plain 
       
       -- speciesbox assumes taxon given as binomial (in documentation), but also takes genus and species (which priority?)
       	if parent.args['genus'] and parent.args['species'] then
	    	--TODO strip off (disambiguater) to handle multi-kingdom genus e.g.| genus = Acanthocarpus (plant)
	    	local genus =mw.text.split( parent.args['genus'], " ", true )
	    	if genus[1] ~= "" then 
	    		parent.args['parent']=parent.args['genus']  -- set parent
	    		parent.args['genus'] = genus[1] 
	    	end
	    	parent.args['taxon'] = parent.args['genus'] .. ' ' .. parent.args['species']
		
		elseif parent.args['taxon'] then
	       local  genus, species = string.match(parent.args['taxon'], "(%S+)%s(%S+)") -- %S: All characters not in %s
	       parent.args['genus'] = genus
	       parent.args['species'] = species
	    else
	    	-- no valid taxon yet
	    	--TODO need to get out of here or use 'name' or page title 
	    end
    
        if not parent.args['parent'] or parent.args['parent'] == "" then
        	parent.args['parent'] = parent.args['genus']       -- set parent to genus if not already
        end
        if not parent.args['name'] or parent.args['name'] == "" then -- if page name not set
        	parent.args['name'] = "''" .. parent.args['taxon'] .. "''"
        end
        
		-- set binomial : the speciesbox template seems to use genus and species before taxon name
		-- "| binomial = ''{{Str letter/trim|{{{genus|{{{taxon|<includeonly>{{PAGENAME}}</includeonly><noinclude>Acacia</noinclude>}}}}}}}} {{{species|{{remove first word|{{{taxon|<includeonly>{{PAGENAMEBASE}}</includeonly><noinclude>Acacia aemula</noinclude>}}}}}}}}''"
		-- documentation suggest taxon, which is followed here
		parent.args['binomial'] = "''" .. parent.args['taxon'] .. "''"
		parent.args['binomial_authority'] = parent.args['authority'] or nil
				

    	-- set species_name e.g. Panthera leo -> P. leo
    	parent.args['species_name'] = extinct .. "'''''" .. string.sub(parent.args['genus'],1,1) .. '. ' .. parent.args['species'] .. "'''''"

        parent.args['display_taxa']   = parent.args['display_taxa'] -1
	    --shift authorities for speciesbox (two steps if subgenus set)
	    if parent.args['subgenus'] and parent.args['subgenus'] ~= ""  then
			parent.args['subgenus_authority']              = parent.args['parent_authority'] or ""
			parent.args['authority']                       = parent.args['grandparent_authority'] or ""
			parent.args['parent_authority']                = parent.args['greatgrandparent_authority'] or ""
			parent.args['grandparent_authority']           = parent.args['greatgreatgrandparent_authority'] or ""
			parent.args['greatgrandparent_authority']      = parent.args['greatgreatgreatgrandparent_authority'] or ""
			parent.args['greatgreatgrandparent_authority'] = parent.args['greatgreatgreatgreatgrandparent_authority'] or ""
		else                                                                
			-- note: must set to "" if 'parent_authority's don't exist, otherwise the value of 'authority' is unchanged
			parent.args['authority']                       = parent.args['parent_authority'] or ""  
			parent.args['parent_authority']                = parent.args['grandparent_authority'] or ""
			parent.args['grandparent_authority']           = parent.args['greatgrandparent_authority'] or ""
			parent.args['greatgrandparent_authority']      = parent.args['greatgreatgrandparent_authority'] or ""
			parent.args['greatgreatgrandparent_authority'] = parent.args['greatgreatgreatgrandparent_authority'] or ""	
		end
    
    -- set-up for subspecies or infraspecies
	elseif parent.args['auto'] == "subspeciesbox" or parent.args['auto'] == "infraspeciesbox" then
	
		--TODO set trinomial name
    	--[[According to subspsecisbox and infraspeciesbox documentation "The genus name, species name and subspecies name must be supplied separately: the combined taxon parameter cannot be used".
            This means the trinomial can be constructed and the parameter ignored.
        --]]
        parent.args['parent'] = parent.args['genus'] -- genus must be supplied
        
        local fullName = parent.args['genus'] .. ' ' .. parent.args['species']
 		parent.args['species_name']= "''[[" .. fullName  .. '|'.. string.sub(parent.args['genus'],1,1) .. '. ' .. parent.args['species'] .. "]]''"
        
        --local bold = "'''"
        local separator = " " -- subspecies separator (default zoological)
	    if parent.args['subspecies'] then -- might not be if variety
        	if parent.args['auto'] == "infraspeciesbox"   then separator = " ''<small>subsp.</small>'' "   end
			parent.args['subspecies_name']= extinct .. "'''''" .. string.sub(parent.args['genus'],1,1) .. '. ' .. string.sub(parent.args['species'],1,1) .. '.' .. separator .. parent.args['subspecies'] .. "'''''"
  			fullName = parent.args['genus'] .. ' ' .. parent.args['species'] .. separator .. parent.args['subspecies'] 
			parent.args['trinomial'] = "''" .. fullName .. "''"
			-- TODO if there is also a variety, this should be linked and not bolded (but would such an article exist)
        end
        if parent.args['variety'] or parent.args['varietas'] then 
            local vSeparator = " ''<small>var.</small>'' " 
            parent.args['variety']= parent.args['variety'] or parent.args['varietas'] -- will use variety as parameter
			parent.args['variety_name']= extinct .. "'''''" .. string.sub(parent.args['genus'],1,1) .. '. ' .. string.sub(parent.args['species'],1,1) .. '.' .. vSeparator .. parent.args['variety'] .. "'''''"
 			parent.args['trinomial'] = "''" .. parent.args['genus'] .. ' ' .. parent.args['species'] .. vSeparator .. parent.args['variety'] .. "''"
    	    if parent.args['subspecies'] then 	-- subspecies needs to linked instead of bold 
	  			fullName = parent.args['genus'] .. ' ' .. parent.args['species'] .. " ''subsp.'' " .. parent.args['subspecies'] 
				parent.args['subspecies_name'] =  "''[[" .. fullName .. '|' .. string.sub(parent.args['genus'],1,1) .. '. ' .. string.sub(parent.args['species'],1,1) .. '.' .. separator .. parent.args['subspecies'] .. "]]''"
        	end
        end
    

		parent.args['trinomial_authority'] = parent.args['authority'] or nil

        if not parent.args['name'] or parent.args['name'] == "" then -- if page name not set
        	parent.args['name'] = parent.args['trinomial']
        end
        
        parent.args['display_taxa']   = (parent.args['display_taxa'] or 1) -2
	    --shift authorities for subspeciesbox (two steps or three if subgenus set)
	    if parent.args['subgenus'] and parent.args['subgenus'] ~= ""  then
			parent.args['subgenus_authority']              = parent.args['grandparent_authority'] or ""
			parent.args['authority']                       = parent.args['greatgrandparent_authority'] or ""
			parent.args['parent_authority']                = parent.args['greatgreatgrandparent_authority'] or ""
			parent.args['grandparent_authority']           = parent.args['greatgreatgreatgrandparent_authority'] or ""
			parent.args['greatgrandparent_authority']      = parent.args['greatgreatgreatgreatgrandparent_authority'] or ""
			parent.args['greatgreatgrandparent_authority'] = parent.args['greatgreatgreatgreatgreatgrandparent_authority'] or ""
		else
			parent.args['authority']                       = parent.args['grandparent_authority'] or ""
			parent.args['parent_authority']                = parent.args['greatgrandparent_authority'] or ""
			parent.args['grandparent_authority']           = parent.args['greatgreatgrandparent_authority'] or ""
			parent.args['greatgrandparent_authority']      = parent.args['greatgreatgreatgrandparent_authority'] or ""
			parent.args['greatgreatgrandparent_authority'] = parent.args['greatgreatgreatgreatgrandparent_authority']	 or ""
		end
	else
  		parent.args['parent'] = parent.args['taxon']
	end	
	
	-- check taxonomy templates for automatic taxobox systtem
	--{{#ifexist:Template:Taxonomy/{{{taxon|<includeonly>{{PAGENAME}}</includeonly><noinclude>Acacia</noinclude>}}}
	--       |<noinclude><!--do nothing if it exists--></noinclude>
	--       |{{Automatic taxobox/floating intro|taxon={{{taxon|{{PAGENAME}}}}} }}
-->}}

end
------------------------------------------------------------------------------------------
--[[ main function callable in Wikipedia via the #invoke command.
        creates a taxobox-style infobox
        creates main table and header section (with header, subheader and fossil ranges)
        the creates addition rows for template arguments with following subsidiary functions:
        	p.addImageSection() - images and range maps 
        	p.addStatusSection() - conservation status
        	p.addTaxonomySection() - listing of taxonomic heirarchy (manuel or using automatic taxonomy system)
        	p.addTaxonSection() - adds section with taxonomic information (binomial or trinomials; type genus or species; diversity)
            p.addListSection()     - section containing list if subdivisions, synonyms, included or excluded groups
--]]
p.main = function(frame) 
	
	 --p.preprocessArgs(frame)  -- preprocess frame arguments (handle alias and empty parameters?)

	if parent.args['auto'] then
		p.specialTaxoboxOptions(frame)
	end
	local name = parent.args['name'] or tostring( mw.title.getCurrentTitle() )

	-- create table
	local taxoboxTable = mw.html.create('table'):addClass('infobox'):addClass('biota')
								                :addClass('taxobox-paraphyletic')
    local subheader = ''
    if parent.args['subheader'] and parent.args['subheader'] ~= '' then
		subheader='<div style="font-weight:normal;font-size:smaller;">'..parent.args['subheader']..'</div>'
    end
    
    local fossilRange = ''
    if parent.args['fossil_range']  then
    	fossilRange = '<div><small>Temporal range: ' .. parent.args['fossil_range'] .. '</small></div>' -- use <div> rather than <br/>
    end
    
    local rowHeader = taxoboxTable:tag('tr'):tag('th'):attr('colspan', '2'):addClass('section-header')
	                :cssText('background:' ..  p.getTaxoboxColor(frame) .. ';')
					:wikitext(name .. subheader .. fossilRange)
    
    -- add images
    p.addImageSection(frame, taxoboxTable, 'image')
    p.addImageSection(frame, taxoboxTable, 'image2')
    
    --add conservation status 
	p.addStatusSection(frame, taxoboxTable, 'status')
	p.addStatusSection(frame, taxoboxTable, 'status2')
	
	-- add taxonomy table (uses entered parameters or automatic taxonomy system)
	p.addTaxonomySection(frame, taxoboxTable)
    
	-- add sections with binomial, trinomial, type species/genus (with authorities)
	p.addTaxonSection(frame, taxoboxTable, 'binomial', 'Bionomial name')
	p.addTaxonSection(frame, taxoboxTable, 'trinomial', 'Trionomial name')
	p.addTaxonSection(frame, taxoboxTable, 'type_genus', 'Type genus')
	--TODO type_ichnogenus, type_oogenus
	p.addTaxonSection(frame, taxoboxTable, 'type_species', 'Type species')
	--TODO type_ichnospecies, type_oospecies
    p.addTaxonSection(frame, taxoboxTable, 'type_strain', 'Type strain')

	-- add sections showing subdivisions (i.e. child taxa)
    p.addListSection(frame, taxoboxTable, 'subdivision', parent.args['subdivision_ranks'] or 'Subdivisions')
	p.addListSection(frame, taxoboxTable, 'possible_subdivision', parent.args['possible_subdivision_ranks'] or 'Possible subdivisions')
    
    p.addTaxonSection(frame, taxoboxTable, 'diversity', 'Diversity') -- diversity section

	-- show included groups (accepts 'included' or 'includes') [used for paraphyletic tax]
	p.addListSection(frame, taxoboxTable, 'includes', 'Groups included')
	p.addListSection(frame, taxoboxTable, 'included', 'Groups included')

    --add range map (should this be below binomial/trinomial?)
    p.addImageSection(frame, taxoboxTable, 'range_map')

	-- show excluded groups (accepts 'excluded' or 'excludes') [used for paraphyletic tax]
	local excludedHeaderText = '[[Cladistics|Cladistically]] included but traditionally excluded taxa'
	p.addListSection(frame, taxoboxTable, 'excludes', excludedHeaderText)
	p.addListSection(frame, taxoboxTable, 'excluded', excludedHeaderText)
    
    -- add addition binomials, trinomial and range maps
	p.addTaxonSection(frame, taxoboxTable, 'binomial2', 'Bionomial name (2)')
	--p.addTaxonSection(frame, taxoboxTable, 'trinomial2', 'Trionomial name (2)')
    p.addImageSection(frame, taxoboxTable, 'range_map2')
	p.addTaxonSection(frame, taxoboxTable, 'binomial3', 'Bionomial name (3)')
	--p.addTaxonSection(frame, taxoboxTable, 'trinomial3', 'Trionomial name (3)')
    p.addImageSection(frame, taxoboxTable, 'range_map3')
	p.addTaxonSection(frame, taxoboxTable, 'binomial4', 'Bionomial name (4)')
	--p.addTaxonSection(frame, taxoboxTable, 'trinomial4', 'Trionomial name (4)')
    p.addImageSection(frame, taxoboxTable, 'range_map4')

	-- add synonyms section
	p.addListSection(frame, taxoboxTable, 'synonyms', '[[Synonym (taxonomy)|Synonyms]]')

	------------------add templateSyles and return taxobox table---------------------------
	
	local src = "Template:Paraphyletic group/sandbox/styles.css" -- TemplateStyles file
    	
	return p.templateStyle( frame, src ) ..  tostring(taxoboxTable)
	
end  -- End the main function.	

-------------------------------------------------------------------------------------------
--[[ function to add conservation sections 
        uses template {{taxobox/species|{{{status_system|}}}|{{{status|}}}|{{{status_ref|}}}|extinct={{{extinct|}}} }} }}
        
--]]
function p.addStatusSection(frame, taxoboxTable, status)

    -- must use table container to handle template output
    -- don't use header or content cells; the 'taxobox/species' template handles it
    -- just need to add background colour on the row

    if parent.args[status] and parent.args[status] ~= "" then
 
		local row = taxoboxTable:tag('tr')
		                                  --:cssText('background:' ..  p.getTaxoboxColor(frame) .. ';')
		local cell = row:tag('td'):attr('colspan', '2')
		           :wikitext('\n{|\n|- style="background:' ..  p.getTaxoboxColor(frame) .. ';"')
		           :wikitext('\n'..tostring(frame:expandTemplate{ title = 'taxobox/species', 
									    		                  args = {parent.args[status..'_system'] or '',
									    		                  	      parent.args[status] or '',
									    		                  	      parent.args[status..'_ref'] or '',
									    		                  	      extinct=parent.args['extinct'] or ''  
									    		                  	      }
    	          	                                         	}))
    	          	:wikitext('\n|}')
    end
end

--[[ function to add sections for taxonomic information with authorities ('_authority' suffix)
        e.g. binomial, trinomial, type_species, type_genus; diversity also handled here
--]]
function p.addTaxonSection(frame, taxoboxTable, target, headerText)
	
    -- return if we don't have value
	if not parent.args[target]  or parent.args[target] == '' then return end
	
	local bold = "" -- variable for bolding binomial and trinomial (type genus/species etc are not bolded)
	-- custom processing section
	if target == 'binomial' or target == 'binomial2' or target == 'binomial3' or target == 'binomial4' then
		headerText = '[[Binomial nomenclature|' .. headerText .. ']]'
		bold ="'''"
	elseif target == 'trinomial' or target == 'trinomial2' or target == 'trinomial3' or target == 'trinomial4' then
		local trinomenLink = "Trinomen" -- for zoological or default
		if parent.args['auto'] ==  "infraspeciesbox" then trinomenLink = "Infraspecific name (botany)" end -- regnum contains plant/fung/Archaeplastida"
		headerText = '[['.. trinomenLink .. '|' .. headerText .. ']]'
		bold ="'''"
	else
	   --TODO is any handling needed for binomial2/3/4, diversity etc	
	   headerText = '[[' .. headerText .. ']]'
	end
    
	if parent.args[target..'_ref'] then
			headerText = headerText .. parent.args[target..'_ref'] .. '\n'
	 end
	
	local contentString = ''   -- content for the content cell
	if target == 'diversity' and parent.args['diversity'] ~= "" then
		if parent.args[target..'_link'] and parent.args[target..'_link'] ~= "" then 
		    contentString =  '\n[[' .. parent.args[target..'_link'] .. '|' .. parent.args[target] .. ']]\n' 
		else
			contentString =  '\n' .. parent.args[target] .. '\n'
		end
	 else
	 	-- taxon name and authority (binomial, type species, etc)
		local authorityString = ''
		if parent.args[target..'_authority'] then
			authorityString = '<br/><small>' .. parent.args[target..'_authority'] .. '</small>\n' 
		end 
		contentString = '\n' .. bold .. parent.args[target] .. bold .. authorityString .. '\n' 
    end 	 
	
	-- add table rows
	if parent.args[target] and parent.args[target] ~= '' then
		local rowHeader = taxoboxTable:tag('tr')
		rowHeader  :tag('th')
		           :attr('colspan', '2')
		           :addClass('section-header')
		           :cssText('background:' ..  p.getTaxoboxColor(frame) .. ';')
		           :wikitext( headerText )                   

		local rowList = taxoboxTable:tag('tr')
		rowList    :tag('td')
		           :attr('colspan', '2')
		           :addClass('section-content')
		           :cssText('text-align:center;') --font-weight:bold;')
		           :wikitext( contentString )

	 end	
end
----------------------------------------------------------------------------------------
--[[ function to produce sections for included taxa (subdivisions), synonyms, etc
      - each consists of two rows containing a header and the content
      - for paraphyletic groups it has include(d|s) and exclude(d|s) groups 
      - for general taxobox it has subdivision and possible subdivision (disabled here)
      - any can be modified for other purposes (e.g. sisters) by changing the header taxt with a -text parameter
  ]]
function p.addListSection(frame, taxoboxTable, target, headerText)
   
    local refString = ''
	if parent.args[target..'_ref'] then
		   --add '_ref' option for 'synonym_ref' (the rest get it as a bonus) TODO check example
			refString = parent.args[target..'_ref'] .. '\n' 	
	 end
	
	-- add table rows
	if parent.args[target] and parent.args[target] ~= ''then
		local rowHeader = taxoboxTable:tag('tr')
		rowHeader  :tag('th')
		           :attr('colspan', '2')
		           :addClass('section-header')
		           :cssText('background:' .. p.getTaxoboxColor(frame) .. ';')
		           :wikitext(parent.args[target..'-text'] or headerText .. refString)                   

		local rowList = taxoboxTable:tag('tr')
		rowList    :tag('td')
		           :attr('colspan', '2')
		           :addClass('section-content')
		           :wikitext('\n' .. parent.args[target] .. '\n' )	
	 end	
end
-----------------------------------------------------------------------------------------------
--[[ function to add image section
     used for images at top and for range maps
--]]
function p.addImageSection(frame, taxoboxTable, target)
	   
	 if parent.args[target] and parent.args[target] ~= '' then
	 	
        local imageWidth = ''
        local imageCaptionString = ''
        if parent.args[target..'_caption'] then 
        	imageCaptionString = '<br /><small><div style="text-align:center">'..parent.args[target ..'_caption']..'</div></small>' 
        end
        local imageAltString = ''
        if parent.args[target..'_alt'] then
        	imageAltString = parent.args[target..'_alt']
        elseif parent.args[target..'_caption'] then
        	imageAltString = parent.args[target..'_caption'] -- use caption for alt text if none provided
        end 
        local upright = parent.args['image_upright'] or 1
        
        local InfoboxImage = require( 'Module:InfoboxImage' ) --, parent.args[target]  )
        local params = { args = { 	image = parent.args[target],
							        size = parent.args[target..'_width'],
							        sizedefault = 'frameless',
							        alt = imageAltString,
							        upright = parent.args[target..'_upright'] or upright 
							        }
					    }
					    
        local image = InfoboxImage.InfoboxImage(  params )
        
	    --local rowImage = taxoboxTable:tag('tr') 
	    local rowImage = mw.html.create('tr')
		rowImage:tag('td')
					 :attr('colspan', '2')
		             :addClass(target)
		             :wikitext(image)
		             :wikitext(imageCaptionString)
        
        taxoboxTable:node(rowImage)
    end
    
    -- TODO handle upright
	
end 
-----------------------------------------------------------------------
--[[  adds a table showing the taxonomy
      uses either manual parameters or the automatic taxonomy system
      currently adds a table inside a cell (like paraphyletic group) rather than just adding rows (core taxobox system)
--]]    
         
function p.addTaxonomySection(frame, taxoboxTable)

	local taxonomyHeader = '[[Taxonomy_(biology)|Scientific classification]]'
	if parent.args['virus_group']  then 
		taxonomyHeader = '[[Virus classification]]'
	else
		-- TODO add other options
	end
	
	-- add symbol and link to taxonomy editor
	local editLink = ''
	if parent.args['auto'] then
	    local tooltip = parent.args['edit link'] or "Edit this classification"
		editLink  = '<span class="plainlinks" style="font-size:smaller; float:right; padding-right:0.4em; margin-left:-3em;">'
			.. '[[File:Red Pencil Icon.png|link=Template:Taxonomy/' .. parent.args['parent']
			.. '|' .. tooltip  .. ']]</span>'
	end
	
	local rowTaxonomyHeader = taxoboxTable:tag('tr')
	rowTaxonomyHeader:tag('th')
	           :attr('colspan', '2')
	           :addClass('section-header')
	           :cssText('background:' ..  p.getTaxoboxColor(frame) .. ';')
	           :wikitext(taxonomyHeader)
	           :wikitext(editLink)

	if parent.args['auto'] then 
	    --p.addAutomaticTaxonomy(frame, taxoboxTable)   -- use #invoke of module
	    p.addAutomaticTaxonomy2(frame, taxoboxTable)  -- use expandTemplate
	else
		p.addManualTaxonomy(frame, taxoboxTable, data.taxonRanks) -- just add rows
    end
end
-------------------------------------------------AUTOMATIC TAXONOMY (using invoke of module function) -----------
function p.addAutomaticTaxonomy(frame, taxoboxTable) -- use invoke of module function
	--emulate template: {{taxobox/taxonomy}}
	--which uses {{#invoke:Autotaxobox|taxoboxList


    local bold_first = 'bold'
    if parent.args['species'] then 	bold_first = 'link'    end

    local localFrame = frame -- this may not work as intended; it just creates another reference to the same table object
    localFrame.args[1] = parent.args['parent'] or tostring( mw.title.getCurrentTitle() )
	localFrame.args['display_taxa']        = (parent.args['display_taxa'] or 1 )
	localFrame.args['authority']           = parent.args['parentauthority']
	localFrame.args['parent_authority']    = parent.args['grantparent_authority']
	localFrame.args['gparent_authority']   = parent.args['greatgrandparent_authority']
	localFrame.args['ggparent_authority']  = parent.args['greatgreatgrandparent_authority']
	localFrame.args['gggparent_authority'] = parent.args['greatgreatgreatgrandparent_authority']
	localFrame.args['bold_first']          = bold_first


	local autotaxa = require("Module:Autotaxobox")
	local autoTaxonomy = autotaxa.taxoboxList(localFrame)
    
    local row = taxoboxTable:tag('tr')  --  incompatible with the templates called
                        :wikitext('\n|rank ||taxon name ')  
                        :wikitext('\n'.. autoTaxonomy )  -- autoTaxonomy ends with a new row (|-)at end
                        :wikitext('\n|x ||y ')                 -- so add blank cells to complete extra row
                                                               --   this and affects spacing in taxonomy rows
                        --:wikitext('\n')                      -- spacing fine, newline for table wikitext
                        
                    
    --[[ note:  the output of {{taxobox/showtaxon}} [used by invoke:Autotaxobox|taxoboxList] ends with a newline token
                this and affects spacing in taxonomy rows
                leaving the empty row results in spurious paragraphs above the table
                 t his and affects spacing in taxonomy rows
           it is present in current taxoboxes but not visible
           results in 
  
      ]]
	return 
end
----------------------------------------------------AUTOMATIC TAXONOMY (using template) ------------------------
function p.addAutomaticTaxonomy2(frame, taxoboxTable)  -- use template and expand
	--emulate template: {{taxobox/taxonomy}}
	--which uses {{#invoke:Autotaxobox|taxoboxList

    local bold_first = 'bold'
    if parent.args['species_name'] then 	bold_first = 'link'    end
                                                -- defaults are now handled earlier 
    local templateArgs = {  parent.args['parent'],  -- or tostring( mw.title.getCurrentTitle() ), 
							parent.args['display_taxa'], -- or 1,
							authority=parent.args['authority'],
			                parent_authority=parent.args['parent_authority'],
			                grandparent_authority=parent.args['grandparent_authority'],
			                greatgrandparent_authority=parent.args['greatgrandparent_authority'],
			                greatgreatgrandparent_authority=parent.args['greatgreatgrandparent_authority'],
			                bold_first
		                	}
	templateArgs['bold first']= bold_first

    local autoTaxonomy = frame:expandTemplate{ title = 'taxobox/taxonomy', args = templateArgs } 
   
    --[[ NOTE: the auto taxonomy system uses wikitext for the table 
    			mixing the mw.html and wikitext causes problems with table structure
    			therefore the automatic taxonomy is embedded as a table table
    --]]
    local row = taxoboxTable:tag('tr')
    local cell = row:tag('td'):attr('colspan', '2')
    cell:wikitext('\n{|\n|-')
              --:wikitext('\n|rank \n|taxon name ')
              :wikitext('\n|-\n' .. autoTaxonomy )  -- autoTaxonomy ends with a new row (|-)at end
    if parent.args['species_name'] then                  -- so add species or blanks to complete extra row
        --TODO add subgenus handling
        cell:wikitext('\n|Species: ||' .. parent.args['species_name']) -- so add blank cells to complete extra row
        if parent.args['subspecies_name'] then 
        	cell:wikitext('\n|-\n|Subspecies: ||' .. parent.args['subspecies_name']) -- add subspecies/infraspecies
        end
        if parent.args['variety_name'] then 
        	cell:wikitext('\n|-\n|Variety: ||' .. parent.args['variety_name']) -- add subspecies/infraspecies
        end
        --TODO handle authority (or do we need to repeat it as shown in binomial/trinomial?)
        -- cell:wikitext(' authority')
    else
    	--cell:wikitext('\n|x ||y ') 
    end
    cell:wikitext('\n|}')                      -- end embedded table for automatic taxonomy
                        
	return 
end

----------------------------------------MANUAL TAXONOMY--------------------------------

function p.addManualTaxonomy(frame,taxoboxTable, taxonRanks)
	
	--local parent = mw.getCurrentFrame():getParent()
	--local taxonRanks = data.taxonRanks
	
	-- following {{Paraphyletic group, a table is add to the cell in the classification row
	--local taxonomyTable = mw.html.create('table'):addClass('taxonomy')
	
	-- an alternative is to dispense with the extra table and just add the rows (like taxobox/core), 
	--    which would need colspan=2 on other rows (DONE)
	local taxonomyTable = 	taxoboxTable  
	
	for k,v in pairs(taxonRanks) do
		
		if parent.args[v] then
		    local row = taxonomyTable:tag('tr')
		    local taxonName = parent.args[v]
		    
		    local taxonRank = frame:expandTemplate{ title = "anglicise rank", args = {taxonRanks[k]} }
		  
		    if taxonRanks[k] == "virus_group" then
		    	taxonName = frame:expandTemplate{ title = "Virus group", args = {parent.args[v]} }
		    --	taxonRank = "Group" -- handled by anglicise rank template
		    end
		    local authorityString = ''
		    if parent.args[taxonRanks[k]..'_authority'] then
		    	authorityString = '<br /><small>'..parent.args[taxonRanks[k]..'_authority']..'</small>'
		    end
	     	row:tag('td'):wikitext(taxonRank..':')
		    row:tag('td'):wikitext('<span class="'.. taxonRanks[k] ..'">'..taxonName..'</span>'..authorityString)
		    --:wikitext('<br /><small>'..parent.args[taxonRanks[k]..'_authority']..'</small>')

		end 
	end -- end for loop
	
	return tostring(taxonomyTable)
end

-----------------------------------------------TAXOBOX COLOUR--------------------------------------
	
function p.getTaxoboxColor(frame)
	
	if  parent.args['auto'] then 
	--[[TODO add autotaxobox colours as option
	   (1) if color_as|colour_as|color as|colour as set, use template {{Taxobox colour|color_as}}
	   	   (2) use the auto taxonnomy tree to find colour: {{#invoke:Autotaxobox|taxoboxColour| }}
	    {{#invoke:Autotaxobox|taxoboxColour|{{{parent|{{{genus|{{first word|{{{taxon|{{PAGENAME}} }}
	--]]
		if (parent.args['color_as'] and parent.args['color_as'] ~= "") or
		   (parent.args['colour_as'] and parent.args['colour_as'] ~= "") or
		   (parent.args['color as'] and parent.args['color as'] ~= "") or
		   (parent.args['colour as'] and parent.args['colour as'] ~= "") then
		    
		   local colorAs = ""
		   if parent.args['color_as'] then colorAs = parent.args['color_as']  end
		   if parent.args['colour_as']  then colorAs =  parent.args['colour_as'] end
		   if parent.args['color as'] then colorAs =  parent.args['color as'] end
		   if parent.args['colour as']  then colorAs =  parent.args['colour as']  end
		    
		    return frame:expandTemplate{ title = 'Taxobox colour', args = {colorAs} }
		    
		else
			-- us #invoke:Autotaxobox|taxoboxColour|{{{parent}}} [parent should be set]
			
			frame.args[1] = parent.args['parent']
	        return autotaxa.taxoboxColour(frame)
			--return	"palegreen"
		end
	else -- use manual taxobox colours
		--{{Taxobox colour|{{{regnum|{{{virus_group|{{{unranked_phylum|{{{phylum|''[[Incertae sedis]]''}}}}}}}}}}}}}}

		local group =''
		if (parent.args['color_as'] and parent.args['color_as'] ~= "") then
			group = parent.args['color_as'] 
		elseif parent.args['regnum'] then
			group = parent.args['regnum']
		elseif parent.args['virus_group'] then
			group = parent.args['virus_group']
		elseif parent.args['unranked_phylum'] then
			group = parent.args['unranked_phylum']
		elseif parent.args['phylum'] then
			group = parent.args['phylum']
		else
			group = "''[[Incertae sedis]]''"          -- TODO check if this is what was desired
		end
	  
	    return frame:expandTemplate{ title = 'Taxobox colour', args = {group} }
	end
end

function p.templateStyle( frame, src )
   return frame:extensionTag( 'templatestyles', '', { src = src } );
   
end	

-----------------------------------------
function p.test(frame)
	if 1==1 then return end  -- disable
	local root = mw.html.create('table'):addClass('wikitable')

	local row = root:tag('tr')                -- add row using lua library
	local cell = row:tag('td')
	cell:wikitext('row A:')
	cell = row:tag('td'):wikitext('content A')  

	row = root:tag('tr')                      -- add row using lua library 
	cell = row:tag('td'):wikitext('row B:')
	cell = row:tag('td')
	          :wikitext('\n{|\n|-\n|P\n|Q\n|}') --but include a wikitxt table in one cell
	         -- :done()

   -- row:done()
    --root=mw.html:allDone()
    root:wikitext('<tr><td>a</td><td>b</td></tr>') -- add row to root using html 
    root:wikitext('\n|-\n|X\n|Y\n')              -- add row to root using wikitext (FAILS) 
    
    root:wikitext('\r|-\r|I\r|J\r')              -- FAIL output |- |X |Y 
	
	root:wikitext(frame:preprocess('\n|-\n|U\n|V\n')) -- FAIL output |- |U |V 
	
	root:wikitext('<tr>\n|M\n|N\n</tr>')    
	

	row=root:tag('tr'):node('<td>c</td><td>d</td>')    -- adds row successfully
	row=root:tag('tr'):node('\n|Xc\n|Xd\n')    -- fails to adds row
	
	
	row = root:tag('tr')                       -- add another row using lua library
	cell = row:tag('td'):wikitext('row C:')
	cell = row:tag('td'):wikitext('content C')

	root:node('\n{|\n|-\n|Xx\n|Yx\n|}\n')    -- adds new table after

	--frame:preprocess
	return 	 tostring(root)

--[[ CONCLUSION: cannot mix wikitext freely in the node structure
           A complete wikitext table can be included in a cell (e.g. used for automatic taxonomy now)
           An alternative is to use wikitext for the whole taxobox table
]]
end


-- All modules end by returning the variable containing its functions to Wikipedia.
return p