وحدة:Webarchive: الفرق بين النسختين

[نسخة منشورة][نسخة منشورة]
تم حذف المحتوى تمت إضافة المحتوى
ط غيّر إعدادات حماية »وحدة:Webarchive«: بوت: [https://w.wiki/7NGP تحسين مستوي الحماية] ([تعديل=السماح للمحررين فقط] (غير محدد) [النقل=السماح للمحررين فقط] (غير محدد))
تحديث
وسم: مُسترجَع
سطر 1:
--[[ ----------------------------------
 
Lua module implementing the {{webarchive}} template.
 
A merger of the functionality of three templates: {{Waybackwayback}}, {{webcite}} and {{cite archives}}
]]
 
local p = {}
 
--[[--------------------------< inlineErrorD E P E N D E N C I E S >------------------------------------------------------
]]
 
require('strict');
Critical error. Render output completely in red. Add to tracking category.
local getArgs = require ('Module:Arguments').getArgs;
 
]]
 
--[[--------------------------< F O R W A R D D E C L A R A T I O N S >--------------------------------------
local function inlineError(arg, msg)
]]
 
local categories = {}; -- category names
track["Category:Webarchive template errors"] = 1
local config = {}; -- global configuration settings
return '<span style="font-size:100%" class="error citation-comment">Error in webarchive template: Check <code style="color:inherit; border:inherit; padding:inherit;">&#124;' .. arg .. '=</code> value. ' .. msg .. '</span>'
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
 
--[[--------------------------< inlineRed >-----------------------
 
--[[--------------------------< tableLength >-----------------------
Render a text fragment in red, such as a warning as part of the final output.
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["Category:Webarchive template warnings"] = 1
elseif trackmsg == "error" then
track["Category:Webarchive template errors"] = 1
end
 
local function make_wikilink (link, display, no_link)
return '<span style="font-size:100%" class="error citation-comment">' .. msg .. '</span>'
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
 
--[[--------------------------< trimArg >-----------------------
 
--[[--------------------------< createTracking >-----------------------
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=
 
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
 
local function trimArg2(arg)
 
if arg == nil then
--[[--------------------------< inlineError >-----------------------
return nil
 
else
Critical error. Render output completely in red. Add to tracking category.
return mw.text.trim(arg)
 
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
 
 
--[[--------------------------< 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 >-----------------------
 
Convert base-62 to base-10
Credit: https://de.wikipedia.org/wiki/Modul:Expr
 
]]
 
local function base62( value )
local r = 1 -- default return value is input value is malformed
 
if value:match ('%W') then -- value must only be in the set [0-9a-zA-Z]
local r = 1
return; -- nil return when value contains extraneous characters
end
 
local n = #value -- number of characters in value
if value:match( "^%w+$" ) then
local nk = #value1
local k = 1c
r = 0
local c
for i = n, 1, -1 do -- loop through all characters in value from ls digit to ms digit
r = 0
c = forvalue:byte( i = n, 1, -1i do)
if c >= 48 and c <= 57 then -- character is digit 0-9
c = value:byte( i, i )
c = c - 48
if c >= 48 and c <= 57 then
elseif c >= 65 and c <= 90 then -- character is ascii a-z
c = c - 48
c = c - 55
elseif c >= 65 and c <= 90 then
else -- must be ascii A-Z
c = c - 55
c = c - 61
elseif c >= 97 and c <= 122 then
end
c = c - 61
r = r + c * k -- accumulate this base62 character's value
else -- How comes?
k = k * 62 -- bump for next
r = 1
break end -- for i
 
end
return r
r = r + c * k
k = k * 62
end -- for i
end
return r
end
 
--[[--------------------------< tableLength >-----------------------
 
--[[--------------------------< D E C O D E _ D A T E >--------------------------------------------------------
Given a 1-D table, return number of elements
 
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
local function decode_date (date_str)
for _ in pairs(T) do count = count + 1 end
local patterns = {
return count
['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
 
--[[--------------------------< makeDate >-----------------------
 
Given year, month, day numbers, (zero-padded or not) return a full date in df format
--[[--------------------------< dateFormat >-----------------------
where df may be one of:
mdy, dmy, iso, ymd
 
on entry, year, month, day are presumed to be correct for the date that they represent; all are required
Given a date string, return its format: dmy, mdy, iso, ymd
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 function makeDate (year, month, day, df)
local dt = {}
local dt.splitformat = {}
['dmy'] = 'j F Y',
['mdy'] = 'F j, Y',
['ymd'] = 'Y F j',
['iso'] = 'Y-m-d',
};
 
local date = table.concat ({year, month, day}, '-'); -- assemble year-initial numeric-format date (zero padding not required here)
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
 
if non_western_digits then -- this wiki uses non-western digits?
dt.split = mw.text.split(date, " ")
date = mw.ustring.gsub (date, '%d', digits); -- convert this wiki's non-western digits to western digits
if tableLength(dt.split) == 3 then
end
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
 
return mw.getContentLanguage():formatDate (format[df], date);
end
 
--[[--------------------------< makeDate >-----------------------
 
--[[--------------------------< I S _ V A L I D _ D A T E >----------------------------------------------------
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
 
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.
 
all arguments are required
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 function is_valid_date (year, month, day)
local zmonth = month -- month with leading 0
local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
month = month:match("0*(%d+)") -- month without leading 0
local month_length;
if tonumber(month) < 1 or tonumber(month) > 12 then
local y, m, d;
return year
local today = os.date ('*t'); -- fetch a table of current date parts
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
 
if not year or '' == year or not month or '' == month or not day or '' == day then
local zday = day
return false; -- something missing
day = zday:match("0*(%d+)")
end
if tonumber(day) < 1 or tonumber(day) > 31 then
if df == "mdy" or df == "dmy" then
y = tonumber (year);
return nmonth .. " " .. year
m = tonumber (month);
elseif df == "iso" then
d = tonumber (day);
return year .. "-" .. zmonth
elseif df == "ymd" then
return year .. " " .. nmonth
else
return nmonth .. " " .. year
end
end
 
if 1900 > y or today.year < y or 1 > m or 12 < m then -- year and month are within bounds TODO: 1900?
if df == "mdy" then
return false;
return nmonth .. " " .. day .. ", " .. year -- September 1, 2016
end
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
 
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
 
السطر 208 ⟵ 323:
--[[--------------------------< decodeWebciteDate >-----------------------
 
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 dt = {};
local decode;
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
 
-- http://www.webcitation.org/query?id=1138911916587475
dt.full = os.date("%Y %m %d", string.sub(string.format("%d", base62(dt.split[2])),1,10) )
-- http://www.webcitation.org/query?url=http..&date=2012-06-01+21:40:03
dt.split = mw.text.split(dt.full, " ")
-- http://www.webcitation.org/1138911916587475
dt.year = dt.split[1]
-- http://www.webcitation.org/cache/73e53dd1f16cf8c5da298418d2a6e452870cf50e
dt.month = dt.split[2]
-- http://www.webcitation.org/getfile.php?fileid=1c46e791d68e89e12d0c2532cc3cf629b8bc8c8e
dt.day = dt.split[3]
 
if dt[2]:find ('query', 1, true) or
if not tonumber(dt.year) or not tonumber(dt.month) or not tonumber(dt.day) then
dt[2]:find ('cache', 1, true) or
return inlineRed("[Date error] (1)", "error")
dt[2]:find ('getfile', 1, true) or
end
tonumber(dt[2]) then
return 'query';
end
 
decode = base62(dt[2]); -- base62 string -> exponential number
if tonumber(dt.month) > 12 or tonumber(dt.day) > 31 or tonumber(dt.month) < 1 then
if not decode then
return inlineRed("[Date error] (2)", "error")
return nil; -- nil return when dt[2] contains characters not in %w
end
end
if tonumber(dt.year) > tonumber(os.date("%Y")) or tonumber(dt.year) < 1900 then
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
return inlineRed("[Date error] (3)", "error")
end
 
fulldate decode = makeDate (dt.year, dt.month, dt.day, df'iso'); -- date comparisons are all done in iso format with western digits
if non_western_digits then -- this wiki uses non-western digits?
if not fulldate then
decode = mw.ustring.gsub (decode, '%d', digits); -- convert this wiki's non-western digits to western digits
return inlineRed("[Date error] (4)", "error")
end
else
return fulldate
end
 
return decode;
end
 
 
--[[--------------------------< snapDateToString >-----------------------
--[[--------------------------< decodeWaybackDate >-----------------------
 
Given a URI-path to Wayback (eg. /web/20160901010101/http://example.com )
or Library of Congress Web Archives (eg. /all/20160901010101/http://example.com)
return the formatted date eg. "September 1, 2016" in df format
or UK Government Web Archive (eg. /ukgwa/20160901010101/http://example.com or /tna/20160901010101/http://example.com)
Handle non-digits in snapshot ID such as "re_" and "-" and "*"
 
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 msg, snapdate;
local snapdate, snapdatelong, currdate, fulldate
 
snapdate = path:gsub ('^/web/', ''):gsub ('^/all/', ''):gsub ('^/ukgwa/', ''):gsub ('^/tna/', ''):gsub ('^/', ''); -- remove leading /web/, /all/, /ukgwa/, /tna/, or /
local safe = path
snapdate = snapdate:match ('^[^/]+'); -- get timestamp
snapdate = string.gsub(safe, "^/w?e?b?/?", "") -- Remove leading "/web/" or "/"
if snapdate == "*" then -- eg. /web/*/http.., etc.
safe = snapdate
return 'index'; -- return indicator that this url has an index date
local N = mw.text.split(safe, "/")
end
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 "*"
 
snapdate = snapdate:gsub ('%a%a_%d?$', ''):gsub ('%-', ''); -- from date, remove any trailing "re_", dashes
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
 
msg = '';
fulldate = makeDate(year, month, day, df)
if snapdate:match ('%*$') then -- a trailing '*' causes calendar display at archive .org
if not fulldate then
snapdate = snapdate:gsub ('%*$', ''); -- remove so not part of length calc later
return inlineRed("[Date error] (7)", "error")
msg = inlineRed (err_warn_msgs.ts_cal, 'warning'); -- make a message
else
end
return fulldate
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
 
 
--[[--------------------------< serviceNamedecodeArchiveisDate >-----------------------
 
Given an Archive.is "long link" URI-path (e.g. /2016.08.28-144552/http://example.com)
Given a domain extracted by mw.uri.new() (eg. web.archive.org) set tail string and service ID
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 function decodeArchiveisDate(path, df)
local tracking = "Category:Webarchive template other archives"
local snapdate
 
if path:match ('^/%w+$') then -- short form url path is '/' followed by some number of base 62 digits and nothing else
local bracketopen = "[["
return "short link" -- e.g. http://archive.is/hD1qz
local bracketclose = "]]"
end
if nolink then
bracketopen = ""
bracketclose = ""
end
 
snapdate = mw.text.split (path, '/')[2]:gsub('[%.%-]', ''); -- get snapshot date, e.g. 2016.08.28-144552; remove periods and hyphens
ulx.url1.service = "other"
ulx.url1.tail = " at " .. ulx.url1.host
 
local dlen = string.len(snapdate)
if mw.ustring.find( host, "archive.org", 1, plain ) then
if dlen < 8 then -- we need 8 digits TODO: but shouldn't this be testing for 14 digits?
ulx.url1.service = "wayback"
return '', inlineRed (err_warn_msgs.ts_short, 'error'); -- return empty string and error message
ulx.url1.tail = " على موقع " .. bracketopen .. "واي باك مشين" .. bracketclose
end
tracking = "تصنيف:قالب أرشيف الإنترنت بوصلات واي باك"--"Category:Webarchive template wayback links"
elseif mw.ustring.find( host, "webcitation.org", 1, plain ) then
ulx.url1.service = "webcite"
ulx.url1.tail = " at " .. bracketopen .. "WebCite" .. bracketclose
tracking = "Category:Webarchive template webcite links"
elseif mw.ustring.find( host, "archive.is", 1, plain ) then
ulx.url1.service = "archiveis"
ulx.url1.tail = " at " .. bracketopen .. "Archive.is" .. bracketclose
tracking = "Category:Webarchive template archiveis links"
elseif mw.ustring.find( host, "archive.today", 1, plain ) then
ulx.url1.service = "archiveis"
ulx.url1.tail = " at " .. bracketopen .. "Archive.is" .. bracketclose
tracking = "Category:Webarchive template archiveis links"
elseif mw.ustring.find( host, "archive-it", 1, plain ) then
ulx.url1.service = "archiveit"
ulx.url1.tail = " at " .. bracketopen .. "Archive-It" .. bracketclose
elseif mw.ustring.find( host, "arquivo.pt", 1, plain) then
ulx.url1.tail = " at the " .. "Portugese Web Archive"
elseif mw.ustring.find( host, "loc.gov", 1, plain ) then
ulx.url1.tail = " at the " .. bracketopen .. "Library of Congress" .. bracketclose
elseif mw.ustring.find( host, "webharvest.gov", 1, plain ) then
ulx.url1.tail = " at the " .. bracketopen .. "National Archives and Records Administration" .. bracketclose
elseif mw.ustring.find( host, "bibalex.org", 1, plain ) then
ulx.url1.tail = " على موقع " .. "[[مكتبة الإسكندرية الجديدة]]"
elseif mw.ustring.find( host, "collectionscanada", 1, plain ) then
ulx.url1.tail = " at the " .. "Canadian Government Web Archive"
elseif mw.ustring.find( host, "haw.nsk", 1, plain ) then
ulx.url1.tail = " at the " .. "Croatian Web Archive (HAW)"
elseif mw.ustring.find( host, "nlib.ee", 1, plain ) then
ulx.url1.tail = " at the " .. "Estonian Web Archive"
elseif mw.ustring.find( host, "vefsafn.is", 1, plain ) then
ulx.url1.tail = " at the " .. "[[National and University Library of Iceland]]"
elseif mw.ustring.find( host, "proni.gov", 1, plain ) then
ulx.url1.tail = " at the " .. bracketopen .. "Public Record Office of Northern Ireland" .. bracketclose
elseif mw.ustring.find( host, "uni-lj.si", 1, plain ) then
ulx.url1.tail = " at the " .. "Slovenian Web Archive"
elseif mw.ustring.find( host, "stanford.edu", 1, plain ) then
ulx.url1.tail = " at the " .. "[[Stanford University Libraries|Stanford Web Archive]]"
elseif mw.ustring.find( host, "nationalarchives.gov.uk", 1, plain ) then
ulx.url1.tail = " at the " .. bracketopen .. "UK Government Web Archive" .. bracketclose
elseif mw.ustring.find( host, "parliament.uk", 1, plain ) then
ulx.url1.tail = " at the " .. bracketopen .. "UK Parliament's Web Archive" .. bracketclose
elseif mw.ustring.find( host, "webarchive.org.uk", 1, plain ) then
ulx.url1.tail = " at the " .. bracketopen .. "UK Web Archive" .. bracketclose
elseif mw.ustring.find( host, "nlb.gov.sg", 1, plain ) then
ulx.url1.tail = " على موقع " .. "Web Archive Singapore"
elseif mw.ustring.find( host, "nlb.gov.sg", 1, plain ) then
ulx.url1.tail = " على موقع " .. "Web Archive Singapore"
elseif mw.ustring.find( host, "screenshots.com", 1, plain ) then
ulx.url1.tail = " at " .. "Screenshots"
elseif mw.ustring.find( host, "wikiwix.com", 1, plain ) then
ulx.url1.tail = " على موقع " .. "Wikiwix"
elseif mw.ustring.find( host, "perma.cc", 1, plain ) then
ulx.url1.tail = " على موقع " .. bracketopen .. "Perma.cc" .. bracketclose
else
tracking = "Category:Webarchive template unknown archives"
end
 
local year, month, day = snapdate:match ('(%d%d%d%d)(%d%d)(%d%d)'); -- no need for snapdatelong here
track[tracking] = 1
 
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
 
 
--[[--------------------------< 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(args)
 
local i, j, argurl, argurl2, argdate, argtitle
 
j = 2
for i = 2, config.maxurls do
argurl = "url" .. i
if trimArg(args[argurl]) then
argurl2 = "url" .. j
ulx[argurl2] = {}
ulx[argurl2]["url"] = args[argurl]
argdate = "date" .. ji
if trimArg(args[argdate]) then
ulx[argurl2]["date"] = args[argdate]
else
ulx[argurl2]["date"] = inlineRed ("[Date missing]"err_warn_msgs.date_miss, "'warning"');
end
argtitle = "title" .. j
argtitle = "title" .. i
if trimArg(args[argtitle]) then
ulx[argurl2]["title"] = if args[argtitle] then
ulx[argurl2]["title"] = args[argtitle]
else
else
ulx[argurl2]["title"] = nil
ulx[argurl2]["title"] = nil
end
end
j = j + 1
j = j + end1
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
 
 
--[[--------------------------< comma >-----------------------
 
Given a date string, return "," if it's MDY
 
]]
 
local function comma(date)
return (date and date:match ('%a+ +%d%d?(,) +%d%d%d%d')) or '';
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 >-----------------------
 
--[[--------------------------< createRendering >-----------------------
Return data in track[] ie. tracking categories
 
Return a rendering of the data in ulx[][]
]]
 
]]
local function createTracking()
 
local sand =function ""createRendering()
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, '&#32;('); -- 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
 
--[[--------------------------< createRendering >-----------------------
 
--[[--------------------------< P A R A M E T E R _ N A M E _ X L A T E >--------------------------------------
Return a rendering of the data in ulx[][]
 
for internaltionalization, translate local-language parameter names to their English equivalents
]]
 
TODO: return error message if multiple aliases of the same canonical parameter name are found?
local function createRendering()
 
returns two tables:
local sand, displayheader, displayfield
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
 
unrecognized parameters are ignored
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 .. " نسخة محفوظة]" .. ulx.url1.tail
elseif not ulx.url1.title and ulx.url1.date then -- No title. Date.
if ulx.url1.service == "wayback" then
period1 = "."
period2 = ""
end
sand = "[" .. ulx.url1.url .. " نسخة محفوظة] " .. ulx.url1.date .. comma(ulx.url1.date) .. ulx.url1.tail .. period1
elseif ulx.url1.title and not ulx.url1.date then -- Title. No date.
sand = "[" .. 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 .. "]" .. ulx.url1.tail .. "&#32;(" .. 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}}
 
local function parameter_name_xlate (args, params, enum_params)
else
local name; -- holds modifiable name of the parameter name during evaluation
if ulx.url1.format == "addlarchives" then -- Multiple archive services
local enum; -- for enumerated parameters, holds the enumerator during evaluation
displayheader = "Additional archives: "
local found = false; -- flag used to break out of nested for loops
else -- Multiple pages from the same archive
local new_args = {}; -- a table that holds canonical and translated parameter k/v pairs
displayheader = "المزيد من النسخ المحفوظة&nbsp;on " .. ulx.url1.date .. ": "
local origin = {}; -- a table that maps original (local language) parameter names to their canonical name for local language error messaging
end
local unnamed_params; -- set true when unsupported positional parameters are detected
local tot = 1 + ulx.url1.extraurls
local sand = displayheader
for k, v in pairs (args) do -- loop through all of the arguments in the args table
for i=1,tot do
name = k; -- copy of original parameter name
local indx = "url" .. i
 
displayfield = ulx[indx]["title"]
if ulx.url1.format'string' == "addlarchives"type (k) then
if non_western_digits then -- true when non-western digits supported at this wiki
if not displayfield then
name = mw.ustring.gsub (name, '%d', digits); -- convert this wiki's non-western digits to western digits
displayfield = ulx[indx]["date"]
end
else
enum = name:match ('%d+$'); -- get parameter enumerator if it exists; nil else
if not displayfield then
displayfield = "Page " .. i
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
end
for pname, aliases in pairs (params) do -- loop through each parameter the params table
sand = sand .. "[" .. ulx[indx]["url"] .. " " .. displayfield .. "]"
for _, alias in ipairs (aliases) do -- loop through each alias in the parameter's aliases table
if i == tot then
if name == alias then
sand = sand .. "."
new_args[pname] = v; -- create a new entry in the new_args table
else
origin [pname] = k; -- create an entry to make canonical parameter name to original local language parameter name
sand = sand .. ", "
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
end
end
return sand
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
 
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 = "yes" -- See documentation. Set "no" to disable.
 
--[[--------------------------< W E B A R C H I V E >----------------------------------------------------------
-- URL argument (first)
 
template entry point
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["Category:Webarchive template errors"] = 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()
 
local function webarchive(frame)
-- Nolink argument
local args = getArgs (frame);
 
local data = mw.loadData (table.concat ({ -- make a data module name; sandbox or live
local nolink = trimArg2(args.nolink)
'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;
 
local origin = {}; -- holds a map of English to local language parameter names used in the current template; not currently used
serviceName(uri1.host, nolink)
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
 
local date, format, msg, udate, uri, url;
-- Date argument
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
]]
 
if not (url:lower():find ('^http') or url:find ('^//')) then
local date = trimArg(args.date) or trimArg(args.date1)
return inlineError (data.crit_err_msgs.invalid_url );
if date == "*" and ulx.url1.service == "wayback" then
end
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 = date -- .. 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
 
ulx.url1 = {}
-- Format argument
ulx.url1.url = url
 
ulx.url1.extraurls = parseExtraArgs(args)
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
 
local good = false;
-- Title argument
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)
 
if args.date and args.date1 then -- Date argument
local title = trimArg(args.title) or trimArg(args.title1)
return inlineError (data.crit_err_msgs.conflicting, {origin.date, origin.date1});
ulx.url1.title = title
end
date = args.date or args.date1;
date = date and date:gsub (' +', ' '); -- replace multiple spaces with a single space
 
if date and config.verifydates then
local rend = createRendering()
if '*' if not== renddate then
date = 'index';
rend = '<span style="font-size:100%" class="error citation-comment">Error in [[:Template:' .. tname .. ']]: Unknown problem. Please report on template talk page.</span>'
ldf = 'iso'; -- set to default format
track["Category:Webarchive template errors"] = 1
elseif 'mdy' == date then
end
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
 
if 'wayback' == ulx.url1.service or 'locwebarchives' == ulx.url1.service or 'ukgwa' == ulx.url1.service then
return rend .. createTracking()
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
 
 
return p
--[[--------------------------< E X P O R T E D F U N C T I O N S >------------------------------------------
]]
 
return {webarchive = webarchive};