Module:Calendar

From Angelina Jordan Wiki
Revision as of 21:11, 27 September 2025 by Most2dot0 (talk | contribs) (bugfix)

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("&","&amp;"):gsub('"',"&quot;"):gsub("<","&lt;"):gsub(">","&gt;")
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=."
    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"

    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) -- correct ordering

    local out = {}

    -- query Cargo (if available)
    local function extractDay(dateStr)
        if not dateStr then return nil end
        local y, m, d = tostring(dateStr):match("^(%d%d%d%d)%-(%d%d)%-(%d%d)")
        if d then return tonumber(d) end
        return nil
    end

    local events = {}
    if mw and mw.ext and mw.ext.cargo and mw.ext.cargo.query then
        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, dateField .. "," .. urlField, { where = where, limit = 1000 })
        if ok and results then
            for _, row in ipairs(results) do
                local dateVal = row[dateField] or row[1]
                local linkVal = row[urlField]  or row[2]
                local di = extractDay(dateVal)
				table.insert(out, string.format("|- \n| %s || %s", dateVal or "nil", linkVal or "nil"))                end
--                if di and linkVal then
--                    events[di] = events[di] or {}
--                    table.insert(events[di], tostring(linkVal))
--            end
        end
    end

    -- build calendar rows safely (cells per row)
    table.insert(out, '{| class="wikitable calendar" style="text-align:center;"')
    table.insert(out, '!Sun !!Mon !!Tue !!Wed !!Thu !!Fri !!Sat')

    local day = 1
    while day <= daysInMonth do
        local cells = {}
        for col = 1, 7 do
            if day == 1 and col < firstWday then
                table.insert(cells, " ")
            elseif day <= daysInMonth then
                if events[day] and #events[day] > 0 then
                    local firstLink = events[day][1]
                    local tip = escAttr(table.concat(events[day], ", "))
                    -- put attributes before the cell content
                    table.insert(cells, string.format('style="color:red;" | [[%s|%d]]', firstLink, day))
                else
                    table.insert(cells, tostring(day))
                end
                day = day + 1
            else
                table.insert(cells, " ")
            end
        end
        table.insert(out, "|-")
        table.insert(out, "| " .. table.concat(cells, " || "))
    end

    table.insert(out, "|}")
    return table.concat(out, "\n")
end

return p