Revision 21306632 of "Module:category tree" on frwiktionary

local export = {}

local m_submodule = nil

-- The main entry point.
-- This is the only function that can be invoked from a template.
function export.show(frame)
	if mw.title.getCurrentTitle().nsText == "Template" then
		return "(This template should be used on pages in the Category: namespace.)"
	elseif mw.title.getCurrentTitle().nsText ~= "Category" then
		error("This template/module can only be used on pages in the Category: namespace.")
	end
	
	local args = frame.args
	local template = args["template"]
	
	if not template then
		error("The \"template\" parameter was not specified.")
	end
	
	m_submodule = require("Module:category tree/" .. template)
	
	-- Get all the parameters and the label data
	local info = {}
	info.code = args["code"]; if info.code == "" then info.code = nil end
	info.label = args["label"]; if info.label == "" then info.label = nil end
	info.sc = args["sc"]; if info.sc == "" then info.sc = nil end
	
	-- Check if the category is empty
	local categories = {}
	
	if mw.site.stats.pagesInCategory(mw.title.getCurrentTitle().text, "all") == 0 then
		table.insert(categories, "[[Category:Empty categories]]")
	end
	
	-- Does the category have the correct name?
	local errormessage = check_name(template, info)
	
	if errormessage then
		return table.concat(categories, "") .. errormessage
	end
	
	-- Generate the displayed information
	local display = {}
	table.insert(display, show_breadcrumbs(info))
	table.insert(display, show_description(info))
	table.insert(display, show_children(info))
	table.insert(display, show_TOC(info))
	
	show_categories(info, categories)
	
	return table.concat(categories, "") .. table.concat(display, "\n\n") .. "<br clear=\"all\"/>"
end

-- Check the name of the current page, and return an error if it's not right.
function check_name(template, info)
	local errortext = nil
	local category = nil
	local current = m_submodule.new(info)
	
	if not current then
		errortext =
			"The label \"" .. (info.label or "") .. "\" given to the " .. mw.getCurrentFrame():expandTemplate{title = "temp", args = {template}} .. " template is not valid. " ..
			"You may have mistyped it, or it simply has not been created yet. To add a new label, please consult the documentation of the template."
		category = "[[Category:Categories with invalid label]]"
	else
		local expected_name = (info.code and current:getBasicName() or current:getUmbrellaName())
		
		if expected_name ~= mw.title.getCurrentTitle().text then
			errortext = "Based on the parameters given to the " .. mw.getCurrentFrame():expandTemplate{title = "temp", args = {template}} .. " template, this category should be called '''[[:Category:" .. expected_name .. "]]'''."
			category = "[[Category:Categories with incorrect name]]"
		end
	end
	
	if errortext then
		return (category or "") .. mw.getCurrentFrame():expandTemplate{title = "maintenance box", args = {
			"red",
			image = "[[File:Ambox warning pn.svg|50px]]",
			title = "The automatically-generated contents of this category has errors.",
			text = errortext,
			}}
	else
		return nil
	end
end

-- Show the parent categories that the current category should be placed in.
function show_categories(info, categories)
	if info.sc then
		local pinfo = mw.clone(info)
		pinfo.sc = nil
		local parent = m_submodule.new(pinfo)
		
		local parent_name = (info.code and parent:getBasicName() or parent:getUmbrellaName())
		local sortkey = require("Module:scripts").getByCode(info.sc):getCanonicalName()
		table.insert(categories, "[[Category:" .. parent_name .. "|" .. sortkey .. "]]")
	else
		local parents = (info.code and m_submodule.new(info):getBasicParentLabels() or m_submodule.new(info):getUmbrellaParentLabels())
		
		if not parents then
			return
		end
		
		for _, parent in ipairs(parents) do
			if type(parent.name) == "string" then
				table.insert(categories, "[[" .. parent.name .. "|" .. parent.sort .. "]]")
			else
				local parent_name = (info.code and parent.name:getBasicName() or parent.name:getUmbrellaName())
				table.insert(categories, "[[Category:" .. parent_name .. "|" .. parent.sort .. "]]")
			end
		end
		
		if info.code then
			-- Also put the category in its corresponding "umbrella" or "by language" category.
			local umbrella = m_submodule.new(info):getUmbrellaName()
			
			if umbrella then
				local current_name = m_submodule.new(info):getBasicName()
				table.insert(categories, "[[Category:" .. umbrella .. "|" .. current_name .. "]]")
			end
		end
	end
end

-- Show navigational "breadcrumbs" at the top of the page.
function show_breadcrumbs(info)
	local steps = {}
	
	-- Start at the current label and move our way up the "chain" from child to parent, until we can't go further.
	local current = m_submodule.new(info)
	
	while current do
		local category = nil
		local display_name = nil
		
		if type(current) == "string" then
			category = current
			display_name = current:gsub("^Category:", "")
		else
			category = "Category:" .. (info.code and current:getBasicName() or current:getUmbrellaName())
			display_name = current:getBreadcrumbName()
		end
		
		display_name = mw.getContentLanguage():ucfirst(display_name)
		table.insert(steps, 1, "ยป [[:" .. category .. "|" .. display_name .. "]]")
		
		-- Move up the "chain" by one level.
		if type(current) == "string" then
			current = nil
		elseif current._info.sc then
			local pinfo = mw.clone(current._info)
			pinfo.sc = nil
			current = m_submodule.new(pinfo)
		else
			current = (info.code and current:getBasicParentLabels() or current:getUmbrellaParentLabels())
			
			if current then
				current = current[1].name
			end
		end
	end
	
	return "<small>" .. table.concat(steps, " ") .. "</small>"
end

-- Show a short description text for the category.
function show_description(info)
	if info.code then
		if info.sc then
			return "This category contains '''" .. m_submodule.new(info):getBasicName() .. "'''."
		else
			local description = m_submodule.new(info):getBasicDescription()
			local edit = m_submodule.new(info):getDataModule()
			return (description or "") .. mw.getCurrentFrame():expandTemplate{title = "edit", args = {edit, type = "sup"}}
		end
	else
		local description = m_submodule.new(info):getUmbrellaDescription()
		local edit = m_submodule.new(info):getDataModule()
		return (description or "") .. mw.getCurrentFrame():expandTemplate{title = "edit", args = {edit, type = "sup"}}
	end
end

-- Show a list of child categories.
function show_children(info)
	if not info.code then
		return nil
	end
	
	local children_list = {}
	local children = m_submodule.new(info):getBasicChildLabels()
	
	if not children then
		return nil
	end
	
	for _, child in ipairs(children) do
		local child_basic = child:getBasicName()
		local child_page = mw.title.new("Category:" .. child_basic)
		
		if child_page.exists then
			local child_description = child:getBasicDescription()
			table.insert(children_list, "* [[:Category:" .. child_basic .. "]]: " .. child_description)
		end
	end
	
	return table.concat(children_list, "\n")
end

-- Show a table of contents with links to each letter in the language's script.
function show_TOC(info)
	if not info.code then
		return nil
	end
	
	local num_pages = mw.site.stats.pagesInCategory(mw.title.getCurrentTitle().text, "pages")
	
	-- No need for a TOC if all entry names can fit on one page.
	if num_pages > 200 then
		-- This category is very large, see if there is an "extended" version of the TOC.
		if num_pages > 2500 then
			local TOC_template_extended = mw.title.new("Template:" .. info.code .. "-categoryTOC/full")
			
			if TOC_template_extended.exists then
				return mw.getCurrentFrame():expandTemplate{title = TOC_template_extended.text, args = {}}
			end
		end
		
		local TOC_template = mw.title.new("Template:" .. info.code .. "-categoryTOC")
		
		if TOC_template.exists then
			return mw.getCurrentFrame():expandTemplate{title = TOC_template.text, args = {}}
		end
	end
	
	return nil
end

return export