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.

// request.cf · coarse context

A page that knows where it met you.

Only coarse request metadata is shown. This demo does not display or persist visitor IP addresses.

Country
US
Cloudflare location
CMH
Connection
HTTP/2
Language
Not provided

Ray ID: a21e44ee88a4962d

Jump to content

Module talk:Color contrast

Page contents not supported in other languages.
Add topic
From Wikipedia, the free encyclopedia

Making the lum function accessible from modules

[edit source]

I've made the lum function accessible from modules by changing the code from:

function p.lum(frame)
	return color2lum(frame.args[1] or frame:getParent().args[1])
end

to:

function p.lum(frame)
	local args = frame.args[1] or frame:getParent().args[1]
	return p._lum(args)
end

function p._lum(args)
	return color2lum(args)
end

The changes are on the sandbox and will implement them if there are no comments. --Gonnym (talk) 11:03, 6 January 2019 (UTC)Reply

@Gonnym: That looks like a very sensible and useful improvement. My only reservation is that passing the parameters as a table gives the person wanting to import the routine no idea of what values/types to supply to the routine without having to read through all of the code to determine them. In general I'd usually recommend either documenting a brief list of required values for the args table or passing the parameters as a list of obviously-named variables rather than a table. But that's just a minor point and shouldn't stop you from updating the main module. --RexxS (talk) 13:03, 6 January 2019 (UTC)Reply
@RexxS: I don't mind doing either if that helps. I just followed the current style used for the other three public functions. Do you want me to change _lum(args) to _lum(color)? --Gonnym (talk) 13:27, 6 January 2019 (UTC)Reply
@Gonnym: Sorry, my confusion: now I've looked harder at it, you're actually passing a string representing the colour, not a table (which is what args would most commonly indicate). I would suggest:
-- use {{#invoke:Color_contrast|somecolor}} directly or {{#invoke:Color_contrast}} from a wrapper template:
function p.lum(frame)
	local color = frame.args[1] or frame:getParent().args[1]
	return p._lum(color)
end

-- This exports the function for use in other modules.
-- The colour is passed as a string:
function p._lum(color)
	return color2lum(color)
end
I know we can put fuller information in the documentation, but I always suggest leaving small annotations in the code to help any re-users.
You could also write p._lum = color2lum instead of the second function definition, but setting it out explicitly, as you have done, helps whoever is importing the module to see what parameters to supply. Cheers --RexxS (talk) 15:41, 6 January 2019 (UTC)Reply
Sure, looks good. I'll update the sandbox version. --Gonnym (talk) 15:43, 6 January 2019 (UTC)Reply

Possible typos in code?

[edit source]

Observing the code, I might have spotted a couple of typos:

In p._greatercontrast function, lines 160 and 161

[edit source]

I think

if mw.ustring.match(v3, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or
	mw.ustring.match(v3, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then

should read

if mw.ustring.match(c3, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') or
	mw.ustring.match(c3, '^[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$') then

instead. Here, v3 is expected to be a number, thus there is no point in applying it a regular expression. Besides, given the four lines above, it seems logical to use c3 variable here instead of v3.

In p._styleratio function, line 209

[edit source]

I think

if( lum ~= '' ) then bg, lum_fg = v, lum end

should read

if( lum ~= '' ) then fg, lum_fg = v, lum end

instead, since at this point we have isolated a forecolor specification from input CSS.

My apologies if I would have misinterpreted your code.

Kindly, Olivier Ph. (talk) 12:11, 13 October 2020 (UTC)Reply

Categorisation broken?

[edit source]

Through Documentation subpage, Category:Modules handling colors is added as expected. However, the page does not appear in Category:Modules handling colors (3). -DePiep (talk) 15:12, 7 January 2021 (UTC)Reply

@DePiep: categorisation behaves as something of a black art. The page appears in Category:Modules handling colors now, but obviously didn't earlier today. Wikipedia:FAQ/Categorization #Why might a category list not be up to date? discusses some of the issues that may cause the lag. I usually try a null edit to "touch" the pages concerned and often find the page then appears in the category, but it's not always 100% successful. --RexxS (talk) 16:07, 7 January 2021 (UTC)Reply
I had just edited out the {{Sandbox other}} . So we have a cause (bug). Did not investigate problem further.-DePiep (talk) 16:11, 7 January 2021 (UTC)Reply
Yes I saw that. But because the category was being added via {{Sandbox other}} and now is added directly via Module:Color contrast/doc, that becomes effectively a different transclusion and the usual caveats about delays because of cached transclusions apply. --RexxS (talk) 16:56, 7 January 2021 (UTC)Reply
{{Sandbox other}} should be checked for Module ns then? But here it seems to work. (To be clear: before my edit the category was empty, and no delay was working, no recent edits). I'll leave it for now. -DePiep (talk) 17:18, 7 January 2021 (UTC)Reply

Template-protected edit request on 18 March 2025

[edit source]

Line 135:

local c2 = args[2] or '#FFFFFF'
+
local c2 = args[2] or 'white'

Line 137:

local c3 = args[3] or '#000000'
+
local c3 = args[3] or 'black'

Change the specification of the default colors from hex triplets '#FFFFFF' and '#000000' to named HTML colors 'white' and 'black' respectively. This allows the default case to take advantage of the pre-computed table of relative luminances of named HTML colors at Module:Color contrast/colors checked by the color2lum() function instead of calculating the relative luminances of white and black every time (as the module as currently written does), as well as, at least for the default colors, avoiding a parser bug that causes output that begins with # to result in a numbered list. Kinsio (talkcontribsrights) 18:55, 19 March 2025 (UTC)Reply

 Done * Pppery * it has begun... 20:30, 30 March 2025 (UTC)Reply

Template-protected edit request on 20 July 2026

[edit source]

Please update the module to support additional CSS3/CSS4 color formats ("rgba", "hsla", 4-digit and 8-digit hex values) and incorporate several code fixes, bringing it up to speed with the improvements from "ptwiki".

Key changes

[edit source]
  1. Updated regex patterns in "color2lum" to support "rgba()", "hsla()", space-separated values, and "#RGBA" (4-digit) / "#RRGGBBAA" (8-digit) hex formats.
  2. Fixed a variable check bug in "_greatercontrast" where "v3" was tested instead of "c3".
  3. Stripped newlines and normalized whitespace in the CSS output for "_greatercontrast" when the "css" flag is active.
  4. Cleaned up variable scoping in "_styleratio" to prevent shadowing loop index "k" and removed unused variables ("bg", "fg").

Replace the current code of the module with:

--GKNishimoto (talk) 05:16, 20 July 2026 (UTC)Reply

I've gone ahead and done some cleanup on the code and everything generally looks good, but I do have a question. Since this adds support for specifying colours with an alpha, is it correct behaviour to just ignore that alpha property entirely? It feels like that should matter for the purpose of calculating the ratio, though I'm not familiar with the exact scope of this module. Aidan9382 (talk) 21:33, 26 July 2026 (UTC)Reply
Hi @Aidan9382,
Thanks for reviewing and refining the code in the sandbox! The regex fix in '_greatercontrast' to support 4-digit and 8-digit hex values when using the 'css' flag is a great spot.
To answer your question directly: Yes, ignoring the alpha component is the intended and correct behavior for this module.
Under the WCAG 2.1 accessibility guidelines, computing the exact contrast ratio of a semi-transparent color requires blending it against whatever background is rendered behind it. Since this Lua module evaluates color values statically without access to the surrounding page layout or DOM context, it cannot reliably determine the underlying background layer.
Stripping or ignoring the alpha channel allows the module to gracefully fall back to evaluating the base RGB/HSL contrast without throwing errors or returning blank values when editors pass modern CSS formats (such as '#RRGGBBAA' or 'rgba()').
The code currently in the sandbox looks great and is ready to be applied. Thanks again for the help! -- GKNishimoto (talk) 21:42, 26 July 2026 (UTC)Reply
P.S. Thanks again! Once this goes live here, I'll be porting this updated version directly to ptwiki as well to keep both modules completely aligned.-- GKNishimoto (talk) 21:51, 26 July 2026 (UTC)Reply
In that case this seems fine,  Done. Aidan9382 (talk) 12:42, 27 July 2026 (UTC)Reply
This change broke the layout at Template:Basketballbox/testcases for transclusions using |bg=. Please test the sandbox module with that template. – Jonesey95 (talk) 16:11, 27 July 2026 (UTC)Reply
More specifically, it caused output in the form of background-color:#eeeeee; color:#202122;1, breaking following css rules. LittlePuppers (talk) 16:16, 27 July 2026 (UTC)Reply
Well, it seems I didn't aniticipate that scribunto would just implicitly concatenate multiple returns instead of taking just the first return, which gsub will cause. Thanks for that. I've gone ahead and fixed that in the sandbox. Aidan9382 (talk) 16:23, 27 July 2026 (UTC)Reply
Updated module sandbox to fix the CSS output formatting issue. Removed the :gsub() whitespace/newline compression that was causing multiple return values and appending an unintended '1' to the style string, fully resolving the layout breaks on templates using |bg= (such as Basketballbox) while retaining all new CSS3/CSS4 color format features.
While Aidan9382's quick fix in the sandbox solved the immediate multiple-return bug by keeping a single :gsub('[\r\n]', ''), completely removing the extra string manipulation—as we did in our version—is cleaner and fully avoids any potential edge cases with complex template markup or string concatenation in Scribunto. It keeps the CSS output pure, exact, and 100% robust. --GKNishimoto (talk) 17:46, 27 July 2026 (UTC)Reply