Module:TOC

From Miranda NG
Jump to navigation Jump to search
Module documentation[view] [edit] [history] [purge]

This module implements various table of contents (TOC) templates. At the moment, it implements {{TOCyears}} and {{List TOC}}.

Usage

Avaiable functions

#invoke function Lua function Template
years _years {{TOCyears}}
list _list {{List TOC}}

From wikitext

From wikitext this module should usually be used through one of the templates in the table above. However, it is also possible to use it with the following syntax:

{{#invoke:TOC|function|args}}

The function names are listed in the table in the "#invoke function" column, and args are the arguments that would normally be added by the template. Please see the template documentation for each template for available parameters.

From Lua

Load the module like this:

local mTOC = require('Module:TOC')

You can then use the functions with the following syntax:

mTOC.func(args)

"func" should be changed to one of the Lua function names in the table above. These all start with an underscore ("_"). The args variable is a table of arguments to be passed to the function. Please see the template documentation for available arguments.

-- This module implements various templates that create custom tables of
-- contents.

-- Load necessary modules
local yesno = require('Module:Yesno')
local checkType = require('libraryUtil').checkType

local p = {}

local function makeTocLink(page, display)
	display = display or page
	return string.format('[[#%s|%s]]', page, display)
end

local function makeToc(s, args)
	-- Make a TOC box from a string and from the given table of arguments.
	checkType('makeToc', 1, s, 'string')
	checkType('makeToc', 2, args, 'table', true)
	args = args or {}

	-- Root
	local root = mw.html.create()
	local isPrimary = yesno(args.primary) ~= false
	if isPrimary then
		root:wikitext('__NOTOC__')
	end

	-- Top div tag
	local top = root:tag('div')
	top:addClass('toc plainlinks hlist')
	if isPrimary then
		top:attr('id', 'toc')
	end
	local align = args.align and args.align:lower()
	if align == 'left' then
		top
			:css('float', 'left')
			:css('clear', args.clear or 'left')
	elseif align == 'right' then
		top
			:css('float', 'right')
			:css('clear', args.clear or 'right')
	elseif align == 'center' then
		top
			:css('margin', 'auto')
			:css('clear', args.clear or 'none')
	else
		top
			:css('clear', args.clear or 'left')
	end
	top:newline()

	-- Title div tag
	local title = args.title or mw.message.new('Toc'):plain()
	local titleDiv = top:tag('div')
	titleDiv:attr('id', 'toctitle')
	if isPrimary then
		titleDiv:wikitext('<h2>' .. title .. '</h2>')
	else
		titleDiv:tag('strong'):wikitext(title)
	end
	
	-- Content
	top
		:newline()
		:wikitext(s)
		:newline()
	
	return tostring(root)
end

function p._years(args)
	local i = tonumber(args.startyear) or 1900
	local endYear = tonumber(args.endyear) or 1950
	local range = tonumber(args.range)
	local step = tonumber(args.step) or 1
	local links = {}
	while i <= endYear do
		local year = tostring(i)
		if range then
			year = year .. '-' .. tostring(i + range)
		end
		links[#links + 1] = makeTocLink(year)
		i = i + step
	end
	if #links > 0 then
		links = '* ' .. table.concat(links, ' ')
		return makeToc(links, args)
	else
		return ''
	end
end

function p._list(args)
	-- Set up the variables.
	local noRows = 4 -- The number of rows, starting at key "a". Must be 26 or less.
	local alphabetPosition = 3 -- The position of the extra alphabet row.
	local lists, chars = {}, {}
	for i = 1, noRows do
		lists[i] = {}
	end

	-- Find the relevant keys from the arguments.
	local a = 97
	local endChar = string.char(a + noRows - 1)
	local pattern = string.format('^([a-%s])([1-9][0-9]*)$', endChar)
	for k, v in pairs(args) do
		local letter, num
		if type(k) == 'string' then
			letter, num = k:match(pattern)
		end
		if letter then
			local iRow = string.byte(letter) - a + 1
			table.insert(lists[iRow], {num = tonumber(num), section = v})
		end
	end

	-- Sort the tables and replace the value tables with the section name.
	for i, valueTables in pairs(lists) do
		table.sort(valueTables, function(t1, t2)
			return t1.num < t2.num
		end)
		for j, valueTable in ipairs(valueTables) do
			lists[i][j] = valueTable.section
		end
	end

	-- Add the extra alphabet row.
--	local A = 65
--	local alphabetRow = {}
--	for i = 1, 26 do
--		local char = string.char(A + i - 1)
--		alphabetRow[i] = char
--	end
--	table.insert(lists, alphabetPosition, alphabetRow)

	-- Render the rows.
	local ret = {}
	for i, sections in ipairs(lists) do
		if #sections > 0 then
			ret[#ret + 1] = '<div>'
			for j, section in ipairs(sections) do
				ret[#ret + 1] = '* ' .. makeTocLink(section)
			end
			ret[#ret + 1] = '</div>'
		end
	end

	return makeToc(table.concat(ret, '\n'), args)
end

setmetatable(p, {__index = function(t, k)
	return function (frame)
		local args = require('Module:Arguments').getArgs(frame, {
			wrappers = {
				'Template:TOCyears',
				'Template:List TOC'
			}
		})
		return p['_' .. k](args)
	end
end})

return p