Moduł:Brudnopis/Paweł Ziemian/Szablony

Z Wikipedii, wolnej encyklopedii

Dokumentacja dla tego modułu może zostać utworzona pod nazwą Moduł:Brudnopis/Paweł Ziemian/Szablony/opis

local FindPositionsInReverseOrder = function(text, plainPattern)
	local result = {}
	if #plainPattern > 0 then
		local init = 1
		while init do
			init = string.find(text, plainPattern, init, true)
			if init then
				table.insert(result, 1, init)
				init = init + #plainPattern
			end
		end
	end
	
	return result
end

local RemoveInPlace = function(text, start, len)
	local before = start > 1 and string.sub(text, 1, start-1) or ""
	local stop = start + len
	local after = stop <= #text and string.sub(text, stop) or ""
	return before..string.rep("_", len)..after
end

local function FindTemplates(contents)
	-- zgumkowanie obszarów nie podlegających szablonowej analize
	local text = contents
	-- komentarze HTML
	text = string.gsub(text, "<!%-%-.-%-%->", function(s) return string.rep('_', #s) end)
	-- sekcje <nowiki>
	text = string.gsub(text, "<nowiki>.-</nowiki>", function(s) return string.rep('_', #s) end)
	-- wzory matematyczne
	text = string.gsub(text, "<math>.-</math>", function(s) return string.rep('_', #s) end)
	-- tekst preformatowany
	text = string.gsub(text, "<pre>.-</pre>", function(s) return string.rep('_', #s) end)
	-- wikilinki iteracyjnie od końca
	for _, startPos in ipairs(FindPositionsInReverseOrder(text, "[[")) do
		local endPos = string.find(text, "]]", startPos, true)
		if endPos then
			local eol = string.find(text, "\n", startPos, true)
			if eol and (eol < endPos) then
				endPos = nil
			end
		end
		
		local len = endPos and (endPos - startPos + 2) or 2
		text = RemoveInPlace(text, startPos, len)
	end

	-- wyszukiwanie pozycji szablonów
	local templates = {}
	-- iteracyjnie od ostatniego
	for _, startPos in ipairs(FindPositionsInReverseOrder(text, "{{")) do
		local endPos = string.find(text, "}}", startPos, true)
		local len = endPos and (endPos - startPos + 2) or 2
		if (len > 2) then
			local template = string.sub(text, startPos, startPos+len-1)
			local separators = {}
			local init = 2
			while init  do
				init = string.find(template, "|", init, true)
				if init then
					table.insert(separators, startPos+init-1)
					init = init + 1
				end
			end
			
			local index = 0
			local m = {}
			local d = {}
			local hasDuplicates = false
			local params = {}
			for i, v in ipairs(separators) do
				local p = {
					start = separators[i],
					len = (separators[i+1] or endPos) - separators[i] - 1,
				}
				local param = string.sub(contents, p.start+1, p.start+p.len)
				local eqPos = string.find(param, "=", 1, true)
				if eqPos then
					p.name = mw.text.trim(string.sub(param, 1, eqPos-1))
					p.namelen = eqPos-1
					p.value = mw.text.trim(string.sub(param, eqPos+1))
				else
					index = index + 1
					p.name = tostring(index)
					p.value = param
				end
				table.insert(params, p)
				if not m[p.name] then
					m[p.name] = p
				elseif not d[p.name] then
					hasDuplicates = true
					d[p.name] = { m[p.name], p }
				else
					table.insert(d[p.name], p)
				end
			end
		
			table.insert(
				templates,
				1,
				{
					name       = mw.language.getContentLanguage():ucfirst(mw.text.trim(string.sub(contents, startPos+2, #separators > 0 and separators[1]-1 or startPos+len-3))),
					text       = string.sub(contents, startPos, startPos+len-1),
					start      = startPos,
					len        = len,
					params     = params,
					duplicates = hasDuplicates and d or nil,
				}
			)
		end

		text = RemoveInPlace(text, startPos, len)
	end

	mw.log("= Moduł:Brudnopis/Paweł Ziemian/Szablony =")
	return templates
end

local function AcceptableTitle(title)
	local ns = title.namespace
	if (ns == 10) or (ns == 828) then
		 -- z modułów lub szablonów tylko opis
		return title.isSubpage and (title.subpageText == "opis")
	elseif ns >= 0 then
		 -- z pozostałych przestrzeni byle nie plik
		return ns ~= 7
	else
		return false
	end
end

return AcceptableTitle(mw.title.getCurrentTitle()) and FindTemplates(mw.title.getCurrentTitle():getContent()) or {}