Moduł:Brudnopis/Paweł Ziemian/WDbox

Z Wikipedii, wolnej encyklopedii

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

local moduleData = mw.loadData("Module:Wikidane/data")

local function Ignored()
	local result = {}
	for _, v in ipairs(mw.loadData("Moduł:WDbox/ignored")) do
		result[v] = true
	end
	
	return result
end

local function Index()
	
	local parseSeparator = function(arg)
		if arg == moduleData.separatorAnd then
			return moduleData.defaultSeparator, moduleData.defaultLastAndSeparator
		elseif arg == moduleData.separatorOr then
			return moduleData.defaultSeparator, moduleData.defaultLastOrSeparator
		elseif arg == moduleData.separatorBullet then
			return "</li><li>", "</li><li>", "<ul><li>", "</li></ul>"
		elseif arg == moduleData.separatorOrdered then
			return "</li><li>", "</li><li>", "<ol><li>", "</li></ol>"
		elseif arg == moduleData.separatorOptionalBullet then
			return "</li><li>", "</li><li>", "<ul><li>", "</li></ul>", true
		elseif arg == moduleData.separatorOptionalOrdered then
			return "</li><li>", "</li><li>", "<ol><li>", "</li></ol>", true
		elseif arg == moduleData.separatorOr then
			return moduleData.defaultSeparator, moduleData.defaultLastOrSeparator
		elseif arg ~= nil then -- custom
			return arg, arg
		end
	end

	local lastGroup
	local groups = { [0]=0, [1]=1, [2]=2, }
	local result = {}
	for i, v in ipairs(mw.loadData("Moduł:WDbox/sorted")) do
		local key
		if type(v) == "string" then
			key = string.match(v, "^P%d+$")
		elseif (type(v) == "table") and (type(v[1]) == "string") then
			key = string.match(v[1], "^P%d+$")
		end
		
		if key and not result[key] then
			local item = {}
			if type(v) == "table" then
				for k, w in pairs(v) do
					item[k] = w
				end
				if item[2]==nil then
					item[2] = "blok"
				end
			else
				item[1] = key
			end
			
			item.group = lastGroup
			item.index = i

			local sep, lastSep, before, after, optional = parseSeparator(item.sep)
			item.separator = sep;
			item.lastSeparator = lastSep;
			item.separatorBefore = before;
			item.separatorAfter = after;
			
			-- global defaults
			item.separator = item.separator or moduleData.defaultSeparator
			item.lastSeparator = item.lastSeparator or moduleData.defaultSeparator
			item.linkCoordinates = (item.linkCoordinates == nil) and moduleData.defaultLinkCoordinates or item.linkCoordinates
			item.linkDate = (item.linkDate == nil) and moduleData.defaultLinkDate or item.linkDate
			item.linkItem = (item.linkItem == nil) and moduleData.defaultLinkItem or item.linkItem
			item.separatorBefore = item.separatorBefore or ""
			item.separatorAfter = item.separatorAfter or ""
			
			result[key] = item
		elseif not key and (type(v) == "string") then
			table.insert(groups, v)
			lastGroup = #groups
		elseif not key and ((v == 0) or (v == 1) or (v == 2)) then
			lastGroup = v
		end
	end
	
	return result, groups
end

local function listToText(items, options)
	if (#items == 0) then
		return
	end
	
	if (#items == 1) and options.separatorOptional then
		return items[1]
	end
	
	return options.separatorBefore..mw.text.listToText(items, options.separator, options.lastSeparator)..options.separatorAfter
end

local imageExtensions = {
	png = true,
	jpg = true,
	jpeg = true,
	jpe = true,
	svg = true,
	gif = true,
	tif = true,
	tiff = true,
	xcf = true,
--	pdf = true,
--	djvu = true,
--	webp = true,
}

local projects = {
	{
		project = "commonswiki",
		icon = "commons",
		format = "[[commons:%s|Multimedia w Wikimedia Commons]]"
	},
	{
		project = "plwikinews",
		icon = "wikinews",
		format = "[[n:%s|Wiadomości w Wikinews]]"
	},
	{
		project = "plwikiquote",
		icon = "wikicytaty",
		format = "[[q:%s|Teksty w Wikicytatach]]"
	},
	{
		project = "plwikisource",
		icon = "wikiźródła",
		format = "[[s:%s|Teksty w Wikiźródłach]]"
	},
	{
		project = "specieswiki",
		icon = "wikispecies",
		format = "[[wikispecies:%s|Systematyka w Wikispecies]]"
	},
	{
		project = "plwikivoyage",
		icon = "wikipodróże",
		format = "[[voy:%s|Informacje w Wikipodróżach]]"
	},
	{
		project = "plwikibooks",
		icon = "wikibooks",
		format = "[[b:%s|Książki w Wikibooks]]"
	},
}

local function ComparePropertyOrder(p1, p2, propsInfo)
	local i1 = propsInfo[p1.p]
	local i2 = propsInfo[p2.p]
	if i1 and not i2 then
		return true
	elseif not i1 and i2 then
		return false
	elseif i1 and i2 then
		return i1.index < i2.index
	else
		local n1 = tonumber(string.match(p1.p, "^[Pp](%d+)$"))
		local n2 = tonumber(string.match(p2.p, "^[Pp](%d+)$"))
		return n1 < n2
	end
end

local function escapeUrl(url)
	local pattern = "[ '%[%]|{}<>]"
	local replacements = {
		[" "] = "&#32;",
		["'"] = "&#39;",
		["["] = "&#91;",
		["]"] = "&#93;",
		["|"] = "&#124;",
		["{"] = "&#123;",
		["}"] = "&#125;",
		["<"] = "&#60;",
		[">"] = "&#62;",
	}
	local result, count = string.gsub(url, pattern, replacements)
	return result
end

local function fixUrlLinks(text)
	local result, count = string.gsub(text, "https?:%S+", escapeUrl)
	return result
end

local function selectQualifiers(property, qualifiers)
	local result = {}
	if property.qualifiers and qualifiers then
		for _, q in ipairs(qualifiers) do
			if property.qualifiers[q] then
				for _, v in ipairs(property.qualifiers[q]) do
					table.insert(result, v)
				end
			end
		end
	end
	
	if #result > 0 then
		return result
	end
end

local function formatQualifiers(qualifiers)
	if not qualifiers or (#qualifiers == 0) then
		return ""
	end
	
	local result = {}
	for _, q in ipairs(qualifiers) do
		local processor = moduleData.processor[q.property]
			or moduleData.processor[string.lower(q.property)]
			or moduleData.processor[2][q.datatype]
			or moduleData.processor[1]
	
		local module = require(processor)
		local s
		if module.scope == "snak" then
			s = module.format(q, {})
		elseif module.scope == "prop" then
			s = module.format( {mainsnak=q}, {})
		elseif module.scope == "props" then
			s = module.format( {{mainsnak=q}}, {})
		end
		
		if s and (#s > 0) then
			table.insert(result, s)
		end
	end
	
	if #result > 0 then
		return " ("..table.concat(result, ", ")..")"
	end
	
	return ""
end

local runners = {
 
	["snak"] = function (processor, properties, options)
		local result = {}
 
		for i, p in ipairs(properties) do
			if (p.type == "statement") and p.mainsnak then
				local s = processor.format(p.mainsnak, options)
				if s and (#s > 0) then
					table.insert(result, s..formatQualifiers(selectQualifiers(p, options.qualifiers)))
				end
			end
		end
 
		return listToText(result, options)
	end,
 
	["prop"] = function (processor, properties, options)
		local result = {}
 
		for i, p in ipairs(properties) do
			if (p.type == "statement") and p.mainsnak then
				local s = processor.format(p, options)
				if s and (#s > 0) then
					table.insert(result, s..formatQualifiers(selectQualifiers(p, options.qualifiers)))
				end
			end
		end
 
		return listToText(result, options)
	end,
 
	["props"] = function (processor, properties, options)
		return processor.format(properties, options)
	end,
}

local function run(options, pid, properties)

	local processor = options.procesor
		or moduleData.processor[pid]
		or moduleData.processor[2][properties[1] and properties[1].datatype or false]
		or moduleData.processor[1]

	local module = require(processor)
	local runner = runners[module.scope]
	if runner then
		return runner(module, properties, options)
	end
end


return {

Infobar = function(frame)
	local entity = mw.wikibase.getEntity(frame.args.id)
	if not entity then
		return
	end
	
	local properties = entity:getProperties()
	if not properties or (#properties == 0) then
		return
	end
	
	local propsInfo, groups = Index()
	
	comparePropertyOrder = function(p1, p2)
		return ComparePropertyOrder(p1, p2, propsInfo)
	end

	local defaultOptions = {
		separator = moduleData.defaultSeparator,
		lastSeparator = moduleData.defaultSeparator ,
		linkCoordinates = false,
		linkDate = false,
		linkItem = moduleData.defaultLinkItem,
		separatorBefore = "",
		separatorAfter = "",
	}
	
	local nameID = "Identyfikator "
	local externals = {}
	local lang = mw.getContentLanguage()
	for _, k in ipairs(properties) do
		local v = entity:getBestStatements(k)
		local label = mw.wikibase.getLabel(k)
		if label and (#label > 0) and v and (#v > 0) then
			if (#label > #nameID) and (string.sub(lang:ucfirst(label), 1, #nameID) == nameID) then
				label = string.sub(label, #nameID + 1)
			end
			
			if v[1].mainsnak.datatype == "external-id" then
				local value = run(defaultOptions, k, v)
				if value and (#value > 0) then
					table.insert(externals, { p=k, label=label, value=value})
				end
			end
		end
	end
	
	if #externals <= 0 then
		return
	end
	
	local infobar = mw.html.create("div")
		:addClass("catlinks")
		:addClass("testbox")
		:addClass("wdbar")
		:wikitext("'''Identyfikator:'''")
	for _, v in ipairs(externals) do
		infobar:wikitext("\n* ", v.label, ": ", v.value)
	end
	
	return infobar:allDone()
end,

Infobox = function(frame)
	local entity = mw.wikibase.getEntity(frame.args.id)
	if not entity then
		return
	end
	
	local properties = entity:getProperties()
	if not properties or (#properties == 0) then
		return
	end
	
	local caption = mw.wikibase.getLabelByLang(entity.id, "pl")
	if not caption or (#caption <= 0) then
		return
	end
	
	local ignored = Ignored()
	local propsInfo, groups = Index()
	
	comparePropertyOrder = function(p1, p2)
		return ComparePropertyOrder(p1, p2, propsInfo)
	end
	
	local image = false
	local data = {
		[0] = {},
		[1] = {},
		[2] = {},
	}
	local images = {}
	local other = {}
	local sisters = {}

	local defaultOptions = {
		separator = moduleData.defaultSeparator,
		lastSeparator = moduleData.defaultSeparator,
		linkCoordinates = moduleData.defaultLinkCoordinates,
		linkDate = moduleData.defaultLinkDate,
		linkItem = moduleData.defaultLinkItem,
		separatorBefore = "",
		separatorAfter = "",
	}
	local hasData = false
	local lang = mw.getContentLanguage()
	for _, k in ipairs(properties) do
		local v = entity:getBestStatements(k)
		local label = mw.wikibase.getLabel(k)
		if not ignored[k] and label and (#label > 0) and v and (#v > 0) then
			local info = defaultOptions
			local datatype = v[1].mainsnak.datatype
			local buffer = false
			if datatype == "commonsMedia" then
				local snak = v[1].mainsnak
				if snak.datavalue and (snak.datavalue.type == "string") then
					local commonMedia = snak.datavalue.value
					if commonMedia then
						mw.logObject(commonMedia, "image "..k)
						local name, ext = string.match(commonMedia, "^(.-)%.([^%.]+)$")
						if name and ext and imageExtensions[ext] then
							local info = propsInfo[k] or {}
							local desc
							if info.opis then
								local pp = entity:getBestStatements(info.opis)
								if pp then
									desc = run(defaultOptions, info.opis, pp)
								end
							end
							
							if not desc then
								desc = require("Moduł:Wikidane/format/qualifiers").TEXT1(v[1], nil, "P2096")
									or info[2]
							end
							
							if not desc and (k ~= "P18") then
								desc = lang:ucfirst(label)
							end
							
							if propsInfo[k] or desc then
								table.insert(images, { p=k, alt=lang:ucfirst(label), file=commonMedia, desc=desc })
							end
						end
					end
				end
			elseif datatype == "external-id" then
				buffer = nil
			else
				info = propsInfo[k] or defaultOptions
				if info.group and groups[info.group] then
					buffer = data[info.group] or {}
					data[info.group] = buffer
				else
					buffer = other
				end
			end
			
			if buffer then
				local value = run(info, k, v)
				if value and (#value > 0) then
					table.insert(buffer, { p=k, label=lang:ucfirst(label), value=value})
					hasData = (info.group ~= 0) or hasData
				end
			end
		end
	end
	
	for _, project in ipairs(projects) do
		mw.logObject(project, "project")
		local link = entity.sitelinks[project.project] and entity.sitelinks[project.project].title
		mw.logObject(project, "link")
		if link then
			local text = mw.ustring.format(project.format, link)
			local icon = "[[Plik:"..require("Module:Ikona").plik(project.icon).."|20px|link=|alt=]]"
			table.insert(sisters, icon..text)
		end
	end
	
	if (#images == 0) and not hasData then
		return
	end

	local infobox = mw.html.create()
	infobox
		:wikitext('{| class="infobox testbox wdbox"')
		:wikitext('\n|+ '):wikitext(caption)

	if #data[0] > 0 then
		table.sort(data[0], comparePropertyOrder)
		for i, v in ipairs(data[0]) do
			infobox
				:tag("br"):done()
				:tag("small"):wikitext(v.value)
		end
	end

	local separator = false
	if #data[1] > 0 then
		table.sort(data[1], comparePropertyOrder)
		for i, v in ipairs(data[1]) do
			infobox
				:wikitext("\n|-")
				:wikitext('\n!'):wikitext(v.label)
				:wikitext('\n|'):wikitext(v.value)
		end
		
		separator = true
	end

	if #images > 0 then
		table.sort(images, comparePropertyOrder)
		mw.logObject(images, "images")
		local image = images[1]
		if (image.p == "P18") or (image.p == "P154") or (image.p == "P2910") then
			table.remove(images, 1)
			infobox
				:wikitext(separator and '\n|- class="iboxs"' or '\n|-')
				:wikitext('\n|colspan="2" style="text-align:center;background:white;"|[[Plik:',image.file,'|240x240px|alt=',image.alt,']]')
			if image.desc then
				infobox:tag("br")
				infobox:wikitext(image.desc)
			end
			separator = false
		end
		
		if #images > 0 then
			infobox
				:wikitext(separator and '\n|- class="iboxs"' or '\n|-')
				:wikitext('\n|colspan="2" padding="0"|')
				:wikitext('\n{| class="ibox2"')
			while #images > 1 do
				local image1 = images[1]
				local image2 = images[2]
				table.remove(images, 1)
				table.remove(images, 1)
				infobox
					:wikitext('\n|-')
					:wikitext('\n|[[Plik:',image1.file,'|120x120px|alt=',image1.alt,']]')
				if image1.desc then
					infobox:tag("br")
					infobox:wikitext(image1.desc)
				end
				infobox
					:wikitext('\n|[[Plik:',image2.file,'|120x120px|alt=',image2.alt,']]')
				if image2.desc then
					infobox:tag("br")
					infobox:wikitext(image2.desc)
				end
			end
			
			if #images > 0 then
				local image = images[1]
				infobox
					:wikitext('\n|-')
					:wikitext('\n|colspan="2"|[[Plik:',image.file,'|120x120px|alt=',image.alt,']]')
				if image.desc then
					infobox:tag("br")
					infobox:wikitext(image.desc)
				end
			end
			
			infobox
				:wikitext('\n|-')
				:wikitext('\n|}')
		end
		
		separator = true
	end

	if #data[2] > 0 then
		table.sort(data[2], comparePropertyOrder)
		for i, v in ipairs(data[2]) do
			infobox
				:wikitext(separator and '\n|- class="iboxs"' or '\n|-')
				:wikitext('\n!'):wikitext(v.label)
				:wikitext('\n|'):wikitext(v.value)
			separator = false
		end
		
		separator = true
	end

	local i = 3
	while groups[i] do
		if data[i] and (#data[i] > 0) then
			table.sort(data[i], comparePropertyOrder)
			local header = mw.text.trim(tostring(groups[i]))
			if #header > 0 then
				infobox
					:wikitext('\n|-')
					:wikitext('\n!colspan="2"| ', header)
				separator = false
			end
			
			for i, v in ipairs(data[i]) do
				local pInfo = propsInfo[v.p]
				if pInfo[2] == "fragment" then
					infobox
						:wikitext('\n', v.value)
					separator = true
				elseif pInfo[2] == "blok" then
					infobox
						:wikitext('\n|-')
						:wikitext('\n!colspan="2"| ', v.label)
						:wikitext('\n|-')
						:wikitext('\n|colspan="2"| ', v.value)
					separator = true
				else
					infobox
						:wikitext(separator and '\n|- class="iboxs"' or '\n|-')
						:wikitext('\n! '):wikitext(v.label)
						:wikitext('\n| '):wikitext(v.value)
					separator = false
				end
			end
			
			separator = true
		end
		
		i = i + 1
	end

	if #other > 0 then
		table.sort(other, comparePropertyOrder)
		infobox
			:wikitext('\n|-')
			:wikitext('\n!colspan="2"| ❧')
		separator = false
		for i, v in ipairs(other) do
			infobox
				:wikitext(separator and '\n|- class="iboxs"' or '\n|-')
				:wikitext('\n! '):wikitext(v.label)
				:wikitext('\n| '):wikitext(v.value)
			separator = false
		end
		
		separator = true
	end

	if #sisters > 0 then
		infobox
			:wikitext("\n|-")
			:wikitext('\n!colspan="2"|'):wikitext("W projektach Wikimedia")
		for i, v in ipairs(sisters) do
			infobox
				:wikitext('\n|-class="iboxsisterlink"')
				:wikitext('\n|colspan="2"| '):wikitext(v)
		end
	end
	
	infobox
		:wikitext('\n|-')
		:wikitext("\n|}")

	-- kategorie psują listę
	local result = tostring(infobox)
	local count
	local pattern = mw.ustring.gsub( moduleData.itemWithoutLabelCat, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" )
	result, count = mw.ustring.gsub(result, pattern, "")
	if count > 0 then
		result = result .. moduleData.itemWithoutLabelCat
	end
	
	return result
end,

}