Edge Rewrite
// HTMLRewriter · presentation

This page was redesigned at the edge.

Cloudflare fetched the original article and streamed it through HTMLRewriter to apply an entirely new visual system without rebuilding the source page.

Jump to content

Module:Sandbox/Tokoko/Calendar

From Wikipedia, the free encyclopedia
require('strict')

local p = {}
local root = {}

local function addRow(row)
	table.insert(root, row)
end

local function isLeapYear(year)
    return year % 4 == 0 and (year % 100 ~= 0 or year % 400 == 0)
end

local function getDaysInMonth(month, year)
    return month == 2 and isLeapYear(year) and 29
           or ("\31\28\31\30\31\30\31\31\30\31\30\31"):byte(month)
end

local function getMonthNumber(m)
    if tonumber(m) ~= nil then
      return tonumber(m)
    elseif m == "current" then
      return tonumber(os.date("%m"))
    elseif m == "next" then
      return tonumber(os.date("%m")) % 12 + 1
    elseif m == "last" then
      return (tonumber(os.date("%m")) - 2) % 12 + 1
    else
      return 1
    end
end

local function applyDefaultValue(inputValue, defaultValue)
	return (inputValue and inputValue ~= "") and inputValue or defaultValue
end

local function getWeekdays(format)
	if format == "Mon1st" then
		return {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"}
	elseif format == "iso" then
		return {"Wk", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"}
	else
		return {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"}
	end
end

local function getIsoWeekNumber(year, month, day)
	local daysFromStart = os.difftime(os.time{year= year, month=month, day=day}, os.time{year=year, month=1, day=1}) / 86400
	local daysUntilEnd = os.difftime(os.time{year= year + 1, month=1, day=1}, os.time{year=year, month=month, day=day}) / 86400
	local firstWeekday = tonumber(os.date("%w",os.time{year=year, month=month, day=1}))
	local nextFirstWeekday = tonumber(os.date("%w",os.time{year=year+1, month=month, day=1}))
	
	if daysUntilEnd < 4 and nextFirstWeekday >= 4 then return 1 end
	local daysFromFirstMonday = daysFromStart	- (8 - firstWeekday)
	local iso = math.floor(daysFromFirstMonday / 7) + 2 - (firstWeekday > 5 and 1 or 0)
	return iso == 0 and getIsoWeekNumber(year - 1, 12, 26) or iso
end

local function make_link(text, flag, pref, suff)
	return flag and "[[" .. pref .. text .. suff .. "|" .. text .. "]]" or text
end

local function format_date(date)
	return date < 10 and "&nbsp;" .. date or date
end

local function _calendar(frame, _monthNumber, full_mode, float)
	local monthNumber = _monthNumber
	
	local year = tonumber(applyDefaultValue(frame.args.year,os.date("%Y")))
	local month = os.date("%B", os.time{year=year, month=monthNumber, day=1})
	local show_year = applyDefaultValue(frame.args.show_year,"on")
	local format = applyDefaultValue(frame.args.format,"Sun1st") --format = "iso"
	local colspan = (format == "iso" and 8 or 7)
	local prevnext = applyDefaultValue(frame.args.prevnext == "on", false)
	local end_note = applyDefaultValue(frame.args.EndNote, "")
	local colour = frame.args.colour
	local title_colour = applyDefaultValue(colour,frame.args.title_colour)
	local week_colour = applyDefaultValue(colour,frame.args.week_colour)
	local wknum_colour = frame.args.wknum_colour
	local lk = applyDefaultValue(frame.args.lk, "")
	local show_link_year = string.match(lk, "y")
	local show_link_month = string.match(lk, "m")
	local show_link_day = string.match(lk, "d")
	local lk_pref = frame.args.lk_pref
	local lk_suff = frame.args.lk_suff
	local lk_pref_d = applyDefaultValue(lk_pref,frame.args.lk_pref_d)
	local lk_suff_d = applyDefaultValue(lk_suff,frame.args.lk_suff_d)
	local lk_pref_m = applyDefaultValue(lk_pref,frame.args.lk_pref_m)
	local lk_suff_m = applyDefaultValue(lk_suff,frame.args.lk_suff_m)
	local lk_pref_mnext = frame.args.lk_pref_mnext
	local lk_pref_mprev = frame.args.lk_pref_mprev
	local lk_suff_mnext = frame.args.lk_suff_mnext
	local lk_suff_mprev = frame.args.lk_suff_mprev
	if full_mode and show_year == "on" then show_year = "with month" end 
	
	-- calculate helper variables
	local prevMonth = os.date("%B", os.time{year=year, month=(monthNumber - 2) % 12 + 1, day=1})
	local nextMonth = os.date("%B", os.time{year=year, month=monthNumber % 12 + 1, day=1})
	local firstWeekday = tonumber(os.date("%w",os.time{year=year, month=monthNumber, day=1}))
	local daysInMonth = getDaysInMonth(monthNumber, year)

	-- constuct title
	addRow("{| class=\"toccolours " .. float ..  "\" style=\"text-align:center;\" cellpadding=2 cellspacing=0\n")
		
	addRow("|- class=\"navbox-title\"" .. " style=\"background:" .. title_colour .. ";\"\n")
		
	local title_colspan = (prevnext and colspan - 2 or colspan)
	local title = make_link(month .. (show_year == "with month" and " " .. year or ""), show_link_month, lk_pref_m, lk_suff_m)
	local title_row = "|colspan=\"" .. title_colspan .. "\"|'''" .. title .. "'''\n"
	
	if prevnext then
		addRow("|[[" .. lk_pref_mprev .. prevMonth .. lk_suff_mprev .. "|  << ]]\n" .. title_row .. "|[[" .. lk_pref_mnext .. nextMonth .. lk_suff_mnext .. "|  >> ]]\n")
	else 
		addRow(title_row)
	end

	-- construct weekdays
	addRow("|- class=\"navbox-title\"" .. " style=\"background:" .. week_colour .. ";\"\n")
	for i, wd in ipairs(getWeekdays(format)) do
    	addRow("|'''" .. wd .. "'''\n")
	end
	addRow("|-\n")

	-- construct dates
	local daysToMiss = firstWeekday - ((format == "Mon1st" or format == "iso") and 1 or 0)
	local date = - daysToMiss + 1
	local num_rows = full_mode and 6 or math.ceil((daysInMonth + daysToMiss) / 7)
	
	for i = 1, num_rows * colspan do
		local lastColumn = i % colspan == 0
		local firstColumn = i % colspan == 1
		
		if format == "iso" and firstColumn then
			addRow("| class=\"navbox-abovebelow\" style=\"background:" .. wknum_colour .. ";\"|" .. getIsoWeekNumber(year, monthNumber, date) .. "\n")
		elseif date > 0 and date <= daysInMonth then
			addRow("|" .. make_link(format_date(date), show_link_day, lk_pref_d .. month .. " ", lk_suff_d) .. "\n")
			date = date + 1
		else 
			addRow("|&nbsp;\n") 
			date = date + 1
		end
		
		if(lastColumn) then addRow("|-\n") end
	end
	
	if end_note ~= "" then
		addRow("|- class=\"navbox-title\" \n")
		addRow("|colspan=\"" .. colspan .."\"|" .. end_note .. "\n")
	end
	
	if show_year == "on" then
		addRow("|- class=\"navbox-title\"" .. " style=\"background:" .. title_colour .. ";\"\n")
		addRow("|colspan=\"" .. colspan .. "\"|'''" .. make_link(year, show_link_year, "", "") .. "'''\n")
	end
	addRow("|}")
end

function p.main(frame)

	local _month = frame.args.month
	local full_calendar = not (_month and _month ~= "")
	local year = tonumber(applyDefaultValue(frame.args.year,os.date("%Y")))
	
	local title = applyDefaultValue(frame.args.title,"")
	local col = applyDefaultValue(frame.args.col,4)
	local row = frame.args.row
	local float = "float" .. applyDefaultValue(frame.args.float,"left")
	
	if full_calendar then 
		
		addRow("{| class=\"" .. float .. "\" style=none\n")
		addRow("! colspan=" .. col .. " style=\"text-align:center; font-size:larger;\" | " .. title .. " " .. year .. "\n")
			
		for i=1, 12 do 
			if (i - 1) % col == 0 then addRow("|- style=\"vertical-align: top;\"\n") end
			addRow("|\n")
			_calendar(frame, i, true, "")
			addRow("\n")
		end
		
		addRow("|}")
	else 
		_calendar(frame, getMonthNumber(frame.args.month), false, float)	
	end

	--return "<nowiki>" .. table.concat(root) .. "</nowiki> \n" .. 
	return table.concat(root)
end

return p