Moduł:Sprawdź
Dokumentacja dla tego modułu może zostać utworzona pod nazwą Moduł:Sprawdź/opis
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
function checkImageName(name)
if not name or (#name==0) or string.match(name, "[#<>%[%]|{}]") then
return false
end
local title = mw.title.makeTitle("Plik", name)
if not title then
return false
end
local res = {
prefix = {
plik = true,
image = true,
grafika = true,
file = true,
},
extension = {
jpg = true,
jpeg = true,
jpe = true,
png = true,
svg = true,
tif = true,
tiff = true,
gif = true,
xcf = true,
pdf = true,
djvu = true,
webp = true,
},
}
local prefix = string.match(name, "^:? *([^:]+) *:")
if prefix and res.prefix[string.lower(prefix)] then
return false
end
local extension = string.match(name, "%S.*%.([^%.]+)$")
return extension and res.extension[string.lower(extension)]
end
local function findPlainHttp(text)
if text then
text = mw.ustring.gsub(text, "%[[hH][tT][tT][pP][sS]?://%S+", "_")
return string.match(text, "[hH][tT][tT][pP][sS]?://%S")
end
end
local function findFile(text)
-- schowaj wyjątek: obrazek generowany przez Szablon:Link-interwiki
text = mw.ustring.gsub(text, "%[%[Plik:Wikidata%-logo%-en%.svg|10x9px|link=:d:Q%d+|Informacje powiązane z artykułem „.-” w Wikidanych%]%]", "")
-- normalize
text = mw.ustring.gsub(text, "%s*[Pp]lik%s*:%s*", "Plik:")
text = mw.ustring.gsub(text, "%s*[Ff]ile%s*:%s*", "Plik:")
text = mw.ustring.gsub(text, "%s*[Gg]rafika%s*:%s*", "Plik:")
text = mw.ustring.gsub(text, "%s*[Ii]mage%s*:%s*", "Plik:")
return mw.ustring.match(text, "%[%[Plik:([^%[%]|]+)[|%]]")
end
-- Lista of template params for wikicode. Like this:
-- | grafika = | data śmierci = | www =
local function listToTplParams(strArray)
return "| " .. table.concat(strArray, " = | ") .. " =";
end
local function showTemplate(templateName, args)
local result = {}
local flags = {}
table.insert(result, mw.text.nowiki("{{"))
if mw.isSubsting() then
table.insert(result, "subst:")
end
local title = mw.title.new(templateName)
if title.namespace ~= 10 then
table.insert(result, title.nsText)
table.insert(result, ":")
end
table.insert(result, title.text)
if args then
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
end
table.insert(result, mw.text.nowiki("}}"))
return table.concat(result)
end
local function infoboxCatTitle(infobox, class)
local catTitle = mw.title.makeTitle(14, "Infoboksy – "..class.." – "..infobox)
if not catTitle.exists then
mw.logObject(catTitle, "Dedykowana kategoria błędów w infoboksie nie istnieje")
catTitle = mw.title.makeTitle(14, "Infoboksy – "..class)
end
mw.logObject(catTitle, "infoboxCatTitle")
return catTitle
end
local function daysInMonth(year, month)
if month == 1 then return 31 end
if month == 2 then return ((year % 4) == 0) and 29 or 28 end
if month == 3 then return 31 end
if month == 4 then return 30 end
if month == 5 then return 31 end
if month == 6 then return 30 end
if month == 7 then return 31 end
if month == 8 then return 31 end
if month == 9 then return 30 end
if month == 10 then return 31 end
if month == 11 then return 30 end
if month == 12 then return 31 end
return 0
end
local function isDate20YYMMDD(date)
local y, m, d = mw.ustring.match(date, "^(20[0-9][0-9])%-([01][0-9])%-([0123][0-9])$")
local year = tonumber(y)
local month = tonumber(m)
local day = tonumber(d)
local result = year and month and day
and (year >= 2001)
and (month >= 1) and (month <= 12)
and (day >= 1) and (day <= daysInMonth(year, month))
if not result then
mw.logObject({date=date,year=year,month=month,day=day}, "isDate20YYMMDD")
end
return result
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>{{")
table.insert(result, templateName)
for i, k in ipairs(params) do
table.insert(result, " | ")
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, "}}</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)
if mw.title.getCurrentTitle().contentModel ~= "wikitext" then
mw.logObject(mw.title.getCurrentTitle().contentModel, "mw.title.getCurrentTitle().contentModel")
return -- to nie ma sensu w takim wypadku
end
local unknown = {}
local invalid = {}
local deprecated = {}
local nakedurl = {}
local files = {}
local templateName = frame:getParent():getTitle()
local infobox = mw.ustring.match(templateName, "^Szablon:(.- infobox)$")
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 required = {}
for k, v in pairs(frame.args) do
if mw.ustring.match(v, "!$") then
required[k] = true
if infobox then
-- odróżniaj pola sugerowane w infoboksach, które mogą być puste
if v == "!" or mw.ustring.match(v, "%?!$") then
required[k] = false
else
local pattern = string.match(v,"^(^.-$)!?$")
if pattern and mw.ustring.match("", pattern) then
required[k] = false
end
end
end
end
end
local emptyArg = false
for k, v in pairs(frame:getParent().args) do
required[k] = nil
local kind = frame.args[k]
if kind == "" or kind == "!" then
kind = "text?"
end
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?") or (kind == "num?!") then
local n = (#v == 0) or tonumber(v)
if not n then table.insert(invalid, argName(k)) end
elseif (kind == "grafika") or (kind == "grafika!") then
if findPlainHttp(v) then
table.insert(nakedurl, argName(k))
else
local g = checkImageName(v)
if not g then table.insert(invalid, argName(k)) end
end
elseif (kind == "grafika?") or (kind == "grafika?!") then
if findPlainHttp(v) then
table.insert(nakedurl, argName(k))
else
local g = (#v == 0) or checkImageName(v)
if not g then table.insert(invalid, argName(k)) end
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?") or (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))
elseif checkUri(v) then
table.insert(nakedurl, argName(k))
elseif findPlainHttp(v) then
table.insert(nakedurl, argName(k))
end
elseif (kind == "text") or (kind == "text!") or (kind == "text?") then
if ((kind ~= "text?") and (#v == 0)) then
table.insert(invalid, argName(k))
elseif findFile(v) then
table.insert(files, argName(k))
elseif checkUri(v) then
table.insert(nakedurl, argName(k))
elseif findPlainHttp(v) then
table.insert(nakedurl, argName(k))
end
elseif kind == "old" then
table.insert(deprecated, argName(k))
elseif kind == "uri*" then -- specjalny przpadek dla pola 'url' w [[Szablon:Cytuj]]
local u = checkUri(v) or checkUri(mw.text.unstripNoWiki(v))
if not u then table.insert(invalid, argName(k)) end
else
local pattern = string.match(kind,"^(^.-$)!?$")
if pattern and not mw.ustring.match(v, pattern) then
table.insert(invalid, argName(k))
elseif (#v > 0) and checkUri(v) then
table.insert(nakedurl, argName(k))
elseif findPlainHttp(v) then
table.insert(nakedurl, argName(k))
end
end
end
local missing = {}
local suggested = {}
mw.logObject(required, "required")
for k, v in pairs(required) do
table.insert(v and missing or suggested, k)
end
if (#missing == 0) and (#suggested == 0) and (#unknown == 0) and (#invalid == 0) and (#deprecated == 0) and (#nakedurl == 0) and (#files == 0) then
return nil
end
local errorClasses = 0
-- generate messages for each category of problems
local messages = {}
if #invalid > 0 then
errorClasses = errorClasses + 2
table.insert(messages, "Nieprawidłowe/puste pola: " .. mw.text.listToText(invalid) .. ".")
end
if (#missing > 0) or (#suggested > 0) then
errorClasses = errorClasses + 1
if (#missing > 0) then table.insert(messages, "Brakujące pola: " .. mw.text.listToText(missing) .. ".") end
if (#suggested > 0) then table.insert(messages, "Sugerowane pola (wstaw w kodzie): <code>" .. listToTplParams(suggested) .. "</code>") end
end
if #unknown > 0 then
errorClasses = errorClasses + 4
table.insert(messages, "Nieznane pola: " .. mw.text.listToText(unknown) .. ".")
end
if #deprecated > 0 then
errorClasses = errorClasses + 8
table.insert(messages, "Przestarzałe pola: " .. mw.text.listToText(deprecated) .. ".")
end
if #nakedurl > 0 then
errorClasses = errorClasses + 16
table.insert(messages, "Gołe linki: " .. mw.text.listToText(nakedurl) .. ".")
end
if #files > 0 then
errorClasses = errorClasses + 32
table.insert(messages, "Nieoczekiwana grafika: " .. mw.text.listToText(files) .. ".")
end
-- nop?
if templateName then
showTemplate(templateName, frame:getParent().args)
end
-- render messages
local message = mw.html.create()
if emptyArg then
message:wikitext("|=", emptyArg, "| ")
end
if infobox then
message:wikitext("\n* ", table.concat(messages, "\n* "))
else
message:wikitext(table.concat(messages, " "))
end
message = tostring(message)
-- result container
local result = mw.html.create(infobox and "table" or "span")
result:addClass("problemy")
:addClass(class or nil)
:attr("aria-hidden", "true")
local restext = result
if infobox then
result:addClass("infobox")
restext = result:tag("tr"):tag("td")
else
result:attr("data-nosnippet", "")
end
if templateName then
restext:wikitext(showTemplate(templateName).." ")
-- pomiń ten komunikat jeśli zabraknie tylko pól sugerowanych w infoboksie
if not infobox or (errorClasses ~= 1) or (#missing > 0) then
local warning = mw.html.create()
warning:tag("code"):wikitext(showTemplate(templateName, frame:getParent().args))
warning:wikitext(" ")
warning:tag("span"):addClass("problemy"):wikitext(message)
mw.addWarning(tostring(warning))
end
end
restext:wikitext(message)
if category then
result:wikitext(category)
end
if infobox then
if (errorClasses == 1) and (#missing <= 0) then
result:addClass("tylko-braki") -- tylko SUGEROWANE braki
end
if (#missing > 0) or (#suggested > 0) then
result:wikitext("[[Kategoria:", infoboxCatTitle(infobox, "brakujące parametry").text, "]]")
end
if mw.title.getCurrentTitle().namespace == 0 then
if #invalid > 0 then
result:wikitext("[[Kategoria:", infoboxCatTitle(infobox, "nieprawidłowe parametry").text, "]]")
end
if #unknown > 0 then
result:wikitext("[[Kategoria:", infoboxCatTitle(infobox, "nieznane parametry").text, "]]")
end
if #deprecated > 0 then
result:wikitext("[[Kategoria:", infoboxCatTitle(infobox, "przestarzałe parametry").text, "]]")
end
if #nakedurl > 0 then
result:wikitext("[[Kategoria:", infoboxCatTitle(infobox, "gołe linki").text, "]]")
end
if #files > 0 then
result:wikitext("[[Kategoria:", infoboxCatTitle(infobox, "grafika w nieodpowiednim miejscu").text, "]]")
end
end
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")
:addClass("problemy-w-odn")
if mw.title.getCurrentTitle().namespace == 0 then
result:wikitext("[[Kategoria:Szablon odn do sprawdzenia]]")
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 autorami"] = function (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,
["uri"] = function(frame)
mw.logObject(frame:getParent():getTitle(), "parent:title")
_ = mw.title.new("Moduł:Sprawdź/deprecated/uri").id
local link = frame.args["link"]
local space = frame.args["spacja"]
local check = checkUri(link)
if check then
return link
end
return (space and (check ~= nil)) and link or ""
end,
--[[Sprawdzanie url do szablonów
Wykorzystanie:
{{#invoke:Sprawdź|url|{{{www|}}}|[{{{www}}} Strona internetowa]}}
{{#invoke:Sprawdź|url|{{{www}}}|[{{{www}}} Strona internetowa]}}
@param #1 Url do sprawdzenia.
Ciąg typu "{{{abc}}}" pominie sprawdzenie, żeby pokazać wartość na stronie szablonu.
@param #2 Tekst do wyświetlenia gdy OK.
@return pusty string gdy błędny, "ok" lub zawartość #2 gdy OK.
]]
["url"] = function(frame)
local link = frame.args[1]
local okText = frame.args[2] or "ok"
local isValid = string.find(link, '{{{') == 1 or checkUri(link)
if isValid then
return okText
end
return ""
end,
["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,
["zapis daty dostępu"] = function(frame)
local accessDate = frame:getParent().args["data dostępu"]
if accessDate and (#accessDate > 0) then
if not isDate20YYMMDD(accessDate) then
local builder = mw.html.create('span')
:addClass('problemy')
:wikitext('zły zapis daty dostępu')
if mw.title.getCurrentTitle().namespace == 0 then
builder:wikitext('[[Kategoria:Szablon cytowania – zły zapis daty dostępu]]')
end
return builder
end
end
end,
}