Tu banner alternativo

Module:Userbox/sandbox

In today's world, Module:Userbox/sandbox is an issue that has gained great relevance in society. As time progresses, we find the need to explore and understand this Module:Userbox/sandbox from different perspectives. The importance of Module:Userbox/sandbox cannot be underestimated as it affects various aspects of daily life. Therefore, it is crucial to address this issue completely and objectively to understand its impact on today's society. In this article, we will analyze in detail Module:Userbox/sandbox and its influence in diverse contexts, in order to offer a comprehensive and updated vision of this very relevant topic.

Tu banner alternativo
-- This module implements {{userbox}}.

local categoryHandler = require('Module:Category handler').main

local p = {}

--------------------------------------------------------------------------------
-- Helper functions
--------------------------------------------------------------------------------

local function checkNum(val, default)
	-- Checks whether a value is a number greater than or equal to zero. If so,
	-- returns it as a number. If not, returns a default value.
	val = tonumber(val)
	if val and val >= 0 then
		return val
	else
		return default
	end
end

local function addSuffix(num, suffix)
	-- Turns a number into a string and adds a suffix.
	if num then
		return tostring(num) .. suffix
	else
		return nil
	end
end

local function checkNumAndAddSuffix(num, default, suffix)
	-- Checks a value with checkNum and adds a suffix.
	num = checkNum(num, default)
	return addSuffix(num, suffix)
end

local function makeCat(cat, sort)
	-- Makes a category link.
	if sort then
		return mw.ustring.format(']', cat, sort)
	else
		return mw.ustring.format(']', cat)
	end
end

--------------------------------------------------------------------------------
-- Argument processing
--------------------------------------------------------------------------------

local function makeInvokeFunc(funcName)
	return function (frame)
		local origArgs = require('Module:Arguments').getArgs(frame)
		local args = {}
		for k, v in pairs(origArgs) do
			args = v
		end
		return p.main(funcName, args)
	end
end

p.userbox = makeInvokeFunc('_userbox')
p = makeInvokeFunc('_userbox-2')
p = makeInvokeFunc('_userbox-r')

--------------------------------------------------------------------------------
-- Main functions
--------------------------------------------------------------------------------

function p.main(funcName, args)
	local userboxData = p(args)
	local userbox = p.render(userboxData)
	local cats = p.categories(args)
	return userbox .. (cats or '')
end

function p._userbox(args)
	-- Does argument processing for {{userbox}}.
	local data = {}

	-- Get div tag values.
	data.float = args.float
	local borderWidthNum = checkNum(args or args, nil)
	data.borderWidth = addSuffix(borderWidthNum, 'px')
	data.borderColor = args or args or args or args
	data.width = borderWidthNum and addSuffix(240 - 2 * borderWidthNum, 'px')
	data.bodyClass = args.bodyclass
	data.bodyMargin = args.bodymargin  -- NEW ARG (having bodyStyle would be nice, too)

	-- Get table tag values.
	data.backgroundColor = args or args or args

	-- Get info values.
	data.info = args.info or args or "<code>{{{info}}}</code>"
	data.infoTextAlign = args
	data.infoFontSize = checkNumAndAddSuffix(args or args, nil, 'pt')
	data.infoHeight = checkNumAndAddSuffix(args or args, nil, 'px')
	data.infoPadding = args or args
	data.infoLineHeight = args or args
	data.infoColor = args or args
	data.infoOtherParams = args or args
	data.infoClass = args

	-- Get id values.
	local id = args.logo or args or args.id
	data.id = id
	data.showId = id and true or false
	data.idWidth = checkNumAndAddSuffix(args or args, nil, 'px')
	data.idHeight = checkNumAndAddSuffix(args or args, nil, 'px')
	data.idBackgroundColor = args or args or args
	data.idTextAlign = args
	data.idFontSize = checkNum(args or args or args, nil)
	data.idColor = args or args or data.infoColor
	data.idPadding = args or args
	data.idLineHeight = args or args
	data.idOtherParams = args or args
	data.idClass = args

	return data
end

p = function (args)
	-- Does argument processing for {{userbox-2}}.
	local data = {}

	-- Get div tag values.
	data.float = args.float
	local borderWidthNum = checkNum(args or args, nil)
	data.borderWidth = addSuffix(borderWidthNum, 'px')
	data.borderColor = args or args or args or args
	data.width = borderWidthNum and addSuffix(240 - 2 * borderWidthNum, 'px')
	data.bodyClass = args.bodyclass
	data.bodyMargin = args.bodymargin  -- NEW ARG (having bodyStyle would be nice, too)

	-- Get table tag values.
	data.backgroundColor = args or args

	-- Get info values.
	data.info = args.info or args or "<code>{{{info}}}</code>"
	data.infoTextAlign = args
	data.infoFontSize = checkNumAndAddSuffix(args, nil, 'pt')
	data.infoColor = args or args
	data.infoPadding = args
	data.infoLineHeight = args
	data.infoOtherParams = args

	-- Get id values.
	data.showId = true
	data.id = args.logo or args or args.id1 or 'id1'
	data.idWidth = checkNumAndAddSuffix(args, nil, 'px')
	data.idHeight = checkNumAndAddSuffix(args, nil, 'px')
	data.idBackgroundColor = args or args
	data.idTextAlign = args
	data.idFontSize = checkNum(args, nil)
	data.idLineHeight = args
	data.idColor = args or data.infoColor
	data.idPadding = args
	data.idOtherParams = args

	-- Get id2 values.
	data.showId2 = true
	data.id2 = args.logo or args or args.id2 or 'id2'
	data.id2Width = checkNumAndAddSuffix(args, nil, 'px')
	data.id2Height = data.idHeight
	data.id2BackgroundColor = args or args or args
	data.id2TextAlign = nil -- Always center, but don't set if no content
	data.id2FontSize = checkNum(args, nil)
	data.id2LineHeight = args
	data.id2Color = args or data.infoColor
	data.id2Padding = args
	data.id2OtherParams = args

	return data
end

p = function (args)
	-- Does argument processing for {{userbox-r}}.
	local data = {}

	-- Get div tag values.
	data.float = args.float
	local borderWidthNum = checkNum(args or args, nil)
	data.borderWidth = addSuffix(borderWidthNum, 'px')
	data.borderColor = args or args or args or args
	data.width = borderWidthNum and addSuffix(240 - 2 * borderWidthNum, 'px')
	data.bodyClass = args.bodyclass
	data.bodyMargin = args.bodymargin  -- NEW ARG (having bodyStyle would be nice, too)

	-- Get table tag values.
	data.backgroundColor = args or args or args

	-- Get id values.
	data.showId = false -- We only show id2 in userbox-r.

	-- Get info values.
	data.info = args.info or args or "<code>{{{info}}}</code>"
	data.infoTextAlign = args or args
	data.infoFontSize = checkNumAndAddSuffix(args or args, nil, 'pt')
	data.infoPadding = args or args
	data.infoLineHeight = args or args
	data.infoColor = args or args
	data.infoOtherParams = args or args

	-- Get id2 values.
	data.showId2 = true  -- userbox-r always shows the ID cell (as id2)
	data.id2 = args.logo or args or args.id or 'id'
	data.id2Width = checkNumAndAddSuffix(args or args, nil, 'px')
	data.id2Height = checkNumAndAddSuffix(args or args, nil, 'px')
	data.id2BackgroundColor = args or args or args
	data.id2TextAlign = args
	data.id2FontSize = checkNum(args or args or args, nil)
	data.id2Color = args or args or data.infoColor
	data.id2Padding = args or args
	data.id2LineHeight = args or args
	data.id2OtherParams = args or args

	return data
end

function p.render(data)
	-- Renders the userbox html using the content of the data table.
	-- Add TemplateStyles
	local templateStyles = mw.getCurrentFrame():extensionTag{
		name = 'templatestyles', args = { src = 'Template:Userbox/styles.css' }
	}

	-- Render the div tag html.
	local root = mw.html.create('div')
	root:addClass('wikipediauserbox')

	-- Only add CSS properties if they have values
	if data.float then root:css('float', data.float) end
	if data.borderWidth then 
		root:css('border-width', data.borderWidth)
	end

	if data.bodyMargin then                 -- if user provides a margin value by param, then...
		root:css('margin', data.bodyMargin) --   just use the param value
	elseif data.float == 'right' then       -- if not, then set some minimal margin so floated box doesn't jam up against text
		root:css('margin-left', '8px')      -- default probly should be a local variable near the top somewhere 
	elseif data.float == 'left' then        -- ditto for float left because we are worrying about text wrapping on the right 
		root:css('margin-right', '8px')     -- (the 8px default probly should be a local variable up top somewhere)
	end                                     -- no margin for default flow (left, non-float) e.g. for a string of boxes

	if data.borderColor then 
		root:css('border-color', data.borderColor)
		-- Set border style if we have a color but potentially no width set
		if not data.borderWidth then
			root:css('border-width', '1px')  -- default border width
		end
		root:css('border-style', 'solid')
	end
	if data.width then root:css('width', data.width) end
	if data.bodyClass then root:addClass(data.bodyClass) end

	-- Render the table tag html.
	local tableroot = root:tag('table')
	tableroot:attr('role', 'presentation')

	-- Only add CSS if values exist
	if data.width then tableroot:css('width', data.width) end
	if data.backgroundColor then tableroot:css('background', data.backgroundColor):css('color', 'inherit') end

	local tablerow = tableroot:tag('tr')

	-- Create cells based on what should actually be shown
	if data.showId == false then
		-- userbox-r: info cell first, then id2 cell (if showId2 is true)
		local infoCell = tablerow:tag('td')
		infoCell:addClass('userbox-info')
		if data.infoTextAlign then infoCell:css('text-align', data.infoTextAlign) end
		if data.infoFontSize then infoCell:css('font-size', data.infoFontSize) end
		if data.infoPadding then infoCell:css('padding', data.infoPadding) end
		if data.infoHeight then infoCell:css('height', data.infoHeight) end
		if data.infoLineHeight then infoCell:css('line-height', data.infoLineHeight) end
		if data.infoColor then infoCell:css('color', data.infoColor) end
		if data.infoOtherParams then infoCell:cssText(data.infoOtherParams) end
		if data.infoClass then infoCell:addClass(data.infoClass) end
		if data.info then infoCell:wikitext(data.info) end
		
		-- Create id2 cell only if showId2 is true
		if data.showId2 then
			local id2Cell = tablerow:tag('td')
			id2Cell:addClass('userbox-id2')
			if data.id2Width then id2Cell:css('width', data.id2Width) end
			if data.id2Height then id2Cell:css('height', data.id2Height) end
			if data.id2BackgroundColor then id2Cell:css('background', data.id2BackgroundColor) end
			if data.id2TextAlign then id2Cell:css('text-align', data.id2TextAlign) end
			if data.id2FontSize then id2Cell:css('font-size', data.id2FontSize .. 'pt') end
			if data.id2Color then id2Cell:css('color', data.id2Color) else id2Cell:css('color', 'inherit') end
			if data.id2Padding then id2Cell:css('padding', data.id2Padding) end
			if data.id2LineHeight then id2Cell:css('line-height', data.id2LineHeight) end
			if data.id2OtherParams then id2Cell:cssText(data.id2OtherParams) end
			if data.id2 then id2Cell:wikitext(data.id2) end
		end
	else
		-- userbox and userbox-2: create id cell only if showId is true
		if data.showId then
			local idCell = tablerow:tag('td')
			idCell:addClass('userbox-id')
			if data.idWidth then idCell:css('width', data.idWidth) end
			if data.idHeight then idCell:css('height', data.idHeight) end
			if data.idBackgroundColor then idCell:css('background', data.idBackgroundColor) end
			if data.idTextAlign then idCell:css('text-align', data.idTextAlign) end
			if data.idFontSize then idCell:css('font-size', data.idFontSize .. 'pt') end
			if data.idColor then idCell:css('color', data.idColor) else idCell:css('color', 'inherit') end
			if data.idPadding then idCell:css('padding', data.idPadding) end
			if data.idLineHeight then idCell:css('line-height', data.idLineHeight) end
			if data.idOtherParams then idCell:cssText(data.idOtherParams) end
			if data.idClass then idCell:addClass(data.idClass) end
			if data.id then idCell:wikitext(data.id) end
		end
		
		-- Always create info cell for userbox and userbox-2
		local infoCell = tablerow:tag('td')
		infoCell:addClass('userbox-info')
		if data.infoTextAlign then infoCell:css('text-align', data.infoTextAlign) end
		if data.infoFontSize then infoCell:css('font-size', data.infoFontSize) end
		if data.infoPadding then infoCell:css('padding', data.infoPadding) end
		if data.infoHeight then infoCell:css('height', data.infoHeight) end
		if data.infoLineHeight then infoCell:css('line-height', data.infoLineHeight) end
		if data.infoColor then infoCell:css('color', data.infoColor) end
		if data.infoOtherParams then infoCell:cssText(data.infoOtherParams) end
		if data.infoClass then infoCell:addClass(data.infoClass) end
		if data.info then infoCell:wikitext(data.info) end
		
		-- Create id2 cell only for userbox-2 and only if showId2 is true
		if data.showId2 then
			local id2Cell = tablerow:tag('td')
			id2Cell:addClass('userbox-id2')
			if data.id2Width then id2Cell:css('width', data.id2Width) end
			if data.id2Height then id2Cell:css('height', data.id2Height) end
			if data.id2BackgroundColor then id2Cell:css('background', data.id2BackgroundColor) end
			if data.id2TextAlign then id2Cell:css('text-align', data.id2TextAlign) end
			if data.id2FontSize then id2Cell:css('font-size', data.id2FontSize .. 'pt') end
			if data.id2Color then id2Cell:css('color', data.id2Color) else id2Cell:css('color', 'inherit') end
			if data.id2Padding then id2Cell:css('padding', data.id2Padding) end
			if data.id2LineHeight then id2Cell:css('line-height', data.id2LineHeight) end
			if data.id2OtherParams then id2Cell:cssText(data.id2OtherParams) end
			if data.id2 then id2Cell:wikitext(data.id2) end
		end
	end

	local title = mw.title.getCurrentTitle()
	if (title.namespace == 2) and not title.text:match("/") then
		return templateStyles .. tostring(root) -- regular user page
	elseif title.namespace == 14 then
		return templateStyles .. tostring(root) -- category
	elseif title.isTalkPage then
		return templateStyles .. tostring(root) -- talk page
	end

	-- Color contrast checking (simplified for TemplateStyles)
	local legible = true
	local contrast = require('Module:Color contrast')._ratio
	local function has_text(wikitext)
		if not wikitext then return false end
		wikitext = wikitext:gsub("]]", "|]]")
		wikitext = wikitext:gsub("%%s*:-(|.-)]]", "")
		wikitext = wikitext:gsub("%%s*:-(|.-)]]", "")
		wikitext = wikitext:gsub("%%s*:-(|.-)]]", "")
		return mw.text.trim(wikitext) ~= ""
	end

	if data.infoColor and data.backgroundColor and contrast { data.infoColor, data.backgroundColor, error = 0 } < 4.5 then
		legible = false
	end

	-- For bold text >= 14pt, requirement is only 3.
	local idContrastThreshold = 4.5
	local id2ContrastThreshold = 4.5
	if (data.idFontSize or 0) >= 14 then idContrastThreshold = 3 end
	if (data.id2FontSize or 0) >= 14 then id2ContrastThreshold = 3 end

	if data.showId and data.idColor and data.idBackgroundColor and contrast { data.idColor, data.idBackgroundColor, error = 0 } < idContrastThreshold then
		if has_text(data.id or "") then legible = false end
	end

	if data.showId2 and data.id2Color and data.id2BackgroundColor and contrast { data.id2Color, data.id2BackgroundColor, error = 0 } < id2ContrastThreshold then
		if has_text(data.id2 or "") then legible = false end
	end

	if not legible then
		root:wikitext(']')
	end

	return templateStyles .. tostring(root)
end

function p.categories(args, page)
	-- Gets categories from ].
	-- The page parameter makes the function act as though the module was being called from that page.
	-- It is included for testing purposes.
	local cats = {}
	cats = args.usercategory
	cats = args.usercategory2
	cats = args.usercategory3
	cats = args.usercategory4
	cats = args.usercategory5

	-- Get the title object
	local title
	if page then
		title = mw.title.new(page)
	else
		title = mw.title.getCurrentTitle()
	end

	-- Build category handler arguments.
	local chargs = {}
	chargs.page = page
	chargs.nocat = args.nocat
	chargs.main = ']'
	if args.notcatsubpages then
		chargs.subpage = 'no'
	end

	-- User namespace.
	local user = ''
	for i, cat in ipairs(cats) do
		user = user .. makeCat(cat)
	end
	chargs.user = user

	return categoryHandler(chargs)
end

return p