Revision 21306569 of "Module:category tree" on frwiktionary

local export = {}

-- 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
	
	-- 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
	info.template = template
	
	-- Does the category have the correct name?
	local errormessage = check_name(info)
	
	if errormessage then
		return errormessage
	end
	
	-- Generate the displayed information
	local display = {}
	table.insert(display, show_breadcrumbs(info))
	table.insert(display, show_description(info))
	table.insert(display, show_subcategory_list(info))
	table.insert(display, show_TOC(info))
	
	return show_categories(info) .. table.concat(display, "\n\n") .. "<br clear=\"all\"/>"
end

-- Retrieves an item of information
function export.get_item(info, item)
	local ret = require("Module:category tree/" .. info.template).get_item(info, item)
	
	if not ret then
		if item:find("^sortparent[1-5]$") or item == "sortparentumbrella" then
			ret = export.get_item(info, "display_name")
		elseif item == "display_name" then
			ret = info.label
		end
	end
	
	return ret
end

-- Check the name of the curren page, and return an error if it's not right.
function check_name(info)
	local expected_name = export.get_item(info, (info.code and "basic" or "umbrella"))
	
	if expected_name ~= mw.title.getCurrentTitle().text then
		return "[[Category:Categories needing attention]]" .. 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 = "Based on the parameters given to the " .. mw.getCurrentFrame():expandTemplate{title = "temp", args = {info.template}} .. " template, this category should be called '''[[:Category:" .. expected_name .. "]]'''.",
			}}
	else
		return nil
	end
end

-- Show the parent categories that the current category should be placed in.
function show_categories(info)
	local categories = {}
	local lang = require("Module:languages").getByCode(mw.getContentLanguage():getCode())  -- Used to create English sort keys
	
	if info.sc then
		local parent = export.get_item({code = info.code, label = info.label, sc = nil, template = info.template}, (info.code and "basic" or "umbrella"))
		local sortparent = require("Module:scripts").getByCode(info.sc):getCanonicalName()
		table.insert(categories, "[[Category:" .. parent .. "|" .. lang:makeSortKey(sortparent) .. "]]")
	elseif info.code then
		-- There is a code, so this is a basic category. Put the category in its parent.
		for i = 1, 5 do
			local parent = export.get_item(info, "parent" .. i)
			local sortparent = export.get_item(info, "sortparent" .. i)
			
			if parent then
				local parent_name = export.get_item({code = info.code, label = parent, sc = info.sc, template = info.template}, "basic")
				table.insert(categories, "[[Category:" .. parent_name .. "|" .. lang:makeSortKey(sortparent) .. "]]")
			else
				local parentbyname = export.get_item(info, "parentbyname" .. i)
				
				if parentbyname then
					table.insert(categories, "[[Category:" .. parentbyname .. "|" .. lang:makeSortKey(sortparent) .. "]]")
				end
			end
		end
		
		-- Also put the category in its corresponding "umbrella" or "by language" category.
		local umbrella = export.get_item(info, "umbrella")
		
		if umbrella then
			local current_name = export.get_item(info, "basic")
			table.insert(categories, "[[Category:" .. umbrella .. "|" .. lang:makeSortKey(current_name) .. "]]")
		end
	else
		-- There is no code, this is an umbrella category. Put the category in a "fundamental" category.
		local umbrella_categorization = export.get_item(info, "umbrella-categorization")
		
		if umbrella_categorization == "fundamental" then
			local fundamental = export.get_item(info, "fundamental")
			
			if fundamental then
				local sortparentumbrella = export.get_item(info, "sortparentumbrella")
				table.insert(categories, "[[Category:" .. fundamental .. "|" .. lang:makeSortKey(sortparentumbrella) .. "]]")
			end
		elseif umbrella_categorization == "parallel" then
			for i = 1, 5 do
				local parent = export.get_item(info, "parent" .. i)
				local sortparent = export.get_item(info, "sortparent" .. i)
				
				if parent then
					local parent_name = export.get_item({code = info.code, label = parent, sc = info.sc, template = info.template}, "umbrella")
					table.insert(categories, "[[Category:" .. parent_name .. "|" .. lang:makeSortKey(sortparent) .. "]]")
				else
					local parentbyname = export.get_item(info, "parentbyname" .. i)
					
					if parentbyname then
						table.insert(categories, "[[Category:" .. parentbyname .. "|" .. lang:makeSortKey(sortparent) .. "]]")
					end
				end
			end
		end
	end
	
	return table.concat(categories, "")
end

-- Show navigational "breadcrumbs" at the top of the page.
function show_breadcrumbs(info)
	if not info.code then
		return nil
	end
	
	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 = info.label
	
	while current do
		local parent = export.get_item({code = info.code, label = current, sc = nil, template = info.template}, "parent1")
		
		if parent then
			local parent_basic = export.get_item({code = info.code, label = parent, sc = nil, template = info.template}, "basic")
			local parent_display_name = export.get_item({code = info.code, label = parent, sc = nil, template = info.template}, "display_name")
			table.insert(steps, 1, "» [[:Category:" .. parent_basic .. "|" .. mw.getContentLanguage():ucfirst(parent_display_name) .. "]]")
		else
			local parent_parentbyname = export.get_item({code = info.code, label = current, sc = nil, template = info.template}, "parentbyname1")
			
			if parent_parentbyname then
				table.insert(steps, 1, "» [[:Category:" .. parent_parentbyname .. "|" .. mw.getContentLanguage():ucfirst(parent_parentbyname) .. "]]")
			end
		end
		
		-- Move up the "chain" by one level.
		current = parent
	end
	
	if info.sc then
		local basic = export.get_item({code = info.code, label = info.label, sc = nil, template = info.template}, "basic")
		local display_name = export.get_item({code = info.code, label = info.label, sc = nil, template = info.template}, "display_name")
		table.insert(steps, "» [[:Category:" .. basic .. "|" .. mw.getContentLanguage():ucfirst(display_name) .. "]]")
	end
	
	local basic = export.get_item(info, "basic")
	local display_name = export.get_item(info, "display_name")
	table.insert(steps, "» [[:Category:" .. basic .. "|" .. mw.getContentLanguage():ucfirst(display_name) .. "]]")

	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
			local basic = export.get_item(info, "basic")
			return "This category contains '''" .. basic .. "'''."
		else
			local description = export.get_item(info, "description")
			local edit = export.get_item(info, "edit")
			return (description or "") .. mw.getCurrentFrame():expandTemplate{title = "edit", args = {edit, type = "sup"}}
		end
	else
		local display_name = export.get_item(info, "display_name")
		local edit = export.get_item(info, "edit")
		return "Categories with " .. display_name .. " in various specific languages." .. mw.getCurrentFrame():expandTemplate{title = "edit", args = {edit, type = "sup"}}
	end
end

-- Show a list of subcategories.
function show_subcategory_list(info)
	if not info.code then
		return nil
	end
	
	local subcategories = {}
	
	for i = 1, 40 do
		local sub = export.get_item(info, "sub" .. i)
		
		if sub then
			local sub_basic = export.get_item({code = info.code, label = sub, sc = info.sc, template = info.template}, "basic")
			local sub_page = mw.title.new("Category:" .. sub_basic)
			
			if sub_page.exists then
				local sub_description = export.get_item({code = info.code, label = sub, sc = info.sc, template = info.template}, "description")
				table.insert(subcategories, "* [[:Category:" .. sub_basic .. "]]: " .. sub_description)
			end
		end
	end
	
	if #subcategories > 0 then
		return table.concat(subcategories, "\n")
	else
		return nil
	end
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