Module:InfoboxNeue

From CLOCKUP WIKI

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

local p = {}

--- Helper function to restore underscore from space
--- so that it does not screw up the external link wikitext syntax
--- For some reason SMW property converts underscore into space 
--- mw.uri.encode can't be used on full URL
local function restoreUnderscore( s )
	return s:gsub( ' ', '%%5F' )
end

--- Put table values into a comma-separated list
--- @param table t
--- @return string
function p.tableToCommaList( t )
	if type( t ) == 'table' then
		return table.concat( t, ', ' )
	else
		return t
	end
end

--- Format text to show comparison as desc text if two strings are different
--- @param string s1 base
--- @param string s2 comparsion
--- @return string html
function p.showDescIfDiff( s1, s2 )
	if s1 == nil or s2 == nil or s1 == s2 then return s1 end
	return string.format( '%s <span class="infobox__desc">(%s)</span>', s1, s2 )
end

--- Shortcut to return the HTML of the infobox message component as string
--- @param table data {title, desc)
--- @return string html
function p.renderMessage( data )
	return p.renderSection( { content = p.renderItem( { data = data.title, desc = data.desc } ) } )
end

--- Return the HTML of the infobox image component as string
--- @param string filename
--- @return string html
function p.renderImage( filename )
	if filename == nil or filename == '' then return '' end

	local html = mw.html.create( 'div' )
		:addClass( 'infobox__image' )
		:wikitext( '[[File:' .. filename .. '|400px]]' )

	return tostring( html );
end

--- Return the HTML of the infobox indicator component as string
--- @param table data {data, desc, class)
--- @return string html
function p.renderIndicator( data )
	if data == nil or data[ 'data' ] == nil or data[ 'data' ] == '' then return '' end

	local html = mw.html.create( 'div' ):addClass( 'infobox__indicator' )
	html:wikitext(
		p.renderItem(
			{
				[ 'data' ] = data[ 'data' ],
				[ 'desc' ] = data[ 'desc' ] or nil,
				row = true,
				spacebetween = true
			}
		)
	)
	
	if data[ 'class' ] then html:addClass( data[ 'class' ] ) end

	return tostring( html )
end

--- Return the HTML of the infobox header component as string
--- @param table data {title, subtitle)
--- @return string html
function p.renderHeader( data )
	if data == nil or data[ 'title' ] == nil then return '' end

	local html = mw.html.create( 'div' ):addClass( 'infobox__header' )

	html:tag( 'div' )
		:addClass( 'infobox__title' )
		:wikitext( data[ 'title' ] )

	if data[ 'subtitle' ] then
		html:tag( 'div' )
			-- Subtitle is always data
			:addClass( 'infobox__subtitle infobox__data' )
			:wikitext( data[ 'subtitle' ] )
	end

	return tostring( html )
end

--- Wrap the HTML into an infobox section
--- @param table data {title, subtitle, content, col, class}
--- @return string html
function p.renderSection( data )
	if data == nil or data[ 'content' ] == nil or data[ 'content' ] == '' then return '' end

	local html = mw.html.create( 'div' ):addClass( 'infobox__section' )

	if data[ 'title' ] then
		local header = html:tag( 'div' ):addClass( 'infobox__sectionHeader' )
		header:tag( 'div' )
				:addClass( 'infobox__sectionTitle' )
				:wikitext( data[ 'title' ] )
		if data[ 'subtitle' ] then
			header:tag( 'div' )
				:addClass( 'infobox__sectionSubtitle' )
				:wikitext( data[ 'subtitle' ] )
		end
	end
	
	local content = html:tag( 'div' )
	content:addClass( 'infobox__sectionContent')
			:wikitext( data[ 'content' ] )

	if data[ 'col' ] then content:addClass( 'infobox__grid--cols-' .. data[ 'col' ] ) end
	if data[ 'class' ] then html:addClass( data[ 'class' ] ) end

	return tostring( html )
end

--- Return the HTML of the infobox link button component as string
--- @param table data {label, link, page}
--- @return string html
function p.renderLinkButton( data )
	if data == nil or data[ 'label' ] == nil or ( data[ 'link' ] == nil and data[ 'page' ] == nil ) then return '' end

	--- Render multiple linkButton when link is a table
	if type( data[ 'link' ] ) == 'table' then
		local htmls = {}
		for i, url in ipairs( data[ 'link' ] ) do
			table.insert( htmls,
				p.renderLinkButton( {
					label = string.format( '%s %d', data[ 'label' ], i ),
					link = url
				} )
			)
		end
		return table.concat( htmls )
	end
	
	local html = mw.html.create( 'div' ):addClass( 'infobox__linkButton' )

	if data[ 'link' ] then
		html:wikitext( string.format( '[%s %s]', restoreUnderscore( data[ 'link' ] ), data[ 'label' ] ) )
	elseif data[ 'page' ] then
		html:wikitext( string.format( '[[%s|%s]]', data[ 'page' ], data[ 'label' ] ) )
	end

	return tostring( html )
end

--- Return the HTML of the infobox footer button component as string
--- @param table data {icon, label, type, content}
--- @return string html
function p.renderFooterButton( data )
	if data == nil or data[ 'label' ] == nil or data[ 'type' ] == nil or data[ 'content' ] == nil or data[ 'content' ] == '' then return '' end

	local html = mw.html.create( 'div' ):addClass( 'infobox__footer' )

	local button = html:tag( 'div' ):addClass( 'infobox__button' )
	local label = button:tag( 'div' ):addClass( 'infobox__buttonLabel' )
	
	if data[ 'icon' ] ~= nil then
		label:wikitext( string.format( '[[File:%s|16px|link=]]%s', data[ 'icon' ], data[ 'label' ] ) )
	else
		label:wikitext( data[ 'label' ] )
	end

	if data[ 'type' ] == 'link' then
		button:tag( 'div' )
			:addClass( 'infobox__buttonLink' )
			:wikitext( data[ 'content' ] )
	elseif data[ 'type' ] == 'popup' then
		button:tag( 'div' )
			:addClass( 'infobox__buttonCard' )
			:wikitext( data[ 'content' ] )
	end

	return tostring( html )
end

--- Return the HTML of the infobox item component as string
--- @param table data {label, data, desc, row, spacebetween, colspan)
--- @return string html
function p.renderItem( data )
	if data == nil or data[ 'data' ] == nil or data[ 'data' ] == '' then return '' end

	local html = mw.html.create( 'div' ):addClass( 'infobox__item' )
	
	if data[ 'row' ] == true then html:addClass( 'infobox__grid--row' ) end
	if data[ 'spacebetween' ] == true then html:addClass( 'infobox__grid--space-between' ) end
	if data[ 'colspan' ] then html:addClass( 'infobox__grid--col-span-' .. data[ 'colspan' ] ) end
	
	local dataOrder = { 'label', 'data', 'desc' }
	
	for _, key in pairs( dataOrder ) do
		if data[ key ] then
			html:tag( 'div' )
				:addClass( 'infobox__' .. key )
				:wikitext( data[ key ] )
		end
	end

	return tostring( html );
end

--- Wrap the infobox HTML
--- @param string innerHtml inner html of the infobox
--- @param string snippetText text used in snippet in mobile view
--- @return string html infobox html with templatestyles
function p.renderInfobox( innerHtml, snippetText )
	local function renderSnippet()
		if snippetText == nil then snippetText = mw.title.getCurrentTitle().rootText end
		local html = mw.html.create( 'div' )
		html
			:addClass( 'infobox__snippet mw-collapsible-toggle' )
			:tag( 'div' )
				:addClass( 'citizen-ui-icon mw-ui-icon-wikimedia-collapse' )
				:done()
			:tag( 'div' )
				:addClass( 'infobox__data' )
				:wikitext( 'Quick facts:' )
				:done()
			:tag( 'div' )
				:addClass( 'infobox__desc' )
				:wikitext( snippetText )
		return tostring( html )
	end

	local html = mw.html.create( 'div' )
	html
		:addClass( 'infobox floatright mw-collapsible' )
		:wikitext( renderSnippet() )
		:tag( 'div' )
			:addClass( 'infobox__content mw-collapsible-content' )
			:wikitext( innerHtml )

	return tostring( html ) .. mw.getCurrentFrame():extensionTag{
		name = 'templatestyles', args = { src = 'Module:InfoboxNeue/styles.css' }
	}
end

return p
Cookies help us deliver our services. By using our services, you agree to our use of cookies.