Moduł:ISBN
Dokumentacja dla tego modułu może zostać utworzona pod nazwą Moduł:ISBN/opis
local resources = {
classLink = "isbn",
classIncorrect = "isbn-incorrect",
classSeparator = "isbn-do-sprawdzenia",
classJustified = "isbn-usprawiedliwiony",
classPretty = "isbn-ulepszony",
specialBooksPrefix = "Specjalna:Książki/",
findLinkPrefix = "Moduł:ISBN/",
isbnPrefix = "ISBN ",
categoryIncorrectNumber = "[[Kategoria:Artykuły z nieprawidłowymi numerami ISBN]]",
categoryInvalidNumber = "[[Kategoria:Artykuły z błędnymi numerami ISBN]]",
errorSyntax = "nieprawidłowa składnia",
errorFormal = "numer jest poprawny, możliwe, że ten sam numer jest przypisany do kilku różnych tytułów",
errorCheck10 = "nieprawidłowa cyfra kontrolna w numerze ISBN-10",
errorCheck13 = "nieprawidłowa cyfra kontrolna w numerze ISBN-13",
errorPretend13 = "numer ISBN-13 zawiera niewłaściwe cyfry na kluczowych pozycjach",
defaultPrefix13 = "978-",
}
local function deduceSeparators(number, prefix)
local function deduce(region, regionLen)
for _, v in ipairs(region) do
local minimum, maximum = string.match(v, "^(%d-)%-(%d-)$")
if minimum and maximum and #minimum==#maximum and (minimum <= maximum) then
local width = #minimum
local minimum = tonumber(minimum)
local maximum = tonumber(maximum)
local publisher = tonumber(string.sub(number, regionLen+1, regionLen+width))
if (minimum <= publisher) and (publisher <= maximum) then
return string.sub(number, 1, regionLen).."-"..string.sub(number, regionLen+1, regionLen+width).."-"..string.sub(number, regionLen+width+1)
end
end
end
end
local publishers = mw.loadData( "Moduł:ISBN/wydawcy" )
local regionLen = 1
while regionLen <= 5 do
local region = publishers[(prefix or resources.defaultPrefix13)..string.sub(number, 1, regionLen)]
if region then
local pretty = deduce(region, regionLen)
if pretty then
return pretty
end
end
regionLen = regionLen + 1
end
if prefix and (prefix ~= defaultPrefix13) then
regionLen = 1
while regionLen <= 5 do
region = publishers["978-"..string.sub(number, 1, regionLen)]
if region then
local pretty = deduce(region, regionLen)
if pretty then
return pretty
end
end
regionLen = regionLen + 1
end
end
end
local function analyze(isbn)
local result = {}
result.isbn = isbn
if string.match(isbn, "^[0-9][0-9%-]+[0-9]%-?[0-9Xx]$") and not string.match(isbn, "%-%-") then
-- numer ma odowiednie cyfry z opcjonalnymi separatorami
local clean, n = string.gsub(isbn, "%-", "")
result.code, result.n = string.upper(clean), n
result.justified = mw.title.new(resources.findLinkPrefix..clean).exists
end
if result.code and string.match(result.code, "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9X]$") then
-- ISBN-10
local b10, b9, b8, b7, b6, b5, b4, b3, b2, b1 = string.byte(result.code, 1, 10)
result.expectedSum = (11 - ((10*(b10-48)+9*(b9-48)+8*(b8-48)+7*(b7-48)+6*(b6-48)+5*(b5-48)+4*(b4-48)+3*(b3-48)+2*(b2-48)) % 11)) % 11
result.receivedSum = b1 == 88 and 10 or (b1 - 48)
result.kind = 10
result.error = result.expectedSum ~= result.receivedSum and resources.errorCheck10 or nil
result.separatorWarn = (result.n~=0) and ((result.n~=3) or not string.match(isbn, "[0-9]%-[0-9Xx]$"))
result.prefix = false
result.number = string.sub(result.code, 1, 9)
result.checksum = "-"..string.sub(result.code, 10, 10)
elseif result.code and (string.match(result.code, "^978[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$") or string.match(result.code, "^979[1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$")) then
-- ISBN-13
local b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13 = string.byte(result.code, 1, 13)
result.expectedSum = (10 - (((b1-48)+3*(b2-48)+(b3-48)+3*(b4-48)+(b5-48)+3*(b6-48)+(b7-48)+3*(b8-48)+(b9-48)+3*(b10-48)+(b11-48)+3*(b12-48)) % 10)) % 10
result.receivedSum = b13 - 48
result.kind = 13
result.error = result.expectedSum ~= result.receivedSum and resources.errorCheck13 or nil
result.separatorWarn = (result.n~=0) and ((result.n~=4) or not string.match(isbn, "^97[89]%-[0-9][0-9%-]-[0-9]%-[0-9]$"))
result.prefix = string.sub(result.code, 1, 3).."-"
result.number = string.sub(result.code, 4, 12)
result.checksum = "-"..string.sub(result.code, 13, 13)
elseif result.code and string.match(result.code, "^9[78][78][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9X]$") then
-- ten numer udaje, że jest ISBN-13
result.error = resources.errorPretend13
else
-- to nie jest numer ISBN, ma nieprawidłową liczbę cyfr lub nieprawidłowe znaki
result.error = resources.errorSyntax
end
if result.justified and not result.error then
result.error = resources.errorFormal
end
if not result.error and (result.n == 0) and (result.prefix ~= nil) and result.checksum and result.number then
local prettyNumber = deduceSeparators(result.number, result.prefix)
if prettyNumber then
result.org = result.isbn
result.isbn = (result.prefix or "")..prettyNumber..result.checksum
end
end
return result
end
local function printISBN(builder, info, prefix)
local ns = mw.title.getCurrentTitle().namespace
if info.error and not info.justified and not mw.site.namespaces[ns].isTalk and (ns >= 0) and (ns <= 102) then
mw.addWarning(mw.text.nowiki("{{ISBN|"..info.isbn.."}} "..info.error))
end
if not info.code then
builder
:wikitext(prefix)
:tag("span")
:addClass(resources.classIncorrect)
:attr("title", mw.getContentLanguage():ucfirst(info.error))
:wikitext(mw.text.nowiki(info.isbn), ns == 0 and resources.categoryIncorrectNumber or "")
return
end
builder
:wikitext("[[", resources.specialBooksPrefix, info.code, "|", prefix)
:tag("span")
:addClass(resources.classLink)
:addClass(info.justified and resources.classJustified or nil)
:addClass((not info.justified and info.error) and resources.classIncorrect or nil)
:addClass(info.separatorWarn and resources.classSeparator or nil)
:addClass(info.org and resources.classPretty or nil)
:attr("title", info.error and mw.getContentLanguage():ucfirst(info.error) or nil)
:wikitext(string.upper(info.isbn))
:done()
:wikitext("]]")
:wikitext((not info.justified and info.error and (ns == 0)) and resources.categoryIncorrectNumber or "")
:wikitext((info.justified and (ns == 0)) and resources.categoryInvalidNumber or "")
end
return {
link = function(builder, isbn)
if isbn then
local info = analyze(isbn)
printISBN(builder, info, resources.isbnPrefix)
return tostring(builder)
end
local isbn = builder[1] or builder.args[1] or builder:getParent().args[1]
if isbn then
isbn = mw.text.trim(isbn)
if #isbn >= 0 then
local info = analyze(isbn)
local builder = mw.html.create()
printISBN(builder, info, resources.isbnPrefix)
return tostring(builder)
end
end
end,
opis = function(frame)
local isbn = type(frame) == "string" and frame or (frame[1] or frame.args[1] or frame:getParent().args[1] or mw.title.getCurrentTitle().subpageText)
local info = analyze(isbn)
local result = mw.html.create()
:tag("tt"):wikitext("{{[[Szablon:ISBN|ISBN]]|", mw.text.nowiki(isbn), "}}"):done()
:wikitext(" → ")
printISBN(result, info, resources.isbnPrefix)
if info.error then
result:wikitext("\n* ", mw.getContentLanguage():ucfirst(info.error), ".")
end
if info.justified then
local status, data = pcall(mw.loadData, "Moduł:ISBN/"..info.code)
if status then
_ = mw.title.new("Module:ISBN/nietrywialne moduły generujące dokumentację").id
result:wikitext("\n----")
for i, v in ipairs(data) do
local text = false
if (type(v) == "table") and (type(v.title) == "string") and (type(v.args) == "table") then
text = mw.getCurrentFrame():expandTemplate(v)
elseif type(v) == "string" then
text = mw.getCurrentFrame():preprocess(v)
end
if text and #text > 0 then
result:wikitext("\n# ", text)
end
end
if data.kategoria and type(data.kategoria) == "string" and (#data.kategoria > 0) then
result:wikitext("\n[[Kategoria:", data.kategoria, "]]")
end
end
end
return tostring(result)
end,
}