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:Badge display

From Wikipedia, the free encyclopedia

--- Badge display module.
-- Initial code by John Dovey (19 April 2023) [[User:BoonDock]].
-- Rationalised 10 September 2026: template wrappers / nil-safe fields / CSS + error markup fixes /
-- sorted BadgeTable / dropped unused globals.
-- @module badge display

require('strict')
local p = {}
local data = mw.loadData('Module:Badge display/data')
local getArgs = require('Module:Arguments').getArgs

local DEFAULT_IMAGE = 'Ribbon - Question mark.png'
local ERROR_CATEGORY = '[[Category:Pages with Module:Badge display errors]]'

local function trim(s)
	return mw.text.trim(tostring(s or ''))
end

local function field(rec, name)
	local v = rec and rec[name]
	if v == nil then
		return ''
	end
	return tostring(v)
end

local function errorBox(message)
	return '<strong class="error">(Badge display module error: ' .. message .. ')</strong>' .. ERROR_CATEGORY
end

local function resolveCode(args)
	local code = trim(args[1])
	if code == '' then
		code = trim(args.code)
	end
	return code
end

local function resolveSize(args)
	-- Prefer named size=, then positional 2, then a modest default matching the template docs.
	local size = trim(args.size)
	if size == '' then
		size = trim(args[2])
	end
	if size == '' then
		size = '40px'
	end
	return size
end

local function floatClass(float)
	float = string.lower(trim(float))
	if float == 'left' then
		return 'floatleft'
	elseif float == 'right' then
		return 'floatright'
	end
	return ''
end

local function imageName(rec)
	local image = field(rec, 'Image')
	if image == '' then
		return DEFAULT_IMAGE
	end
	return image
end

local function safeDomId(code)
	-- IDs must not contain spaces/odd filename characters; use the lookup code.
	return 'badge-display-' .. (code:gsub('[^%w%-_]', '-'))
end

function p.DisplayImage(frame)
	local args = getArgs(frame, {
		wrappers = {
			'Template:Badge display',
		},
	})

	local code = resolveCode(args)
	if code == '' then
		return errorBox('missing badge code')
	end
	local rec = data[code]
	if not rec then
		return errorBox('<code>' .. code .. '</code> code not found')
	end

	local size = resolveSize(args)
	local description = field(rec, 'Description')
	local pageLink = field(rec, 'PageLink')
	local className = field(rec, 'Class')
	local variation = field(rec, 'Variation')
	local note = field(rec, 'Note')
	local typeName = field(rec, 'Type')
	local image = imageName(rec)

	-- NoTable=yes: image only
	if trim(args.NoTable) ~= '' then
		-- |center so images sit centred in table cells
		return '[[File:' .. image .. '|' .. size .. '|center|' .. description .. ']]'
	end

	-- DescOnly=yes or DescOnly=custom text: image + linked description
	local descOnly = args.DescOnly
	if descOnly ~= nil and trim(descOnly) ~= '' then
		if string.lower(trim(descOnly)) ~= 'yes' then
			description = tostring(descOnly)
		end
		local linkTarget = pageLink ~= '' and pageLink or description
		return '[[File:' .. image .. '|' .. size .. ']] [[' .. linkTarget .. '|' .. description .. ']]'
	end

	local float = floatClass(args.float)
	local domId = safeDomId(code)
	local caption = description
	if pageLink ~= '' then
		caption = '[[' .. pageLink .. '|' .. description .. ']]'
	end
	if #typeName > 1 then
		caption = caption .. ' (' .. typeName .. ')'
	end

	local details = {}
	if #className > 1 then
		table.insert(details, className .. '.')
	end
	if #variation > 1 then
		table.insert(details, variation .. '.')
	end
	if #note > 1 then
		table.insert(details, '<i>' .. note .. '</i>')
	end

	local wikitext = {}
	table.insert(wikitext, '{| class="wikitable ' .. float .. '" style="max-width: 18em; width: auto; margin: 4px; border: none;"')
	table.insert(wikitext, '|+ ' .. caption)
	table.insert(wikitext, '|-')
	table.insert(wikitext, '|aria-describedby="' .. domId .. '" style="text-align: center; border: none; padding-bottom: 10px;" | [[File:' .. image .. '|' .. size .. '|alt=]]')
	table.insert(wikitext, '|-')
	table.insert(wikitext, '|id="' .. domId .. '" style="text-align: center; border: 0; border-top: 1px solid var(--border-color-subtle); padding-top: 4px; margin-top: 4px; text-wrap-style: pretty;"|' .. table.concat(details, ' '))
	table.insert(wikitext, '|-')
	table.insert(wikitext, '|}')
	return table.concat(wikitext, '\n')
end

function p.BadgeTable(frame)
	local codes = {}
	for code, _ in pairs(data) do
		table.insert(codes, code)
	end
	table.sort(codes, function(a, b)
		local da = field(data[a], 'Description')
		local db = field(data[b], 'Description')
		if da == db then
			return a < b
		end
		return da < db
	end)

	local rows = {
		'{| class="wikitable sortable"',
		'|+ List of badges available',
		'|-',
		'! Code !! Type !! Description !! Class !! Variation !! Image !! Note !! Country',
	}
	for _, code in ipairs(codes) do
		local rec = data[code]
		local description = field(rec, 'Description')
		local pageLink = field(rec, 'PageLink')
		local image = imageName(rec)
		local descCell
		if pageLink == '' then
			descCell = description
		else
			descCell = '[[' .. pageLink .. '|' .. description .. ']]'
		end
		table.insert(rows, '|-')
		table.insert(rows, '|' .. code)
		table.insert(rows, '| ' .. field(rec, 'Type'))
		table.insert(rows, '| ' .. descCell)
		table.insert(rows, '| ' .. field(rec, 'Class'))
		table.insert(rows, '| ' .. field(rec, 'Variation'))
		table.insert(rows, '| [[File:' .. image .. '|80px]]')
		table.insert(rows, '| style="text-align: left;" | ' .. field(rec, 'Note'))
		table.insert(rows, '| ' .. field(rec, 'Country'))
	end
	table.insert(rows, '|}')
	return table.concat(rows, '\n')
end

return p