User:TheUnit 72/backups/Universal clickable button/Module
local p = {}
local colorMap = {
red = "#d33333",
["deep red"] = "#8b0000",
["light red"] = "#ff7f7f",
orange = "#ff8c00",
["light orange"] = "#ffd1a3",
yellow = "#ffeb3b",
gold = "#d4af37",
["deep yellow"] = "#d4af37",
["light yellow"] = "#fff59d",
green = "#4caf50",
["deep green"] = "#1b5e20",
["light green"] = "#88e788",
turquoise = "#40e0d0",
turqoise = "#40e0d0",
blue = "#3366cc",
["deep blue"] = "#0d47a1",
["light blue"] = "#90caf9",
purple = "#7953a9",
["deep purple"] = "#4a148c",
["light purple"] = "#ce93d8",
pink = "#e91e63",
magenta = "#c2185b",
white = "#ffffff",
black = "#000000",
grey = "#a2a9b1",
gray = "#a2a9b1",
silver = "#c8ccd1",
["light grey"] = "#f8f9fa",
["deep grey"] = "#54595d",
["charcoal"] = "#36454f",
beige = "#f8eaba",
["deep beige"] = "#c0c090",
["progressive"] = "#3366cc",
["destructive"] = "#bf3c2c",
["constructive"] = "#008000",
["effective"] = "#d4af37",
["neutral"] = "#f8f9fa"
}
local DEFAULT_BG = "#f8f9fa"
local DEFAULT_FG = "#000000"
local DEFAULT_BORDER = "#a2a9b1"
local function normalizeKey(str)
if not str then return nil end
str = tostring(str):lower()
:gsub("^%s+", "")
:gsub("%s+$", "")
:gsub("%s+", " ")
str = str:gsub("^dark%s+", "deep ")
return str
end
local function resolveColor(input)
if not input then return nil end
local key = normalizeKey(input)
if colorMap[key] then return colorMap[key] end
if key:match("^#%x%x%x$") or key:match("^#%x%x%x%x%x%x$") then return key end
if key:match("^%x%x%x$") or key:match("^%x%x%x%x%x%x$") then return "#" .. key end
return nil
end
local function expandHex(hex)
hex = hex:gsub("#", "")
if #hex == 3 then
return hex:sub(1,1) .. hex:sub(1,1)
.. hex:sub(2,2) .. hex:sub(2,2)
.. hex:sub(3,3) .. hex:sub(3,3)
elseif #hex == 6 then
return hex
end
return "808080"
end
local function getTextColor(bg)
local hex = expandHex(bg)
local r = tonumber(hex:sub(1,2), 16)
local g = tonumber(hex:sub(3,4), 16)
local b = tonumber(hex:sub(5,6), 16)
local lum = (0.299 * r + 0.587 * g + 0.114 * b)
return (lum > 186) and "#000" or "#fff"
end
local function pickBaseColor(args)
local raw = args.color or args.colour or args[3]
local resolved = resolveColor(raw)
if resolved then
local border
if resolved == "#f8f9fa" then
border = "#a2a9b1"
elseif resolved == "#f8eaba" then
border = "#c0c090"
else
border = resolved
end
return resolved, getTextColor(resolved), border
end
return DEFAULT_BG, DEFAULT_FG, DEFAULT_BORDER
end
local function isValidUrl(url)
if not url or url == "" then return false end
return url:match("^https?://") ~= nil
or url:match("^//") ~= nil
end
local function adjustColor(hex, factor)
local h = expandHex(hex)
local r = tonumber(h:sub(1,2), 16)
local g = tonumber(h:sub(3,4), 16)
local b = tonumber(h:sub(5,6), 16)
r = math.min(255, math.max(0, math.floor(r * factor)))
g = math.min(255, math.max(0, math.floor(g * factor)))
b = math.min(255, math.max(0, math.floor(b * factor)))
return string.format("#%02x%02x%02x", r, g, b)
end
local function getHoverColor(bg)
local hex = expandHex(bg)
local r = tonumber(hex:sub(1,2), 16)
local g = tonumber(hex:sub(3,4), 16)
local b = tonumber(hex:sub(5,6), 16)
local lum = (0.299 * r + 0.587 * g + 0.114 * b)
if bg == "#000000" or bg == "#000" then
return adjustColor(bg, 1.15)
elseif lum >= 220 and lum < 255 then
-- Near-white: lighten slightly
return adjustColor(bg, 1.08)
else
return adjustColor(bg, 0.82)
end
end
local function buildDisplay(args, bg, fg, border)
local span = mw.html.create("span")
span
:addClass("ucb-button")
:css({
["background-color"] = bg,
["color"] = fg,
["border-color"] = border,
["vertical-align"] = "middle"
})
local userClass = args.class and tostring(args.class):lower():gsub("^%s+", ""):gsub("%s+$", "") or nil
if userClass and userClass ~= "" and userClass ~= "mw-ui-button" then
span:addClass(userClass)
end
if args.tooltip and tostring(args.tooltip) ~= "" then
span:attr("title", tostring(args.tooltip))
end
if args.style then
span:cssText(args.style)
end
local text = args.text or args[2] or args[1] or ""
if args.icon and tostring(args.icon) ~= "" then
local filename = tostring(args.icon):gsub("^[Ff]ile:", "")
span:wikitext(string.format('[[File:%s|16px|link=]] ', filename))
end
span:wikitext(text)
return tostring(span)
end
function p.main(frame)
local args = frame:getParent().args
local styleLink = frame:extensionTag("templatestyles", "", {
src = "Module:Universal clickable button/styles.css"
})
local link = args.url or args[1] or args.link
if not link or tostring(link) == "" then
return ""
end
local isUrl = args.url ~= nil and tostring(args.url) ~= ""
if isUrl and not isValidUrl(tostring(args.url)) then
return '<span class="error">Universal Clickable Button: invalid or unsafe URL.</span>'
end
local bg, fg, border = pickBaseColor(args)
local useHover = not isUrl
and args.hover and tostring(args.hover):lower():gsub("^%s+", ""):gsub("%s+$", "") == "yes"
if not isUrl then
local currentTitle = mw.title.getCurrentTitle()
local targetTitle = mw.title.new(tostring(link))
if targetTitle and currentTitle
and targetTitle.prefixedText == currentTitle.prefixedText then
return styleLink .. buildDisplay(args, bg, fg, border)
end
end
local display = buildDisplay(args, bg, fg, border)
local linkHtml
if useHover then
linkHtml = string.format('[[%s|%s]]', tostring(link), display)
return styleLink .. string.format('<span class="plainlinks">%s</span>', linkHtml)
end
local href
if isUrl then
href = tostring(args.url)
else
local titleObj = mw.title.new(tostring(link))
href = titleObj and titleObj:fullUrl() or tostring(link)
end
linkHtml = string.format('[%s %s]', href, display)
return styleLink .. string.format('<span class="plainlinks">%s</span>', linkHtml)
end
return p
Content Disclaimer
Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.
- The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
- There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
- It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
- Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
- Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.