Jump to content

Module:Haplogroup

From Wikidata
Lua
CodeDiscussionLinksLink count SubpagesDocumentationTestsResultsSandboxLive code All modules

Module used at Wikidata:WikiProject Haplogroups. A derivative version of Template:Tree.

Tree structure is generated by tracking "followed by (P156)" from the first item. By setting direction = parent, tracking is done through "follows (P155)" toward ancestral direction.

If item page has link to Wikipedia (of your setting language), Wikimedia Commons, or haplogroup.org, it is shown next to each haplogroup name. (Do not use haplogroup.org as source but use it to find original sources.)

If there are other data (for example, "date of birth (P569)", "place of birth (P19)", or "locator map image (P242)"), it is shown by clicking [Show detail] button at the top-left of the tree.

Example

[edit]
Input

{{ #invoke:Haplogroup | main | firstItemId = Q3491260| maxdepth = 10 | highlight = Q1584156}}

Output


Input

{{ #invoke:Haplogroup | main | firstItemId = Q3491260| maxdepth = 10 | highlight = Q45070466| direction = parent }}

Output

See also

[edit]

Template:Tree, original of this module.

Code

-- This is derivative version of [[Module:Tree]]. See https://www.wikidata.org/wiki/Template:Tree
--
-- Usage example
--
-- {{#invoke:Haplogroup|main|firstItemId= Q221674|maxdepth=25}}
--
-- firstItemId: First item ID. This item become the root of the tree.
-- maxdepth: Maximum depth of the tree.

local p = {}

datas = {}


-- These setdata() and getdata() functions are used to access (read and write) to "datas" table
function p.setdata(n, key, val)
	if datas[n] == nil then
		datas[n] = {}
	end
	datas[n][key] = val
end

function p.getdata(n, key, defval)
	if  datas[n] == nil or datas[n][key] == nil then
		return defval
	else
		return datas[n][key] 
	end
end

function p.children(itemId, property, direction, maxdepth, lang1, lang2 )
 --------------------------------------------------------------------------------
 -- children function which listing all childrens that certain item has.
 -- Not listing grand childrens, or grand-grand childrens. Listing only childrens.
 -- Final returning value "childrens" is like {Q123123, Q3984198237, Q1874138746} 
 --------------------------------------------------------------------------------
	local childrens = {}
	local entity = mw.wikibase.getEntity( itemId )
	local claims = nil
	local x = 1
	local tmpValue = {}
	
	---------------------------------------------------------------
	-- Start collecting data from the retrieved entity, and save that into the datas[] table.
	-- Because getEntity() function is EXPENSIVE, so here, collecting all data at once.
	-- https://en.wikipedia.org/wiki/WP:EXPENSIVE
	-- https://www.mediawiki.org/wiki/Extension:Wikibase_Client/Lua#mw.wikibase.getEntity
	----------------------------------------------------------------
	local globalSiteId_1 = lang1 .. 'wiki'
	local globalSiteId_2
	
	if lang2 and lang2 ~= '' then
		globalSiteId_2 = lang2 .. 'wiki'
	else
		globalSiteId_2 = nil
	end
	
	p.setdata(itemId, "sitelink_1", entity:getSitelink( globalSiteId_1 ))
	p.setdata(itemId, "label_1", entity:getLabelWithLang( lang1 ))
	
	local claimShort = entity['claims']['P1813'] -- variable for P1813 (Short name)
	if claimShort and claimShort ~= '' then
		p.setdata(itemId, "short", claimShort[1].mainsnak.datavalue.value.text) --
	end
	
	local claimDate = entity['claims']['P569'] -- variable for P569 (Date of birth)
	if claimDate and claimDate ~= '' then
		p.setdata(itemId, "date", claimDate[1].mainsnak.datavalue.value) --
	end
	
	local claimsPlace = entity['claims']['P19'] -- variable for P19 (Place of birth)
	local tmpPlcae = nil
	if claimsPlace and claimsPlace ~= '' then
		for  _,claim in pairs( claimsPlace ) do --Various place can be registered in this property. So marging these all places.
			if tmpPlcae and tmpPlcae ~= '' then
				tmpPlcae = tmpPlcae .. ', ' .. mw.getCurrentFrame():expandTemplate{ title = 'LinkedLabel', args = { claim.mainsnak.datavalue.value.id } }
			else
				tmpPlcae = mw.getCurrentFrame():expandTemplate{ title = 'LinkedLabel', args = { claim.mainsnak.datavalue.value.id } }
			end
		end
		p.setdata(itemId, "place", tmpPlcae)
	end
	
	local claimsPossessor = entity['claims']['P127'] -- variable for P127 (Owned by)
	local tmpPossessor = nil
	if claimsPossessor and claimsPossessor ~= '' then
		for  _,claim in pairs( claimsPossessor ) do --Various place can be registered in this property. So marging these all places.
			if tmpPossessor and tmpPossessor ~= '' then
				tmpPossessor = tmpPossessor .. ', ' .. mw.getCurrentFrame():expandTemplate{ title = 'LinkedLabel', args = { claim.mainsnak.datavalue.value.id } }
			else
				tmpPossessor = mw.getCurrentFrame():expandTemplate{ title = 'LinkedLabel', args = { claim.mainsnak.datavalue.value.id } }
			end
		end
		p.setdata(itemId, "possessor", tmpPossessor)
	end
	
	local claimsRefSeq = entity['claims']['P2249'] -- variable for P2249 (Refseq Genome ID)
	local tmpRefSeq = nil
	if claimsRefSeq and claimsRefSeq ~= '' then
		for  _,claim in pairs( claimsRefSeq ) do --Various place can be registered in this property. So marging these all places.
			if tmpRefSeq and tmpRefSeq ~= '' then
				tmpRefSeq = tmpRefSeq .. ', ' .. '[https://www.ncbi.nlm.nih.gov/nuccore/' .. claim.mainsnak.datavalue.value .. '?report=fasta ' .. claim.mainsnak.datavalue.value .. ']'
			else
			
				tmpRefSeq = '[https://www.ncbi.nlm.nih.gov/nuccore/' .. claim.mainsnak.datavalue.value .. '?report=fasta ' .. claim.mainsnak.datavalue.value .. ']'
			end
			tmpRefSeq = '' .. tmpRefSeq .. ''
		end
		p.setdata(itemId, "refseq", tmpRefSeq)
	end
	
	local claimMapIamge = entity['claims']['P242'] -- variable for P242 (locator map image)
	if claimMapIamge and claimMapIamge ~= '' then
		p.setdata(itemId, "mapimage", claimMapIamge[1].mainsnak.datavalue.value) --
	end
	
	--{{#invoke: Wikidata|Dump|claims|P155|1|references|1|snaks|P854|1|datavalue|value}}
	local claimsPhyloTreeURL = entity['claims']['P155'] -- variable for phylotree.org URL taken from reference data in P155 (follows)
	local tmpPhyloTreeURL
	if claimsPhyloTreeURL then
		for  _,claim in pairs( claimsPhyloTreeURL ) do --Various website can be registered in this property. So picking-up only haplogroup.org website.
			for _,reference in pairs( claim.references ) do
				if reference.snaks['P854'] then
					tmpPhyloTreeURL = reference.snaks['P854'][1].datavalue.value
					if string.find( tmpPhyloTreeURL, 'phylotree.org') then
						p.setdata(itemId, "phylotree.org", tmpPhyloTreeURL)
					end
				end
			end
		end
	end
	
	local claimsDescribedURL = entity['claims']['P973'] -- variable for haplogroup.org URL in P973 (described at URL)
	local tmpDescribedURL
	if claimsDescribedURL then
		for  _,claim in pairs( claimsDescribedURL ) do --Various website can be registered in this property. So picking-up only haplogroup.org website.
			tmpDescribedURL = claim.mainsnak.datavalue.value
			if string.find( tmpDescribedURL, 'haplogroup.org') then
				p.setdata(itemId, "haplogroup.org", tmpDescribedURL)
			end
			if string.find( tmpDescribedURL, 'yfull.com') then
				p.setdata(itemId, "yfull.com", tmpDescribedURL)
			end
		end
	end
	
	local claimCommons = entity['sitelinks'] -- variable for Wikimedia Commons
	if claimCommons and claimCommons ~= '' then
		if claimCommons.commonswiki and claimCommons.commonswiki ~= '' then
			p.setdata(itemId, "commons", claimCommons['commonswiki'].title) --
		end
	end
	
	if lang2 and lang2 ~= '' then
		p.setdata(itemId, "sitelink_2", entity:getSitelink( globalSiteId_2 ))
		p.setdata(itemId, "label_2", entity:getLabelWithLang( lang2 ))
	end
	
	---------------------------------------------------------------		
	-- End collecting data
	---------------------------------------------------------------
	
	---------------------------------------------------------------		
	-- Start collecting childrens
	---------------------------------------------------------------
	claims = entity['claims'][property]
	
	if not claims then
		return {}
	end
	
	for  _,claim in pairs( claims ) do
		local value = claim.mainsnak.datavalue.value
		local nextitem = 'Q' .. value['numeric-id']

		childrens[x] = nextitem
		x = x + 1
	end
	
	return childrens
	---------------------------------------------------------------		
	-- End collecting childrens
	---------------------------------------------------------------
end
		
-- generator, see http://lua-users.org/wiki/LuaCoroutinesVersusPythonGenerators for lua doc
-- definition a function that when called several times will generate a sequence of strings
 
-- gensymbols = create_gensymbols("ABC")
-- gensymbols() == "A" 
-- gensymbols() == "B" g
-- gensymbols() == "C" 
-- gensymbols() == "AA" '
-- gensymbols() == "BABBA"
-- ...
function p.gensymbols(chars)
	local i = 0
	local charset = chars
 
	local generator = function ()
		local symbol = ""
		local rest
 
		rest = i
 
		repeat
			local j 
			j = rest % string.len(charset)
			rest = math.floor(rest / string.len(charset))
			symbol = symbol .. string.sub(charset, j+1, j+1)
		until rest <= 0
		i = i + 1
		return symbol
	end
	return generator
end

-------------------------------------------------------------------------------------------	
-- Start definition of itemOutput function which returns text like '[[' .. link .. '|' .. label .. ']]'
-------------------------------------------------------------------------------------------	
function p.itemOutput(item, lang1, lang2, datas, setdata, getdata, highlightItemID)
		
	local globalSiteId_1 = lang1 .. 'wiki'
	local globalSiteId_2 = lang2 .. 'wiki'
	local highlightItem = highlightItemID
	
	local currentLabel
	local currentLabel_temp
	local wpLinkText = nil
	local commonsLinkText = nil
	local mapImageName = nil
	local currentPage = tostring(mw.title.getCurrentTitle().text)
	
	local content
	
	
	currentLabel = p.getdata(item, "short", nil )
	if currentLabel == nil or currentLabel == '' then
		currentLabel = p.getdata(item, "label_1", nil )
		if currentLabel == nil or currentLabel == '' then
			currentLabel = p.getdata(item, "sitelink_1", nil )
			if currentLabel == nil or currentLabel == '' then
				currentLabel = p.getdata(item, "label_2", nil )
				if currentLabel == nil or currentLabel == '' then
					currentLabel = p.getdata(item, "sitelink_2", nil )
					if currentLabel == nil or currentLabel == '' then
						currentLabel = item
					end
				end
			end
		end
	end
	
	content = '[[' .. item .. '|' .. currentLabel .. ']]'
	
	wpLinkText = p.getdata(item, "sitelink_1", nil )
	commonsLinkText = p.getdata(item, "commons", nil )
	haplogroupDotOrgText = p.getdata(item, "haplogroup.org", nil ) 
	phylotreeDotOrgText = p.getdata(item, "phylotree.org", nil ) 
	yfullDotComText = p.getdata(item, "yfull.com", nil ) 
	dateText = p.getdata(item, "date", nil )
	placeText = p.getdata(item, "place", nil )
	possessorText = p.getdata(item, "possessor", nil )
	refseqText = p.getdata(item, "refseq", nil )
	mapImageName = p.getdata(item, "mapimage", nil )
	
	if wpLinkText or commonsLinkText or haplogroupDotOrgText or yfullDotComText then 
		content = content .. ' ('
	end
	--content = content .. '[[Talk:'.. item .. '|talk]]'
	
	if wpLinkText and wpLinkText ~= '' then
		--content = content .. ', '
		if highlightItem == item then
			content = content .. '[[:w:'.. lang1 ..':' .. wpLinkText .. '|' .. lang1 ..'wiki]]'
		else
			content = content .. '[[:w:'.. lang1 ..':' .. wpLinkText .. '|' .. lang1 ..'wiki]]'
		end
	end
		
	if commonsLinkText and commonsLinkText ~= '' then
		if wpLinkText then
			content = content .. ', '
		end
		if highlightItem == item then
			content = content .. '[[:commons:' .. commonsLinkText .. '|commons]]'
		else
			content = content .. '[[:commons:' .. commonsLinkText .. '|commons]]'
		end
	end
	
	if haplogroupDotOrgText and haplogroupDotOrgText ~= '' then
		if wpLinkText or commonsLinkText then
			content = content .. ', '
		end
		content = content .. '[' .. haplogroupDotOrgText .. ' haplogroup.org]'
		--content = content .. haplogroupDotOrgText -- When checking bare URL
	end
	
	if yfullDotComText and yfullDotComText ~= '' then
		if wpLinkText or commonsLinkText or haplogroupDotOrgText then
			content = content .. ', '
		end
		content = content .. '[' .. yfullDotComText .. ' yfull.com]'
		--content = content .. yfullDotComText -- When checking bare URL
	end
		
	if wpLinkText or commonsLinkText or haplogroupDotOrgText or yfullDotComText then 
		content = content .. ')'
	end
	--red #FFDFDF|#FF9797
	--blue '#D7D1F8', '#A095EE'
	if highlightItem == item then
		--'' ..  .. ''
		content =  '' ..  mw.getCurrentFrame():expandTemplate{ title = 'Font & border color', args = {'black','#D7D1F8', '#A095EE', content} } .. ''
	end
	
	if item == 'Q46999198' then --Q46999198 is 'Haplogroup H2a2a1' which is haplogroup for CRS (Cambridge Reference Sequence)
		content = content .. ' ' .. mw.getCurrentFrame():expandTemplate{ title = 'Font & border color', args = {'black','#FFEAB7', '#FFC848', '[[:w:en:Cambridge Reference Sequence|rCRS]]'} }
	end
	
	if phylotreeDotOrgText or dateText or placeText or possessorText or refseqText or mapImageName then 
		content = content .. '
' if phylotreeDotOrgText and phylotreeDotOrgText ~= '' then content = content .. 'Reference tree: ' .. '' .. phylotreeDotOrgText .. '' end if dateText and dateText ~= '' then if phylotreeDotOrgText then content = content .. '
'
end content = content .. 'Age: ' .. dateText.time --mw.logObject(dateText) end if placeText and placeText ~= '' then if phylotreeDotOrgText or dateText then content = content .. '
'
end content = content .. 'Origin: ' .. placeText end if refseqText and refseqText ~= '' then if phylotreeDotOrgText or dateText or placeText then content = content .. '
'
end content = content .. 'Full DNA sequence: ' .. refseqText end if possessorText and possessorText ~= '' then if phylotreeDotOrgText or dateText or placeText or refseqText then content = content .. '
'
end content = content .. 'Possessor: ' .. possessorText end if mapImageName and mapImageName ~= '' then if phylotreeDotOrgText or dateText or placeText or refseqText or possessorText then content = content .. '
'
end content = content .. '[[File:' .. mapImageName .. '|x150px]]' end content = content .. '
'
end --if mapImageName and mapImageName ~= '' then --content = content .. '
▼
'
--content = content .. '
' -- content = content .. '[[File:' .. mapImageName .. '|x150px]]' --content = content .. '
'
--end return content end ------------------------------------------------------------------------------------------- -- End definition of itemOutput function which returns text like '[[' .. link .. '|' .. label .. ']]' ------------------------------------------------------------------------------------------- function p.outputTree( firstItemId, property, direction, maxdepth, lang1, lang2, highlightItemID) ------------------------------------------------------------------------------------------- -- Start preparation of functions ------------------------------------------------------------------------------------------- ----- topological sort and meta data of the DAG ( https://en.wikipedia.org/wiki/Topological_sorting ) --This firstPass() function is called only once, at first local function firstPass( firstItemId, item_repr ) --mw.log("firstItemId is: ") --mw.logObject(firstItemId) --mw.log("") --mw.log("") local content = p.itemOutput(firstItemId, lang1, lang2, datas, setdata, getdata, highlightItemID) local opened = 1 -- This means the downstream branch of the item is under processing. -- If encountering opened item through the processing, it indicates that infinite loop exists. local closed = 2 -- This means the processing of all downstream branches of the item reached to its end. -- The downest item is showed with " ? " in tree. local incomplete = 3 -- This means the processing of all downstream branches of the item reached to its end. -- If more downstream branches exist but not processed (because of limitation from maxdepth), -- then the downest item showed with "…" in tree. local marks = {} --opened(1) or closed(2) or incomplete(3) for each QID (e.g. marks[Q12234234] -> closed) --local datas = {} --datas[QID]["nparents"], datas[QID]["symbol"], datas[QID]["looped"], datas[QID]["rank"], datas[QID]["status"] --datas[QID]["nparents"] represents "number of parents" of certain item. This is normally 1. --If this is 2 or more, it means that the exact same item appears several times in defferent branches of the tree repeatedly. local childrens = {} -- for example, childrens[Q1234] contains data like {Q123123, Q3984198237, Q1874138746}, three childrens of Q1234 --while there are unmarked nodes do -- select an unmarked node n -- visit(n) --function visit(node n) -- if n has a temporary mark then stop (not a DAG) -- if n is not marked (i.e. has not been visited yet) then -- mark n temporarily -- for each node m with an edge from n to m do -- visit(m) -- mark n permanently -- add n to head of L -- this function -- * visits and builds the tree, DAG or graph, -- * in the same pass, computes a topological ordering for the DAG -- * annotates the nodes with informations function visit(n, depth, rank) --mw.log("depth is " .. depth .. ">=" .. "maxdepth is " .. maxdepth) --mw.log(n .. ": mark is " .. tostring(marks[n])) if marks[n] == opened then p.setdata(n, "status", "loop") p.setdata(n, "rank", rank) return rank elseif marks[n] ~= closed then marks[n] = opened childrens[n] = p.children( n, property, direction, maxdepth, lang1, lang2) for _, node in ipairs(childrens[n]) do p.setdata(node, "nparents", p.getdata(node, "nparents", 0) + 1 ) if depth <= maxdepth then rank = visit(node, depth + 1, rank + 1) end end if depth <= maxdepth then if p.getdata(n, "status", "complete") ~= "loop" then p.setdata(n, "status", "complete") end marks[n] = closed else p.setdata(n, "status", "incomplete") marks[n] = incomplete end p.setdata(n, "rank", rank) end return rank + 1 end p.setdata(firstItemId, "nparents", 0) visit(firstItemId, 1, 0) return datas, childrens end local langobj = mw.language.new(lang1) -- link inside tree local function formatSymbol(prefix) return '(' .. prefix .. ")" end local function genAnchor(id) return ' .. firstItemId .. id .. '">' end local function anchorLink(id, content) return "[[#" .. firstItemId .. id .. "|" .. content .. "]]" end local function fmtTreeLinks(content) return mw.text.tag("sup", {}, content) end local function renderTree( itemId, datas, children, alreadyOuted, gs ) local content = p.itemOutput( itemId, lang1, lang2, datas, setdata, getdata, highlightItemID) local state if datas[itemId]["status"] ~= nil then state = datas[itemId]["status"] end --mw.log(itemId .. ": status is " .. state ) if datas[itemId] ["nparents"] > 1 and datas[itemId]["symbol"] == nil then p.setdata(itemId, "symbol", gs() ) end -- prevent infinite loops in non DAGs if state == "loop" then if datas[itemId]["looped"] == nil then datas[itemId]["looped"] = "treated" content = fmtTreeLinks(" ∞") .. " " .. content .. genAnchor(itemId) else return content .. fmtTreeLinks("∞" .. " ↑ " .. anchorLink(itemId, formatSymbol( datas[itemId]["symbol"] ))) end elseif state == "incomplete" or state == "unvisited" then content = content .. " " .. fmtTreeLinks("…") return content end -- has no chilren ? display as leaf if children[itemId] ~= nil and table.getn(children[itemId]) == 0 then --return " " .. content .. " ? " -- would be great to use "?b, but font problem return " " .. content end datas[itemId] ["nparents"] = datas[itemId]["nparents"] - 1 local parts = {} -- sort children topologycally if alreadyOuted[itemId] == nil then local langobj = mw.language.new(lang1) local prefix = " " if datas[itemId] ["nparents"] > 0 then local arrow = langobj:getArrow() prefix = fmtTreeLinks(genAnchor(itemId) .. " " .. arrow .. " " .. formatSymbol(datas[itemId]["symbol"])) end order = children[itemId] table.sort(order, function (a, b) return datas[a]["rank"] < datas[b]["rank"] end ) for i, childId in ipairs(order) do table.insert( parts, renderTree( childId, datas, children, alreadyOuted, gs ) ) end if direction == "child" or direction == "brother" then local l = table.maxn( parts ) for i = 1,(l - 1) do parts[i] = mw.text.tag( 'li', {}, parts[i] ) end parts[l] = mw.text.tag( 'li', { class = 'lastline' }, parts[l] ) alreadyOuted[itemId] = prefix .. " " .. content .. mw.text.tag( 'ul', {}, table.concat( parts ) ) elseif direction == "parent" then local texttmp local matchCount = 0 --mw.log("parts is: ") --mw.logObject(parts) texttmp = mw.text.tag( 'ul', {}, mw.text.tag( 'li', { class = 'lastline' }, content ) ) alreadyOuted[itemId], matchCount = string.gsub(table.concat( parts ), "()", texttmp .. "%1", 1) --mw.log('matchCount is:') --mw.log(matchCount) if matchCount == 0 then alreadyOuted[itemId] = prefix .. " " .. string.gsub(table.concat( parts ), "$", texttmp, 1) end alreadyOuted[itemId] = prefix .. " " .. alreadyOuted[itemId] --mw.log("alreadyOuted[itemId] is: ") --mw.logObject(alreadyOuted[itemId]) end end if datas[itemId] ["nparents"] <= 0 or state == "loop" then return alreadyOuted[itemId] else return content .. " " .. fmtTreeLinks(anchorLink(itemId, formatSymbol(datas[itemId]["symbol"])) .. " " .. langobj:getArrow(forward)) end end ------------------------------------------------------------------------------------------- -- End preparation of functions ------------------------------------------------------------------------------------------- ------------------------- -- Start creating tree -- ------------------------- -- gen = p.gensymbols("??") -- gen = p.gensymbols("12") -- gen = p.gensymbols("★☆?") -- These symbols are used as link button for "jumping" from certain branch to other branch. -- "jumping" functionality is used when same item appears multipul times in one tree. local gen = p.gensymbols("@*#") local children datas, children = firstPass( firstItemId, gen) -- alreadyOuted is the table which contains html code for each QID. -- For example, like this... alreadyOuted[Q1234] = "
  • [[Human body]]
  • "
    -- Actually items which located more nearer to the root (to say, FirstItemId) contain html codes of their branchs within it. -- For example, like this... alreadyOuted[Q1234] = "
  • [[Human body]]
    • [[Nervous system]]
  • "
    -- This is done by recursive calling of renderTree() function inside the renderTree() function. local alreadyOuted = {} rendering = {} -- What does this do? return renderTree( firstItemId, datas, children, alreadyOuted, gen) ----------------------- -- End creating tree -- ----------------------- end function p.main( frame ) ------------------------------------ -- Start adjustments of arguments ------------------------------------ local maxdepth --local lang1 = mw.language.getContentLanguage().code local lang1 = mw.getCurrentFrame():preprocess("{{int:lang}}") local lang2 = 'en' local firstItemId = frame.args.firstItemId local direction = frame.args.direction -- tree searching direction. "child", "parent" or "brother local highlightItemID = frame.args.highlight local maxdepth = frame.args.maxdepth if tonumber(firstItemId) then --legacy format firstItemId = 'Q'.. tostring(firstItemId) end if direction == nil or direction =='' then --Default direction is child direction = 'child' end if tonumber(highlightItemID) then --legacy format highlightItemID = 'Q'.. tostring(highlightItemID) end if maxdepth and maxdepth ~= '' then maxdepth = tonumber( maxdepth ) else maxdepth = 25 end ---------------------------------- -- End adjustments of arguments ---------------------------------- ------------------------- -- Start creating tree -- ------------------------- local content = '' local property -- property used to search items. For example "P156" (followed by) or "P155" (follows) -------------------------------------------------- --Creating tree for child side (downstream side) -------------------------------------------------- if direction == 'child' then property = "P156" elseif direction == 'parent' then property = "P155" end content = mw.text.tag( 'li', { class = 'lastline' }, p.outputTree( firstItemId, property, direction, maxdepth, lang1, lang2, highlightItemID ) ) content = '
    [Show detail]


    '
    .. content
    --mw.log("content is: ") --mw.logObject(content) -------------------------------------------------- -- Final formatting -------------------------------------------------- res = mw.text.tag( 'div', { class = 'treeview' }, mw.text.tag( 'ul', {}, content ) ) ----------------------- -- End creating tree -- ----------------------- return res end return p