Jump to content

Module:颜色组

From CountryHumans中文百科

用于生成模板:颜色组模板:配色


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
Cookies help us deliver our services. By using our services, you agree to our use of cookies.