Module:Calendar
From Angelina Jordan Wiki
Documentation for this module may be created at Module:Calendar/doc
local p = {}
local function trim(s)
if not s then return nil end
return (tostring(s):gsub("^%s*(.-)%s*$", "%1"))
end
local function escAttr(s)
if not s then return "" end
return tostring(s):gsub("&", "&"):gsub('"', """):gsub("<", "<"):gsub(">", ">")
end
function p.month(frame)
local args = frame.args or (frame.getParent and frame:getParent().args) or {}
local year = tonumber(trim(args.year))
local month = tonumber(trim(args.month))
if not year or not month then
return "Error: module requires numeric |year= and |month= parameters."
end
if month < 1 or month > 12 then
return "Error: |month must be between 1 and 12."
end
local tableName = trim(args.table) or "DatedEvents"
local dateField = trim(args.datefield) or "Date"
local urlField = trim(args.urlfield) or "Link"
-- month bounds
local daysInMonth = tonumber(os.date("*t", os.time{year=year, month=month+1, day=0}).day)
local firstWday = tonumber(os.date("*t", os.time{year=year, month=month, day=1}).wday) -- 1 = Sunday
-- Cargo check
if not (mw and mw.ext and mw.ext.cargo and mw.ext.cargo.query) then
return "Error: Cargo extension is not available."
end
local fields = dateField .. "," .. urlField
local startDate = string.format("%04d-%02d-01", year, month)
local endDate = string.format("%04d-%02d-%02d", year, month, daysInMonth)
local where = string.format("%s >= '%s' AND %s <= '%s'", dateField, startDate, dateField, endDate)
local ok, results = pcall(mw.ext.cargo.query, tableName, fields, { where = where, limit = 1000 })
if not ok then
return "Error querying Cargo: " .. tostring(results)
end
results = results or {}
-- map events by day (allow multiple entries per day)
local events = {}
for _, row in ipairs(results) do
local dateVal = row[dateField] or row[1]
local linkVal = row[urlField] or row[2]
if dateVal and linkVal then
local y, m, d = tostring(dateVal):match("(%d%d%d%d)%-(%d%d)%-(%d%d)")
if d then
local dnum = tonumber(d)
if dnum then
events[dnum] = events[dnum] or {}
table.insert(events[dnum], tostring(linkVal))
end
end
end
end
-- build table
local out = {}
table.insert(out, '{| class="wikitable calendar" style="text-align:center;"')
table.insert(out, '!Sun !!Mon !!Tue !!Wed !!Thu !!Fri !!Sat')
local day, col = 1, 1
table.insert(out, '|-')
-- leading empty cells
for i = 1, firstWday - 1 do
table.insert(out, '| ')
if i < 7 then table.insert(out, '||') end
col = col + 1
end
while day <= daysInMonth do
if col > 7 then
table.insert(out, '\n|-')
col = 1
end
if events[day] and #events[day] > 0 then
local firstLink = trim(events[day][1])
local tip = escAttr(table.concat(events[day], ", "))
local cell = string.format(' style="color:red;" | <span title="%s">[[%s|%d]]</span>', tip, firstLink, day)
table.insert(out, '|' .. cell)
else
table.insert(out, '|' .. day)
end
if col < 7 then table.insert(out, '||') end
day = day + 1
col = col + 1
end
-- trailing empty cells
while col <= 7 do
table.insert(out, '| ')
if col < 7 then table.insert(out, '||') end
col = col + 1
end
table.insert(out, '\n|}')
return table.concat(out, ' ')
end
return p