require('Module:No globals')  local yesno = require('Module:Yesno') local navbox = require('Module:Navbox')._navbox local getArgs = require('Module:Arguments').getArgs local convert = require('মডিউল:সংখ্যা রূপান্তরকারী').convert local p = {}  -- Add a blank table cell local function addBlank(args, row, prev, current) 	if row and prev < current then 		if yesno(args.decades) == false then 			row:tag('td') 				:addClass('timeline-blank') 				:cssText(args.blankstyle) 				:attr('colspan', current - prev) 		-- Divide the cell up every decade if showing decades at the top 		else 			local year = prev 			 			while year < current do 				local dur = math.min(10 - year % 10, current - year) 				 				row:tag('td') 					:addClass('timeline-blank') 					:cssText(args.blankstyle) 					:attr('colspan', dur) 				 				year = year + dur 			end 		end 	end end  -- Get timeline entries, start years, and end years local function timelineInfo(args) 	local info = { 		startYear = math.huge, 		startYears = {}, 		endYear = 0, 		endYears = {}, 		entries = {} 	} 	 	for k, _ in pairs(args) do 		if type(k) == 'string' then 			local num = k:match('^%a+(%d+)$')  			if num then 				table.insert(info.entries, tonumber(num)) 			end 		end 	end 	 	table.sort(info.entries) 	 	for i, num in ipairs(info.entries) do  		if args['item' .. i] then 			if not args['date' .. i] then 				error('item' .. i .. ' requires a corresponding ' .. 'date' .. i, 0) 			end 			 			local dates = mw.text.split(args['date' .. i], '-', true) 			local startYear = tonumber(dates[1]) 			local endYear = tonumber(dates[2]) or tonumber(os.date('%Y')) + 1 			 			if not startYear then 				error('date' .. i .. ' contains an invalid timerange', 0) 			end 			 			info.startYear = math.min(info.startYear, startYear) 			info.endYear = math.max(info.endYear, endYear) 			info.startYears[i] = startYear 			info.endYears[i] = endYear 		end 	end 	 	if args.startoffset then 		info.startYear = info.startYear - tonumber(args.startoffset) 	end 	 	if args.startyear then 		info.startYear = math.min(info.startYear, tonumber(args.startyear)) 	end 	 	if args.endoffset then 		info.endYear = info.endYear + tonumber(args.endoffset) 	end 	 	if args.endyear then 		info.endYear = math.max(info.endYear, tonumber(args.endyear)) 	end 	 	return info end  -- Render the date rows local function renderDates(args, tbl, info) 	local showDecades = yesno(args.decades) 	local labelRow = nil 	 	if args.label then 		labelRow = mw.html.create('th') 			:attr('scope', 'col') 			:addClass('navbox-group timeline-label') 			:cssText(args.labelstyle) 			:attr('rowspan', showDecades ~= false and '2' or '1') 			:wikitext(args.label or ) 	end 	 	-- Render the decades row 	if showDecades ~= false then 		local decadeRow = tbl:tag('tr') 			:addClass('timeline-row') 		local year = info.startYear 		 		decadeRow:node(labelRow) 		 		while year < info.endYear do 			local dur = math.min(10 - year % 10, info.endYear - year) 			 			decadeRow:tag('th') 				:attr('scope', 'col') 				:addClass('timeline-decade') 				:cssText(args.datestyle) 				:cssText(args.decadestyle) 				:attr('colspan', dur) 				:wikitext(convert('bn', tostring(math.floor(year / 10))) .. '০-এর দশক') 			 			year = year + dur 		end 	end  	-- Render the years row 	local yearRow = tbl:tag('tr') 		:addClass('timeline-row') 	local width = 100 / (info.endYear - info.startYear) 	 	if showDecades == false then 		yearRow:node(labelRow) 	end 	 	for i = info.startYear, info.endYear - 1 do 		 		yearRow:tag('th') 			:attr('scope', 'col') 			:addClass('timeline-year') 			:cssText(args.datestyle) 			:cssText(args.yearstyle) 			:cssText('width:' .. width .. '%') 			:wikitext(convert('bn', tostring(showDecades == false and i or i % 10))) 	end end  -- Render the timeline itself local function renderTimeline(args, tbl, info) 	local row = nil 	local prev = info.startYear 	local prevItem = nil 	local prevLabel = nil 	local labelSpan = 0 	 	for i, num in ipairs(info.entries) do 		if args['row' .. i] or row == nil then 			addBlank(args, row, prev, info.endYear) 			 			row = tbl:tag('tr') 				:addClass('timeline-row') 			prev = info.startYear 			 			if labelSpan <= 0 and args.label then 				labelSpan = tonumber(args['span' .. i]) or 1 				 				prevLabel = row:tag('th') 					:attr('scope', 'row') 					:attr('rowspan', labelSpan) 					:addClass('navbox-group timeline-label') 					:cssText(args.labelstyle) 					:cssText(args['labelstyle' .. i] or ) 					:wikitext(args['row' .. i]) 			end 			 			labelSpan = labelSpan - 1 		end 		 		if args['item' .. i] then 			local content = args['item' .. i]  			local startYear = info.startYears[i] 			local endYear = info.endYears[i] 			 			addBlank(args, row, prev, startYear) 			 			-- Shrink previous item so new item can start at the start year 			if prevItem and prev > startYear then 				prevItem:attr('colspan', prevItem:getAttr('colspan') - prev + startYear); 			end 			 			prevItem = row:tag('td') 				:addClass('timeline-item') 				:cssText(args.itemstyle) 				:cssText(args['style' .. i] or '') 				:attr('colspan', endYear - startYear) 				:wikitext(content) 			 			prev = endYear 		end 	end 	 	-- Remove any extra rowspan from the label 	if prevLabel and labelSpan > 0 then 		prevLabel:attr('rowspan', prevLabel:getAttr('rowspan') - labelSpan); 	end 	 	addBlank(args, row, prev, info.endYear) end  function p.main(frame) 	local args = getArgs(frame, { 		removeBlanks = false, 		wrappers = 'টেমপ্লেট:সময়ক্রম' 	}) 	local targs = { 		listpadding = '0' 	} 	-- Arguments to passthrough to navbox 	local passthrough = { 		'name', 'title', 'above', 'below', 'state', 'navbar', 'border', 1, 		'image', 'imageleft', 'style', 'bodystyle', 'style', 'bodystyle', 		'basestyle', 'titlestyle', 'abovestyle', 'belowstyle', 'imagestyle', 		'imageleftstyle', 'titleclass', 'aboveclass', 'bodyclass', 		'belowclass', 'imageclass' 	} 	local info = timelineInfo(args) 	local wrapper = mw.html.create('table') 		:addClass('timeline-wrapper') 	local tbl = wrapper:tag('tr') 		:tag('td') 			:addClass('timeline-wrapper-cell') 			:tag('table') 				:addClass('timeline-table') 	 	renderDates(args, tbl, info) 	renderTimeline(args, tbl, info) 	 	if yesno(args.footer) then 		renderDates(args, tbl, info) 	end 	 	for _, name in ipairs(passthrough) do  		targs[name] = args[name] 	end  	targs.list1 = frame:extensionTag{ 		name = 'templatestyles', 		args = { 			src = 'মডিউল:সময়ক্রম/শৈলী.css' 		} 	} .. tostring(wrapper) 	 	return navbox(targs) end  return p