<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3ATimeline_of_release_years%2Fsandbox</id>
	<title>Module:Timeline of release years/sandbox - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://stockhub.co/index.php?action=history&amp;feed=atom&amp;title=Module%3ATimeline_of_release_years%2Fsandbox"/>
	<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Timeline_of_release_years/sandbox&amp;action=history"/>
	<updated>2026-04-11T17:45:50Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://stockhub.co/index.php?title=Module:Timeline_of_release_years/sandbox&amp;diff=147270&amp;oldid=prev</id>
		<title>imported&gt;WOSlinker: use require(&#039;strict&#039;) instead of require(&#039;Module:No globals&#039;)</title>
		<link rel="alternate" type="text/html" href="https://stockhub.co/index.php?title=Module:Timeline_of_release_years/sandbox&amp;diff=147270&amp;oldid=prev"/>
		<updated>2022-10-21T10:03:49Z</updated>

		<summary type="html">&lt;p&gt;use require(&amp;#039;strict&amp;#039;) instead of require(&amp;#039;Module:No globals&amp;#039;)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;require(&amp;#039;strict&amp;#039;)&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
local function items(args, year, oldrange)&lt;br /&gt;
	local itemList = {}&lt;br /&gt;
	&lt;br /&gt;
	-- First loop through is to find the lowest year range, if any. If oldrange is supplied, the year range must also be greater than it.&lt;br /&gt;
	local range = 0;&lt;br /&gt;
	if args[year .. &amp;#039;_to&amp;#039;] or args[year .. &amp;#039;a_to&amp;#039;] then&lt;br /&gt;
		local newrange = tonumber(args[year .. &amp;#039;_to&amp;#039;] or args[year .. &amp;#039;a_to&amp;#039;])&lt;br /&gt;
		if newrange and (oldrange == nil or newrange &amp;gt; oldrange) then&lt;br /&gt;
			range = newrange;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	for asciiletter = 98, 106 do -- 98 &amp;gt; b, 106 &amp;gt; j&lt;br /&gt;
		if args[year .. string.char(asciiletter) .. &amp;#039;_to&amp;#039;] then&lt;br /&gt;
			local newrange = tonumber(args[year .. string.char(asciiletter) .. &amp;#039;_to&amp;#039;])&lt;br /&gt;
			if newrange and (oldrange == nil or newrange &amp;gt; oldrange) and (range == 0 or newrange &amp;lt; range) then&lt;br /&gt;
				range = newrange;&lt;br /&gt;
			end			&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Find items, filtered by range if available.&lt;br /&gt;
	if args[year] or args[year .. &amp;#039;a&amp;#039;] then&lt;br /&gt;
		local thisrange = tonumber(args[year .. &amp;#039;_to&amp;#039;] or args[year .. &amp;#039;a_to&amp;#039;])&lt;br /&gt;
		if (range == 0 and thisrange == nil) or (thisrange and thisrange == range) then&lt;br /&gt;
			table.insert(itemList, args[year] or args[year .. &amp;#039;a&amp;#039;])&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	for asciiletter = 98, 106 do -- 98 &amp;gt; b, 106 &amp;gt; j&lt;br /&gt;
		if args[year .. string.char(asciiletter)] then&lt;br /&gt;
			local thisrange = tonumber(args[year .. string.char(asciiletter) .. &amp;#039;_to&amp;#039;])&lt;br /&gt;
			if (range == 0 and thisrange == nil) or (thisrange and thisrange == range) then&lt;br /&gt;
				table.insert(itemList, args[year .. string.char(asciiletter)])&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return table.maxn(itemList), itemList, range&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function color(args, year, itemNum, to_range)&lt;br /&gt;
&lt;br /&gt;
	if args[year .. &amp;#039;_color&amp;#039;] then&lt;br /&gt;
		return args[year .. &amp;#039;_color&amp;#039;] &lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if to_range and args[year .. &amp;#039;_to_&amp;#039; .. to_range .. &amp;#039;_color&amp;#039;] then&lt;br /&gt;
		return args[year .. &amp;#039;_to_&amp;#039; .. to_range .. &amp;#039;_color&amp;#039;]&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	for yearrange = 1, 10 do&lt;br /&gt;
		if args[&amp;#039;range&amp;#039; .. yearrange] and args[&amp;#039;range&amp;#039; .. yearrange .. &amp;#039;_color&amp;#039;] then&lt;br /&gt;
			local _, _, beginyear, endyear = string.find( args[&amp;#039;range&amp;#039; .. yearrange], &amp;#039;^(%d%d%d%d)%D+(%d%d%d%d)$&amp;#039; )&lt;br /&gt;
&lt;br /&gt;
			local year = tonumber(year) or 9999 -- For year == &amp;#039;TBA&amp;#039;&lt;br /&gt;
			beginyear = tonumber(beginyear) or 0&lt;br /&gt;
			endyear =  tonumber(endyear) or 9999&lt;br /&gt;
&lt;br /&gt;
			if year &amp;gt;= beginyear and year &amp;lt;= endyear then&lt;br /&gt;
				local _, _, color1, color2 = string.find( args[&amp;#039;range&amp;#039; .. yearrange .. &amp;#039;_color&amp;#039;], &amp;#039;^(%S*)%s*(%S*)$&amp;#039; )&lt;br /&gt;
				color2 = string.find(color2, &amp;#039;^#?%w+$&amp;#039;) and color2 or color1&lt;br /&gt;
				return itemNum &amp;gt; 0 and color1 or color2&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return itemNum &amp;gt; 0 and &amp;#039;#0BDA51&amp;#039; or &amp;#039;#228B22&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function left(builder, args, year, itemNum, range)&lt;br /&gt;
	builder = builder:tag(&amp;#039;th&amp;#039;)&lt;br /&gt;
		:attr(&amp;#039;scope&amp;#039;, &amp;#039;row&amp;#039;)&lt;br /&gt;
		:css(&amp;#039;border-right&amp;#039;, &amp;#039;1.4em solid &amp;#039; .. color(args, year, itemNum, range))&lt;br /&gt;
		:wikitext(range ~= 0 and year .. &amp;#039;–&amp;#039; .. range or year)&lt;br /&gt;
	if itemNum &amp;gt; 1 then&lt;br /&gt;
		builder = builder:attr(&amp;#039;rowspan&amp;#039;, itemNum)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function right(builder, itemNum, itemList)&lt;br /&gt;
	if itemNum == 0 then return end&lt;br /&gt;
&lt;br /&gt;
	if itemNum == 1 then&lt;br /&gt;
		builder:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
			:wikitext(itemList[1])&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- if itemNum &amp;gt;= 2&lt;br /&gt;
	builder:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
		:addClass(&amp;#039;rt-first&amp;#039;)&lt;br /&gt;
		:wikitext(itemList[1])&lt;br /&gt;
&lt;br /&gt;
	for key = 2, itemNum - 1 do&lt;br /&gt;
		builder = builder:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
			:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
			:addClass(&amp;#039;rt-next&amp;#039;)&lt;br /&gt;
			:wikitext(itemList[key])&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	builder = builder:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
		:tag(&amp;#039;td&amp;#039;)&lt;br /&gt;
		:addClass(&amp;#039;rt-last&amp;#039;)&lt;br /&gt;
		:wikitext(itemList[itemNum])&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function row(builder, args, year, emptyyear, lastyear, highrange)&lt;br /&gt;
	local oldrange = nil&lt;br /&gt;
	&lt;br /&gt;
	repeat&lt;br /&gt;
		local itemNum, itemList, range = items(args, year, oldrange)&lt;br /&gt;
		&lt;br /&gt;
		-- Now check for a new high range and catch it. We need to know what highrange was prior to update though.&lt;br /&gt;
		local oldhighrange = nil&lt;br /&gt;
		if(range &amp;gt; 0 and (highrange == nil or range &amp;gt; highrange)) then&lt;br /&gt;
			oldhighrange = (highrange or range)&lt;br /&gt;
			highrange = range&lt;br /&gt;
		end&lt;br /&gt;
		oldhighrange = (oldhighrange or highrange)&lt;br /&gt;
&lt;br /&gt;
		-- If compressempty is set, check for empty items, track empty years and high ranges, and&lt;br /&gt;
		-- put out a compressed range when next year is found.&lt;br /&gt;
		if args.compressempty and oldrange == nil then&lt;br /&gt;
			-- If we&amp;#039;re compressing and there&amp;#039;s no items, return this year for tracking.&lt;br /&gt;
			if #itemList &amp;lt; 1 then&lt;br /&gt;
				return year, highrange&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			-- If emptyyear is below or equal the highrange, we need to make adjustments.&lt;br /&gt;
			if(emptyyear and oldhighrange and emptyyear &amp;lt;= oldhighrange) then&lt;br /&gt;
				-- If the current year is highrange or highrange +1, suppress empty row output entirely.&lt;br /&gt;
				-- If the current year is highrange+2 or more, adjust the emptyyear to be above highrange)				&lt;br /&gt;
				if(year &amp;lt;= (oldhighrange+1)) then&lt;br /&gt;
					emptyyear = nil&lt;br /&gt;
				elseif(year &amp;gt; (oldhighrange+1)) then&lt;br /&gt;
					emptyyear = oldhighrange+1&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			-- If we have items but are tracking an empty year, output compressed range row.&lt;br /&gt;
			if emptyyear ~= nil then&lt;br /&gt;
				builder = builder:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
				if year == &amp;#039;TBA&amp;#039; then&lt;br /&gt;
					left(builder, args, emptyyear, 0, lastyear)&lt;br /&gt;
				else&lt;br /&gt;
					if year-1 == emptyyear then&lt;br /&gt;
						left(builder, args, emptyyear, 0, 0)&lt;br /&gt;
					else&lt;br /&gt;
						left(builder, args, emptyyear, 0, year-1)&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		&lt;br /&gt;
		-- We can break out if this is the case. This means we have looped through more than once, but there were no more items remaining.&lt;br /&gt;
		if range == 0 and oldrange and #itemList &amp;lt; 1 then&lt;br /&gt;
			break&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		builder = builder:tag(&amp;#039;tr&amp;#039;)&lt;br /&gt;
		left(builder, args, year, itemNum, range)&lt;br /&gt;
		right(builder, itemNum, itemList)&lt;br /&gt;
&lt;br /&gt;
		if range ~= 0 then&lt;br /&gt;
			oldrange = range&lt;br /&gt;
		end&lt;br /&gt;
	until range == 0&lt;br /&gt;
	&lt;br /&gt;
	return nil, highrange&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main(args)&lt;br /&gt;
	-- Main module code goes here.&lt;br /&gt;
	local currentyear = os.date(&amp;#039;%Y&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
	local ret&lt;br /&gt;
	local firstyear, lastyear&lt;br /&gt;
	local TBA = items(args, &amp;#039;TBA&amp;#039;) &amp;gt; 0 and true or false&lt;br /&gt;
&lt;br /&gt;
	ret = mw.html.create( &amp;#039;table&amp;#039; )&lt;br /&gt;
		:addClass(&amp;#039;release-timeline wikitable&amp;#039;)&lt;br /&gt;
		:addClass(args.align == &amp;#039;left&amp;#039; and &amp;#039;rt-left&amp;#039; or nil)&lt;br /&gt;
&lt;br /&gt;
	ret:tag(&amp;#039;caption&amp;#039;)&lt;br /&gt;
		:wikitext((args.title or &amp;#039;Release timeline&amp;#039;) ..&lt;br /&gt;
			(args.subtitle and (&amp;#039;&amp;lt;div class=&amp;quot;rt-subtitle&amp;quot;&amp;gt;&amp;#039;..args.subtitle..&amp;#039;&amp;lt;/div&amp;gt;&amp;#039;) or &amp;#039;&amp;#039;))&lt;br /&gt;
&lt;br /&gt;
	if tonumber(args.first) then&lt;br /&gt;
		firstyear = tonumber(args.first)&lt;br /&gt;
	else&lt;br /&gt;
		for i = 1, currentyear do&lt;br /&gt;
			if items(args, i) &amp;gt; 0 then&lt;br /&gt;
				firstyear = i&lt;br /&gt;
				break&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		firstyear = firstyear or (currentyear + 3)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if tonumber(args.last) then&lt;br /&gt;
		lastyear = tonumber(args.last)&lt;br /&gt;
	else&lt;br /&gt;
		for i = currentyear + 3, TBA and currentyear or firstyear, -1 do&lt;br /&gt;
			if items(args, i) &amp;gt; 0 then&lt;br /&gt;
				lastyear = i&lt;br /&gt;
				break&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		lastyear = lastyear or (currentyear - 1)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local emptyyear = nil&lt;br /&gt;
	local highrange = nil&lt;br /&gt;
	for year = firstyear, lastyear do&lt;br /&gt;
		local yearcheck, newhighrange = row(ret, args, year, emptyyear, lastyear, highrange)&lt;br /&gt;
		if (emptyyear == nil and yearcheck ~= nil) or (emptyyear ~= nil and yearcheck == nil) then&lt;br /&gt;
			emptyyear = yearcheck&lt;br /&gt;
		end&lt;br /&gt;
		highrange = newhighrange		&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if TBA then&lt;br /&gt;
		row(ret, args, &amp;#039;TBA&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return mw.getCurrentFrame():extensionTag{&lt;br /&gt;
		name = &amp;#039;templatestyles&amp;#039;, args = { src = &amp;#039;Module:Timeline of release years/styles.css&amp;#039;}&lt;br /&gt;
	} .. tostring(ret)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
	local args = require(&amp;#039;Module:Arguments&amp;#039;).getArgs(frame)&lt;br /&gt;
	return p._main(args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>imported&gt;WOSlinker</name></author>
	</entry>
</feed>