Module:Archives

From BoyWiki
Revision as of 17:00, 22 June 2022 by Etenne (talk | contribs) (Created page with "p = {} local cfg = mw.loadData('Module:Archives/config') local function is_filled(var) return var and var ~= '' end -- simple helper for simple cases local function var_or_default(var, default) if is_filled(var) then return var else return default end end local function wikilink(link, display) if display then return '' .. display .. '' else return '' .. link .. '' end end local function talk_other(demospace, talk) if is_filled(...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Documentation for this module may be created at Module:Archives/doc

p = {}

local cfg = mw.loadData('Module:Archives/config')

local function is_filled(var)
	return var and var ~= ''
end

-- simple helper for simple cases
local function var_or_default(var, default)
	if is_filled(var) then
		return var
	else
		return default
	end
end

local function wikilink(link, display)
	if display then
		return '[[' .. link .. '|' .. display .. ']]'
	else
		return '[[' .. link .. ']]'
	end
end

local function talk_other(demospace, talk)
	if is_filled(demospace) then return demospace end
	
	if mw.title.getCurrentTitle().isTalkPage then return talk end
	
	return nil -- just return nil rather than 'other' since we have no need
end


local function add_image(image)
	if image.image and (image.image == 'none' or image.image == '') then return nil end

	return mw.html.create('div'):addClass('archives-image'):wikitext(
		require('Module:InfoboxImage/sandbox')._InfoboxImage({
			[cfg.img_mod.image] = var_or_default(image.image, cfg.image),
			[cfg.img_mod.alt] = var_or_default(image.alt, cfg.img_mod.alt_none),
			[cfg.img_mod.link] = var_or_default(image.link, cfg.img_mod.link_none),
			[cfg.img_mod.size] = var_or_default(image.size, nil),
			[cfg.img_mod.sizedefault] = cfg.image_size
		})
	)
end

local function auto_list(list_root, is_banner, list_auto, list_prefix)
	local list_args = {}
	
	if list_root then
		list_args.root = list_root
	else
		list_args.DISABLE1 = list_root
	end
	
	if is_banner then
		list_args.nobr = 'yes'
		list_args.DISABLE2 = list_auto or 'long'
	else
		list_args.nobr = 'no'
		list_args.auto = list_auto or 'long'
	end
	
	if list_prefix then
		list_args.prefix = list_prefix
	else
		list_args.DISABLE3 = list_prefix
	end
	
	return require('Module:Archive list').main(list_args)
end

local function make_title(is_banner, title)

end

local function search_box(frame, is_banner, root, search)

	if search.search and search.search == cfg.search_no then return nil end
	
	local prefix = ''
	if is_filled(search.prefix) then
		prefix = search.prefix
	-- this double-check elseif may move out to code-proper
	elseif is_filled(root) then
		prefix = root
	else
		prefix = mw.title.getCurrentTitle().prefixedText .. '/'
	end
	
	-- break
	local sbreak
	if search.sbreak and (search.sbreak == 'yes' or search.sbreak == 'no') then
		sbreak = search.sbreak
	end
	-- set sbreak's default
	if not sbreak then
		if is_banner then
			sbreak = 'no'
		else
			sbreak = 'yes'
		end
	end
	
	-- width
	local width = ''
	if not is_banner then
		width = var_or_default(search.width, cfg.search_width)
	end
	
	-- label
	local label = var_or_default(search.label, cfg.search_label)
	
	local inputbox_options = {
		['bgcolor'] = 'transparent',
		['type'] = 'fulltext',
		['prefix'] = prefix,
		['break'] = sbreak,
		['width'] = width,
		['searchbuttonlabel'] = label
	}
	
	local inputbox_content = {}
	for k, v in pairs(inputbox_options) do
		table.insert(inputbox_content, k .. '=' .. v)
	end

	return mw.html.create('div'):addClass('archives-search'):wikitext(frame:extensionTag{
		name = 'inputbox',
		content = table.concat(inputbox_content, '\n')
	})
end

local function note_auto(frame, auto)
	if not is_filled(auto.age) and not is_filled(auto.target) then return nil end
	
	local age = var_or_default(auto.age, nil)
	local target = var_or_default(auto.target, nil)
	
	local target_text = ''
	if target then
		target_text = mw.ustring.format(
			cfg.has_archives,
			frame:callParserFunction( '#rel2abs', target ),
			age and ' ' or ''
		)
	end
	local age_text = ''
	if age then
		local units = var_or_default(auto.units, cfg.units)
		-- there's probably a friendlier l10n way to do this check on units...
		-- TODO make it friendlier. maybe split it to a separate function?
		-- (borrowed from Module:String.endswith in the meantime)
		if age ~= '1' and mw.ustring.sub(units, -1, -1) ~= 's' then
			units = units .. 's'
		end
		
		-- TODO localize
		local age_with_units = age .. ' ' .. units
		
		local has_bot = is_filled(auto.bot)
		local has_minthreads = is_filled(auto.minthreads)
		if has_bot and has_minthreads then
			age_text = mw.ustring.format(
				cfg.age_bot_threads,
				age_with_units,
				wikilink('User:' .. auto.bot, auto.bot),
				var_or_default(auto.minthreads, cfg.min_threads)
			)
		elseif has_bot then
			age_text = mw.ustring.format(
				cfg.age_bot,
				age_with_units,
				wikilink('User:' .. auto.bot, auto.bot)
			)
		elseif has_minthreads then
			age_text = mw.ustring.format(
				cfg.age_threads,
				age_with_units,
				var_or_default(auto.minthreads, cfg.min_threads)
			)
		else
			age_text = mw.ustring.format(
				cfg.age,
				age_with_units
			)
		end
	end
	
	return mw.html.create('div'):addClass('archives-auto'):wikitext(target_text .. age_text)
end

local function edit_list(frame, auto, list1, archive_list, archive_list_exists, editbox)
	
	local has_editbox = not editbox or (editbox and (editbox == '' or editbox == 'yes'))
	if not (archive_list_exists and has_editbox and not auto and list1) then
		return nil
	end
	
	return mw.html.create('div'):addClass('archives-edit'):wikitext(mw.ustring.format(
		cfg.edit_this_box,
		archive_list.fullUrl('action=edit' .. cfg.pre_load)
	))
end

local function render_list(root, auto, list1, archive_list_title, archive_list_exists, list, index, prefix)
	-- this logic is seriously fucking screwy
	-- only hope is for the test cases to catch the insanity
	local auto_default = true
	if list1 then
		auto_default = false
	end

	local is_foreign = true
	if (auto and auto == 'no') or (not auto and not auto_default) then
		is_foreign = false
	end
	local foreign_archive_list = ''
	local list = var_or_default(content.list, nil)
	if not list and is_foreign then
	
		local index_page = frame:callParserFunction(
			'#rel2abs',
			var_or_default(content.index, './Archive index')
		)
		local index_link = ''
		if mw.title.new(index_page).exists then
			index_link = wikilink(index_page, 'Index')
		end

		local prefix = var_or_default(content.prefix, nil)
		if archive_list_exists then
			foreign_archive_list = frame:expandTemplate{ title = archive_list_name}
		else
			foreign_archive_list = auto_list(root, is_banner, auto, prefix)
		end
		
		foreign_archive_list = index_link .. foreign_archive_list
	end
	
	local local_archive_list = ''
	if list or list1 then
		local_archive_list = '\n' .. (list or list1)
	end
	
	return foreign_archive_list .. local_archive_list

end

local function add_main_content(frame, is_banner, content)
	
	local is_collapsible = false
	local is_collapsed = false
	if content.collapsible and content.collapsible == 'yes' then
		is_collapsible = true
	end
	if content.collapsed and content.collapsed == 'yes' then
		is_collapsed = true
		is_collapsible = true
	end
	local root = var_or_default(content.root, nil)
	local auto = var_or_default(content.auto, nil)
	local list1 = var_or_default(content.list1, nil)
		
	local archive_list_name = frame:callParserFunction(
		'#rel2abs',
		var_or_default(content.archive_list, cfg.archive_list)
	)
	local archive_list_title = mw.title.new(archive_list_name)
	local archive_list_exists = archive_list_title.exists
	
	local all_lists = render_list(
		root,
		auto,
		list1,
		archive_list_title,
		archive_list_exists,
		content.list,
		content.index,
		content.prefix
	)
	
	local main_content = mw.html.create()
	main_content
		:tag('div')
			:addClass('archives-flex-child')
			:wikitext(all_lists)
			:node(search_box(frame, is_banner, root, content.search))
			:node(note_auto(frame, content.auto_explanation))
			:node(edit_list(
				frame, auto, list1, archive_list_title, archive_list_exists, content.editbox
			))

	return main_content
end




--[[
pass the frame down for a minute because we do a lot of work with a frame

]]
function p._main(args, frame)

	local is_banner = false
	if (args[cfg.arg.banner] and args[cfg.arg.banner] == cfg.banner_yes) or
		(args[cfg.arg.large] and args[cfg.arg.large] == cfg.banner_yes) then
		is_banner = true
	end
	
	local archives = mw.html.create()
	archives
		:tag('div')
			:addClass('archives plainlinks')
			-- banner is roughly mbox, small is roughly mbox-small
			:addClass(is_banner and 'archives-banner' or 'archives-small')
			-- archives-talk has same-ish styles as tmbox tmbox-notice
			-- base styles are same-ish as ombox ombox-notice
			:addClass(talk_other(
				var_or_default(args[cfg.arg.demospace], nil),
				'archives-talk'
			))
			:css('width', var_or_default(args[cfg.arg.box_width], nil))
			:cssText(var_or_default(args[cfg.arg.style], nil))
			
			:node(add_image({
				image = args[cfg.arg.image],
				alt = args[cfg.arg.alt],
				link = args[cfg.arg.link],
				size = args[cfg.arg.image_size]
			}))
			:node(add_main_content(frame, is_banner, {
				archive_list = args[cfg.arg.archive_list],
				auto = args[cfg.arg.auto],
				collapsible = args[cfg.arg.collapsible],
				collapsed = args[cfg.arg.collapsed],
				edit_box = args[cfg.arg.edit_box],
				index = args[cfg.arg.index],
				list = args[cfg.arg.list],
				list1 = args[cfg.arg.list1],
				prefix = args[cfg.arg.prefix],
				root = args[cfg.arg.root],
				title = args[cfg.arg.title],
				search = {
					search = args[cfg.arg.search],
					prefix = args[cfg.arg.search_prefix],
					width = args[cfg.arg.search_width],
					sbreak = args[cfg.arg.search_break],
					label = args[cfg.arg.search_button_label]
				},
				auto_explanation = {
					age = args[cfg.arg.age],
					target = args[cfg.arg.target],
					units = args[cfg.arg.units],
					bot = args[cfg.arg.bot],
					minthreads = args[cfg.arg.minthreads]
				}
			}))

	return frame:extensionTag{
		name = 'templatestyles', args = { src = cfg.templatestyles }
	} .. tostring(archives)
end

function p.main(frame)
	return p._main(require('Module:Arguments').getArgs(frame), frame)
end

return p