Przejdź do zawartości

Moduł:Brudnopis/Paweł Ziemian/test

Z Wikipedii, wolnej encyklopedii

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

local m = {}

m["wartość"] = function(frame)
	local msg = frame.args.msg
	local value = tonumber(frame.args[1]) or frame.args[1]
	local index = 2 -- pierwszy wzór
	while value do
		local pattern = frame.args[index]
		if not pattern then
			break -- nie ma więcej wzorów
		end
		
		if mw.ustring.match(value, "^"..pattern.."$") then
			return -- wzór pasuje, nie ma błędów
		end
		
		-- następny wzór
		index = index + 1
	end
	
	-- komunikat błędu
	return msg
end


m["lista nazw niepustych argumentów"] = function(frame)
	local argNames = {}
	for k, v in pairs(frame:getParent().args) do
		if #mw.text.trim(v) > 0 then
			table.insert(argNames, tostring(k))
		end
	end
	
	return table.concat(argNames, ",")
end

function m.Wrap(frame)
	
	local blockPatterns = {
		"\n[*:;#]", -- wikilista
		"\n\n", -- wikiakapit
		"\n{|", -- wikitabela
		"<[Pp][ >]", -- <p>
		"<[Hh][Rr1-6][ >]", -- <hr>, <h1>..<h6>
		"<[UuOoDd][Ll][ >]", -- <ul><ol><dl>
		"<[Ll][Ii][ >]", -- <li>
		"<[Dd][DdTt][ >]", -- <dd><dt>
		"<[Dd][Ii][Vv][ >]", -- <div>
		"<[Tt][Aa][Bb][Ll][Ee][ >]", -- <table>
		"<[Bb][Ll][Oo][Cc][Kk][Qq][uu][Oo][Tt][Ee][ >]", -- <blockquote>
	}
	
	local text = frame.args[1]
	mw.logObject(text, "WRAP: text")
	if not text or (#text == 0) then
		mw.logObject(pattern, "WRAP: empty")
		return
	end
	
	local lead = frame.args.leadInline or ""
	local tail = frame.args.tailInline or ""

	for i, pattern in ipairs(blockPatterns) do
		local catch = mw.ustring.match(text, pattern)
		if catch then
			mw.logObject(pattern, "WRAP: pattern")
			mw.logObject(catch, "WRAP: catch")
			lead = frame.args.leadBlock or ""
			tail = frame.args.tailBlock or ""
			break
		end
	end
	
	mw.logObject(lead,"WRAP: lead")
	mw.logObject(tail,"WRAP: tail")
	return lead..text..tail
end

function m.ListaCech(frame)
	local t = frame.args["tytuł"] or "[[Kontrola autorytatywna]]"
	local e = frame.args["pusto"]
	local sd = require("Module:Wikidane/select")
	local f = require("Module:Wikidane/format")
	local result = {}
	local i = 1
	while true do
		local p = frame.args[i]
		if not p then
			break
		end
		
		local pid, qid, prop = sd.selectProperty(p, {})
		if qid then
			local ppid, pqid, pprop = sd.selectProperty("P1629", {}, pid)
			if pqid then
				local s = "\n*"..f.run(frame, ppid, pprop)..":&nbsp;"..f.run(frame, pid, prop)
				table.insert(result, s)
			end
		end
		
		i = i + 1
	end
	
	if #result > 0 then
		table.insert(result, 1, '<div class="catlinks">')
		table.insert(result, 2, t)
		local pid, qid, prop = sd.selectProperty("P31", {}, nil, 1)
		table.insert(result, 3, qid and (" ("..f.run(frame, pid, prop).."):") or ":")
		table.insert(result, "</div>")
		return table.concat(result)
	end
	
	return e
end

function m.PolaZAutorami(frame)
	local result = {}
	local nazwisko = frame.args["nazwisko"]
	local imie = frame.args["imię"]
	local autor = frame.args["autor"]
	local link = frame.args["link"]
	local maxIndex = tonumber(frame.args["max"])
	local prefix = frame.args["przed"] or ""
	local suffix = frame.args["po"] or ""
	for i = 1, maxIndex do
		local s = i == 1 and "" or tostring(i)
		local nin = string.gsub(nazwisko, '#', s)
		local iin = string.gsub(imie, '#', s)
		local ain = string.gsub(autor, '#', s)
		local lin = string.gsub(link, '#', s)
		local niv = frame:getParent().args[nin]
		local iiv = frame:getParent().args[iin]
		local aiv = frame:getParent().args[ain]
		local liv = frame:getParent().args[lin]
		local nis = niv and (#niv > 0)
		local iis = iiv and (#iiv > 0)
		local ais = aiv and (#aiv > 0)
		local lis = liv and (#liv > 0)
		local bad = (nis and ais) -- nazwisko -> zbędny autor
			or (nis and not iis) -- nazwisko bez imienia
			or (lis and not nis and not ais) -- tylko link
			or (iis and not nis) -- imię bez nazwiska
		if bad then
			table.insert(result, i)
		end
	end

	if #result > 0 then
		return prefix..mw.text.listToText(result)..suffix
	end
end

function m.BezParametrow(frame)
	for k, v in pairs(frame:getParent().args) do
		return nil
	end
	
	return "tak"
end

function m.Klad(frame)
	local demo = {
		["label1"] = "baza1",
		[1] = "węzeł1",
		["label2"] = "baza2",
		[2] = "węzeł2",
		["label3"] = "baza3",
		--[3] = "węzeł3",
		["3.label1"] = "baza3.1",
		["3.1"] = "węzeł3.1",
		["3.label2"] = "baza3.2",
		["3.2"] = "węzeł3.2",
		["3.3.1.1.1.1"] = "węzeł3.3.1.1.1.1",
		["label4"] = "baza4",
		[4] = "węzeł4",
	}
	
	local tree = {}
	
	local data
	if frame and frame.getParent then
		data = frame:getParent().args
	end
	if not data and frame and frame.args then
		data = frame.args
	end
	if not data then
		data = demo
	end

	for k, v in pairs(data) do
		local keys = mw.text.split(k,'.',true)
		local index = keys[#keys]
		if #keys > 1 then
			for i = 1, #keys-1 do
				keys[i] = tonumber(string.match(keys[i], "^[0-9][0-9]?$"))
				if not keys[i] or (keys[i] == 0) then
					mw.logObject(keys,"failed-keys")
					index = false
					break
				end
			end
		end
		
		if index then
			mw.logObject(keys,"insert-keys")
			local node = tree
			for i = 1, #keys-1 do
				local k = keys[i]
				local child = node[k]
				if not child then
					child = {}
					node[k] = child
				end
				
				node = child
			end
			
			node[tonumber(index) or index] = v
			mw.logObject(tree,"updated-tree")
		end
	end
	
	mw.logObject(tree,"tree")
	
	function klad(lista)
		local result = {}
		local style = lista.style or ""
		local thickness = tostring(tonumber(lista.thickness) or 1)
		table.insert(result, '{| cellspacing=0 cellpadding=0 border=0 style="'..style..'"\n')
		for i, v in ipairs(lista) do
			local text
			local labelName = "label"..tostring(i)
			local label = lista[labelName] or "<br />"
			if type(v) == "string" then
				text = v
			elseif type(v) == "table" then
				text = klad(v)
			end
			
			if i == 1 then
				table.insert(result, '| style="width:1.5em;border-bottom:'..thickness..'px solid black;" valign=bottom align=center | '..label..' || rowspan=2 |\n')
				table.insert(result, text or "{{{1}}}")
				table.insert(result, '\n|-\n')
			elseif text and #text > 0 then
				table.insert(result, '| style="border-left:'..thickness..'px solid black;" valign=top |<br/>\n')
				table.insert(result, '|-\n')
				table.insert(result, '| style="border-left:'..thickness..'px solid black; border-bottom:'..thickness..'px solid black;" valign=bottom align=center | '..label..' || rowspan=2 |\n')
				table.insert(result, text)
				table.insert(result, '\n|-\n')
			end
		end
		
		table.insert(result, '| valign=top | <br/>\n')
		table.insert(result, '|}')
		return table.concat(result)
	end
	
	return klad(tree)
end

function m.Kladogram(frame)
	local demo = [[
	"label1":"baza1",
	"1":"węzeł1",

	"label2":"baza2",
	"2":"węzeł2",

	"label3":"baza3",
	"3": {
		"label1":"baza3.1",
		"1":"węzeł3.1",

		"label2":"baza3.2",
		"2":"węzeł3.2"
	},

	"label4":"baza4",
	"4":"węzeł4"
]]
	
	function klad(lista)
		local result = {}
		local style = lista.style or ""
		local thickness = tostring(tonumber(lista.thickness) or 1)
		table.insert(result, '{| cellspacing=0 cellpadding=0 border=0 style="'..style..'"\n')
		for i, v in ipairs(lista) do
			local text
			local labelName = "label"..tostring(i)
			local label = lista[labelName] or "<br />"
			if type(v) == "string" then
				text = v
			elseif type(v) == "table" then
				text = klad(v)
			end
			
			if i == 1 then
				table.insert(result, '| style="width:1.5em;border-bottom:'..thickness..'px solid black;" valign=bottom align=center | '..label..' || rowspan=2 |\n')
				table.insert(result, text or "{{{1}}}")
				table.insert(result, '\n|-\n')
			elseif text and #text > 0 then
				table.insert(result, '| style="border-left:'..thickness..'px solid black;" valign=top |<br/>\n')
				table.insert(result, '|-\n')
				table.insert(result, '| style="border-left:'..thickness..'px solid black; border-bottom:'..thickness..'px solid black;" valign=bottom align=center | '..label..' || rowspan=2 |\n')
				table.insert(result, text)
				table.insert(result, '\n|-\n')
			end
		end
		
		table.insert(result, '| valign=top | <br/>\n')
		table.insert(result, '|}')
		return table.concat(result)
	end
	
	local data
	if frame and frame.getParent then
		data = frame:getParent().args[1]
	end
	if not data and frame and frame.args then
		data = frame.args[1]
	end
	if not data then
		data = demo
	end

	local text = klad(mw.text.jsonDecode('{'..data..'}'))
	mw.log(text)
	return text
end

function m.Encode(frame)
	local html = frame.args.html
	return html and mw.text.encode(html) or html
end

function wczytajWladcow(title, data)
	local map = {}
	for i, g in ipairs(data) do
		map[g.header] = g
	end
	
	local group = false
	local merge = false
	for line in mw.ustring.gmatch(title:getContent(), "[^\n]+") do
		local h = mw.ustring.match(line, "^==%s*([^=%s].-[^=%s])%s*==$")
		if h then
			if group and group.items and not map[group.header] then
				table.insert(data, group)
			end
	
			group = map[h] or { header = h }
			merge = group.items ~= nil
		elseif group then
			local s, e, n = mw.ustring.match(line, "^%s+(%-?[0-9]+)%s+(%-?[0-9]+)%s+(.-)%s*$")
			s = tonumber(s)
			e = tonumber(e)
			if s and e and n then
				if not group.items then
					group.items = {}
				end
				
				local add = true
				if merge then
					merge = false
					if #group.items > 0 then
						local last = group.items[#group.items]
						add = (last[1] ~= s) or (last[2] ~= e) -- or (last[3] ~= n)
					end
				end

				if add then
					table.insert(group.items, { s, e, n } )
				end
			end
		end
	end
	
	if group and group.items and not map[group.header] then
		table.insert(data, group)
	end
end

function m.ListaWladcow(frame)
	-- mw.title.new( "Tabele władców", "Szablon" )
	local allData = {}
	wczytajWladcow(mw.title.new( "Paweł_Ziemian/Tabele_władców/Polska", "Wikipedysta" ), allData)
	wczytajWladcow(mw.title.new( "Paweł_Ziemian/Tabele_władców/p.n.e.", "Wikipedysta" ), allData)
	wczytajWladcow(mw.title.new( "Paweł_Ziemian/Tabele_władców/n.e.", "Wikipedysta" ), allData)
	wczytajWladcow(mw.title.new( "Paweł_Ziemian/Tabele_władców/XI", "Wikipedysta" ), allData)
	wczytajWladcow(mw.title.new( "Paweł_Ziemian/Tabele_władców/XII", "Wikipedysta" ), allData)
	wczytajWladcow(mw.title.new( "Paweł_Ziemian/Tabele_władców/XIII", "Wikipedysta" ), allData)
	wczytajWladcow(mw.title.new( "Paweł_Ziemian/Tabele_władców/XIV", "Wikipedysta" ), allData)
	wczytajWladcow(mw.title.new( "Paweł_Ziemian/Tabele_władców/XV", "Wikipedysta" ), allData)
	wczytajWladcow(mw.title.new( "Paweł_Ziemian/Tabele_władców/XVI", "Wikipedysta" ), allData)
	wczytajWladcow(mw.title.new( "Paweł_Ziemian/Tabele_władców/XVII", "Wikipedysta" ), allData)
	wczytajWladcow(mw.title.new( "Paweł_Ziemian/Tabele_władców/XVIII", "Wikipedysta" ), allData)
	wczytajWladcow(mw.title.new( "Paweł_Ziemian/Tabele_władców/XIX", "Wikipedysta" ), allData)
	wczytajWladcow(mw.title.new( "Paweł_Ziemian/Tabele_władców/XX", "Wikipedysta" ), allData)
	wczytajWladcow(mw.title.new( "Paweł_Ziemian/Tabele_władców/XXI", "Wikipedysta" ), allData)
	
	--local allData = mw.loadData("Moduł:Tabela władców/dane")
	
	local yearToString = function(y, prefix)
		if y == 9999 then
			return ""
		end
		
		local text = y < 0 and tostring(-y).." p.n.e." or tostring(y)
		return prefix.."[["..text.."]]"
	end
	
	local textToString = function(t)
		local result, _ = mw.ustring.gsub(t, "\\n", " ")
		return result
	end
	
	local result = {}
	for _, v in ipairs(allData) do
		table.insert(result,"==")
		table.insert(result,textToString(v.header))
		table.insert(result,"==")
		for _, i in ipairs(v.items) do
			table.insert(result, "\n*")
			table.insert(result,textToString(i[3]))
			table.insert(result, " (")
			if i[1] == i[2] then
				table.insert(result,yearToString(i[1], "w "))
			else
				table.insert(result,yearToString(i[1], "od "))
				table.insert(result,yearToString(i[2], " do "))
			end
			table.insert(result, ")")
		end
		table.insert(result,"\n\n")
	end
	
	local text = table.concat(result, "")
	--mw.logObject(text, "text")
	return text
end

function m.Number(frame)
	local s = frame.args[1] or ""
	local n, _ = string.gsub(s or "", '%s', '');
	local r = mw.getContentLanguage():parseFormattedNumber(n) or s
	mw.logObject({s, n, r}, "snr")
	return r
end

function m.NoWrapDates(frame)
	local yes = "tak"
	local fixedDates = {}
	local fixedMarkerFormat = "\127_FixedDate%d_\127"
	local fixedMarkerPattern = "\127_FixedDate(%d+)_\127"
	local patterns = {
		"%[%[(%d%d?)%s+(%l+)%]%]%s+%[%[(%d%d%d%d) p%.n%.e%.%]%]",
		"(%d%d?)%s+(%l+)%s+(%d%d%d%d) p%.n%.e%.",
		"%[%[(%d%d?)%s+(%l+)%]%]%s+%[%[(%d%d%d%d)%]%]",
		"(%d%d?)%s+(%l+)%s+(%d%d%d%d)",
	}
	local months = require("Moduł:Cytuj/dane").monthparser
	
	function customPattern(variant, plain)
		if not variant then
			return ""
		elseif #variant == 0 then
			return "%s*"
		elseif plain then
			return mw.ustring.gsub( variant, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" )
		else
			return variant
		end
	end
	
	local text = frame.args[1]
	local plain = (frame.args.plain == yes) or (frame.args.plain == 1)
	local attachLeft = "("..customPattern(frame.args.left, plain)
	local attachRight = customPattern(frame.args.right, plain)..")"

	function NoWrapDate(full, day, month, year)
		local d = tonumber(day)
		local m = months[month]
		local y = tonumber(year)
		
		if not months[month] or (d <= 0) or (d > 31) then
			return null
		end
		
		local result = mw.html.create("span")
			:css("white-space", "nowrap")
			:wikitext(full)
		table.insert(fixedDates, tostring(result))
		local fixedIndex = #fixedDates
		return string.format(fixedMarkerFormat, fixedIndex)
	end
	
	for i, v in ipairs(patterns) do
		text, _ = mw.ustring.gsub(text, attachLeft..v..attachRight, NoWrapDate)
	end

	text = string.gsub(text, fixedMarkerPattern, function(n) return fixedDates[tonumber(n)] end)
	return text
end

function m.Czywiesz(frame)
	local textRequired = "brak"
	local classRequired = "czywiesz-brak"
	local cssRequired = {
		color = 'red',
		['font-weight'] = 'bold'
	}
	
	local id = mw.wikibase.getEntityIdForTitle(frame.args[1])
	if not id then
		return tostring(mw.html.create("span"):addClass(classRequired):css(cssRequired):wikitext(textRequired))
	end

	local result = mw.html.create("dl")
	
	function appendProperty(mandatory, prop)
		if prop and prop.label and prop.value and (#prop.value > 0) then
			result:tag("dt"):wikitext(prop.label)
			result:tag("dd"):wikitext(prop.value)
		elseif mandatory and prop and prop.label then
			result:tag("dt"):addClass(classRequired):wikitext(prop.label)
			result:tag("dd"):addClass(classRequired):css(cssRequired):wikitext(textRequired)
		end
	end

	local entity = mw.wikibase.getEntity(id)
	local label, lang = entity:getLabelWithLang('pl')
	appendProperty(true, { label="etykieta", value = lang == 'pl' and label or false})
	local description, lang = entity:getDescriptionWithLang('pl')
	appendProperty(true, { label="opis", value = lang == 'pl' and description or false})
	appendProperty(true, { label="liczba cech", value = tostring(#entity:getProperties())})
	appendProperty(false, entity:formatStatements('P31'))
	appendProperty(false, entity:formatStatements('P279'))

	mw.logObject(tostring(result),"tostring(result)")
	return tostring(result)
end

function m.JSON(frame)
	local result = {}
	local args = frame:getParent().args
	for k, v in pairs(frame:getParent().args) do
		result[k] = v
	end
	
	return mw.text.jsonEncode(result)
end

function m.Navbox(frame)
	local text = frame.args and frame.args[1] or frame[1]
	mw.logObject(text, "text")
	if not text then
		return text
	end
	
	local navbox = "navbox"
	local navboxSubGroup = "navbox-subgroup"
	local navboxList = "navbox-list"
	local navboxOdd = "navbox-odd"
	local navboxEven = "navbox-even"
	
	local classes = {}
	local i = 1
	while true do
		local s, e, c = mw.ustring.find(text, "class%s*=%s*\"([^\"]-%f[%a]navbox%f[^%a][^\"]*)\"", i)
		if not c then
			break
		end
		
		local cc = mw.text.split(c,"%s+")
		local w = false
		for _, v in ipairs(cc) do
			if (v == navbox) or (v == navboxSubGroup) then
				mw.logObject({s, e, w, c, cc}, mw.ustring.sub(text, s, e))
				table.insert(classes, { c, list=false })
				break
			elseif v == navboxList then
				mw.logObject({s, e, w, c, cc}, mw.ustring.sub(text, s, e))
				table.insert(classes, { c, list=true, c=cc, s=s, e=e })
				break
			end
		end
		
		i = e + 1
	end
	mw.log("-------------------------------------------")
	mw.logObject(classes, "classes")	
	local lists = {}
	local oddParity = true
	for i = 1, #classes do
		if classes[i].list then
			local nextIsList = i >= #classes or classes[i + 1].list
			local cc = {}
			for _, v in ipairs(classes[i].c) do
				if (v ~= navboxOdd) and (v ~= navboxEven) then
					table.insert(cc, v)
				end
			end
			
			if not nextIsList then
				mw.logObject(i, "L+G")
			else
				mw.logObject(i, "L+L")
				table.insert(cc, oddParity and navboxOdd or navboxEven)
				oddParity = not oddParity
			end
			
			local ccc = 'class="'..table.concat(cc, ' ')..'"'
			table.insert(lists, { s = classes[i].s, e = classes[i].e, c = ccc })
		else
			mw.logObject(i, "G")
		end
	end

	mw.log("-------------------------------------------")
	mw.logObject(lists, "lists")
	if #lists == 0 then
		return text
	end
	
	local fragments = {}
	local start = 1
	for _, l in ipairs(lists) do
		table.insert(fragments, mw.ustring.sub(text, start, l.s-1))
		table.insert(fragments, l.c)
		start = l.e + 1
	end
	
	mw.log("-------------------------------------------")
	mw.logObject(fragments, "fragments")
	table.insert(fragments, mw.ustring.sub(text, start, #text))
	local result = table.concat(fragments, "")
	
	mw.log("-------------------------------------------")
	mw.logObject(result, "result")
	return result
end

function m.Szablony(frame)
	local templates = mw.loadData("Moduł:Brudnopis/Paweł Ziemian/Szablony")
	mw.logObject(templates, "=== templates ===")
	return mw.text.jsonEncode(templates)
end

function m.s1(frame)
	local a = frame.args and frame.args[1] or frame[1]
	local b = tostring(a)
	local r = {}
	if #b > 0 then
		for i = 1, #b do
			local c = string.byte(b, i)
			if (c <= 32) or (c >= 127) or (c == 34) or (c == 39) then
				table.insert(r, tostring(c))
			else
				table.insert(r, "'"..string.char(c).."'")
			end
		end
	end

	local t = table.concat(r, ", ")
	mw.log(t)
	return t
end

function m.P527withLowestP393(frame)
	local args = require('Module:Arguments').getArgs(frame)
	local entity = mw.wikibase.getEntity(args.id)
	if not entity or not entity.claims or not entity.claims.P527 then
		mw.log("no claims")
		return
	end
	
	-- select P527 with P393
	local data = {}
	for i, v in ipairs(entity.claims.P527) do
		if (v.type == "statement") and (v.rank ~= "deprecated") and v.qualifiers and v.qualifiers.P393 -- not deprecated statement with qualifier P393
		and v.mainsnak and (v.mainsnak.datatype == "wikibase-item") and v.mainsnak.datavalue -- consists of wikibase item
		and (v.mainsnak.datavalue.type == "wikibase-entityid") and v.mainsnak.datavalue.value and (v.mainsnak.datavalue.value["entity-type"] == "item") -- to Q entity
		then
			local id = v.mainsnak.datavalue.value.id
			-- select MIN(P393) although there is mostly one
			local edition = false
			for _, e in ipairs(v.qualifiers.P393) do
				if e and (e.snaktype == "value") and (e.datatype == "string") and e.datavalue and (e.datavalue.type == "string") and e.datavalue.value then
					local value = tonumber(e.datavalue.value)
					if value then
						if not edition then
							edition = value
						elseif value < edition then
							edition = value
						end
					end
				end
			end

			if edition then
				table.insert(data, { id, edition })
			end
		end
	end

	if #data == 0 then
		mw.log("there is no data with edition")
		return
	end
	
	-- select min edition
	local edition = data[1][2]
	for i = 2, #data do
		if data[i][2] < edition then
			edition = data[i][2]
		end
	end

	local function makeResult(id)
		local sitelink = mw.wikibase.sitelink(id)
		local label = mw.wikibase.label(id)
		if sitelink and label and (sitelink ~= label) then
			return "[["..sitelink.."|"..label.."]]"
		elseif sitelink then
			return "[["..sitelink.."]]"
		elseif label then
			return label
		else
			return id
		end
	end

	local result = {}
	-- select data with minimum edition
	for _, v in ipairs(data) do
		if v[2] == edition then
			table.insert(result, makeResult(v[1]))
		end
	end

	mw.log(table.concat(result, ", "))
	return table.concat(result, ", ")
end

function m.LY(frame)
	return frame:preprocess("{{LOCALYEAR}}")
end

function m.pptest(frame)
	local result = (frame or mw.getCurrentFrame()):preprocess("{{#if:{{{test|}}}|JEST {{{test}}}|NIE MA {{{test}}}u}}")
	mw.logObject(result, "result")
	return result
end

function m.Y(frame)
	mw.log("== {{Moduł:Brudnopis/Paweł Ziemian/test|Y}} ==")
	local args = frame:getParent().args
	
	local function itself()
		local result = {}
		local flags = {}
		table.insert(result, "{{")
		if mw.isSubsting() then
			table.insert(result, "subst:")
		end
		
		table.insert(result, "Wikipedysta:Paweł Ziemian/Y")
		local i = 1
		while args[i] do
			table.insert(result, "|")
			table.insert(result, mw.text.nowiki(args[i]))
			i = i + 1
		end
		
		for k, v in pairs(args) do
			local index = tonumber(k)
			if (type(k) == "string") or (index and ((index < 1) or (index > i))) then
				table.insert(result, "|")
				table.insert(result, tostring(k))
				table.insert(result, "=")
				table.insert(result, mw.text.nowiki(v))
			end
		end
	
		table.insert(result, "}}")
		return table.concat(result)
	end
	
	local arg1 = args[1]
	mw.logObject(arg1, "arg1")
	if not arg1 then
		mw.log("missing arguments")
		return itself()
	end
	
	if not string.match(arg1,"^%d+$") then
		mw.log("invalid argument type")
		return itself()
	end
	
	local id = "Q"..arg1
	local text = args[2] or mw.wikibase.label(id)
	local redirect = false
	mw.logObject(text, "text")
	if not text then
		redirect = mw.wikibase.getEntity(id)
		if redirect then
			text = redirect:getLabel()
		end
	end
	local link = mw.wikibase.sitelink(id)
	mw.logObject(link, "link")
	if not link and redirect then
		link = redirect:getSitelink()
	end
	if link then
		mw.log("exists")
		local result = {}
		local marker = not mw.isSubsting()
		mw.logObject(marker, "marker")
		local builder = mw.html.create(marker and "span" or "")
		if marker then
			builder
				:addClass("q-inactive")
				:addClass("q-inactive-"..arg1)
				:addClass(redirect and "q-redir" or "")
				:addClass(redirect and ("q-redir-"..redirect.id) or "")
				:wikitext("<<Kategoria:Strony z nieaktualną propozycją przetłumaczenia>>")
		end
		builder:wikitext("[[", link, ((link == text) or not text or (#text == 0)) and "" or "|"..text, "]]")
		return builder:done()
	end
	
	mw.log("not exists")
	if mw.isSubsting() then
		return itself()
	end
	
	local builder = mw.html.create("span")
		:addClass("q-active")
		:addClass("q-active-"..arg1)
		:addClass(redirect and "q-redir" or "")
		:addClass(redirect and ("q-redir-"..redirect.id) or "")
		:wikitext(redirect and "<<Kategoria:Strony z nieprawidłową propozycją przetłumaczenia>>" or "")

	local link = args.link
	local title = false
	if not link then
		label = mw.wikibase.label(id)
		title = (label and (#label > 0)) and mw.title.new(label, 0) or false
	else
		title = mw.title.new(link, 0)
	end

	if title and not title.exists then
		mw.log("red link")
		builder:wikitext("[[:"..title.text.."|"..text.."]]")
	elseif text and (#text > 0) then
		mw.log("no link or exists")
		builder:addClass(title and "q-ambig" or "q-nolink")
		builder:wikitext(text)
	else
		mw.log("no text")
		return itself()
	end

	mw.log("TODO propositions")
	local entity = mw.wikibase.getEntity(id)
	if not entity then
		mw.log("invalid id value")
	end
	
	return builder:done()
end

function m.pn(frame)
	return "{{PAGENAME}}"
end

function m.TPM(frame)
	local redirM = "Moduł:Brudnopis/Paweł Ziemian/mapy/pl1"
	local data = mw.loadData(redirM)
	mw.logObject(data, "data")
	local redir = "Wikipedysta:Paweł Ziemian/tpdm"
	local title = mw.title.new(redir)
	if title.isRedirect then
		local contentModel = title.contentModel
		mw.logObject(contentModel, "contentModel")
		local content = title:getContent()
		mw.logObject(content, "content")
		local targetName = mw.ustring.match(content, "^#%u+%s+%[%[([^%[%]|]+)")
		title = mw.title.new(targetName)
		contentModel = title.contentModel
		mw.logObject(contentModel, "contentModel")
	end
end

function m.D1(frame)
	mw.logObject(frame.args[1], "frame.args[1]")
	return frame.args[1]
end

function m.TestPrzypisu(frame)
	local text = "Jakiś tekst"..frame:extensionTag{ name = 'ref', content="Treść przypisu", args = { group='mini'} }
	local references = frame:extensionTag{name = 'references', args = { group='mini' }}
	return text..references
end

local function searchDnuPrefix(date, subjectPattern)
	
	local function scanContent(titleText, pattern)
		local archiveTitle = mw.title.new(titleText)
		if not archiveTitle.exists then
			return false
		end

		local result = mw.ustring.match(archiveTitle:getContent(), pattern)
		return result
	end
	
	local roots = {
		{ "Wikipedia:Poczekalnia/Załatwione artykuły ", "Wikipedia:Poczekalnia/artykuły/%d%d%d%d:%d%d:%d%d:" },
		{ "Wikipedia:Poczekalnia/Załatwione biografie ", "Wikipedia:Poczekalnia/biografie/%d%d%d%d:%d%d:%d%d:" },
		{ "Wikipedia:Poczekalnia/Załatwione naprawa ", "Wikipedia:Poczekalnia/naprawa/%d%d%d%d:%d%d:%d%d:" },
		{ "Wikipedia:Poczekalnia/Załatwione kwestie techniczne ", "Wikipedia:Poczekalnia/kwestie techniczne/%d%d%d%d:%d%d:%d%d:" },
	}

	local baseDate = mw.getContentLanguage():formatDate("F Y", date, true)
	for _, v in ipairs(roots) do
		local pattern = "{{("..v[2]..")"..subjectPattern.."}}"
		local result = scanContent(v[1].."("..baseDate..")", pattern)
		if result then
			return result
		end
		
		local i = 1
		while i < 9 do
			result = scanContent(v[1].."("..baseDate.."/"..tostring(i)..")", pattern)
			if result then
				return result
			end

			if result == false then
				break
			end
			
			i = i + 1
		end
	end
end

function m.TestDNU(frame)
	local currentTitle = mw.title.getCurrentTitle()
	if not currentTitle.isTalkPage then
		-- to nie dyskusja
		return 
	end
	
	local subjectTitle = currentTitle.subjectPageTitle
	if subjectTitle.namespace ~= 0 then
		-- dyskusja nie dodytczy artykułu
		return 
	end
	
	if subjectTitle.exists then
		-- artykuł istnieje
		return 
	end

	local subjectPattern = mw.ustring.gsub(require("Moduł:String")._escapePattern(subjectTitle.text), " ", "[ _]")
	local timestamp = mw.getContentLanguage():formatDate("Y-m-d", nil, true)
	local result = searchDnuPrefix(timestamp, subjectPattern)
		or searchDnuPrefix(timestamp.." -1 month", subjectPattern)
		or searchDnuPrefix(timestamp.." -2 months", subjectPattern)
	
	if result then
		return result..subjectTitle.text
	end
end

local function stripText(text, stripTemplates)
	text, _ = mw.ustring.gsub(text, "<[Dd][Ii][Vv]>", "\n") -- remove <div>
	text, _ = mw.ustring.gsub(text, "<[Dd][Ii][Vv]%s.->", "\n") -- remove <div>
	text, _ = mw.ustring.gsub(text, "</[Dd][Ii][Vv]>", "\n") -- remove </div>
	text, _ = mw.ustring.gsub(text, "<[Ss][Pp][Aa][Nn]>", "") -- remove <span>
	text, _ = mw.ustring.gsub(text, "<[Ss][Pp][Aa][Nn]%s.->", "") -- remove <span>
	text, _ = mw.ustring.gsub(text, "</[Ss][Pp][Aa][Nn]>", "") -- remove </span>
	text, _ = mw.ustring.gsub(text, "<[Bb][Rr]%s*/?>", " ") -- remove <br/>

	text, _ = mw.ustring.gsub(text, "{|[^\n]-\n", "\n{|\n") -- remove table attributes
	text, _ = mw.ustring.gsub(text, "\n|%-[^\n]*\n", "\n|-\n") -- remove table raw attributes
	text, _ = mw.ustring.gsub(text, "\n|[^\n|]-|([^|])", "\n| |%1") -- remove table cell attributes
	if stripTemplates then
		text, _ = mw.ustring.gsub(text, "{{[^|}]*([|}])", "{{%1") -- remove template name
		text, _ = mw.ustring.gsub(text, "|[^|=]*=", "|") -- remove template field names
	end

	text, _ = mw.ustring.gsub(text, "%[%[[Pp]lik:[^\n]-%]%]", "") -- remove files
	text, _ = mw.ustring.gsub(text, "%[%[[Ff]ile:[^\n]-%]%]", "") -- remove files
	text, _ = mw.ustring.gsub(text, "%[%[[^%]|\n]+|([^%]|\n]+)%]%]", "%1") -- remove internal links
	text, _ = mw.ustring.gsub(text, "%[%[Kategoria:.-%]%]", "") -- remove categories
	text, _ = mw.ustring.gsub(text, "%[https?://[^%s%]]*([^\n]-)%]", "%1") -- remove external link
	text, _ = mw.ustring.gsub(text, "%[//[^%s%]]*([^\n]-)%]", "%1") -- remove external link
	
	text, _ = mw.ustring.gsub(text, "UNIQ[0-9a-zA-F%-]+QINU", "") -- remove nowiki
	text, _ = mw.ustring.gsub(text, "%W", " ") -- vanish non alpha nor digits
	text, _ = mw.ustring.gsub(text, "%s+", " ") -- compact spaces

	return text	
end

function m.plainText(frame)
	return stripText(frame.args[1], frame.args.templates == "tak")
end

function m.countPattern(frame)
	local text = frame.args[1]
	local pattern = frame.args.pattern
	if not text then
		return -1
	end
	
	if not pattern then
		return -2
	end
	
	local _, count = mw.ustring.gsub(text, pattern, "")
	return count
end

function m.countWords(frame)
	local text = frame.args[1]
	if not text then
		return -1
	end
	
	text = stripText(text)
	local _, count = mw.ustring.gsub(text, "%w+", "")
	return count
end

function m.countCharacters(frame)
	local text = frame.args[1]
	if not text then
		return -1
	end
	
	text = stripText(text)
	local _, count = mw.ustring.gsub(text, "%w", "")
	return count
end

function m.getTextSize(frame)
	local text = frame.args[1]
	if not text then
		return -1
	end
	
	local title = mw.title.new(text)
	if not title then
		return -2
	end
	
	local content = title:getContent()
	if not content then
		return -3
	end

	local full = mw.ustring.len(content)
	content, _ = mw.ustring.gsub(content, "<[Dd][Ii][Vv]%s+[^>]*>", "") -- remove <div>
	content, _ = mw.ustring.gsub(content, "</[Dd][Ii][Vv]>", "") -- remove </div>
	content, _ = mw.ustring.gsub(content, "<[Ss][Pp][Aa][Nn]%s+[^>]*>", "") -- remove <span>
	content, _ = mw.ustring.gsub(content, "</[Ss][Pp][Aa][Nn]>", "") -- remove </span>
	content, _ = mw.ustring.gsub(content, "<[Bb][Rr]%s*/?>", "") -- remove <br/>
	local html = mw.ustring.len(content)
	content, _ = mw.ustring.gsub(content, "\n{|.-\n", "\n{|\n") -- remove table attributes
	content, _ = mw.ustring.gsub(content, "\n|\\-.-\n", "\n|-\n") -- remove table raw attributes
	content, _ = mw.ustring.gsub(content, "{{[^|}]*([|}])", "{{%1") -- remove template name
	content, _ = mw.ustring.gsub(content, "|[^|=]*=", "|") -- remove template field names
	local temp = mw.ustring.len(content)
	content, _ = mw.ustring.gsub(content, "%[%[[^|%]]*|([^%]])", "%1") -- remove internal links
	content, _ = mw.ustring.gsub(content, "%[%[Kategoria:.-%]%]", "") -- remove categories
	content, _ = mw.ustring.gsub(content, "%[http[s]://%S*%s+.-%]", "") -- remove external link
	local link = mw.ustring.len(content)
	content, _ = mw.ustring.gsub(content, "%W", "") -- remove spaces
	local space = mw.ustring.len(content)
	mw.log(full.." (full), "..(html-full).." (html), "..(temp-html).." (template), "..(link-temp).." (link),  "..(space-link).." (space) => "..space.." (text)")
	return space
end


m.Subst = function(frame)
	local title = mw.title.getCurrentTitle()
	mw.logObject(title.text, "title.text")
	local prefixedTitleName = mw.ustring.match(title.prefixedText, "^(.-)/opis")
		or mw.ustring.match(title.prefixedText, "^(.-)/test")
		or mw.ustring.match(title.prefixedText, "^(.-)/brudnopis")
		or title.prefixedText
	if mw.isSubsting() or (prefixedTitleName == frame:getParent():getTitle()) or (frame:getParent().args["usprawiedliwienie na brak 'subst:'"] == "przykład wywołania szablonu przez transkluzję poza stronami testowymi") then
		return frame.args[1]
	end
	
	mw.log("Brak 'subst:' w wywołaniu '"..frame:getParent():getTitle().."'")
	return "<<Kategoria:Brak 'subst:' w wywołaniu szablonu>>"
end

	m.preprocess = function (frame)
		local arg = frame.args[1]
		if not arg  then
			-- missing arguments
			return nil
		end
		
		if #arg == 0 then
			-- empty argument
			return nil
		end
		
		if not mw.ustring.isutf8(arg) then
			-- invalid input is left as is
			return arg
		end
		
		local ipadata = mw.loadData( 'Moduł:IPA/data' )
	 
		local split = function(text)
			local result = {}
			local joined = false
			local current = ""
			for code in mw.ustring.gcodepoint(text) do
				local c = mw.ustring.char(code)
				if ipadata.joining[code] then
					current = current .. c
					joined = true
				elseif joined or ipadata.combining[code] then
					current = current .. c
					joined = false
				else
					if current ~= "" then
						table.insert(result, current)
					end
					current = c
				end
			end
	 
			-- append last part
			if current ~= "" then
				table.insert(result, current)
			end
	 
			return result
		end
	 
		local decorate = function(parts)
			local last = false
			local currentLink = nil
			local result = {}
			local count = #parts
			table.insert(parts,"") -- append empty text to simplify loop below
			local i = 1
			while i <= count do
				local s, n = parts[i]..parts[i+1], 2
				local t = ipadata.sounds[s]
				if not t then
					s, n = parts[i], 1
					t = ipadata.sounds[s]
				end
	 
				local link = nil
				if t then
					t = t.see and ipadata.sounds[t.see] or t
					link = ((t.last and last) and last[t.last] or t.link) or ipadata.unknownSound
					last = t.last and last or t
				elseif mw.ustring.match(s,"%S") then
					link = ipadata.unknownSound
					last = false
				else
					last = false
				end
	 
				-- append the optional title
				if link ~= currentLink then
					if currentLink then
						table.insert(result,"]]")
						currentLink = nil
					end
					if link then
						table.insert(result,"[[")
						table.insert(result,link)
						table.insert(result,"|")
						currentLink = link
					end
				end
	 
				-- append the sound
				table.insert(result,s)
	 
				-- move to next sound in the input
				i = i + n
			end
	 
			if currentLink then
				table.insert(result, "]]")
			end
	 
			return table.concat(result,"")
		end
	 
		local parts = split(arg)
		local result = decorate(parts)
		return result
	end


m.TEMPLATENAME = function(frame)
	local templateTitle = mw.title.new(frame:getParent():getTitle())
	mw.logObject(templateTitle, "templateTitle")
	mw.logObject(templateTitle.namespace, "namespace")
	mw.logObject(templateTitle.text, "text")
	return (templateTitle and (templateTitle.namespace == 10)) and templateTitle.text or nil
end

local PrzyimekZE = {
	w = {
		"^[Mm][Nn][Ii][Ee]$",
		"^[Mm][Nn][Ii][Ee]%s",
		"^[Mm][Nn][Ąą]$",
		"^[Mm][Nn][Ąą]%s",
		"^[Mm][Gg][Lg][Ee]$",
		"^[Ll][Ww][Oo][Ww][Ii][Ee]$",
		"^[Śś][Nn][Ii][Ee]$",
		"^[WwFf][BbCcĆćDdFfGgHhJjKkLlŁłMmNnŃńPpRrSsŚśTtWwZzŹźŻż]",
	},

	z = {
		"^[Mm][Nn][Ii][Ee]$",
		"^[Mm][Nn][Ii][Ee]%s",
		"^[Mm][Nn][Ąą]$",
		"^[Mm][Nn][Ąą]%s",
		"^[Ss][Oo][Bb][Ąą]%s",
		"^[Ss][Zz][BbCcĆćDdFfGgHhJjKkLlŁłMmNnŃńPpRrSsŚśTtWwZzŹźŻż]",
		"^[Ss][BbCcĆćDdFfGgHhJjKkLlŁłMmNnŃńPpRrSsŚśTtWwŹźŻż]",
		"^[ŚśZz][BbCcĆćDdFfGgHhJjKkLlŁłMmNnŃńPpRrSsŚśTtWwZzŹźŻż]",
	},

	d = {
		"^[Mm][Nn][Ii][Ee]$",
		"^[Mm][Nn][Ii][Ee]%s",
		"^[Mm][Nn][Ąą]$",
		"^[Mm][Nn][Ąą]%s",
	},
}

function m.Z(frame)
	local ze = {
		"^%s*[Mm][Nn][Ii][Ee]$",
		"^%s*[Mm][Nn][Ii][Ee]%s",
		"^%s*[Mm][Nn][Ąą]$",
		"^%s*[Mm][Nn][Ąą]%s",
		"^%s*[Ss][Oo][Bb][Ąą]$",
		"^%s*[Ss][Oo][Bb][Ąą]%s",
		"^%s*[Ss][Zz][BbCcĆćDdFfGgHhJjKkLlŁłMmNnŃńPpRrSsŚśTtWwZzŹźŻż]",
		"^%s*[Ss][BbCcĆćDdFfGgHhJjKkLlŁłMmNnŃńPpRrSsŚśTtWwŹźŻż]",
		"^%s*[ŚśZz][BbCcĆćDdFfGgHhJjKkLlŁłMmNnŃńPpRrSsŚśTtWwZzŹźŻż]",
	}

	local text = frame.args[1]
	if text then
		for _, regex in ipairs(ze) do
			if mw.ustring.match(text, regex) then
				return "ze"
			end
		end
	end

	return "z"
end

function m.CT(frame)
	local title = mw.title.getCurrentTitle()
	local data =
	{
		id = title.id,
		interwiki = title.interwiki,
		namespace = title.namespace,
		fragment = title.fragment,
		nsText = title.nsText,
		subjectNsText = title.subjectNsText,
		text = title.text,
		prefixedText = title.prefixedText,
		fullText = title.fullText,
		rootText = title.rootText,
		baseText = title.baseText,
		subpageText = title.subpageText,
		canTalk = title.canTalk,
		exists = title.exists,
	}
	mw.logObject(data, "currentTitle")
	return "<pre>"..mw.dumpObject(data, "currentTitle").."</pre>"
end

function m.ikonaPlik(frame)
	return require("Module:Ikona").plik(frame.args[1] or "")
end

function m.P460links2(frame)
	local qid = frame.args.id
	local data = mw.wikibase.getEntityObject(qid)
	if not data then
		return "brak danych"
	end
	
	local links = {}
	local appendLink = function(lang, title)
		mw.log("appendLink("..lang..", "..title..")")
		if not links[lang] then
			links[lang] = { title }
		else
			table.insert(links[lang], title)
		end
	end
	
	local extractLinks = function(data)
		mw.log("extractLinks("..data.id..")")
		local langs = {}
		if data.claims and data.claims.P407 then
			for _, v in ipairs(data.claims.P407) do
				if v.mainsnak.snaktype == "value" then
					local langid = "Q"..tostring(v.mainsnak.datavalue.value["numeric-id"])
					mw.logObject(langid, "P407")
					local langdata = mw.wikibase.getEntityObject(langid)
					if langdata and langdata.claims and langdata.claims.P424 then
						for _, l in ipairs(langdata.claims.P424) do
							if l.mainsnak.snaktype == "value" then
								langs[l.mainsnak.datavalue.value] = true
							end
						end
					end
				end
			end
		end
		mw.logObject(langs, "langs")
		if data.sitelinks then
			for k, v in pairs(data.sitelinks) do
				local l = string.sub(k, 1, -5)
				if langs[l] then
					appendLink(l, v.title)
				end
			end
		end
	end

	extractLinks(data)
	if data.claims and data.claims.P460 then
		for _, v in ipairs(data.claims.P460) do
			if v.mainsnak.snaktype == "value" then
				local seeid = "Q"..tostring(v.mainsnak.datavalue.value["numeric-id"])
				local seedata = mw.wikibase.getEntityObject(seeid)
				if seedata then
					extractLinks(seedata)
				end
			end
		end
	end

	local result = "<pre>"..mw.dumpObject(links).."</pre>"
	return result
end

function m.P460links(frame)
	local qid = frame.args.id
	local data = mw.wikibase.getEntityObject(qid)
	if not data then
		return -- brak danych -> kategoria?
	end
	
	local links = {}
	local appendLink = function(lang, title)
		if not links[lang] then
			links[lang] = { title }
		else
			table.insert(links[lang], title)
		end
	end
	
	local knownLanguages = mw.loadData("Module:Lang/data")
	local extractLinks = function(data)
		if data.sitelinks then
			for k, v in pairs(data.sitelinks) do
				local lang = string.sub(k, 1, -5)
				local project = string.sub(k, -4)
				if (project == "wiki") and knownLanguages[lang] then
					appendLink(lang, v.title)
				end
			end
		end
	end

	extractLinks(data)
	if data.claims and data.claims.P460 then
		for _, v in ipairs(data.claims.P460) do
			if v.mainsnak.snaktype == "value" then
				local seeid = "Q"..tostring(v.mainsnak.datavalue.value["numeric-id"])
				local seedata = mw.wikibase.getEntityObject(seeid)
				if seedata then
					extractLinks(seedata)
				end
			end
		end
	end

	local result = {}
	local content = mw.title.getCurrentTitle():getContent()
	for k, v in pairs(links) do
		local pattern = "%[%["..mw.ustring.gsub( k, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" )..":[^%[%]|]+%]%]"
		local interwiki = mw.ustring.match(content, pattern)
		if not interwiki and not data.sitelinks[k.."wiki"] then
			table.insert(result, "[[")
			table.insert(result, k)
			table.insert(result, ":")
			table.insert(result, v[1])
			table.insert(result, "]]")
		end
	end

	return table.concat(result, "")
end


function m.pt(frame)
	mw.logObject(frame:getParent():getTitle(), "parent:title")
end

function m.Grafika2(frame)
	mw.log("=======================================================================")
	local namespace = mw.title.getCurrentTitle().namespace
	local localGraphics = frame.args.grafika or "grafika"
	if #localGraphics == 0 then
		localGraphics = false
	end
	
	mw.logObject(localGraphics, "localGraphics")
	local wdGraphics = frame.args.cecha or "P18"
	if #wdGraphics == 0 then
		wdGraphics = false
	elseif not mw.ustring.match(wdGraphics, "^P%d+$") then
		error("Błąd składni parametru {{{cecha}}}")
	end
	
	mw.logObject(wdGraphics, "wdGraphics")
	if not localGraphics and not wdGraphics then
		error("Bezsensowne wywołanie")
	end
	
	local categories = frame.args.kategorie
	if not categories then
		categories = ((namespace == 0) and localGraphics and (wdGraphics == "P18")) and true or false
	elseif categories == "tak" then
		categories = true
	elseif categories == "nie" then
		categories = false
	else
		error("Zły parametr {{{kategorie}}")
	end
	
	local descriptionOver = frame.args["opis nad"]
	if not descriptionOver or (#descriptionOver == 0) then
		descriptionOver = false
	end
	
	mw.logObject(descriptionOver, "descriptionOver")
	local descriptionUnder = frame.args["opis pod"] or (localGraphics and "opis grafiki" or "")
	if not descriptionUnder or (#descriptionUnder == 0) then
		descriptionUnder = false
	end

	mw.logObject(descriptionUnder, "descriptionUnder")
	local maxwidth, maxheight = mw.ustring.match(frame.args["maksymalny rozmiar"] or "", "^(%d+)x(%d+)px$")
	local minwidth, minheight = mw.ustring.match(frame.args["minimalny rozmiar"]  or "", "^(%d+)x(%d+)px$")
	maxwidth, maxheight = tonumber(maxwidth) or 240, tonumber(maxheight) or 300
	minwidth, minheight = tonumber(minwidth) or 120, tonumber(minheight) or 100
	
	mw.logObject(maxwidth, "maxwidth")
	mw.logObject(maxheight, "maxheight")
	mw.logObject(minwidth, "minwidth")
	mw.logObject(minheight, "minheight")
	local size = frame.args.rozmiar
	if not size or (#size == 0) then
		size = false
	end

	mw.logObject(size, "size")
	local col = frame.args.pole or 'style="text-align:center; font-size:95%; background-color:white; border-top:1px solid #eee; border:1px solid #aaa;"'
	local row = frame.args.wiersz or ""
	local alt = frame.args.alt
	if not alt then
		alt = descriptionUnder
	elseif #alt == 0 then
		alt = false
	end

	mw.logObject(col, "col")
	mw.logObject(row, "row")
	mw.logObject(alt, "alt")
	local pf = frame:getParent() or {args={}}
	local demo = frame.args[1] == "demo"
	local claims = {}
	if wdGraphics then
		local entity = mw.wikibase.getEntity()
		if entity and entity.claims then
			claims = entity.claims
		end
	end
	
	local plik = false
	local opis = ""
	local kategoria = {}
	
	if localGraphics then
		local grafika = pf.args[localGraphics]
		if not grafika and demo then
			grafika = "{{{"..localGraphics.."}}}"
		end
		
		if grafika and (#grafika > 0) then
			-- normalize
			grafika = mw.ustring.gsub(grafika, "%s*[Pp]lik%s*:%s*", "Plik:")
			grafika = mw.ustring.gsub(grafika, "%s*[Ff]ile%s*:%s*", "Plik:")
			grafika = mw.ustring.gsub(grafika, "%s*[Gg]rafika%s*:%s*", "Plik:")
			grafika = mw.ustring.gsub(grafika, "%s*[Ii]mage%s*:%s*", "Plik:")
	
			plik = mw.ustring.match(grafika, "^Plik:(.*)")
			if not plik then
				plik = mw.ustring.match(grafika, "%[%[Plik:([^%[%]|]+)[|%]]")
			end
			if not plik then
				plik = grafika
			else
				table.insert(kategoria, "<<Kategoria:Łatki - Plik>>")
			end
			
			if descriptionUnder then
				opis = pf.args[descriptionUnder]
				mw.logObject(opis, "opis")
				if not opis then
					opis = demo and "{{{"..descriptionUnder.."}}}" or ""
				end
			end
		end

		if grafika and not plik and not wdGrahics then
			-- tylko lokalne obrazki - brak
			mw.log("exit 1")
			return categories
				and "|- style=\"display:none;\"\n| colspan=\"2\" | <<Kategoria:Brak grafiki załadowanej lokalnie>>\n|-"
				or ""
		end
	end
	
	mw.logObject(claims[wdGraphics], wdGraphics)
	
	if plik then
		mw.log(plik, "plik 1")
		if categories and wdGrahics then
			local cat2
			if claims[wdGrahics] then
				local same = false
				for _, v in ipairs(claim[wdGrahics]) do
					if v.mainsnak.datavalue.value == plik then
						same = true
						break
					end
				end
				cat2 = same
					and "<<Kategoria:Grafika załadowana lokalnie jest taka sama jak w serwisie Wikidata>>"
					or "<<Kategoria:Grafika załadowana lokalnie jest inna niż w serwisie Wikidata>>"
			elseif not claims.P18 and not claims.P41 and not claims.P94 and not claims.P117 and not claims.P154 and not claims.P242 then
				cat2 = "<<Kategoria:Istnieje grafika załadowana lokalnie, brak grafiki w serwisie Wikidata>>"
			end
			
			if cat2 then
				table.insert(kategoria, kat2)
			end
		end
	elseif claims[wdGraphics] then
		plik = claims[wdGraphics][1].mainsnak.datavalue.value
		mw.log(plik, "plik 2")
		if localGraphics and categories then
			table.insert(kategoria, "<<Kategoria:Brak grafiki załadowanej lokalnie, załadowano grafikę z serwisu Wikidata>>")
		end
	elseif demo then
		plik = "#property:"..wdGraphics
	elseif categories then
		mw.log("exit 2")
		return localGraphics
			and "|- style=\"display:none;\"\n| colspan=\"2\" | <<Kategoria:Brak grafiki załadowanej lokalnie lub w serwisie Wikidata>>\n|-"
			or "|- style=\"display:none;\"\n| colspan=\"2\" | <<Kategoria:Brak grafiki w serwisie Wikidata>>\n|-"
	else
		mw.log("exit 3")
		return
	end

	local width, height = maxwidth, maxheight
	if size then
		width, height = mw.ustring.match(pf.args[size] or "", "^(%d+)x(%d+)px$")
	end
	width  = width  > maxwidth  and maxwidth  or (width  < minwidth  and minwidth  or width)
	height = height > maxheight and maxheight or (height < minheight and minheight or height)

	local contents = {
		"|-", row,
		"\n| colspan=\"2\" ", col, " | ",
	}
	
	if descriptionOver then
		local text = pf.args[descriptionOver]
		if not text and demo then
			text = "{{{"..descriptionOver.."}}}"
		end
		if text and (#text > 0) then
			table.insert(contents, text)
			table.insert(contents, "<br/>")
		end
	end

	local underText = ""
	local autoText = ""
	if descriptionUnder then
		underText = opis
		if #opis > 0 then
			opis = mw.ustring.gsub(opis, "%[%[[^|]+|", "")
			opis = mw.ustring.gsub(opis, "%[%[", "")
			autoText = mw.ustring.gsub(opis, "%]%]", "")
		end
	end

	local altText = ""
	if alt then
		altText = alt == underText and autoText or pf.args[alt]
		if not altText and demo then
			altText = "{{{"..alt.."}}}"
		else
			altText = ""
		end
	end
	
	table.insert(contents, string.format("[[Plik:%s|%dx%dpx", plik, width, height))
	if #altText > 0 then
		table.insert(contents, "|alt=")
		table.insert(contents, altText)
	end
	
	if #autoText > 0 then
		table.insert(contents, "|")
		table.insert(contents, autoText)
	end

	table.insert(contents, "]]")
	if #underText > 0 then
		table.insert(contents, "<br/>")
		table.insert(contents, underText)
	end
	
	for _, v in ipairs(kategoria) do
		table.insert(contents, v)
	end
	
	table.insert(contents, "\n|-")
	mw.logObject(contents, "contents")
	return table.concat(contents)
end

function m.Grafika(frame)
	local pf = frame:getParent() or {args={}}
	local demo = frame.args[1] == "demo"
	local grafika = pf.args.grafika or (demo and "{{{grafika}}}" or nil)
	local plik = false
	local kategoria = false
	local claims = {}
	local opis = false
	local namespace = mw.title.getCurrentTitle().namespace

	local wd = pf.args.cecha
	if not wd or (#wd == 0) then
		wd = "P18"
	end
	if wd ~= "nie" then
		local entity = mw.wikibase.getEntity()
		if entity then
			claims = entity.claims
		end
	end
	
	if grafika and (#grafika > 0) then
		-- normalize
		grafika = mw.ustring.gsub(grafika, "%s*[Pp]lik%s*:%s*", "Plik:")
		grafika = mw.ustring.gsub(grafika, "%s*[Ff]ile%s*:%s*", "Plik:")
		grafika = mw.ustring.gsub(grafika, "%s*[Gg]rafika%s*:%s*", "Plik:")
		grafika = mw.ustring.gsub(grafika, "%s*[Ii]mage%s*:%s*", "Plik:")

		plik = mw.ustring.match(grafika, "^Plik:(.*)")
		if not plik then
			plik = mw.ustring.match(grafika, "%[%[Plik:([^%[%]|]+)[|%]]")
		end
		if not plik then
			plik = grafika
			kategoria = ""
		else
			kategoria = "<<Kategoria:Łatki - Plik>>"
		end
		
		opis = pf.args["opis grafiki"] or (demo and "{{{opis grafiki}}}" or nil)
	end
	
	if grafika and not plik and (wd == "nie") then
		-- tylko lokalne obrazki - brak
		return namespace == 0
			and "|- style=\"display:none;\"\n| colspan=\"2\" | <<Kategoria:Brak grafiki załadowanej lokalnie>>\n|-"
			or ""
	end
	
	if plik then
		local kat2 = false
		if claims[wd] then
			local same = false
			for _, v in ipairs(claim.P18) do
				if v.mainsnak.datavalue.value == plik then
					same = true
					break
				end
			end
			kat2 = same
				and "<<Kategoria:Grafika załadowana lokalnie jest taka sama jak w serwisie Wikidata>>"
				or "<<Kategoria:Grafika załadowana lokalnie jest inna niż w serwisie Wikidata>>"
		elseif not claims.P18 and not claims.P41 and not claims.P94 and not claims.P117 and not claims.P154 and not claims.P242 then
			kat2 = "<<Kategoria:Istnieje grafika załadowana lokalnie, brak grafiki w serwisie Wikidata>>"
		end
		
		if kat2 then
			kategoria = kategoria..kat2
		end
	elseif claims.P18 then
		plik = claims.P18.mainsnak.datavalue.value
		if grafika and namespace == 0 then
			kategoria = "<<Kategoria:Brak grafiki załadowanej lokalnie, załadowano grafikę z serwisu Wikidata>>"
		end
	elseif namespace == 0 then
		return grafika
			and "|- style=\"display:none;\"\n| colspan=\"2\" | <<Kategoria:Brak grafiki załadowanej lokalnie lub w serwisie Wikidata>>\n|-"
			or "|- style=\"display:none;\"\n| colspan=\"2\" | <<Kategoria:Brak grafiki w serwisie Wikidata>>\n|-"
	else
		return
	end
	
	local width,    height    = mw.ustring.match(pf.args["rozmiar grafiki"]    or "", "^(%d+)x(%d+)px$")
	local maxwidth, maxheight = mw.ustring.match(pf.args["maksymalny rozmiar"] or "", "^(%d+)x(%d+)px$")
	local minwidth, minheight = mw.ustring.match(pf.args["minimalny rozmiar"]  or "", "^(%d+)x(%d+)px$")
	maxwidth, maxheight = tonumber(maxwidth) or 240, tonumber(maxheight) or 300
	minwidth, minheight = tonumber(minwidth) or 120, tonumber(minheight) or 100
	width,    height    = tonumber(width)    or 240, tonumber(height)    or 240
	width  = width  > maxwidth  and maxwidth  or (width  < minwidth  and minwidth  or width)
	height = height > maxheight and maxheight or (height < minheight and minheight or height)

	local col = pf.args.pole or 'style="text-align:center; font-size:95%; background-color:white; border-top:1px solid #eee; border:1px solid #aaa;"'
	local row = pf.args.wiersz or ""
	local alt = pf.args["alt grafiki"] or (demo and "{{{alt grafiki}}}" or "Ilustracja")
	local contents = {
		"|-",
		pf.args.wiersz or "",
		"\n| colspan=\"2\" ",
		pf.args.pole or 'style="text-align:center; font-size:95%; background-color:white; border-top:1px solid #eee; border:1px solid #aaa;"',
		" | ",
		string.format("[[Plik:%s|%dx%dpx|alt=%s|%s]]", plik, width, height, alt, opis),
	}
	if opis and (#opis > 0) then
		table.insert(contents, "<br/>")
		table.insert(contents, opis)
	end
	if kategoria and (namespace == 0) then
		table.insert(contents, kategoria)
	end
	table.insert(contents, "\n|-")
	return table.concat(contents)
end

function m.TS(frame)
	local result = {
		"Jakiś tekst",
		frame:extensionTag{ name="ref", content="jakiś przypis", args = { group='mini',  name="nazwa_przypisu"} }, -- przypis
		" ",
		"Dalszy tekst.\n",
		frame:expandTemplate{ title = 'przypisy-lista', args = { grupa='mini'} },
	}
	
	return table.concat(result,"")
end

function m.QQ(frame)
	local content = mw.title.getCurrentTitle():getContent()
	local q = mw.ustring.match(content, "{{%s*Wikipedysta:Paweł Ziemian/Q%s*|[^}]*}}")
	local entity = mw.wikibase.getEntityObject()
	local sitelinks = entity and entity.sitelinks or {}
	local sister = sitelinks.plwikinews
		or sitelinks.plwikiquote
		or sitelinks.plwikisource
		or sitelinks.plwikivoyage
		or sitelinks.commonswki
	
	if not q and not sister then
		mw.log("Ani Q ani SISTER")
		return
	end
	
	mw.log("Generuje LZ")
	local builder = mw.html.create()
	
	if sister then
		mw.log("Generuje SISTERS")
		local div = builder:tag("div")
		div:attr("class", "infobox sisterproject do-not-make-smaller")
		div:attr("style", "font-size: 85%; width:250px; padding:3px; line-height:2em")
		if sitelinks.commonswki then
			div:tag("span"):attr("style", "margin:1px"):wikitext("[[Plik:Commons-logo.svg|13px]]")
			div:wikitext("&nbsp;")
			div:tag("span"):attr("class", "plainlinks"):wikitext("[//commons.wikimedia.org/wiki/", mw.uri.encode(sitelinks.commonswki.title, "WIKI"), "&uselang=pl '''Ilustracje i media''']")
			div:wikitext("&nbsp;w [[Wikimedia Commons]]")
			div:tag("br")
		end

		if sitelinks.plwikisource then
			div:wikitext("[[Plik:Wikisource-logo.svg|15px]] &nbsp;'''[[s:", sitelinks.plwikisource.title, "|Teksty źródłowe]]'''&nbsp;w [[Wikiźródła]]ch")
			div:tag("br")
		end

		if sitelinks.plwikiquote then
			div:wikitext("[[Plik:Wikiquote-logo.svg|15px]] &nbsp;'''[[q:", sitelinks.plwikiquote.title, "|Cytaty]]'''&nbsp;w [[Wikicytaty|Wikicytatach]]")
			div:tag("br")
		end

		if sitelinks.plwikinews then
			div:wikitext("[[Plik:Wikinews-logo.svg|15px]] &nbsp;'''[[n:", sitelinks.plwikinews.title, "|Wiadomości]]'''&nbsp;w [[Wikinews]]")
			div:tag("br")
		end

		if sitelinks.plwikivoyage then
			div:wikitext("[[Plik:Wikivoyage-logo.svg|15px]] &nbsp;'''[[voy:", sitelinks.plwikivoyage.title, "|Informacje turystyczne]]'''&nbsp;w [[Wikipodróże|Wikipodróżach]]")
			div:tag("br")
		end
	end
	
	mw.log("Generuje LZQQ")
	local div = builder:tag("div")
	div:attr("class", "do-not-make-smaller refsection refsection-LZ references-column-count references-3column")
	div:wikitext(frame:extensionTag('references', '', { group='LZ' }))

	return tostring(builder)
end

function m.SimpleDuplicates(frame)
	local result = {}
	local wikitext = mw.title.getCurrentTitle():getContent()
	
	while true do
		local templateIterator = mw.ustring.gmatch(wikitext, "{{[^{}]+}}")
		while true do
			local template = templateIterator()
			if not template then
				-- no more templates
				break
			end
	
			mw.log(template)
			local parameters = {}
			local patch, _ = mw.ustring.gsub(template, "(%[%[[^%[%]|]+)|([^%[%]|]-%]%])", "%1<nowiki>&x7C;</nowiki>%2")
			local chunks = mw.text.split(patch, "|")
			local i = 2 -- skip first item which is template name
			local auto = 0
			local emited = false
			while i <= #chunks do
				local chunk = chunks[i]
				local name, value = mw.ustring.match(chunk, "%s*(.-)%s*=(.*)")
				if not name then
					auto = auto + 1
					name = tostring(auto)
					value = chunk
				end
				
				value = mw.ustring.gsub(value, "<nowiki>&x7C;</nowiki>", "|")
				
				if not parameters[name] then
					parameters[name] = { value }
				else
					-- duplicated parameter
					if not emited then
						emited = {}
						table.insert(emited, "<tt>"..mw.text.nowiki(template).."</tt>")
					end
					
					if #parameters[name] == 1 then
						table.insert(emited, name..": "..mw.text.nowiki(parameters[name][1]))
					end
						
					table.insert(parameters[name], value)
					table.insert(emited, name..": "..mw.text.nowiki(value))
				end

				i = i + 1
			end
			
			if emited then
				table.insert(result, table.concat(emited, "<br /> → "))
			end
		end
	
		local count = false
		wikitext, count = mw.ustring.gsub(wikitext, "{{[^{}]+}}", "€")
		if count == 0 then
			break
		end
	end

	return "<ul><li>"..table.concat(result, "</li><li>").."</li></ul>"
end

m.p = function(frame)
	local title = mw.title.getCurrentTitle()
	local pf = frame:getParent()
	local text = mw.text.trim(pf.args[1] or "")
	if #text == 0 then
		return title.namespace == 0 and "<<Kategoria:Szablon przypisu bez treści>>" or ""
	end

	local detectedReference = false
	local undetectedReferece = false
	local autofullstop = false
	local fullstop = false
	local references = {}
	local i = 2
	while true do
		local ref = pf.args[i]
		if not ref then
			break
		end
		
		i = i + 1
		
		ref = mw.text.trim(ref)
		local rlen = mw.ustring.len(ref)
		if rlen == 0 then
			-- empty full stop detected
			fullstop = ""
			break
		else
			local prefix = mw.ustring.sub(ref, 1, 2)
			if prefix == "p:" then
				-- simple text that must be placed in the <ref> tag
				ref = mw.ustring.sub(ref, 3, rlen)
				ref = frame:extensionTag("ref", ref)
			elseif prefix == "r:" then
				-- it is declared that the text is already wrapped in a <ref> tag
				ref = mw.ustring.sub(ref, 3, rlen)
			elseif prefix == "n:" then
				-- there is given name of the named <ref> tag
				ref = mw.ustring.sub(ref, 3, rlen)
				ref = frame:extensionTag("ref", "", { name = ref })
			elseif mw.ustring.match(ref, "^%p$") then
				-- full stop detected
				fullstop = ref
				break
			elseif string.match(ref, "^\127UNIQ%-%-ref%-[0-9A-F]+%-QINU\127$") then
				-- simple reference is detected
				detectedReference = true
			else
				undetectedReference = true
				mw.logObject(ref, "undetected ref")
				ref = frame:extensionTag("ref", ref)
			end
		
			table.insert(references, ref)
		end
	end

	if #references == 0 then
		return text.."<<Kategoria:Szablon przypisu bez źródeł>>"
	end
	
	if not fullstop then
		autofullstop = true
		local emptyfullstops = { "itp%.$", "itd%.$", "%.%.%.$", }
		for _, v in ipairs(emptyfullstops) do
			if mw.ustring.match(text, v) then
				fullstop = ""
				break
			end
		end
	
		if not fullstop then
			local tail = mw.ustring.match(text, "%p$")
			if tail then
				tlen = mw.ustring.len(text) - mw.ustring.len(tail)
				if tlen <= 0 then
					return "<<Kategoria:Szablon przypisu bez treści>>"
				end
				text = mw.ustring.sub(text, 1, tlen)
				fullstop = tail
			end
		end
	end
	
	-- build result text
	local result = {}
	table.insert(result, "<span class=\"cited-sentence\">")
	table.insert(result, text)
	for _, r in ipairs(references) do
		table.insert(result, r)
	end
	table.insert(result, fullstop)
	table.insert(result, "</span>")
	if detectedReference then
		table.insert(result, "<<Kategoria:Szablon przypisu bez deklaracji odnośnika>>")
	end
	if undetectedReference then
		table.insert(result, "<<Kategoria:Szablon przypisu bez deklaracji opisu>>")
	end
	if autofullstop then
		table.insert(result, "<<Kategoria:Szablon przypisu z automatycznym zakończeniem>>")
	end
	
	return table.concat(result, "")
end

function m.I(frame)
	local args = frame:getParent().args
	local arg1 = args[1]
	if not arg1 then
		-- missing arguments
		return nil
	end
	
	if not string.match(arg1,"^%d*$") then
		-- invalid argument type
		return nil
	end
	
	local num = tonumber(arg1)
	if not num then
		-- invalid argument value
		return nil
	end
	
	if tostring(num) ~= arg1 then
		-- unexpected leading zeros?
		return nil
	end

	local qid = "Q" .. arg1
	local sitelink = mw.wikibase.sitelink(qid)
	
	if sitelink then
		return ""--"<<Kategoria:Wikidane - istniejące artykuły>>"
	else
		return "<sup>[[d:"..qid.."#sitelinks-wikipedia|<span title=\"Poszukaj w innych wersjach językowych\">D</span>]]</sup>"--"<<Kategoria:Wikidane - brakujące artykuły>>"
	end
end

function m.Q(frame)
	local args = frame:getParent().args
	local arg1 = args[1]
	if not arg1 then
		-- missing arguments
		return nil
	end
	
	if not string.match(arg1,"^%d*$") then
		-- invalid argument type
		return nil
	end
	
	local num = tonumber(arg1)
	if not num then
		-- invalid argument value
		return nil
	end
	
	if tostring(num) ~= arg1 then
		-- unexpected leading zeros?
		return nil
	end

	local title1 = args[2]
	local title2 = args[3]
	
	-- reject empty texts
	if title1 and (#title1 == 0) then
		title1 = nil
	end
	if title2 and (#title2 == 0) then
		title2 = nil
	end

	local qid = "Q" .. arg1
	local sitelink = mw.wikibase.sitelink(qid)
	local category
	
	if sitelink then
		wikidata = ""
		category = ""--"<<Kategoria:Wikidane - istniejące artykuły>>"
	else
		sitelink = title1 or mw.wikibase.label(qid) or qid
		wikidata = "<sup>[[d:"..qid.."#sitelinks-wikipedia|<span title=\"Poszukaj w innych wersjach językowych\">*</span>]]</sup>"
		category = ""--"<<Kategoria:Wikidane - brakujące artykuły>>"
	end
	
	local label = title2 and ("|"..title2) or ""
			
	return "[["..sitelink..label.."]]"..wikidata..category
end

function m.D(frame)
    local entity = mw.wikibase.getEntity()
    if not entity then
        return nil
    else
        return string.format(moduleData.wikidataItemLink, entity.id)
    end
end

function m.frameArgsMeta(frame)
	local args = frame.args
	local am = getmetatable(args)
    return "<pre>"..mw.dumpObject(am, "frame.args.metatable").."</pre>"
end

function m.frameContents(frame)
    return "<pre>"..mw.dumpObject(frame, "frame").."</pre>"
end

function m.dump(frame)
	local bug = {}
    local object = _G
    for i, v in ipairs(frame.args) do
        table.insert(bug, v)
        if not object[v] then
            local n = tonumber(v)
            if n and object[n] then
                v = n
            end
        end
        object = object[v]
        if object == nil then
            return "<span class=\"error\">" .. table.concat(bug, "→") .. "</span>"
        end
    end
    -- return contents(object)
    local result = mw.dumpObject(object, table.concat(bug, "→"))
    return "<pre>" .. result .. "</pre>"
end

return m