Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Editing Module:BSW/MainPage

From the only original and legitimate Battlestar Wiki: the free-as-in-beer, non-corporate, open-content encyclopedia, analytical reference, and episode guide on all things Battlestar Galactica. Accept neither subpar substitutes nor subpar clones.
Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision Your text
Line 1: Line 1:
-- Module:BSW/MainPage
-- Module:BSW/MainPage
-- MW 1.45 compatible. Uses only sanitizer-safe HTML elements.
-- Generates all main page HTML components via mw.html,
-- <button> is NOT on the MW 1.45 allowed list — replaced with
-- bypassing the wikitext parser entirely.
-- <span role="button"> which IS allowed and is wired by JS.
-- Usage: {{#invoke:BSW/MainPage|functionName|param=value|...}}
-- External <a class="..."> replaced with wikitext [url text]
-- processed via frame:preprocess().


local p = {}
local p = {}


-- ── Helpers ───────────────────────────────────────────────────────
-- ── Shared helpers ────────────────────────────────────────────────


local function e( s )
-- Safe attribute setter skips nil/empty values
    s = tostring( s or '' )
local function attr( el, name, value )
    s = s:gsub( '&', '&amp;' ):gsub( '<', '&lt;' ):gsub( '>', '&gt;' ):gsub( '"', '&quot;' )
     if value and value ~= '' then
    return s
        el:attr( name, value )
end
 
local function a( name, val )
    if val and val ~= '' then return ' ' .. name .. '="' .. e(val) .. '"' end
    return ''
end
 
-- Wikitext internal link: [[target|label]]
local function wlink( frame, target, label )
    return frame:preprocess( '[[' .. target .. '|' .. (label or target) .. ']]' )
end
 
-- External link via wikitext: [url label] survives sanitizer
local function xlink( frame, url, label )
    return frame:preprocess( '<span class="plainlinks">[' .. url .. ' ' .. (label or url) .. ']</span>' )
end
 
-- Span acting as a button — sanitizer-safe, JS wires the behaviour
local function spanBtn( id, cls, onclick, label )
     return '<span' ..
        a('id', id) ..
        a('class', cls) ..
        a('role', 'button') ..
        a('tabindex', '0') ..
        a('onclick', onclick) ..
        '>' .. (label or '') .. '</span>'
end
 
-- Check if transcluded content is just a red link (page doesn't exist).
-- Returns true if content should be hidden.
local function isRedlink( content )
    if not content or mw.text.trim( content ) == '' then return true end
    -- MW renders missing transclusions as red links with class="new"
    -- Check if content is ONLY a red link and nothing else meaningful
    local stripped = mw.text.trim( content )
    -- If it starts with the page title link pattern for a missing page
    -- (the whole content is just one red link), hide it
    if stripped:match( '^<a[^>]+class="[^"]*new[^"]*"' ) and
      not stripped:match( '</a>%s*%S' ) then
        return true
     end
     end
     return false
     return el
end
end


-- Wrap a card so JS can hide it if content is a red link
-- ── hero() ────────────────────────────────────────────────────────
local function conditionalCard( id, html )
-- Renders the entire hero slideshow: slides + dots + nav buttons.
    return '<div class="bsw-conditional-card"' .. a('id', id) .. '>' .. html .. '</div>'
-- Called ONCE from the main page with all slide data packed as
end
-- numbered parameter groups.
--
-- Usage:
-- {{#invoke:BSW/MainPage|hero
-- |slide1_article  = Battlestar Galactica (RDM)
-- |slide1_series  = Re-imagined Series
-- |slide1_title    = Battlestar Galactica
-- |slide1_titlelink= Battlestar Galactica (RDM)
-- |slide1_desc    = The last surviving...
-- |slide1_badgecolor=
-- |slide2_article  = Number Eight
-- ...
-- |count          = 3
-- }}


-- ── welcome() ────────────────────────────────────────────────────
function p.hero( frame )
function p.welcome( frame )
     local args = frame.args
     local articles = mw.site.stats.articles
     local count = tonumber( args.count ) or 0
     local formatted = tostring( articles ):reverse():gsub( '(%d%d%d)', '%1,' ):reverse():gsub( '^,', '' )
    local root  = mw.html.create( 'div' ):addClass( 'bsw-hero' )


     local logo = frame:preprocess( '[[File:BSG-WIKI SM.png|40px|link=Main Page|alt=Battlestar Wiki]]' )
     for i = 1, count do
        local pfx    = 'slide' .. i .. '_'
        local article = args[ pfx .. 'article'  ] or ''
        local series  = args[ pfx .. 'series'    ] or ''
        local title  = args[ pfx .. 'title'    ] or article
        local tlink  = args[ pfx .. 'titlelink' ] or article
        local desc    = args[ pfx .. 'desc'      ] or ''
        local bcolor  = args[ pfx .. 'badgecolor'] or ''


    local desc = frame:preprocess(
        local slide = root:tag( 'div' )
        "The free, non-corporate encyclopedia on all things " ..
            :addClass( 'bsw-slide' )
        "''Battlestar Galactica'' \226\128\148 " ..
            :attr( 'data-article', article )
        formatted .. "\194\160articles and counting."
    )


    local inner =
         if i == 1 then slide:addClass( 'bsw-active' ) end
         '<div class="bsw-welcome-logo">' .. logo .. '</div>' ..
        '<div class="bsw-welcome-text">' ..
        '<div class="bsw-welcome-title">Battlestar Wiki</div>' ..
        '<div class="bsw-welcome-desc">' .. desc .. '</div>' ..
        '</div>' ..
        '<div class="bsw-welcome-links">' ..
        frame:preprocess( '[[Special:Random|Random article]]' ) ..
        frame:preprocess( '[[Battlestar_Wiki:About|About]]' ) ..
        frame:preprocess( '[[Battlestar_Wiki:Community_portal|Community]]' ) ..
        '</div>'


    return '<div class="bsw-welcome">' .. inner .. '</div>'
        -- Background image container (populated by JS)
end
        slide:tag( 'div' ):addClass( 'bsw-slide-bg' ):done()


        -- Gradient overlay
        slide:tag( 'div' ):addClass( 'bsw-slide-overlay' ):done()


function p.hero( frame )
        -- Content
    local args  = frame.args
        local content = slide:tag( 'div' ):addClass( 'bsw-slide-content' )
    local count = tonumber( args.count ) or 0
    local html  = '<div class="bsw-hero">'


    for i = 1, count do
         -- Badge
         local pfx    = 'slide' .. i .. '_'
         local badge = content:tag( 'div' ):addClass( 'bsw-slide-badge' )
         local art    = mw.text.trim( args[pfx..'article']    or '' )
         local dot  = badge:tag( 'span' ):addClass( 'bsw-slide-badge-dot' )
         local series = mw.text.trim( args[pfx..'series']    or '' )
         if bcolor ~= '' then dot:attr( 'style', 'background:' .. bcolor ) end
        local title  = mw.text.trim( args[pfx..'title']      or art )
         badge:tag( 'span' ):wikitext( series )
         local tlink  = mw.text.trim( args[pfx..'titlelink']  or art )
        local desc  = mw.text.trim( args[pfx..'desc']      or '' )
         local bcolor = mw.text.trim( args[pfx..'badgecolor'] or '' )


         local active  = i == 1 and ' bsw-active' or ''
         -- Title as wikilink
        local dot_sty  = bcolor ~= '' and ' style="background:' .. bcolor .. '"' or ''
        content:tag( 'div' )
        local wl      = wlink( frame, tlink, title )
            :addClass( 'bsw-slide-title' )
            :wikitext( '[[' .. tlink .. '|' .. title .. ']]' )


         html = html ..
         -- Description
            '<div class="bsw-slide' .. active .. '"' .. a('data-article', art) .. '>' ..
        content:tag( 'div' )
            '<div class="bsw-slide-bg"></div>' ..
             :addClass( 'bsw-slide-desc' )
            '<div class="bsw-slide-overlay"></div>' ..
             :wikitext( desc )
            '<div class="bsw-slide-content">' ..
            '<div class="bsw-slide-badge">' ..
             '<span class="bsw-slide-badge-dot"' .. dot_sty .. '></span>' ..
            '<span>' .. e(series) .. '</span>' ..
            '</div>' ..
            '<div class="bsw-slide-title">' .. wl .. '</div>' ..
             '<div class="bsw-slide-desc">' .. e(desc) .. '</div>' ..
            '</div>' ..
            '</div>'
     end
     end


     -- Dots: span[role=button] — sanitizer safe
     -- Dots
     html = html .. '<div class="bsw-hero-dots">'
     local dots = root:tag( 'div' ):addClass( 'bsw-hero-dots' )
     for i = 1, count do
     for i = 1, count do
         local cls = 'bsw-hero-dot' .. (i == 1 and ' bsw-active' or '')
         local dot = dots:tag( 'button' )
        html = html .. spanBtn(nil, cls, 'bswGoSlide(' .. (i-1) .. ')', '')
            :addClass( 'bsw-hero-dot' )
            :attr( 'aria-label', 'Slide ' .. i )
            :wikitext( '' )
        if i == 1 then dot:addClass( 'bsw-active' ) end
     end
     end
    html = html .. '</div>'


     -- Prev/next: span[role=button]
     -- Prev / next buttons
     html = html ..
     local nav = root:tag( 'div' ):addClass( 'bsw-hero-nav' )
        '<div class="bsw-hero-nav">' ..
    nav:tag( 'button' )
         spanBtn('bsw-hero-prev', 'bsw-hero-btn', 'bswPrevSlide()', '&#8249;') ..
         :attr( 'id', 'bsw-hero-prev' )
         spanBtn('bsw-hero-next', 'bsw-hero-btn', 'bswNextSlide()', '&#8250;') ..
        :attr( 'aria-label', 'Previous slide' )
         '</div>' ..
        :wikitext( '‹' )
        '</div>'
    nav:tag( 'button' )
         :attr( 'id', 'bsw-hero-next' )
        :attr( 'aria-label', 'Next slide' )
         :wikitext( '' )


     return html
     return tostring( root )
end
end


-- ── portals() ─────────────────────────────────────────────────────
-- ── portals() ─────────────────────────────────────────────────────
-- Renders the full portals bar.
-- Usage:
-- {{#invoke:BSW/MainPage|portals
-- |portal1_href  = /Portal:Battlestar_Galactica_(TOS)
-- |portal1_stripe= #ef9f27
-- |portal1_icon  = 📺
-- |portal1_name  = Original Series
-- |portal1_sub  = TOS · 1978
-- |count        = 5
-- }}
function p.portals( frame )
function p.portals( frame )
     local args  = frame.args
     local args  = frame.args
     local count = tonumber( args.count ) or 0
     local count = tonumber( args.count ) or 0


     local html =
     local wrap = mw.html.create( 'div' ):addClass( 'bsw-portals' )
        '<div class="bsw-portals">' ..
    wrap:tag( 'div' )
         '<div class="bsw-portals-label">∞ Portals of Battlestar Wiki ∞</div>' ..
         :addClass( 'bsw-portals-label' )
        '<div class="bsw-portals-grid">'
        :wikitext( '∞ Portals of Battlestar Wiki ∞' )
 
    local grid = wrap:tag( 'div' ):addClass( 'bsw-portals-grid' )


     for i = 1, count do
     for i = 1, count do
         local pfx    = 'portal' .. i .. '_'
         local pfx    = 'portal' .. i .. '_'
         local href  = mw.text.trim( args[pfx..'href']   or '#' )
         local href  = args[ pfx .. 'href'   ] or '#'
         local stripe = mw.text.trim( args[pfx..'stripe'] or '' )
         local stripe = args[ pfx .. 'stripe' ] or ''
         local icon  = mw.text.trim( args[pfx..'icon']   or '' )
         local icon  = args[ pfx .. 'icon'   ] or ''
         local name  = mw.text.trim( args[pfx..'name']   or '' )
         local name  = args[ pfx .. 'name'   ] or ''
         local sub    = mw.text.trim( args[pfx..'sub']   or '' )
         local sub    = args[ pfx .. 'sub'   ] or ''
 
        local card = grid:tag( 'a' )
            :addClass( 'bsw-portal' )
            :attr( 'href', href )


         -- Internal links (/Portal:...) work as wikitext links
         -- Colour stripe
        -- Use span wrapper styled as link block via CSS
         local stripeEl = card:tag( 'div' ):addClass( 'bsw-portal-stripe' )
         local stripe_sty = stripe ~= '' and ' style="background:' .. stripe .. '"' or ''
        if stripe ~= '' then
        local inner =
             stripeEl:attr( 'style', 'background:' .. stripe )
            '<div class="bsw-portal-stripe"' .. stripe_sty .. '></div>' ..
        end
            '<span class="bsw-portal-icon">' .. icon .. '</span>' ..
             '<span class="bsw-portal-name">' .. e(name) .. '</span>' ..
            '<span class="bsw-portal-sub">' .. e(sub) .. '</span>'


         -- Use MW internal link syntax — href is a /Wiki_Path
         card:tag( 'span' ):addClass( 'bsw-portal-icon' ):wikitext( icon )
         -- Strip leading slash to get page title
         card:tag( 'span' ):addClass( 'bsw-portal-name' ):wikitext( name )
        local page = href:gsub('^/', '')
         card:tag( 'span' ):addClass( 'bsw-portal-sub' ):wikitext( sub  )
         local link = frame:preprocess( '[[' .. page .. '|<div class="bsw-portal">' .. inner .. '</div>]]' )
        html = html .. link
     end
     end


    html = html .. '</div></div>'
     return tostring( wrap )
     return html
end
end


-- ── card header helper ────────────────────────────────────────────
-- ── card() ────────────────────────────────────────────────────────
-- Returns card-hd div; link is rendered as wikitext [url text]
-- Renders a single card with a header bar.
local function cardHd( frame, title, linktext, linkurl )
-- |title    = Card title (plain text)
    local hd = '<div class="bsw-card-hd">' .. e(title)
-- |linktext = Link text (optional)
    if linkurl and linkurl ~= '' then
-- |linkurl = Link URL (optional)
        -- Internal links start with /
-- |id      = Optional id on the card-body div
        local link
-- |content  = Wikitext/HTML body content
        if linkurl:match('^/') or linkurl:match('^#') then
            local page = linkurl:gsub('^/', '')
            if page == '' or page:match('^#') then
                -- anchor-only or hash — can't wikilink, use span
                link = '<span class="bsw-card-hd-link">' .. e(linktext or 'More') .. '</span>'
            else
                link = frame:preprocess( '[[' .. page .. '|' .. (linktext or 'More →') .. ']]' )
            end
        else
            link = xlink( frame, linkurl, linktext or 'More →' )
        end
        hd = hd .. link
    end
    hd = hd .. '</div>'
    return hd
end


-- ── card() ────────────────────────────────────────────────────────
function p.card( frame )
function p.card( frame )
     local args    = frame.args
     local args    = frame.args
     local title  = mw.text.trim( args.title    or '' )
     local title  = args.title    or ''
     local ltext  = mw.text.trim( args.linktext or '' )
     local ltext  = args.linktext or ''
     local lurl    = mw.text.trim( args.linkurl  or '' )
     local lurl    = args.linkurl  or ''
     local content = args.content or ''
    local bodyid  = args.id      or ''
     local content = args.content or ''


     -- Hide card entirely if content resolved to only a red link
     local wrap = mw.html.create( 'div' ):addClass( 'bsw-card' )
    if isRedlink( content ) then return '' end


     return '<div class="bsw-card">' ..
     local hd = wrap:tag( 'div' ):addClass( 'bsw-card-hd' )
        cardHd( frame, title, ltext, lurl ) ..
    hd:wikitext( title )
         '<div class="bsw-card-body">' .. content .. '</div>' ..
    if lurl ~= '' then
        '</div>'
         hd:tag( 'a' ):attr( 'href', lurl ):wikitext( ltext ~= '' and ltext or 'More →' )
end
    end


-- ── featuredloading() ─────────────────────────────────────────────
    local body = wrap:tag( 'div' ):addClass( 'bsw-card-body' )
function p.featuredloading( frame )
     if bodyid ~= '' then body:attr( 'id', bodyid ) end
    -- "Read more" link points to '#' — JS will update href
    body:wikitext( content )
    -- Use a span since we can't href to '#' cleanly in wikitext
     local hd =
        '<div class="bsw-card-hd">Featured article' ..
        '<span class="bsw-card-hd-link" id="bsw-featured-link">Read more →</span>' ..
        '</div>'


     return '<div class="bsw-card">' ..
     return tostring( wrap )
        hd ..
        '<div class="bsw-card-body">' ..
        '<div id="bsw-featured-inner">' ..
        '<div class="bsw-loading">' ..
        '<div class="bsw-spinner"></div>' ..
        'Loading today\'s featured article\226\128\166' ..
        '</div></div></div></div>'
end
end


-- ── photolab() ────────────────────────────────────────────────────
-- ── statbox() ─────────────────────────────────────────────────────
function p.photolab( frame )
-- Single statistic box.
     local args      = frame.args
-- |n     = number (use MW magic word e.g. {{NUMBEROFARTICLES}})
    local content  = mw.text.trim( args.content or '' )
-- |label = label text
    local prev_potd = mw.text.trim( args.prev_url  or '' )
 
     local prev_lbl = mw.text.trim( args.prev_label or '‹' )
function p.statbox( frame )
     local next_potd = mw.text.trim( args.next_url  or '' )
     local args = frame.args
     local next_lbl  = mw.text.trim( args.next_label or '' )
     local n    = args.n    or ''
     local label = args.label or ''


     local caption_page = mw.text.trim( args.caption_page or '' )
     local wrap = mw.html.create( 'div' ):addClass( 'bsw-stat' )
    local caption = ''
     wrap:tag( 'div' ):addClass( 'bsw-stat-n' ):wikitext( n )
     if caption_page ~= '' then
    wrap:tag( 'div' ):addClass( 'bsw-stat-l' ):wikitext( label )
        caption = frame:preprocess( '{{' .. caption_page .. '}}' )
    else
        caption = args.caption or ''
    end


     -- Hide if today's PotD subpage doesn't exist yet
     return tostring( wrap )
    if isRedlink( content ) then return '' end
end


    -- The Potd: subpage stores just the bare filename without "File:" prefix.
-- ── statsblock() ──────────────────────────────────────────────────
    local rendered_content = content
-- Full statistics card including grid + action links.
    if content ~= '' and not content:match( '%[%[' ) and not content:match( '<' ) then
-- Accepts |n1|label1 ... |n6|label6 for the six stat boxes,
        local filename = mw.text.trim( content )
-- plus |link1_url, |link1_text, |link2_url, |link2_text.
        if filename ~= '' then
            -- Use thumb syntax suppressed via frameless|none to avoid
            -- MW adding figure wrapper with extra margins
            rendered_content = frame:preprocess(
                '[[File:' .. filename .. '|center|frameless|upright=1.5]]'
            )
        end
    end


    -- Resolve a Potd:MM-DD subpage to its bare filename,
function p.statsblock( frame )
    -- then build a [[File:filename|label]] link from it.
    local args = frame.args
    local function potdFileLink( potd_page, label )
        if potd_page == '' then return label end
        local t = mw.title.new( potd_page )
        if t and t.exists then
            local fn = mw.text.trim( t:getContent() or '' )
            if fn ~= '' and not fn:match( '%[%[' ) then
                -- Use [[:File:...]] (colon prefix) to link TO the file page
                -- rather than [[File:...]] which would transclude/embed the image
                return frame:preprocess( '[[:File:' .. fn .. '|' .. label .. ']]' )
            end
        end
        return frame:preprocess( '[[' .. potd_page .. '|' .. label .. ']]' )
    end


     local hd =
     local wrap = mw.html.create( 'div' ):addClass( 'bsw-card' )
        '<div class="bsw-card-hd">\226\136\158 Photo Lab \226\128\148 Picture of the Day' ..
        frame:preprocess( '[[BW:Potd|View project →]]' ) ..
        '</div>'


     local nav =
     -- Header
        '<div class="bsw-photo-nav">' ..
    wrap:tag( 'div' ):addClass( 'bsw-card-hd' ):wikitext( 'Wiki statistics' )
        potdFileLink( prev_potd, prev_lbl ) ..
        '<span class="bsw-photo-caption">' .. caption .. '</span>' ..
        potdFileLink( next_potd, next_lbl ) ..
        '</div>'


     return '<div class="bsw-card">' .. hd .. rendered_content .. nav .. '</div>'
     local body = wrap:tag( 'div' ):addClass( 'bsw-card-body' )
end
    local grid = body:tag( 'div' ):addClass( 'bsw-stats-grid' )


-- ── statsblock() ──────────────────────────────────────────────────
function p.statsblock( frame )
    local args = frame.args
    local grid = '<div class="bsw-stats-grid">'
     for i = 1, 6 do
     for i = 1, 6 do
         local n    = mw.text.trim( args['n'    .. i] or '' )
         local n    = args[ 'n'    .. i ] or ''
         local label = mw.text.trim( args['label' .. i] or '' )
         local label = args[ 'label' .. i ] or ''
         if n ~= '' or label ~= '' then
         if n ~= '' or label ~= '' then
             grid = grid ..
             local box = grid:tag( 'div' ):addClass( 'bsw-stat' )
                '<div class="bsw-stat">' ..
            box:tag( 'div' ):addClass( 'bsw-stat-n' ):wikitext( n )
                '<div class="bsw-stat-n">' .. n .. '</div>' ..
            box:tag( 'div' ):addClass( 'bsw-stat-l' ):wikitext( label )
                '<div class="bsw-stat-l">' .. e(label) .. '</div>' ..
                '</div>'
         end
         end
     end
     end
    grid = grid .. '</div>'


     local links = '<div class="bsw-stat-links">'
    -- Action links
     local links = body:tag( 'div' ):addClass( 'bsw-stat-links' )
     for i = 1, 4 do
     for i = 1, 4 do
         local url  = mw.text.trim( args['link' .. i .. '_url' ] or '' )
         local url  = args[ 'link' .. i .. '_url' ] or ''
         local text = mw.text.trim( args['link' .. i .. '_text'] or '' )
         local text = args[ 'link' .. i .. '_text' ] or ''
         if url ~= '' then
         if url ~= '' then
             local page = url:gsub('^/', '')
             links:tag( 'a' )
            links = links .. frame:preprocess( '[[' .. page .. '|<span class="bsw-stat-link">' .. e(text) .. '</span>]]' )
                :addClass( 'bsw-stat-link' )
                :attr( 'href', url )
                :wikitext( text ~= '' and text or url )
         end
         end
     end
     end
    links = links .. '</div>'


     return
     return tostring( wrap )
        '<div class="bsw-card">' ..
        '<div class="bsw-card-hd">Wiki statistics</div>' ..
        '<div class="bsw-card-body">' .. grid .. links .. '</div>' ..
        '</div>'
end
end


-- ── recenttabs() ──────────────────────────────────────────────────
-- ── recenttabs() ──────────────────────────────────────────────────
-- Renders the wiki-tab bar for Recent Changes.
-- Tabs are wired to bswSetTab() in Common.js.
function p.recenttabs( frame )
function p.recenttabs( frame )
     local tabs = { {'All','all'}, {'EN','en'}, {'DE','de'}, {'FR','fr'}, {'Media','media'} }
     local tabs = { 'All', 'EN', 'DE', 'Media' }
     local html = '<div class="bsw-wiki-tabs">'
    local keys  = { 'all', 'en', 'de', 'media' }
     for i, t in ipairs(tabs) do
 
         local cls = 'bsw-wtab' .. (i == 1 and ' bsw-active' or '')
     local wrap = mw.html.create( 'div' ):addClass( 'bsw-wiki-tabs' )
        html = html .. spanBtn(nil, cls, "bswSetTab(this,'" .. t[2] .. "')", t[1])
     for i, label in ipairs( tabs ) do
         local btn = wrap:tag( 'button' )
            :addClass( 'bsw-wtab' )
            :attr( 'onclick', "bswSetTab(this,'" .. keys[i] .. "')" )
            :wikitext( label )
        if i == 1 then btn:addClass( 'bsw-active' ) end
     end
     end
     return html .. '</div>'
 
     return tostring( wrap )
end
end


-- ── interwiki() ───────────────────────────────────────────────────
-- ── interwiki() ───────────────────────────────────────────────────
-- Renders the interwiki bar.
-- |1_flag, |1_label, |1_url ... up to 8 entries.
function p.interwiki( frame )
function p.interwiki( frame )
     local args = frame.args
     local args = frame.args
     local html = '<div class="bsw-interwiki">'
     local wrap = mw.html.create( 'div' ):addClass( 'bsw-interwiki' )
 
     for i = 1, 8 do
     for i = 1, 8 do
         local flag  = mw.text.trim( args[i..'_flag' ] or '' )
         local flag  = args[ i .. '_flag' ] or ''
         local label = mw.text.trim( args[i..'_label'] or '' )
         local label = args[ i .. '_label' ] or ''
         local url  = mw.text.trim( args[i..'_url' ] or '' )
         local url  = args[ i .. '_url'   ] or ''
         if url ~= '' then
         if url ~= '' then
             local link
             local iw = wrap:tag( 'div' ):addClass( 'bsw-iw' )
            if url:match('^/') then
             if flag ~= '' then iw:wikitext( flag .. ' ' ) end
                link = frame:preprocess( '[[' .. url:gsub('^/','') .. '|' .. label .. ']]' )
             iw:tag( 'a' ):attr( 'href', url ):wikitext( label )
             else
                link = xlink( frame, url, label )
            end
            local prefix = flag ~= '' and (flag .. ' ') or ''
             html = html .. '<div class="bsw-iw">' .. prefix .. link .. '</div>'
         end
         end
     end
     end
     return html .. '</div>'
 
     return tostring( wrap )
end
end


-- ── tagline() ─────────────────────────────────────────────────────
-- ── featuredloading() ─────────────────────────────────────────────
function p.tagline( frame )
-- Renders the featured article card shell with loading state.
    local inner = frame:preprocess(
-- JS replaces the inner content after fetching.
        "The only original and legitimate '''Battlestar Wiki''' " ..
        "\226\128\148 the free-as-in-beer, non-corporate, open-content encyclopedia " ..
        "on all things ''Battlestar Galactica''.<br>" ..
        "\226\136\158 ''Accept neither subpar substitutes nor subpar clones.'' \226\136\158"
    )
    return '<div class="bsw-tagline">' .. inner .. '</div>'
end


-- ── newestarticle() ──────────────────────────────────────────────
function p.featuredloading( frame )
-- Shell card populated by JS from Special:NewPages API.
     local wrap = mw.html.create( 'div' ):addClass( 'bsw-card' )
function p.newestarticle( frame )
     return
        '<div class="bsw-card" id="bsw-newest-card">' ..
        '<div class="bsw-card-hd">Newest article' ..
        frame:preprocess( '[[Special:NewPages|All new pages →]]' ) ..
        '</div>' ..
        '<div class="bsw-card-body">' ..
        '<div id="bsw-newest-inner">' ..
        '<div class="bsw-loading"><div class="bsw-spinner"></div>Loading…</div>' ..
        '</div>' ..
        '</div>' ..
        '</div>'
end


    local hd = wrap:tag( 'div' ):addClass( 'bsw-card-hd' )
    hd:wikitext( 'Featured article' )
    hd:tag( 'a' )
        :attr( 'id', 'bsw-featured-link' )
        :attr( 'href', '#' )
        :wikitext( 'Read more →' )


-- Dedicated card for sister wiki links.
     local body = wrap:tag( 'div' ):addClass( 'bsw-card-body' )
-- Uses numbered params: |1_label, |1_url, |2_label, |2_url ...
     local inner = body:tag( 'div' ):attr( 'id', 'bsw-featured-inner' )
-- External URLs rendered via frame:preprocess [url label] syntax.
    local loading = inner:tag( 'div' ):addClass( 'bsw-loading' )
function p.sisterprojects( frame )
    loading:tag( 'div' ):addClass( 'bsw-spinner' ):wikitext( '' )
    local args = frame.args
     loading:wikitext( 'Loading today\'s featured article…' )
     local body = '<div style="display:flex;flex-direction:column;gap:0.375rem">'
     for i = 1, 8 do
        local label = mw.text.trim( args[i .. '_label'] or '' )
        local url  = mw.text.trim( args[i .. '_url' ] or '' )
        if url ~= '' and label ~= '' then
            -- Wrap in span.bsw-sister-link for styling
            -- Use preprocess so [url text] becomes a real hyperlink
            local link = frame:preprocess( '[' .. url .. ' ' .. label .. ']' )
            body = body .. '<div class="bsw-sister-link">' .. link .. '</div>'
        end
     end
    body = body .. '</div>'


     return
     return tostring( wrap )
        '<div class="bsw-card">' ..
        '<div class="bsw-card-hd">Sister projects</div>' ..
        '<div class="bsw-card-body">' .. body .. '</div>' ..
        '</div>'
end
end


-- ── votd() ────────────────────────────────────────────────────────
-- ── photolab() ────────────────────────────────────────────────────
function p.votd( frame )
-- Renders the Photo Lab card shell.
     local today = os.date( '%Y-%m-%d' )
-- Content (the actual PotD image) is passed as |content=
-- via a nested template call on the main page.
-- |prev_label, |prev_url, |caption, |next_label, |next_url
 
function p.photolab( frame )
     local args    = frame.args
    local content  = args.content  or ''
    local prev_url = args.prev_url  or '#'
    local prev_lbl = args.prev_label or '‹'
    local caption  = args.caption  or ''
    local next_url = args.next_url  or '#'
    local next_lbl = args.next_label or '›'
 
    local wrap = mw.html.create( 'div' ):addClass( 'bsw-card' )


     -- Check for manual override subpage server-side.
     local hd = wrap:tag( 'div' ):addClass( 'bsw-card-hd' )
    -- Rather than putting the token in a data attribute (which can
     hd:wikitext( '∞ Photo Lab — Picture of the Day' )
    -- trigger Citizen skin hook warnings), we embed it in a hidden
     hd:tag( 'a' ):attr( 'href', '/BW:Potd' ):wikitext( 'View project →' )
     -- <span> inside the container that the JS reads instead.
    local override_page  = 'Battlestar Wiki:Video of the Day/' .. today
     local override_title = mw.title.new( override_page )
    local override_token = ''
    if override_title and override_title.exists then
        local content = override_title:getContent()
        if content then
            override_token = mw.text.trim( content )
        end
    end


     local override_span = ''
     -- PotD image transcluded as wikitext
     if override_token ~= '' then
     wrap:wikitext( content )
        override_span =
            '<span id="bsw-votd-override" style="display:none">' ..
            mw.text.nowiki( override_token ) ..
            '</span>'
    end


     -- Header bar
     -- Nav row
     local hd =
     local nav = wrap:tag( 'div' ):addClass( 'bsw-photo-nav' )
        '<div class="bsw-votd-hd">' ..
    nav:tag( 'a' ):attr( 'href', prev_url ):wikitext( prev_lbl )
        '<span class="bsw-votd-hd-inner">' ..
    nav:tag( 'span' ):addClass( 'bsw-photo-caption' ):wikitext( caption )
        '<span class="bsw-votd-hd-dot"></span>' ..
    nav:tag( 'a' ):attr( 'href', next_url ):wikitext( next_lbl )
        '\226\136\158 Video of the Day' ..
        '</span>' ..
        frame:preprocess( '<span class="plainlinks">[https://battlestarpegasus.com battlestarpegasus.com \226\134\151]</span>' ) ..
        '</div>'


     -- Inner grid: player + info panel, both populated by JS
     return tostring( wrap )
    local inner =
end
        '<div class="bsw-votd-inner">' ..
        '<div class="bsw-votd-player">' ..
        '<div class="bsw-loading"><div class="bsw-spinner"></div>' ..
        'Loading today\226\128\153s video\226\128\166</div>' ..
        '</div>' ..
        '<div class="bsw-votd-info" id="bsw-votd-info" style="display:none"></div>' ..
        '</div>'


     return
-- ── tagline() ─────────────────────────────────────────────────────
        '<div class="bsw-votd-band" id="bsw-votd-container"' ..
function p.tagline( frame )
         ' data-date="' .. today .. '">' ..
     local wrap = mw.html.create( 'div' ):addClass( 'bsw-tagline' )
         override_span ..
    wrap:wikitext(
         hd .. inner ..
         "The only original and legitimate '''Battlestar Wiki''' " ..
         '</div>'
         "— the free-as-in-beer, non-corporate, open-content encyclopedia " ..
         "on all things ''Battlestar Galactica''.<br>" ..
         "∞ ''Accept neither subpar substitutes nor subpar clones.'' ∞"
    )
    return tostring( wrap )
end
end


return p
return p

To protect the wiki against automated edit spam, please solve the following captcha:

Cancel Editing help (opens in new window)

  [] · [[]] · [[|]] · {{}} · · “” ‘’ «» ‹› „“ ‚‘ · ~ | ° &nbsp; · ± × ÷ ² ³ ½ · §
     [[Category:]] · [[:File:]] · [[Special:MyLanguage/]] · <code></code> · <nowiki></nowiki> <code><nowiki></nowiki></code> · <syntaxhighlight></syntaxhighlight> · <includeonly></includeonly> · <noinclude></noinclude> · #REDIRECT[[]] · <translate></translate> · <languages/> · {{#translation:}} · <tvar|></> · {{DEFAULTSORT:}} · <categorytree></categorytree> · <div style="clear:both;"></div> <s></s>


Your changes will be visible immediately.
  • For testing, please use the sandbox instead.
  • On talk pages, please sign your comment by typing four tildes (~~~~).

Page included on this page: