Moduł:Brudnopis/Paweł Ziemian/Infobox

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

require("strict")
local resources = mw.loadData("Moduł:Infobox/resources")

local function P(frame, qid, pid)
	local sd = require("Module:Wikidane/select")
	return sd.selectProperty(pid, sd.prepareFilters(frame), qid)
end

local function isNullOrWhiteSpace(text)
	return (text == nil)
		or (#text <= 0)
		or string.match(text, "^%s+$")
end

local function addClass(attributes, class)
	if not class or (#class == 0) then
		return attributes
	end
	
	if not attributes or (#attributes == 0) then
		return "class=\""..class.."\""
	end
	
	local r, c = string.gsub(attributes or "", "%f[%w]class%s*=%s*['\"]", "%0"..class.." ", 1)
	if c == 1 then
		return r
	end
	
	return "class=\""..class.."\" "..attributes
end

local function iboxSpan(header, text, row, cell)
	assert(type(header) == "boolean")

	local result = {}
	table.insert(result, "|-")
	if row and (#row > 0) then
		table.insert(result, " ")
		table.insert(result, row)
	end

	table.insert(result, "\n")
	table.insert(result, header and "!" or "|")
	if cell and (#cell > 0) then
		table.insert(result, cell)
		table.insert(result,' ')
	end
	
	table.insert(result, 'colspan="2"|')
	table.insert(result, text)
	table.insert(result, "\n|-\n")
	return table.concat(result)
end

local function emptyCategory(frame, emptyCat)
	if not emptyCat or (mw.title.getCurrentTitle().namespace ~= 0) then
		return ""
	end
	
	if mw.ustring.match(emptyCat, "%[%[[Kk]ategoria:.-%]%]") then
		return emptyCat
	end
	
	local template = frame:getParent():getTitle()
	local infobox = mw.ustring.match(template, "^Szablon:(.- infobox)$")
	return mw.ustring.format(resources.catMissingData, infobox or template, emptyCat)
end

local function InputData(frame, Q, demo, source, sourcepropid)
	local ns = mw.title.getCurrentTitle().namespace
	local add = frame.args["dodaj"]
	local cell = frame.args["pole"]
	local propid = frame.args[sourcepropid or "cecha"]
	local emptyCat = frame.args["kategoria brak"]
	local value = frame.args[source or 1]
	
	add = (add == nil) or (#add > 0)

	if emptyCat and (#emptyCat == 0) then
		emptyCat = false
	end

	if propid and (#propid == 0) then
		propid = false
	end
	
	if isNullOrWhiteSpace(value) then
		value = false
	end
	
	local demovalue = false
	if value then
		demovalue = mw.ustring.match(value, "^%s*{{{(.-)}}}%s*$")
	end
	
	local wdvalue = false
	if add and not demo and (not value or demovalue) and propid then
		local pid, qid, prop = P(frame, Q, propid)
		if pid and qid and prop then
			value = require("Moduł:Wikidane/format").run(frame, pid, prop)
			if not value or (#value <= 0) then
				value = false
			else
				wdvalue = true
			end
		end
	end

	if add and not demo and (not value or (demovalue and not wdvalue)) and emptyCat then
		cell = addClass(cell, resources.classEmpty)
		value = (value or "") .. emptyCategory(frame, emptyCat)
	end
	
	if not demo and demovalue then
		cell = addClass(cell, resources.classMissingArg)
		if ns == 0 then
			value = value..resources.catMissingArg
		end
	end
	
	return add and value or false, cell, demovalue, propid
end

local function Qdemo(frame)
	local Q = frame:getParent().args.Q
	if Q and string.match(Q, "^%d") then
		Q = "Q"..Q
	end
	
	if Q then
		-- jest Q to nie demo
		return Q, false
	end
	
	for k, v in pairs(frame:getParent().args) do
		-- nie ma Q lecz dowolny argument to również nie demo
		return nil, false
	end

	-- nie ma Q ani żadnego parametru, jeśli to źródło szablonu, to musi to być demo
	return nil, (mw.title.getCurrentTitle().fullText == frame:getParent():getTitle())
end

local function editWDlink(qid, pid)
	return "<span class=\"plainlinks wdlink\" title=\"edytuj dane z infoboxu w Wikidanych\">&#x5B;[https://www.wikidata.org/wiki/"..qid.."#"..pid.." e]&#x5D;</span>"
end

local function imageWDdemo(pid)
	if pid then
		if string.match(pid, "^P%d+$") then
			pid = "[[:d:Property:"..pid.."|"..pid.."]]"
		end
		return "<span style=\"white-space: nowrap;\">[[Plik:Wikidata-logo-en.svg|22x20px|link=|Wikidane]] <tt>"..pid.."</tt></span>"
	end
end

local function propertyLabel(frame, propid, propid2)
	local lang = mw.getContentLanguage()
	if not propid2 then
		local pid, qid, prop = P(frame, propid, "P1629")
		if pid and qid and prop then
			mw.logObject(prop, "P1629")
			local value = require("Moduł:Wikidane/format").run(frame, pid, prop)
			if value and (#value > 0) then
				value = mw.ustring.gsub(value, "(|)(%l)", function(bar, lcase) return bar..lang:ucfirst(lcase) end)
				return lang:ucfirst(value)
			end
		end
	end

	local label1 = mw.wikibase.label(propid)
	if not label1 or (#label1 <= 0) then
		return false
	end
	
	if not propid2 then
		return lang:ucfirst(label1)
	end
		
	local label2 = mw.wikibase.label(propid2)
	if not label2 or (#label2 <= 0) then
		return false
	end
		
	local cp1 = { mw.ustring.codepoint(label1, 1, mw.ustring.len(label1)) }
	local cp2 = { mw.ustring.codepoint(label2, 1, mw.ustring.len(label2)) }
	local len = #cp1 < #cp2 and #cp1 or #cp2
	-- find common suffix
	local suffix = false
	for i = 1, len do
		if cp1[#cp1-i+1] ~= cp2[#cp2-i+1] then
			suffix = len - i + 1
			break
		end
	end

	while (suffix < len) and (cp1[#cp1 - suffix + 1] ~= 32) do
		suffix = suffix + 1
	end
	
	if suffix < len then
		label1 = mw.ustring.char(unpack(cp1, 1, #cp1 - suffix))
	end
	
	return lang:ucfirst(mw.text.trim(label1).." i "..mw.text.trim(label2))
end

local function makeDemoArg(wrap, ...)
	local count = select('#', ...)
	if count <= 0 then
		return
	end

	local items = {}
	local index = 1
	while index <= count do
		local v = select(index, ...)
		if v and (type(v) == "string") then
			table.insert(items, v)
		end
		
		index = index + 1
	end
	
	if #items <= 0 then
		return
	end

	local prefix = wrap and "{{{" or ""
	local suffix = wrap and "}}}" or ""
	return prefix..table.concat(items,"&#x7C;")..suffix
end

local function SecondaryInfobox(templateTitle, message)
	local contents = mw.title.getCurrentTitle():getContent()
	local infoboxPattern = "{{ *(%f[%a][%a ]-%f[ ] infobox)%s*|"
	local start = 1
	while true do
		mw.logObject(start, "Kolejny:start")
		local s, e, n = mw.ustring.find(contents, infoboxPattern, start, false)
		if not s then
			break
		end
		
		mw.logObject({s, e, n}, "Kolejny:find{s e n}")
		local prefix = mw.ustring.match(n, "^(%a-):")
		mw.logObject(prefix, "Kolejny:prefix")
		local ns = 10
		if prefix then
			prefix = mw.getCurrentLang():ucfirst(prefix)
			ns = mw.site.namespaces[prefix] or ns
		end
		mw.logObject(ns, "Kolejny:ns")
		local infoboxTitle = mw.title.new(n, ns)
		mw.logObject(infoboxTitle, "Kolejny:infoboxTitle")
		if templateTitle == infoboxTitle then
			mw.logObject(start == 1 and "" or message, "Kolejny:return")
			return start == 1 and "" or message
		end
		
		start = e
	end
	
	mw.log("Kolejny: BRAK")
	return "?"
end

return {
	["Q"] = function(frame)
		local Q, demo = Qdemo(frame)
		return demo and "demo" or Q
	end,
	
	["Demo"] = function(frame)
		local args = require('Module:Arguments').getArgs(frame, { trim = false, removeBlanks = false })
		local result = {}
		local i = 1
		local wd = false
		while true do
			local v = args[i]
			i = i + 1
			if not v then
				break
			end
			
			if #v == 0 then
				if wd then
					table.insert(result, "")
				end
				
				wd = true
			else
				table.insert(result, wd and imageWDdemo(v) or v)
				wd = false
			end
		end
		
		if #result then
			local result = "{{{"..table.concat(result,"&#x7C;").."}}}"
			mw.logObject(result, "result")
			return result
		end
	end,
	
	["Kolejny"] = function(frame)
		local message = frame.args[1]
		if not message or (#mw.text.trim(message) == 0) then
			message = "tak"
		end
		
		local templateTitle = mw.title.new(frame:getParent():getTitle())
		return SecondaryInfobox(templateTitle, message)
	end,

	["Test"] = function(frame)
		local Q, demo = Qdemo(frame)
		if demo then
			return "demo"
		end
		
		local i = 1
		local sd = require("Module:Wikidane/select")
		while true do
			local pid = frame.args[i]
			if not pid then
				return
			end
			
			local pid, qid, prop = sd.selectProperty(pid, {}, Q)
			if qid then
				return pid
			end
			
			i = i + 1
		end
	end,

	["Tytuł"] = function(frame)
		local Q, demo = Qdemo(frame)
		local emptyCat = frame.args["kategoria brak"]
		local attrs = frame.args["pole"]
		local props = frame.args["cecha"] or resources.defaultTitle2Property
		local text1 = frame.args[1]
		local text2 = frame.args[2]
		local text3 = frame.args[3]
		
		if isNullOrWhiteSpace(text1) then
			text1 = false
		end
		if isNullOrWhiteSpace(text2) then
			text2 = false
		end
		if isNullOrWhiteSpace(text3) then
			text3 = false
		end

		local demo1 = false
		if text1 then
			demo1 = mw.ustring.match(text1, "^{{{(.-)}}}$")
		end
		local demo2 = false
		if text2 then
			demo2 = mw.ustring.match(text2, "^{{{(.-)}}}$")
		end
		local demo3 = false
		if text3 then
			demo3 = mw.ustring.match(text3, "^{{{(.-)}}}$")
		end

		local Q, demo = Qdemo(frame)

		local builder = mw.html.create()
		builder:wikitext("|+")
		if attrs and (#attrs > 0) then
			builder:wikitext(" ", attrs, " | ")
		end

		local titleWithText = false
		local function appendPart(class)
			if titleWithText then
				builder:tag("br")
			end
			
			titleWithText = true
			return builder:tag("span"):addClass(class)
		end
		
		local label = false
		if demo and demo1 then
			appendPart(resources.classTitle1):wikitext("{{{", demo1, "&#x7C;", imageWDdemo("Etykieta"), "}}}")
		elseif demo then
			appendPart(resources.classTitle1):wikitext(imageWDdemo("Etykieta"))
		elseif text1 and (#text1 > 0) then
			appendPart(resources.classTitle1):wikitext(text1)
		else
			label = mw.wikibase.label(Q)
			if label then
				appendPart(resources.classTitle1):wikitext(label)
			end
		end
		
		local props1 = {}
		local props2 = {}
		for propid in string.gmatch(props, "%S+") do
			table.insert(props1, propid)
			table.insert(props2, "&#x7C;")
			table.insert(props2, imageWDdemo(propid))
		end
		props2 = table.concat(props2, "")
		
		mw.text.split(props, "%s")
		if demo and demo2 then
			appendPart(resources.classTitle2):wikitext("{{{", demo2, props2, "}}}")
		elseif demo and (#props1 > 0) then
			appendPart(resources.classTitle2):wikitext("{{{", props2, "}}}")
		elseif text2 and (#text2 > 0) then
			appendPart(resources.classTitle2):wikitext(text2)
		elseif #props1 > 0 then
			local pid, qid, prop
			for _, propid in ipairs(props1) do
				pid, qid, prop = P(frame, Q, propid)
				if qid and prop then
					local text2 = require("Moduł:Wikidane/format").run(frame, pid, prop)
					if text2 then
						local lang = mw.getContentLanguage()
						local l = label and lang:caseFold(label) or label
						local t1 = text1 and lang:caseFold(text1) or text1
						local t2, _ = mw.ustring.gsub(text2, "</?[A-Za-z]+ ?[^<>]*/?>", "") -- remove HTML tags
						t2 = lang:caseFold(t2)
						if (t2 ~= t1) and (t2 ~= l) then
							appendPart(resources.classTitle2):wikitext(text2)
							break
						end
					end
				end
			end
		end
		
		if text3 and (#text3 > 0) then
			appendPart(resources.classTitle3):wikitext(text3)
		end
		
		if not titleWithText then
			-- use page title
			local title = mw.title.getCurrentTitle()
			local text = title.text
			local nodisambig = mw.ustring.match(text, "^(.-)%s+%([^%(%)]+%)$")
			if nodisambig and (#nodisambig > 0) then
				text = nodisambig
			end
			
			appendPart(resources.classEmpty):wikitext(text, emptyCategory(frame, emptyCat))
		end
		
		if not titleWithText then
			-- no text
			return
		end
		
		builder:wikitext("\n")
		return builder:allDone()
	end,

	["Grafika"] = function(frame)
		local add = frame.args["dodaj"]
		add = (add == nil) or (#add > 0)
		if not add then
			return
		end
		
		local function formatFile(file, alt, format, description)
			
			local function removeLinks(text)
				--mw.logObject(text, "RemoveLinks:input")
				if text then
					text = mw.ustring.gsub(text, "%s+", " ") -- compact white characters into one space
					text = mw.ustring.gsub(text, "%[https?://[^%[%]%s|]+%]", "") -- remove LZ
					text = mw.ustring.gsub(text, "%[https?://[^%[%]%s|]+ ([^%[%]|]+)%]", "%1") -- remove LZ, leave description
					text = mw.ustring.gsub(text, "%[%[[^%[%]|]+|([^%[%]|]*)%]%]", "%1" ) -- remove wikilinks, leave description
					text = mw.ustring.gsub(text, "%[%[([^%[%]|]*)%]%]", "%1" ) -- remove wikilinks, leave description
					text = mw.ustring.gsub(text, "%s+", " ") -- compact white characters into one space again
					text = mw.text.nowiki(text)
				end
				
				--mw.logObject(text, "RemoveLinks:output")
				return text
			end

			local result = {}
			table.insert(result, "[[Plik:")
			table.insert(result, file)
			if format and (#format > 0) then
				table.insert(result, "|")
				table.insert(result, format)
				if mw.ustring.match(format, "^%s*alt%s*=") or mw.ustring.match(format, "|%s*alt%s*=") then
					alt = false
				end
			end
			if alt and (#alt > 0) then
				table.insert(result, "|alt=")
				table.insert(result, removeLinks(alt))
			end
			if description and (#description > 0) then
				table.insert(result, "|")
				table.insert(result, removeLinks(description))
			end
			
			table.insert(result,"]]")
			return table.concat(result)
		end
		
		local function checkIfFileExists(file)
			local pattern, _ = mw.ustring.gsub( file, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" )
			pattern, _ = mw.ustring.gsub(pattern, "[ _]", "[ _]")
			pattern = "%[%[%s*(%a+)%s*:"..pattern.."%s*[%]|]"
			--mw.logObject(pattern, "Grafika:checkIfFileExists PATTERN")
			local contents = mw.title.getCurrentTitle():getContent()
			local start = 1
			while true do
				--mw.logObject(start, "Grafika:checkIfFileExists NEXT")
				local s, e, n = mw.ustring.find(contents, pattern, start, false)
				if not s then
					--mw.logObject(file, "Grafika:checkIfFileExists FALSE")
					return false
				end
				
				--mw.logObject({n,file}, "Grafika:checkIfFileExists{n,file}")
				local title = mw.title.new(file, n)
				if title and (title.namespace == 6) then
					--mw.logObject(file, "Grafika:checkIfFileExists TRUE")
					return true
				end
				
				start = e
			end
		end
		
		local Q, demo = Qdemo(frame)
		local row = frame.args["wiersz"]
		local cell = frame.args["pole"]
		local format = frame.args["format"]
		local imageTitle = false
		local secondary = false
		local callingTemplate = frame:getParent():getTitle()
		if mw.title.new(callingTemplate) == mw.title.new("Szablon:Infobox grafika") then
			imageTitle = frame:getParent().args["tytuł grafiki"]
			secondary = frame:getParent().args["kolejny"]
		else
			imageTitle = frame.args["tytuł grafiki"]
			if (#callingTemplate > 8) and (mw.ustring.sub(callingTemplate, -8) == " infobox") then
				secondary = SecondaryInfobox(callingTemplate, callingTemplate)
			end
		end
		
		local wdExists = false
		
		local function loadPicture(file, description, alt, fileProperty, descProperty, defaultFormat)
			if file == "nie" then
				return
			end
			
			if isNullOrWhiteSpace(file)	then
				file = false
				description = false
			elseif isNullOrWhiteSpace(description) then
				description = false
			end
			
			if isNullOrWhiteSpace(fileProperty) then
				fileProperty = false
				descProperty = false
			elseif isNullOrWhiteSpace(descProperty) then
				descProperty = false
			end
			
			local desc = nil
			local patched = false
			if not alt and fileProperty then
				alt = mw.wikibase.label(fileProperty)
			end
			
			local demoFile = false
			local demoDescription = false
			if file then
				demoFile = mw.ustring.match(file, "^{{{(.-)}}}$")
				if not demoFile then
					file = mw.ustring.gsub(file, "%s*[Pp]lik%s*:%s*", "Plik:")
					file = mw.ustring.gsub(file, "%s*[Ff]ile%s*:%s*", "Plik:")
					file = mw.ustring.gsub(file, "%s*[Gg]rafika%s*:%s*", "Plik:")
					file = mw.ustring.gsub(file, "%s*[Ii]mage%s*:%s*", "Plik:")
					if mw.ustring.match(file, "^Plik:(.*)") then
					    file = mw.ustring.match(file, "^Plik:(.*)")
					    patched = true
					elseif mw.ustring.match(file, "%[%[Plik:([^%[%]|]+)[|%]]") then
					    file = mw.ustring.match(file, "%[%[Plik:([^%[%]|]+)[|%]]")
					    patched = true
					end
				end
			end
			if description then
				demoDescription = mw.ustring.match(description, "^{{{(.-)}}}$")
			end
			
			if not demo and (not file or demoFile) and fileProperty then
				if secondary and (#secondary > 0) then
					mw.logObject(secondary, "Grafika: nie ładuję obrazka z Wikidanych na drugim lub kolejnym infoboksie")
					return
				end
				
				local pid, qid, prop = P(frame, Q, fileProperty)
				if pid and qid and prop then
					for _, v in ipairs(prop) do
						if v.mainsnak and (v.mainsnak.snaktype == "value") and (v.mainsnak.datatype == "commonsMedia") and v.mainsnak.datavalue and (v.mainsnak.datavalue.type == "string") then
							local commonMedia = v.mainsnak.datavalue.value
							if not isNullOrWhiteSpace(commonMedia) then
								if checkIfFileExists(commonMedia) then
									mw.logObject(commonMedia, "Grafika: obrazek, który jest oferowany w Wikidanych, już jest umieszczony w kodzie strony")
									wdExists = true
									return
								end
								
								file = commonMedia
								alt = mw.wikibase.label(v.mainsnak.property)
								desc = require("Moduł:Wikidane/format/qualifiers").TEXT1(v, nil, "P2096")
								break
							end
						end
					end
				end
			
				if file and descProperty then
					pid, qid, prop = P(frame, Q, descProperty)
					if pid and qid and prop then
						local v = require("Moduł:Wikidane/format").run(frame, pid, prop)
						if not isNullOrWhiteSpace(v) then
							description = v
						end
					end
				end
			end
		
			if not demo and file then
				return {
					formatFile(file, alt, defaultFormat, desc or description)..(patched and resources.catPatchedFile or ""),
					description or desc
				}
			end
		
			if demo and (demoFile or fileProperty) then
				return {
					formatFile(makeDemoArg(true, demoFile, imageWDdemo(fileProperty)), alt, format or defaultFormat, false),
					makeDemoArg(true, demoDescription, imageWDdemo(descProperty))
				}
			end
		end

		local args = {
			file = "grafika", description = "opis grafiki", alt = "alt grafiki", fileProperty = "cecha", descProperty = "cecha opisu", defaultFormat = "240x240px",
			fileN = "%d. grafika", descriptionN = "%d. opis grafiki", altN = "%d. alt grafiki", filePropertyN = "%d. cecha", descPropertyN = "%d. cecha opisu", defaultFormatN = "100x100px",
		}
		
		local bigImage = loadPicture(frame.args[args.file], frame.args[args.description], frame.args[args.alt], frame.args[args.fileProperty], frame.args[args.descProperty], args.defaultFormat)
		mw.logObject(bigImage, "bigImage")
		local smallImages = {}
		local index = 1
		while true do
			local file = frame.args[mw.ustring.format(args.fileN, index)]
			local description = frame.args[mw.ustring.format(args.descriptionN, index)]
			local alt = frame.args[mw.ustring.format(args.altN, index)]
			local fileProperty = frame.args[mw.ustring.format(args.filePropertyN, index)]
			local descProperty = frame.args[mw.ustring.format(args.descPropertyN, index)]
			if not file and not fileProperty then
				break
			end
			
			index = index + 1
			local image = loadPicture(file, description, alt, fileProperty, descProperty, args.defaultFormatN)
			if image then
				table.insert(smallImages, image)
			end
		end
		
		local result = {}
		if wdExists and secondary and (#secondary == 0) and (mw.title.getCurrentTitle().namespace == 0) then
			table.insert(result, '|- style="display:none"\n| colspan="2" |"')
			table.insert(result, resources.catIgnoreImage)
			table.insert(result, '\n')
		end
		
		if bigImage then
			if imageTitle and (#imageTitle > 0) then
				table.insert(bigImage, 1, '<span style="font-weigth: bold>'..imageTitle..'</span>')
			end
			
			table.insert(result, iboxSpan(false, table.concat(bigImage, "<br />"), row, cell))
		end
		
		if #smallImages > 0 then
			local index = 1
			table.insert(result, '|-')
			table.insert(result, row)
			table.insert(result, '\n|colspan="2" padding="0" ')
			table.insert(result, cell)
			table.insert(result, '|\n{| class="ibox2"\n')
			
			-- display images in pairs
			while (index + 1) <= #smallImages do
				local image1 = smallImages[index + 0]
				local image2 = smallImages[index + 1]
				-- both files must exists
				table.insert(result, '|-\n|')
				table.insert(result, image1[1])
				table.insert(result, '\n|')
				table.insert(result, image2[1])
				table.insert(result, '\n')
				-- descriptions are optional
				if image1[2] or image2[2] then
					table.insert(result, '|-\n|')
					table.insert(result, image1[2] or "")
					table.insert(result, '\n|')
					table.insert(result, image2[2] or "")
					table.insert(result, '\n')
				end
				
				-- next pair
				index = index + 2
			end
			
			-- display last odd image
			if index == #smallImages then
				local image = smallImages[index]
				table.insert(result, '|-\n|colspan=2|')
				table.insert(result, image[1])
				table.insert(result, '\n')
				if image[2] then
					table.insert(result, '|-\n|colspan=2|')
					table.insert(result, image[2])
					table.insert(result, '\n')
				end
			end
		
			table.insert(result, '|-\n|}\n|-\n')
		end
		if #result > 0 then
			return table.concat(result)
		end
	end,
	
	["Grupa"] = function(frame)
		local Q, demo = Qdemo(frame)
		local emptyCat = frame.args["kategoria brak"]
		local header = frame.args["nagłówek"]
		local headerRow = frame.args["wiersz nagłówka"]
		local headerCell = frame.args["pole nagłówka"]
		local lineClass = frame.args["klasa kreski"]
		local result = {}
		
		local append = function(text)
			if (#result == 0) and header then
				local cell = headerCell
				if #header == 0 then
					cell = addClass(headerCell, resources.classEmpty)
					header = emptyCategory(frame, emptyCat)
				elseif not demo and mw.ustring.match(header, "^{{{(.-)}}}$") then
					cell = addClass(headerCell, resources.classMissingArg)
				end
				
				table.insert(result, iboxSpan(true, header, headerRow, cell))
			end
		
			table.insert(result, text)
		end
		
		local total = false
		local sep = false
		local i = 1
		while true do
			local arg = frame.args[i]
			if not arg then
				break
			end
			
			i = i + 1
			arg = string.match(arg, "^(.-)%s*$") -- trim remaing space
			if arg == "-" then
				sep = true
			elseif #arg > 0 then -- real content
				local next = false
				for line in mw.text.gsplit(arg, "\n%f[|!]", false) do
					if next then
						append("\n")
					end
					
					next = true
					if sep and (#line >= 2) and (string.byte(line, 1) == 124) and (string.byte(line, 2) == 45) then
						-- row with separator line
						local class = string.match(line, 'class="(.-)"')
						local newClass = resources.classSeparator
						if lineClass and (#lineClass > 0) then
							newClass = newClass.." "..lineClass
						end
						
						if class then
							line = string.gsub(line, 'class="', 'class="'..newClass.." ", 1)
						else
							line = mw.text.trim(line)..' class="'..newClass..'"'
						end
					else
						-- content or row without separator line
						sep = false
					end
					
					append(line)
				end
			end
		end
	
		return table.concat(result)
	end,
	
	["Blok"] = function(frame)
		local Q, demo = Qdemo(frame)
		local headerRow = frame.args["wiersz nagłówka"]
		local headerCell = frame.args["pole nagłówka"]
		local row = frame.args["wiersz"]
		local label = frame.args["nagłówek"]
		local value, cell, demovalue, propid = InputData(frame, Q, demo)

		if label == "-" then
			label = false
			row = addClass(row, resources.classSeparator)
		elseif label and (#label == 0) then
			label = false
		elseif not label and propid then
			label = propertyLabel(frame, propid)
		end
		
		local demolabel = false
		if label then
			demolabel = mw.ustring.match(label, "^{{{(.-)}}}$")
		end
		
		local text = false
		if demo and demovalue and propid then
			text = "{{{"..demovalue.."&#x7C;"..imageWDdemo(propid).."}}}"
		elseif demo and propid then
			text = "{{{"..imageWDdemo(propid).."}}}"
		elseif demo and demolabel then
			text = "{{{"..demovalue.."}}}"
		elseif value then
			text = value
		end
		
		if not text then
			return
		end
		
		local header
		if label == false then
			header = false
		elseif label and (#label > 0) then
			header = label
		elseif demo and demolabel and propid then
			header = "{{{"..demolabel.."&#x7C;"..imageWDdemo("label").."}}}"
		elseif demo and propid then
			header = "{{{"..imageWDdemo("label").."}}}"
		elseif demo and demolabel then
			header = "{{{"..demolabel.."}}}"
		elseif propid then
			header = "{{{nagłówek}}}"..resources.catMissingLabel
		elseif demo then
			header = "{{{nagłówek}}}"
		end
		
		local result = {}
		if header then
			table.insert(result, iboxSpan(true, header, headerRow, headerCell))
		end
		
		table.insert(result, iboxSpan(false, text, row, cell))
		return table.concat(result)
	end,

	["Wiersz"] = function(frame)
		local Q, demo = Qdemo(frame)
		local row = frame.args["wiersz"]
		local label = frame.args["etykieta"]
		local value, cell, demovalue, propid = InputData(frame, Q, demo)

		if label and (#label == 0) then
			label = false
		end
		
		if not label and propid then
			label = propertyLabel(frame, propid)
		end
		
		local demolabel = false
		if label then
			demolabel = mw.ustring.match(label, "^{{{(.-)}}}$")
		end
		
		local builder = mw.html.create()
		builder:wikitext("|-")
		if row and (#row > 0) then
			builder:wikitext(" ", row, " | ")
		end

		builder:wikitext("\n!")
		
		if label and (#label > 0) then
			builder:wikitext(label)
		elseif demo and demolabel and propid then
			builder:wikitext("{{{", demolabel, "&#x7C;", imageWDdemo("label"), "}}}")
		elseif demo and propid then
			builder:wikitext("{{{", imageWDdemo("label"), "}}}")
		elseif demo and demolabel then
			builder:wikitext("{{{", demolabel, "}}}")
		elseif propid then
			builder:wikitext("{{{etykieta}}}", resources.catMissingLabel)
		else
			builder:wikitext("{{{etykieta}}}")
		end
		
		builder:wikitext("\n|")
		if cell and (#cell > 0) then
			builder:wikitext(cell)
			builder:wikitext("|")
		end
		
		if demo and demovalue and propid then
			builder:wikitext("{{{", demovalue, "&#x7C;", imageWDdemo(propid), "}}}")
		elseif demo and propid then
			builder:wikitext("{{{", imageWDdemo(propid), "}}}")
		elseif demo and demovalue then
			builder:wikitext("{{{", demovalue, "}}}")
		elseif value then
			builder:wikitext(value)
		else
			return
		end
		
		builder:wikitext("\n|-")
		return builder:allDone()
	end,
	
	["Wiersz2"] = function(frame)
		local Q, demo = Qdemo(frame)
		local row = frame.args["wiersz"]
		local label = frame.args["etykieta"]
		local label1 = frame.args["etykieta 1"]
		local label2 = frame.args["etykieta 2"]
		local value1, cell, demovalue1, propid1 = InputData(frame, Q, demo, 1, "cecha 1")
		local value2, _, demovalue2, propid2 = InputData(frame, Q, demo, 2, "cecha 2")

		if label and (#label == 0) then
			label = false
		end
		
		if not label and propid1 and propid2 then
			label = propertyLabel(frame, propid1, propid2)
		end

		if label1 and (#label1 == 0) then
			label1 = false
		end
		
		if not label1 and propid1 then
			label1 = propertyLabel(frame, propid1)
		end

		if label2 and (#label2 == 0) then
			label2 = false
		end
		
		if not label2 and propid2 then
			label2 = propertyLabel(frame, propid2)
		end

		local demolabel1 = false
		if label1 then
			demolabel1 = mw.ustring.match(label1, "^{{{(.-)}}}$")
		end
		
		local demolabel2 = false
		if label2 then
			demolabel2 = mw.ustring.match(label2, "^{{{(.-)}}}$")
		end
		
		local builder = mw.html.create()
		builder:wikitext("|-")
		if row and (#row > 0) then
			builder:wikitext(" ", row, " | ")
		end

		builder:wikitext("\n!")
		
		if demo then
			if label and (#label > 0) then
				builder:wikitext(label)
			else
				if label1 and (#label1 > 0) then
					builder:wikitext(label1)
				elseif demolabel1 and propid1 then
					builder:wikitext("{{{", demolabel1, "&#x7C;", imageWDdemo("label1"), "}}}")
				elseif propid1 then
					builder:wikitext("{{{", imageWDdemo("label1"), "}}}")
				elseif demolabel1 then
					builder:wikitext("{{{", demolabel1, "}}}")
				elseif propid1 then
					builder:wikitext("{{{etykieta 1}}}", resources.catMissingLabel)
				else
					builder:wikitext("{{{etykieta 1}}}")
				end
				builder:wikitext(" i ")
				if label2 and (#label2 > 0) then
					builder:wikitext(label2)
				elseif demolabel2 and propid2 then
					builder:wikitext("{{{", demolabel2, "&#x7C;", imageWDdemo("label2"), "}}}")
				elseif propid2 then
					builder:wikitext("{{{", imageWDdemo("label2"), "}}}")
				elseif demolabel2 then
					builder:wikitext("{{{", demolabel2, "}}}")
				elseif propid2 then
					builder:wikitext("{{{etykieta 2}}}", resources.catMissingLabel)
				else
					builder:wikitext("{{{etykieta 2}}}")
				end
			end
		elseif value1 and value2 and label then
			builder:wikitext(label)
		elseif value1 and value2 and label1 and label2 then
			builder:wikitext(label1, " i ", label2)
		elseif value1 and value2 then
			builder:wikitext("{{{etykieta}}}", resources.catMissingLabel)
		elseif value1 and label1 then
			builder:wikitext(label1)
		elseif value1 then
			builder:wikitext("{{{etykieta 1}}}", resources.catMissingLabel)
		elseif value2 and label2 then
			builder:wikitext(label2)
		elseif value2 then
			builder:wikitext("{{{etykieta 2}}}", resources.catMissingLabel)
		else
			return
		end

		builder:wikitext("\n|")
		if cell and (#cell > 0) then
			builder:wikitext(cell)
			builder:wikitext("|")
		end
		
		local br = true
		if demo and demovalue1 and propid1 then
			builder:wikitext("{{{", demovalue1, "&#x7C;", imageWDdemo(propid1), "}}}")
		elseif demo and propid1 then
			builder:wikitext("{{{", imageWDdemo(propid1), "}}}")
		elseif demo and demovalue1 then
			builder:wikitext("{{{", demovalue1, "}}}")
		elseif value1 then
			builder:wikitext(value1)
		else
			br = false
		end
		
		if demo and demovalue2 and propid2 then
			if br then builder:tag("br") end
			builder:wikitext("{{{", demovalue2, "&#x7C;", imageWDdemo(propid2), "}}}")
		elseif demo and propid2 then
			if br then builder:tag("br") end
			builder:wikitext("{{{", imageWDdemo(propid2), "}}}")
		elseif demo and demovalue2 then
			if br then builder:tag("br") end
			builder:wikitext("{{{", demovalue2, "}}}")
		elseif value2 then
			if br then builder:tag("br") end
			builder:wikitext(value2)
		end
		
		builder:wikitext("\n|-")
		return builder:allDone()
	end,
	
	["Fragment"] = function(frame)
		local Q, demo = Qdemo(frame)
		local value, unused, demovalue, propid = InputData(frame, Q, demo)
		local text = false
		if demo and demovalue and propid then
			text = "{{{"..demovalue.."&#x7C;"..imageWDdemo(propid).."}}}"
		elseif demo and propid then
			text = "{{{"..imageWDdemo(propid).."}}}"
		elseif demo and demolabel then
			text =  "{{{"..demovalue.."}}}"
		elseif value then
			return value
		end
		
		return text and '|-\n|colspan="2"|'..text.."\n" or ""
	end,
	
	["Drzewo"] = function(frame)
		local Q, demo = Qdemo(frame)
		local headerRow = frame.args["wiersz nagłówka"]
		local headerCell = frame.args["pole nagłówka"]
		local header = frame.args["nagłówek"]
		local row = frame.args["wiersz"] or 'class="tree"'
		local cell = frame.args["pole"]
		
		local text = false
		if demo then
			text = imageWDdemo("'''Skrypt Lua'''")
		else
			if not Q then
				local entity = mw.wikibase.getEntity()
				if not entity then
					return
				end
				
				Q = entity.id
			end
			
			text = require("Module:Wikidane/Tree").classTree(frame, Q)
		end
		
		if not text then
			return
		end
		
		if header == "-" then
			header = false
			row = addClass(row, resources.classSeparator)
		elseif header and (#header == 0) then
			label = false
		end
		
		local result = {}
		if header then
			table.insert(result, iboxSpan(true, header, headerRow, headerCell))
		end
		
		table.insert(result, iboxSpan(false, text, row, cell))
		return table.concat(result, "")
	end,

	["Projekt"] = function(frame)
		local Q, demo = Qdemo(frame)
		local entity = mw.wikibase.getEntity(Q)
		local standardLink = function(sitelink)
			return entity and entity.sitelinks and entity.sitelinks[sitelink] and entity.sitelinks[sitelink].title
		end
		local standardProp = function(pid)
			local pid, qid, prop = require("Module:Wikidane/select").selectProperty(pid, {}, Q)
			if prop and prop[1] then
				local snak = prop[1].mainsnak
				if (snak.snaktype == "value") and (snak.datatype == "string") then
					return snak.datavalue.value
				end
			end
		end
		local demoProp = function(sitelink, arg)
			local demovalue = false
			if arg then
				demovalue = mw.ustring.match(arg, "^{{{(.-)}}}$")
			end
			
			local result = {}
			if demovalue then
				table.insert(result, "&#8203;") -- wrap here
				table.insert(result, "{{{")
				table.insert(result, demovalue)
				table.insert(result, "&#x7C;&#8203;")
				table.insert(result, imageWDdemo(sitelink))
				table.insert(result, "}}}&#8203;")
			else
				table.insert(result, "&#8203;")
				table.insert(result, imageWDdemo(sitelink))
				table.insert(result, "&#8203;")
			end
			
			return table.concat(result)
		end
		local projects = {
			{
				arg = "wikipedia",
				icon = "wikipedia",
				text = function()
					if demo then
						return "Wikipedia w języku [[:d:Property:P424|P424]]"
					end
					
					local wikilang = arg or standardProp("P424")
					if wikilang == "pl" then
						return "Wikipedia w [[Wikipedia:Strona główna|języku polskim]]"
					end
					
					if wikilang then
						return mw.ustring.format("Wikipedia w [[:%s:|języku %s]]", wikilang, mw.loadData("Module:Lang/data")[wikilang].miejscownik)
					end
				end,
			},
			{
				arg = "c",
				icon = "commons",
				text = function(arg)
					local link = false
					if demo then
						link = demoProp("commonswiki", arg)
					elseif arg then
						link = arg
					else
						link = standardLink("commonswiki")
						if not link then
							local cat = standardProp("P373")
							if cat then
								link = "Category:"..cat
							else
								--or standardProp("P910") -- main category article
							end
						end
					end
				
					if link then
						return mw.ustring.format("[[commons:%s|Multimedia w Wikimedia Commons]]", link)
					end
				end,
			},
			{
				arg = "n",
				icon = "wikinews",
				text = function(arg)
					local link = demo and demoProp("plwikinews", arg) or (arg or standardLink("plwikinews"))
					if link then
						return mw.ustring.format("[[n:%s|Wiadomości w Wikinews]]", link)
					end
				end,
			},
			{
				arg = "q",
				icon = "wikicytaty",
				text = function(arg)
					local link = demo and demoProp("plwikiquote", arg) or (arg or standardLink("plwikiquote"))
					if link then
						return mw.ustring.format("[[q:%s|Teksty w Wikicytatach]]", link)
					end
				end,
			},
			{
				arg = "s",
				icon = "wikiźródła",
				text = function(arg)
					local link = demo and demoProp("plwikisource", arg) or (arg or standardLink("plwikisource"))
					if link then
						return mw.ustring.format("[[s:%s|Teksty w Wikiźródłach]]", link)
					end
				end,
			},
			{
				arg = "wikt",
				icon = "wikisłownik",
				text = function(arg)
					-- nie ma jeszcze linków w Wikidanych
					local link = arg or (demo and "" or false)
					if link then
						return mw.ustring.format("[[wikt:%s|Hasło w Wikisłowniku]]", link)
					end
				end,
			},
			{
				arg = "wikispecies",
				icon = "wikispecies",
				text = function(arg)
					local link = demo and demoProp("specieswiki", arg) or (arg or standardLink("specieswiki"))
					if link then
						return mw.ustring.format("[[wikispecies:%s|Systematyka w Wikispecies]]", link)
					end
				end,
			},
			{
				arg = "voy",
				icon = "wikipodróże",
				text = function(arg)
					local link = demo and demoProp("plwikivoyage", arg) or (arg or standardLink("plwikivoyage"))
					if link then
						return mw.ustring.format("[[voy:%s|Informacje w Wikipodróżach]]", link)
					end
				end,
			},
			{
				arg = "b",
				icon = "wikibooks",
				text = function(arg)
					local link = demo and demoProp("plwikibooks", arg) or (arg or standardLink("plwikibooks"))
					if link then
						return mw.ustring.format("[[b:%s|Książki w Wikibooks]]", link)
					end
				end,
			},
			{
				arg = "wikt:cat",
				icon = "wikisłownik",
				text = function(arg)
					if demo then
						return "W Wikisłowniku: słownik języka [[:d:Property:P424|P424]]"
					end
					
					if arg then
						local data = mw.loadData("Module:Lang/data")[standardProp("P424") or ""]
						return mw.ustring.format("W Wikisłowniku: [[wikt:Kategoria:%s|słownik języka%s]]", arg, data and (" "..data["dopełniacz"]) or "")
					end
				end,
			},
		}
	
		local result = {}
		for _, project in ipairs(projects) do
			local param = frame.args[project.arg]
			if param then
				local text = project.text(#param > 0 and param or nil)
				if text then
					if #result == 0 then
						local header = frame.args["nagłówek"] or resources.defaultProjectHeader
						if #header > 0 then
							table.insert(result, iboxSpan(true, header, frame.args["wiersz nagłówka"], frame.args["pole nagłówka"]))
						end
					end
					
					--local icon = "<div style=\"float:left; margin-right: 0.5em\">[[Plik:"..require("Module:Ikona").plik(project.icon).."|20px]]</div>"
					local icon = "[[Plik:"..require("Module:Ikona").plik(project.icon).."|20px|link=|alt=]]"
					table.insert(result, iboxSpan(false, icon..text, addClass(frame.args["wiersz"], resources.classSisterProject), frame.args["pole"]))
				end
			end
		end
		
		return table.concat(result, "")
	end,

	["Państwo"] = function(frame)
		local Q, demo = Qdemo(frame)
		if not Q then
			Q = mw.wikibase.getEntityIdForCurrentPage()
		end
		if not Q then
			return
		end
		
		local statements = mw.wikibase.getBestStatements(Q, "P17")
		local errorCat = frame.args.kategoria
		local link = frame.args.link
		local altlink = frame.args.altlink
		local nazwa = frame.args.nazwa
		local opis = frame.args.opis
		local results = {}
		for i, s in ipairs(statements) do
			local countryName = mw.wikibase.renderSnak(s.mainsnak)
			local templateCountry = mw.title.new("Państwo dane "..countryName, "Szablon")
			local result
			if templateCountry.exists then
				local dependent = frame:expandTemplate{ title = "Terytorium zależne", args = {
					[1] = countryName,
					[2] = countryName
				}}
				if dependent and (#dependent == 0) then
					dependent = nil
				end
				result = frame:expandTemplate{ title = templateCountry.text, args = {
					[1] = "infobox państwo/core",
					wariant = dependent or countryName,
					link = link,
					altlink = altlink,
					nazwa = nazwa,
					rozmiar = i == 1 and opis or "&nbsp;"
				}}
			else -- nie ma szablonu państwa
				result = frame:expandTemplate{ title = "Infobox wiersz", args = {
					[1] = "[[Państwo]]",
					[2] = errorCat.."WD"..tostring(i)..": "..countryName,
					kol2 = 'class="linksInherit" style="background:yellow; color:red;"'
				}}
			end
			if result then
				table.insert(results, result)
			end
		end
		
		mw.logObject(results, "results")
		return table.concat(results)
		
	end,
}