Module:Current events calendar

-- This module renders the calendar seen on Portal:Current events.

--[[

Incoming expected variables:

frame.args.year = Integer value for year

frame.args.month = Integer value for month, 1 based.

--]]

local p = {}

local function makeWikilink(link, display)

if display then

return string.format('%s', link, display)

else

return string.format('%s', link)

end

end

local function getDateStuff(argsDate)

--[[

Note: This function takes advantage of the formatDate's second argument to

create data for the archival calendars. If the second arg (argsDate) is nil,

then formatDate assumes the current date/time.

--]]

local lang = mw.language.getContentLanguage()

local firstOfMonth = lang:formatDate('01-m-Y', argsDate)

return {

argsDate = argsDate,

year = tonumber(lang:formatDate('Y', argsDate)),

month = lang:formatDate('F', argsDate),

monthAndYear = lang:formatDate('F Y', argsDate),

previousMonthAndYear = lang:formatDate('F Y', firstOfMonth .. ' -1 month'),

nextMonthAndYear = lang:formatDate('F Y', firstOfMonth .. ' +1 month'),

day = tonumber(lang:formatDate('j', argsDate)),

daysInMonth = tonumber(lang:formatDate('j', firstOfMonth .. ' +1 month -1 day')),

-- Weekday of the first day of the month

-- Make compatible with Lua tables so we add 1. Sunday = 1, Saturday = 7.

firstWeekday = tonumber(lang:formatDate('w', firstOfMonth)) + 1

}

end

local function isLinkworthy(day, currentDay)

-- Returns true if the calendar day should be linked, and false if not. Days

-- should be linked if they are the current day or if they are within the six

-- preceding days, as that is the number of items on the current events page.

return currentDay - 6 <= day and day <= currentDay

end

local function makeDayStrings(dateStuff)

local calStrings = {}

local currentDay = dateStuff.day

local currentMonth = dateStuff.month

local currentYear = dateStuff.year

for day = 1, dateStuff.daysInMonth do

if dateStuff.argsDate or isLinkworthy(day, currentDay) then

table.insert(calStrings, string.format(

"%d",

currentYear,

currentMonth,

day,

day

))

else

table.insert(calStrings, tostring(day))

end

end

return calStrings

end

local function export(dayStrings, dateStuff)

-- Generates the calendar HTML.

local monthAndYear = dateStuff.monthAndYear

local root = mw.html.create('table')

root

:addClass('current-events-calendar')

-- Make the table-layout-based Archive pages look good. When the Archives

-- have been converted to a grid-based layout, this logic can be removed,

-- and the corressponding CSS margin attribute can be simplified.

:addClass(dateStuff.argsDate and 'current-events-calendar-archive')

-- Headings

:tag('caption')

:tag('span')

:addClass('noprint')

:wikitext(makeWikilink(

'Portal:Current events/' .. dateStuff.previousMonthAndYear,

'◀'

))

:done()

:tag('span')

:wikitext(makeWikilink(

'Portal:Current events/' .. monthAndYear,

monthAndYear

))

:done()

:tag('span')

:addClass('noprint')

:wikitext(makeWikilink(

'Portal:Current events/' .. dateStuff.nextMonthAndYear,

'▶'

))

-- Day of week headings

local dayHeadingRow = root:tag('tr')

local weekdays = {'S', 'M', 'T', 'W', 'T', 'F', 'S'}

for _, weekday in ipairs(weekdays) do

dayHeadingRow:tag('th'):wikitext(weekday)

end

-- Days

-- Tracks the number of day cells. Negative values used for initial blank cells.

local cellCount = 1 - dateStuff.firstWeekday

while cellCount < #dayStrings do -- Weekly rows

local weeklyRow = root:tag('tr')

for i = 1, 7 do -- Always make 7 cells.

cellCount = cellCount + 1

-- Use a blank cell if there is no corresponding dateString

local dayString = dayStrings[cellCount] or ''

weeklyRow:tag('td'):wikitext(dayString)

end

end

-- Footer

if not dateStuff.argsDate then -- No footer necessary on Archive pages.

root:tag('tr')

:addClass('current-events-calendar-footer')

:addClass('noprint')

:tag('td')

:attr('colspan', '7')

:wikitext(makeWikilink(

'Portal:Current events/' .. monthAndYear,

'More ' .. monthAndYear .. ' events...   '

))

end

return tostring(root)

end

function p.main(frame)

local argsDate = nil

if frame and frame.args and frame.args.year and frame.args.month then

-- If a date is passed in, assume that the display page is an Archive page.

-- If no date passed in, assume that the display page is the current Current Events page

-- Construct a date, YYY-M-DD format.

argsDate = frame.args.year .. "-" .. frame.args.month .. "-01"

end

local dateStuff = getDateStuff(argsDate)

return frame:extensionTag{

name = 'templatestyles',

args = { src = 'Module:Current events calendar/styles.css' }

} .. export(makeDayStrings(dateStuff), dateStuff)

end

return p