Module:descendants tree

From Wiktionary, the free dictionary
Jump to navigation Jump to search

This module is used byModule:descendants tree/templatesto generate the content of{{desctree}}.It gets the content of an entry and searches for a list of descendants. If there is such a list, it displays the contents of the list, or else it displays an error.


localexport={}

localalternative_forms_module="Module:alternative forms"
localstring_utilities_module="Module:string utilities"

localremove_comments=require(string_utilities_module).remove_comments

localfunctiontrack(page)
--[[Special:WhatLinksHere/Wiktionary:Tracking/descendants tree/PAGE]]
returnrequire("Module:debug/track")("descendants tree/"..page)
end


localfunctionpreview_error(what,entry_name,language_name,reason)
mw.log("Could not retrieve"..what.."for"..language_name.."in the entry [["
..entry_name.."]]:"..reason..".")
track(what.."error")
end

localfunctionget_content_after_senseid(content,entry_name,lang,id)
localcode=lang:getFullCode()
localt_start,t_end
fortemplateinrequire("Module:template parser").find_templates(content)do
localname=template:get_name()
ifname=="senseid"then
localargs=template:get_arguments()
ifargs[1]==codeandargs[2]==idthen
t_start=template.index
end
elseifname=="etymid"then
localargs=template:get_arguments()
ifargs[1]==codeandargs[2]==idthen
t_start=template.index
elseift_start~=nilandt_end==nilthen
t_end=template.index
end
elseifname=="head"then
localargs=template:get_arguments()
localid_arg=args.id
ifid_arg==idthen
t_start=template.index
elseifid_arg~=nilandt_start~=nilandt_end==nilthen
t_end=template.index
end
end
end

ift_start==nilthen
error("Could not find the correct senseid template in the entry [["
..entry_name.."]] (with language"..code.."and id '"..id.."')")
end

ift_end==nilthen
-- terminate on L2 or another "Etymology..." header
-- match L2 and remove it and everything after it
content=string.gsub(content:sub(t_start),"\n==[^=].+$ ","")
-- match Etymology header and remove it and everything after it
content=string.gsub(content,"\n===+%s*Etymology.+$ ","")
returncontent
end

returncontent:sub(t_start,t_end)
end

functionexport.get_alternative_forms(lang,entry_name,id,default_separator)
localpage=mw.title.new(entry_name)
localcontent=page:getContent()

localfunctionalt_form_error(reason)
preview_error("alternative forms",entry_name,lang:getFullName(),reason)
end

ifnotcontentthen
-- FIXME, should be an error
alt_form_error("nonexistent page")
track("alts-nonexistent-page")
return""
end

local_,index=string.find(content,
"==[\t]* "..require(string_utilities_module).pattern_escape(lang:getFullName()).."[\t]*== ")

ifnotindexthen
-- FIXME, should be an error
alt_form_error("L2 header for language not found")
track("alts-lang-not-found")
return""
end

ifidthen
content=get_content_after_senseid(content,entry_name,lang,id)
index=0
end

local_,next_lang=string.find(content,"\n==[^=\n]+== ",index,false)
local_,index=string.find(content,"\n(====?=?)[\t]*Alternative forms[\t]*%1 ",index,false)
ifnotindexthen
_,index=string.find(content,"\n(====?=?)[\t]*Alternative reconstructions[\t]*%1 ",index,false)
end

ifnotindexthen
-- FIXME, should be an error
alt_form_error("'Alternative forms' section for language not found")
track("alts-section-not-found")
return""
end

locallangCodeRegex=require(string_utilities_module).pattern_escape(lang:getFullCode())
index=string.find(content,"{{alte?r?|"..langCodeRegex.."|[^|}]+",index)
if(notindex)or(next_langandnext_lang<index)then
-- FIXME, should be an error
alt_form_error("no 'alt' or 'alter' template in 'Alternative forms' section for language")
track("alts-alter-not-found")
return""
end

localnext_section=string.find(content,"\n(=+)[^=]+%1 ",index)

localalternative_forms_section=string.sub(content,index,next_section)

localterms_list={}

localaltforms=require("Module:alternative forms")

fortemplateinrequire("Module:template parser").find_templates(alternative_forms_section)do
iftemplate:get_name()=="alter"then
localargs=template:get_arguments()
ifargs[1]==lang:getFullCode()then
saw_alter=true
localformatted_altforms=altforms.display_alternative_forms(args,entry_name,"allow self link",default_separator)
table.insert(terms_list,formatted_altforms)
end
end
end

if#terms_list==0then
-- FIXME, should be an error
alt_form_error("no terms in 'alt' or 'alter' template in 'Alternative forms' section for language")
track("alts-no-terms-in-alter")
return""
end

returntable.concat(terms_list,default_separatoror",")
end

functionexport.get_descendants(lang,entry_name,id,noerror)
localpage=mw.title.new(entry_name)
localcontent=page:getContent()
localnamespace=mw.title.getCurrentTitle().nsText

localfunctiondesc_error(reason)
preview_error("descendants",entry_name,lang:getFullName(),reason)
end

ifnotcontentthen
-- FIXME, should be an error
desc_error("nonexistent page")
track("desctree-nonexistent-page")
return""
end

-- Ignore HTML comments, columns and blank lines.
content=remove_comments(content)
:gsub("{{top%d}}%s","")
:gsub("{{mid%d}}%s","")
:gsub("{{bottom}}%s","")
:gsub("\n?{{(desc?%-%l+)|?[^}]*}} ",
function(template_name)
iftemplate_name=="desc-top"ortemplate_name=="desc-bottom"ortemplate_name=="des-top"ortemplate_name=="des-mid"ortemplate_name=="des-bottom"then
return""
end
end)
:gsub("\n%s*\n","\n")

local_,index=string.find(content,
"%f[^\n%z]==[\t]* "..lang:getFullName().."[\t]*== ",nil,true)
ifnotindexthen
_,index=string.find(content,"%f[^\n%z]==[\t]* "
..require(string_utilities_module).pattern_escape(lang:getFullName())
.."[\t]*== ",nil,false)
end
ifnotindexthen
desc_error("L2 header for language not found")
-- FIXME, should be an error
track("desctree-lang-not-found")
return""
end

ifidthen
content=get_content_after_senseid(content,entry_name,lang,id)
index=0
end

local_,next_lang=string.find(content,"\n==[^=\n]+== ",index,false)
local_,index=string.find(content,"\n(====*)[\t]*Descendants[\t]*%1 ",index,false)
localfunctiondesctree_no_descendants(with_lang_in_error)
ifnoerrorand(namespace==""ornamespace=="Reconstruction")then
track("desctree-no-descendants")
return"<small class=\ "error previewonly\ ">( "..
"Please either change this template to {{desc}}"..
"or insert a ====Descendants==== section in [["..
entry_name.."#"..lang:getFullName().."]])</small>"..
"[[Category:"..lang:getFullName().."descendants to be fixed in desctree]]"
else
error(("No Descendants section was found in the entry [[%s]]%s"):format(entry_name,
with_lang_in_errorand("under the header for %s"):format(lang:getFullName())or""))
end
end
ifnotindexthen
returndesctree_no_descendants()
elseifnext_langandnext_lang<indexthen
returndesctree_no_descendants("with lang in error")
end

-- Skip past final equals sign.
index=index+1

-- Skip past spaces or tabs.
whiletruedo
localnew_index=string.match(content,"^[\t]+() ",index)
ifnotnew_indexthen
break
end
index=new_index
end

localitems=require("Module:array")()
localframe=mw.getCurrentFrame()
localprevious_list_markers=""

-- Skip paragraphs at beginning of Descendants section.
whiletruedo
localnew_index=content:match("^\n[^%*:=][^\n]*() ",index)
ifnotnew_indexthen
break
else
index=new_index
end
end

previous_index=1

-- Find a consecutive series of list items that begins directly after the
-- Descendants header.
-- start_index and previous_index are used to check that list items are
-- consecutive.
forstart_index,list_markers,item,indexinstring.gmatch(content:sub(index),"()\n([%*:]+) *([^\n]+)() ")do
ifstart_index~=previous_indexthen
break
end

-- Preprocess, but replace recursive calls to avoid template loop errors
item=string.gsub(item,"{{desctree|","{{#invoke:etymology/templates/descendant|descendants_tree|")
item=frame:preprocess(item)

localdifference=#list_markers-#previous_list_markers

ifdifference>0then
fori=#previous_list_markers+1,#list_markersdo
items:insert(list_markers:sub(i,i)=="*"and"<ul>"or"<dl>")
end
else
ifdifference<0then
fori=#previous_list_markers,#list_markers+1,-1do
items:insert(previous_list_markers:sub(i,i)=="*"and"</li></ul>"or"</dd></dl>")
end
else
items:insert(previous_list_markers:sub(-1,-1)=="*"and"</li>"or"</dd>")
end

ifprevious_list_markers:sub(#list_markers,#list_markers)~=list_markers:sub(-1,-1)then
items:insert(list_markers:sub(-1,-1)=="*"and"</dl><ul>"or"</ul><dl>")
end
end

items:insert(list_markers:sub(-1,-1)=="*"and"<li>"or"<dd>")

items:insert(item)

previous_list_markers=list_markers
previous_index=index
end

fori=#previous_list_markers,1,-1do
items:insert(previous_list_markers:sub(i,i)=="*"and"</li></ul>"or"</dd></dl>")
end

returnitems:concat()
end

returnexport