Module:Bar box
local getArgs = require('Module:Arguments').getArgs
 local yesno = require('Module:Yesno')
 
 local function is(v)
 	return (v or '') ~= ''
 end
 
 local function widths(w,d)
 	local width = is(w) and w or d
 	if tonumber(width) then width = width .. 'px' end
 	return width
 end
 
 local p = {}
 
 function p._box(args)
 	local width = widths(args.width,'auto')
 	
 	local class = 'barbox'
 	if args.float == 'left' or args.float == 'right' or args.float == 'none' then
 		class = 'barbox t' .. args.float
 	elseif args.float == 'center' then
 		class = 'barbox tnone'
 	end
 	
 	local output = {}
 	
 	output[1] = mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = {src='Module:Bar box/styles.css'} }
 	
 	output[2] = is(args.css) and (mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = {src=args.css} }) or ''
 	
 	if (args.float == 'left') or (args.float == 'right') then
 		output[3], output[15] = '', ''
 	else
 		output[3] =
 			'&lt;table style=&quot;margin:' .. ( (args.float == 'center') and '0 auto' or '0' ) .. '; border:none;&quot;&gt;' .. 
 				'&lt;tr&gt;' .. 
 					'&lt;td style=&quot;border:none; padding:0;&quot;&gt;'
 		output[15] = '&lt;/td&gt;' ..
 				'&lt;/tr&gt;' .. 
 			'&lt;/table&gt;' .. 
 			'[[Category:Pages using bar box without float left or float right|' .. ( (width == 'auto') and 'Ω' or '' ) .. mw.title.getCurrentTitle().text .. ']]'
 	end
 	
 	output[4] = 
 		'&lt;div class=&quot;' .. class .. '&quot; style=&quot;overflow-x: auto;' .. (args.style or '') .. '&quot;&gt;\n' ..
 		'&lt;div style=&quot;border:' .. (args.border_width or '1') .. 'px solid silver; font-size:88%; padding:0.4em; width:' .. width .. '; background: ' .. (args['background-color'] or 'white') .. ';&quot;&gt;\n' ..
 		'&lt;table style=&quot;text-align:left; border-collapse:collapse; width:100%;&quot;&gt;\n'
 		output[5] = ( is(args.title) and (
 			'&lt;tr style=&quot;background:' .. (args.titlebar or 'none') .. '&quot;&gt;' ..
 				'&lt;th style=&quot;text-align:center;&quot; colspan=&quot;5&quot;&gt;' .. args.title .. '&lt;/th&gt;' ..
 			'&lt;/tr&gt;\n') or '')
 		output[6] =
 			'&lt;tr style=&quot;font-size:88%; height:4px;&quot;&gt;\n'
 			output[7] =
 				'&lt;td ' .. (args.left2 and '' or 'colspan=&quot;2&quot;') .. ' style=&quot;padding:0 4px; text-align:left;&quot;&gt;' .. 
 					(args.left1 or '') .. 
 				'&lt;/td&gt;\n'
 			output[8] = ( is(args.left2) and (
 				'&lt;td style=&quot;padding:0 4px; text-align:right;&quot;&gt;' .. args.left2 .. '&lt;/td&gt;\n') or '')
 			output[9] =
 				'&lt;td style=&quot;width:' ..  widths(args.barwidth,'100px') .. '; text-align:left;&quot;&gt;&lt;/td&gt;\n' ..
 				'&lt;td ' .. (args.right2 and '' or 'colspan=&quot;2&quot;') .. ' style=&quot;padding:0 4px; width:1em; text-align:right;&quot;&gt;' .. 
 					(args.right1 or '') .. 
 				'&lt;/td&gt;\n'
 			output[10] = ( is(args.right2) and (
 				'&lt;td style=&quot;padding:0 4px; text-align:right;&quot;&gt;' .. args.right2 .. '&lt;/td&gt;\n') or '')
 		output[11] =
 			'&lt;/tr&gt;\n'
 		output[12] =
 			args.bars or ''
 		output[13] = ( is(args.caption) and (
 			'&lt;tr&gt;&lt;td colspan=&quot;5&quot; style=&quot;padding:5px; text-align:left;&quot;&gt;' .. 
 				args.caption .. 
 			'&lt;/td&gt;&lt;/tr&gt;\n') or '')
 	output[14] =
 		'&lt;/table&gt;\n&lt;/div&gt;\n&lt;/div&gt;\n'
 	-- output[15] defined above
 	
 	return table.concat(output)
 end
 
 function p._percent(args)
 	local output = {}
 	local background = is(args.bg) and ('background:' .. args.bg .. ';') or '' 
 	local percentage = ( is(args[3]) and args[3] or '0' ) .. '%'
 	local rowStyle = is(args.rowstyle) and (' style=&quot;' .. args.rowstyle .. '&quot;') or ''
 	
 	output[1] = '&lt;tr' .. rowStyle .. '&gt;\n'
 		output[2] = '&lt;td colspan=&quot;2&quot; class=&quot;bb-4em&quot; style=&quot;min-width:8em;' .. background .. '&quot;&gt;' .. (args[1] or '') .. '&lt;/td&gt;\n'
 		output[3] = '&lt;td class=&quot;bb-lr&quot; style=&quot;width:' .. widths(args.barwidth,'100px') .. ';' .. background .. '&quot;&gt;'
 			output[4] = '&lt;div style=&quot;background:' .. ( is(args[2]) and args[2] or 'gray' ) .. ';width:' .. percentage .. ';overflow:hidden;&quot;&gt;&amp;thinsp;&lt;/div&gt;'
 		output[5] = '&lt;/td&gt;\n'
 		output[6] = '&lt;td colspan=&quot;' .. ( is(args.note) and '1' or '2' ) .. '&quot; class=&quot;bb-4emr&quot; style=&quot;' .. background .. '&quot;&gt;' .. ( is(args[4]) and args[4] or percentage ) .. '&lt;/td&gt;\n'
 		output[7] = ( is(args.note) and ('&lt;td class=bb-4emr&quot; style=&quot;' .. background .. '&quot;&gt;' .. args.note .. '&lt;/td&gt;\n') or '' )
 	output[8] = '&lt;/tr&gt;'
 	
 	return table.concat(output)
 end
 
 function p._pixel(args)
 	local output = {}
 	local background = ( is(args[2]) and args[2] or 'gray' )
 	local width = ( is(args[3]) and args[3] or '0' )
 	local note = ( is(args.note) and '1' or '2' )
 	local rowStyle = is(args.rowstyle) and (' style=&quot;' .. args.rowstyle .. '&quot;') or ''
 	
 	output[1] =
 		'&lt;tr' .. rowStyle .. '&gt;\n'
 		output[2] =
 			'&lt;td colspan=&quot;2&quot; class=&quot;bb-4em&quot;&gt;' .. (args[1] or '') .. '&lt;/td&gt;\n'
 		output[3] =
 			'&lt;td class-&quot;bb-lr&quot;&gt;' ..
 				'&lt;div style=&quot;background:' .. background .. '; width:' .. width .. 'px; overflow:hidden&quot;&gt;' .. 
 					'&amp;emsp;' ..
 				'&lt;/div&gt;' ..
 			'&lt;/td&gt;\n'
 		output[4] =
 			'&lt;td colspan=&quot;' .. note .. '&quot; class=&quot;bb-min3&quot;&gt;' ..
 				( is(args[5]) and args[5] or (width .. (args[4] or '')) ) ..
 			'&lt;/td&gt;\n'
 		output[5] = ( is(args.note)  and (
 			'&lt;td class=&quot;bb-4emr&quot;&gt;' ..
 				args.note ..
 			'&lt;/td&gt;\n') or '' )
 	output[6] =
 		'&lt;/tr&gt;'
 	
 	return table.concat(output)
 end
 
 function p._stacked(args)
 	local function _align(n, default)
 		if (args.align or '') ~= '' then
 			local a = mw.ustring.sub(args.align,n,n)
 			if a == 'l' then
 				return 'left'
 			elseif a == 'c' then
 				return 'center'
 			elseif a == 'r' then
 				return 'right'
 			elseif a == 'd' then
 				return default
 			end
 		end
 		
 		return default
 	end
 
 	local output = {}
 	
 	local rowStyle = is(args.rowstyle) and (' style=&quot;' .. args.rowstyle .. '&quot;') or ''
 	output[1] = ( is(args.id) and (
 		'&lt;tr class=&quot;mw-collapsible' .. ( yesno(args.collapsed) and ' mw-collapsed' or '') ..
 		'&quot; id=&quot;mw-customcollapsible-' .. args.id .. '&quot;' .. rowStyle .. '&gt;\n') or ('&lt;tr' .. rowStyle .. '&gt;\n') )
 		output[2] =
 			'&lt;td ' .. (args.note1 and '' or 'colspan=&quot;2&quot; ') .. 
 			'style=&quot;text-align:' .. _align(1,'left') .. '&quot; class=&quot;bb-04em&quot;&gt;' .. 
 				mw.text.trim(args[1] or '') .. 
 			'&lt;/td&gt;\n'
 		output[3] = ( is(args.note1) and (
 			'&lt;td style=&quot;text-align:' .. _align(2,'right') .. '&quot; class=&quot;bb-04em&quot;&gt;' .. 
 				args.note1 .. 
 			'&lt;/td&gt;\n') or '')
 		output[4] =
 			'&lt;td class=&quot;bb-lr&quot;&gt;\n'
 			
 			local maxn = 4
 			for k in pairs(args) do
 				local kn = tonumber(k) or 0
 				if kn &gt; maxn then maxn = kn end
 			end
 			
 			for i=1,(( maxn - 2 )/2),1 do
 				local width = ( mw.text.trim(args[(2*i) + 2] or 0) )
 				width = (is(width) and width or 0)
 				width = tonumber( mw.ustring.format(&quot;%.2f&quot;, width) )
 				if width == 0 then
 					output[i+4] = ''
 				else
 					local title = ( (args['title' .. i] or '') ~= '' ) and ( ' title=' .. args['title' .. i] ) or ''
 					local background = ( (args[(2*i) + 1] or '') ~= '' ) and args[(2*i) + 1] or 'gray'
 					
 					output[i+4] =
 						'&lt;div' .. title .. ' style=&quot;background:' .. background .. ';width:' .. width .. 'px&quot; class=&quot;bb-fl&quot;&gt;' ..
 							'&amp;#8203;' ..
 						'&lt;/div&gt;\n'
 				end
 			end
 	
 		output[#output+1] =
 			'&lt;/td&gt;\n'
 		output[#output+1] = 
 			'&lt;td ' .. (args.note2 and '' or 'colspan=&quot;2&quot; ') .. 
 			'style=&quot;text-align:' .. _align(3,'left') .. '&quot; class=&quot;bb-04em&quot;&gt;' .. 
 				mw.text.trim(args[2] or '') .. 
 			'&lt;/td&gt;\n'
 		output[#output+1] = ( is(args.note2) and (
 			'&lt;td style=&quot;text-align:' .. _align(4,'right') .. '&quot; class=&quot;bb-04em&quot;&gt;' .. 
 				args.note2 ..
 			'&lt;/td&gt;\n') or '')
 	output[#output+1] =
 		'&lt;/tr&gt;\n'
 	
 	return table.concat(output)
 end
 
 function p._gap(args)
 	local output = {}
 	local rowStyle = is(args.rowstyle) and (' style=&quot;' .. args.rowstyle .. '&quot;') or ''
 	local height = '10px'
 	if (args.height or '') ~= '' then
 		height = (tonumber(args.height) and (args.height .. 'px') or args.height)
 	end
 			
 	output[1] =
 		'&lt;tr' .. rowStyle .. '&gt;\n'
 		output[2] = 
 			'&lt;td colspan=&quot;5&quot; style=&quot;height:'.. height .. '&quot;&gt;' .. (args[1] or '') .. '&lt;/td&gt;\n'
 	output[3] =
 		'&lt;/tr&gt;\n'
 
 	return table.concat(output)
 end
 
 function p.box(frame)
 	local args = getArgs(frame, {
 		valueFunc = function (key, value)
 			if value then
 				value = mw.text.trim(value)
 				if (key == 'width') or (key == 'float') then
 					value = mw.ustring.lower(value)
 				end
 				if value ~= '' then
 					return value
 				end
 			end
 			return nil
 		end
 	})
 	return p._box(args)
 end
 
 function p.percent(frame)
 	local args = getArgs(frame, {
 		valueFunc = function (key, value)
 			if value then
 				value = mw.text.trim(value)
 				if value ~= '' then
 					return value
 				end
 			end
 			return nil
 		end
 	})
 	return p._percent(args)
 end
 
 function p.pixel(frame)
 	local args = getArgs(frame, {
 		valueFunc = function (key, value)
 			if value then
 				value = mw.text.trim(value)
 				if value ~= '' then
 					return value
 				end
 			end
 			return nil
 		end
 	})
 	return p._pixel(args)
 end
 
 function p.gap(frame)
 	local args = getArgs(frame, {
 		valueFunc = function (key, value)
 			if value then
 				value = mw.text.trim(value)
 				if value ~= '' then
 					return value
 				end
 			end
 			return nil
 		end
 	})
 	return p._gap(args)
 end
 
 function p.stacked(frame)
 	local args = getArgs(frame, {
 		valueFunc = function (key, value)
 			if value then
 				value = mw.text.trim(value)
 				if (key == 'collapsed') or (key == 'align') then
 					value = mw.ustring.lower(value)
 				end
 				if value ~= '' then
 					return value
 				end
 			end
 			return nil
 		end
 	})
 	return p._stacked(args)
 end