Jump to content

Module:Table of contents

From Wikibooks, open books for an open world
local table_of_contents = {}

local html = mw.html

local function exists(arg)
	return arg ~= nil and not arg:match('^%s*$')
end

local function trim_arguments(args)
	local result = {}
	for key, value in pairs(args) do
		result[key] = mw.text.trim(value)
	end
	return result
end

local function are_section_descriptions_present(args)
	for key, value in pairs(args) do
		if type(key) == 'number' and (key + 1) % 4 == 0 and exists(value) then
			return true
		end
	end
	return false
end

local function generate_section_label(name, page, description, completion_status)
	return (description and html.create('dt') or html.create('li')):wikitext((exists(page) and "[[" .. page .. "|" .. name .. "]]" or name) .. (completion_status and ' ' .. completion_status or '')), (description and description[1]) and html.create('dd'):wikitext(description[1]) or label
end

local function get_section_page_name(page_name, page_name_prefix)
	return exists(page_name) and (page_name_prefix or '') .. page_name or nil
end

function table_of_contents.generate(frame)
	local args = trim_arguments(frame.args)
	local is_a_description_list = are_section_descriptions_present(args)
	local toc = (is_a_description_list and html.create('dl') or (args.unordered and html.create('ul') or html.create('ol'))):attr('id', 'generated-table-of-contents')
	toc = exists(args.indent) and toc:css('margin-left', args.indent) or toc
	toc = exists(args['list style']) and toc:css('list-style', args['list style']) or toc

	local section_name = args[1]
	local section_page = get_section_page_name(args[2], args['page name prefix'])
	local section_description = args[3]
	local section_completion_status = args[4]
	local section_marker = 5
	while section_name do
		for _, node in next, {generate_section_label(section_name, section_page, is_a_description_list and {section_description} or nil, (exists(section_completion_status) and frame:expandTemplate{title = 'stage short', args = {section_completion_status}} or nil))} do
			toc:node(node)
		end
		section_name = args[section_marker]
		section_page = get_section_page_name(args[section_marker+1], args['page name prefix'])
		section_description = args[section_marker+2]
		section_completion_status = args[section_marker+3]
		section_marker = section_marker + 4
	end
	return tostring(toc)
end

return table_of_contents