Module:Category tree/script cat

From The Languages of David J. Peterson
Jump to navigation Jump to search

Documentation for this module may be created at Module:Category tree/script cat/documentation

local export = {}

local labels = require("Module:category tree/script cat/data")

-- Category object

local Category = {}
Category.__index = Category


function Category.new(info)
	local self = setmetatable({}, Category)
	assert(type(info) == "table", "The \"info\" parameter must be a table.")
	self._info = {}
	
	for key, val in pairs(info) do
		if key == "code" then
			self._info.code = val
			self._sc = require("Module:scripts").getByCode(val) or error("The script code \"" .. val .. "\" is not valid.")
		elseif key == "label" then
			self._info.label = val
			self._data = labels[self._info.label]
		elseif key ~= "umbrella" then
			error("The parameter \"" .. key .. "\" was not recognized.")
		end
	end
	
	-- Check if the label exists
	if not self._info.label then
		error("No label was specified.")
	elseif not self._data then
		return nil
	end
	
	if self._info.label == "ROOT" and not self._sc then
		return nil
	end
	
	--[[
		Distinguish "type of writing system" categories from those that need "by language"
		tacked on at the end.
	]]
	if self._info.label == mw.getContentLanguage():ucfirst(self._info.label) then
		self._info.umbrella = true
	else
		self._info.umbrella = false
	end
	
	return self
end

export.new = Category.new


function Category:getInfo()
	return self._info
end


function Category:getBreadcrumbName()
	if self._info.label == "ROOT" then
		return self._sc:getCategoryName()
	else
		return self._info.label
	end
end


function Category:getDataModule()
	return "Module:category tree/script cat/data"
end


function Category:canBeEmpty()
	return self._info.label == "ROOT"
end


function Category:isHidden()
	return self._data["hidden"] and self._info.code
end


function Category:getCategoryName()
	if self._sc then
		local ret = nil
		
		if self._info.label ~= "ROOT" then
			ret = " " .. self._info.label
		end
		
		return mw.getContentLanguage():ucfirst(self._sc:getCategoryName() .. (ret or ""))
	else
		if self._info.umbrella then
			return self._info.label
		else
			return mw.getContentLanguage():ucfirst(self._info.label .. " by script")
		end
	end
end


function Category:getDescription()
	if self._sc then
		local ret = self._data["description"]
		
		if ret then
			ret = { ret }
			
			if self._info.label == "ROOT" then
				local systems = self._sc:getSystems()
				for _,system in ipairs(systems) do
					table.insert(ret, "\n\nThe {{{scname}}} script is ")
					if mw.ustring.sub(system:getCanonicalName(), 1, 1) == "a" then
						table.insert(ret, "an ")
					else
						table.insert(ret, "a ")
					end
					
					local singular = system:getCategoryName()
					singular = mw.getContentLanguage():lcfirst(singular)
					singular = mw.ustring.gsub(singular, "ies$", "y")
					singular = mw.ustring.gsub(singular, "s$", "")
					
					table.insert(ret, singular .. ".[[Category:" .. system:getCategoryName() .. "]]")
				end
				
				local blocks = require("Module:category tree/script cat/blocks")
					.print_blocks_by_canonical_name(self._sc:getCanonicalName())
				
				if blocks then
					table.insert(ret, "\n")
					table.insert(ret, blocks)
				end
			end
			
			-- Add catfix to character lists.
			if self._info.label == "characters" then
				local mul = require("Module:languages").getByCode("mul")
				local catfix = require("Module:utilities").catfix(mul, self._sc)
				table.insert(ret, catfix)
			end
		end

		-- Replace template notation {{{}}} with variables.
		
		ret = table.concat(ret)
		local categoryName = self._sc:getCategoryName()
		local scname = self._sc:getCanonicalName()
		local codes = {}
		
		for code, data in pairs(mw.loadData("Module:scripts/data")) do
			if data.canonicalName == scname then
				table.insert(codes, "'''" .. code .. "'''")
			end
		end
		
		if codes[2] then
			table.sort(
				codes,
				-- Four-letter codes have length 10, because they are bolded: '''Latn'''.
				function(code1, code2)
					if #code1 == 10 then
						if #code2 == 10 then
							return code1 < code2
						else
							return true
						end
					else
						if #code2 == 10 then
							return false -- four-letter codes before other codes
						else
							return code1 < code2
						end
					end
				end)
		end
		
		local content = {
			code = self._sc:getCode(),
			codesplural = codes[2] and "s" or "",
			codes = table.concat(codes, ", "),
			scname = scname,
			sccat = categoryName,
			scprosename = categoryName:find("code") and categoryName or "the " .. categoryName,
			Wikipedia = self._sc:getWikipediaArticle(),
		}
		
		local unrecognized
		ret = string.gsub(
			ret,
			"{{{([^}]+)}}}",
			function (parameter)
				return content[parameter] or error("No value for " .. parameter .. " generated by [[Module:category tree/script cat]].")
			end)
		
		return ret
	else
		if self._info.umbrella then
			return self._data.description
		else
			return "Categories with " .. self._info.label .. " of various specific scripts."
		end
	end
end


function Category:getParents()
	local ret = {}
	
	if self._sc then
		local parents = self._data["parents"]
		
		if not parents or #parents == 0 then
			return nil
		end
		
		for key, parent in ipairs(parents) do
			local parent = mw.clone(parent)
			
			if type(parent) ~= "table" then
				parent = {name = parent}
			end
			
			if not parent.sort then
				parent.sort = self._info.label
			end
			
			parent.sort = parent.sort:gsub("{{{scname}}}", self._sc:getCanonicalName())
			parent.sort = parent.sort:gsub("{{{sccat}}}", self._sc:getCategoryName())
			
			if parent.name and parent.name:find("^Category:") then
				parent.name = parent.name:gsub("{{{scname}}}", self._sc:getCanonicalName())
				parent.name = parent.name:gsub("{{{sccat}}}", self._sc:getCategoryName())
			else
				local pinfo = mw.clone(self._info)
				pinfo.label = parent.name
				
				if parent.template then
					parent.name = require("Module:category tree/" .. parent.template).new(pinfo)
				else
					parent.name = Category.new(pinfo)
				end
			end
			
			table.insert(ret, parent)
		end
	else
		if self._data.fundamental then
			return {{name = "Category:" .. self._data["fundamental"], sort = self._data["sortparentumbrella"] or self._info.label}}
		elseif self._data.parents then
			for i, parent in pairs(self._data.parents) do
				local label, sort
				if type(parent) == "table" then
					label = parent.name
					sort = parent.sort
				else
					label = parent
					sort = self._info.label
				end
				
				if labels[label] and Category.new{ label = label } then
					table.insert(ret, { name = Category.new{ label = label }, sort = sort } )
				end
			end
		end
	end
	
	if #ret > 0 then
		return ret 
	else
		return nil
	end
end


function Category:getChildren()
	local children = self._data["children"]
	
	if not self._sc or not children or #children == 0 then
		return nil
	end
	
	local ret = {}
	
	for _, child in ipairs(children) do
		child = mw.clone(child)
		
		if type(child) ~= "table" then
			child = {name = child, sort = child}
		end
		
		local cinfo = mw.clone(self._info)
		cinfo.label = child.name
		child.name = Category.new(cinfo)
		
		table.insert(ret, child)
	end
	
	return ret
end


function Category:getUmbrella()
	if not self._sc then
		return nil
	end
	
	local uinfo = mw.clone(self._info)
	uinfo.code = nil
	return Category.new(uinfo)
end


return export