Module:Contents topic list

require('strict')

local getArgs = require('Module:Arguments').getArgs
local p = {}

-- Close <li> and <ul> enclosing deeper depths
local function closePending(toClose, depth)
	local out = ''
	
	while #toClose > 0 and toClose[#toClose][1] >= depth do
		out = out .. toClose[#toClose][2]
		table.remove(toClose, #toClose)
	end
	
	return out
end

function p.main(frame)
	local args = getArgs(frame)
	local wikitext = frame:preprocess(args[1])
	local items = {}
	local out = ''
	
	for indent, item in wikitext:gmatch("(**) *([^\n]+)") do  
	    items[#items + 1] = {#indent + 1, item}
	end
	
	-- List of { depth, closing tag [, rest block-level (for <ul>s) ] }
	local toClose = {}
	
	-- Lowest depth of parent that forces all <li>s to be inline
	local forcedInline = math.huge

	for i, item in pairs(items) do  
		out = out .. closePending(toClose, item[1])
		
		-- Create a new list if needed
		if #toClose == 0 or toClose[#toClose][2] ~= '</ul>' then
			out = out .. (forcedInline <= item[1] and '<ul class="content-inline-ul">' or '<ul>')
			toClose[#toClose + 1] = { item[1] - 1, '</ul>', false }
		end
		
		if item[1] <= forcedInline then
			forcedInline = math.huge
		end
		
		-- Added by {{Keep inline}}
		local keepInline = item[2]:match('KEEP%-INLINE$') ~= nil
		
		if keepInline then
			out = out .. '<li>' .. item[2]:gsub(' *KEEP%-INLINE$', '')
			forcedInline = math.min(item[1], forcedInline)
		elseif forcedInline < item[1] then
			out = out .. '<li>' .. item[2]
		elseif i < #items and items[i + 1][1] > item[1] then
			-- Remove ":" if first item is block-level
			out = out:gsub("&#58; '''''<ul>$", "'''''<ul>")
			-- Treat remaining items in this last as block-level
			toClose[#toClose][3] = true
			out = out .. '<li class="content-sublist">' .. "'''''" .. item[2] .. "&#58; '''''"
		elseif toClose[#toClose][3] then
			out = out .. '<li class="content-sublist">' .. "'''''" .. item[2] .. "'''''"
		else
			out = out .. '<li>' .. item[2]
		end
		
		toClose[#toClose + 1] = { item[1], '</li>' }
	end
	
	out = out .. closePending(toClose, 0)
	
	return '<div class="content-list">\n' .. out  .. '</div>' .. frame:extensionTag{
		name = 'templatestyles', args = { src = 'Template:Contents topic list/styles.css' }
	}
end

return p