UsageEdit

This Lua module is a metamodule: it is not designed to be invoked directly from wikitext: it is to be imported by other Lua modules.

First, import the module as follows:

local treeView = require('Module:Sandbox/Luis150902/Test')

Second, invoke the treeView function of the module with the object to render and (optionally) an option table as the second argument. Wikitext of the table will be returned.



-- This is a metamodule for producing wikitext trees.

local p = {};
local middleclass = require('Module:Middleclass').class;

local TreeNode = middleclass('TreeNode');

function TreeNode:initialize(object, options)
	self.children = {};
	self.object = object;
	self.options = options or {};
end

function TreeNode:addChild(child, level)
	if type(child) ~= "table" then
		error({
			message = "Value passed to child is not a table (cannot currently check for TreeNodes)",
			source = "TreeView",
			method = "TreeNode:addChild",
			status = -1073741585
		}, 1);
	end
	self.children[child] = child:render(level)
end

local function process(object, pairFunction)
	-- This function returns the node text to show for object, invoking
	-- pairFunction for the keys and values of the object.
	local metatable = getmetatable(object);
	if type(object) ~= "table" then
		return tostring(object);
	end
	if metatable and type(metatable.dissector) == "table" then
		return metatable.dissector:processObject(object, pairFunction);
	end
	if metatable.name then
		return 'An instance of' .. metatable.name;
	end
	local function counter()
		local count = 0;
		for k, v in pairs(object) do
			pairFunction(k, v);
			count = count + 1;
		end
		return count;
	end
	local success, result = pcall(counter);
	if success then
		return 'A table with ' .. tostring(result) .. ' pairs';
	end
	return 'A table with an unknown number of pairs';
end

function TreeNode:render(level)
	if self.options.noRender then
		-- Options requested not to render, simply to return self.
		return self;
	end
	local pairFunction = function(k, v)
		self:addChild(TreeNode:new(v, options), (level or 0) + 1);
	end;
	local title = process(self.object, pairFunction);
	if options.nodeMaker then
		title = options.nodeMaker(title, level);
	else
		if options.indent and type(options.indent) ~= "number" then
			error({
				message = "Value passed to options.indent is a not a number and not nil.  Default is 30.",
				source = "TreeView",
				status = -1073741811
			}, 1);
		end
		local indent = options.indent or 30;
		title = tostring(mw.html.create('div')
			:css('padding-left', tostring(level * options.indent) .. 'px')
			:css('overflow', 'hidden')
			:css('white-space', 'nowrap'));
	end
	for child, renderingResult in pairs(self.children) do
		title = title .. '\n' .. renderingResult
	end
end

function p.treeView(object, options)
	local metatable = getmetatable(object);
	if metatable.tree then
		return style(metatable.tree(object), options);
	end
	return TreeNode:new(object, options):render();
end

return p