Module:Portal: Difference between revisions
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
Created page with "-- Module:Portal -- Provides dynamic portal widgets for BattlestarWiki: -- stats bar, newest page, random image, colonial calendar -- -- Usage (from Template:Portal/Layout): -- {{#invoke:Portal|stats|category=Characters (RDM)|episodes=73|characters=62|seasons=4|year=2003}} -- {{#invoke:Portal|newestPage|category=Characters (RDM)}} -- {{#invoke:Portal|randomImage|category=Images (RDM)}} -- {{#invoke:Portal|colonialCalendar|category=RDM}} local p = {} local mwTi..." |
No edit summary |
||
| Line 1: | Line 1: | ||
-- Module:Portal | -- Module:Portal | ||
-- Provides | -- Provides server-side portal widgets for BattlestarWiki. | ||
-- | -- | ||
-- | -- Functions: | ||
-- | -- colonialCalendar — "On this day in BSG" sidebar widget | ||
-- | -- relatedPortals — related-portals tile grid | ||
-- | -- | ||
-- | -- NOTE: stats, newest article, and image carousel are handled | ||
-- entirely by the portal JS in MediaWiki:Common.js, not Lua. | |||
-- The JS reads data-category / data-listpage attributes set by | |||
-- Template:Portal/Layout and makes live API calls. | |||
local p = {} | local p = {} | ||
local mwHtml = mw.html | |||
local mwHtml | |||
local mwUstring = mw.ustring | local mwUstring = mw.ustring | ||
| Line 19: | Line 19: | ||
------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ||
local function trim( s ) | |||
local function trim(s) | return s and mwUstring.match( s, '^%s*(.-)%s*$' ) or '' | ||
return s and mwUstring.match(s, '^%s*(.-)%s*$') or '' | |||
end | end | ||
local function arg( args, key, default ) | |||
local function arg(args, key, default) | |||
local v = args[key] | local v = args[key] | ||
return (v and trim(v) ~= '') and trim(v) or default | return ( v and trim( v ) ~= '' ) and trim( v ) or default | ||
end | end | ||
------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ||
-- Colonial Calendar | -- Colonial Calendar | ||
-- Keyed | -- Keyed "M-D" (no zero-padding) → list of {year, text} | ||
-- Covers real-world broadcast dates | -- Covers real-world BSG broadcast dates. | ||
-- | -- To extend: add entries here, or extract to Module:Portal/Calendar | ||
-- (see DEPLOYMENT.md) so non-Lua editors can add dates directly. | |||
------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ||
local CALENDAR = { | local CALENDAR = { | ||
['1-14'] = { | ['1-14'] = { | ||
{ year='2005', text='[[33 (episode)|33]] premieres on Sci Fi Channel — | { year = '2005', text = '[[33 (episode)|33]] premieres on Sci Fi Channel — first regular RDM episode' }, | ||
}, | }, | ||
['1-21'] = { | ['1-21'] = { | ||
{ year='2005', text='[[Water (episode)|Water]] airs on Sci Fi Channel | { year = '2005', text = '[[Water (episode)|Water]] airs on Sci Fi Channel' }, | ||
}, | }, | ||
['3-4'] = { | ['3-4'] = { | ||
{ year='2005', text='[[Tigh Me Up, Tigh Me Down]] airs on Sky One (UK) | { year = '2005', text = '[[Tigh Me Up, Tigh Me Down]] airs on Sky One (UK)' }, | ||
}, | }, | ||
['3-18'] = { | ['3-18'] = { | ||
{ year='2005', text='[[Colonial Day]] airs on Sky One | { year = '2005', text = '[[Colonial Day]] airs on Sky One' }, | ||
}, | }, | ||
['3-20'] = { | ['3-20'] = { | ||
{ year='2009', text='[[Daybreak, Part II|Daybreak]] finale airs — end of the Re-imagined Series | { year = '2009', text = '[[Daybreak, Part II|Daybreak]] finale airs — end of the Re-imagined Series' }, | ||
}, | }, | ||
['4-1'] = { | ['4-1'] = { | ||
{ year='2005', text= | { year = '2005', text = "[[Kobol's Last Gleaming, Part II]] airs — Season 1 finale" }, | ||
}, | }, | ||
['4-12'] = { | ['4-12'] = { | ||
{ year='2007', text='[[The Woman King]] airs on Sci Fi Channel | { year = '2007', text = '[[The Woman King]] airs on Sci Fi Channel' }, | ||
{ year='2009', text='[[Islanded in a Stream of Stars]] airs — three episodes remain | { year = '2009', text = '[[Islanded in a Stream of Stars]] airs — three episodes remain' }, | ||
}, | }, | ||
['6-3'] = { | ['6-3'] = { | ||
{ year='2005', text='[[Scattered]] airs — Season 2 premiere | { year = '2005', text = '[[Scattered]] airs — Season 2 premiere' }, | ||
}, | }, | ||
['9-22'] = { | ['9-22'] = { | ||
{ year='2006', text='[[Occupation]]/[[Precipice]] two-hour Season 3 premiere airs | { year = '2006', text = '[[Occupation]]/[[Precipice]] two-hour Season 3 premiere airs' }, | ||
}, | }, | ||
['10-6'] = { | ['10-6'] = { | ||
{ year='2006', text='[[Exodus, Part II]] airs — fan-favourite | { year = '2006', text = '[[Exodus, Part II]] airs — fan-favourite Galactica dive sequence' }, | ||
}, | }, | ||
['12-8'] = { | ['12-8'] = { | ||
{ year='2003', text='[[Miniseries, Night 1|BSG Miniseries]] premieres on Sci Fi Channel | { year = '2003', text = '[[Miniseries, Night 1|BSG Miniseries]] premieres on Sci Fi Channel' }, | ||
}, | }, | ||
} | } | ||
local function todayKey() | local function todayKey() | ||
local | local frame = mw.getCurrentFrame() | ||
local d = tonumber( | local m = tonumber( frame:callParserFunction( '#time', 'n' ) ) | ||
local d = tonumber( frame:callParserFunction( '#time', 'j' ) ) | |||
return m .. '-' .. d | return m .. '-' .. d | ||
end | end | ||
function p.colonialCalendar( frame ) | |||
function p.colonialCalendar(frame) | |||
local key = todayKey() | local key = todayKey() | ||
local events = CALENDAR[key] | local events = CALENDAR[key] | ||
local dateDisplay = mw.getCurrentFrame():callParserFunction( '#time', 'F j' ) | |||
local dateDisplay = mw.getCurrentFrame():callParserFunction('#time', 'F j' | |||
local | local root = mwHtml.create( 'div' ):addClass( 'portal-calendar' ) | ||
:wikitext('Real-world BSG broadcast history') | root:tag( 'div' ):addClass( 'portal-calendar-date' ):wikitext( dateDisplay ) | ||
root:tag( 'div' ):addClass( 'portal-calendar-sub' ) | |||
:wikitext( 'Real-world BSG broadcast history' ) | |||
if events and #events > 0 then | if events and #events > 0 then | ||
local list = root:tag('ul'):addClass('portal-calendar-events') | local list = root:tag( 'ul' ):addClass( 'portal-calendar-events' ) | ||
for _, ev in ipairs(events) do | for _, ev in ipairs( events ) do | ||
list:tag('li'):addClass('portal-calendar-event') | list:tag( 'li' ):addClass( 'portal-calendar-event' ) | ||
:tag('span'):addClass('portal-calendar-year'):wikitext(ev.year):done() | :tag( 'span' ):addClass( 'portal-calendar-year' ):wikitext( ev.year ):done() | ||
:wikitext(' | :wikitext( ' \xe2\x80\x94 ' .. ev.text ) | ||
end | end | ||
else | else | ||
root:tag('div'):addClass('portal-calendar-none') | root:tag( 'div' ):addClass( 'portal-calendar-none' ) | ||
:wikitext('<small>No recorded BSG events on this date.</small>') | :wikitext( '<small>No recorded BSG events on this date.</small>' ) | ||
end | end | ||
return frame:preprocess(tostring(root)) | return frame:preprocess( tostring( root ) ) | ||
end | end | ||
------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ||
-- | -- Related Portals | ||
-- Args: type | -- Args: | ||
-- | -- type "series" (default) or "topic" | ||
-- exclude Full page title to hide (this portal itself) | |||
------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ||
local SERIES_PORTALS = { | local SERIES_PORTALS = { | ||
{ title = 'Portal:Battlestar Galactica (TOS)', label = 'Original Series', sub = 'TOS | { title = 'Portal:Battlestar Galactica (TOS)', label = 'Original Series', sub = 'TOS · 1978' }, | ||
{ title = 'Portal:Galactica 1980', label = 'Galactica 1980', sub = '1980' }, | { title = 'Portal:Galactica 1980', label = 'Galactica 1980', sub = '1980' }, | ||
{ title = 'Portal:Battlestar Galactica (RDM)', label = 'Re-imagined Series', sub = 'RDM | { title = 'Portal:Battlestar Galactica (RDM)', label = 'Re-imagined Series', sub = 'RDM · 2003–2009' }, | ||
{ title = 'Portal:Caprica', label = 'Caprica', sub = 'Prequel | { title = 'Portal:Caprica', label = 'Caprica', sub = 'Prequel · 2010–2011' }, | ||
{ title = 'Portal:Blood and Chrome', label = 'Blood & Chrome', sub = 'Prequel | { title = 'Portal:Blood and Chrome', label = 'Blood & Chrome', sub = 'Prequel · 2012' }, | ||
} | } | ||
local TOPIC_PORTALS = { | local TOPIC_PORTALS = { | ||
{ title = 'Portal:Characters', label = 'Characters', sub = 'All series' }, | { title = 'Portal:Characters', label = 'Characters', sub = 'All series' }, | ||
{ title = 'Portal:Ships', | { title = 'Portal:Ships', label = 'Ships', sub = 'All series' }, | ||
{ title = 'Portal:Cylons', | { title = 'Portal:Cylons', label = 'Cylons', sub = 'All series' }, | ||
{ title = 'Portal:Episodes', | { title = 'Portal:Episodes', label = 'Episodes', sub = 'All series' }, | ||
{ title = 'Portal:Merchandise',label = 'Merchandise',sub = 'All series' }, | { title = 'Portal:Merchandise', label = 'Merchandise', sub = 'All series' }, | ||
} | } | ||
function p.relatedPortals(frame) | function p.relatedPortals( frame ) | ||
local args = frame:getParent().args | local args = frame:getParent().args | ||
local exclude = arg( args, 'exclude', '' ) | |||
local exclude = arg(args, 'exclude', '') | |||
local combined = {} | local combined = {} | ||
for _, v in ipairs(SERIES_PORTALS) do combined[#combined+1] = v end | for _, v in ipairs( SERIES_PORTALS ) do combined[#combined + 1] = v end | ||
for _, v in ipairs(TOPIC_PORTALS) | for _, v in ipairs( TOPIC_PORTALS ) do combined[#combined + 1] = v end | ||
local root = mwHtml.create('div'):addClass('portal-related-grid') | local root = mwHtml.create( 'div' ):addClass( 'portal-related-grid' ) | ||
for _, portal in ipairs(combined) do | for _, portal in ipairs( combined ) do | ||
if portal.title ~= exclude then | if portal.title ~= exclude then | ||
root:tag('div'):addClass('portal-related-tile') | root:tag( 'div' ):addClass( 'portal-related-tile' ) | ||
:tag('div'):addClass('portal-related-title') | :tag( 'div' ):addClass( 'portal-related-title' ) | ||
:wikitext('[[' .. portal.title .. '|' .. portal.label .. ']]'):done() | :wikitext( '[[' .. portal.title .. '|' .. portal.label .. ']]' ):done() | ||
:tag('div'):addClass('portal-related-sub') | :tag( 'div' ):addClass( 'portal-related-sub' ) | ||
:wikitext(portal.sub) | :wikitext( portal.sub ) | ||
end | end | ||
end | end | ||
return tostring(root) | return tostring( root ) | ||
end | end | ||
return p | return p | ||
Revision as of 20:35, 13 April 2026
Documentation for this module may be created at Module:Portal/doc
-- Module:Portal
-- Provides server-side portal widgets for BattlestarWiki.
--
-- Functions:
-- colonialCalendar — "On this day in BSG" sidebar widget
-- relatedPortals — related-portals tile grid
--
-- NOTE: stats, newest article, and image carousel are handled
-- entirely by the portal JS in MediaWiki:Common.js, not Lua.
-- The JS reads data-category / data-listpage attributes set by
-- Template:Portal/Layout and makes live API calls.
local p = {}
local mwHtml = mw.html
local mwUstring = mw.ustring
------------------------------------------------------------------------
-- Helpers
------------------------------------------------------------------------
local function trim( s )
return s and mwUstring.match( s, '^%s*(.-)%s*$' ) or ''
end
local function arg( args, key, default )
local v = args[key]
return ( v and trim( v ) ~= '' ) and trim( v ) or default
end
------------------------------------------------------------------------
-- Colonial Calendar
-- Keyed "M-D" (no zero-padding) → list of {year, text}
-- Covers real-world BSG broadcast dates.
-- To extend: add entries here, or extract to Module:Portal/Calendar
-- (see DEPLOYMENT.md) so non-Lua editors can add dates directly.
------------------------------------------------------------------------
local CALENDAR = {
['1-14'] = {
{ year = '2005', text = '[[33 (episode)|33]] premieres on Sci Fi Channel — first regular RDM episode' },
},
['1-21'] = {
{ year = '2005', text = '[[Water (episode)|Water]] airs on Sci Fi Channel' },
},
['3-4'] = {
{ year = '2005', text = '[[Tigh Me Up, Tigh Me Down]] airs on Sky One (UK)' },
},
['3-18'] = {
{ year = '2005', text = '[[Colonial Day]] airs on Sky One' },
},
['3-20'] = {
{ year = '2009', text = '[[Daybreak, Part II|Daybreak]] finale airs — end of the Re-imagined Series' },
},
['4-1'] = {
{ year = '2005', text = "[[Kobol's Last Gleaming, Part II]] airs — Season 1 finale" },
},
['4-12'] = {
{ year = '2007', text = '[[The Woman King]] airs on Sci Fi Channel' },
{ year = '2009', text = '[[Islanded in a Stream of Stars]] airs — three episodes remain' },
},
['6-3'] = {
{ year = '2005', text = '[[Scattered]] airs — Season 2 premiere' },
},
['9-22'] = {
{ year = '2006', text = '[[Occupation]]/[[Precipice]] two-hour Season 3 premiere airs' },
},
['10-6'] = {
{ year = '2006', text = '[[Exodus, Part II]] airs — fan-favourite Galactica dive sequence' },
},
['12-8'] = {
{ year = '2003', text = '[[Miniseries, Night 1|BSG Miniseries]] premieres on Sci Fi Channel' },
},
}
local function todayKey()
local frame = mw.getCurrentFrame()
local m = tonumber( frame:callParserFunction( '#time', 'n' ) )
local d = tonumber( frame:callParserFunction( '#time', 'j' ) )
return m .. '-' .. d
end
function p.colonialCalendar( frame )
local key = todayKey()
local events = CALENDAR[key]
local dateDisplay = mw.getCurrentFrame():callParserFunction( '#time', 'F j' )
local root = mwHtml.create( 'div' ):addClass( 'portal-calendar' )
root:tag( 'div' ):addClass( 'portal-calendar-date' ):wikitext( dateDisplay )
root:tag( 'div' ):addClass( 'portal-calendar-sub' )
:wikitext( 'Real-world BSG broadcast history' )
if events and #events > 0 then
local list = root:tag( 'ul' ):addClass( 'portal-calendar-events' )
for _, ev in ipairs( events ) do
list:tag( 'li' ):addClass( 'portal-calendar-event' )
:tag( 'span' ):addClass( 'portal-calendar-year' ):wikitext( ev.year ):done()
:wikitext( ' \xe2\x80\x94 ' .. ev.text )
end
else
root:tag( 'div' ):addClass( 'portal-calendar-none' )
:wikitext( '<small>No recorded BSG events on this date.</small>' )
end
return frame:preprocess( tostring( root ) )
end
------------------------------------------------------------------------
-- Related Portals
-- Args:
-- type "series" (default) or "topic"
-- exclude Full page title to hide (this portal itself)
------------------------------------------------------------------------
local SERIES_PORTALS = {
{ title = 'Portal:Battlestar Galactica (TOS)', label = 'Original Series', sub = 'TOS · 1978' },
{ title = 'Portal:Galactica 1980', label = 'Galactica 1980', sub = '1980' },
{ title = 'Portal:Battlestar Galactica (RDM)', label = 'Re-imagined Series', sub = 'RDM · 2003–2009' },
{ title = 'Portal:Caprica', label = 'Caprica', sub = 'Prequel · 2010–2011' },
{ title = 'Portal:Blood and Chrome', label = 'Blood & Chrome', sub = 'Prequel · 2012' },
}
local TOPIC_PORTALS = {
{ title = 'Portal:Characters', label = 'Characters', sub = 'All series' },
{ title = 'Portal:Ships', label = 'Ships', sub = 'All series' },
{ title = 'Portal:Cylons', label = 'Cylons', sub = 'All series' },
{ title = 'Portal:Episodes', label = 'Episodes', sub = 'All series' },
{ title = 'Portal:Merchandise', label = 'Merchandise', sub = 'All series' },
}
function p.relatedPortals( frame )
local args = frame:getParent().args
local exclude = arg( args, 'exclude', '' )
local combined = {}
for _, v in ipairs( SERIES_PORTALS ) do combined[#combined + 1] = v end
for _, v in ipairs( TOPIC_PORTALS ) do combined[#combined + 1] = v end
local root = mwHtml.create( 'div' ):addClass( 'portal-related-grid' )
for _, portal in ipairs( combined ) do
if portal.title ~= exclude then
root:tag( 'div' ):addClass( 'portal-related-tile' )
:tag( 'div' ):addClass( 'portal-related-title' )
:wikitext( '[[' .. portal.title .. '|' .. portal.label .. ']]' ):done()
:tag( 'div' ):addClass( 'portal-related-sub' )
:wikitext( portal.sub )
end
end
return tostring( root )
end
return p