跳转到内容
打开/关闭菜单
  • 5 条目
  • 6 文件
  • 13 用户
  • 665 编辑
久远澪Wiki
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

此模块的文档可以在Module:ColorRGB/doc创建

-- Module:ColorRGB
-- 主题色 RGB 分量计算器:从 MediaWiki:Common.css 载入主题色 hex,计算 r/g/b 分量,
-- 输出 CSS 变量声明。颜色单一来源 = common.css 的 --color-* 变量(本模块不重复定义,
-- 改色只需改 common.css)。读取 common.css 失败时回退到内置默认色表。
-- 用法:
--   {{#invoke:ColorRGB|cardVars}} → 卡片所需两套分量(*-light/*-night),模板内联到 style
--   {{#invoke:ColorRGB|light}} / {{#invoke:ColorRGB|night}} → 输出整套分量
--   {{#invoke:ColorRGB|rgb|theme-soft}} → 输出单个颜色分量
local p = {}

-- 内置默认色表(仅当 common.css 读取失败时回退;正常以 common.css 为准)
local fallbackLight = {
	['theme-soft']     = '#F9FCF4',
	['theme']          = '#F1F8E6',
	['theme-deep']     = '#E0EFD0',
	['primary']        = '#8FBC8F',
	['primary-deep']   = '#2E6B45',
	['accent']         = '#E8B96A',
	['accent-deep']    = '#8A5A1E',
	['accent-bg']      = '#FFF8EF',
	['accent-bg-soft'] = '#FDF2E3',
}

-- 深色默认色表(回退用)
local fallbackNight = {
	['theme-soft']     = '#232D1D',
	['theme']          = '#1D2618',
	['theme-deep']     = '#303D2A',
	['primary']        = '#7FAA85',
	['primary-deep']   = '#A9CFAE',
	['accent']         = '#E0A85C',
	['accent-deep']    = '#F0C48A',
	['accent-bg']      = '#2E2719',
	['accent-bg-soft'] = '#382D1C',
}

-- 需要的颜色名(对应 common.css 的 --color-<name>)
local colorNames = {
	'theme-soft', 'theme', 'theme-deep',
	'primary', 'primary-deep',
	'accent', 'accent-deep', 'accent-bg', 'accent-bg-soft',
}

-- 从 MediaWiki:Common.css 读取内容(Scribunto 依赖追踪会自动使其在编辑后失效)
local function getCss()
	local title = mw.title.new('MediaWiki:Common.css')
	return (title and title.getContent and title:getContent()) or ''
end

-- 提取选择器后第一个 {...} 块内的 CSS 变量(--name: value;)
local function extractVars(css, selector)
	local vars = {}
	local start = css:find(selector, 1, true)
	if not start then return vars end
	local open = css:find('{', start)
	if not open then return vars end
	local close = css:find('}', open)
	if not close then return vars end
	for name, value in css:sub(open + 1, close - 1):gmatch('%-%-([%w-]+)%s*:%s*([^;]+);') do
		vars[name] = value:gsub('^%s+', ''):gsub('%s+$', '')
	end
	return vars
end

-- 从 common.css 载入浅色/深色 palette(缺失/非法 hex 时回退内置)
local function getPalette(css, selector, fallback)
	local vars = extractVars(css, selector)
	local pal = {}
	for _, name in ipairs(colorNames) do
		local v = vars['color-' .. name]
		if v and v:match('^#%x+$') then
			pal[name] = v
		else
			pal[name] = fallback[name]
		end
	end
	return pal
end

-- 模块级缓存(同一次页面解析内多次 invoke 复用)
local lightPal, nightPal
local function palettes()
	if not lightPal then
		local css = getCss()
		lightPal = getPalette(css, ':root', fallbackLight)
		nightPal = getPalette(css, 'html.skin-theme-clientpref-night', fallbackNight)
	end
	return lightPal, nightPal
end

-- hex → r,g,b(支持 #RGB 与 #RRGGBB)
local function hexToRgb(hex)
	hex = (hex or ''):gsub('#', ''):lower()
	if #hex == 3 then
		hex = hex:gsub('.', function(c) return c .. c end)
	end
	if #hex ~= 6 then
		return 0, 0, 0
	end
	return tonumber(hex:sub(1, 2), 16),
		tonumber(hex:sub(3, 4), 16),
		tonumber(hex:sub(5, 6), 16)
end

-- 单个颜色 → 三个分量变量
local function single(name, hex)
	local r, g, b = hexToRgb(hex)
	return string.format(
		'--color-%s-r: %d; --color-%s-g: %d; --color-%s-b: %d;',
		name, r, name, g, name, b
	)
end

-- 按名取 hex(先浅色后深色)
local function hexOf(name)
	local l, n = palettes()
	return l[name] or n[name]
end

-- 输出一个颜色的分量(按名或按 hex)
function p.rgb(frame)
	local args = frame.args
	local name = args[1] or args.name
	local hex = args[2] or args.hex or hexOf(name)
	if not name then
		return ''
	end
	return single(name, hex)
end

-- 输出浅色全部颜色分量(供 :root)
function p.light(frame)
	local l = palettes()
	local out = {}
	for name, hex in pairs(l) do
		table.insert(out, single(name, hex))
	end
	return table.concat(out, '\n')
end

-- 输出深色全部颜色分量(供深色块)
function p.night(frame)
	local n = palettes()
	local out = {}
	for name, hex in pairs(n) do
		table.insert(out, single(name, hex))
	end
	return table.concat(out, '\n')
end

-- 输出卡片所需全部颜色分量(浅色 + 深色两套,供模板内联到 style:
-- 浅色用 *-light,深色用 *-night,styles.css 分别引用)
function p.cardVars(frame)
	local l, n = palettes()
	local out = {}
	for name, hex in pairs(l) do
		local r, g, b = hexToRgb(hex)
		table.insert(out, string.format(
			'--color-%s-r-light:%d;--color-%s-g-light:%d;--color-%s-b-light:%d;',
			name, r, name, g, name, b
		))
	end
	for name, hex in pairs(n) do
		local r, g, b = hexToRgb(hex)
		table.insert(out, string.format(
			'--color-%s-r-night:%d;--color-%s-g-night:%d;--color-%s-b-night:%d;',
			name, r, name, g, name, b
		))
	end
	return table.concat(out)
end

return p