Jump to content

Module:Userbox: Difference between revisions

From L&S Wiki
m Protected "Module:Userbox": Moudle ([Edit=Allow only administrators] (indefinite) [Move=Allow only administrators] (indefinite))
No edit summary
 
Line 79: Line 79:


-- Get div tag values.
-- Get div tag values.
data.float = args.float
data.float = args.float or 'left'
local borderWidthNum = checkNum(args['border-width'] or args['border-s'], nil)
local borderWidthNum = checkNum(args['border-width'] or args['border-s'], 1) -- Used to calculate width.
data.borderWidth = addSuffix(borderWidthNum, 'px')
data.borderWidth = addSuffix(borderWidthNum, 'px')
data.borderColor = args['border-color'] or args['border-c'] or args[1] or args['id-c']
data.borderColor = args['border-color'] or args['border-c'] or args[1] or args['id-c'] or '#999'
data.width = borderWidthNum and addSuffix(240 - 2 * borderWidthNum, 'px')
data.width = addSuffix(240 - 2 * borderWidthNum, 'px') -- Also used in the table tag.
data.bodyClass = args.bodyclass
data.bodyClass = args.bodyclass


-- Get table tag values.
-- Get table tag values.
data.backgroundColor = args['info-background'] or args[2] or args['info-c']
data.backgroundColor = args['info-background'] or args[2] or args['info-c'] or '#eee'


-- Get info values.
-- Get info values.
data.info = args.info or args[4] or "<code>{{{info}}}</code>"
data.info = args.info or args[4] or "<code>{{{info}}}</code>"
data.infoTextAlign = args['info-a']
data.infoTextAlign = args['info-a'] or 'left'
data.infoFontSize = checkNumAndAddSuffix(args['info-size'] or args['info-s'], nil, 'pt')
data.infoFontSize = checkNumAndAddSuffix(args['info-size'] or args['info-s'], 8, 'pt')
data.infoHeight = checkNumAndAddSuffix(args['logo-height'] or args['id-h'], nil, 'px')
data.infoHeight = checkNumAndAddSuffix(args['logo-height'] or args['id-h'], 45, 'px')
data.infoPadding = args['info-padding'] or args['info-p']
data.infoPadding = args['info-padding'] or args['info-p'] or '0 4px 0 4px'
data.infoLineHeight = args['info-line-height'] or args['info-lh']
data.infoLineHeight = args['info-line-height'] or args['info-lh'] or '1.25em'
data.infoColor = args['info-color'] or args['info-fc']
data.infoColor = args['info-color'] or args['info-fc'] or 'black'
data.infoOtherParams = args['info-other-param'] or args['info-op']
data.infoOtherParams = args['info-other-param'] or args['info-op']
data.infoClass = args['info-class']
data.infoClass = args['info-class']
Line 104: Line 104:
data.id = id
data.id = id
data.showId = id and true or false
data.showId = id and true or false
data.idWidth = checkNumAndAddSuffix(args['logo-width'] or args['id-w'], nil, 'px')
data.idWidth = checkNumAndAddSuffix(args['logo-width'] or args['id-w'], 45, 'px')
data.idHeight = checkNumAndAddSuffix(args['logo-height'] or args['id-h'], nil, 'px')
data.idHeight = checkNumAndAddSuffix(args['logo-height'] or args['id-h'], 45, 'px')
data.idBackgroundColor = args['logo-background'] or args[1] or args['id-c']
data.idBackgroundColor = args['logo-background'] or args[1] or args['id-c'] or '#ddd'
data.idTextAlign = args['id-a']
data.idTextAlign = args['id-a'] or 'center'
data.idFontSize = checkNum(args['logo-size'] or args[5] or args['id-s'], nil)
data.idFontSize = checkNumAndAddSuffix(args['logo-size'] or args[5] or args['id-s'], 14, 'pt')
data.idColor = args['logo-color'] or args['id-fc'] or data.infoColor
data.idColor = args['logo-color'] or args['id-fc'] or data.infoColor
data.idPadding = args['logo-padding'] or args['id-p']
data.idPadding = args['logo-padding'] or args['id-p'] or '0 1px 0 0'
data.idLineHeight = args['logo-line-height'] or args['id-lh']
data.idLineHeight = args['logo-line-height'] or args['id-lh'] or '1.25em'
data.idOtherParams = args['logo-other-param'] or args['id-op']
data.idOtherParams = args['logo-other-param'] or args['id-op']
data.idClass = args['id-class']
data.idClass = args['id-class']
Line 123: Line 123:


-- Get div tag values.
-- Get div tag values.
data.float = args.float
data.float = args.float or 'left'
local borderWidthNum = checkNum(args['border-s'] or args[9], nil)
local borderWidthNum = checkNum(args['border-s'] or args[9], 1) -- Used to calculate width.
data.borderWidth = addSuffix(borderWidthNum, 'px')
data.borderWidth = addSuffix(borderWidthNum, 'px')
data.borderColor = args['border-c'] or args[6] or args['id1-c'] or args[1]
data.borderColor = args['border-c'] or args[6] or args['id1-c'] or args[1] or '#999999'
data.width = borderWidthNum and addSuffix(240 - 2 * borderWidthNum, 'px')
data.width = addSuffix(240 - 2 * borderWidthNum, 'px') -- Also used in the table tag.
data.bodyClass = args.bodyclass
data.bodyClass = args.bodyclass


-- Get table tag values.
-- Get table tag values.
data.backgroundColor = args['info-c'] or args[2]
data.backgroundColor = args['info-c'] or args[2] or '#eeeeee'


-- Get info values.
-- Get info values.
data.info = args.info or args[4] or "<code>{{{info}}}</code>"
data.info = args.info or args[4] or "<code>{{{info}}}</code>"
data.infoTextAlign = args['info-a']
data.infoTextAlign = args['info-a'] or 'left'
data.infoFontSize = checkNumAndAddSuffix(args['info-s'], nil, 'pt')
data.infoFontSize = checkNumAndAddSuffix(args['info-s'], 8, 'pt')
data.infoColor = args['info-fc'] or args[8]
data.infoColor = args['info-fc'] or args[8] or 'black'
data.infoPadding = args['info-p']
data.infoPadding = args['info-p'] or '0 4px 0 4px'
data.infoLineHeight = args['info-lh']
data.infoLineHeight = args['info-lh'] or '1.25em'
data.infoOtherParams = args['info-op']
data.infoOtherParams = args['info-op']


Line 145: Line 145:
data.showId = true
data.showId = true
data.id = args.logo or args[3] or args.id1 or 'id1'
data.id = args.logo or args[3] or args.id1 or 'id1'
data.idWidth = checkNumAndAddSuffix(args['id1-w'], nil, 'px')
data.idWidth = checkNumAndAddSuffix(args['id1-w'], 45, 'px')
data.idHeight = checkNumAndAddSuffix(args['id-h'], nil, 'px')
data.idHeight = checkNumAndAddSuffix(args['id-h'], 45, 'px')
data.idBackgroundColor = args['id1-c'] or args[1]
data.idBackgroundColor = args['id1-c'] or args[1] or '#dddddd'
data.idTextAlign = args['id-a']
data.idTextAlign = 'center'
data.idFontSize = checkNum(args['id1-s'], nil)
data.idFontSize = checkNumAndAddSuffix(args['id1-s'], 14, 'pt')
data.idLineHeight = args['id1-lh']
data.idLineHeight = args['id1-lh'] or '1.25em'
data.idColor = args['id1-fc'] or data.infoColor
data.idColor = args['id1-fc'] or data.infoColor
data.idPadding = args['id1-p']
data.idPadding = args['id1-p'] or '0 1px 0 0'
data.idOtherParams = args['id1-op']
data.idOtherParams = args['id1-op']


Line 158: Line 158:
data.showId2 = true
data.showId2 = true
data.id2 = args.logo or args[5] or args.id2 or 'id2'
data.id2 = args.logo or args[5] or args.id2 or 'id2'
data.id2Width = checkNumAndAddSuffix(args['id2-w'], nil, 'px')
data.id2Width = checkNumAndAddSuffix(args['id2-w'], 45, 'px')
data.id2Height = data.idHeight
data.id2Height = data.idHeight
data.id2BackgroundColor = args['id2-c'] or args[7] or args[1]
data.id2BackgroundColor = args['id2-c'] or args[7] or args[1] or '#dddddd'
data.id2TextAlign = nil -- Always center, but don't set if no content
data.id2TextAlign = 'center'
data.id2FontSize = checkNum(args['id2-s'], nil)
data.id2FontSize = checkNumAndAddSuffix(args['id2-s'], 14, 'pt')
data.id2LineHeight = args['id2-lh']
data.id2LineHeight = args['id2-lh'] or '1.25em'
data.id2Color = args['id2-fc'] or data.infoColor
data.id2Color = args['id2-fc'] or data.infoColor
data.id2Padding = args['id2-p']
data.id2Padding = args['id2-p'] or '0 0 0 1px'
data.id2OtherParams = args['id2-op']
data.id2OtherParams = args['id2-op']


Line 176: Line 176:


-- Get div tag values.
-- Get div tag values.
data.float = args.float
data.float = args.float or 'left'
local borderWidthNum = checkNum(args['border-width'] or args['border-s'], nil)
local borderWidthNum = checkNum(args['border-width'] or args['border-s'], 1) -- Used to calculate width.
data.borderWidth = addSuffix(borderWidthNum, 'px')
data.borderWidth = addSuffix(borderWidthNum, 'px')
data.borderColor = args['border-color'] or args['border-c'] or args[1] or args['id-c']
data.borderColor = args['border-color'] or args['border-c'] or args[1] or args['id-c'] or '#999'
data.width = borderWidthNum and addSuffix(240 - 2 * borderWidthNum, 'px')
data.width = addSuffix(240 - 2 * borderWidthNum, 'px') -- Also used in the table tag.
data.bodyClass = args.bodyclass
data.bodyClass = args.bodyclass
 
-- Get table tag values.
-- Get table tag values.
data.backgroundColor = args['info-background'] or args[2] or args['info-c']
data.backgroundColor = args['info-background'] or args[2] or args['info-c'] or '#eee'


-- Get id values.
-- Get id values.
Line 191: Line 191:
-- Get info values.
-- Get info values.
data.info = args.info or args[4] or "<code>{{{info}}}</code>"
data.info = args.info or args[4] or "<code>{{{info}}}</code>"
data.infoTextAlign = args['info-align'] or args['info-a']
data.infoTextAlign = args['info-align'] or args['info-a'] or 'left'
data.infoFontSize = checkNumAndAddSuffix(args['info-size'] or args['info-s'], nil, 'pt')
data.infoFontSize = checkNumAndAddSuffix(args['info-size'] or args['info-s'], 8, 'pt')
data.infoPadding = args['info-padding'] or args['info-p']
data.infoPadding = args['info-padding'] or args['info-p'] or '0 4px 0 4px'
data.infoLineHeight = args['info-line-height'] or args['info-lh']
data.infoLineHeight = args['info-line-height'] or args['info-lh'] or '1.25em'
data.infoColor = args['info-color'] or args['info-fc']
data.infoColor = args['info-color'] or args['info-fc'] or 'black'
data.infoOtherParams = args['info-other-param'] or args['info-op']
data.infoOtherParams = args['info-other-param'] or args['info-op']
 
-- Get id2 values.
-- Get id2 values.
data.showId2 = true -- userbox-r always shows the ID cell (as id2)
data.showId2 = true
data.id2 = args.logo or args[3] or args.id or 'id'
data.id2 = args.logo or args[3] or args.id or 'id'
data.id2Width = checkNumAndAddSuffix(args['logo-width'] or args['id-w'], nil, 'px')
data.id2Width = checkNumAndAddSuffix(args['logo-width'] or args['id-w'], 45, 'px')
data.id2Height = checkNumAndAddSuffix(args['logo-height'] or args['id-h'], nil, 'px')
data.id2Height = checkNumAndAddSuffix(args['logo-height'] or args['id-h'], 45, 'px')
data.id2BackgroundColor = args['logo-background'] or args[1] or args['id-c']
data.id2BackgroundColor = args['logo-background'] or args[1] or args['id-c'] or '#ddd'
data.id2TextAlign = args['id-a']
data.id2TextAlign = args['id-a'] or 'center'
data.id2FontSize = checkNum(args['logo-size'] or args[5] or args['id-s'], nil)
data.id2FontSize = checkNumAndAddSuffix(args['logo-size'] or args[5] or args['id-s'], 14, 'pt')
data.id2Color = args['logo-color'] or args['id-fc'] or data.infoColor
data.id2Color = args['logo-color'] or args['id-fc'] or data.infoColor
data.id2Padding = args['logo-padding'] or args['id-p']
data.id2Padding = args['logo-padding'] or args['id-p'] or '0 0 0 1px'
data.id2LineHeight = args['logo-line-height'] or args['id-lh']
data.id2LineHeight = args['logo-line-height'] or args['id-lh'] or '1.25em'
data.id2OtherParams = args['logo-other-param'] or args['id-op']
data.id2OtherParams = args['logo-other-param'] or args['id-op']


Line 215: Line 215:


function p.render(data)
function p.render(data)
-- Renders the userbox html using the content of the data table.
-- 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.
-- Render the div tag html.
local root = mw.html.create('div')
local root = mw.html.create('div')
root:addClass('wikipediauserbox')
root
 
:css('float', data.float)
-- Only add CSS properties if they have values
:css('border', (data.borderWidth or '') .. ' solid ' .. (data.borderColor or ''))
if data.float then root:css('float', data.float) end
:css('margin', '1px')
if data.borderWidth then
:css('width', data.width)
root:css('border-width', data.borderWidth)
:addClass('wikipediauserbox')
end
:addClass(data.bodyClass)
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.
-- Render the table tag html.
local tableroot = root:tag('table')
local tableroot = root:tag('table')
tableroot:attr('role', 'presentation')
tableroot
 
:attr('role', 'presentation')
-- Only add CSS if values exist
:css('border-collapse', 'collapse')
if data.width then tableroot:css('width', data.width) end
:css('width', data.width)
if data.backgroundColor then tableroot:css('background', data.backgroundColor):css('color', 'inherit') end
:css('margin-bottom', '0')
 
:css('margin-top', '0')
:css('background', data.backgroundColor)
-- Render the id html.
local tablerow = tableroot:tag('tr')
local tablerow = tableroot:tag('tr')
if data.showId then
tablerow:tag('td')
:css('border', '0')
:css('width', data.idWidth)
:css('height', data.idHeight)
:css('background', data.idBackgroundColor)
:css('text-align', data.idTextAlign)
:css('font-size', data.idFontSize)
:css('font-weight', 'bold')
:css('color', data.idColor)
:css('padding', data.idPadding)
:css('line-height', data.idLineHeight)
:css('vertical-align', 'middle')
:cssText(data.idOtherParams)
:addClass(data.idClass)
:wikitext(data.id)
end


-- Create cells based on what should actually be shown
-- Render the info html.
if data.showId == false then
tablerow:tag('td')
-- userbox-r: info cell first, then id2 cell (if showId2 is true)
:css('border', '0')
local infoCell = tablerow:tag('td')
:css('text-align', data.infoTextAlign)
infoCell:addClass('userbox-info')
:css('font-size', data.infoFontSize)
if data.infoTextAlign then infoCell:css('text-align', data.infoTextAlign) end
:css('padding', data.infoPadding)
if data.infoFontSize then infoCell:css('font-size', data.infoFontSize) end
:css('height', data.infoHeight)
if data.infoPadding then infoCell:css('padding', data.infoPadding) end
:css('line-height', data.infoLineHeight)
if data.infoHeight then infoCell:css('height', data.infoHeight) end
:css('color', data.infoColor)
if data.infoLineHeight then infoCell:css('line-height', data.infoLineHeight) end
:css('vertical-align', 'middle')
if data.infoColor then infoCell:css('color', data.infoColor) end
:cssText(data.infoOtherParams)
if data.infoOtherParams then infoCell:cssText(data.infoOtherParams) end
:addClass(data.infoClass)
if data.infoClass then infoCell:addClass(data.infoClass) end
:wikitext(data.info)
if data.info then infoCell:wikitext(data.info) end
-- Render the second id html.
-- Create id2 cell only if showId2 is true
if data.showId2 then
if data.showId2 then
tablerow:tag('td')
local id2Cell = tablerow:tag('td')
:css('border', '0')
id2Cell:addClass('userbox-id2')
:css('width', data.id2Width)
if data.id2Width then id2Cell:css('width', data.id2Width) end
:css('height', data.id2Height)
if data.id2Height then id2Cell:css('height', data.id2Height) end
:css('background', data.id2BackgroundColor)
if data.id2BackgroundColor then id2Cell:css('background', data.id2BackgroundColor) end
:css('text-align', data.id2TextAlign)
if data.id2TextAlign then id2Cell:css('text-align', data.id2TextAlign) end
:css('font-size', data.id2FontSize)
if data.id2FontSize then id2Cell:css('font-size', data.id2FontSize .. 'pt') end
:css('font-weight', 'bold')
if data.id2Color then id2Cell:css('color', data.id2Color) else id2Cell:css('color', 'inherit') end
:css('color', data.id2Color)
if data.id2Padding then id2Cell:css('padding', data.id2Padding) end
:css('padding', data.id2Padding)
if data.id2LineHeight then id2Cell:css('line-height', data.id2LineHeight) end
:css('line-height', data.id2LineHeight)
if data.id2OtherParams then id2Cell:cssText(data.id2OtherParams) end
:css('vertical-align', 'middle')
if data.id2 then id2Cell:wikitext(data.id2) end
:cssText(data.id2OtherParams)
end
:wikitext(data.id2)
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
end


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


-- Color contrast checking (simplified for TemplateStyles)
local legible = true
local legible = true
local contrast = require('Module:Color contrast')._ratio
local contrast = require('Module:Color contrast')._ratio
local function has_text(wikitext)
local function has_text(wikitext)
if not wikitext then return false end
local function get_alt(text)
return text:match("|alt=([^|]*)") or ""
end
wikitext = wikitext:gsub("]]", "|]]")
wikitext = wikitext:gsub("]]", "|]]")
wikitext = wikitext:gsub("%[%[%s*[Mm][Ee][Dd][Ii][Aa]%s*:[^|]-(|.-)]]", "")
wikitext = wikitext:gsub("%[%[%s*[Mm][Ee][Dd][Ii][Aa]%s*:[^|]-(|.-)]]", get_alt)
wikitext = wikitext:gsub("%[%[%s*[Ii][Mm][Aa][Gg][Ee]%s*:[^|]-(|.-)]]", "")
wikitext = wikitext:gsub("%[%[%s*[Ii][Mm][Aa][Gg][Ee]%s*:[^|]-(|.-)]]", get_alt)
wikitext = wikitext:gsub("%[%[%s*[Ff][Ii][Ll][Ee]%s*:[^|]-(|.-)]]", "")
wikitext = wikitext:gsub("%[%[%s*[Ff][Ii][Ll][Ee]%s*:[^|]-(|.-)]]", get_alt)
return mw.text.trim(wikitext) ~= ""
return mw.text.trim(wikitext) ~= ""
end
end


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


-- For bold text >= 14pt, requirement is only 3.
if data.showId and contrast { data.idColor, data.idBackgroundColor, error = 0 } < 4.5 then
local idContrastThreshold = 4.5
if has_text(data.id or "") then
local id2ContrastThreshold = 4.5
legible = false
if (data.idFontSize or 0) >= 14 then idContrastThreshold = 3 end
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
end


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


Line 372: Line 332:
end
end


return templateStyles .. tostring(root)
return tostring(root)
end
end


Line 385: Line 345:
cats[#cats + 1] = args.usercategory4
cats[#cats + 1] = args.usercategory4
cats[#cats + 1] = args.usercategory5
cats[#cats + 1] = args.usercategory5
 
if #cats > 0 then
-- Get the title object
-- Get the title object
local title
local title
if page then
if page then
title = mw.title.new(page)
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 = '[[Category:Pages with misplaced templates]]'
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
-- Template namespace.
local basepage = title.baseText
local template = ''
for i, cat in ipairs(cats) do
template = template .. makeCat(cat, ' ' .. basepage)
end
chargs.template = template
return categoryHandler(chargs)
else
else
title = mw.title.getCurrentTitle()
return nil
end
 
-- Build category handler arguments.
local chargs = {}
chargs.page = page
chargs.nocat = args.nocat
chargs.main = '[[Category:Pages with templates in the wrong namespace]]'
if args.notcatsubpages then
chargs.subpage = 'no'
end
end
-- User namespace.
local user = ''
for i, cat in ipairs(cats) do
user = user .. makeCat(cat)
end
chargs.user = user
return categoryHandler(chargs)
end
end


return p
return p

Latest revision as of 11:57, 26 December 2025

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

-- 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('[[Category:%s|%s]]', cat, sort)
	else
		return mw.ustring.format('[[Category:%s]]', 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[k] = v
		end
		return p.main(funcName, args)
	end
end

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

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

function p.main(funcName, args)
	local userboxData = p[funcName](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 or 'left'
	local borderWidthNum = checkNum(args['border-width'] or args['border-s'], 1) -- Used to calculate width.
	data.borderWidth = addSuffix(borderWidthNum, 'px')
	data.borderColor = args['border-color'] or args['border-c'] or args[1] or args['id-c'] or '#999'
	data.width = addSuffix(240 - 2 * borderWidthNum, 'px') -- Also used in the table tag.
	data.bodyClass = args.bodyclass

	-- Get table tag values.
	data.backgroundColor = args['info-background'] or args[2] or args['info-c'] or '#eee'

	-- Get info values.
	data.info = args.info or args[4] or "<code>{{{info}}}</code>"
	data.infoTextAlign = args['info-a'] or 'left'
	data.infoFontSize = checkNumAndAddSuffix(args['info-size'] or args['info-s'], 8, 'pt')
	data.infoHeight = checkNumAndAddSuffix(args['logo-height'] or args['id-h'], 45, 'px')
	data.infoPadding = args['info-padding'] or args['info-p'] or '0 4px 0 4px'
	data.infoLineHeight = args['info-line-height'] or args['info-lh'] or '1.25em'
	data.infoColor = args['info-color'] or args['info-fc'] or 'black'
	data.infoOtherParams = args['info-other-param'] or args['info-op']
	data.infoClass = args['info-class']

	-- Get id values.
	local id = args.logo or args[3] or args.id
	data.id = id
	data.showId = id and true or false
	data.idWidth = checkNumAndAddSuffix(args['logo-width'] or args['id-w'], 45, 'px')
	data.idHeight = checkNumAndAddSuffix(args['logo-height'] or args['id-h'], 45, 'px')
	data.idBackgroundColor = args['logo-background'] or args[1] or args['id-c'] or '#ddd'
	data.idTextAlign = args['id-a'] or 'center'
	data.idFontSize = checkNumAndAddSuffix(args['logo-size'] or args[5] or args['id-s'], 14, 'pt')
	data.idColor = args['logo-color'] or args['id-fc'] or data.infoColor
	data.idPadding = args['logo-padding'] or args['id-p'] or '0 1px 0 0'
	data.idLineHeight = args['logo-line-height'] or args['id-lh'] or '1.25em'
	data.idOtherParams = args['logo-other-param'] or args['id-op']
	data.idClass = args['id-class']

	return data
end

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

	-- Get div tag values.
	data.float = args.float or 'left'
	local borderWidthNum = checkNum(args['border-s'] or args[9], 1) -- Used to calculate width.
	data.borderWidth = addSuffix(borderWidthNum, 'px')
	data.borderColor = args['border-c'] or args[6] or args['id1-c'] or args[1] or '#999999'
	data.width = addSuffix(240 - 2 * borderWidthNum, 'px') -- Also used in the table tag.
	data.bodyClass = args.bodyclass

	-- Get table tag values.
	data.backgroundColor = args['info-c'] or args[2] or '#eeeeee'

	-- Get info values.
	data.info = args.info or args[4] or "<code>{{{info}}}</code>"
	data.infoTextAlign = args['info-a'] or 'left'
	data.infoFontSize = checkNumAndAddSuffix(args['info-s'], 8, 'pt')
	data.infoColor = args['info-fc'] or args[8] or 'black'
	data.infoPadding = args['info-p'] or '0 4px 0 4px'
	data.infoLineHeight = args['info-lh'] or '1.25em'
	data.infoOtherParams = args['info-op']

	-- Get id values.
	data.showId = true
	data.id = args.logo or args[3] or args.id1 or 'id1'
	data.idWidth = checkNumAndAddSuffix(args['id1-w'], 45, 'px')
	data.idHeight = checkNumAndAddSuffix(args['id-h'], 45, 'px')
	data.idBackgroundColor = args['id1-c'] or args[1] or '#dddddd'
	data.idTextAlign = 'center'
	data.idFontSize = checkNumAndAddSuffix(args['id1-s'], 14, 'pt')
	data.idLineHeight = args['id1-lh'] or '1.25em'
	data.idColor = args['id1-fc'] or data.infoColor
	data.idPadding = args['id1-p'] or '0 1px 0 0'
	data.idOtherParams = args['id1-op']

	-- Get id2 values.
	data.showId2 = true
	data.id2 = args.logo or args[5] or args.id2 or 'id2'
	data.id2Width = checkNumAndAddSuffix(args['id2-w'], 45, 'px')
	data.id2Height = data.idHeight
	data.id2BackgroundColor = args['id2-c'] or args[7] or args[1] or '#dddddd'
	data.id2TextAlign = 'center'
	data.id2FontSize = checkNumAndAddSuffix(args['id2-s'], 14, 'pt')
	data.id2LineHeight = args['id2-lh'] or '1.25em'
	data.id2Color = args['id2-fc'] or data.infoColor
	data.id2Padding = args['id2-p'] or '0 0 0 1px'
	data.id2OtherParams = args['id2-op']

	return data
end

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

	-- Get div tag values.
	data.float = args.float or 'left'
	local borderWidthNum = checkNum(args['border-width'] or args['border-s'], 1) -- Used to calculate width.
	data.borderWidth = addSuffix(borderWidthNum, 'px')
	data.borderColor = args['border-color'] or args['border-c'] or args[1] or args['id-c'] or '#999'
	data.width = addSuffix(240 - 2 * borderWidthNum, 'px') -- Also used in the table tag.
	data.bodyClass = args.bodyclass
	
	-- Get table tag values.
	data.backgroundColor = args['info-background'] or args[2] or args['info-c'] or '#eee'

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

	-- Get info values.
	data.info = args.info or args[4] or "<code>{{{info}}}</code>"
	data.infoTextAlign = args['info-align'] or args['info-a'] or 'left'
	data.infoFontSize = checkNumAndAddSuffix(args['info-size'] or args['info-s'], 8, 'pt')
	data.infoPadding = args['info-padding'] or args['info-p'] or '0 4px 0 4px'
	data.infoLineHeight = args['info-line-height'] or args['info-lh'] or '1.25em'
	data.infoColor = args['info-color'] or args['info-fc'] or 'black'
	data.infoOtherParams = args['info-other-param'] or args['info-op']
	
	-- Get id2 values.
	data.showId2 = true
	data.id2 = args.logo or args[3] or args.id or 'id'
	data.id2Width = checkNumAndAddSuffix(args['logo-width'] or args['id-w'], 45, 'px')
	data.id2Height = checkNumAndAddSuffix(args['logo-height'] or args['id-h'], 45, 'px')
	data.id2BackgroundColor = args['logo-background'] or args[1] or args['id-c'] or '#ddd'
	data.id2TextAlign = args['id-a'] or 'center'
	data.id2FontSize = checkNumAndAddSuffix(args['logo-size'] or args[5] or args['id-s'], 14, 'pt')
	data.id2Color = args['logo-color'] or args['id-fc'] or data.infoColor
	data.id2Padding = args['logo-padding'] or args['id-p'] or '0 0 0 1px'
	data.id2LineHeight = args['logo-line-height'] or args['id-lh'] or '1.25em'
	data.id2OtherParams = args['logo-other-param'] or args['id-op']

	return data
end

function p.render(data)
	-- Renders the userbox html using the content of the data table. 
	-- Render the div tag html.
	local root = mw.html.create('div')
	root
		:css('float', data.float)
		:css('border', (data.borderWidth or '') .. ' solid ' .. (data.borderColor or ''))
		:css('margin', '1px')
		:css('width', data.width)
		:addClass('wikipediauserbox')
		:addClass(data.bodyClass)

	-- Render the table tag html.
	local tableroot = root:tag('table')
	tableroot
		:attr('role', 'presentation')
		:css('border-collapse', 'collapse')
		:css('width', data.width)
		:css('margin-bottom', '0')
		:css('margin-top', '0')
		:css('background', data.backgroundColor)
	
	-- Render the id html.
	local tablerow = tableroot:tag('tr')
	if data.showId then
		tablerow:tag('td')
			:css('border', '0')
			:css('width', data.idWidth)
			:css('height', data.idHeight)
			:css('background', data.idBackgroundColor)
			:css('text-align', data.idTextAlign)
			:css('font-size', data.idFontSize)
			:css('font-weight', 'bold')
			:css('color', data.idColor)
			:css('padding', data.idPadding)
			:css('line-height', data.idLineHeight)
			:css('vertical-align', 'middle')
			:cssText(data.idOtherParams)
			:addClass(data.idClass)
			:wikitext(data.id)
	end

	-- Render the info html.
	tablerow:tag('td')
		:css('border', '0')
		:css('text-align', data.infoTextAlign)
		:css('font-size', data.infoFontSize)
		:css('padding', data.infoPadding)
		:css('height', data.infoHeight)
		:css('line-height', data.infoLineHeight)
		:css('color', data.infoColor)
		:css('vertical-align', 'middle')
		:cssText(data.infoOtherParams)
		:addClass(data.infoClass)
		:wikitext(data.info)
	
	-- Render the second id html.
	if data.showId2 then
		tablerow:tag('td')
			:css('border', '0')
			:css('width', data.id2Width)
			:css('height', data.id2Height)
			:css('background', data.id2BackgroundColor)
			:css('text-align', data.id2TextAlign)
			:css('font-size', data.id2FontSize)
			:css('font-weight', 'bold')
			:css('color', data.id2Color)
			:css('padding', data.id2Padding)
			:css('line-height', data.id2LineHeight)
			:css('vertical-align', 'middle')
			:cssText(data.id2OtherParams)
			:wikitext(data.id2)
	end

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

	local legible = true
	local contrast = require('Module:Color contrast')._ratio

	local function has_text(wikitext)
		local function get_alt(text)
			return text:match("|alt=([^|]*)") or ""
		end
	
		wikitext = wikitext:gsub("]]", "|]]")
		wikitext = wikitext:gsub("%[%[%s*[Mm][Ee][Dd][Ii][Aa]%s*:[^|]-(|.-)]]", get_alt)
		wikitext = wikitext:gsub("%[%[%s*[Ii][Mm][Aa][Gg][Ee]%s*:[^|]-(|.-)]]", get_alt)
		wikitext = wikitext:gsub("%[%[%s*[Ff][Ii][Ll][Ee]%s*:[^|]-(|.-)]]", get_alt)
		return mw.text.trim(wikitext) ~= ""
	end

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

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

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

	if not legible then
		root:wikitext('[[Category:Userboxes with insufficient color contrast]]')
	end

	return tostring(root)
end

function p.categories(args, page)
	-- Gets categories from [[Module:Category handler]].
	-- 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[#cats + 1] = args.usercategory
	cats[#cats + 1] = args.usercategory2
	cats[#cats + 1] = args.usercategory3
	cats[#cats + 1] = args.usercategory4
	cats[#cats + 1] = args.usercategory5
	if #cats > 0 then
		-- 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 = '[[Category:Pages with misplaced templates]]'
		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
		-- Template namespace.
		local basepage = title.baseText
		local template = ''
		for i, cat in ipairs(cats) do
			template = template .. makeCat(cat, ' ' .. basepage)
		end
		chargs.template = template
		return categoryHandler(chargs)
	else
		return nil
	end
end

return p