Documentation for this module may be created at Module:Color template/doc
-- DECLARATIONS
local p = {}
-- libraries
local getArgs = require('Dev:Arguments').getArgs
local tabber = require('Module:Tabber')._main
-- system functions
local str_gsub = string.gsub
local str_lower = string.lower
local mth_fmod = math.fmod
local mth_rand = math.random
local mth_randseed = math.randomseed
-- data
local data = mw.loadData('Module:Item data')
-- constants
local MOD = 1000000007
local timeSeed = mth_fmod(os.time(os.date('*t')), MOD)
local darkBackground = '#0e191a'
local lightBackground = '#ffffff'
-- HELPER FUNCTIONS
-- copy a table
-- Source - https://stackoverflow.com/a/16077650
local function deepcopy(o, seen)
seen = seen or {}
if o == nil then return nil end
if seen[o] then return seen[o] end
local no
if type(o) == 'table' then
no = {}
seen[o] = no
for k, v in next, o, nil do
no[deepcopy(k, seen)] = deepcopy(v, seen)
end
setmetatable(no, deepcopy(getmetatable(o), seen))
else -- number, string, boolean, etc
no = o
end
return no
end
-- dealing with truthy/falsy value\
local function conditional(value)
local falsy = {0, "", false}
for _, fal in pairs(falsy) do
if (value == fal) then
return false
end
end
return (value ~= nil)
end
-- sorted pairs()
local function spairs(t, order)
local keys = {}
for k in pairs(t) do keys[#keys+1] = k end
if order then
table.sort(keys, function(a,b) return order(t, a, b) end)
else
table.sort(keys)
end
local i = 0
return function()
i = i + 1
if keys[i] then
return keys[i], t[keys[i]]
end
end
end
-- get CSS class from name
local function getCSSClassName(name)
return 'color-template-' .. str_gsub(str_lower(name), '%s+', '-')
end
-- get size of table
local function getTableSize(t)
local count = 0
for _, _ in pairs(t) do
count = count + 1
end
return count
end
-- hash a string (for seed generation)
local function hash(str)
local h = 5381
for i = 1, #str do
h = mth_fmod(h*32 + h + str:byte(i), MOD)
end
return h
end
-- extra constants
local nameList = data.nameList
local cntNames = getTableSize(nameList)
-- MAIN FUNCTIONS
-- checks if name is legal (not empty and exists in database)
function p.checkName(name)
return not ((not name) or (not data.possibleInputs[name]))
end
-- creates element
function p.span(name, display, extra, noLink)
if (not p.checkName(name)) then
return error('Template error! ' .. (name or '<blank or nil>') .. ' not found in database')
end
-- prepare variables
local entry = data.possibleInputs[name]
local classString = 'color-template '
.. getCSSClassName(name)
.. (entry["backgroundClip"] and ' color-template-background-clip' or '')
local text = (conditional(display) and display or name)
extra = (conditional(extra) and extra or '')
-- generate span
local spanString ='<span class="' .. classString .. '">' .. text .. '</span>'
if entry["noLink"] or noLink then
return spanString .. extra
end
local pageName = (conditional(entry["customLink"]) and str_gsub(entry["customLink"], '$1', name))
or name
return '[[' .. pageName .. '|' .. spanString .. ']]' .. extra
end
-- creates element (AF edition)
function p.AFspan(name, display, extra, noLink)
if (not p.checkName(name)) then
return error('Template error! ' .. (name or '<blank or nil>') .. ' not found in database')
end
-- set random seed
local elementHash = hash((name or '') .. (display or '') .. (extra or '') .. (noLink or ''))
local seed = mth_fmod(timeSeed * elementHash, MOD)
mth_randseed(seed)
-- prepare variables
local entry = data.possibleInputs[name]
local text = (conditional(display) and display or name)
-- generate span
local AFname = nameList[mth_rand(cntNames)]
local pageName = (conditional(entry["customLink"]) and str_gsub(entry["customLink"], '$1', name))
or name
local ret = str_gsub(p.span(AFname, text, extra, noLink), "%[%[[%a%A]+|", "[[" .. pageName .. "|")
return ret
end
-- main function
function p.main(frame)
local args = getArgs(frame, {
wrapper = 'Template:Color',
parentOnly = true,
removeBlanks = true,
})
local span = data.isAprilFools and p.AFspan or p.span
if (args["multi"]) then
local ret = ""
local i = 1
while args["name" .. i] do
ret = ret .. span(args["name" .. i], args["display" .. i],
args["extra" .. i], args["noLink" .. i])
i = i + 1
end
return ret
end
return span(args[1], args[2], args[3], args[4])
end
-- TEST SUITE
-- test function (copy of main but can be called from outside template)
function p.test(frame)
local args = getArgs(frame, {
wrapper = 'Template:Color',
parentOnly = true,
removeBlanks = true,
})
local span = data.isAprilFools and p.AFspan or p.span
if (args["multi"]) then
local ret = ""
local i = 1
while args["name" .. i] do
ret = ret .. span(args["name" .. i], args["display" .. i],
args["extra" .. i], args["noLink" .. i])
i = i + 1
end
return ret
end
return span(args[1], args[2], args[3], args[4])
end
-- display table with all possible inputs
function p.docsTable()
local output = { '{| class="wikitable mw-collapsible COLORTEMPLATE_THEME"',
'|+ Possible inputs<br/><small>(sorted in alphabetic order)</small>',
}
local counter = 0
local span = data.isAprilFools and p.AFspan or p.span
for item, entry in spairs(data.possibleInputs) do
if counter == 0 then
output[#output + 1] = '|- COLORTEMPLATE_STYLE'
end
local link = (entry["noLink"] and '\'\'No link\'\'')
or '[[' .. ((conditional(entry["customLink"]) and str_gsub(entry["customLink"], '$1', item)) or item) .. ']]'
output[#output + 1] = '| ' .. p.span(item) .. '<br/><small>\'\'\'Link\'\'\': ' .. link .. '</small><br/><small>\'\'\'CSS class\'\'\': ' .. getCSSClassName(item) .. '</small>'
counter = mth_fmod(counter + 1, 5)
end
output[#output + 1] = '|}'
local outputDark = deepcopy(output)
local outputLight = deepcopy(output)
outputDark = str_gsub(table.concat(outputDark, '\n'), "COLORTEMPLATE_STYLE", ' style="color:white;background-color:' .. darkBackground .. '"')
outputDark = str_gsub(outputDark, "COLORTEMPLATE_THEME", "theme-fandomdesktop-dark")
outputLight = str_gsub(table.concat(outputLight, '\n'), "COLORTEMPLATE_STYLE",' style="color:black;background-color:' .. lightBackground .. '"')
outputLight = str_gsub(outputLight, "COLORTEMPLATE_THEME", "theme-fandomdesktop-light")
mw.log(outputDark)
output = {}
output["centerTabs"] = 1;
output[1] = "Dark theme"
output[2] = outputDark
output[3] = "Light theme"
output[4] = outputLight
return tabber(output)
end
return p