Mô đun:Clade

--NOTE: this module contains functions for generating the table structure of the clade tree: 
The main function is called by the template using the  instruction; the three main functions are:
p.main(frame) - opens and closes table, loops through the children of node, main is invoked once and controls the rest, calling ...
p.addTaxon(childNumber, nodeLeaf) - the nuts and bolts; code dealing with each child node
p.addLabel(childNumber) - adds the label text

now uses templatestyles
require('strict')
local p = {}
local pargs = {}  -- parent arguments
local lastNode=0
local nodeCount=0
local cladeCount=0
local leafCount=0
local templateStylesCount=0
local infoOutput
local reverseClade = false
--============================== main function  =======================**
-- main function, which will generate the table structure of the tree
Test version:
Usage: 
Template:CladeN
Release version:
Usage: 
Template:Clade
function p.main(frame)
	local cladeString = ""	
	local maxChildren = 20 -- was 17 in the clade/cladex templates
	local childNumber = 0
	local childCount = 0 -- number of leaves in the clade (can use to set bottom of bracket in addTaxon()
	local totalCount = 0
	
	pargs = frame:getParent().args -- parent arguments
	
infoOutput = p.getCladeTreeInfo() -- get info about clade structure, e.g. lastNode (last |N= child number)

-- add the templatestyles tag  conditionally to reduce expansion size (currently diabled)
when added to every clade table, it increases post‐expand include size significantly
e.g. the Neosuchia page (or test version) is increase by about 8% (672 bytes each)
if template styles added to all pages there are 133 stripmarkers 
with cladeCount==1 condition, this is reduced to 34
however cladeCount==1 condition interfers with fix for additional line due to parser bug T18700
killing the strip markers also removes backlinks to references using citation templates 
--
--cladeString =mw.text.killMarkers( cladeString ) -- also kills off strip markers using citation templates
--cladeString = mw.text.unstrip(cladeString)
--if cladeCount==1  then 
	local src = "Template:Clade/styles.css"
	cladeString = cladeString .. p.templateStyle( frame, src ) .. '\n'
--end	

	local tableStyle = frame.args.style or ""
	if tableStyle ~= "" then
		tableStyle = ' style="' .. tableStyle .. '"' -- include style= in string to suppress empty style elements
	end

reverseClade =frame.args.reverse or pargs.reverse or false -- a global
--ENFORCE GLOBAL FOR DEVELOPMENT
--reverseClade = true
	local captionName  = pargs'caption' or ""
	local captionStyle = pargs'captionstyle' or ""
-- add an element to mimick nowiki WORKS BUT DISABLE FOR DEMO PURPOSES
--cladeString = '\n'

	-- open table	
	-- (border-collapse causes problems (see talk) -- cladeString = cladeString .. 
	
	cladeString = p.addSubTrees(cladeString) -- add subtrees
	
	return cladeString
	--return '\n' .. cladeString .. 
end
-- =============================function to add subtrees ========================================== 
function p.addSubTrees(cladeString)
	
	--local pargs = mw.getCurrentFrame():getParent().args 
	
	local suffix = { 1="A", 2="B", 3="C", 4="D", 5="E", 6="F", 7="G", 8="H", 9="I", 10="J", 
		             11="K", 12="L", 13="M", 14="N", 15="O", 16="P", 17="Q", 18="R", 19="S", 20="T", 
		             21="U", 22="V", 23="W", 24="X", 25="Y", 26="Z", -1="-1", 0="0"}
for i=27, 500, 1 do
	suffixi = tostring(i)
end
for i=-100, 0, 1 do
	suffixi= tostring(i)
end
	for i=-100, 500, 1 do
		local subclade = pargs'subclade'..suffixi
		local target = pargs'target'..suffixi or "SUBCLADE_" .. suffixi
		if subclade  then 
			if string.find(cladeString, target) then
				cladeString = string.gsub(cladeString,target,subclade)
			end
		end
end
	return cladeString
end
--3 ...) use a left border to create the vertical line of the bracket
	     the first child element doesn't use a left border for the first cell in the top row (as it is above the bracket)
	     the last child doesn't use a left border for the first cell in the second row (as it is below the bracket)
function p.addTaxon(childNumber, nodeLeaf, nodeLabel, lastNode)
	--state
	
local nodeColor = pargs'color' or ""                 -- don't set default to allow green on black gadget
	local nodeThickness = tonumber(pargs'thickness') or 1
	local nodeState = pargs'state' or "solid"
	-- get border formating parameters for branch (default to global nodeParameters)
	local branchColor = pargs'color'..tostring(childNumber) or nodeColor 
	local branchThickness = tonumber(pargs'thickness'..tostring(childNumber)) or nodeThickness
	local branchState = pargs'state'..tostring(childNumber) or nodeState 
	if branchState == 'double' then 
		if branchThickness  1 then prefix = 'max-' end
			branchLengthStyle = branchLengthStyle --= prefix  .. 'width:' .. branchLength .. ';' 
										.. 'max-width:' .. branchLength ..';'
			                            .. 'padding:0em;'         -- remove padding to make calculation easier
						-- following moved to styles.css
						--				.. 'white-space:nowrap'
						--				.. 'overflow:hidden;'    -- clip labels longer than the max-width
						--				.. 'text-overflow:clip;' -- ellipsis;'
		    widthClass = " clade-fixed-width"
		end
		styleString = 'style="' .. borderStyle .. branchLengthStyle .. branchStyle .. labelStyle .. '"'
end	
	if childNumber == 1 then
		classString= 'class="clade-label first'.. widthClass .. '" '                  -- add class "first" for top row
else
	classString = 'class="clade-label' .. reverseClass .. widthClass .. '" ' -- add "reverse" class if ltr cladogram
end
--  wikitext for cell with label
local labelCellString = '\n|' .. classString .. styleString  .. '|' .. p.addLabel(childNumber,nodeLabel) -- p.addLabel(nodeLabel)

--cladeString = cladeString .. labelCellString
	---------------------------------------------------------------------------------
	-- (3) add cell with leaf (which may be a table with transluded clade content)

if barRight  ~= "0"  then 
	if reverseClade then -- we want the bar on the left
		styleString = ' style="border-left:' .. barRight .. ';border-bottom:' .. barBottom .. ';border-top:' .. barTop .. ';' .. branchStyle .. '"'
	else
		styleString = ' style="border-right:' .. barRight .. ';border-bottom:' .. barBottom .. ';border-top:' .. barTop .. ';' .. branchStyle .. '"'
	end
else
	if (branchStyle ~= ) then
		styleString = ' style="' .. branchStyle .. '"'
else
	styleString =  -- use defaults in styles.css
end
end

classString = 'class="clade-leaf' .. reverseClass .. '"'
--note: the \n causes plain leaf elements get wrapped in  with style="margin:0.4em 0 0.5em 0;" 
	       this adds spacing to rows, but is set by defaults rather than the clade template
	       it also means there are two newlines when it is a clade structure (which might explain some past issues)

local content = '\n' .. nodeLeaf  -- the newline is not necessary, but keep for backward compatibility
-- test using image parameter
local image = pargs'image'..tostring(childNumber) or ""  
if image ~= "" then                                   
	--content = content .. image -- basic version
	content = '\n'
	-- note: the classes interfere with the node counter, so try simpler version with style
content = '\n'
end
-- wikitext for leaf cell (note: nodeLeaf needs to be on newline if new wikitable)
--                         but that is no longer the case (newline is now forced)
--                         the newline wraps plain leaf terminals in  with vertical padding (see above)
--local leafCellString = '\n|rowspan=2 ' .. classString  .. styleString .. ' |\n' .. content -- the new line causes  wrapping for plain leaf terminals
local leafCellString = '\n|rowspan=2 ' .. classString  .. styleString .. ' |' .. content

--cladeString = cladeString .. leafCellString

-------------------------------------------
-- (4) stuff for right-hand bracket labels
	classString='class="clade-bar' .. reverseClass .. '"'
	
local barLabelCellString = 
	if barRight  ~= "0"  and barLabel ~= "" then 
	   barLabelCellString = '\n|rowspan=2 ' .. classString .. ' |' .. barLabel
	else -- uncomment following line to see the cell structure
	   --barLabelCellString = '\n|rowspan=2 ' .. classString .. ' |' .. 'BL'
	end 
	
	if groupLabel ~= "" then 		
		barLabelCellString = barLabelCellString .. '\n|rowspan=2 ' .. classString .. ' style="'.. groupLabelStyle .. '" |' .. groupLabel 
	else -- uncomment following line to see the cell structure
	    --barLabelCellString = barLabelCellString .. '\n|rowspan=2 ' .. classString .. '" |' .. 'GL' 
end 	
--cladeString = cladeString .. barLabelCellString

	-------------------------------------------------------------------------------------
	-- (5) add second row (only one cell needed for sublabel because of rowspan=2); 
	--     note: earlier versions applied branch style to row rather than cell
	--           for consistency, it is applied to the sublabel cell as with the label cell
	
	--cladeString = cladeString .. '\n
	
	-----------------------------------
	-- (6) add cell containing sublabel
	
	local subLabel = pargs'sublabel'..tostring(childNumber) or ""  -- request in addLabel
	
	-- FOR TESTING: use subLabel for annotating the clade structues to use structure information (DEBUGGIING ONLY)
	--if childNumber==lastNode then subLabel= infoOutput end
	-- END TESTING
	
	borderStyle = 
	styleString = 
	if useInlineStyle then
		if childNumber==lastNode then 		-- if childNumber==lastNode we don't want left border, otherwise we do
			borderStyle = 'border-right:none;border-left:none;'
	    else
	 		if reverseClade then
	    		borderStyle  = 'border-left:none;border-right:' .. leftBorder .. ';' 
	 	    else
	    		borderStyle  = 'border-right:none;border-left:' .. leftBorder .. ';'  
	    	end
	    end 
end
if borderStyle ~=  or  branchStyle ~=  or  branchLength ~=  or sublabelStyle ~= "" then         
		local branchLengthStyle = ""
		if branchLength ~= "" then 
			if childNumber == 1 then
				branchLengthStyle = 'width:' .. branchLength .. ';'  -- add width to first element
			end
			--if childNumber > 1 then prefix = 'max-' end
			branchLengthStyle = branchLengthStyle --= prefix  .. 'width:' .. branchLength .. ';' 
										.. 'max-width:' .. branchLength ..';'
			                            .. 'padding:0em;'         -- remove padding to make calculation easier
		end
		styleString = 'style="' .. borderStyle .. branchLengthStyle .. branchStyle .. sublabelStyle .. '"'
--styleString = ' style="' .. borderStyle .. branchStyle .. sublabelStyle .. '"'
end
--local sublabel = p.addLabel(childNumber,subLabel)
if childNumber == lastNode then 
	classString = 'class="clade-slabel last' .. widthClass .. '" ' 
else
classString = 'class="clade-slabel' .. reverseClass .. widthClass .. '" '
end
local sublabelCellString = '\n|' .. classString .. styleString .. '|' ..  p.addLabel(childNumber,subLabel)

--cladeString = cladeString .. sublabelCellString
-- constuct child element wikitext
if reverseClade then
	    cladeString = cladeString .. '\n
	    cladeString = cladeString .. barLabelCellString
	    cladeString = cladeString .. leafCellString
	    cladeString = cladeString .. labelCellString
		cladeString = cladeString .. '\n
		cladeString = cladeString .. sublabelCellString
else	
	    cladeString = cladeString .. '\n
	    cladeString = cladeString .. labelCellString
	    cladeString = cladeString .. leafCellString
	    cladeString = cladeString .. barLabelCellString
		cladeString = cladeString .. '\n
		cladeString = cladeString .. sublabelCellString
end

	return cladeString
end
-- adds text for label or sublabel to a cell
function p.addLabel(childNumber,nodeLabel)
	
	--local nodeLabel = mw.getCurrentFrame():getParent().args'label'..tostring(childNumber) or ""
	--local firstChars = string.sub(nodeLabel, 1,2) -- get first two characters; will be