Jump to content

Module:Calendar TOC/sandbox

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Frietjes (talk | contribs) at 20:24, 22 November 2019. The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
local p = {}

local lang -- Lazy initialize
local function formatDate(fmt, d)
	lang = lang or mw.language.getContentLanguage()
	local success, newDate = pcall(lang.formatDate, lang, fmt, d)
	if success then
		return newDate
	else
		error(string.format(
			"invalid date '%s' passed to getDate",
			tostring(date)
		))
	end
end
	
local function caltoc(founddays, days, footer, month, year)
	local weekdays = {'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'}
	local j = tonumber(formatDate('N','1 ' .. month .. ' ' .. year))
	local N = tonumber(formatDate('t','1 ' .. month .. ' ' .. year))
	local toptext1 = [[__NOTOC__<table role="navigation" id="toc" class="wikitable toc plainlinks" style="text-align:center">
<tr><th colspan=7 id="toctitle"><span id="tocheading" style="font-weight:bold">]]
	local toptext2 = [[</th></tr>]]
	local res = {toptext1 .. month .. ' ' .. year .. toptext2}
    table.insert(res, '<tr><th scope="col">' .. table.concat(weekdays, '</th><th scope="col">') .. '</th></tr>')
    local d = 1-j
    while d <= N do
    	table.insert(res, '<tr>')
    	for i=1,7 do
    		d = d + 1
    		if d > 0 and d <= N then
    			local f = days[tostring(d)]
    			if f and f == 'df' then
    				table.insert(res, '<td>[[#' .. d .. ' ' .. month .. '|' .. d .. ']]</td>')
    			elseif f and f == 'mf' then
    				table.insert(res, '<td>[[#' .. month .. ' ' .. d .. '|' .. d .. ']]</td>')
    			else
    				table.insert(res, '<td>' .. d .. '</td>')
    			end
    		else
    			table.insert(res, '<td></td>')
    		end
    	end
    	table.insert(res, '</tr>')
    end
    local entries = {}
    for k,v in ipairs(footer) do
		table.insert(entries, '* [[#' .. v .. '|' .. v .. ']]')
	end
	if #entries > 0 then
		table.insert(res, '<tr><td colspan=7><div class="hlist">')
		table.insert(res, table.concat(entries, '\n'))
		table.insert(res, '</div>')
		table.insert(res, '</td></tr>')
	end
	table.insert(res, '</table>')

	return table.concat(res, '\n') .. table.concat(footer, '\n')
end

local function listtoc(founddays, days, footer, month)
	local starttxt = [[
__NOTOC__<!--
--><div role="navigation" id="toc" class="toc plainlinks hlist" aria-labelledby="tocheading" style="text-align:left;">
<div id="toctitle" class="toctitle" style="text-align:center;"><span id="tocheading" style="font-weight:bold;">Contents</span></div>
<div style="margin:auto;white-space:nowrap;">
]]
	local closetxt = [[</div></div>]]
	local entries = { ';' .. month}
	for k,d in ipairs(founddays) do
		local fmt = days[d] 
		if fmt == 'df' then
			table.insert(entries, ': [[#' .. d .. ' ' .. month .. '|' .. d .. ']]')
		elseif fmt == 'mf' then
			table.insert(entries, ': [[#' .. month .. ' ' .. d .. '|' .. d .. ']]')
		end
	end
	for k,v in ipairs(footer) do
		table.insert(entries, ': [[#' .. v .. '|' .. v .. ']]')
	end
	return starttxt .. table.concat(entries,"\n") .. closetxt
end

local function getYear(s,y)
	if y and mw.ustring.match(y, '^%d+$') then
		return y
	end
	y = mw.ustring.gsub(s, '^.-(%d+).-$', '%1')
	return y
end

local function getMonth(s,m)
	local mnames = {
		['January']=1,
		['February']=2, 
		['March']=3,
		['April']=4,
		['May']=5,
		['June']=6,
		['July']=7,
		['August']=8,
		['September']=9,
		['October']=10,
		['November']=11,
		['December']=12
	}
	if m and mnames[m] then
		return m
	end
	
	for k,n in pairs(mnames) do
		if mw.ustring.match(s or '', k) then
			return k
		end
	end
	
	return ''
end

function p.main(frame)
	local current_title = mw.title.getCurrentTitle()
	local pagename = current_title.text
	local content = current_title:getContent()
	local args = frame.args
	local pargs = frame:getParent().args
	local outfmt = args['format'] or pargs['format'] or ''
	
	if not content then
		error "The current page has no content"
	end

	-- Get the month and year	
	local month = getMonth(pagename, args['month'] or pargs['month'] or '')
	local year = getYear(pagename, args['year'] or pargs['year'] or '')

	-- Get list of valid footer links	
	local extra = args['extra'] or pargs['extra'] or ''
	local footerlinks = {}
	if extra ~= '' then
		footerlinks = mw.text.split(extra, '%s*=%s*')
	else
		footerlinks = {"Unknown date", "See also", "References", "Notes", "Further reading", "External links"}
	end
	local validfooter = {}
	for k,v in ipairs(footerlinks) do
		validfooter[v] = 1
	end
	
	-- Get all the level two headings for days of the month
	local days = {}
	local founddays = {}
	local footer = {}
	for v in mw.ustring.gmatch(content, "%f[^\n]==%s*([^\r\n]-)%s*==%f[^=]") do
		v = mw.ustring.gsub(v,'^[=%s]*(.-)[%s=]*', '%1')
		local df = mw.ustring.gsub(v,'^(%d+[%-–%d]*)%s*' .. month .. '$', '%1')
		local mf = mw.ustring.gsub(v,'^' .. month .. '%s*(%d+[%-–%d]*)$', '%1')
		if df then
			days[df] = 'df'
			table.insert(founddays, df)
		elseif mf then
			days[df] = 'mf'
			table.insert(founddays, mf)
		elseif validfooter[v] then
			table.insert(footer, v)
		end
	end

	-- Now generate the TOC
	if outfmt == 'cal' then
		return caltoc(founddays, days, footer, month, year)
	end

	return listtoc(founddays, days, footer, month)
end

return p