Module:List: Difference between revisions

From the Croc Wiki, the Croc encyclopedia
Jump to navigationJump to search
Content added Content deleted
(tweak comment at the start)
(fix horizontal numbered list style)
Line 56: Line 56:
local function getStyle(listType, indent, style)
local function getStyle(listType, indent, style)
local styles = {}
local styles = {}
if listType == 'horizontal' then
if listType == 'horizontal' or listType == 'horizontal_numbered' then
indent = indent and tonumber(indent)
indent = indent and tonumber(indent)
indent = tostring((indent and indent * 1.6) or 0)
indent = tostring((indent and indent * 1.6) or 0)

Revision as of 03:30, November 14, 2013

Documentation for this module may be created at Module:List/doc

-- This module outputs different kinds of lists. At the moment, bulleted, unbulleted,
-- horizontal, numbered, and horizontal numbered lists are supported.

local p = {}

local function getListItem(data, style, itemStyle)
	if not data then
		return nil
	end
	if style or itemStyle then
		style = style or ''
		itemStyle = itemStyle or ''
		return mw.ustring.format(
			'<li style="%s%s">%s</li>',
			style, itemStyle, data
		)
	else
		return mw.ustring.format(
			'<li>%s</li>',
			data
		)
	end
end

local function getArgNums(args)
	-- Returns an array containing the keys of all positional arguments
	-- that contain data (i.e. non-whitespace values).
	local nums = {}
	for k, v in pairs(args) do
		if type(k) == 'number' and 
			k >= 1 and 
			math.floor(k) == k and 
			mw.ustring.match(v, '%S') then
				table.insert(nums, k)
		end
	end
	table.sort(nums)
	return nums
end

local function getClass(listType, class)
	local classes = {}
	if listType == 'horizontal' or listType == 'horizontal_numbered' then
		table.insert(classes, 'hlist')
	elseif listType == 'unbulleted' then
		table.insert(classes, 'plainlist')
	end
	table.insert(classes, class)
	local ret
	if #classes == 0 then
		return nil
	end
	return mw.ustring.format(' class="%s"', table.concat(classes, ' '))
end

local function getStyle(listType, indent, style)
	local styles = {}
	if listType == 'horizontal' or listType == 'horizontal_numbered' then
		indent = indent and tonumber(indent)
		indent = tostring((indent and indent * 1.6) or 0)
		table.insert(styles, 'margin-left: ' .. indent .. 'em;')
	end
	table.insert(styles, style)
	if #styles == 0 then
		return nil
	end
	return mw.ustring.format(' style="%s"', table.concat(styles, ' '))
end

function p.makeList(listType, args)
	-- This is the main function to be called from other Lua modules.
	-- First, get the list items.
	local listItems = {}
	local argNums = getArgNums(args)
	for i, num in ipairs(argNums) do
		local item = getListItem(
			args[num],
			args.item_style or args.li_style, -- li_style is included for backwards compatibility. item_style was included to be easier to understand for non-coders.
			args['item_style' .. tostring(num)] or args['li_style' .. tostring(num)]
		)
		table.insert(listItems, item)
	end
	if #listItems == 0 then
		return ''
	end
	-- Check if we need a ul tag or an ol tag, and get the start and type attributes for ordered lists.
	local listTag = 'ul'
	local startAttr, typeAttr
	if listType == 'numbered' or listType == 'horizontal_numbered' then
		listTag = 'ol'
		startAttr = args.start
		if startAttr then
			startAttr = ' start="' .. startAttr .. '"'
		end
		typeAttr = args.type
		if typeAttr then
			typeAttr = ' type="' .. typeAttr .. '"'
		end
	end
	startAttr = startAttr or ''
	typeAttr = typeAttr or ''
	-- Get the classes and styles and output the list.
	local class = getClass(listType, args.class) or ''
	local style = getStyle(listType, args.indent, args.style) or ''
	local list_style = args.list_style or args.ul_style -- ul_style is included for backwards compatibility, and will work even with ordered lists.
	list_style = list_style and (' style="' .. list_style .. '"') or ''
	return mw.ustring.format(
		'<div%s%s><%s%s%s%s>%s</%s></div>',
		class, style, listTag, startAttr, typeAttr, list_style, table.concat(listItems), listTag
	)
end

local function makeWrapper(listType)
	return function(frame)
		local origArgs
		if frame == mw.getCurrentFrame() then
			origArgs = frame:getParent().args
			for k, v in pairs(frame.args) do
				origArgs = frame.args
				break
			end
		else
			origArgs = frame
		end
		
		local args = {}
		for k, v in pairs(origArgs) do
			if type(k) == 'number' or v ~= '' then
				args[k] = v
			end
		end
		return p.makeList(listType, args)
	end
end

local funcNames = {'bulleted', 'unbulleted', 'horizontal', 'numbered', 'horizontal_numbered'}

for _, funcName in ipairs(funcNames) do
	p[funcName] = makeWrapper(funcName)
end

return p