Modul:Webarchive: Forskjell mellom sideversjoner
Hopp til navigering
Hopp til søk
m (Én sideversjon ble importert) |
m (Ændrede beskyttelsesindstillinger for "Modul:Webarchive": Robot: Beskytter en liste af filer. ([Flyt=Tillad kun skabelonredaktører og administratorer] (på ubestemt tid) [Redigér=Tillad kun skabelonredaktører og administratorer] (på ubestemt tid))) |
||
Linje 1: | Linje 1: | ||
--[[ ---------------------------------- |
--[[ ---------------------------------- |
||
Lua module implementing the {{webarchive}} template. |
Lua module implementing the {{webarchive}} template. |
||
A merger of the functionality of three templates: {{wayback}}, {{webcite}} and {{cite archives}} |
A merger of the functionality of three templates: {{wayback}}, {{webcite}} and {{cite archives}} |
||
]] |
]] |
||
local p = {} |
|||
--[[--------------------------< |
--[[--------------------------< inlineError >----------------------- |
||
]] |
|||
Critical error. Render output completely in red. Add to tracking category. |
|||
require('strict'); |
|||
local getArgs = require ('Module:Arguments').getArgs; |
|||
]] |
|||
local function inlineError(arg, msg) |
|||
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >-------------------------------------- |
|||
]] |
|||
track["Kategori:Webarchive-skabelon fejl"] = 1 |
|||
local categories = {}; -- category names |
|||
return '<span style="font-size:100%" class="error citation-comment">Error in webarchive template: Check <code style="color:inherit; border:inherit; padding:inherit;">|' .. arg .. '=</code> value. ' .. msg .. '</span>' |
|||
local config = {}; -- global configuration settings |
|||
local digits = {}; -- for i18n; table that translates local-wiki digits to western digits |
|||
local err_warn_msgs = {}; -- error and warning messages |
|||
local excepted_pages = {}; |
|||
local month_num = {}; -- for i18n; table that translates local-wiki month names to western digits |
|||
local prefixes = {}; -- service provider tail string prefixes |
|||
local services = {}; -- archive service provider data from |
|||
local s_text = {}; -- table of static text strings used to build final rendering |
|||
local uncategorized_namespaces = {}; -- list of namespaces that we should not categorize |
|||
local uncategorized_subpages = {}; -- list of subpages that should not be categorized |
|||
--[[--------------------------< P A G E S C O P E I D E N T I F I E R S >---------------------------------- |
|||
]] |
|||
local non_western_digits; -- boolean flag set true when data.digits.enable is true |
|||
local this_page = mw.title.getCurrentTitle(); |
|||
local track = {}; -- Associative array to hold tracking categories |
|||
local ulx = {}; -- Associative array to hold template data |
|||
--[[--------------------------< S U B S T I T U T E >---------------------------------------------------------- |
|||
Populates numbered arguments in a message string using an argument table. |
|||
]] |
|||
local function substitute (msg, args) |
|||
return args and mw.message.newRawMessage (msg, args):plain() or msg; |
|||
end |
end |
||
--[[--------------------------< inlineRed >----------------------- |
|||
Render a text fragment in red, such as a warning as part of the final output. |
|||
--[[--------------------------< tableLength >----------------------- |
|||
Add tracking category. |
|||
]] |
|||
Given a 1-D table, return number of elements |
|||
local function inlineRed(msg, trackmsg) |
|||
]] |
|||
local function tableLength(T) |
|||
local count = 0 |
|||
for _ in pairs(T) do count = count + 1 end |
|||
return count |
|||
end |
|||
--[=[-------------------------< M A K E _ W I K I L I N K >---------------------------------------------------- |
|||
Makes a wikilink; when both link and display text is provided, returns a wikilink in the form [[L|D]]; if only |
|||
link is provided, returns a wikilink in the form [[L]]; if neither are provided or link is omitted, returns an |
|||
empty string. |
|||
if trackmsg == "warning" then |
|||
]=] |
|||
track["Kategori:Webarchive-skabelon advarsler"] = 1 |
|||
elseif trackmsg == "error" then |
|||
track["Kategori:Webarchive-skabelon fejl"] = 1 |
|||
end |
|||
return '<span style="font-size:100%" class="error citation-comment">' .. msg .. '</span>' |
|||
local function make_wikilink (link, display, no_link) |
|||
if nil == no_link then |
|||
if link and ('' ~= link) then |
|||
if display and ('' ~= display) then |
|||
return table.concat ({'[[', link, '|', display, ']]'}); |
|||
else |
|||
return table.concat ({'[[', link, ']]'}); |
|||
end |
|||
end |
|||
return display or ''; -- link not set so return the display text |
|||
else -- no_link |
|||
if display and ('' ~= display) then -- if there is display text |
|||
return display; -- return that |
|||
else |
|||
return link or ''; -- return the target article name or empty string |
|||
end |
|||
end |
|||
end |
end |
||
--[[--------------------------< trimArg >----------------------- |
|||
trimArg returns nil if arg is "" while trimArg2 returns 'true' if arg is "" |
|||
--[[--------------------------< createTracking >----------------------- |
|||
trimArg2 is for args that might accept an empty value, as an on/off switch like nolink= |
|||
]] |
|||
Return data in track[] ie. tracking categories |
|||
]] |
|||
local function createTracking() |
|||
if not excepted_pages[this_page.fullText] then -- namespace:title/fragment is allowed to be categorized (typically this module's / template's testcases page(s)) |
|||
if uncategorized_namespaces[this_page.nsText] then |
|||
return ''; -- this page not to be categorized so return empty string |
|||
end |
|||
for _,v in ipairs (uncategorized_subpages) do -- cycle through page name patterns |
|||
if this_page.text:match (v) then -- test page name against each pattern |
|||
return ''; -- this subpage type not to be categorized so return empty string |
|||
end |
|||
end |
|||
end |
|||
local out = {}; |
|||
if tableLength(track) > 0 then |
|||
for key, _ in pairs(track) do -- loop through table |
|||
table.insert (out, make_wikilink (key)); -- and convert category names to links |
|||
end |
|||
end |
|||
return table.concat (out); -- concat into one big string; empty string if table is empty |
|||
local function trimArg(arg) |
|||
if arg == "" or arg == nil then |
|||
return nil |
|||
else |
|||
return mw.text.trim(arg) |
|||
end |
|||
end |
end |
||
local function trimArg2(arg) |
|||
if arg == nil then |
|||
return nil |
|||
--[[--------------------------< inlineError >----------------------- |
|||
else |
|||
return mw.text.trim(arg) |
|||
Critical error. Render output completely in red. Add to tracking category. |
|||
end |
|||
This function called as the last thing before abandoning this module |
|||
]] |
|||
local function inlineError (msg, args) |
|||
track[categories.error] = 1 |
|||
return table.concat ({ |
|||
'<span style="font-size:100%" class="error citation-comment">Error in ', -- open the error message span |
|||
config.tname, -- insert the local language template name |
|||
' template: ', |
|||
substitute (msg, args), -- insert the formatted error message |
|||
'.</span>', -- close the span |
|||
createTracking() -- add the category |
|||
}) |
|||
end |
end |
||
--[[--------------------------< inlineRed >----------------------- |
|||
Render a text fragment in red, such as a warning as part of the final output. |
|||
Add tracking category. |
|||
]] |
|||
local function inlineRed(msg, trackmsg) |
|||
if trackmsg == "warning" then |
|||
track[categories.warning] = 1; |
|||
elseif trackmsg == "error" then |
|||
track[categories.error] = 1; |
|||
end |
|||
return '<span style="font-size:100%" class="error citation-comment">' .. msg .. '</span>' |
|||
end |
|||
--[[--------------------------< base62 >----------------------- |
--[[--------------------------< base62 >----------------------- |
||
Convert base-62 to base-10 |
Convert base-62 to base-10 |
||
Credit: https://de.wikipedia.org/wiki/Modul:Expr |
Credit: https://de.wikipedia.org/wiki/Modul:Expr |
||
]] |
]] |
||
local function base62( value ) |
local function base62( value ) |
||
local r = 1 -- default return value is input value is malformed |
|||
local r = 1 |
|||
if value:match ('%W') then -- value must only be in the set [0-9a-zA-Z] |
|||
return; -- nil return when value contains extraneous characters |
|||
end |
|||
if value:match( "^%w+$" ) then |
|||
local n = #value -- number of characters in value |
|||
local n = #value |
|||
local k = 1 |
|||
local c |
|||
r = 0 |
|||
r = 0 |
|||
for i = n, 1, -1 do -- loop through all characters in value from ls digit to ms digit |
|||
for i = n, 1, -1 do |
|||
c = value:byte( i, i ) |
|||
if c >= 48 and c <= 57 then -- character is digit 0-9 |
|||
if c >= 48 and c <= 57 then |
|||
c = c - 48 |
|||
c = c - 48 |
|||
elseif c >= 65 and c <= 90 then -- character is ascii a-z |
|||
elseif c >= 65 and c <= 90 then |
|||
c = c - 55 |
|||
c = c - 55 |
|||
else -- must be ascii A-Z |
|||
elseif c >= 97 and c <= 122 then |
|||
c = c - 61 |
|||
c = c - 61 |
|||
end |
|||
else -- How comes? |
|||
r = r + c * k -- accumulate this base62 character's value |
|||
r = 1 |
|||
k = k * 62 -- bump for next |
|||
break -- for i |
|||
end |
|||
r = r + c * k |
|||
return r |
|||
k = k * 62 |
|||
end -- for i |
|||
end |
|||
return r |
|||
end |
end |
||
--[[--------------------------< tableLength >----------------------- |
|||
Given a 1-D table, return number of elements |
|||
--[[--------------------------< D E C O D E _ D A T E >-------------------------------------------------------- |
|||
]] |
|||
Given a date string, return it in iso format along with an indicator of the date's format. Except that month names |
|||
must be recognizable as legitimate month names with proper capitalization, and that the date string must match one |
|||
of the recognized date formats, no error checking is done here; return nil else |
|||
local function tableLength(T) |
|||
]] |
|||
local count = 0 |
|||
for _ in pairs(T) do count = count + 1 end |
|||
local function decode_date (date_str) |
|||
return count |
|||
local patterns = { |
|||
['dmy'] = {'^(%d%d?) +([^%s%d]+) +(%d%d%d%d)$', 'd', 'm', 'y'}, -- %a does not recognize unicode combining characters used by some languages |
|||
['mdy'] = {'^([^%s%d]+) (%d%d?), +(%d%d%d%d)$', 'm', 'd', 'y'}, |
|||
['ymd'] = {'^(%d%d%d%d) +([^%s%d]+) (%d%d?)$', 'y', 'm', 'd'}, -- not mos compliant at en.wiki but may be acceptible at other wikis |
|||
}; |
|||
local t = {}; |
|||
if non_western_digits then -- this wiki uses non-western digits? |
|||
date_str = mw.ustring.gsub (date_str, '%d', digits); -- convert this wiki's non-western digits to western digits |
|||
end |
|||
if date_str:match ('^%d%d%d%d%-%d%d%-%d%d$') then -- already an iso format date, return western digits form |
|||
return date_str, 'iso'; |
|||
end |
|||
for k, v in pairs (patterns) do |
|||
local c1, c2, c3 = mw.ustring.match (date_str, patterns[k][1]); -- c1 .. c3 are captured but we don't know what they hold |
|||
if c1 then -- set on match |
|||
t = { -- translate unspecified captures to y, m, and d |
|||
[patterns[k][2]] = c1, -- fill the table of captures with the captures |
|||
[patterns[k][3]] = c2, -- take index names from src_pattern table and assign sequential captures |
|||
[patterns[k][4]] = c3, |
|||
}; |
|||
if month_num[t.m] then -- when month not already a number |
|||
t.m = month_num[t.m]; -- replace valid month name with a number |
|||
else |
|||
return nil, 'iso'; -- not a valid date form because month not valid |
|||
end |
|||
return mw.ustring.format ('%.4d-%.2d-%.2d', t.y, t.m, t.d), k; -- return date in iso format |
|||
end |
|||
end |
|||
return nil, 'iso'; -- date could not be decoded; return nil and default iso date |
|||
end |
end |
||
--[[--------------------------< makeDate >----------------------- |
|||
--[[--------------------------< dateFormat >----------------------- |
|||
Given year, month, day numbers, (zero-padded or not) return a full date in df format |
|||
where df may be one of: |
|||
mdy, dmy, iso, ymd |
|||
Given a date string, return its format: dmy, mdy, iso, ymd |
|||
on entry, year, month, day are presumed to be correct for the date that they represent; all are required |
|||
If unable to determine return nil |
|||
]] |
|||
in this module, makeDate() is sometimes given an iso-format date in year: |
|||
makeDate (2018-09-20, nil, nil, df) |
|||
this works because table.concat() sees only one table member |
|||
local function dateFormat(date) |
|||
]] |
|||
local dt = {} |
|||
local function makeDate (year, month, day, df) |
|||
dt.split = {} |
|||
['dmy'] = 'j F Y', |
|||
['mdy'] = 'F j, Y', |
|||
['ymd'] = 'Y F j', |
|||
['iso'] = 'Y-m-d', |
|||
}; |
|||
dt.split = mw.text.split(date, "-") |
|||
local date = table.concat ({year, month, day}, '-'); -- assemble year-initial numeric-format date (zero padding not required here) |
|||
if tableLength(dt.split) == 3 then |
|||
if tonumber(dt.split[1]) > 1900 and tonumber(dt.split[1]) < 2200 and tonumber(dt.split[2]) and tonumber(dt.split[3]) then |
|||
return "iso" |
|||
else |
|||
return nil |
|||
end |
|||
end |
|||
dt.split = mw.text.split(date, " ") |
|||
if non_western_digits then -- this wiki uses non-western digits? |
|||
if tableLength(dt.split) == 3 then |
|||
date = mw.ustring.gsub (date, '%d', digits); -- convert this wiki's non-western digits to western digits |
|||
if tonumber(dt.split[3]) then |
|||
end |
|||
if tonumber(dt.split[3]) > 1900 and tonumber(dt.split[3]) < 2200 then |
|||
if tonumber(dt.split[1]) then |
|||
return "dmy" |
|||
else |
|||
return "mdy" |
|||
end |
|||
else |
|||
if tonumber(dt.split[1]) then |
|||
if tonumber(dt.split[1]) > 1900 and tonumber(dt.split[1]) < 2200 then |
|||
return "ymd" |
|||
end |
|||
end |
|||
end |
|||
end |
|||
end |
|||
return nil |
|||
return mw.getContentLanguage():formatDate (format[df], date); |
|||
end |
end |
||
--[[--------------------------< makeDate >----------------------- |
|||
Given a zero-padded 4-digit year, 2-digit month and 2-digit day, return a full date in df format |
|||
--[[--------------------------< I S _ V A L I D _ D A T E >---------------------------------------------------- |
|||
df = mdy, dmy, iso, ymd |
|||
]] |
|||
Returns true if date is after 31 December 1899 (why is 1900 the min year? shouldn't the internet's date-of-birth |
|||
be min year?), not after today's date, and represents a valid date (29 February 2017 is not a valid date). Applies |
|||
Gregorian leapyear rules. |
|||
local function makeDate(year, month, day, df) |
|||
all arguments are required |
|||
if not year or year == "" or not month or month == "" or not day or day == "" then |
|||
]] |
|||
return nil |
|||
end |
|||
local zmonth = month -- month with leading 0 |
|||
local function is_valid_date (year, month, day) |
|||
month = month:match("0*(%d+)") -- month without leading 0 |
|||
local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
|||
if tonumber(month) < 1 or tonumber(month) > 12 then |
|||
local month_length; |
|||
return year |
|||
local y, m, d; |
|||
end |
|||
local today = os.date ('*t'); -- fetch a table of current date parts |
|||
local nmonth = os.date("%B", os.time{year=2000, month=month, day=1} ) -- month in name form |
|||
if not nmonth then |
|||
return year |
|||
end |
|||
local zday = day |
|||
if not year or '' == year or not month or '' == month or not day or '' == day then |
|||
day = zday:match("0*(%d+)") |
|||
return false; -- something missing |
|||
if tonumber(day) < 1 or tonumber(day) > 31 then |
|||
end |
|||
if df == "mdy" or df == "dmy" then |
|||
return nmonth .. " " .. year |
|||
y = tonumber (year); |
|||
elseif df == "iso" then |
|||
m = tonumber (month); |
|||
return year .. "-" .. zmonth |
|||
d = tonumber (day); |
|||
elseif df == "ymd" then |
|||
return year .. " " .. nmonth |
|||
else |
|||
return nmonth .. " " .. year |
|||
end |
|||
end |
|||
if df == "mdy" then |
|||
if 1900 > y or today.year < y or 1 > m or 12 < m then -- year and month are within bounds TODO: 1900? |
|||
return nmonth .. " " .. day .. ", " .. year -- September 1, 2016 |
|||
return false; |
|||
elseif df == "dmy" then |
|||
end |
|||
return day .. " " .. nmonth .. " " .. year -- 1 September 2016 |
|||
elseif df == "iso" then |
|||
return year .. "-" .. zmonth .. "-" .. zday -- 2016-09-01 |
|||
elseif df == "ymd" then |
|||
return year .. " " .. nmonth .. " " .. cday -- 2016 September 1 |
|||
else |
|||
return nmonth .. " " .. day .. ", " .. year -- September 1, 2016 |
|||
end |
|||
if (2==m) then -- if February |
|||
month_length = 28; -- then 28 days unless |
|||
if (0==(y%4) and (0~=(y%100) or 0==(y%400))) then -- is a leap year? |
|||
month_length = 29; -- if leap year then 29 days in February |
|||
end |
|||
else |
|||
month_length=days_in_month[m]; |
|||
end |
|||
if 1 > d or month_length < d then -- day is within bounds |
|||
return false; |
|||
end |
|||
-- here when date parts represent a valid date |
|||
return os.time({['year']=y, ['month']=m, ['day']=d, ['hour']=0}) <= os.time(); -- date at midnight must be less than or equal to current date/time |
|||
end |
end |
||
Linje 323: | Linje 208: | ||
--[[--------------------------< decodeWebciteDate >----------------------- |
--[[--------------------------< decodeWebciteDate >----------------------- |
||
Given a URI-path to Webcite (eg. /67xHmVFWP) return the encoded date in df format |
Given a URI-path to Webcite (eg. /67xHmVFWP) return the encoded date in df format |
||
returns date string in df format - webcite date is a unix timestamp encoded as bae62 |
|||
or the string 'query' |
|||
]] |
|||
]] |
|||
local function decodeWebciteDate(path, df) |
local function decodeWebciteDate(path, df) |
||
local dt = {} |
|||
dt.split = {} |
|||
local decode; |
|||
dt.split = mw.text.split(path, "/") |
|||
-- valid URL formats that are not base62 |
|||
-- http://www.webcitation.org/query?id=1138911916587475 |
|||
-- http://www.webcitation.org/1138911916587475 |
|||
-- http://www.webcitation.org/cache/73e53dd1f16cf8c5da298418d2a6e452870cf50e |
|||
if dt.split[2] == "query" or dt.split[2] == "cache" or tonumber(dt.split[2]) then |
|||
return "query" |
|||
end |
|||
dt.full = os.date("%Y %m %d", string.sub(string.format("%d", base62(dt.split[2])),1,10) ) |
|||
-- http://www.webcitation.org/query?id=1138911916587475 |
|||
dt.split = mw.text.split(dt.full, " ") |
|||
-- http://www.webcitation.org/query?url=http..&date=2012-06-01+21:40:03 |
|||
dt.year = dt.split[1] |
|||
-- http://www.webcitation.org/1138911916587475 |
|||
dt.month = dt.split[2] |
|||
-- http://www.webcitation.org/cache/73e53dd1f16cf8c5da298418d2a6e452870cf50e |
|||
dt.day = dt.split[3] |
|||
-- http://www.webcitation.org/getfile.php?fileid=1c46e791d68e89e12d0c2532cc3cf629b8bc8c8e |
|||
if not tonumber(dt.year) or not tonumber(dt.month) or not tonumber(dt.day) then |
|||
if dt[2]:find ('query', 1, true) or |
|||
return inlineRed("[Date error] (1)", "error") |
|||
dt[2]:find ('cache', 1, true) or |
|||
end |
|||
dt[2]:find ('getfile', 1, true) or |
|||
tonumber(dt[2]) then |
|||
return 'query'; |
|||
end |
|||
if tonumber(dt.month) > 12 or tonumber(dt.day) > 31 or tonumber(dt.month) < 1 then |
|||
decode = base62(dt[2]); -- base62 string -> exponential number |
|||
return inlineRed("[Date error] (2)", "error") |
|||
if not decode then |
|||
end |
|||
return nil; -- nil return when dt[2] contains characters not in %w |
|||
if tonumber(dt.year) > tonumber(os.date("%Y")) or tonumber(dt.year) < 1900 then |
|||
end |
|||
return inlineRed("[Date error] (3)", "error") |
|||
dt = os.date('*t', string.format("%d", decode):sub(1,10)) -- exponential number -> text -> first 10 characters (a unix timestamp) -> a table of date parts |
|||
end |
|||
fulldate = makeDate(dt.year, dt.month, dt.day, df) |
|||
if not fulldate then |
|||
if non_western_digits then -- this wiki uses non-western digits? |
|||
return inlineRed("[Date error] (4)", "error") |
|||
decode = mw.ustring.gsub (decode, '%d', digits); -- convert this wiki's non-western digits to western digits |
|||
else |
|||
end |
|||
return fulldate |
|||
end |
|||
return decode; |
|||
end |
end |
||
--[[--------------------------< snapDateToString >----------------------- |
|||
--[[--------------------------< decodeWaybackDate >----------------------- |
|||
Given a URI-path to Wayback (eg. /web/20160901010101/http://example.com ) |
Given a URI-path to Wayback (eg. /web/20160901010101/http://example.com ) |
||
return the formatted date eg. "September 1, 2016" in df format |
|||
or Library of Congress Web Archives (eg. /all/20160901010101/http://example.com) |
|||
Handle non-digits in snapshot ID such as "re_" and "-" and "*" |
|||
or UK Government Web Archive (eg. /ukgwa/20160901010101/http://example.com or /tna/20160901010101/http://example.com) |
|||
]] |
|||
return the formatted date eg. "September 1, 2016" in df format |
|||
Handle non-digits in snapshot ID such as "re_" and "-" and "*" |
|||
returns two values: |
|||
first value is one of these: |
|||
valid date string in df format - wayback date is valid (including the text string 'index' when date is '/*/') |
|||
empty string - wayback date is malformed (less than 8 digits, not a valid date) |
|||
nil - wayback date is '/save/' or otherwise not a number |
|||
second return value is an appropriate 'message' may or may not be formatted |
|||
]] |
|||
local function decodeWaybackDate(path, df) |
local function decodeWaybackDate(path, df) |
||
local snapdate, snapdatelong, currdate, fulldate |
|||
local msg, snapdate; |
|||
local safe = path |
|||
snapdate = path:gsub ('^/web/', ''):gsub ('^/all/', ''):gsub ('^/ukgwa/', ''):gsub ('^/tna/', ''):gsub ('^/', ''); -- remove leading /web/, /all/, /ukgwa/, /tna/, or / |
|||
snapdate = string.gsub(safe, "^/w?e?b?/?", "") -- Remove leading "/web/" or "/" |
|||
snapdate = snapdate:match ('^[^/]+'); -- get timestamp |
|||
safe = snapdate |
|||
if snapdate == "*" then -- eg. /web/*/http.., etc. |
|||
local N = mw.text.split(safe, "/") |
|||
return 'index'; -- return indicator that this url has an index date |
|||
snapdate = N[1] |
|||
end |
|||
if snapdate == "*" then -- eg. /web/*/http.. |
|||
return "index" |
|||
end |
|||
safe = snapdate |
|||
snapdate = string.gsub(safe, "[a-z][a-z]_[0-9]?$", "") -- Remove any trailing "re_" from date |
|||
safe = snapdate |
|||
snapdate = string.gsub(safe, "[-]", "") -- Remove dashes from date eg. 2015-01-01 |
|||
safe = snapdate |
|||
snapdate = string.gsub(safe, "[*]$", "") -- Remove trailing "*" |
|||
if not tonumber(snapdate) then |
|||
snapdate = snapdate:gsub ('%a%a_%d?$', ''):gsub ('%-', ''); -- from date, remove any trailing "re_", dashes |
|||
return inlineRed("[Date error] (2)", "error") |
|||
end |
|||
local dlen = string.len(snapdate) |
|||
if dlen < 4 then |
|||
return inlineRed("[Date error] (3)", "error") |
|||
end |
|||
if dlen < 14 then |
|||
snapdatelong = snapdate .. string.rep("0", 14 - dlen) |
|||
else |
|||
snapdatelong = snapdate |
|||
end |
|||
local year = string.sub(snapdatelong, 1, 4) |
|||
local month = string.sub(snapdatelong, 5, 6) |
|||
local day = string.sub(snapdatelong, 7, 8) |
|||
if not tonumber(year) or not tonumber(month) or not tonumber(day) then |
|||
return inlineRed("[Date error] (4)", "error") |
|||
end |
|||
if tonumber(month) > 12 or tonumber(day) > 31 or tonumber(month) < 1 then |
|||
return inlineRed("[Date error] (5)", "error") |
|||
end |
|||
currdate = os.date("%Y") |
|||
if tonumber(year) > tonumber(currdate) or tonumber(year) < 1900 then |
|||
return inlineRed("[Date error] (6)", "error") |
|||
end |
|||
fulldate = makeDate(year, month, day, df) |
|||
msg = ''; |
|||
if not fulldate then |
|||
if snapdate:match ('%*$') then -- a trailing '*' causes calendar display at archive .org |
|||
return inlineRed("[Date error] (7)", "error") |
|||
snapdate = snapdate:gsub ('%*$', ''); -- remove so not part of length calc later |
|||
else |
|||
msg = inlineRed (err_warn_msgs.ts_cal, 'warning'); -- make a message |
|||
return fulldate |
|||
end |
|||
end |
|||
if not tonumber(snapdate) then |
|||
return nil, 'ts_nan'; -- return nil (fatal error flag) and message selector |
|||
end |
|||
local dlen = snapdate:len(); |
|||
if dlen < 8 then -- we need 8 digits TODO: but shouldn't this be testing for 14 digits? |
|||
return '', inlineRed (err_warn_msgs.ts_short, 'error'); -- return empty string and error message |
|||
end |
|||
local year, month, day = snapdate:match ('(%d%d%d%d)(%d%d)(%d%d)'); -- no need for snapdatelong here |
|||
if not is_valid_date (year, month, day) then |
|||
return '', inlineRed (err_warn_msgs.ts_date, 'error'); -- return empty string and error message |
|||
end |
|||
snapdate = table.concat ({year, month, day}, '-'); -- date comparisons are all done in iso format |
|||
if 14 == dlen then |
|||
return snapdate, msg; -- return date with message if any |
|||
else |
|||
return snapdate, msg .. inlineRed (err_warn_msgs.ts_len, 'warning'); -- return date with warning message(s) |
|||
end |
|||
end |
end |
||
--[[--------------------------< |
--[[--------------------------< serviceName >----------------------- |
||
Given a domain extracted by mw.uri.new() (eg. web.archive.org) set tail string and service ID |
|||
Given an Archive.is "long link" URI-path (e.g. /2016.08.28-144552/http://example.com) |
|||
return the date in df format (e.g. if df = dmy, return 28 August 2016) |
|||
Handles "." and "-" in snapshot date, so 2016.08.28-144552 is same as 20160828144552 |
|||
]] |
|||
returns two values: |
|||
first value is one of these: |
|||
valid date string in df format - archive.is date is valid (including the text string 'short link' when url is the short form) |
|||
empty string - wayback date is malformed (not a number, less than 8 digits, not a valid date) |
|||
nil - wayback date is '/save/' |
|||
second return value is an appropriate 'message' may or may not be formatted |
|||
local function serviceName(host, nolink) |
|||
]] |
|||
local tracking = "Kategori:Sider med Webarchive-skabelon som henviser til andre arkiver" |
|||
local function decodeArchiveisDate(path, df) |
|||
local snapdate |
|||
local bracketopen = "[[" |
|||
if path:match ('^/%w+$') then -- short form url path is '/' followed by some number of base 62 digits and nothing else |
|||
local bracketclose = "]]" |
|||
return "short link" -- e.g. http://archive.is/hD1qz |
|||
if nolink then |
|||
end |
|||
bracketopen = "" |
|||
bracketclose = "" |
|||
end |
|||
ulx.url1.service = "other" |
|||
snapdate = mw.text.split (path, '/')[2]:gsub('[%.%-]', ''); -- get snapshot date, e.g. 2016.08.28-144552; remove periods and hyphens |
|||
ulx.url1.tail =" hos " .. ulx.url1.host .. " " .. inlineRed("Error: unknown archive URL") |
|||
if mw.ustring.find( host, "archive.org", 1, plain ) then |
|||
local dlen = string.len(snapdate) |
|||
ulx.url1.service = "wayback" |
|||
if dlen < 8 then -- we need 8 digits TODO: but shouldn't this be testing for 14 digits? |
|||
ulx.url1.tail = " " .. bracketopen .. "Wayback Machine" .. bracketclose |
|||
return '', inlineRed (err_warn_msgs.ts_short, 'error'); -- return empty string and error message |
|||
tracking = "Kategori:Sider med Webarchive-skabelon som henviser til Wayback Machine" |
|||
end |
|||
elseif mw.ustring.find( host, "webcitation.org", 1, plain ) then |
|||
ulx.url1.service = "webcite" |
|||
ulx.url1.tail = " " .. bracketopen .. "WebCite" .. bracketclose |
|||
tracking = "Kategori:Sider med Webarchive-skabelon som henviser til webcite" |
|||
elseif mw.ustring.find( host, "archive.is", 1, plain ) then |
|||
ulx.url1.service = "archiveis" |
|||
ulx.url1.tail ="" .. bracketopen .. "Archive.is" .. bracketclose |
|||
tracking = "Kategori:Sider med Webarchive-skabelon som henviser til archiveis" |
|||
elseif mw.ustring.find( host, "archive.fo", 1, plain ) then |
|||
ulx.url1.service = "archiveis" |
|||
ulx.url1.tail =" hos " .. bracketopen .. "Archive.is" .. bracketclose |
|||
tracking = "Kategori:Sider med Webarchive-skabelon som henviser til archiveis" |
|||
elseif mw.ustring.find( host, "archive.today", 1, plain ) then |
|||
ulx.url1.service = "archiveis" |
|||
ulx.url1.tail =" hos " .. bracketopen .. "Archive.is" .. bracketclose |
|||
tracking = "Kategori:Sider med Webarchive-skabelon som henviser til archiveis" |
|||
elseif mw.ustring.find( host, "archive[-]it.org", 1, plain ) then |
|||
ulx.url1.service = "archiveit" |
|||
ulx.url1.tail =" hos " .. bracketopen .. "Archive-It" .. bracketclose |
|||
elseif mw.ustring.find( host, "arquivo.pt", 1, plain) then |
|||
ulx.url1.tail = " hos " .. "Portugese Web Archive" |
|||
elseif mw.ustring.find( host, "loc.gov", 1, plain ) then |
|||
ulx.url1.tail = " hos " .. bracketopen .. "Library of Congress" .. bracketclose |
|||
elseif mw.ustring.find( host, "webharvest.gov", 1, plain ) then |
|||
ulx.url1.tail = " hos " .. bracketopen .. "National Archives and Records Administration" .. bracketclose |
|||
elseif mw.ustring.find( host, "bibalex.org", 1, plain ) then |
|||
ulx.url1.tail =" hos " .. "[[Bibliotheca_Alexandrina#Internet_Archive_partnership|Bibliotheca Alexandrina]]" |
|||
elseif mw.ustring.find( host, "collectionscanada", 1, plain ) then |
|||
ulx.url1.tail = " hos " .. "Canadian Government Web Archive" |
|||
elseif mw.ustring.find( host, "haw.nsk", 1, plain ) then |
|||
ulx.url1.tail = " hos " .. "Croatian Web Archive (HAW)" |
|||
elseif mw.ustring.find( host, "nlib.ee", 1, plain ) then |
|||
ulx.url1.tail = " hos " .. "Estonian Web Archive" |
|||
elseif mw.ustring.find( host, "vefsafn.is", 1, plain ) then |
|||
ulx.url1.tail = " hos " .. "[[National and University Library of Iceland]]" |
|||
elseif mw.ustring.find( host, "proni.gov", 1, plain ) then |
|||
ulx.url1.tail = " hos " .. bracketopen .. "Public Record Office of Northern Ireland" .. bracketclose |
|||
elseif mw.ustring.find( host, "uni[-]lj.si", 1, plain ) then |
|||
ulx.url1.tail = " hos " .. "Slovenian Web Archive" |
|||
elseif mw.ustring.find( host, "stanford.edu", 1, plain ) then |
|||
ulx.url1.tail = " hos " .. "[[Stanford University Libraries|Stanford Web Archive]]" |
|||
elseif mw.ustring.find( host, "nationalarchives.gov.uk", 1, plain ) then |
|||
ulx.url1.tail = " hos " .. bracketopen .. "UK Government Web Archive" .. bracketclose |
|||
elseif mw.ustring.find( host, "parliament.uk", 1, plain ) then |
|||
ulx.url1.tail = " hos " .. bracketopen .. "UK Parliament's Web Archive" .. bracketclose |
|||
elseif mw.ustring.find( host, "webarchive.org.uk", 1, plain ) then |
|||
ulx.url1.tail = " hos " .. bracketopen .. "UK Web Archive" .. bracketclose |
|||
elseif mw.ustring.find( host, "nlb.gov.sg", 1, plain ) then |
|||
ulx.url1.tail =" hos " .. "Web Archive Singapore" |
|||
elseif mw.ustring.find( host, "nlb.gov.sg", 1, plain ) then |
|||
ulx.url1.tail =" hos " .. "Web Archive Singapore" |
|||
elseif mw.ustring.find( host, "screenshots.com", 1, plain ) then |
|||
ulx.url1.tail =" hos " .. "Screenshots" |
|||
elseif mw.ustring.find( host, "wikiwix.com", 1, plain ) then |
|||
ulx.url1.tail =" hos " .. "Wikiwix" |
|||
elseif mw.ustring.find( host, "perma.cc", 1, plain ) then |
|||
ulx.url1.tail =" hos " .. bracketopen .. "Perma.cc" .. bracketclose |
|||
else |
|||
tracking = "Kategori:Sider med Webarchive-skabelon som henviser til ukendte arkiver" |
|||
end |
|||
track[tracking] = 1 |
|||
local year, month, day = snapdate:match ('(%d%d%d%d)(%d%d)(%d%d)'); -- no need for snapdatelong here |
|||
if not is_valid_date (year, month, day) then |
|||
return '', inlineRed (err_warn_msgs.ts_date, 'error'); -- return empty string and error message |
|||
end |
|||
snapdate = table.concat ({year, month, day}, '-'); -- date comparisons are all done in iso format |
|||
if 14 == dlen then |
|||
return snapdate; -- return date |
|||
else |
|||
return snapdate, inlineRed (err_warn_msgs.ts_len, 'warning'); -- return date with warning message |
|||
end |
|||
end |
|||
--[[--------------------------< serviceName >----------------------- |
|||
Given a domain extracted by mw.uri.new() (eg. web.archive.org) set tail string and service ID |
|||
]] |
|||
local function serviceName(host, no_link) |
|||
local tracking; |
|||
local index; |
|||
host = host:lower():gsub ('^web%.(.+)', '%1'):gsub ('^www%.(.+)', '%1'); -- lowercase, remove web. and www. subdomains |
|||
if services[host] then |
|||
index = host; |
|||
else |
|||
for k, _ in pairs (services) do |
|||
if host:find ('%f[%a]'..k:gsub ('([%.%-])', '%%%1')) then |
|||
index = k; |
|||
break; |
|||
end |
|||
end |
|||
end |
|||
if index then |
|||
local out = {''}; -- empty string in [1] so that concatenated result has leading single space |
|||
ulx.url1.service = services[index][4] or 'other'; |
|||
tracking = services[index][5] or categories.other; |
|||
-- build tail string |
|||
if false == services[index][1] then -- select prefix |
|||
table.insert (out, prefixes.at); |
|||
elseif true == services[index][1] then |
|||
table.insert (out, prefixes.atthe); |
|||
else |
|||
table.insert (out, services[index][1]); |
|||
end |
|||
table.insert (out, make_wikilink (services[index][2], services[index][3], no_link)); -- add article wikilink |
|||
if services[index][6] then -- add tail postfix if it exists |
|||
table.insert (out, services[index][6]); |
|||
end |
|||
ulx.url1.tail = table.concat (out, ' '); -- put it all together; result has leading space character |
|||
else -- here when unknown archive |
|||
ulx.url1.service = 'other'; |
|||
tracking = categories.unknown; |
|||
ulx.url1.tail = table.concat ({'', prefixes.at, host, inlineRed (err_warn_msgs.unknown_url, error)}, ' '); |
|||
end |
|||
track[tracking] = 1 |
|||
end |
end |
||
--[[--------------------------< parseExtraArgs >----------------------- |
--[[--------------------------< parseExtraArgs >----------------------- |
||
Parse numbered arguments starting at 2, such as url2..url10, date2..date10, title2..title10 |
Parse numbered arguments starting at 2, such as url2..url10, date2..date10, title2..title10 |
||
For example: {{webarchive |url=.. |url4=.. |url7=..}} |
|||
Three url arguments not in numeric sequence (1..4..7). |
|||
Function only processes arguments numbered 2 or greater (in this case 4 and 7) |
|||
It creates numeric sequenced table entries like: |
|||
urlx.url2.url = <argument value for url4> |
|||
urlx.url3.url = <argument value for url7> |
|||
Returns the number of URL arguments found numbered 2 or greater (in this case returns "2") |
|||
]] |
]] |
||
local function parseExtraArgs( |
local function parseExtraArgs() |
||
local i, j, argurl, argurl2, argdate, argtitle |
|||
j = 2 |
|||
for i = 2, maxurls do |
|||
argurl = "url" .. i |
|||
if trimArg(args[argurl]) then |
|||
argurl2 = "url" .. j |
|||
ulx[argurl2] = {} |
|||
ulx[argurl2]["url"] = args[argurl] |
|||
argdate = "date" .. i |
|||
if trimArg(args[argdate]) then |
|||
ulx[argurl2]["date"] = args[argdate] |
|||
else |
|||
ulx[argurl2]["date"] = inlineRed("[Date missing]", "warning") |
|||
end |
|||
argtitle = "title" .. i |
|||
if trimArg(args[argtitle]) then |
|||
argtitle = "title" .. i |
|||
ulx[argurl2]["title"] = args[argtitle] |
|||
else |
|||
ulx[argurl2]["title"] = args[argtitle] |
|||
ulx[argurl2]["title"] = nil |
|||
else |
|||
end |
|||
ulx[argurl2]["title"] = nil |
|||
j = j + 1 |
|||
end |
|||
end |
|||
end |
|||
end |
|||
if j == 2 then |
|||
return 0 |
|||
else |
|||
return j - 2 |
|||
end |
|||
if j == 2 then |
|||
return 0 |
|||
else |
|||
return j - 2 |
|||
end |
|||
end |
end |
||
--[[--------------------------< comma >----------------------- |
--[[--------------------------< comma >----------------------- |
||
Given a date string, return "," if it's MDY |
Given a date string, return "," if it's MDY |
||
]] |
]] |
||
local function comma(date) |
local function comma(date) |
||
local N = mw.text.split(date, " ") |
|||
return (date and date:match ('%a+ +%d%d?(,) +%d%d%d%d')) or ''; |
|||
local O = mw.text.split(N[1], "-") -- for ISO |
|||
if O[1] == "index" then return "" end |
|||
if not tonumber(O[1]) then |
|||
return "," |
|||
else |
|||
return "" |
|||
end |
|||
end |
end |
||
--[[--------------------------< createTracking >----------------------- |
|||
Return data in track[] ie. tracking categories |
|||
--[[--------------------------< createRendering >----------------------- |
|||
]] |
|||
Return a rendering of the data in ulx[][] |
|||
local function createTracking() |
|||
]] |
|||
local |
local sand = "" |
||
if tableLength(track) > 0 then |
|||
for key,_ in pairs(track) do |
|||
sand = sand .. "[[" .. key .. "]]" |
|||
end |
|||
end |
|||
return sand |
|||
local displayfield |
|||
local out = {}; |
|||
local index_date, msg = ulx.url1.date:match ('(index)(.*)'); -- when ulx.url1.date extract 'index' text and message text (if there is a message) |
|||
ulx.url1.date = ulx.url1.date:gsub ('index.*', 'index'); -- remove message |
|||
if 'none' == ulx.url1.format then -- For {{wayback}}, {{webcite}} |
|||
table.insert (out, '['); -- open extlink markup |
|||
table.insert (out, ulx.url1.url); -- add url |
|||
if ulx.url1.title then |
|||
table.insert (out, ' ') -- the required space |
|||
table.insert (out, ulx.url1.title) -- the title |
|||
table.insert (out, ']'); -- close extlink markup |
|||
table.insert (out, ulx.url1.tail); -- tail text |
|||
if ulx.url1.date then |
|||
table.insert (out, ' ('); -- open date text; TODO: why the html entity? replace with regular space? |
|||
table.insert (out, 'index' == ulx.url1.date and s_text.archive or s_text.archived); -- add text |
|||
table.insert (out, ' '); -- insert a space |
|||
table.insert (out, ulx.url1.date); -- add date |
|||
table.insert (out, ')'); -- close date text |
|||
end |
|||
else -- no title |
|||
if index_date then -- when url date is 'index' |
|||
table.insert (out, table.concat ({' ', s_text.Archive_index, ']'})); -- add the index link label |
|||
table.insert (out, msg or ''); -- add date mismatch message when url date is /*/ and |date= has valid date |
|||
else |
|||
table.insert (out, table.concat ({' ', s_text.Archived, '] '})); -- add link label for url has timestamp date (will include mismatch message if there is one) |
|||
end |
|||
if ulx.url1.date then |
|||
if 'index' ~= ulx.url1.date then |
|||
table.insert (out, ulx.url1.date); -- add date when data is not 'index' |
|||
end |
|||
table.insert (out, comma(ulx.url1.date)); -- add ',' if date format is mdy |
|||
table.insert (out, ulx.url1.tail); -- add tail text |
|||
else -- no date |
|||
table.insert (out, ulx.url1.tail); -- add tail text |
|||
end |
|||
end |
|||
if 0 < ulx.url1.extraurls then -- For multiple archive URLs |
|||
local tot = ulx.url1.extraurls + 1 |
|||
table.insert (out, '.') -- terminate first url |
|||
table.insert (out, table.concat ({' ', s_text.addlarchives, ': '})); -- add header text |
|||
for i=2, tot do -- loop through the additionals |
|||
local index = table.concat ({'url', i}); -- make an index |
|||
displayfield = ulx[index]['title'] and 'title' or 'date'; -- choose display text |
|||
table.insert (out, '['); -- open extlink markup |
|||
table.insert (out, ulx[index]['url']); -- add the url |
|||
table.insert (out, ' '); -- the required space |
|||
table.insert (out, ulx[index][displayfield]); -- add the label |
|||
table.insert (out, ']'); -- close extlink markup |
|||
table.insert (out, i==tot and '.' or ', '); -- add terminator |
|||
end |
|||
end |
|||
return table.concat (out); -- make a big string and done |
|||
else -- For {{cite archives}} |
|||
if 'addlarchives' == ulx.url1.format then -- Multiple archive services |
|||
table.insert (out, table.concat ({s_text.addlarchives, ': '})); -- add header text |
|||
else -- Multiple pages from the same archive |
|||
table.insert (out, table.concat ({s_text.addlpages, ' '})); -- add header text |
|||
table.insert (out, ulx.url1.date); -- add date to header text |
|||
table.insert (out, ': '); -- close header text |
|||
end |
|||
local tot = ulx.url1.extraurls + 1; |
|||
for i=1, tot do -- loop through the additionals |
|||
local index = table.concat ({'url', i}); -- make an index |
|||
table.insert (out, '['); -- open extlink markup |
|||
table.insert (out, ulx[index]['url']); -- add url |
|||
table.insert (out, ' '); -- add required space |
|||
displayfield = ulx[index]['title']; |
|||
if 'addlarchives' == ulx.url1.format then |
|||
if not displayfield then |
|||
displayfield = ulx[index]['date'] |
|||
end |
|||
else -- must be addlpages |
|||
if not displayfield then |
|||
displayfield = table.concat ({s_text.Page, ' ', i}); |
|||
end |
|||
end |
|||
table.insert (out, displayfield); -- add title, date, page label text |
|||
table.insert (out, ']'); -- close extlink markup |
|||
table.insert (out, (i==tot and '.' or ', ')); -- add terminator |
|||
end |
|||
return table.concat (out); -- make a big string and done |
|||
end |
|||
end |
end |
||
--[[--------------------------< createRendering >----------------------- |
|||
Return a rendering of the data in ulx[][] |
|||
--[[--------------------------< P A R A M E T E R _ N A M E _ X L A T E >-------------------------------------- |
|||
]] |
|||
for internaltionalization, translate local-language parameter names to their English equivalents |
|||
local function createRendering() |
|||
TODO: return error message if multiple aliases of the same canonical parameter name are found? |
|||
local sand, displayheader, displayfield |
|||
returns two tables: |
|||
new_args - holds canonical form parameters and their values either from translation or because the parameter was already in canonical form |
|||
origin - maps canonical-form parameter names to their untranslated (local language) form for error messaging in the local language |
|||
local period1 = "" -- For backwards compat with {{wayback}} |
|||
unrecognized parameters are ignored |
|||
local period2 = "." |
|||
local indexstr = "" |
|||
if ulx.url1.date == "index" then |
|||
indexstr = "archive" |
|||
end |
|||
-- For {{wayback}}, {{webcite}} |
|||
if ulx.url1.format == "none" then |
|||
]] |
|||
if not ulx.url1.title and not ulx.url1.date then -- No title. No date |
|||
sand = "[" .. ulx.url1.url .. " Arkiveret]" .. ulx.url1.tail |
|||
elseif not ulx.url1.title and ulx.url1.date then -- No title. Date. |
|||
if ulx.url1.service == "wayback" then |
|||
period1 = "" |
|||
-- ofte et punktum for meget, når IABot indsætter skabelonen: |
|||
-- period1 = "." |
|||
period2 = "" |
|||
end |
|||
sand = "[" .. ulx.url1.url .. " Arkiveret] " .. ulx.url1.date .. comma(ulx.url1.date) .. " hos " .. ulx.url1.tail .. period1 |
|||
elseif ulx.url1.title and not ulx.url1.date then -- Title. No date. |
|||
sand = " hos [" .. ulx.url1.url .. " " .. ulx.url1.title .. "]" .. ulx.url1.tail |
|||
elseif ulx.url1.title and ulx.url1.date then -- Title. Date. |
|||
sand = "[" .. ulx.url1.url .. " " .. ulx.url1.title .. "] arkiveret hos " .. ulx.url1.tail .. " (" .. indexstr .. "" .. ulx.url1.date .. ")" |
|||
else |
|||
return nil |
|||
end |
|||
if ulx.url1.extraurls > 0 then -- For multiple archive URLs |
|||
local tot = ulx.url1.extraurls + 1 |
|||
sand = sand .. period2 .. " Additional archives: " |
|||
for i=2,tot do |
|||
local indx = "url" .. i |
|||
if ulx[indx]["title"] then |
|||
displayfield = "title" |
|||
else |
|||
displayfield = "date" |
|||
end |
|||
sand = sand .. "[" .. ulx[indx]["url"] .. " " .. ulx[indx][displayfield] .. "]" |
|||
if i == tot then |
|||
sand = sand .. "." |
|||
else |
|||
sand = sand .. ", " |
|||
end |
|||
end |
|||
else |
|||
return sand |
|||
end |
|||
return sand |
|||
-- For {{cite archives}} |
|||
else |
|||
local function parameter_name_xlate (args, params, enum_params) |
|||
if ulx.url1.format == "addlarchives" then -- Multiple archive services |
|||
local name; -- holds modifiable name of the parameter name during evaluation |
|||
displayheader = "Additional archives: " |
|||
local enum; -- for enumerated parameters, holds the enumerator during evaluation |
|||
else -- Multiple pages from the same archive |
|||
local found = false; -- flag used to break out of nested for loops |
|||
displayheader = "Additional pages archived on " .. ulx.url1.date .. ": " |
|||
local new_args = {}; -- a table that holds canonical and translated parameter k/v pairs |
|||
end |
|||
local origin = {}; -- a table that maps original (local language) parameter names to their canonical name for local language error messaging |
|||
local tot = 1 + ulx.url1.extraurls |
|||
local unnamed_params; -- set true when unsupported positional parameters are detected |
|||
local sand = displayheader |
|||
for i=1,tot do |
|||
for k, v in pairs (args) do -- loop through all of the arguments in the args table |
|||
local indx = "url" .. i |
|||
name = k; -- copy of original parameter name |
|||
displayfield = ulx[indx]["title"] |
|||
if ulx.url1.format == "addlarchives" then |
|||
if not displayfield then |
|||
if non_western_digits then -- true when non-western digits supported at this wiki |
|||
displayfield = ulx[indx]["date"] |
|||
name = mw.ustring.gsub (name, '%d', digits); -- convert this wiki's non-western digits to western digits |
|||
end |
|||
else |
|||
if not displayfield then |
|||
enum = name:match ('%d+$'); -- get parameter enumerator if it exists; nil else |
|||
displayfield = "Page " .. i |
|||
end |
|||
if not enum then -- no enumerator so looking for non-enumnerated parameters |
|||
end |
|||
-- TODO: insert shortcut here? if params[name] then name holds the canonical parameter name; no need to search further |
|||
sand = sand .. "[" .. ulx[indx]["url"] .. " " .. displayfield .. "]" |
|||
for pname, aliases in pairs (params) do -- loop through each parameter the params table |
|||
if i == tot then |
|||
for _, alias in ipairs (aliases) do -- loop through each alias in the parameter's aliases table |
|||
sand = sand .. "." |
|||
if name == alias then |
|||
else |
|||
new_args[pname] = v; -- create a new entry in the new_args table |
|||
sand = sand .. ", " |
|||
origin [pname] = k; -- create an entry to make canonical parameter name to original local language parameter name |
|||
end |
|||
found = true; -- flag so that we can break out of these nested for loops |
|||
end |
|||
break; -- no need to search the rest of the aliases table for name so go on to the next k, v pair |
|||
return sand |
|||
end |
|||
end |
|||
if found then -- true when we found an alias that matched name |
|||
found = false; -- reset the flag |
|||
break; -- go do next args k/v pair |
|||
end |
|||
end |
|||
else -- enumerated parameters |
|||
name = name:gsub ('%d$', '#'); -- replace enumeration digits with place holder for table search |
|||
-- TODO: insert shortcut here? if num_params[name] then name holds the canonical parameter name; no need to search further |
|||
for pname, aliases in pairs (enum_params) do -- loop through each parameter the num_params table |
|||
for _, alias in ipairs (aliases) do -- loop through each alias in the parameter's aliases table |
|||
if name == alias then |
|||
pname = pname:gsub ('#$', enum); -- replace the '#' place holder with the actual enumerator |
|||
new_args[pname] = v; -- create a new entry in the new_args table |
|||
origin [pname] = k; -- create an entry to make canonical parameter name to original local language parameter name |
|||
found = true; -- flag so that we can break out of these nested for loops |
|||
break; -- no need to search the rest of the aliases table for name so go on to the next k, v pair |
|||
end |
|||
end |
|||
if found then -- true when we found an alias that matched name |
|||
found = false; -- reset the flag |
|||
break; -- go do next args k/v pair |
|||
end |
|||
end |
|||
end |
|||
else |
|||
unnamed_params = true; -- flag for unsupported positional parameters |
|||
end |
|||
end -- for k, v |
|||
return new_args, origin, unnamed_params; |
|||
end |
end |
||
function p.webarchive(frame) |
|||
args = frame.args |
|||
if (args[1]==nil) and (args["url"]==nil) then -- if no argument provided than check parent template/module args |
|||
args = frame:getParent().args |
|||
end |
|||
local tname = "Webarchive" -- name of calling template. Change if template rename. |
|||
ulx = {} -- Associative array to hold template data |
|||
track = {} -- Associative array to hold tracking categories |
|||
maxurls = 10 -- Max number of URLs allowed. |
|||
local verifydates = "no" -- Sat til "no", for at undgå fejlmelding ved dansk datoformat |
|||
-- URL argument (first) |
|||
--[[--------------------------< W E B A R C H I V E >---------------------------------------------------------- |
|||
local url1 = trimArg(args.url) or trimArg(args.url1) |
|||
template entry point |
|||
if not url1 then |
|||
return inlineError("url", "Empty.") .. createTracking() |
|||
end |
|||
if mw.ustring.find( url1, "https://web.http", 1, plain ) then -- track bug |
|||
track["Kategori:Webarchive-skabelon fejl"] = 1 |
|||
return inlineError("url", "https://web.http") .. createTracking() |
|||
end |
|||
ulx.url1 = {} |
|||
]] |
|||
ulx.url1.url = url1 |
|||
local uri1 = mw.uri.new(ulx.url1.url) |
|||
ulx.url1.host = uri1.host |
|||
ulx.url1.extraurls = parseExtraArgs() |
|||
-- Nolink argument |
|||
local function webarchive(frame) |
|||
local args = getArgs (frame); |
|||
local nolink = trimArg2(args.nolink) |
|||
local data = mw.loadData (table.concat ({ -- make a data module name; sandbox or live |
|||
'Module:Webarchive/data', |
|||
frame:getTitle():find('sandbox', 1, true) and '/sandbox' or '' -- this instance is ./sandbox then append /sandbox |
|||
})); |
|||
categories = data.categories; -- fill in the forward declarations |
|||
config = data.config; |
|||
if data.digits.enable then |
|||
digits = data.digits; -- for i18n; table of digits in the local wiki's language |
|||
non_western_digits = true; -- use_non_western_digits |
|||
end |
|||
err_warn_msgs = data.err_warn_msgs; |
|||
excepted_pages = data.excepted_pages; |
|||
month_num = data.month_num; -- for i18n; table of month names in the local wiki's language |
|||
prefixes = data.prefixes; |
|||
services = data.services; |
|||
s_text = data.s_text; |
|||
uncategorized_namespaces = data.uncategorized_namespaces; |
|||
uncategorized_subpages = data.uncategorized_subpages; |
|||
serviceName(uri1.host, nolink) |
|||
local origin = {}; -- holds a map of English to local language parameter names used in the current template; not currently used |
|||
local unnamed_params; -- boolean set to true when template call has unnamed parameters |
|||
args, origin, unnamed_params = parameter_name_xlate (args, data.params, data.enum_params); -- translate parameter names in args to English |
|||
-- Date argument |
|||
local date, format, msg, udate, uri, url; |
|||
local ldf = 'iso'; -- when there is no |date= parameter, render url dates in iso format |
|||
if args.url and args.url1 then -- URL argument (first) |
|||
return inlineError (data.crit_err_msgs.conflicting, {origin.url, origin.url1}); |
|||
end |
|||
url = args.url or args.url1; |
|||
if not url then |
|||
return inlineError (data.crit_err_msgs.empty); |
|||
end |
|||
-- these iabot bugs perportedly fixed; removing these causes lua script error |
|||
--[[ -- at Template:Webarchive/testcases/Production; resolve that before deleting these tests |
|||
if mw.ustring.find( url, "https://web.http", 1, true ) then -- track bug - TODO: IAbot bug; not known if the bug has been fixed; deferred |
|||
track[categories.error] = 1; |
|||
return inlineError (data.crit_err_msgs.iabot1); |
|||
end |
|||
if url == "https://web.archive.org/http:/" then -- track bug - TODO: IAbot bug; not known if the bug has been fixed; deferred |
|||
track[categories.error] = 1; |
|||
return inlineError (data.crit_err_msgs.iabot2); |
|||
end |
|||
]] |
|||
local date = trimArg(args.date) or trimArg(args.date1) |
|||
if not (url:lower():find ('^http') or url:find ('^//')) then |
|||
if date == "*" and ulx.url1.service == "wayback" then |
|||
return inlineError (data.crit_err_msgs.invalid_url ); |
|||
date = "index" |
|||
end |
|||
elseif date and ulx.url1.service == "wayback" and verifydates == "yes" then |
|||
local ldf = dateFormat(date) |
|||
if ldf then |
|||
local udate = decodeWaybackDate( uri1.path, ldf ) |
|||
if udate ~= date then |
|||
date = udate .. inlineRed("<sup>[Date mismatch]</sup>", "warning") |
|||
end |
|||
end |
|||
elseif date and ulx.url1.service == "webcite" and verifydates == "yes" then |
|||
local ldf = dateFormat(date) |
|||
if ldf then |
|||
local udate = decodeWebciteDate( uri1.path, ldf ) |
|||
if udate == "query" then -- skip |
|||
elseif udate ~= date then |
|||
date = udate .. inlineRed("<sup>[Date mismatch]</sup>", "warning") |
|||
end |
|||
end |
|||
elseif not date and ulx.url1.service == "wayback" then |
|||
date = decodeWaybackDate( uri1.path, "iso" ) |
|||
if not date then |
|||
date = inlineRed("[Date error] (1)", "error") |
|||
end |
|||
elseif not date and ulx.url1.service == "webcite" then |
|||
date = decodeWebciteDate( uri1.path, "iso" ) |
|||
if date == "query" then |
|||
date = inlineRed("[Date missing]", "warning") |
|||
elseif not date then |
|||
date = inlineRed("[Date error] (1)", "error") |
|||
end |
|||
elseif not date then |
|||
date = inlineRed("[Date missing]", "warning") |
|||
end |
|||
ulx.url1.date = date |
|||
-- Format argument |
|||
ulx.url1 = {} |
|||
ulx.url1.url = url |
|||
local format = trimArg(args.format) |
|||
ulx.url1.extraurls = parseExtraArgs(args) |
|||
if not format then |
|||
format = "none" |
|||
else |
|||
if format == "addlpages" then |
|||
if not ulx.url1.date then |
|||
format = "none" |
|||
end |
|||
elseif format == "addlarchives" then |
|||
format = "addlarchives" |
|||
else |
|||
format = "none" |
|||
end |
|||
end |
|||
ulx.url1.format = format |
|||
-- Title argument |
|||
local good = false; |
|||
good, uri = pcall (mw.uri.new, ulx.url1.url); -- get a table of uri parts from this url; protected mode to prevent lua error when ulx.url1.url is malformed |
|||
if not good or nil == uri.host then -- abandon when ulx.url1.url is malformed |
|||
return inlineError (data.crit_err_msgs.invalid_url); |
|||
end |
|||
serviceName(uri.host, args.nolink) |
|||
local title = trimArg(args.title) or trimArg(args.title1) |
|||
if args.date and args.date1 then -- Date argument |
|||
ulx.url1.title = title |
|||
return inlineError (data.crit_err_msgs.conflicting, {origin.date, origin.date1}); |
|||
end |
|||
date = args.date or args.date1; |
|||
date = date and date:gsub (' +', ' '); -- replace multiple spaces with a single space |
|||
local rend = createRendering() |
|||
if date and config.verifydates then |
|||
if not rend then |
|||
rend = '<span style="font-size:100%" class="error citation-comment">Error in [[:Template:' .. tname .. ']]: Unknown problem. Please report on template talk page.</span>' |
|||
date = 'index'; |
|||
track["Kategori:Webarchive-skabelon fejl"] = 1 |
|||
ldf = 'iso'; -- set to default format |
|||
end |
|||
elseif 'mdy' == date then |
|||
date = nil; -- if date extracted from URL, |
|||
ldf = 'mdy'; -- then |date=mdy overrides iso |
|||
elseif 'dmy' == date then |
|||
date = nil; -- if date extracted from URL, |
|||
ldf = 'dmy'; -- then |date=dmy overrides iso |
|||
elseif 'ymd' == date then |
|||
date = nil; -- if date extracted from URL, |
|||
ldf = 'ymd'; -- then |date=ymd overrides iso |
|||
else |
|||
date, ldf = decode_date (date); -- get an iso format date from date and get date's original format |
|||
end |
|||
end |
|||
return rend .. createTracking() |
|||
if 'wayback' == ulx.url1.service or 'locwebarchives' == ulx.url1.service or 'ukgwa' == ulx.url1.service then |
|||
if date then |
|||
if config.verifydates then |
|||
if ldf then |
|||
udate, msg = decodeWaybackDate (uri.path); -- get the url date in iso format and format of date in |date=; 'index' when wayback url date is * |
|||
if not udate then -- this is the only 'fatal' error return |
|||
return inlineError (data.crit_err_msgs[msg]); |
|||
end |
|||
if udate ~= date then -- date comparison using iso format dates |
|||
date = udate; |
|||
msg = table.concat ({ |
|||
inlineRed (err_warn_msgs.mismatch, 'warning'), -- add warning message |
|||
msg, -- add message if there is one |
|||
}); |
|||
end |
|||
end |
|||
end |
|||
else -- no |date= |
|||
udate, msg = decodeWaybackDate (uri.path); |
|||
if not udate then -- this is the only 'fatal' error return |
|||
return inlineError (data.crit_err_msgs[msg]); |
|||
end |
|||
if '' == udate then |
|||
date = nil; -- unset |
|||
else |
|||
date = udate; |
|||
end |
|||
end |
|||
elseif 'webcite' == ulx.url1.service then |
|||
if date then |
|||
if config.verifydates then |
|||
if ldf then |
|||
udate = decodeWebciteDate (uri.path); -- get the url date in iso format |
|||
if 'query' ~= udate then -- skip if query |
|||
if udate ~= date then -- date comparison using iso format dates |
|||
date = udate; |
|||
msg = table.concat ({ |
|||
inlineRed (err_warn_msgs.mismatch, 'warning'), |
|||
}); |
|||
end |
|||
end |
|||
end |
|||
end |
|||
else |
|||
date = decodeWebciteDate( uri.path, "iso" ) |
|||
if date == "query" then |
|||
date = nil; -- unset |
|||
msg = inlineRed (err_warn_msgs.date_miss, 'warning'); |
|||
elseif not date then -- invalid base62 string |
|||
date = inlineRed (err_warn_msgs.date1, 'error'); |
|||
end |
|||
end |
|||
elseif 'archiveis' == ulx.url1.service then |
|||
if date then |
|||
if config.verifydates then |
|||
if ldf then |
|||
udate, msg = decodeArchiveisDate (uri.path) -- get the url date in iso format |
|||
if 'short link' ~= udate then -- skip if short link |
|||
if udate ~= date then -- date comparison using iso format dates |
|||
date = udate; |
|||
msg = table.concat ({ |
|||
inlineRed (err_warn_msgs.mismatch, 'warning'), -- add warning message |
|||
msg, -- add message if there is one |
|||
}); |
|||
end |
|||
end |
|||
end |
|||
end |
|||
else -- no |date= |
|||
udate, msg = decodeArchiveisDate( uri.path, "iso" ) |
|||
if udate == "short link" then |
|||
date = nil; -- unset |
|||
msg = inlineRed (err_warn_msgs.date_miss, 'warning'); |
|||
elseif '' == udate then |
|||
date = nil; -- unset |
|||
else |
|||
date = udate; |
|||
end |
|||
end |
|||
else -- some other service |
|||
if not date then |
|||
msg = inlineRed (err_warn_msgs.date_miss, 'warning'); |
|||
end |
|||
end |
|||
if 'index' == date then |
|||
ulx.url1.date = date .. (msg or ''); -- create index + message (if there is one) |
|||
elseif date then |
|||
ulx.url1.date = makeDate (date, nil, nil, ldf) .. (msg or ''); -- create a date in the wiki's local language + message (if there is one) |
|||
else |
|||
ulx.url1.date = msg; |
|||
end |
|||
format = args.format; -- Format argument |
|||
if not format then |
|||
format = "none" |
|||
else |
|||
for k, v in pairs (data.format_vals) do -- |format= accepts two specific values loop through a table of those values |
|||
local found; -- declare a nil flag |
|||
for _, p in ipairs (v) do -- loop through local language variants |
|||
if format == p then -- when |format= value matches |
|||
format = k; -- use name from table key |
|||
found = true; -- declare found so that we can break out of outer for loop |
|||
break; -- break out of inner for loop |
|||
end |
|||
end |
|||
if found then |
|||
break; |
|||
end |
|||
end |
|||
if format == "addlpages" then |
|||
if not ulx.url1.date then |
|||
format = "none" |
|||
end |
|||
elseif format == "addlarchives" then |
|||
format = "addlarchives" |
|||
else |
|||
format = "none" |
|||
end |
|||
end |
|||
ulx.url1.format = format |
|||
if args.title and args.title1 then -- Title argument |
|||
return inlineError (data.crit_err_msgs.conflicting, {origin.title, origin.title1}); |
|||
end |
|||
ulx.url1.title = args.title or args.title1; |
|||
local rend = createRendering() |
|||
if not rend then |
|||
return inlineError (data.crit_err_msgs.unknown); |
|||
end |
|||
return rend .. ((unnamed_params and inlineRed (err_warn_msgs.unnamed_params, 'warning')) or '') .. createTracking(); |
|||
end |
end |
||
return p |
|||
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------ |
|||
]] |
|||
return {webarchive = webarchive}; |
Sideversjonen fra 26. apr. 2024 kl. 17:07
Dokumentasjon for denne modulen kan opprettes på Modul:Webarchive/dok
--[[ ---------------------------------- Lua module implementing the {{webarchive}} template. A merger of the functionality of three templates: {{wayback}}, {{webcite}} and {{cite archives}} ]] local p = {} --[[--------------------------< inlineError >----------------------- Critical error. Render output completely in red. Add to tracking category. ]] local function inlineError(arg, msg) track["Kategori:Webarchive-skabelon fejl"] = 1 return '<span style="font-size:100%" class="error citation-comment">Error in webarchive template: Check <code style="color:inherit; border:inherit; padding:inherit;">|' .. arg .. '=</code> value. ' .. msg .. '</span>' end --[[--------------------------< inlineRed >----------------------- Render a text fragment in red, such as a warning as part of the final output. Add tracking category. ]] local function inlineRed(msg, trackmsg) if trackmsg == "warning" then track["Kategori:Webarchive-skabelon advarsler"] = 1 elseif trackmsg == "error" then track["Kategori:Webarchive-skabelon fejl"] = 1 end return '<span style="font-size:100%" class="error citation-comment">' .. msg .. '</span>' end --[[--------------------------< trimArg >----------------------- trimArg returns nil if arg is "" while trimArg2 returns 'true' if arg is "" trimArg2 is for args that might accept an empty value, as an on/off switch like nolink= ]] local function trimArg(arg) if arg == "" or arg == nil then return nil else return mw.text.trim(arg) end end local function trimArg2(arg) if arg == nil then return nil else return mw.text.trim(arg) end end --[[--------------------------< base62 >----------------------- Convert base-62 to base-10 Credit: 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 -- How comes? r = 1 break -- for i end r = r + c * k k = k * 62 end -- for i end return r end --[[--------------------------< tableLength >----------------------- Given a 1-D table, return number of elements ]] local function tableLength(T) local count = 0 for _ in pairs(T) do count = count + 1 end return count end --[[--------------------------< dateFormat >----------------------- Given a date string, return its format: dmy, mdy, iso, ymd If unable to determine return nil ]] local function dateFormat(date) local dt = {} dt.split = {} dt.split = mw.text.split(date, "-") if tableLength(dt.split) == 3 then if tonumber(dt.split[1]) > 1900 and tonumber(dt.split[1]) < 2200 and tonumber(dt.split[2]) and tonumber(dt.split[3]) then return "iso" else return nil end end dt.split = mw.text.split(date, " ") if tableLength(dt.split) == 3 then if tonumber(dt.split[3]) then if tonumber(dt.split[3]) > 1900 and tonumber(dt.split[3]) < 2200 then if tonumber(dt.split[1]) then return "dmy" else return "mdy" end else if tonumber(dt.split[1]) then if tonumber(dt.split[1]) > 1900 and tonumber(dt.split[1]) < 2200 then return "ymd" end end end end end return nil end --[[--------------------------< makeDate >----------------------- Given a zero-padded 4-digit year, 2-digit month and 2-digit day, return a full date in df format df = mdy, dmy, iso, ymd ]] local function makeDate(year, month, day, df) if not year or year == "" or not month or month == "" or not day or day == "" then return nil end local zmonth = month -- month with leading 0 month = month:match("0*(%d+)") -- month without leading 0 if tonumber(month) < 1 or tonumber(month) > 12 then return year end local nmonth = os.date("%B", os.time{year=2000, month=month, day=1} ) -- month in name form if not nmonth then return year end local zday = day day = zday:match("0*(%d+)") if tonumber(day) < 1 or tonumber(day) > 31 then if df == "mdy" or df == "dmy" then return nmonth .. " " .. year elseif df == "iso" then return year .. "-" .. zmonth elseif df == "ymd" then return year .. " " .. nmonth else return nmonth .. " " .. year end end if df == "mdy" then return nmonth .. " " .. day .. ", " .. year -- September 1, 2016 elseif df == "dmy" then return day .. " " .. nmonth .. " " .. year -- 1 September 2016 elseif df == "iso" then return year .. "-" .. zmonth .. "-" .. zday -- 2016-09-01 elseif df == "ymd" then return year .. " " .. nmonth .. " " .. cday -- 2016 September 1 else return nmonth .. " " .. day .. ", " .. year -- September 1, 2016 end end --[[--------------------------< decodeWebciteDate >----------------------- Given a URI-path to Webcite (eg. /67xHmVFWP) return the encoded date in df format ]] local function decodeWebciteDate(path, df) local dt = {} dt.split = {} dt.split = mw.text.split(path, "/") -- valid URL formats that are not base62 -- http://www.webcitation.org/query?id=1138911916587475 -- http://www.webcitation.org/1138911916587475 -- http://www.webcitation.org/cache/73e53dd1f16cf8c5da298418d2a6e452870cf50e if dt.split[2] == "query" or dt.split[2] == "cache" or tonumber(dt.split[2]) then return "query" end dt.full = os.date("%Y %m %d", string.sub(string.format("%d", base62(dt.split[2])),1,10) ) dt.split = mw.text.split(dt.full, " ") dt.year = dt.split[1] dt.month = dt.split[2] dt.day = dt.split[3] if not tonumber(dt.year) or not tonumber(dt.month) or not tonumber(dt.day) then return inlineRed("[Date error] (1)", "error") end if tonumber(dt.month) > 12 or tonumber(dt.day) > 31 or tonumber(dt.month) < 1 then return inlineRed("[Date error] (2)", "error") end if tonumber(dt.year) > tonumber(os.date("%Y")) or tonumber(dt.year) < 1900 then return inlineRed("[Date error] (3)", "error") end fulldate = makeDate(dt.year, dt.month, dt.day, df) if not fulldate then return inlineRed("[Date error] (4)", "error") else return fulldate end end --[[--------------------------< snapDateToString >----------------------- Given a URI-path to Wayback (eg. /web/20160901010101/http://example.com ) return the formatted date eg. "September 1, 2016" in df format Handle non-digits in snapshot ID such as "re_" and "-" and "*" ]] local function decodeWaybackDate(path, df) local snapdate, snapdatelong, currdate, fulldate local safe = path snapdate = string.gsub(safe, "^/w?e?b?/?", "") -- Remove leading "/web/" or "/" safe = snapdate local N = mw.text.split(safe, "/") snapdate = N[1] if snapdate == "*" then -- eg. /web/*/http.. return "index" end safe = snapdate snapdate = string.gsub(safe, "[a-z][a-z]_[0-9]?$", "") -- Remove any trailing "re_" from date safe = snapdate snapdate = string.gsub(safe, "[-]", "") -- Remove dashes from date eg. 2015-01-01 safe = snapdate snapdate = string.gsub(safe, "[*]$", "") -- Remove trailing "*" if not tonumber(snapdate) then return inlineRed("[Date error] (2)", "error") end local dlen = string.len(snapdate) if dlen < 4 then return inlineRed("[Date error] (3)", "error") end if dlen < 14 then snapdatelong = snapdate .. string.rep("0", 14 - dlen) else snapdatelong = snapdate end local year = string.sub(snapdatelong, 1, 4) local month = string.sub(snapdatelong, 5, 6) local day = string.sub(snapdatelong, 7, 8) if not tonumber(year) or not tonumber(month) or not tonumber(day) then return inlineRed("[Date error] (4)", "error") end if tonumber(month) > 12 or tonumber(day) > 31 or tonumber(month) < 1 then return inlineRed("[Date error] (5)", "error") end currdate = os.date("%Y") if tonumber(year) > tonumber(currdate) or tonumber(year) < 1900 then return inlineRed("[Date error] (6)", "error") end fulldate = makeDate(year, month, day, df) if not fulldate then return inlineRed("[Date error] (7)", "error") else return fulldate end end --[[--------------------------< serviceName >----------------------- Given a domain extracted by mw.uri.new() (eg. web.archive.org) set tail string and service ID ]] local function serviceName(host, nolink) local tracking = "Kategori:Sider med Webarchive-skabelon som henviser til andre arkiver" local bracketopen = "[[" local bracketclose = "]]" if nolink then bracketopen = "" bracketclose = "" end ulx.url1.service = "other" ulx.url1.tail =" hos " .. ulx.url1.host .. " " .. inlineRed("Error: unknown archive URL") if mw.ustring.find( host, "archive.org", 1, plain ) then ulx.url1.service = "wayback" ulx.url1.tail = " " .. bracketopen .. "Wayback Machine" .. bracketclose tracking = "Kategori:Sider med Webarchive-skabelon som henviser til Wayback Machine" elseif mw.ustring.find( host, "webcitation.org", 1, plain ) then ulx.url1.service = "webcite" ulx.url1.tail = " " .. bracketopen .. "WebCite" .. bracketclose tracking = "Kategori:Sider med Webarchive-skabelon som henviser til webcite" elseif mw.ustring.find( host, "archive.is", 1, plain ) then ulx.url1.service = "archiveis" ulx.url1.tail ="" .. bracketopen .. "Archive.is" .. bracketclose tracking = "Kategori:Sider med Webarchive-skabelon som henviser til archiveis" elseif mw.ustring.find( host, "archive.fo", 1, plain ) then ulx.url1.service = "archiveis" ulx.url1.tail =" hos " .. bracketopen .. "Archive.is" .. bracketclose tracking = "Kategori:Sider med Webarchive-skabelon som henviser til archiveis" elseif mw.ustring.find( host, "archive.today", 1, plain ) then ulx.url1.service = "archiveis" ulx.url1.tail =" hos " .. bracketopen .. "Archive.is" .. bracketclose tracking = "Kategori:Sider med Webarchive-skabelon som henviser til archiveis" elseif mw.ustring.find( host, "archive[-]it.org", 1, plain ) then ulx.url1.service = "archiveit" ulx.url1.tail =" hos " .. bracketopen .. "Archive-It" .. bracketclose elseif mw.ustring.find( host, "arquivo.pt", 1, plain) then ulx.url1.tail = " hos " .. "Portugese Web Archive" elseif mw.ustring.find( host, "loc.gov", 1, plain ) then ulx.url1.tail = " hos " .. bracketopen .. "Library of Congress" .. bracketclose elseif mw.ustring.find( host, "webharvest.gov", 1, plain ) then ulx.url1.tail = " hos " .. bracketopen .. "National Archives and Records Administration" .. bracketclose elseif mw.ustring.find( host, "bibalex.org", 1, plain ) then ulx.url1.tail =" hos " .. "[[Bibliotheca_Alexandrina#Internet_Archive_partnership|Bibliotheca Alexandrina]]" elseif mw.ustring.find( host, "collectionscanada", 1, plain ) then ulx.url1.tail = " hos " .. "Canadian Government Web Archive" elseif mw.ustring.find( host, "haw.nsk", 1, plain ) then ulx.url1.tail = " hos " .. "Croatian Web Archive (HAW)" elseif mw.ustring.find( host, "nlib.ee", 1, plain ) then ulx.url1.tail = " hos " .. "Estonian Web Archive" elseif mw.ustring.find( host, "vefsafn.is", 1, plain ) then ulx.url1.tail = " hos " .. "[[National and University Library of Iceland]]" elseif mw.ustring.find( host, "proni.gov", 1, plain ) then ulx.url1.tail = " hos " .. bracketopen .. "Public Record Office of Northern Ireland" .. bracketclose elseif mw.ustring.find( host, "uni[-]lj.si", 1, plain ) then ulx.url1.tail = " hos " .. "Slovenian Web Archive" elseif mw.ustring.find( host, "stanford.edu", 1, plain ) then ulx.url1.tail = " hos " .. "[[Stanford University Libraries|Stanford Web Archive]]" elseif mw.ustring.find( host, "nationalarchives.gov.uk", 1, plain ) then ulx.url1.tail = " hos " .. bracketopen .. "UK Government Web Archive" .. bracketclose elseif mw.ustring.find( host, "parliament.uk", 1, plain ) then ulx.url1.tail = " hos " .. bracketopen .. "UK Parliament's Web Archive" .. bracketclose elseif mw.ustring.find( host, "webarchive.org.uk", 1, plain ) then ulx.url1.tail = " hos " .. bracketopen .. "UK Web Archive" .. bracketclose elseif mw.ustring.find( host, "nlb.gov.sg", 1, plain ) then ulx.url1.tail =" hos " .. "Web Archive Singapore" elseif mw.ustring.find( host, "nlb.gov.sg", 1, plain ) then ulx.url1.tail =" hos " .. "Web Archive Singapore" elseif mw.ustring.find( host, "screenshots.com", 1, plain ) then ulx.url1.tail =" hos " .. "Screenshots" elseif mw.ustring.find( host, "wikiwix.com", 1, plain ) then ulx.url1.tail =" hos " .. "Wikiwix" elseif mw.ustring.find( host, "perma.cc", 1, plain ) then ulx.url1.tail =" hos " .. bracketopen .. "Perma.cc" .. bracketclose else tracking = "Kategori:Sider med Webarchive-skabelon som henviser til ukendte arkiver" end track[tracking] = 1 end --[[--------------------------< parseExtraArgs >----------------------- Parse numbered arguments starting at 2, such as url2..url10, date2..date10, title2..title10 For example: {{webarchive |url=.. |url4=.. |url7=..}} Three url arguments not in numeric sequence (1..4..7). Function only processes arguments numbered 2 or greater (in this case 4 and 7) It creates numeric sequenced table entries like: urlx.url2.url = <argument value for url4> urlx.url3.url = <argument value for url7> Returns the number of URL arguments found numbered 2 or greater (in this case returns "2") ]] local function parseExtraArgs() local i, j, argurl, argurl2, argdate, argtitle j = 2 for i = 2, maxurls do argurl = "url" .. i if trimArg(args[argurl]) then argurl2 = "url" .. j ulx[argurl2] = {} ulx[argurl2]["url"] = args[argurl] argdate = "date" .. i if trimArg(args[argdate]) then ulx[argurl2]["date"] = args[argdate] else ulx[argurl2]["date"] = inlineRed("[Date missing]", "warning") end argtitle = "title" .. i if trimArg(args[argtitle]) then ulx[argurl2]["title"] = args[argtitle] else ulx[argurl2]["title"] = nil end j = j + 1 end end if j == 2 then return 0 else return j - 2 end end --[[--------------------------< comma >----------------------- Given a date string, return "," if it's MDY ]] local function comma(date) local N = mw.text.split(date, " ") local O = mw.text.split(N[1], "-") -- for ISO if O[1] == "index" then return "" end if not tonumber(O[1]) then return "," else return "" end end --[[--------------------------< createTracking >----------------------- Return data in track[] ie. tracking categories ]] local function createTracking() 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() local sand, displayheader, displayfield local period1 = "" -- For backwards compat with {{wayback}} local period2 = "." local indexstr = "" if ulx.url1.date == "index" then indexstr = "archive" end -- For {{wayback}}, {{webcite}} if ulx.url1.format == "none" then if not ulx.url1.title and not ulx.url1.date then -- No title. No date sand = "[" .. ulx.url1.url .. " Arkiveret]" .. ulx.url1.tail elseif not ulx.url1.title and ulx.url1.date then -- No title. Date. if ulx.url1.service == "wayback" then period1 = "" -- ofte et punktum for meget, når IABot indsætter skabelonen: -- period1 = "." period2 = "" end sand = "[" .. ulx.url1.url .. " Arkiveret] " .. ulx.url1.date .. comma(ulx.url1.date) .. " hos " .. ulx.url1.tail .. period1 elseif ulx.url1.title and not ulx.url1.date then -- Title. No date. sand = " hos [" .. ulx.url1.url .. " " .. ulx.url1.title .. "]" .. ulx.url1.tail elseif ulx.url1.title and ulx.url1.date then -- Title. Date. sand = "[" .. ulx.url1.url .. " " .. ulx.url1.title .. "] arkiveret hos " .. ulx.url1.tail .. " (" .. indexstr .. "" .. ulx.url1.date .. ")" else return nil end if ulx.url1.extraurls > 0 then -- For multiple archive URLs local tot = ulx.url1.extraurls + 1 sand = sand .. period2 .. " Additional archives: " for i=2,tot do local indx = "url" .. i if ulx[indx]["title"] then displayfield = "title" else displayfield = "date" end sand = sand .. "[" .. ulx[indx]["url"] .. " " .. ulx[indx][displayfield] .. "]" if i == tot then sand = sand .. "." else sand = sand .. ", " end end else return sand end return sand -- For {{cite archives}} else if ulx.url1.format == "addlarchives" then -- Multiple archive services displayheader = "Additional archives: " else -- Multiple pages from the same archive displayheader = "Additional pages archived on " .. ulx.url1.date .. ": " end local tot = 1 + ulx.url1.extraurls local sand = displayheader for i=1,tot do local indx = "url" .. i displayfield = ulx[indx]["title"] if ulx.url1.format == "addlarchives" then if not displayfield then displayfield = ulx[indx]["date"] end else if not displayfield then displayfield = "Page " .. i end end sand = sand .. "[" .. ulx[indx]["url"] .. " " .. displayfield .. "]" if i == tot then sand = sand .. "." else sand = sand .. ", " end end return sand end end function p.webarchive(frame) args = frame.args if (args[1]==nil) and (args["url"]==nil) then -- if no argument provided than check parent template/module args args = frame:getParent().args end local tname = "Webarchive" -- name of calling template. Change if template rename. ulx = {} -- Associative array to hold template data track = {} -- Associative array to hold tracking categories maxurls = 10 -- Max number of URLs allowed. local verifydates = "no" -- Sat til "no", for at undgå fejlmelding ved dansk datoformat -- URL argument (first) local url1 = trimArg(args.url) or trimArg(args.url1) if not url1 then return inlineError("url", "Empty.") .. createTracking() end if mw.ustring.find( url1, "https://web.http", 1, plain ) then -- track bug track["Kategori:Webarchive-skabelon fejl"] = 1 return inlineError("url", "https://web.http") .. createTracking() end ulx.url1 = {} ulx.url1.url = url1 local uri1 = mw.uri.new(ulx.url1.url) ulx.url1.host = uri1.host ulx.url1.extraurls = parseExtraArgs() -- Nolink argument local nolink = trimArg2(args.nolink) serviceName(uri1.host, nolink) -- Date argument local date = trimArg(args.date) or trimArg(args.date1) if date == "*" and ulx.url1.service == "wayback" then date = "index" elseif date and ulx.url1.service == "wayback" and verifydates == "yes" then local ldf = dateFormat(date) if ldf then local udate = decodeWaybackDate( uri1.path, ldf ) if udate ~= date then date = udate .. inlineRed("<sup>[Date mismatch]</sup>", "warning") end end elseif date and ulx.url1.service == "webcite" and verifydates == "yes" then local ldf = dateFormat(date) if ldf then local udate = decodeWebciteDate( uri1.path, ldf ) if udate == "query" then -- skip elseif udate ~= date then date = udate .. inlineRed("<sup>[Date mismatch]</sup>", "warning") end end elseif not date and ulx.url1.service == "wayback" then date = decodeWaybackDate( uri1.path, "iso" ) if not date then date = inlineRed("[Date error] (1)", "error") end elseif not date and ulx.url1.service == "webcite" then date = decodeWebciteDate( uri1.path, "iso" ) if date == "query" then date = inlineRed("[Date missing]", "warning") elseif not date then date = inlineRed("[Date error] (1)", "error") end elseif not date then date = inlineRed("[Date missing]", "warning") end ulx.url1.date = date -- Format argument local format = trimArg(args.format) if not format then format = "none" else if format == "addlpages" then if not ulx.url1.date then format = "none" end elseif format == "addlarchives" then format = "addlarchives" else format = "none" end end ulx.url1.format = format -- Title argument local title = trimArg(args.title) or trimArg(args.title1) ulx.url1.title = title local rend = createRendering() if not rend then rend = '<span style="font-size:100%" class="error citation-comment">Error in [[:Template:' .. tname .. ']]: Unknown problem. Please report on template talk page.</span>' track["Kategori:Webarchive-skabelon fejl"] = 1 end return rend .. createTracking() end return p