Jump to content

Module:BadgeLua

From Creopedia

This documentation is transcluded from Module:BadgeLua/doc.

Lua interface for building a badge.

Implements Template:Badge.


require( 'strict' )

--- Lua interface for building a badge.

--- @class BadgeProps
--- @field text string
--- @field color string
--- @field backgroundColor string
--- @field icon string
--- @field link string
--- @field class string
--- @field sortValue string|number

local p = {}


--- @param file string
--- @param size string
--- @return string
local function getFileWikitext( file, size )
	-- `metadata` class is needed to be excluded from MultimediaViewer.
	-- `link=` is needed make sure the image is not clickable.
	return string.format( '[[File:%s|%s|class=metadata|link=]]', file, size )
end

--- @param root mw.html
--- @param icon string
local function renderIcon( root, icon )
	local html = mw.html.create( 'span' )

	html
		:addClass( 't-badge__icon' )
		:wikitext( getFileWikitext( icon, '16px' ) )

	root:node( html )
end

--- @param props BadgeProps
--- @return string
function p.render( props )
	local root = mw.html.create( 'span' ):addClass( 't-badge' )

	if type( props.class ) == 'string' then
		root:addClass( props.class )
	end

	-- A sortable table reads a cell it has no stated value for as the text it
	-- displays, which for a badge is a name. Where the badge stands for a scale
	-- rather than a label, that name sorts alphabetically and says nothing.
	-- MediaWiki's sorter looks for data-sort-value on the cell first and then
	-- on what the cell contains, so a badge carrying its own value orders every
	-- table it appears in, hand written ones included, with no per-table edit.
	if props.sortValue ~= nil then
		root:attr( 'data-sort-value', props.sortValue )
	end

	if type( props.color ) == 'string' then
		root:css( 'color', props.color )
	end

	if type( props.backgroundColor ) == 'string' then
		root:css( 'background-color', props.backgroundColor )
	end

	if type( props.icon ) == 'string' then
		renderIcon( root, props.icon )
	end

	local text = props.text

	-- The link is placed on the text and stretched over the badge by the
	-- styles, so the icon and the padding are clickable as well.
	if type( props.link ) == 'string' and type( text ) == 'string' then
		root:addClass( 't-badge--is-link' )
		text = string.format( '[[%s|%s]]', props.link, text )
	end

	root:tag( 'span' ):addClass( 't-badge__text' ):wikitext( text )

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

--- Wikitext entry point for the module
---
--- @param frame mw.frame
--- @return string
function p.main( frame )
	local getArgs = require( 'Module:Arguments' ).getArgs
	return p.render( getArgs( frame ) )
end


return p