require('strict') local p = {} local sandbox-- = '/sandbox' local cfg = mw.loadData('মডিউল:উইকিপ্রকল্প ব্যানার/config' .. (sandbox or )) local i18n = mw.loadData('মডিউল:ব্যানারের খোলস/কনফিগ' .. (sandbox or )) local auxiliary = cfg.auxiliary_module .. (sandbox or ) local args_module = require('Module:Arguments') local mbox = require('Module:Message box').main local yesno = require('Module:Yesno') local frame = mw.getCurrentFrame() local lang = mw.getLanguage(cfg.language) local current_title = mw.title.getCurrentTitle() local parameter_format = function(parameter, value) 	return frame:expandTemplate{title='para', args={parameter, value or }} end  local wikilink = function(link, display) 	if link then 		return display and ''..display..'' or ''..link..'' 	else 		return display or 	end end local display_error = function(text) 	local span = mw.html.create('div') 		:addClass('error') 		:wikitext(text) 	return tostring(span)	 end  local image = function(image_name, size, alt, position) 	return image_name and '[[File:' 		.. image_name 		.. (size and '|' .. size or ) 		.. (position and '|' .. position or ) 		.. (alt and '|alt=' .. alt or ) 		.. ']]' end  local if_exists = function(target, fallback) -- function to add wikilink if target exists 	local title = mw.title.new(target) 	if title and title.exists then 		return wikilink(target) 	else 		return fallback or target 	end end  local isarticle = function(class) 	local article = true 	for _,v in ipairs(cfg.quality.non_article_classes) do 		if class==v then -- class matches one of the non-article classes 			article = false 			break 		end 	end 	return article end  local importance_mask = function(raw_importance, scale, banner_name, pagetype)  -- Importance mask --------  local importance if scale=='inline' then -- pass importance without change 	importance = raw_importance elseif scale=='subpage' then 	local custom_mask = banner_name:subPageTitle('importance') 	if custom_mask.exists and #custom_mask:getContent()>1 then -- pass to custom importance mask 		importance = mw.text.trim(frame:expandTemplate{ 			title = custom_mask.prefixedText, 			args = { 				importance = raw_importance or '¬', 				pagetype = pagetype 			} 		}) 	end elseif raw_importance then-- standard importance scale 	importance = cfg.importance.na 	if pagetype=='নিবন্ধ' or pagetype=='redirect' or pagetype=='draft' then 		local mask = cfg.importance.mask 		if mask[raw_importance:lower()] then -- valid importance specified 			importance = mask[raw_importance:lower()] 		elseif pagetype=='নিবন্ধ' then -- unspecified or invalid importance, use "Unknown" for articles 			importance = cfg.importance.unknown 		end 	end end return importance end  -- Quality class mask -----  p.readarticleclass = function(options, page) 	page = page or current_title.prefixedText 	local get_parameter_value = require('Module:Template parameter value').getParameter 	local success, result = get_parameter_value(page, cfg.banner_shell.redirects, 'class', options)  	-- If not found or blank, try alternative parameter names 	if not success or result ==  then 		local fallback_keys = cfg.banner_shell.class_parameter 		for _, key in ipairs(fallback_keys) do 			success, result = get_parameter_value(page, cfg.banner_shell.redirects, key, options) 			if success and result ~=  then 				break 			end 		end 	end  	return success and result end  p.class_mask = function(class, title, FQS, pagetype) 	local resolveFQSgrade = function(class) 		return FQS and lang:ucfirst(class) or 'অ-নিবন্ধ'  	end 	local out 	title = title or mw.title.getCurrentTitle() 	local ns = title.namespace 	class = class 	if pagetype=='redirect' or pagetype=='soft redirect' then 		out = resolveFQSgrade('redirect') 	elseif pagetype=='disambiguation page' then 		out = resolveFQSgrade('disambig') 	elseif pagetype=='নিবন্ধ' then 		if class=='প্রারম্ভিক' or class=='অসম্পূর্ণ' then  			out = class 		elseif class=='খ' or class=='গ' or class=='নির্বাচিত নিবন্ধ' or class=='নির্বাচিত তালিকা' or class=='ক' or class== 'ভালো নিবন্ধ' then -- Upper-case 			out = class 		elseif class=='তালিকা' or class=='sia' or class=='si' or class=='sl' then-- List 			out = 'তালিকা' 		else 			out =  -- অপর্যালোচিত 		end 	elseif ns==7 or ns==711 then -- File talk 		if class=='fm' then 			out = 'FM' 		else 			out = resolveFQSgrade('file') 		end 	else 	    local grade = cfg.quality.ns_to_class[ns] or 'NA' 		out = resolveFQSgrade(grade) 	end 	return out end  local page_assessment = function(project, class, importance) -- add PageAssessments parser function 	local assessment = table.concat({project, class or , importance or },'|') 	frame:preprocess('') end  local bubble = function(text, conflict, style) 	local out = mw.html.create('span') 		:addClass('wpb-header-bubbles') 		:addClass(style) 		:addClass(conflict and 'conflict' or nil) 		:wikitext(text) 	return tostring(out) end  p._main = function(args, raw_args, demo_page, banner_name, inactive)  -- Initialise parameters --  local project = args.PROJECT or 'PROJECT' local project_name = args.PROJECT_NAME or 'উইকিপ্রকল্প ' .. project local project_link = mw.title.new(args.PROJECT_LINK or 'Wikipedia:' .. project_name) local pagetype = demo_page==true and 'নিবন্ধ' or require('Module:পাতার ধরন')._main({ 	page = demo_page, 	dab = 'disambiguation page' }) local rows, nested_ratings, task_forces, notes, categories, taskforce_categories = {}, {}, {}, {}, {}, {} local add_category = function(category, key) 	if category and category~='none' then 		table.insert(categories, {category = category, key = key}) 	end end local parse_text = function(text) 	return text and text:gsub('_PAGETYPE_', pagetype) end for arg_name, arg_value in pairs(args) do 	local tf_match = mw.ustring.match(arg_name,'^tf (%d+)$') 	local note_match = mw.ustring.match(arg_name,'^note (%d+)$') 	if tf_match and yesno(arg_value, true) then 		table.insert(task_forces, tf_match) 	elseif note_match and yesno(arg_value, true) then 		table.insert(notes, note_match) 	else 		local tf, cat = mw.ustring.match(arg_name,'^tf (%d+) cat (%d+)$') 		if tf and yesno(arg_value, true) then 			if not taskforce_categories[tf] then -- initialise table 				taskforce_categories[tf] = {} 			end 			table.insert(taskforce_categories[tf], cat) 		end 	end end table.sort(task_forces, function (x, y) return tonumber(x) < tonumber(y) end) table.sort(notes, function (x, y) return tonumber(x) < tonumber(y) end)  -- Location warning -------  local warning =  local show_namespace_warning = not (current_title.isTalkPage or demo_page) if show_namespace_warning then 	local text = cfg.namespace_warning.text:format( 		pagetype, 		current_title.talkPageTitle.fullText, 		parameter_format('category', 'no') 	) 	local sortkey = current_title.namespace==10 and cfg.namespace_warning.sortkey_on_template_page or cfg.namespace_warning.sortkey 	if current_title.namespace==10 then -- on the Template namespace 		text = text .. '  ' .. cfg.namespace_warning.on_template_page:format( 			parameter_format('BANNER_NAME'), 			current_title.prefixedText 		) 	end 	warning = mbox('ombox', { 		image = '40px', 		type = cfg.namespace_warning.type_, 		text = text 	}) 	if not current_title.subjectPageTitle:inNamespace(2) then 		add_category(cfg.namespace_warning.categories, sortkey) 	end end  -- Substitution warning ---  if args.substcheck=='SUBST' then 	local text = cfg.subst_warning.text:format( 		project_name, 		'{{'..banner_name.prefixedText..'}}' 	) 	warning = warning .. mbox('ombox', { 		image = '40px', 		type = cfg.subst_warning.type_, 		text = text, 	}) .. cfg.subst_warning.categories end  -- Primary image/text -----  local assessment_cat = args.ASSESSMENT_CAT or project .. ' নিবন্ধ' local primary_image = function(image_name, size) 	local cell = mw.html.create('td') 	if image_name and image_name~= then 		cell:addClass('mbox-image wpb-image') 			:wikitext(image(image_name, size, cfg.image.alt)) 	else 		cell:addClass('mbox-empty-cell') 	end 	return cell end  local portal = args.PORTAL local portal_box = portal and frame:expandTemplate{title='Portal', args={portal}} or  local main_text = portal_box .. (parse_text(args.MAIN_TEXT) or cfg.main_text:format( 	project_link.prefixedText, 	project_name, 	pagetype, 	args.MAIN_ARTICLE and if_exists(args.MAIN_ARTICLE) or if_exists(project, project .. ' articles'), 	project_link.talkPageTitle.prefixedText )) local image_left_size = args.IMAGE_LEFT_SIZE or cfg.image.default_size local metadata = function(class, data) 	return mw.html.create('span') 		:addClass(class) 		:wikitext(data) end local text_cell = mw.html.create('td') 	:addClass('mbox-text') 	:wikitext(main_text) 	:tag('span') 		:addClass('metadata wpb-metadata') 		:node(metadata('wpb-project', project)) 		:node(metadata('wpb-project_link', project_link.prefixedText)) 		:node(metadata('wpb-banner_name', banner_name.prefixedText)) 		:node(metadata('wpb-assessment_cat', assessment_cat)) 	:done() local primary_row = mw.html.create('tr') 	:node(primary_image(args.IMAGE_LEFT, image_left_size)) 	:node(text_cell) 	:node(primary_image(args.IMAGE_RIGHT, args.IMAGE_RIGHT_SIZE or cfg.image.default_size)) table.insert(rows, primary_row)  -- Banner shell checks ----  local title = demo_page and demo_page~=true and mw.title.new(demo_page) or current_title local article_class = p.readarticleclass({ignore_subtemplates=true}, title.prefixedText) if article_class then -- banner shell exists 	local special_chars = '([%%%(%)%.%+%-%*%?%[%]%^%$])' 	local banner_name_escaped = banner_name.text 	local page_content = require('Module:Wikitext Parsing').PrepareText(title:getContent()) -- get content of current page 	local content_without_shell 	for capture in mw.ustring.gmatch(page_content, '%b{}') do -- look for possible templates on page 		for _, redirect in ipairs(cfg.banner_shell.redirects) do 			if mw.ustring.find(capture, '^{{%s*' .. redirect .. '%s*[|}].*}}$') then -- found a banner shell 				banner_name_escaped = banner_name_escaped:gsub(special_chars, '%%%1') -- escape each special character 				capture = capture:gsub(special_chars, '%%%1') 				content_without_shell = mw.ustring.gsub(page_content, capture, ) -- remove banner shell content from page content 			end 			if content_without_shell then break end 		end 		if content_without_shell then break end 	end 	local template_outside_shell 	if content_without_shell and mw.ustring.find(content_without_shell, '{{%s*' .. banner_name_escaped .. '%s*[|}]') then -- found banner template outside of the shell 		add_category(cfg.banner_shell.category.outside_shell) 	end else -- no banner shell on page 	if pagetype=='নিবন্ধ' then 		add_category(cfg.banner_shell.category.no_banner_shell_articles) 	elseif title.namespace==3 then --User talk namespace 		for _, user in ipairs(cfg.banner_shell.valid_users) do 			if string.find(title.rootText, user) then 				add_category(cfg.banner_shell.category.no_banner_shell) 			end 		end 	else 		add_category(cfg.banner_shell.category.no_banner_shell) 	end end  -- Quality assessment -----  local assessment_link = args.ASSESSMENT_LINK if not assessment_link then 	local fallback = mw.title.new(project_link.prefixedText .. '/Assessment') 	assessment_link = fallback.exists and fallback.prefixedText elseif assessment_link=='no' then 	assessment_link = nil end local check_exists = function(class, assessment_cat) -- check if category exists and is not blank 	if not isarticle(class) then 		local cat =  mw.title.new('Category:' .. class ..'-শ্রেনীর' .. ' ' .. assessment_cat) 		return (cat.exists and #cat:getContent()>0) and class or 'NA' -- automatically use NA for non-article pages if category does not exist 	else 		return class 	end end local class = i18n.class[raw_args.class] or raw_args.class if class then -- banner gives quality ratings 	article_class = article_class and p.class_mask(article_class, title, false, pagetype) 	local show_quality, conflict = true, false 	if args.QUALITY_CRITERIA=='custom' then -- project has opted out of standard assessment scale and uses a custom mask 		local custom_mask = banner_name:subPageTitle('class') 		if custom_mask.exists and #custom_mask:getContent()>1 then 			raw_args.demo_page = demo_page -- send demo_page to custom mask 			class = mw.text.trim(frame:expandTemplate{ 				title = custom_mask.prefixedText, 				args = raw_args 			}) 			if class== and article_class and article_class~= then -- if অপর্যালোচিত and article class exists, check if it can be inherited 				local new_arg_table = {} 				for arg, val in pairs(raw_args) do -- construct new argument table to send to custom mask 					new_arg_table[arg] = val 				end 				new_arg_table.class = article_class -- replace class with inherited class 				local article_class_normalised = mw.text.trim(frame:expandTemplate{ 					title = custom_mask.prefixedText, 					args = new_arg_table 				}) 				if article_class_normalised and article_class_normalised~= then 					class = article_class_normalised -- inherit class from article_class normalised by custom mask 				else 					article_class = nil -- effectively no article_class for this banner 				end 			end 		end 	else 		class = p.class_mask(class, title, true, pagetype) 	end 	if article_class then -- banner shell exists 		if class== or class==article_class or article_class=='FM' then -- local class matches article class or is blank 			show_quality = false -- hide quality class in project banner 			class = article_class 			if raw_args.class~= and args.QUALITY_CRITERIA~='custom' then 				add_category(cfg.banner_shell.category.redundant_class) 			end 		elseif article_class== then -- local class defined and no article class defined 			add_category(cfg.banner_shell.category.no_quality_rating) 			if args.QUALITY_CRITERIA~='custom' then 				warning = warning .. display_error(cfg.banner_shell.piqa_warning) 			end 		elseif pagetype~='নিবন্ধ' and not isarticle(class) and class~='FM' then -- article class and local class are both non-article classes 			show_quality = false 		elseif args.QUALITY_CRITERIA~='custom' then -- article class exists and differs from local class 			conflict = true 			add_category(class .. cfg.banner_shell.conflict.category) 		end 	end 	if not isarticle(class) then -- check fallbacks for non-article classes 		local category_exists = function(class) 			local cat =  mw.title.new(cfg.quality.assessment_category:format(class, assessment_cat)) 			return cat.exists and #cat:getContent()>0 -- check if category exists and is not blank 		end 		if class=='FM' and not category_exists('FM') then 			class = 'File' -- fall back to File-clas if FM category does not exist 		end 		if not category_exists(class) then 			class = 'NA' -- automatically use NA for non-article pages if category does not exist 		end 	end 	local category = (class== and 'অপর্যালোচিত' or class....'-শ্রেনীর') .. ' ' .. assessment_cat 	if show_quality then -- quality rating shown in banner 		local rating 		if pagetype=='নিবন্ধ' then 			rating = class== and cfg.quality.not_yet or cfg.quality.rated:format(class) 		else 			rating = cfg.quality.not_required 		end 		local scale = args.QUALITY_CRITERIA=='custom' 			and assessment_link 			and cfg.quality.project_scale:format(wikilink(assessment_link..'#'..lang:ucfirst(cfg.quality.name), cfg.quality.name)) 			or cfg.quality.default_scale 		local quality_rating = conflict 			and cfg.banner_shell.conflict.text:format(pagetype) 			or cfg.quality.rating:format(scale, pagetype, rating) 		local cssClass = 'class-' .. (class== and 'অপর্যালোচিত' or class:lower()) 		local class_row =  mw.html.create('tr') 			:tag('td') 				:addClass('assess') 				:addClass(cssClass) 				:addClass(conflict and 'conflict' or nil) 				:wikitext(wikilink(':বিষয়শ্রেণী:' .. category, class== and '???' or class)) 			:done() 			:tag('td') 				:addClass('mbox-text') 				:attr('colspan', '2') 				:wikitext(quality_rating) 			:done() 		table.insert(rows, class_row) 		table.insert( 			nested_ratings, 			1, 			bubble(class== and 'অপর্যালোচিত' or (class..'‑শ্রেনী'), conflict, cssClass) 		) 	end 	add_category(category) end if args.HOOK_ASSESS then 	table.insert(rows, args.HOOK_ASSESS) end if raw_args.b1 or raw_args.b2 or raw_args.b3 or raw_args.b4 or raw_args.b5 or raw_args.b6 then 	local b_checklist = require(auxiliary).b_checklist(args, raw_args, class, demo_page, assessment_link) 	table.insert(rows, b_checklist) end  -- Importance assessment --  local importance = importance_mask(raw_args.importance or raw_args.priority, args.IMPORTANCE_SCALE, banner_name, pagetype) local importance_name = args.IMPN or (raw_args.priority and 'priority' or cfg.importance.default_name) if importance then -- banner gives importance ratings 	local category = importance .. '-' .. importance_name .. ' ' .. assessment_cat 	if importance~='NA' then -- display importance rating 		local rating = importance=='Unknown' and cfg.importance.not_yet or cfg.importance.rated:format(importance, importance_name) 		local scale_name = cfg.importance.scale:format(importance_name) 		local scale = assessment_link 			and cfg.importance.project_scale:format(assessment_link..'#'..lang:ucfirst(scale_name), scale_name) 			or cfg.importance.default_scale 		local importance_rating = cfg.importance.rating:format(scale, pagetype, rating) 		local cssClass = 'import-' .. importance:lower() 		local importance_row =  mw.html.create('tr') 			:tag('td') 				:addClass('assess') 				:addClass(cssClass) 				:wikitext(wikilink(':Category:' .. category, importance=='Unknown' and '???' or importance)) 			:done() 			:tag('td') 				:addClass('mbox-text') 				:attr('colspan', '2') 				:wikitext(importance_rating) 			:done() 		table.insert(rows, importance_row) 		if importance~='Unknown' then -- importance is not NA or Unknown 			table.insert( 				nested_ratings, 				bubble(importance .. '‑' .. importance_name, false, cssClass) 			) 		end 	end 	add_category(category) end page_assessment(project, class, importance) if args.HOOK_IMPORTANCE then 	table.insert(rows, args.HOOK_IMPORTANCE) end if args.QII_FORMAT then 	add_category(require(auxiliary).quality_importance_insection(args, class, importance, importance_name)) end  -- Collapsing sections ----  local collapse_section = function(collapse, new_rows, header) 	if collapse then 		local header_row = mw.html.create('tr') 			:tag('th') 				:attr('colspan','3') 				:addClass('wpb-collapsed-head') 				:wikitext(header) 			:done() 		local blank_row = mw.html.create('tr') 			:tag('td') 				:addClass('mbox-image wpb-gutter') 				:css('min-width', image_left_size) 				:tag('span') 					:addClass('wpb-iefix') 					:wikitext('/ ') 					:done() --TO FIX IE 			:done() 			:tag('td'):done() 			:tag('td'):done() 		local collapsed_rows = mw.html.create('table') 			:addClass('mw-collapsible mw-collapsed') 			:node(header_row) 			:node(blank_row) 			for _, row in ipairs(new_rows) do 				collapsed_rows:node(row) 			end 		local collapsed_section = mw.html.create('tr') 			:tag('td') 				:attr('colspan','3') 				:addClass('wpb-collapsed-notes') 				:node(collapsed_rows) 			:done() 		table.insert(rows, collapsed_section) 	else 		for _, row in ipairs(new_rows) do 			table.insert(rows, row) 		end 	end end  -- Task forces ------------  local nested_tf, taskforce_output = {}, {} local tf_default_size = args.TF_SIZE or cfg.task_force.default_size for _, k in ipairs(task_forces) do 	local tf_prefix = 'TF_' .. k .. '_' 	local tf_assessment_cat = args[tf_prefix..'ASSESSMENT_CAT'] or (args[tf_prefix..'NAME'] or )..' নিবন্ধ' 	local tf_importance 	if raw_args['tf '..k..' importance'] then 		tf_importance = importance_mask(raw_args['tf '..k..' importance'], args.IMPORTANCE_SCALE, banner_name, pagetype) 		if tf_importance=='Unknown' and yesno(args.INHERIT_IMPORTANCE) then 			tf_importance = importance 		end 	end 	if args[tf_prefix .. 'TEXT']~='none' then 		local portal = args[tf_prefix..'PORTAL'] and frame:expandTemplate{ 			title='Portal', 			args={args[tf_prefix .. 'PORTAL'], height='15', margin='0'} 		} or 		local text =  		local tf_text = args[tf_prefix..'TEXT'] or args.TF_TEXT 		if tf_text then 			text = portal .. tf_text 				:gsub('_NAME_', args[tf_prefix .. 'NAME'] or ) 				:gsub('_LINK_', args[tf_prefix .. 'LINK'] or ) 				:gsub('_IMPORTANCE_', tf_importance or ) 				:gsub('_PAGETYPE_', pagetype) 		else 			local tf_importance_text = tf_importance 				and tf_importance~='NA' 				and tf_importance~='Unknown' 				and ' ' .. cfg.task_force.importance:format( 					wikilink(':Category:' .. tf_importance .. '-' .. importance_name .. ' ' .. tf_assessment_cat, tf_importance .. '-' .. importance_name..' '..pagetype) 				) or  			text = portal .. cfg.task_force.text:format( 				pagetype, 				wikilink(args[tf_prefix .. 'LINK'], args[tf_prefix .. 'NAME']), 				tf_importance_text 			) 		end 		local tf_size = args[tf_prefix .. 'SIZE'] or tf_default_size 		local tf_image = 		if args[tf_prefix .. 'IMAGE'] then 			tf_image = image(args[tf_prefix .. 'IMAGE'], tf_size, cfg.task_force.icon_alt, 'center') 		end 		local taskforce = mw.html.create('tr') 			:tag('td') 				:wikitext(tf_image) 			:done() 			:tag('td') 				:addClass('mbox-text') 				:attr('colspan','2') 				:wikitext(text) 			:done() 		table.insert(taskforce_output, taskforce) 	end 	if args[tf_prefix..'HOOK'] then 		table.insert(taskforce_output, args[tf_prefix..'HOOK']) 	end 	if yesno(args[tf_prefix..'QUALITY']) and class then 		local tf_class = check_exists(class, tf_assessment_cat) 		add_category((tf_class== and 'অপর্যালোচিত' or tf_class..'-শ্রেনীর') .. ' ' .. tf_assessment_cat) 	end 	if tf_importance then 		add_category(tf_importance .. '-' .. importance_name .. ' ' .. tf_assessment_cat) 	end 	if args[tf_prefix..'QII_FORMAT'] then 		add_category(require(auxiliary).quality_importance_insection(args, class, tf_importance, importance_name, tf_prefix)) 	end 	if args[tf_prefix..'NAME'] then 		page_assessment(project..'/'..args[tf_prefix..'NAME'], class, tf_importance) 	end 	if args[tf_prefix..'MAIN_CAT'] then 		add_category(args[tf_prefix..'MAIN_CAT']) 	end 	if args[tf_prefix..'NESTED'] then 		table.insert(nested_tf, wikilink(args[tf_prefix..'LINK'], args[tf_prefix..'NESTED'])) 	end 	for _, c in ipairs(taskforce_categories[k] or {}) do-- add additional taskforce categories 		add_category(args[tf_prefix..'CAT_'..c]) 	end end if args.HOOK_TF then 	table.insert(taskforce_output, args.HOOK_TF) end local threshold = tonumber(args.TF_COLLAPSE) or (args.TF_HEADER and cfg.task_force.lower_threshold) or cfg.task_force.upper_threshold collapse_section( 	#taskforce_output > threshold, 	taskforce_output, 	args.TF_HEADER or cfg.task_force.header )  -- Notes ------------------  local note_output = {} local note_default_size = args.NOTE_SIZE or args.NOTE_1_SIZE or cfg.note.default_size local render_note = function(note_args)--text, image_name, size, category, sort_prefix 	local sort = note_args.sort_prefix and note_args.sort_prefix .. current_title.text 	add_category(note_args.category, sort) 	add_category(note_args.category2, sort) 	if note_args.text then 		local note_image = image(note_args.image_name, note_args.size or note_default_size, cfg.note.icon_alt, 'center') 		local new_note = mw.html.create('tr') 			:tag('td') 				:css('background', note_args.background) 				:wikitext(note_image) 			:done() 			:tag('td') 				:addClass('mbox-text') 				:attr('colspan', '2') 				:wikitext(note_args.text) 			:done() 		table.insert(note_output, new_note) 		if note_image then 			local icon = mw.html.create('span') 				:addClass('wpb-header-bubbles') 				:wikitext('' .. cfg.note.header_icon .. '|' .. note_args.text .. '|link=|alt=') 			table.insert(nested_ratings, tostring(icon)) 		end 	end end local auto = false local auto_arg = args.auto and args.auto:lower() if (auto_arg=='yes' or auto_arg=='stub') and class=='Stub' then 	auto = 'stub' elseif (auto_arg=='inherit' or auto_arg=='length') and class and class~= then 	auto = auto_arg end if auto then 	local auto_cat = args.AUTO_ASSESS_CAT or cfg.auto.default_cat:format(project) 	local auto_text = cfg.auto.assessed:format( 		pagetype, 		cfg.auto[auto], -- method of automatic assessment 		parameter_format('auto') 	) 	local sort_prefix 	if auto=='stub' then 		sort_prefix = 'S' 	elseif auto=='length' then 		sort_prefix = 'L' 	elseif auto=='inherit' then 		local sort_codes = cfg.auto.sort_codes 		sort_prefix = sort_codes[class] or cfg.auto.default_sort_code 	end 	render_note{ 		text = auto_text, 		image_name =  cfg.auto.icon, 		category = auto_cat, 		sort_prefix = sort_prefix 	} end if yesno(args.attention, true) then 	local attention_cat = args.ATTENTION_CAT or cfg.attention.default_cat:format(project) 	render_note{ 		text = cfg.attention.text:format(pagetype), 		image_name = cfg.attention.icon, 		category = attention_cat 	} end if yesno(args.infobox, true) then 	local infobox_cat = args.INFOBOX_CAT or cfg.infobox.default_cat:format(project) 	render_note{ 		text = cfg.infobox.text:format(pagetype), 		image_name = cfg.infobox.icon, 		category = infobox_cat 	} end for _, k in ipairs(notes) do 	local note_prefix = 'NOTE_' .. k .. '_' 	render_note{ 		text = parse_text(args[note_prefix..'TEXT']), 		image_name = args[note_prefix..'IMAGE'], 		size = args[note_prefix..'SIZE'], 		category = args[note_prefix..'CAT'] 	} end if yesno(args['image-needed'], true) then 	local image_needed_args = require(auxiliary).image_needed(args, pagetype) 	render_note(image_needed_args) end if yesno(args['collaboration-candidate'], true) or yesno(args['collaboration-current'], true) or yesno(args['collaboration-past'], true) then 	local collaboration_args = require(auxiliary).collaboration(args, pagetype, current_title) 	render_note(collaboration_args.candidate) 	render_note(collaboration_args.current) 	render_note(collaboration_args.past) end if yesno(args['a class'], true) then 	local a_class_args = require(auxiliary).a_class(args, lang) 	render_note(a_class_args) end if yesno(args['peer review'], true) or yesno(args['old peer review'], true) then 	local peer_review_args = require(auxiliary).peer_review(args, current_title) 	render_note(peer_review_args.current) 	render_note(peer_review_args.past) end  local note_count = #note_output if args.HOOK_NOTE then 	table.insert(note_output, args.HOOK_NOTE) 	local hook_collapsed = 0 	if args.HOOK_COLLAPSED then 		local success, result = pcall(mw.ext.ParserFunctions.expr, args.HOOK_COLLAPSED) 		hook_collapsed = success and tonumber(result) or 0 		if args.HOOK_COLLAPSED=='auto' then 			hook_collapsed = 1 		end 	end 	note_count = note_count + hook_collapsed end collapse_section( 	note_count > (tonumber(args.COLLAPSED) or cfg.note.threshold), 	note_output, 	args.COLLAPSED_HEAD or cfg.note.header )  -- Bottom text ------------  if args.HOOK_BOTTOM then 	table.insert(rows, args.HOOK_BOTTOM) end if args.TODO_LINK or args.TODO_TEXT then 	local todolist = require(auxiliary).todo_list(args, frame) 	table.insert(rows, todolist) end if args.BOTTOM_TEXT then 	local bottom_text = mw.html.create('tr') 		:tag('td') 			:attr('colspan','3') 			:wikitext(parse_text(args.BOTTOM_TEXT)) 		:done() 	table.insert(rows, bottom_text) end if args.MAIN_CAT then 	add_category(args.MAIN_CAT) end  -- Nested display ---------  if args.HOOK_NESTED then 	local hook_nested = args.HOOK_NESTED:gsub('^ / ', ) -- remove initial slash, will be added later 	table.insert(nested_tf, hook_nested) end local nested_tf_str = if #nested_tf>0 then 	nested_tf_str = tostring(mw.html.create('span') 		:addClass('wpb-nested-task-force') 		:wikitext(': ' .. table.concat(nested_tf, ' / ')) 	) end local nested_ratings_str = #nested_ratings>0 and table.concat(nested_ratings, ' ') or  if args.HOOK_NESTED_ASSESS then 	nested_ratings_str = nested_ratings_str .. tostring(mw.html.create('span') 		:addClass('wpb-header-bubbles') 		:wikitext(args.HOOK_NESTED_ASSESS) 	) end local header_row = mw.html.create('tr') 	:addClass('wpb-header') 	:tag('td') 		:addClass('wpb-header-icon') 		:wikitext(image(args.IMAGE_LEFT, cfg.image.header_size, cfg.image.alt)) 		:done() 	:tag('td') 		:addClass('wpb-header-combined') 		:wikitext(wikilink(project_link.prefixedText, project) .. nested_tf_str .. '  ' .. nested_ratings_str) 		:done()  -- Default sort -----------  if args.listas then 	frame:preprocess('') 	if title.namespace~=3 then -- exclude user talk namespace 		local success, shell_listas_value = require('Module:Template parameter value').getParameter( 			title.prefixedText, 			cfg.banner_shell.redirects, 			'listas', 			{ignore_subtemplates = true, ignore_blank = true} 		) 		if success and shell_listas_value~= then 			if args.listas==shell_listas_value then-- same value in both (with spacing trimming) 				add_category('WikiProject banners with redundant listas value') 			end 		else-- listas is blank or not defined in banner shell 			add_category('WikiProject banners with listas value which needs moving to banner shell') 		end 	end end  -- Prepare categories -----  local categories_formatted =  if demo_page and demo_page~=true then -- for testing purposes 	local category_list = mw.html.create('ul') 	for _, cat in ipairs(categories) do 		local item = mw.html.create('li') 			:wikitext(wikilink(':Category:' .. cat.category, cat.category)) 		category_list:node(item) 	end 	local category_box = mw.html.create('div') 		:addClass('wpb-category-box') 		:wikitext('Categories:') 		:node(category_list) 	categories_formatted = tostring(category_box) elseif not demo_page then 	local categories_linked = {} 	for _, cat in ipairs(categories) do 		local cat_link = wikilink('Category:' .. cat.category, cat.key) 		table.insert(categories_linked, cat_link) 	end 	categories_formatted = table.concat(categories_linked) end  -- Make banner ------------  local banner_rows = mw.html.create('table') for _, row in ipairs(rows) do 	banner_rows:node(row) end local banner = mw.html.create('table') 	:addClass('tmbox tmbox-notice mw-collapsible innercollapse wpb wpb-table') 	:addClass(inactive and cfg.status.inactive_class or nil) 	:node(header_row) 	:tag('tr') 		:tag('td') 			:addClass('mbox-text wpb-main') 			:attr('colspan','2') 			:node(banner_rows) 	:allDone() local tstyle = frame:extensionTag('templatestyles', , {src='Module:Message box/tmbox.css'}) .. 	frame:extensionTag ('templatestyles', , {src = 'Module:WikiProject banner' .. (sandbox or ) .. '/styles.css'}) return warning .. tstyle .. tostring(banner) .. categories_formatted, note_count, #taskforce_output, assessment_link end  local initialise = function(args, raw_args, inactive_status)  -- Initialise arguments ---  local parent_args = args_module.getArgs(frame, {parentOnly = true}) local category = parent_args.category or args.category or true local demo_page = parent_args.demo_page local on_template_page = false local banner_name = mw.title.new(args.BANNER_NAME or 'টেমপ্লেট:উইকিপ্রকল্প ' .. (args.PROJECT or 'PROJECT')) if not demo_page then 	if yesno(category, true) then 		on_template_page = current_title.rootPageTitle==banner_name.rootPageTitle 	else 		demo_page = true 	end end local project_name = args.PROJECT_NAME or 'উইকিপ্রকল্প ' .. (args.PROJECT or 'PROJECT') local unknown_parameters =  if banner_name.exists and not demo_page then -- check for unknown parameters 	local parameters = {} 	for parameter in banner_name:getContent():gmatch('{{{([^|}]+)') do 		table.insert(parameters, parameter) 	end 	local check_for_unknown = require('Module:Check for unknown parameters')._check 	local unknowns = check_for_unknown(parameters, parent_args) 	if unknowns and unknowns~= then-- there are some unknown parameters 		parameters.preview = cfg.unknown_parameters.preview:format(wikilink(banner_name.fullText)) 		local unknown_category = cfg.unknown_parameters.tracking:format(project_name) 		if not mw.title.new(unknown_category).exists then 			unknown_category = cfg.unknown_parameters.default 		end 		parameters.unknown = unknown_category and '_VALUE_' or  		unknown_parameters = check_for_unknown(parameters, parent_args) 	end end if on_template_page then 	local templatepage = require('মডিউল:উইকিপ্রকল্প ব্যানার/templatepage' .. (sandbox or )).templatepage 	return templatepage(args, raw_args, inactive_status) else 	return unknown_parameters 		.. p._main(args, raw_args, demo_page, banner_name, inactive_status and true or false), nil -- nil to disregard subsequent returned values end end  p.main = function(frame) 	local args = args_module.getArgs(frame, {frameOnly = true}) 	local raw_args = args_module.getArgs(frame, {frameOnly = true, removeBlanks = false}) 	return initialise(args, raw_args) end  -- Inactive projects ------  p.inactive = function(frame) 	local args = args_module.getArgs(frame, {frameOnly = true}) 	local project_name = args.PROJECT_NAME or 'উইকিপ্রকল্প ' .. (args.PROJECT or 'PROJECT') 	local project_link = mw.title.new(args.PROJECT_LINK or 'Wikipedia:' .. project_name) 	local _status = cfg.status[args.PROJECT_STATUS] or cfg.status.default_inactive 	local main_text = cfg.inactive.text:format( 		'_PAGETYPE_', 		project_link.prefixedText, 		project_name, 		_status 	) 	return initialise( 		{ 			PROJECT = args.PROJECT, 			BANNER_NAME = args.BANNER_NAME, 			IMAGE_LEFT = cfg.inactive.image, 			IMAGE_LEFT_SIZE = cfg.inactive.image_size, 			MAIN_TEXT = main_text, 			HOOK_NESTED_ASSESS = ' ' .. cfg.inactive.nested:format(_status), 			substcheck = args.substcheck, 			category = args.category 		}, { 			substcheck =  -- to prevent warning on templatepage 		}, _status 	) end  return p