Module:SocialMedia: Difference between revisions

No edit summary
Tag: Manual revert
No edit summary
Tag: Reverted
Line 1: Line 1:
-- Reusable social media component meant to be called from other modules
local m = {}


local sf = {}
-- 1) Inline SVG Definitions (hand-copy your actual SVG strings)
local svgIcons = {
    facebook = [==[
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
  <path d="M16,2c-7.732,0-14,6.268-14,14,0,6.566,4.52,12.075,10.618,13.588v-9.31h-2.887v-4.278h2.887v-1.843
  c0-4.765,2.156-6.974,6.835-6.974,.887,0,2.417,.174,3.043,.348v3.878c-.33-.035-.904-.052-1.617-.052-2.296,0-3.183,.87-3.183,3.13
  v1.513h4.573l-.786,4.278h-3.787v9.619c6.932-.837,12.304-6.74,12.304-13.897,0-7.732-6.268-14-14-14Z"
  style="fill: #1877F2;" />
</svg>
]==],


-- This section defines the social platforms; can be added or deleted without consequence
    instagram = [==[
-- param = handle for the platform; for "x", we also accept "twitter" for legacy purposes
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M10.202,2.098c-1.49,.07-2.507,.308-3.396,.657-.92,.359-1.7,.84-2.477,1.619-.776,.779-1.254,1.56-1.61,2.481-.345,.891-.578,1.909-.644,3.4-.066,1.49-.08,1.97-.073,5.771s.024,4.278,.096,5.772c.071,1.489,.308,2.506,.657,3.396,.359,.92,.84,1.7,1.619,2.477,.779,.776,1.559,1.253,2.483,1.61,.89,.344,1.909,.579,3.399,.644,1.49,.065,1.97,.08,5.771,.073,3.801-.007,4.279-.024,5.773-.095s2.505-.309,3.395-.657c.92-.36,1.701-.84,2.477-1.62s1.254-1.561,1.609-2.483c.345-.89,.579-1.909,.644-3.398,.065-1.494,.081-1.971,.073-5.773s-.024-4.278-.095-5.771-.308-2.507-.657-3.397c-.36-.92-.84-1.7-1.619-2.477s-1.561-1.254-2.483-1.609c-.891-.345-1.909-.58-3.399-.644s-1.97-.081-5.772-.074-4.278,.024-5.771,.096m.164,25.309c-1.365-.059-2.106-.286-2.6-.476-.654-.252-1.12-.557-1.612-1.044s-.795-.955-1.05-1.608c-.192-.494-.423-1.234-.487-2.599-.069-1.475-.084-1.918-.092-5.656s.006-4.18,.071-5.656c.058-1.364,.286-2.106,.476-2.6,.252-.655,.556-1.12,1.044-1.612s.955-.795,1.608-1.05c.493-.193,1.234-.422,2.598-.487,1.476-.07,1.919-.084,5.656-.092,3.737-.008,4.181,.006,5.658,.071,1.364,.059,2.106,.285,2.599,.476,.654,.252,1.12,.555,1.612,1.044s.795,.954,1.051,1.609c.193,.492,.422,1.232,.486,2.597,.07,1.476,.086,1.919,.093,5.656,.007,3.737-.006,4.181-.071,5.656-.06,1.365-.286,2.106-.476,2.601-.252,.654-.556,1.12-1.045,1.612s-.955,.795-1.608,1.05c-.493,.192-1.234,.422-2.597,.487-1.476,.069-1.919,.084-5.657,.092s-4.18-.007-5.656-.071M21.779,8.517c.002,.928,.755,1.679,1.683,1.677s1.679-.755,1.677-1.683c-.002-.928-.755-1.679-1.683-1.677,0,0,0,0,0,0-.928,.002-1.678,.755-1.677,1.683m-12.967,7.496c.008,3.97,3.232,7.182,7.202,7.174s7.183-3.232,7.176-7.202c-.008-3.97-3.233-7.183-7.203-7.175s-7.182,3.233-7.174,7.203m2.522-.005c-.005-2.577,2.08-4.671,4.658-4.676,2.577-.005,4.671,2.08,4.676,4.658,.005,2.577-2.08,4.671-4.658,4.676-2.577,.005-4.671-2.079-4.676-4.656h0"></path></svg>
-- icon  = wiki file for the icon
]==],
-- prefix = URL prefix
 
-- label  = used for alt text/screen readers
    linkedin = [==[
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M26.111,3H5.889c-1.595,0-2.889,1.293-2.889,2.889V26.111c0,1.595,1.293,2.889,2.889,2.889H26.111c1.595,0,2.889-1.293,2.889-2.889V5.889c0-1.595-1.293-2.889-2.889-2.889ZM10.861,25.389h-3.877V12.87h3.877v12.519Zm-1.957-14.158c-1.267,0-2.293-1.034-2.293-2.31s1.026-2.31,2.293-2.31,2.292,1.034,2.292,2.31-1.026,2.31-2.292,2.31Zm16.485,14.158h-3.858v-6.571c0-1.802-.685-2.809-2.111-2.809-1.551,0-2.362,1.048-2.362,2.809v6.571h-3.718V12.87h3.718v1.686s1.118-2.069,3.775-2.069,4.556,1.621,4.556,4.975v7.926Z" fill-rule="evenodd"></path></svg>
]==],
 
    telegram = [==[
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M16,2c-7.732,0-14,6.268-14,14s6.268,14,14,14,14-6.268,14-14S23.732,2,16,2Zm6.489,9.521c-.211,2.214-1.122,7.586-1.586,10.065-.196,1.049-.583,1.401-.957,1.435-.813,.075-1.43-.537-2.218-1.053-1.232-.808-1.928-1.311-3.124-2.099-1.382-.911-.486-1.412,.302-2.23,.206-.214,3.788-3.472,3.858-3.768,.009-.037,.017-.175-.065-.248-.082-.073-.203-.048-.29-.028-.124,.028-2.092,1.329-5.905,3.903-.559,.384-1.065,.571-1.518,.561-.5-.011-1.461-.283-2.176-.515-.877-.285-1.574-.436-1.513-.92,.032-.252,.379-.51,1.042-.773,4.081-1.778,6.803-2.95,8.164-3.517,3.888-1.617,4.696-1.898,5.222-1.907,.116-.002,.375,.027,.543,.163,.142,.115,.181,.27,.199,.379,.019,.109,.042,.357,.023,.551Z" fill-rule="evenodd"></path></svg>
]==],
 
    threads = [==[
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M22.7,14.977c-.121-.058-.243-.113-.367-.167-.216-3.982-2.392-6.262-6.046-6.285-.017,0-.033,0-.05,0-2.185,0-4.003,.933-5.122,2.63l2.009,1.378c.836-1.268,2.147-1.538,3.113-1.538,.011,0,.022,0,.033,0,1.203,.008,2.111,.357,2.698,1.04,.428,.497,.714,1.183,.855,2.049-1.067-.181-2.22-.237-3.453-.166-3.474,.2-5.707,2.226-5.557,5.041,.076,1.428,.788,2.656,2.003,3.459,1.028,.678,2.351,1.01,3.727,.935,1.817-.1,3.242-.793,4.236-2.06,.755-.963,1.233-2.21,1.444-3.781,.866,.523,1.507,1.21,1.862,2.037,.603,1.405,.638,3.714-1.246,5.596-1.651,1.649-3.635,2.363-6.634,2.385-3.326-.025-5.842-1.091-7.478-3.171-1.532-1.947-2.323-4.759-2.353-8.359,.03-3.599,.821-6.412,2.353-8.359,1.636-2.079,4.151-3.146,7.478-3.171,3.35,.025,5.91,1.097,7.608,3.186,.833,1.025,1.461,2.313,1.874,3.815l2.355-.628c-.502-1.849-1.291-3.443-2.365-4.764-2.177-2.679-5.361-4.051-9.464-4.08h-.016c-4.094,.028-7.243,1.406-9.358,4.095-1.882,2.393-2.853,5.722-2.886,9.895v.01s0,.01,0,.01c.033,4.173,1.004,7.503,2.886,9.895,2.115,2.689,5.264,4.067,9.358,4.095h.016c3.64-.025,6.206-.978,8.32-3.09,2.765-2.763,2.682-6.226,1.771-8.352-.654-1.525-1.901-2.763-3.605-3.581Zm-6.285,5.909c-1.522,.086-3.104-.598-3.182-2.061-.058-1.085,.772-2.296,3.276-2.441,.287-.017,.568-.025,.844-.025,.909,0,1.76,.088,2.533,.257-.288,3.602-1.98,4.187-3.471,4.269Z"></path></svg>
]==],
 
    tiktok = [==[
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M24.562,7.613c-1.508-.983-2.597-2.557-2.936-4.391-.073-.396-.114-.804-.114-1.221h-4.814l-.008,19.292c-.081,2.16-1.859,3.894-4.039,3.894-.677,0-1.315-.169-1.877-.465-1.288-.678-2.169-2.028-2.169-3.582,0-2.231,1.815-4.047,4.046-4.047,.417,0,.816,.069,1.194,.187v-4.914c-.391-.053-.788-.087-1.194-.087-4.886,0-8.86,3.975-8.86,8.86,0,2.998,1.498,5.65,3.783,7.254,1.439,1.01,3.19,1.606,5.078,1.606,4.886,0,8.86-3.975,8.86-8.86V11.357c1.888,1.355,4.201,2.154,6.697,2.154v-4.814c-1.345,0-2.597-.4-3.647-1.085Z"></path></svg>
]==],
 
    twitter = [==[
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M18.42,14.009L27.891,3h-2.244l-8.224,9.559L10.855,3H3.28l9.932,14.455L3.28,29h2.244l8.684-10.095,6.936,10.095h7.576l-10.301-14.991h0Zm-3.074,3.573l-1.006-1.439L6.333,4.69h3.447l6.462,9.243,1.006,1.439,8.4,12.015h-3.447l-6.854-9.804h0Z"></path></svg>
]==],
 
    youtube = [==[
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path d="M31.331,8.248c-.368-1.386-1.452-2.477-2.829-2.848-2.496-.673-12.502-.673-12.502-.673,0,0-10.007,0-12.502,.673-1.377,.37-2.461,1.462-2.829,2.848-.669,2.512-.669,7.752-.669,7.752,0,0,0,5.241,.669,7.752,.368,1.386,1.452,2.477,2.829,2.847,2.496,.673,12.502,.673,12.502,.673,0,0,10.007,0,12.502-.673,1.377-.37,2.461-1.462,2.829-2.847,.669-2.512,.669-7.752,.669-7.752,0,0,0-5.24-.669-7.752ZM12.727,20.758V11.242l8.364,4.758-8.364,4.758Z"></path></svg>
]==],
}
 
-- 2) Social platform definitions
local socialPlatforms = {
local socialPlatforms = {
     {
     {
         param = "facebook",
         param     = "facebook",
         icon  = "File:SocialFacebookIcon.svg",
         inlineKey = "facebook",
         prefix = "https://www.facebook.com/",
         prefix   = "https://www.facebook.com/",
         label = "Facebook"
         label     = "Facebook"
     },
     },
     {
     {
         param = "instagram",
         param     = "instagram",
         icon  = "File:SocialInstagramIcon.svg",
         inlineKey = "instagram",
         prefix = "https://www.instagram.com/",
         prefix   = "https://www.instagram.com/",
         label = "Instagram"
         label     = "Instagram"
     },
     },
     {
     {
         param = "linkedin",
         param     = "linkedin",
         icon  = "File:SocialLinkedInIcon.svg",
         inlineKey = "linkedin",
         prefix = "https://www.linkedin.com/",
         prefix   = "https://www.linkedin.com/",
         label = "LinkedIn"
         label     = "LinkedIn"
     },
     },
     {
     {
         param = "telegram",
         param     = "telegram",
         icon  = "File:SocialTelegramIcon.svg",
         inlineKey = "telegram",
         prefix = "https://t.me/",
         prefix   = "https://t.me/",
         label = "Telegram"
         label     = "Telegram"
     },
     },
     {
     {
         param = "threads",
         param     = "threads",
         icon  = "File:SocialThreadsIcon.svg",
         inlineKey = "threads",
         prefix = "https://www.threads.net/",
         prefix   = "https://www.threads.net/",
         label = "Threads"
         label     = "Threads"
     },
     },
     {
     {
         param = "tiktok",
         param     = "tiktok",
         icon  = "File:SocialTikTokIcon.svg",
         inlineKey = "tiktok",
         prefix = "https://www.tiktok.com/",
         prefix   = "https://www.tiktok.com/",
         label = "TikTok"
         label     = "TikTok"
     },
     },
     {
     {
        -- Multiple aliases: the editor can supply "x" or "twitter"
         param     = { "x", "twitter" },
         param = { "x", "twitter" },
         inlineKey = "twitter",
         icon  = "File:SocialXIcon.svg",
         prefix   = "https://x.com/",
         prefix = "https://x.com/",
         label     = "X (Twitter)"
         label = "X (Twitter)"
     },
     },
     {
     {
         param = "youtube",
         param     = "youtube",
         icon  = "File:SocialYouTubeIcon.svg",
         inlineKey = "youtube",
         prefix = "https://www.youtube.com/",
         prefix   = "https://www.youtube.com/",
         label = "YouTube"
         label     = "YouTube"
     },
     },
}
}


--------------------------------------------------------------------------------
-- 3) Helper: Retrieve the user's handle for a given platform key (or alias)
-- Helper to find the first non-empty user handle from a param or table of params
-- If param is a single string (e.g. "facebook"), we do args["facebook"]
-- If it's a table like { "x", "twitter" }, we check args["x"] then args["twitter"]
--------------------------------------------------------------------------------
local function getUserHandle(args, param)
local function getUserHandle(args, param)
     if type(param) == "string" then
     if type(param) == "string" then
Line 75: Line 104:
             end
             end
         end
         end
        return nil
     end
     end
    return nil
end
end


-- Build a clickable icon link (24px) with alt text for accessibility:
-- 4) Build an icon link with inline SVG and inline styles for proper layout.
-- [[File:Something.svg|24px|alt=ALT_TEXT|link=URL]]
local function buildIcon(platform, handle)
local function buildIconLink(iconFile, altText, url)
    local svgCode = svgIcons[platform.inlineKey] or ""
     return string.format("[[%s|24px|alt=%s|link=%s]]", iconFile, altText, url)
    local url    = platform.prefix .. handle
    local altText = platform.label
    -- Inline CSS here ensures the icon displays as an inline-block with margin.
     return string.format(
        '<a href="%s" title="%s" style="display:inline-block; margin-right:0.5em; text-decoration:none;">%s</a>',
        url, altText, svgCode
    )
end
end


-- Build a single table row with colspan=2, containing a flex container for icons
-- 5) Build a table row with colspan=2 containing a flex container of icons.
local function buildSocialRow(icons)
local function buildSocialRow(icons)
     local iconMarkup = table.concat({
     local container = table.concat({
         '<div style="display: flex; flex-wrap: wrap; gap: 0.5em; margin-top: 0.2em;">',
        -- Inline flex container to control layout without relying on external CSS.
         '<div style="display:flex; flex-wrap:wrap; gap:0.5em; align-items:center; margin-top:0.2em;">',
             table.concat(icons, ""),
             table.concat(icons, ""),
         '</div>'
         '</div>'
     }, "\n")
     })
 
     return table.concat({
     return table.concat({
         "|-",
         "|-",
         '| colspan="2" | ' .. iconMarkup
         '| colspan="2" | ' .. container
     }, "\n")
     }, "\n")
end
end


-- Main render function, takes a table of arguments (handles), returns wiki markup with social icons
-- 6) Main render function: iterates over platforms and returns a table row if any handles are set.
function sf.render(args)
function m.render(args)
     local icons = {}
     local icons = {}


Line 106: Line 141:
         local handle = getUserHandle(args, platform.param)
         local handle = getUserHandle(args, platform.param)
         if handle and handle ~= "" then
         if handle and handle ~= "" then
             local url = platform.prefix .. handle
             table.insert(icons, buildIcon(platform, handle))
            local iconLink = buildIconLink(platform.icon, platform.label, url)
            table.insert(icons, iconLink)
         end
         end
     end
     end


    -- If no handles were provided, return nothing.
     if #icons == 0 then
     if #icons == 0 then
         return ""
         return ""
     end
     end


    -- Return a row that fits nicely in the template, with a flex container for icons
     return buildSocialRow(icons)
     return buildSocialRow(icons)
end
end


return sf
return m