|
|
| Line 1: |
Line 1: |
| -- This module handles inline SVGs for social icons and returns a table row. | | -- Reusable social media component meant to be called from other modules |
|
| |
|
| local m = {} | | local sf = {} |
|
| |
|
| -- 1) Inline SVG Definitions | | -- This section defines the social platforms; can be added or deleted without consequence |
| -- All your platform icons are stored here as local strings. | | -- param = handle for the platform; for "x", we also accept "twitter" for legacy purposes |
| local svgIcons = {
| | -- icon = wiki file for the icon |
| facebook = [==[
| | -- prefix = URL prefix |
| <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
| | -- label = used for alt text/screen readers |
| <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>
| |
| ]==],
| |
| | |
| instagram = [==[
| |
| <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>
| |
| ]==],
| |
| | |
| 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) Table listing param, inlineKey, prefix, label, etc.
| |
| local socialPlatforms = { | | local socialPlatforms = { |
| { | | { |
| param = "facebook", | | param = "facebook", |
| inlineKey = "facebook", | | icon = "File:SocialFacebookIcon.svg", |
| prefix = "https://www.facebook.com/", | | prefix = "https://www.facebook.com/", |
| label = "Facebook" | | label = "Facebook" |
| }, | | }, |
| { | | { |
| param = "instagram", | | param = "instagram", |
| inlineKey = "instagram", | | icon = "File:SocialInstagramIcon.svg", |
| prefix = "https://www.instagram.com/", | | prefix = "https://www.instagram.com/", |
| label = "Instagram" | | label = "Instagram" |
| }, | | }, |
| { | | { |
| param = "linkedin", | | param = "linkedin", |
| inlineKey = "linkedin", | | icon = "File:SocialLinkedInIcon.svg", |
| prefix = "https://www.linkedin.com/", | | prefix = "https://www.linkedin.com/", |
| label = "LinkedIn" | | label = "LinkedIn" |
| }, | | }, |
| { | | { |
| param = "telegram", | | param = "telegram", |
| inlineKey = "telegram", | | icon = "File:SocialTelegramIcon.svg", |
| prefix = "https://t.me/", | | prefix = "https://t.me/", |
| label = "Telegram" | | label = "Telegram" |
| }, | | }, |
| { | | { |
| param = "threads", | | param = "threads", |
| inlineKey = "threads", | | icon = "File:SocialThreadsIcon.svg", |
| prefix = "https://www.threads.net/", | | prefix = "https://www.threads.net/", |
| label = "Threads" | | label = "Threads" |
| }, | | }, |
| { | | { |
| param = "tiktok", | | param = "tiktok", |
| inlineKey = "tiktok", | | icon = "File:SocialTikTokIcon.svg", |
| prefix = "https://www.tiktok.com/", | | prefix = "https://www.tiktok.com/", |
| label = "TikTok" | | label = "TikTok" |
| }, | | }, |
| { | | { |
| -- Accept either |x= or |twitter= from the user, | | -- Multiple aliases: the editor can supply "x" or "twitter" |
| -- but we'll reuse the same inlineKey "twitter"
| | param = { "x", "twitter" }, |
| param = { "x", "twitter" }, | | icon = "File:SocialXIcon.svg", |
| inlineKey = "twitter", | | prefix = "https://x.com/", |
| prefix = "https://x.com/", | | label = "X (Twitter)" |
| label = "X (Twitter)" | |
| }, | | }, |
| { | | { |
| param = "youtube", | | param = "youtube", |
| inlineKey = "youtube", | | icon = "File:SocialYouTubeIcon.svg", |
| prefix = "https://www.youtube.com/", | | prefix = "https://www.youtube.com/", |
| label = "YouTube" | | label = "YouTube" |
| }, | | }, |
| } | | } |
|
| |
|
| -- 3) Helper to find the user's input handle for a given platform | | -------------------------------------------------------------------------------- |
| | -- 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 109: |
Line 75: |
| end | | end |
| end | | end |
| | return nil |
| end | | end |
| return nil
| |
| end | | end |
|
| |
|
| -- 4) Build each icon as an <a> with inline SVG | | -- Build a clickable icon link (24px) with alt text for accessibility: |
| local function buildIcon(platform, handle)
| | -- [[File:Something.svg|24px|alt=ALT_TEXT|link=URL]] |
| local svgCode = svgIcons[platform.inlineKey] or ""
| | local function buildIconLink(iconFile, altText, url) |
| local url = platform.prefix .. handle
| | return string.format("[[%s|24px|alt=%s|link=%s]]", iconFile, altText, url) |
| local altText = platform.label
| |
| -- We'll rely on external CSS to style .social-icon or the <svg> inside it
| |
| return string.format( | |
| '<a href="%s" title="%s" class="social-icon">%s</a>',
| |
| url, altText, svgCode
| |
| )
| |
| end | | end |
|
| |
|
| -- 5) Return a table row (|-) with colspan=2 containing a flex container of icons | | -- Build a single table row with colspan=2, containing a flex container for icons |
| local function buildSocialRow(icons) | | local function buildSocialRow(icons) |
| | local iconMarkup = table.concat({ |
| | '<div style="display: flex; flex-wrap: wrap; gap: 0.5em; margin-top: 0.2em;">', |
| | table.concat(icons, ""), |
| | '</div>' |
| | }, "\n") |
| | |
| return table.concat({ | | return table.concat({ |
| "|-", | | "|-", |
| '| colspan="2" | <div class="social-icons">', | | '| colspan="2" | ' .. iconMarkup |
| table.concat(icons, ""),
| |
| '</div>'
| |
| }, "\n") | | }, "\n") |
| end | | end |
|
| |
|
| -- 6) Main render function: produce a table row with icons | | -- Main render function, takes a table of arguments (handles), returns wiki markup with social icons |
| function m.render(args) | | function sf.render(args) |
| local icons = {} | | local icons = {} |
|
| |
|
| -- Loop over each platform definition
| |
| 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 |
| table.insert(icons, buildIcon(platform, handle)) | | local url = platform.prefix .. handle |
| | local iconLink = buildIconLink(platform.icon, platform.label, url) |
| | table.insert(icons, iconLink) |
| end | | end |
| end | | end |
|
| |
|
| -- If user provided no handles, return empty string | | -- If no handles were provided, return nothing. |
| if #icons == 0 then | | if #icons == 0 then |
| return "" | | return "" |
| end | | end |
|
| |
|
| -- Otherwise, return the social row | | -- Return a row that fits nicely in the template, with a flex container for icons |
| return buildSocialRow(icons) | | return buildSocialRow(icons) |
| end | | end |
|
| |
|
| return m | | return sf |