--[[ ----------------------------------
Modulo Lua che implementa il template {{Webarchive}} e offre alcune
funzionalità ad altri moduli Lua per la gestione degli archivi.
]]
require('Module:No globals')
local getArgs = require('Module:Arguments').getArgs
local p = {}
local track = {} -- array associativo per accumulare le categorie di tracciamento
local maxurls = 10 -- massimo numero di URL permessi
local servizi = {
{ signature = "archive.org", service = "wayback", tailbracket = " in %sInternet Archive%s", tracking = "Categoria:Template Webarchive - collegamenti all'Internet Archive" },
{ signature = "webcitation.org", service = "webcite", tailbracket = " in %sWebCite%s", tracking = "Categoria:Template Webarchive - collegamenti a WebCite" },
{ signature = "archive.is", service = "archiveis", tailbracket = " in %sArchive.is%s", tracking = "Categoria:Template Webarchive - collegamenti a archive.is" },
{ signature = "archive.fo", service = "archiveis", tailbracket = " in %sArchive.is%s", tracking = "Categoria:Template Webarchive - collegamenti a archive.is" },
{ signature = "archive.today", service = "archiveis", tailbracket = " in %sArchive.is%s", tracking = "Categoria:Template Webarchive - collegamenti a archive.is" },
{ signature = "archive.il", service = "archiveis", tailbracket = " in %sArchive.is%s", tracking = "Categoria:Template Webarchive - collegamenti a archive.is" },
{ signature = "archive.ec", service = "archiveis", tailbracket = " in %sArchive.is%s", tracking = "Categoria:Template Webarchive - collegamenti a archive.is" },
{ signature = "archive[-]it.org", service = "archiveit", tailbracket = " in %sArchive-It%s" },
{ signature = "arquivo.pt", tail = " nel Portuguese Web Archive" },
{ signature = "loc.gov", tailbracket = " nella %sLibrary of Congress%s" },
{ signature = "webharvest.gov", tailbracket = " nel %sNational Archives and Records Administration%s" },
{ signature = "bibalex.org", tail = " nella [[Bibliotheca Alexandrina#Struttura e collezioni|Bibliotheca Alexandrina]]" },
{ signature = "collectionscanada", tail = " nel Canadian Government Web Archive" },
{ signature = "haw.nsk", tail = " nel Croatian Web Archive (HAW)" },
{ signature = "veebiarhiiv.digar.ee", tail = " nell'Estonian Web Archive" },
{ signature = "vefsafn.is", tailbracket = " nella %sNational and University Library of Iceland%s]]" },
{ signature = "proni.gov", tailbracket = " nel %sPublic Record Office of Northern Ireland%s" },
{ signature = "uni[-]lj.si", tail = " nello Slovenian Web Archive" },
{ signature = "stanford.edu", tail = " nello [[Stanford University Libraries|Stanford Web Archive]]" },
{ signature = "nationalarchives.gov.uk", tailbracket = " in %sUK Government Web Archive%s" },
{ signature = "parliament.uk", tailbracket = " in %sUK Parliament's Web Archive%s" },
{ signature = "webarchive.org.uk", tailbracket = " in %sUK Web Archive%s" },
{ signature = "nlb.gov.sg", tail = " in Web Archive Singapore" },
{ signature = "pandora.nla.gov.au", tailbracket = " in %sPandora Archive%s" },
{ signature = "perma.cc", tailbracket = " in %sPerma.cc%s" },
{ signature = "perma-archives.cc", tailbracket = " in %sPerma.cc%s" },
{ signature = "screenshots.com", tail = " in Screenshots" },
{ signature = "wikiwix.com", tail = " in Wikiwix" },
{ signature = "freezepage.com", tail = " in Freezepage" },
{ signature = "webcache.googleusercontent.com", tail = " in Google Cache" }
}
local month_localized = { 'gennaio', 'febbraio', 'marzo', 'aprile', 'maggio', 'giugno',
'luglio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dicembre'}
--[[--------------------------< inlineError >-----------------------
Errore critico. Formatta l'output completamente in rosso. Aggiunge una categoria di tracciamento.
]]
local function inlineError(arg, msg)
track["Categoria:Errori di compilazione del template Webarchive"] = 1
return '<span style="font-size:100%" class="error citation-comment">Errore di compilazione del template Webarchive: controllare il valore di <code style="color:inherit; border:inherit; padding:inherit;">|' .. arg .. '=</code> (' .. msg .. ').</span>'
end
--[[--------------------------< inlineRed >-----------------------
Formatta un frammento di testo in rosso, quale ad esempio un avvertimento da integrare nell'output finale.
Aggiunge una categoria di tracciamento.
]]
local function inlineRed(msg, trackmsg)
if trackmsg == "warning" then
track["Categoria:Errori di compilazione del template Webarchive - Avvisi"] = 1
elseif trackmsg == "error" then
track["Categoria:Errori di compilazione del template Webarchive"] = 1
end
return '<span style="font-size:100%" class="error citation-comment">' .. msg .. '</span>'
end
--[[--------------------------< base62 >-----------------------
Converte base-62 in base-10
Crediti: https://de.wikipedia.org/wiki/Modul:Expr
]]
local function base62( value )
local r = 1
if value:match( "^%w+$" ) then
local n = #value
local k = 1
local c
r = 0
for i = n, 1, -1 do
c = value:byte( i, i )
if c >= 48 and c <= 57 then
c = c - 48
elseif c >= 65 and c <= 90 then
c = c - 55
elseif c >= 97 and c <= 122 then
c = c - 61
else
r = 1
break
end
r = r + c * k
k = k * 62
end
end
return r
end
--[[--------------------------< tableLength >-----------------------
Restituisce il numero di elementi in una tabella
]]
local function tableLength(t)
local count = 0
for _ in pairs(t) do count = count + 1 end
return count
end
--[[--------------------------< formatDate >-----------------------
Verifica il formato di una data (dmy o iso) e se lo riconosce
la riformatta in dmy, altrimenti restituisce il valore così com'è
]]
local function formatDate(date)
local y, m, d
local try_year
local split = mw.text.split(date, '-')
if tableLength(split) == 3 then
try_year = tonumber(split[1])
if try_year and try_year > 1900 and try_year < 2200 then -- iso
y, m, d = split[1], month_localized[tonumber(split[2])], split[3]
end
else
split = mw.text.split(date, ' ')
if tableLength(split) == 3 then
try_year = tonumber(split[3])
if try_year and try_year > 1900 and try_year < 2200 and
(split[1] == '1º' or tonumber(split[1])) then -- dmy
d, m, y = split[1], split[2], split[3]
end
end
end
if tonumber(d) == 1 then d = '1º' end
return m and mw.ustring.format('%s %s %s', d, m, y) or date
end
--[[--------------------------< formatUrlDate >-----------------------
Controlla la data prelevata automaticamente dall'url di un archivio.
Se è valida la formatta in dmy, altrimenti restituisce nil.
]]
local function formatUrlDate(y, m, d)
local current_year = tonumber(os.date("%Y"))
y, m, d = tonumber(y), tonumber(m), tonumber(d)
if not y or y == '' or not m or m == '' or not d or d == '' or d > 31 or
m < 1 or m > 12 or y < 1900 or y > current_year then
return nil
end
m = month_localized[m]
if d == 1 then d = '1º' end
return mw.ustring.format('%s %s %s', d, m, y)
end
--[[--------------------------< decodeWebciteDate >-----------------------
Ricava la data da un URI-path a Webcite (es. /67xHmVFWP).
Restituisce false se l'URL è valido ma in formato senza data.
]]
function p.decodeWebciteDate(path)
local path_elements = mw.text.split(path, "/")
-- Formati URL validi che non sono base62
-- http://www.webcitation.org/query?id=1138911916587475
-- http://www.webcitation.org/query?url=http..&date=2012-06-01+21:40:03
-- http://www.webcitation.org/1138911916587475
-- http://www.webcitation.org/cache/73e53dd1f16cf8c5da298418d2a6e452870cf50e
-- http://www.webcitation.org/getfile.php?fileid=1c46e791d68e89e12d0c2532cc3cf629b8bc8c8e
if mw.ustring.find(path_elements[2], "query") or
mw.ustring.find(path_elements[2], "cache") or
mw.ustring.find(path_elements[2], "getfile") or
tonumber(path_elements[2]) then
return false
end
local snapdate = os.date("%Y %m %d", string.sub(string.format("%d", base62(path_elements[2])),1,10))
local dt = mw.text.split(snapdate, " ")
local fulldate = formatUrlDate(dt[1], dt[2], dt[3])
return fulldate
end
--[[--------------------------< snapDateToString >-----------------------
Ricava la data da un URI-path a Wayback (es. /web/20160901010101/http://example.com ).
Gestisce anche le non cifre come "re_", "-" e "*".
]]
function p.decodeWaybackDate(path)
local snapdate = string.gsub(path, "^/w?e?b?/?", "") -- rimuove la sequenza iniziale "/web/" o "/"
local path_elements = mw.text.split(snapdate, "/")
snapdate = path_elements[1]
if snapdate == '*' then return end
snapdate = string.gsub(snapdate, "[a-z][a-z]_[0-9]?$", "")
snapdate = string.gsub(snapdate, "[-]", "")
snapdate = string.gsub(snapdate, "[*]$", "")
local fulldate
local dlen = string.len(snapdate)
if tonumber(snapdate) and dlen >= 8 then
local year = string.sub(snapdate, 1, 4)
local month = string.sub(snapdate, 5, 6)
local day = string.sub(snapdate, 7, 8)
fulldate = formatUrlDate(year, month, day)
end
return fulldate
end
--[[--------------------------< serviceName >-----------------------
Imposta la stringa di coda e l'ID del servizio in base al dominio
estratto da mw.uri.new() (es. web.archive.org)
]]
local function serviceName(url_main, nolink)
local tracking = 'Categoria:Template Webarchive - altri archivi'
local bracketopen, bracketclose = nolink and '' or '[[', nolink and '' or ']]'
url_main.service = 'altri'
for _,servizio in ipairs(servizi) do
if mw.ustring.find(url_main.host, servizio.signature) then
url_main.service = servizio['service'] or url_main.service
if servizio['tailbracket'] then
url_main.tail = mw.ustring.format(servizio.tailbracket, bracketopen, bracketclose)
else
url_main.tail = servizio['tail']
end
tracking = servizio['tracking'] or tracking
break
end
end
if url_main.tail == nil then
url_main.tail = " a " .. url_main.host .. " " .. inlineRed("Errore: URL di servizio di archiviazione sconosciuto")
end
track[tracking] = 1
end
--[[--------------------------< parseExtraArgs >-----------------------
Analizza gli argomenti numerati da 2 a maxurls, come url2..url10, date2..date10, title2..title10
e li memorizza in una tabella.
Per esempio: {{webarchive |url=.. |url4=.. |url7=..}}
Tre argomenti url non in una sequenza numerica (1..4..7).
La funzione processa solo gli argomenti numerati 2 o maggiore (in questo caso 4 e 7).
Crea entrate in una tabella a sequenza numerica come:
urlx[1].url = <valore argomento di url4>
urlx[2].url = <valore argomento di url7>
Restituisce la tabella elaborata.
]]
local function parseExtraArgs(args, maxurls)
local i, index, argurl, argurl2, argdate, argtitle
local ulx = {}
index = 1
for i = 2, maxurls do
argurl = 'url' .. i
if args[argurl] then
ulx[index] = {}
ulx[index]['url'] = args[argurl]
ulx[index]['date'] = args['date' .. i] or args['data' .. i] or
inlineRed('Data mancante', 'warning')
ulx[index]['title'] = args['title' .. i] or args['titolo' .. i]
index = index + 1
end
end
return ulx
end
--[[--------------------------< createTracking >-----------------------
Restituisce le categorie di tracciamento inserite in track[]
]]
local function createTracking()
-- procede solo nel namespace 0
local current_namespace = mw.title.getCurrentTitle().namespace
if current_namespace ~= 0 then return '' end
local sand = ''
if tableLength(track) > 0 then
for key,_ in pairs(track) do
sand = sand .. '[[' .. key .. ']]'
end
end
return sand
end
--[[--------------------------< createRendering >-----------------------
Return a rendering of the data in ulx[][]
]]
local function createRendering(url_main, ulx)
local sand, displayheader, displayfield
local period1 = "" -- For backwards compat with {{wayback}}
local period2 = "."
--local url_main = ulx[1]
local indexstr = "archiviato"
if url_main.date == "index" then
indexstr = "archivio"
end
if not url_main.title and not url_main.date then -- No title. No date
sand = mw.ustring.format("[%s Archiviato]%s", url_main.url, url_main.tail)
elseif not url_main.title and url_main.date then -- No title. Date.
if url_main.service == "wayback" then
period1 = "."
period2 = ""
end
sand = mw.ustring.format("[%s Archiviato] il %s%s%s", url_main.url, url_main.date, url_main.tail, period1)
elseif url_main.title and not url_main.date then -- Title. No date.
sand = mw.ustring.format("[%s %s]%s", url_main.url, url_main.title, url_main.tail)
elseif url_main.title and url_main.date then -- Title. Date.
sand = mw.ustring.format("[%s %s]%s (%s %s)", url_main.url, url_main.title, url_main.tail, indexstr, url_main.date)
else
return nil
end
if #ulx > 0 then -- For multiple archive URLs
sand = sand .. period2 .. " Archivi aggiuntivi: "
local archives_output = {}
for indx,urlx in ipairs(ulx) do
archives_output[#archives_output+1] = mw.ustring.format("[%s %s]", urlx["url"], urlx["title"] or urlx["date"] )
end
sand = sand .. table.concat(archives_output, ", ") .. "."
end
return sand
end
--[[--------------------------------------------------------------------
Funzione di interfaccia principale per implementazione del
Template:Webarchive
]]
function p.webarchive(frame)
-- carica in args i parametri e se sono nulli li ignora, eccetto che per il parametro nolink
local args = getArgs(frame, {
valueFunc = function(key, value)
if key == 'nolink' then
return true
elseif value then
value = mw.text.trim(value)
if value ~= '' then return value end
end
return nil
end
})
-- verifica eventuali errori nel parametro url
local url1 = args.url or args.url1
if not url1 then
return inlineError('url', 'vuoto') .. createTracking()
elseif mw.ustring.find(url1, 'https://web.http') then
track['Categoria:Errori di compilazione del template Webarchive'] = 1
return inlineError('url', 'https://web.http') .. createTracking()
elseif url1 == 'https://web.archive.org/http:/' then
track['Categoria:Errori di compilazione del template Webarchive'] = 1
return inlineError('url', 'URL non valido') .. createTracking()
end
local url_main = {}
url_main.url = url1
local uri1 = mw.uri.new(url1)
url_main.host = uri1.host
serviceName(url_main, args.nolink)
-- gestione delle date
local date = args.date or args.date1 or args.data or args.data1
if date then
date = formatDate(date)
local udate = url_main.service == 'wayback' and p.decodeWaybackDate(uri1.path) or
url_main.service == 'webcite' and p.decodeWebciteDate(uri1.path)
if udate and udate ~= date then
date = udate .. inlineRed('<sup>[Date non combacianti]</sup>', 'warning')
end
elseif url_main.service == 'wayback' then
date = p.decodeWaybackDate(uri1.path) or inlineRed('Collegamento non valido', 'error')
elseif url_main.service == 'webcite' then
date = p.decodeWebciteDate(uri1.path)
if date == false then
date = inlineRed('Data mancante', 'warning')
elseif not date then
date = inlineRed('Collegamento non valido', 'error')
end
else
date = inlineRed('Data mancante', 'warning')
end
url_main.date = date
-- gestione del titolo
url_main.title = args.title or args.title1 or args.titolo or args.titolo1
local ulx = parseExtraArgs(args, maxurls)
local rend = createRendering(url_main, ulx)
if not rend then
track["Categoria:Errori di compilazione del template Webarchive"] = 1
rend = '<span style="font-size:100%" class="error citation-comment">Errori in [[:Template:Webarchive]]: problema sconosciuto. Si prega di segnalarlo nella [[Discussioni_template:Webarchive|pagina di discussione]] del template.</span>'
end
return rend .. createTracking()
end
return p