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:LightDarkColor

From Wikipedia, the free encyclopedia

--- Given a color given in light or dark mode, provide CSS that makes it dark
--  mode compatible.
--
-- @module		lightdarkcolor
-- @alias		p
-- @release		beta
-- @author		Awesome Aasim
-- @require		Module:Arguments
-- @require		Module:Entrypoint

local p = {}
local getArgs = require("Module:Arguments").getArgs

--- Converts hex to dec
-- @function		hex2dec
-- @param	{string}	hex		hex to convert
-- @return						Decimal value
local function hex2dec(hex)
	return tonumber('0x' .. hex)
end

function padZero(x, length)
	while #x < length do
		x = '0' .. x
	end
	return x
end

function round(x)
	local q,r = math.modf(x)
	if math.abs(r) < 0.5 or (math.abs(r) <= 0.5 and x < 0) then
		return q
	else
		return q + 1
	end
end

--- Converts dec to hex
-- @function		dec2hex
-- @param	{string}	dec		dec to convert
-- @return						Hexadecimal value
local function dec2hex(dec)
	return mw.ustring.format("%x", dec)
end

--- Inverts RGB
-- @function		p.invertRGB
-- @param	{table}		rgb		rgb table
-- @return						Inverted RGB table
function p._invertRGB(rgb)
	rgb[1] = 255 - rgb[1]
	rgb[2] = 255 - rgb[2]
	rgb[3] = 255 - rgb[3]
	return rgb
end

--- Get original hue for any color
-- @function			getHue
-- @param	{table}		rgb		rgb table
-- @return						Appropriate RGB for pigment
function getHue(rgb)
	local prgb = {
		rgb[1],
		rgb[2],
		rgb[3]
	}
	local maxPRGB = math.max(prgb[1], prgb[2], prgb[3])
	local minPRGB = math.min(prgb[1], prgb[2], prgb[3])
	if (maxPRGB == minPRGB) or (maxPRGB == 255 and minPRGB == 0) or (prgb[1] == prgb[2] and prgb[2] == prgb[3]) then
		return prgb
	end
	prgb[1] = prgb[1] - minPRGB
	prgb[2] = prgb[2] - minPRGB
	prgb[3] = prgb[3] - minPRGB
	local prgbFraction = 255 / (maxPRGB - minPRGB)
	prgb[1] = prgb[1] * prgbFraction
	prgb[2] = prgb[2] * prgbFraction
	prgb[3] = prgb[3] * prgbFraction
	prgb[1] = round(prgb[1])
	prgb[2] = round(prgb[2])
	prgb[3] = round(prgb[3])
	return prgb
end

p._getHue = getHue

--- Converts from (R, G, B) to (r, g, b, a) while preserving actual color in light mode
-- @function			p._RGB
-- @param	{table}		rgb		rgb table
-- @return						Appropriate RGBA
function p._RGB(rgb, bg)
	bg = bg or {255, 255, 255}
	local avgColor = (bg[1] + bg[2] + bg[3]) / 3
	-- extract original hue
	local hrgb = getHue(rgb)
	if hrgb[1] == hrgb[2] and hrgb[2] == hrgb[3] then
		hrgb[1] = hrgb[1] < avgColor and 0 or (hrgb[1] > avgColor and 1 or avgColor)
		hrgb[2] = hrgb[1]
		hrgb[3] = hrgb[1]
	end
	local alpha = 0
	local alphaCount = 0
	for k,v in pairs(rgb) do
		if hrgb[k] ~= bg[k] then
			alpha = alpha + math.abs(rgb[k] - bg[k]) / math.abs(hrgb[k] - bg[k])
			alphaCount = alphaCount + 1
		end
	end
	if alphaCount == 0 then
		alpha = 0
	else
		alpha = alpha / alphaCount
	end
	if alpha >= 1 then
		rgb[4] = 1
		return rgb
	elseif alpha <= 0 then
		alpha = 0
	end
	hrgb[4] = alpha
	return hrgb
end

--- Entrypoint for RGB related functions
-- @function			p.RGB
-- @param	{table} 	frame		invocation frame
-- @return							Wikitext output
function p.RGB(frame)
	local args = getArgs(frame)
	local rgbStr = args[1] or error("RGB not specified", 1)
	rgbStr = mw.text.trim(rgbStr)
	local rgb = mw.text.split(rgbStr, ",")
	rgb[1] = tonumber(rgb[1])
	if not rgb[2] and not rgb[3] then
		rgb[2] = rgb[1]
		rgb[3] = rgb[1]
	end
	rgb[2] = tonumber(rgb[2])
	rgb[3] = tonumber(rgb[3])
	local rgba = p._RGB(rgb)
	return table.concat(rgba, ',')
end


--- Converts from #RRGGBB to #rrggbbaa while preserving actual color
-- @function			p.Hex
-- @param	{table}		frame	invocation frame
-- @return						Wikitext output
function p.Hex(frame)
	local args = getArgs(frame)
	local hexStr = args[1] or error("Hex not specified", 1)
	hexStr = mw.text.trim(hexStr)
	local hexChars = mw.text.split(hexStr, '')
	local rgb = {}
	local rH = hexChars[1] .. hexChars[2]
	local gH = (hexChars[3] or '') .. (hexChars[4] or '')
	local bH = (hexChars[5] or '') .. (hexChars[6] or '')
	local aH = ''
	rgb[1] = hex2dec(rH)
	if gH == '' and bH == '' then
		rgb[2] = rgb[1]
		rgb[3] = rgb[1]
	end
	rgb[2] = hex2dec(gH)
	rgb[3] = hex2dec(bH)
	local rgba = p._RGB(rgb)
	rH = dec2hex(rgba[1])
	gH = dec2hex(rgba[2])
	bH = dec2hex(rgba[3])
	aH = dec2hex(round(rgba[4] * 255))
	return padZero(rH, 2) .. padZero(gH, 2) .. padZero(bH, 2) .. padZero(aH, 2)
end

--- Converts from HSL to hsla while preserving actual color
-- @function			p.HSL
-- @param	{table}		frame	invocation frame
-- @return						Wikitext output
-- @todo fill in function
function p.HSL(frame, dark)
	
end

--- Entrypoint for module
-- @function			p.main
-- @param	{table}		frame	invocation frame
-- @return						Wikitext output
p.main = require("Module:Entrypoint")(p)

return p