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.
More actions
Documentation for this module may be created at Module:BSW/MainPage/doc
-- Module:BSW/MainPage
-- Generates all main page HTML components via mw.html,
-- bypassing the wikitext parser entirely.
-- Usage: {{#invoke:BSW/MainPage|functionName|param=value|...}}
local p = {}
-- ── Shared helpers ────────────────────────────────────────────────
-- Safe attribute setter — skips nil/empty values
local function attr( el, name, value )
if value and value ~= '' then
el:attr( name, value )
end
return el
end
-- ── hero() ────────────────────────────────────────────────────────
-- Renders the entire hero slideshow: slides + dots + nav buttons.
-- Called ONCE from the main page with all slide data packed as
-- 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
-- }}
function p.hero( frame )
local args = frame.args
local count = tonumber( args.count ) or 0
local root = mw.html.create( 'div' ):addClass( 'bsw-hero' )
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 slide = root:tag( 'div' )
:addClass( 'bsw-slide' )
:attr( 'data-article', article )
if i == 1 then slide:addClass( 'bsw-active' ) end
-- Background image container (populated by JS)
slide:tag( 'div' ):addClass( 'bsw-slide-bg' ):done()
-- Gradient overlay
slide:tag( 'div' ):addClass( 'bsw-slide-overlay' ):done()
-- Content
local content = slide:tag( 'div' ):addClass( 'bsw-slide-content' )
-- Badge
local badge = content:tag( 'div' ):addClass( 'bsw-slide-badge' )
local dot = badge:tag( 'span' ):addClass( 'bsw-slide-badge-dot' )
if bcolor ~= '' then dot:attr( 'style', 'background:' .. bcolor ) end
badge:tag( 'span' ):wikitext( series )
-- Title as wikilink
content:tag( 'div' )
:addClass( 'bsw-slide-title' )
:wikitext( '[[' .. tlink .. '|' .. title .. ']]' )
-- Description
content:tag( 'div' )
:addClass( 'bsw-slide-desc' )
:wikitext( desc )
end
-- Dots
local dots = root:tag( 'div' ):addClass( 'bsw-hero-dots' )
for i = 1, count do
local dot = dots:tag( 'button' )
:addClass( 'bsw-hero-dot' )
:attr( 'aria-label', 'Slide ' .. i )
:wikitext( '' )
if i == 1 then dot:addClass( 'bsw-active' ) end
end
-- Prev / next buttons
local nav = root:tag( 'div' ):addClass( 'bsw-hero-nav' )
nav:tag( 'button' )
:attr( 'id', 'bsw-hero-prev' )
:attr( 'aria-label', 'Previous slide' )
:wikitext( '‹' )
nav:tag( 'button' )
:attr( 'id', 'bsw-hero-next' )
:attr( 'aria-label', 'Next slide' )
:wikitext( '›' )
return tostring( root )
end
-- ── 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 )
local args = frame.args
local count = tonumber( args.count ) or 0
local wrap = mw.html.create( 'div' ):addClass( 'bsw-portals' )
wrap:tag( 'div' )
:addClass( 'bsw-portals-label' )
:wikitext( '∞ Portals of Battlestar Wiki ∞' )
local grid = wrap:tag( 'div' ):addClass( 'bsw-portals-grid' )
for i = 1, count do
local pfx = 'portal' .. i .. '_'
local href = args[ pfx .. 'href' ] or '#'
local stripe = args[ pfx .. 'stripe' ] or ''
local icon = args[ pfx .. 'icon' ] or ''
local name = args[ pfx .. 'name' ] or ''
local sub = args[ pfx .. 'sub' ] or ''
local card = grid:tag( 'a' )
:addClass( 'bsw-portal' )
:attr( 'href', href )
-- Colour stripe
local stripeEl = card:tag( 'div' ):addClass( 'bsw-portal-stripe' )
if stripe ~= '' then
stripeEl:attr( 'style', 'background:' .. stripe )
end
card:tag( 'span' ):addClass( 'bsw-portal-icon' ):wikitext( icon )
card:tag( 'span' ):addClass( 'bsw-portal-name' ):wikitext( name )
card:tag( 'span' ):addClass( 'bsw-portal-sub' ):wikitext( sub )
end
return tostring( wrap )
end
-- ── card() ────────────────────────────────────────────────────────
-- Renders a single card with a header bar.
-- |title = Card title (plain text)
-- |linktext = Link text (optional)
-- |linkurl = Link URL (optional)
-- |id = Optional id on the card-body div
-- |content = Wikitext/HTML body content
function p.card( frame )
local args = frame.args
local title = args.title or ''
local ltext = args.linktext or ''
local lurl = args.linkurl or ''
local bodyid = args.id or ''
local content = args.content or ''
local wrap = mw.html.create( 'div' ):addClass( 'bsw-card' )
local hd = wrap:tag( 'div' ):addClass( 'bsw-card-hd' )
hd:wikitext( title )
if lurl ~= '' then
hd:tag( 'a' ):attr( 'href', lurl ):wikitext( ltext ~= '' and ltext or 'More →' )
end
local body = wrap:tag( 'div' ):addClass( 'bsw-card-body' )
if bodyid ~= '' then body:attr( 'id', bodyid ) end
body:wikitext( content )
return tostring( wrap )
end
-- ── statbox() ─────────────────────────────────────────────────────
-- Single statistic box.
-- |n = number (use MW magic word e.g. {{NUMBEROFARTICLES}})
-- |label = label text
function p.statbox( frame )
local args = frame.args
local n = args.n or ''
local label = args.label or ''
local wrap = mw.html.create( 'div' ):addClass( 'bsw-stat' )
wrap:tag( 'div' ):addClass( 'bsw-stat-n' ):wikitext( n )
wrap:tag( 'div' ):addClass( 'bsw-stat-l' ):wikitext( label )
return tostring( wrap )
end
-- ── statsblock() ──────────────────────────────────────────────────
-- Full statistics card including grid + action links.
-- Accepts |n1|label1 ... |n6|label6 for the six stat boxes,
-- plus |link1_url, |link1_text, |link2_url, |link2_text.
function p.statsblock( frame )
local args = frame.args
local wrap = mw.html.create( 'div' ):addClass( 'bsw-card' )
-- Header
wrap:tag( 'div' ):addClass( 'bsw-card-hd' ):wikitext( 'Wiki statistics' )
local body = wrap:tag( 'div' ):addClass( 'bsw-card-body' )
local grid = body:tag( 'div' ):addClass( 'bsw-stats-grid' )
for i = 1, 6 do
local n = args[ 'n' .. i ] or ''
local label = args[ 'label' .. i ] or ''
if n ~= '' or label ~= '' then
local box = grid:tag( 'div' ):addClass( 'bsw-stat' )
box:tag( 'div' ):addClass( 'bsw-stat-n' ):wikitext( n )
box:tag( 'div' ):addClass( 'bsw-stat-l' ):wikitext( label )
end
end
-- Action links
local links = body:tag( 'div' ):addClass( 'bsw-stat-links' )
for i = 1, 4 do
local url = args[ 'link' .. i .. '_url' ] or ''
local text = args[ 'link' .. i .. '_text' ] or ''
if url ~= '' then
links:tag( 'a' )
:addClass( 'bsw-stat-link' )
:attr( 'href', url )
:wikitext( text ~= '' and text or url )
end
end
return tostring( wrap )
end
-- ── recenttabs() ──────────────────────────────────────────────────
-- Renders the wiki-tab bar for Recent Changes.
-- Tabs are wired to bswSetTab() in Common.js.
function p.recenttabs( frame )
local tabs = { 'All', 'EN', 'DE', 'Media' }
local keys = { 'all', 'en', 'de', 'media' }
local wrap = mw.html.create( 'div' ):addClass( 'bsw-wiki-tabs' )
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
return tostring( wrap )
end
-- ── interwiki() ───────────────────────────────────────────────────
-- Renders the interwiki bar.
-- |1_flag, |1_label, |1_url ... up to 8 entries.
function p.interwiki( frame )
local args = frame.args
local wrap = mw.html.create( 'div' ):addClass( 'bsw-interwiki' )
for i = 1, 8 do
local flag = args[ i .. '_flag' ] or ''
local label = args[ i .. '_label' ] or ''
local url = args[ i .. '_url' ] or ''
if url ~= '' then
local iw = wrap:tag( 'div' ):addClass( 'bsw-iw' )
if flag ~= '' then iw:wikitext( flag .. ' ' ) end
iw:tag( 'a' ):attr( 'href', url ):wikitext( label )
end
end
return tostring( wrap )
end
-- ── featuredloading() ─────────────────────────────────────────────
-- Renders the featured article card shell with loading state.
-- JS replaces the inner content after fetching.
function p.featuredloading( frame )
local wrap = mw.html.create( 'div' ):addClass( 'bsw-card' )
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 →' )
local body = wrap:tag( 'div' ):addClass( 'bsw-card-body' )
local inner = body:tag( 'div' ):attr( 'id', 'bsw-featured-inner' )
local loading = inner:tag( 'div' ):addClass( 'bsw-loading' )
loading:tag( 'div' ):addClass( 'bsw-spinner' ):wikitext( '' )
loading:wikitext( 'Loading today\'s featured article…' )
return tostring( wrap )
end
-- ── photolab() ────────────────────────────────────────────────────
-- Renders the Photo Lab card shell.
-- 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' )
local hd = wrap:tag( 'div' ):addClass( 'bsw-card-hd' )
hd:wikitext( '∞ Photo Lab — Picture of the Day' )
hd:tag( 'a' ):attr( 'href', '/BW:Potd' ):wikitext( 'View project →' )
-- PotD image transcluded as wikitext
wrap:wikitext( content )
-- Nav row
local nav = wrap:tag( 'div' ):addClass( 'bsw-photo-nav' )
nav:tag( 'a' ):attr( 'href', prev_url ):wikitext( prev_lbl )
nav:tag( 'span' ):addClass( 'bsw-photo-caption' ):wikitext( caption )
nav:tag( 'a' ):attr( 'href', next_url ):wikitext( next_lbl )
return tostring( wrap )
end
-- ── tagline() ─────────────────────────────────────────────────────
function p.tagline( frame )
local wrap = mw.html.create( 'div' ):addClass( 'bsw-tagline' )
wrap:wikitext(
"The only original and legitimate '''Battlestar Wiki''' " ..
"— 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
return p