Module:颜色组
Appearance
local p = {}
-- 颜色转换辅助函数
local function parseHex(hex)
hex = hex:gsub("#", "")
if #hex == 3 then
hex = hex:gsub("(.)", "%1%1")
end
if #hex ~= 6 then return nil end
return {
r = tonumber(hex:sub(1,2), 16),
g = tonumber(hex:sub(3,4), 16),
b = tonumber(hex:sub(5,6), 16)
}
end
local function parseRgb(rgbStr)
local parts = {}
for n in rgbStr:gmatch("%d+") do
table.insert(parts, tonumber(n))
end
if #parts ~= 3 then return nil end
return {
r = parts[1],
g = parts[2],
b = parts[3]
}
end
local function rgbToHex(rgb)
return string.format("#%02X%02X%02X", rgb.r, rgb.g, rgb.b)
end
local function rgbToHsb(rgb)
local r = rgb.r / 255
local g = rgb.g / 255
local b = rgb.b / 255
local max = math.max(r, g, b)
local min = math.min(r, g, b)
local d = max - min
local h, s, v
v = max
if max == 0 then
s = 0
else
s = d / max
end
if max == min then
h = 0
else
if max == r then
h = (g - b) / d
if g < b then h = h + 6 end
elseif max == g then
h = (b - r) / d + 2
elseif max == b then
h = (r - g) / d + 4
end
h = h * 60
if h < 0 then h = h + 360 end
end
return {
h = math.floor(h + 0.5),
s = math.floor(s * 100 + 0.5),
v = math.floor(v * 100 + 0.5)
}
end
-- 参数合并函数
local function mergeArgs(frame)
local templateArgs = frame:getParent().args -- 模板参数
local invokeArgs = frame.args -- invoke直接参数
local args = {}
-- 合并参数(invoke参数优先)
for k, v in pairs(templateArgs) do
args[k] = v
end
for k, v in pairs(invokeArgs) do
if v ~= "" then -- 空值不覆盖模板参数
args[k] = v
end
end
return args
end
local function processRow(i, args)
local sources = {}
local colorData = {}
-- 解析输入参数
if args["hex"..i] then
sources.hex = parseHex(args["hex"..i])
if not sources.hex then return nil end
end
if args["rgb"..i] then
sources.rgb = parseRgb(args["rgb"..i])
if not sources.rgb then return nil end
end
-- 优先使用hex > rgb > hsb的顺序
if sources.hex then
colorData.rgb = sources.hex
colorData.hsb = rgbToHsb(sources.hex)
colorData.hex = args["hex"..i]:upper():gsub("^#", "")
elseif sources.rgb then
colorData.rgb = sources.rgb
colorData.hex = rgbToHex(sources.rgb):upper():gsub("^#", "")
colorData.hsb = rgbToHsb(sources.rgb)
else
return nil -- 无有效颜色数据
end
return {
color = "#"..colorData.hex,
des = args["des"..i] or "",
hex = colorData.hex,
rgb = colorData.rgb,
hsb = colorData.hsb,
pan = args["pan"..i]
}
end
function p.main(frame)
local args = mergeArgs(frame) -- 使用合并后的参数
local rows = {}
-- 确定显示列
local showColumns = {
des = not args.udes,
hex = not args.uhex,
rgb = not args.urgb,
hsb = not args.uhsb,
pan = false -- 初始值
}
-- 确定最大行数和是否显示Pantone列
local maxRow = 0
for k in pairs(args) do
local num = k:match("%d+$")
if num then
num = tonumber(num)
if num > maxRow then maxRow = num end
if k:match("^pan") then showColumns.pan = true end
end
end
-- 生成表头
local headers = {}
if args.colormeaning then
table.insert(headers, "! colspan=\"2\" | 颜色和含义")
else
table.insert(headers, "! 颜色")
if showColumns.des then table.insert(headers, "!! 描述") end
end
if showColumns.hex then table.insert(headers, "!! HEX") end
if showColumns.rgb then table.insert(headers, "!! RGB") end
if showColumns.hsb then table.insert(headers, "!! HSB") end
if showColumns.pan then table.insert(headers, "!! Pantone") end
-- 处理每行数据
for i = 1, maxRow do
local row = processRow(i, args)
if row then
local cells = {
string.format('style="background: %s;" | ', row.color)
}
if showColumns.des then table.insert(cells, row.des) end
if showColumns.hex then table.insert(cells, "#"..row.hex) end
if showColumns.rgb then
table.insert(cells, string.format("%d, %d, %d", row.rgb.r, row.rgb.g, row.rgb.b))
end
if showColumns.hsb then
table.insert(cells, string.format("%d°, %d%%, %d%%", row.hsb.h, row.hsb.s, row.hsb.v))
end
if showColumns.pan then table.insert(cells, row.pan or "") end
table.insert(rows, "|-\n| "..table.concat(cells, " || "))
end
end
local tableClass = ""
if args.wikitable ~= "false" then -- 默认显示wikitable样式
tableClass = 'class="wikitable"'
end
return string.format(
"{| %s\n%s\n%s\n|}",
tableClass,
table.concat(headers, " "),
table.concat(rows, "\n")
)
end
return p