Edge Rewrite
// HTMLRewriter · presentation

This page was redesigned at the edge.

Cloudflare fetched the original article and streamed it through HTMLRewriter to apply an entirely new visual system without rebuilding the source page.

Jump to content

Module:MultiReplace/sandbox

From Wikipedia, the free encyclopedia
require[[strict]]


	---                                        ---
	---     PRIVATE ENVIRONMENT                ---
	---    ________________________________    ---
	---                                        ---



-- Get the actual arguments
local function get_args (frame, ...)
	return type(frame) ~= 'table' and { frame, ... } or
		type(frame.args) ~= 'table' and frame or
		frame.args[1] and frame.args or
		frame:getParent().args
end


-- Copied from Module:String's `str._escapePattern()`
local function escape_pattern (str)
	return (string.gsub(str, "[%(%)%.%%%+%-%*%?%[%^%$%]]", "%%%0"))
end


	---                                        ---
	---     PUBLIC ENVIRONMENT                 ---
	---    ________________________________    ---
	---                                        ---



local iface = {}


-- Syntax:  #invoke:multiReplace|singlepass|[plain=yes (optional)]|pattern1|
--            replacement1|pattern2|replacement2|...|
iface.singlepass = function (frame, ...)
	local args = get_args(frame, ...)
	local argc, seq, txt, plain =
		0, {}, args[1] or '{{{1}}}', args.plain == 'yes'
	for key, val in ipairs(args) do argc, seq[key] = argc + 1, val end
	if argc % 2 == 0 then
		error('Module:MultiReplace, ‘singlepass’: Unpaired argument: <code>'
			.. argc .. ' = ' .. mw.text.nowiki(seq[argc]) .. '</code>', 0)
	end
	local start, bestStart, bestStop, bestChange
	local len, pos, result, maps, rlen = mw.ustring.len(txt), 1, {}, {}, 0
	for idx = 2, argc, 2 do
		maps[idx - 1], maps[idx] =
			mw.ustring.find(txt, seq[idx], pos, plain)
	end
	while pos <= len do
		bestStart, bestStop, bestChange = len + 1, len, nil
		for idx = 2, argc, 2 do
			start = maps[idx - 1]
			if start and start < pos then
				maps[idx - 1], maps[idx] = mw.ustring.find(txt,
					seq[idx], pos, plain)
				start = maps[idx - 1]
			end
			if start and start < bestStart then
				bestStart, bestStop, bestChange =
					start, maps[idx], idx
			end
		end
		rlen = rlen + 1
		result[rlen] = mw.ustring.sub(txt, pos, bestStart - 1)
		if bestChange then
			maps[bestChange - 1], maps[bestChange] =
				mw.ustring.find(txt, seq[bestChange],
					maps[bestChange] + 1, plain)
			rlen = rlen + 1
			result[rlen] = (plain and seq[bestChange + 1] or
				mw.ustring.gsub(mw.ustring.sub(txt, bestStart,
					bestStop), seq[bestChange],
					seq[bestChange + 1], 1))
		end
		pos = bestStop + 1
	end
	return table.concat(result)
end


-- Syntax:  #invoke:multiReplace|cascade|[plain=yes (optional)]|pattern1|
--            replacement1|pattern2|replacement2|...|
iface.cascade = function (frame, ...)
	local args, argc = get_args(frame, ...), 0
	for _ in ipairs(args) do argc = argc + 1 end
	if argc % 2 == 0 then
		error('Module:MultiReplace, ‘cascade’: Unpaired argument: <code>'
			.. argc .. ' = ' .. mw.text.nowiki(args[argc]) .. '</code>', 0)
	end
	local txt = args[1] or '{{{1}}}'
	if args.plain == 'yes' then
		for idx = 2, argc, 2 do
			txt = mw.ustring.gsub(txt, escape_pattern(args[idx]),
				args[idx + 1])
		end
	else
		for idx = 2, argc, 2 do
			txt = mw.ustring.gsub(txt, args[idx], args[idx + 1])
		end
	end
	return txt
end


-- For compatibility reasons; must not be documented; to delete in the future
iface.main = iface.singlepass


return iface