模块:Background
来自Blockland Wiki
更多操作
此模块的文档可以在模块:Background/doc创建
local p = {}
-- 清理参数
local function trim(value)
return mw.text.trim(tostring(value or ""))
end
-- 透明度限制在 0 到 1
local function opacity(value, default)
local number = tonumber(trim(value))
if not number then
return default
end
number = math.max(0, math.min(1, number))
return tostring(number)
end
-- 只接受安全、常见的图片定位写法
local validPositions = {
center = true,
top = true,
bottom = true,
left = true,
right = true,
["center top"] = true,
["center bottom"] = true,
["left center"] = true,
["right center"] = true,
["left top"] = true,
["right top"] = true,
["left bottom"] = true,
["right bottom"] = true,
["center center"] = true
}
local function validPositionToken(token)
if token:match("^%-?%d+%.?%d*%%$") then
return true
end
if token:match("^%-?%d+%.?%d*px$") then
return true
end
return tonumber(token) == 0
end
local function position(value)
value = trim(value)
if validPositions[value] then
return value
end
local x, y = value:match("^(%S+)%s+(%S+)$")
if x and y
and validPositionToken(x)
and validPositionToken(y) then
return x .. " " .. y
end
return "center center"
end
-- 限制颜色格式,避免把任意内容拼入 CSS
local colorNames = {
white = true,
black = true,
transparent = true,
red = true,
blue = true,
green = true,
yellow = true,
gray = true,
grey = true,
navy = true
}
local function safeColor(value)
value = trim(value)
if value:match("^#%x%x%x$") or
value:match("^#%x%x%x%x%x%x$") then
return value
end
local lower = value:lower()
if colorNames[lower] then
return lower
end
return ""
end
-- 解析外部图片 URL 或 Wiki 文件名
local function getImageSource(frame, image)
image = trim(image)
if image == "" then
return ""
end
-- 允许 HTTPS、HTTP 或协议相对的外链
if image:match("^https?://") or image:match("^//") then
return image
end
-- 内部文件:支持 File:、Image:、文件: 前缀
image = image:gsub("^[Ff]ile:", "")
image = image:gsub("^[Ii]mage:", "")
image = image:gsub("^文件:", "")
local ok, result = pcall(function()
return frame:callParserFunction("filepath", image)
end)
if ok and result and result ~= "" then
return result
end
return ""
end
function p.main(frame)
local parent = frame:getParent()
local args = (parent or frame).args
local image = args["图片"] or args["url"] or args[1] or ""
local src = getImageSource(frame, image)
local imageOpacity = opacity(args["透明度"] or args["opacity"], 1)
local imagePosition = position(args["位置"] or args["position"] or "center")
local baseColor = safeColor(args["背景色"] or args["颜色"] or args["color"])
local shadeColor = safeColor(args["遮罩颜色"] or args["shadeColor"])
local shadeOpacity = opacity(args["遮罩透明度"] or args["shade"], 0)
-- 无图片、无背景色、无有效遮罩时不输出
if src == "" and baseColor == "" then
return ""
end
-- 最外层位于负层级;不需要 pointer-events
local rootStyle =
"position:fixed;" ..
"top:0;" ..
"left:0;" ..
"width:100%;" ..
"height:100%;" ..
"z-index:-1;" ..
"overflow:hidden;"
if baseColor ~= "" then
rootStyle = rootStyle .. "background-color:" .. baseColor .. ";"
end
local root = mw.html.create("div")
:addClass("bl-page-bg-layer")
:attr("aria-hidden", "true")
:cssText(rootStyle)
-- 图片层
if src ~= "" then
local img = mw.html.create("img")
:addClass("bl-page-bg-image")
:attr("src", src)
:attr("alt", "")
:cssText(
"position:absolute;" ..
"top:0;" ..
"left:0;" ..
"width:100%;" ..
"height:100%;" ..
"object-fit:cover;" ..
"object-position:" .. imagePosition .. ";" ..
"opacity:" .. imageOpacity .. ";"
)
root:wikitext(tostring(img))
end
-- 可选颜色遮罩
if shadeColor ~= "" and tonumber(shadeOpacity) > 0 then
local shade = mw.html.create("div")
:addClass("bl-page-bg-shade")
:cssText(
"position:absolute;" ..
"top:0;" ..
"left:0;" ..
"width:100%;" ..
"height:100%;" ..
"background-color:" .. shadeColor .. ";" ..
"opacity:" .. shadeOpacity .. ";"
)
root:wikitext(tostring(shade))
end
return tostring(root)
end
return p