Module:LightDarkColor

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