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.
| This is the module sandbox page for Module:Userbox (diff). See also the companion subpage for test cases (run). |
| This Lua module is used on approximately 338,000 pages. To avoid major disruption and server load, any changes should be tested in the module's /sandbox or /testcases subpages, or in your own module sandbox. The tested changes can be added to this page in a single edit. Consider discussing changes on the talk page before implementing them. |
| This module depends on the following other modules: |
This module does the processing for three userbox templates, {{userbox}}, {{userbox-2}} and {{userbox-r}}.
| Template | Description | Examples | |||
|---|---|---|---|---|---|
| {{userbox}} | Makes userboxes with an id on the left-hand side, or with no id. |
| |||
| {{userbox-2}} | Makes userboxes with an id on both the left- and right-hand sides. |
| |||
| {{userbox-r}} | Makes userboxes with an id on the right-hand side. |
|
To use any of these templates from a wiki page, please see the individual template pages for documentation. To generate userboxes directly from Lua, read on.
To generate a userbox directly from Lua, first load the module.
local userbox = require('Module:Userbox')
You can then run any of the three templates with the code:
userbox.main(functionName, args)
For {{userbox}} use the function name "_userbox"; for {{userbox-2}} use the function name "_userbox-2"; and for {{userbox-r}} use the function name "_userbox-r". The args parameter is a table of arguments to pass to the different userbox functions. To see a list of valid arguments, please consult the individual template pages.
-- 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