Module:SocialMedia: Difference between revisions
No edit summary Tag: Reverted |
// via Wikitext Extension for VSCode |
||
| (35 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
-- Module:SocialMedia | |||
-- Reusable social media component meant to be called from other modules | |||
-- | -- ############################################################### | ||
-- Currently supported platforms are: | |||
-- (UPDATE THE LIST BETWEEN THE HOOK EMOJIS AS PLATFORMS GET ADDED OR REMOVED) | |||
-- 🪝Facebook, Github, Instagram, LinkedIn, Telegram, Threads, TikTok, X/Twitter, Youtube🪝 | |||
-- ############################################################### | |||
local sf = {} | |||
local TemplateHelpers = require('Module:TemplateHelpers') | |||
-- This section defines the social platforms; can be added or deleted without consequence | |||
-- param = handle for the platform; for "x", we also accept "twitter" for legacy purposes | |||
-- icon = wiki file for the icon | |||
-- prefix = URL prefix | |||
-- label = used for alt text/screen readers | |||
local socialPlatforms = { | local socialPlatforms = { | ||
{ | { | ||
param | param = "facebook", | ||
icon = "File:SocialFacebookIcon.svg", | |||
prefix | prefix = "https://www.facebook.com/", | ||
label | label = "Facebook" | ||
}, | }, | ||
{ | { | ||
param | param = "instagram", | ||
icon = "File:SocialInstagramIcon.svg", | |||
prefix | prefix = "https://www.instagram.com/", | ||
label | label = "Instagram" | ||
}, | }, | ||
{ | { | ||
param | param = "linkedin", | ||
icon = "File:SocialLinkedInIcon.svg", | |||
prefix | prefix = "https://www.linkedin.com/in/", | ||
label | label = "LinkedIn" | ||
}, | }, | ||
{ | { | ||
param | param = "telegram", | ||
icon = "File:SocialTelegramIcon.svg", | |||
prefix | prefix = "https://t.me/", | ||
label | label = "Telegram" | ||
}, | }, | ||
{ | { | ||
param | param = "threads", | ||
icon = "File:SocialThreadsIcon.svg", | |||
prefix | prefix = "https://www.threads.net/@", | ||
label | label = "Threads" | ||
}, | }, | ||
{ | { | ||
param | param = "tiktok", | ||
icon = "File:SocialTikTokIcon.svg", | |||
prefix | prefix = "https://www.tiktok.com/@", | ||
label | label = "TikTok" | ||
}, | }, | ||
{ | { | ||
param | param = { "x", "twitter" }, | ||
icon = "File:SocialXIcon.svg", | |||
prefix | prefix = "https://x.com/", | ||
label | label = "X (Twitter)" | ||
}, | }, | ||
{ | { | ||
param | param = "youtube", | ||
icon = "File:SocialYouTubeIcon.svg", | |||
prefix | prefix = "https://www.youtube.com/@", | ||
label = " | label = "YouTube" | ||
}, | |||
{ | |||
param = "github", | |||
icon = "File:SocialGithub.svg", | |||
prefix = "https://github.com/", | |||
label = "Github" | |||
}, | }, | ||
} | } | ||
-- | -- Helper function to check if text is a full URL | ||
local function isFullUrl(text) | |||
return text and text:match("^https?://") ~= nil | |||
end | |||
-- Platform-specific normalizers table | |||
local normalizers = { | |||
linkedin = function(handle) | |||
-- If it's not a URL, return as is | |||
if not isFullUrl(handle) then return handle end | |||
-- Extract the path from the URL (case insensitive for linkedin.com) | |||
local path = handle:lower():match("linkedin%.com/(.+)") | |||
if not path then return handle end | |||
-- Handle /pub/ format | |||
if path:match("^pub/") then | |||
-- Extract the name part (first segment after /pub/) | |||
local name = path:match("^pub/([^/]+)") | |||
if name then return name end | |||
end | |||
-- Handle /in/ format - just extract the username | |||
if path:match("^in/") then | |||
return path:match("^in/([^/]+)") | |||
end | |||
-- If we can't parse it, return the original | |||
return handle | |||
end | |||
-- Add other platform normalizers as needed | |||
} | |||
-- Helper function to normalize handles based on platform | |||
local function normalizeHandle(platform, handle) | |||
-- Skip normalization if handle is nil or empty | |||
if not handle or handle == "" then return handle end | |||
-- Get the platform param (use first one if it's a table) | |||
local platformParam = platform.param | |||
if type(platformParam) == "table" then | |||
platformParam = platformParam[1] | |||
end | |||
-- If platform has a specific normalizer, use it | |||
if normalizers[platformParam] then | |||
return normalizers[platformParam](handle) | |||
end | |||
-- Default behavior: if it's a full URL, try to extract the handle | |||
if isFullUrl(handle) then | |||
-- Try to extract the handle from the URL based on the platform's prefix | |||
local prefix = platform.prefix:gsub("([%%%-%.])", "%%%1") -- Escape special pattern chars | |||
return handle:match(prefix .. "(.+)") or handle | |||
end | |||
-- If not a URL, return as is | |||
return handle | |||
end | |||
-- (Non-generalizable) Helper to find the first non-empty user handle from a param or table of params | |||
local function getUserHandle(args, param) | local function getUserHandle(args, param) | ||
local key, handle | |||
if type(param) == "string" then | if type(param) == "string" then | ||
key, handle = TemplateHelpers.getFieldValue(args, { key = param }) | |||
else | else | ||
key, handle = TemplateHelpers.getFieldValue(args, { keys = param }) | |||
end | |||
if handle and handle ~= "" then | |||
return mw.text.trim(handle) | |||
end | end | ||
return nil | return nil | ||
end | end | ||
-- | -- Build a clickable icon link (24px) with alt text for accessibility: [[File:Name.svg|24px|class=...|alt=...|link=URL]] | ||
function | local function buildIconLink(iconFile, altText, url) | ||
-- Add the reusable filter class to the image attributes | |||
return string.format("[[%s|24px|alt=%s|link=%s|class=filter-icon-green]]", iconFile, altText, url) | |||
end | |||
-- Build a single table row with colspan=2, containing a flex container for icons | |||
local function buildSocialRow(icons) | |||
local iconMarkup = table.concat({ | |||
'<div class="social-icons link-open-external">', | |||
table.concat(icons, ""), | |||
'</div>' | |||
}, "\n") | |||
return table.concat({ | |||
"|-", | |||
'| colspan="2" |', | |||
iconMarkup | |||
}, "\n") | |||
end | |||
-- Main render function, takes a table of arguments (handles), returns wiki markup with social icons | |||
function sf.render(args) | |||
-- Early return if args is empty or nil | |||
if not args or next(args) == nil then | |||
return "" | |||
end | |||
-- Pre-allocate icons table based on maximum possible size (number of platforms) | |||
local icons = {} | |||
icons[#socialPlatforms] = nil -- Pre-allocate table to avoid reallocation | |||
local iconCount = 0 | |||
for _, platform in ipairs(socialPlatforms) do | for _, platform in ipairs(socialPlatforms) do | ||
local handle = getUserHandle(args, platform.param) | local handle = getUserHandle(args, platform.param) | ||
if handle and handle ~= "" then | if handle and handle ~= "" then | ||
local | -- Normalize the handle based on platform | ||
local | local normalizedHandle = normalizeHandle(platform, handle) | ||
: | |||
: | -- Check for special FULLURL: prefix from Python transformation | ||
local url | |||
if handle:match("^FULLURL:") then | |||
-- Extract the URL part after the FULLURL: prefix | |||
a | url = handle:gsub("^FULLURL:", "") | ||
-- If the handle is already a full URL, use it directly | |||
elseif isFullUrl(handle) and not isFullUrl(normalizedHandle) then | |||
-- We have a full URL that was successfully normalized to a handle | |||
url = platform.prefix .. normalizedHandle | |||
elseif isFullUrl(handle) then | |||
-- We have a full URL that couldn't be normalized, use it directly | |||
url = handle | |||
else | |||
-- We have a regular handle, use the standard approach | |||
url = platform.prefix .. handle | |||
end | |||
local iconLink = buildIconLink(platform.icon, platform.label, url) | |||
iconCount = iconCount + 1 | |||
icons[iconCount] = iconLink -- Direct index assignment is faster than table.insert | |||
end | end | ||
end | end | ||
if | -- If no handles were provided, return nothing | ||
if #icons == 0 then | |||
return "" | return "" | ||
end | end | ||
-- Return a row with a flex container for icons | |||
return buildSocialRow(icons) | |||
) | |||
end | end | ||
return | return sf | ||