Moduł:Sprawdź

Z Wikibooks, biblioteki wolnych podręczników.
Przejdź do nawigacji Przejdź do wyszukiwania
Template-info.png Dokumentacja modułu [zobacz] [edytuj] [historia] [odśwież]

Ten moduł zapewnia platformę programistyczną dla tworzenia szablonów budujących przypadki testowe szablonów Wikibooksa. Przypadki testowe mogą być tworzone ręcznie, aczkolwiek te tworzone za pomocą szablonów opartych na module Lua, takim jak niniejszy moduł, mają taką zaletę, że argumenty szablonu muszą być wprowadzone jedynie jednokrotnie, co zmniejsza nakład pracy konieczny do tworzenia testów, a także zmniejsza ryzyko występowania błędów w danych wejściowych.

Porównaj[edytuj]

Ta funkcja jest obecnie wykorzystywana przez szablon {{Przypadek testowy}}.

Parametry[edytuj]

Funkcja do wykrywania wywołań szablonów z nierozpoznanymi, pustymi lub przestarzałymi parametrami. Należy ją wywołać ze wszystkimi możliwymi parametrami jakie przyjmuje szablon podlegający sprawdzaniu.

Opis parametrów
pole opis status uwagi
bez nazwy konfiguracja działania wymagany klasa lub klasa odstęp suffix
inny deklaracja pola obsługiwanego w szablonie opcjonalny txt, num, num?, uri, uri?, old, ^…$ lub pusty
Konfiguracja
  • klasa – ciąg znaków bez spacji umieszczany jako wartość atrybutu class w tagu <span> z wygenerowanym raportem
  • odstęp – ciąg znaków odstępu oddzielający pozostałą treść konfiguracji, jeśli zawiera znak nowej linii to przed wygenerowanym raportem jest również umieszczany znak nowej linii
  • suffix – treść dołączana po wygenerowanym raporcie, zwykle deklaracja technicznej kategorii
Sprawdzanie parametrów
  • pusty – parametr jest opcjonalny, jest to najczęściej stosowany sposób użycia
  • txt – oczekiwany jest dowolna niepusta wartość pola
  • num – sprawdzanie czy przekazana wartość jest liczbą
  • num? – sprawdzanie czy przekazana wartość jest pusta lub jest liczbą
  • uri – sprawdzanie czy przekazana wartość jest linkiem obsługiwanym przez MediaWiki
  • uri? – sprawdzanie czy przekazana wartość jest pusta lub jest linkiem
  • old – informuje, że przekazywany parametr jest przestarzały
  • ^…$ – tekst rozpoczynający się znakiem ^ i zakończony na $ w całości traktowany jest jako wyrażenie regularne Lua wskazującego prawidłowy parametr
Przykład
{{#invoke:Sprawdź|Parametry|=problemy-w-szablonie [[Kategoria:Błędy wywołań w szablonie]]|argument1=|argument2=}}

odn[edytuj]

Funkcja sprawdzająca prawidłowość parametrów w {{odn}}.
local function checkUri(uri)
	local urilen = #uri
	for _,v in ipairs(mw.loadData("Moduł:Cytuj/dane").supportedUriSchemas) do
		if (#v < urilen) and (string.lower(string.sub(uri,1, #v)) == v) then
			return not string.match(uri, '%s')
		end
	end
end
return {
	["Porównaj"] = function(frame)
		local config = frame:getParent().args[""] or ""
		local options = mw.text.split(config, "|")
		local templateName = mw.text.trim(options[1])
		if #templateName == 0 then
			local title = mw.title.getCurrentTitle()
			if title.namespace == 10 then
				templateName = mw.ustring.match(title.text, "^(.-)/opis")
					or mw.ustring.match(title.text, "^(.-)/test")
					or mw.ustring.match(title.text, "^(.-)/brudnopis")
					or title.text
			end
			if #templateName == 0 then
				mw.log("brak nazwy szablonu")
				return
			end
		end
	
		local templateTitle = mw.title.new(templateName, 10)
		if templateTitle.id == 0 then
			mw.log("szablon '"..templateName.."' nie istnieje")
			return
		end
		
		local sandboxName = templateName.."/brudnopis"
		local sandboxTitle = mw.title.new(sandboxName, 10)
		if sandboxTitle.id == 0 then
			mw.log("brudnopis '"..sandboxName.."' nie istnieje")
			return
		end
		
		local i = 2
		local showparams = true
		local showinfo = true
		local vertical = false
		while i <= #options do
			local option = mw.text.trim(options[i])
			if option == "bez wikikodu" then
				showparams = false
			elseif option == "bez opisu" then
				showinfo = false
			elseif option == "pionowo" then
				vertical = true
			end
			
			i = i + 1
		end
	
		local templateParams = {}
		local params = {}
		for k, v in pairs(frame:getParent().args) do
			if k ~= "" then
				templateParams[k] = v
				table.insert(params, k)
			end
		end
	
		local result = {}
		table.insert(result, '<table style="width: 100%;">')
		
		if showparams and (#params > 0) then
			local compare = function(a, b)
				-- return a < b
				if (type(a) == "number") and (type(b) == "number") then
					return a < b
				end
				
				if (type(a) == "string") and (type(b) == "string") then
					return a < b
				end
				
				if (type(a) == "number") and (type(b) == "string") then
					return true
				end
				
				return false
			end
			
			table.sort(params, compare)
			table.insert(result, "<caption><code>&#x7B;&#x7B;")
			table.insert(result, templateName)
			for i, k in ipairs(params) do
				table.insert(result, " &#x7C; ")
				local p = mw.text.nowiki(tostring(k))
				local v = mw.text.nowiki(templateParams[k])
				table.insert(result, p)
				table.insert(result, " = ")
				table.insert(result, v)
			end
			table.insert(result, "&#x7D;&#x7D;</code></caption>")
		end
		
		local templateResult = frame:expandTemplate{ title=templateName, args=templateParams}
		local sandboxResult = frame:expandTemplate{ title=sandboxName, args=templateParams}
		
		if templateResult and string.match(templateResult, "^{|") then
			templateResult = "\n"..templateResult
		end
		if sandboxResult and string.match(sandboxResult, "^{|") then
			sandboxResult = "\n"..sandboxResult
		end
		
		if vertical and showinfo then
			table.insert(result, '<tr><th style="width: 15em">[[Szablon:')
			table.insert(result, templateName)
			table.insert(result, '|Szablon]]</th><td>')
			table.insert(result, templateResult)
			table.insert(result, '</td></tr><tr><th>[[Szablon:')
			table.insert(result, sandboxName)
			table.insert(result, '|Brudnopis szablonu]]</th><td>')
			table.insert(result, sandboxResult)
			table.insert(result, '</td></tr>')
		elseif vertical then
			table.insert(result, '<tr><td>')
			table.insert(result, templateResult)
			table.insert(result, '</td></tr><tr><td>')
			table.insert(result, sandboxResult)
			table.insert(result, '</td></tr>')
		else
			if showinfo then
				table.insert(result, '<tr><th style="width: 50%;">[[Szablon:')
				table.insert(result, templateName)
				table.insert(result, '|Szablon]]</th><th style="width: 50%;">[[Szablon:')
				table.insert(result, sandboxName)
				table.insert(result, '|Brudnopis szablonu]]</th></tr>')
			end
			
			table.insert(result, '<tr style="vertical-align: top;"><td>')
			table.insert(result, templateResult)
			table.insert(result, '</td><td>')
			table.insert(result, sandboxResult)
			table.insert(result, '</td></tr>')
		end
		
		table.insert(result, "</table>")
		return table.concat(result)
	end,

	["Parametry"] = function(frame)
		local unknown = {}
		local invalid = {}
		local deprecated = {}
		local pf=frame:getParent();
		local templateName;
		local config = frame.args[""]
		local class, space, category = string.match(config or "", "^%s*(%S+)(%s+)(.-)%s*$")
		local nl = space and string.match(space, "\n") or ""
		class = class or config

		local function argName(arg)
			return type(arg) ~= "string" and tostring(arg) or ('"'..arg..'"')
		end
		
		local ramka_modul=require("Module:Ramka");
		
		local parametry_modul=require("Module:Parametry");
		
		local tabelka1=ramka_modul.RozpakujArgumenty(frame.args["bez argumentów szablonu"]);
		local tabelka2=ramka_modul.RozpakujArgumenty(pf.args["bez argumentów szablonu"]);
		
		local tabelka_bez_argumentow=parametry_modul["ŁączDwieTabele"](tabelka1,tabelka2)

		local required = {}
		
		local tabelka_argumentow_typ_jednostki={
			["nazwa przestrzeni nazw"]="",
			["nazwa jednostki"]="txt",
			["typ jednostki"]="txt",
			["bez argumentów szablonu"]="txt",
		};
		tabelka_bez_argumentow=parametry_modul["UsuńElementyTabeli"](tabelka_bez_argumentow,tabelka_argumentow_typ_jednostki);
		
		for k, v in pairs(frame.args) do
			if((not tabelka_argumentow_typ_jednostki[k])and(not tabelka_bez_argumentow[k]))then
				if mw.ustring.match(v, "!$") then
					required[k] = true
				end
			end;
		end
		
		local emptyArg = false
		local tabelka_parametrow_rodzica={};
		local parametry_rodzica=parametry_modul.CzyTak(pf.args["potomek"])and pf.args["parametry rodzica"];
	    if(parametry_rodzica)then
	        tabelka_parametrow_rodzica=ramka_modul.RozpakujParametry(parametry_rodzica);
	        templateName=pf.args["nazwa szablonu rodzica"] or parametry_modul.NazwaSzablonu(pf:getTitle());
	    else
	    	tabelka_parametrow_rodzica=pf.args;
	    	templateName=parametry_modul.NazwaSzablonu(pf:getTitle());
	    end;
	    
		for k, v in pairs(tabelka_parametrow_rodzica) do
			required[k] = false
			local kind=(not tabelka_bez_argumentow[k])and (tabelka_argumentow_typ_jednostki[k] or frame.args[k]);
			if k == "" then
				emptyArg = v
			elseif not kind then
				table.insert(unknown, argName(k))
			elseif (kind == "num") or (kind == "num!") then
				local n = tonumber(v)
				if not n then table.insert(invalid, argName(k)) end
			elseif kind == "num?" then
				local n = (#v == 0) or tonumber(v)
				if not n then table.insert(invalid, argName(k)) end
			elseif (kind == "uri") or (kind == "uri!") then
				local u = checkUri(v)
				if not u then table.insert(invalid, argName(k)) end
			elseif kind == "uri?" then
				local u = (#v == 0) or checkUri(v)
				if not u then table.insert(invalid, argName(k)) end	
			elseif (kind == "txt") or (kind == "txt!") then
				if #v == 0 then table.insert(invalid, argName(k)) end
			elseif kind == "old" then
				table.insert(deprecated, argName(k))
			else
				local pattern = string.match(kind,"^(^.-$)!?$")
				if pattern and not mw.ustring.match(v, pattern) then
					table.insert(invalid, argName(k))
				end
			end
		end;
		
		local missing = {}
		for k, v in pairs(required) do
			if v then
				table.insert(missing, k)
			end
		end

		if (#missing == 0) and (#unknown == 0) and (#invalid == 0) and (#deprecated == 0) then
			return nil
		end
 		local result = mw.html.create("span")
		result:addClass("problemy");
 		
 		local frame2=pf:newChild{args = {["obsługiwane jednostki jako nieopisowe strony"]="tak"}}
	    local typ_jednostki=require("Module:Pudełko")["Typ jednostki 2"](frame2)
	    local typ;
	    if(typ_jednostki=="artykuł")then
	    	typ="(artykuły)";
	    elseif(typ_jednostki=="artykuł dla dzieci")then
	    	typ="(artykuły dla dzieci)";
	    elseif(typ_jednostki=="strona użytkownika")then
	    	typ="(strony użytkowników)";
	    elseif(typ_jednostki=="strona brudnopisu projektu")then
	    	typ="(strony brudnopisu projektu)";
	    else
	    	typ="";
	    end;
	 	if typ_jednostki=="artykuł" or typ_jednostki=="artykuł dla dzieci" or typ_jednostki=="strona użytkownika" or typ_jednostki=="strona brudnopisu projektu" then
 			result:css("display", "none")
 		else
 			result:css("color", "red")
 		end
 		local message=mw.html.create()
		if emptyArg then
			message:wikitext("|=", emptyArg, "| ")
		end
		
		if #missing > 0 then
			message:wikitext("Brakujące pola: ", mw.text.listToText(missing), ". ")
		end

		if #invalid > 0 then
			message:wikitext("Nieprawidłowe pola: ", mw.text.listToText(invalid), ". ")
		end

		if #unknown > 0 then
			message:wikitext("Nieznane pola: ", mw.text.listToText(unknown), ". ")
		end

		if #deprecated > 0 then
			message:wikitext("Przestarzałe pola: ", mw.text.listToText(deprecated), ". ")
		end
         
        local warning = mw.html.create('span')
        warning:css('color','red');
        warning:addClass("problemy");
        
        if(templateName)then
        	mw.logObject(templateName, "templateName")
        	local dwukropek=mw.ustring.match(templateName,"^%s*:");
        	local nazwy_modul=require("Module:Nazwy");
			local nazwa_przestrzeni_strony=nazwy_modul["NAZWAPRZESTRZENIFUN"](templateName);
			local wywolanie;local wywolanie2;
			if dwukropek or nazwa_przestrzeni_strony~="" then
                wywolanie=parametry_modul["PokażSzablon"](templateName,tabelka_parametrow_rodzica);
                wywolanie2="{{"..templateName.."}}";
				if(parametry_modul.CzyTak(category))then 
					  templateName=mw.ustring.gsub(templateName,"^%s*:","");
					  category=mw.ustring.format(category,templateName,typ);
					  category=pf:preprocess(category);
					  class=mw.ustring.format(class,mw.ustring.gsub(templateName,"%s+","-"));
			    end;
			else
				wywolanie=parametry_modul["PokażSzablon"](templateName,tabelka_parametrow_rodzica);
                wywolanie2="{{"..templateName.."}}";
				if(parametry_modul.CzyTak(category))then 
					local bez_pierwszej_litery=mw.ustring.match(templateName,"^.(.*)");
					local czy_jest_wielka_litera=mw.ustring.match(bez_pierwszej_litery,"%u");
					local szablon;
					if(not czy_jest_wielka_litera)then szablon=mw.ustring.lower(templateName);else szablon=templateName;end;
					category=mw.ustring.format(category,szablon,typ);
					category=pf:preprocess(category);
					class=mw.ustring.format(class,mw.ustring.gsub(szablon,"%s+","-"));
				end;
			end
			warning:wikitext("Wywołanie "..wywolanie..": ")
 			result:wikitext("Szablon "..wywolanie2..": ");
        end;
        message = tostring(message)
 		warning:wikitext(message);
        mw.addWarning(tostring(warning));
		 
		if class then
		    result:addClass(class)
		end
        
        result:wikitext(message);
         
		if category then
			result:wikitext(category)
		end

		return nl..tostring(result)
	end,

	["odn"] = function(frame)
		local pf = frame:getParent()
		local i = 1
		local problems = false
		local yeardetected = false
		while true do
			local arg = pf.args[i]
			if not arg then
				problems = i == 1 and "brak argumentów" or false
				break
			end
	 
			if (i > 5) or yeardetected then
				problems = "za dużo argumentów pozycyjnych"
				break
			end
	 
			if #arg == 0 then
				problems = "pusty argument"
				break
			end
	 
			if arg ~= mw.text.trim(arg) then
				problems = "nieoczekiwane odstępy na początku lub końcu argumentu"
				break
			end
	 
			if string.match(arg, "^%d+%l?$") then
				yeardetected = true
				if i == 1 then
					problems = "rok musi być ostatnim parametrem po nazwiskach autorów"
					break
				end
			elseif string.match(arg, "^s[%-%.:]%s*%d+") then
				problems = "prawdopodobnie nieprawidłowo podany numer strony"
				break
			elseif string.match(arg, "%s%s") then
				problems = "podwójne odstępy"
				break
			elseif mw.ustring.match(arg, "^%a+%d") then
				if not mw.ustring.match(arg, "^[%u%d]+$") then
					problems = "prawdopodobnie sklejone argumenty (brak pionowej kreski)"
					break
				end
			elseif mw.ustring.match(arg, "^OdeB ") then
				-- [[Ordre de Bataille]]
			elseif mw.ustring.match(arg, "^%u%l+%u") then
				local justification = {
					["De"] = true,
					["Del"] = true,
					["Di"] = true,
					["Le"] = true,
					["Mac"] = true,
					["Mc"] = true,
					["Te"] = true, -- TeSelle
					["Sar"] = true, -- SarDesai
					["Van"] = true, -- VanBuren
					["La"] = true, -- LaSalle
				}
				if not justification[mw.ustring.match(arg, "^%u%l+")] then
					problems = "prawdopodobnie sklejone argumenty (brak pionowej kreski)"
					break
				end
			end
	 
			i = i + 1
		end
	 
		if not problems then
			local odn = pf.args.odn
			if odn and ((#odn ~= 1) or (odn < "a") or (odn > "z")) then
				problems = "nieoczekiwany parametr odn"
			end
		end
	 
	 	if not problems then
	 		local s = pf.args.s
	 		if s and string.match(s, "&[a-z]+;") then
	 			problems = "użyto encji HTML w numerze strony"
	 		end
	 	end
	 
		if not problems then
			if pf.args.strona or pf.args.ss or pf.args.strony or pf.args.p or pf.args.page or pf.args.pp or pf.args.pages then
				problems = "przestarzały parametr z numerem strony"
			end
		end
	
	 	if not problems then
	 		return nil
	 	end
	 	
	 	local result = mw.html.create("span"):addClass("problemy-w-odn")
	    local frame2=pf:newChild{args = {["obsługiwane jednostki jako nieopisowe strony"]="tak"}}
	    local typ_jednostki=require("Module:Pudełko")["Typ jednostki 2"](frame2)
	    if typ_jednostki=="artykuł" or typ_jednostki=="artykuł dla dzieci" or typ_jednostki=="strona użytkownika" or typ_jednostki=="strona brudnopisu projektu" then
	 		result:css("display", "none")
	 		result:wikitext("[[Kategoria:Szablon odn do sprawdzenia]]")
	 	else
	 		result:css("color", "red")
	 	end
	 	result:wikitext("ODN: ", problems)
	 	return tostring(result)
	end,
	
	["Wikidane"] = function(frame)
		local property = frame.args.cecha
		local field = frame.args.pole
		local value = frame.args[1]
		if not property or not field then
			return
		end
		
		if not value then
			value = frame:getParent().args[field]
			if not value or (#value == 0) then
				return
			end
		end
		
		local entity = mw.wikibase.getEntity()
		if not entity or not entity.claims or not entity.claims[property] then
			return
		end
		
		for i, v in ipairs(entity.claims[property]) do
			if v.mainsnak.snaktype == "value" then
				if value == v.mainsnak.datavalue.value then
					return
				end
			end
		end
	
		local template = frame:getParent():getTitle()
		local infobox = mw.ustring.match(template, "^Szablon:(.- infobox)$")
		return mw.ustring.format("[[Kategoria:%s – niezgodność w Wikidanych – %s – %s]]", infobox and "Infoboksy" or "Szablony", infobox or template, field)
	end,

	["bez parametrów"] = function(frame)
		for k, v in pairs(frame:getParent().args) do
			return nil
		end
		
		return "tak"
	end,

	["pole z hostem"] = function (frame)
		local host = frame.args.host
		if host and (#host > 0) then
			for k, v in pairs(frame:getParent().args) do
				local link = string.match(v, "[hH][tT][tT][pP][sS]?://[%S]+")
				if link then
					local uri = mw.uri.new(link)
					local valid, _ = mw.uri.validate(uri)
					if valid and uri.host and (#uri.host > 0) then
						if host == uri.host then
							mw.logObject({k, link}, "cały")
							return k
						end
						
						if #host < #uri.host then
							local s1 = '.'..host
							local s2 = string.sub(uri.host, -#s1)
							if s1 == s2 then
								mw.logObject({k, link}, "fragment")
								return k
							end
						end
					end
				end
			end
		end
	end,
	
	["pola z gołymi linkami"] = function (frame)
		local result = {}
		for k, v in pairs(frame:getParent().args) do
			local link = string.match(v, "^[hH][tT][tT][pP][sS]?://[%S]+")
			if link then
				local justified = frame.args[k]
				if not justified then
					mw.logObject(v,k)
					table.insert(result, '"'..k..'"')
				end
			end
		end
		
		return mw.text.listToText(result)
	end,
	
}