Spring til indhold

Modul:Arg filter

Page skabelon-beskyttet
Fra Wikipedia, den frie encyklopædi

-- Dette modul bruges af [[Skabelon:Infoboks med filter]]. Se skabelondokumentationen for detaljer.

-- Module to act as a filter between a template and another module
-- The transfered arguments from the template may be changed before calling the other module
-- The return value from the other module is returned unchanged

-- This module is made especially as a filter for Module:Infoboks.

-- WARNING: The arguments are transferred in another way than normal, and the current frame
-- is not transferred as normal. It may not work depending on how the called module interprets
-- its arguments and frame. This should work with Module:Infoboks. Check carefully before other uses.

local p = {}

-- Direct arguemnts (to be applied in #invoke call):
-- 1 argument: Module to call
-- 2 argument: Function to call in the module
-- 3 argument: Delimiter for parsing transfered template arguments

-- Arguments from the calling template:

-- If any argument contains the delimiter, it will be split into the parts between
-- occurances of the delimiter. The first part will be the new value for the argument.
-- Any subsequent parts will be spilt to <name>=<value> parts, and new arguments with
-- the given name and value will be created. Any existing arguments with the same names
-- will be overwritten. If the value part is empty, any existing argument with the name
-- will be removed without replacement.

-- If any argument starts with "arg filter fjern" then the rest of that argument names
-- an argument which may be deleted. The argument value is a comma separated list
-- of argument names. The argument in the argument name will be deleted if all of the
-- arguments in the argument list are not defined or only contains whitespace.

p.filter = function(frame)
	local my_args = frame.args

	local module = mw.text.trim(my_args[1] or '')
	local func = mw.text.trim(my_args[2] or '')
	local delim = mw.text.trim(my_args[3] or '')

	if module == '' or func == '' or delim == '' then
		return 'Error: Module Arg filter called without module, function or delimiter arguments'
	end

	local args
	if frame == mw.getCurrentFrame() then
		-- Arguments from the parent template
		args = frame:getParent().args
	else
		-- Try local given arguments for testing
		args = frame.args
	end

	local old_args = {}
	local changed_args = {}
	local deleted_args = {}
	local test_for_deletion = {}

	local mwText = mw.text
	local string = string

	for name, value in pairs(args) do
		if string.sub(name, 1, 16) == 'arg filter fjern' then
			test_for_deletion[mwText.trim(string.sub(name, 17))] = value
		else
			local first_part = true
			for part in mwText.gsplit(value, delim, true) do
				if first_part then
					old_args[name] = part
					first_part = nil
				else
					local new_name, new_value = string.match(part, '^(.-)=(.*)$')
					if new_name then
						new_name = mwText.trim(new_name)
						if new_name ~= '' then
							if new_value ~= '' then
								changed_args[new_name] = new_value
							else
								deleted_args[new_name] = true
							end
						end
					end
				end
			end
		end
	end

	for name, value in pairs(changed_args) do
		old_args[name] = value
	end

	for name, value in pairs(deleted_args) do
		old_args[name] = nil
	end

	for name, value in pairs(test_for_deletion) do
		if old_args[name] then
			local found_not_empty_arg
			for arg in mwText.gsplit(value, ',', true) do
				arg = mwText.trim(arg)
				if old_args[arg] and mwText.trim(old_args[arg]) ~= '' then
					found_not_empty_arg = true
					break
				end
			end
			if found_not_empty_arg == nil then
				old_args[name] = nil
			end
		end
	end

	-- I cannot change the current frame. It is no use to create a new frame for calling Module:Infoboks
	-- because it tests if the passed frame argument is really the current frame or not. Instead just
	-- pass the changed args alone as Module:Infoboks will assume that it is args when not the current frame. 
	return require(module)[func](old_args)
end

return p