Edge Rewrite
// HTMLRewriter · presentation

This page was redesigned at the edge.

Cloudflare fetched the original article and streamed it through HTMLRewriter to apply an entirely new visual system without rebuilding the source page.

Jump to content

Module:Contents topic list

From Wikipedia, the free encyclopedia

require('strict')

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

-- Close <li> and <ul> elements enclosing deeper depths
local function closePending(toClose, depth)
	local out = ''
	
	while #toClose > 0 and (toClose[#toClose].depth >= depth or depth == 0) do
		out = out .. toClose[#toClose].close
		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]*)\n') do
	    table.insert(items, {#indent, item})
	end
	
	-- Match the last line
	local lastIndent, lastItem = wikitext:match('(**) *([^\n]*)$')
	table.insert(items, {#lastIndent, lastItem})
	
	-- Elements that are currently open
	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
		local level, text = unpack(item)
		out = out .. closePending(toClose, level)
		
		if level == 0 then
			-- Just output 
			out = out .. text .. '\n'
		else
			-- Create a new list if needed
			if #toClose == 0 or toClose[#toClose].type ~= 'ul' then
				out = out .. (forcedInline <= level and '<ul class="content-inline-ul">' or '<ul>')
				
				toClose[#toClose + 1] = {
					depth = level - 1,
					type = 'ul',
					close = '</ul>' .. (level == 1 and '\n' or '')
				}
			end
			
			-- Went up a level, discard forced inline and rest block
			if level <= forcedInline then
				forcedInline = math.huge
			end
			
			if text:match('KEEP%-INLINE$') ~= nil then
				-- Line is marked by {{Inline sublist}}
				out = out .. '<li>' .. text:gsub(' *KEEP%-INLINE$', '')
				forcedInline = math.min(level, forcedInline)
			elseif forcedInline < level then
				-- Inline forced
				out = out .. '<li>' .. text
			elseif i < #items and items[i + 1][1] > level then
				-- Next item is deeper
				-- Remove ":" if first item is block-level
				out = out:gsub("&#58; '''''<ul>$", "'''''<ul>")
				out = out .. '<li class="content-sublist">' .. "'''''" .. text .. "&#58; '''''"
				-- Treat remaining items in this list as block-level
				toClose[#toClose].restBlock = true
			elseif toClose[#toClose].restBlock then
				-- Rest of list should be block level
				out = out .. '<li class="content-sublist">' .. "'''''" .. text .. "'''''"
			else
				-- Normal list item
				out = out .. '<li>' .. text
			end
			
			toClose[#toClose + 1] = {
				depth = level,
				type = 'li',
				close = '</li>'
			}
		end
	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