Modulo:Webarchive

Dokumentado Dokumentado


Ŝablona programadoDiskutojLuaTestojSubpaĝoj
ModuloEsperantoEnglish

Modulo:Dokumentado


Se vi havas demandon pri ĉi tiu Lua-modulo, tiam vi povas demandi en la diskutejo pri Lua-moduloj. La Intervikiaj ligiloj estu metataj al Vikidatumoj. (Vidu Helpopaĝon pri tio.)
--[[ ----------------------------------Lua module implementing the {{webarchive}} template. A merger of the functionality of three templates: {{wayback}}, {{webcite}} and {{cite archives}}]]--[[--------------------------< D E P E N D E N C I E S >------------------------------------------------------]]require('strict')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 categories = {};-- category nameslocal config = {};-- global configuration settingslocal digits = {};-- for i18n; table that translates local-wiki digits to western digitslocal err_warn_msgs = {};-- error and warning messageslocal excepted_pages = {};local month_num = {};-- for i18n; table that translates local-wiki month names to western digitslocal prefixes = {};-- service provider tail string prefixeslocal services = {};-- archive service provider data fromlocal s_text = {};-- table of static text strings used to build final renderinglocal uncategorized_namespaces = {};-- list of namespaces that we should not categorizelocal 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 truelocal this_page = mw.title.getCurrentTitle();local track = {};-- Associative array to hold tracking categorieslocal 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--[[--------------------------< tableLength >-----------------------Given a 1-D table, return number of elements]]local function tableLength(T)local count = 0for _ in pairs(T) do count = count + 1 endreturn countend--[=[-------------------------< 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 onlylink is provided, returns a wikilink in the form [[L]]; if neither are provided or link is omitted, returns anempty string.]=]local function make_wikilink (link, display, no_link)if nil == no_link thenif link and ('' ~= link) thenif display and ('' ~= display) thenreturn table.concat ({'[[', link, '|', display, ']]'});elsereturn table.concat ({'[[', link, ']]'});endendreturn display or '';-- link not set so return the display textelse-- no_linkif display and ('' ~= display) then-- if there is display textreturn display;-- return thatelsereturn link or '';-- return the target article name or empty stringendendend--[[--------------------------< createTracking >-----------------------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] thenreturn '';-- this page not to be categorized so return empty stringendfor _,v in ipairs (uncategorized_subpages) do-- cycle through page name patternsif this_page.text:match (v) then-- test page name against each patternreturn '';-- this subpage type not to be categorized so return empty stringendendendlocal out = {};if tableLength(track) > 0 thenfor key, _ in pairs(track) do-- loop through tabletable.insert (out, make_wikilink (key));-- and convert category names to linksendendreturn table.concat (out);-- concat into one big string; empty string if table is emptyend--[[--------------------------< inlineError >-----------------------Critical error. Render output completely in red. Add to tracking category.This function called as the last thing before abandoning this module]]local function inlineError (msg, args)track[categories.error] = 1return table.concat ({'<span style="font-size:100%" class="error citation-comment">Error in ',-- open the error message spanconfig.tname,-- insert the local language template name' template: ',substitute (msg, args),-- insert the formatted error message'.</span>',-- close the spancreateTracking()-- 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" thentrack[categories.warning] = 1;elseif trackmsg == "error" thentrack[categories.error] = 1;endreturn '<span style="font-size:100%" class="error citation-comment">' .. msg .. '</span>'end--[[--------------------------< base62 >-----------------------Convert base-62 to base-10Credit: https://www.search.com.vn/wiki/de/Modul:Expr ]]local function base62( value )local r = 1-- default return value is input value is malformedif value:match ('%W') then-- value must only be in the set [0-9a-zA-Z]return;-- nil return when value contains extraneous charactersendlocal n = #value-- number of characters in valuelocal k = 1local cr = 0for i = n, 1, -1 do-- loop through all characters in value from ls digit to ms digitc = value:byte( i, i )if c >= 48 and c <= 57 then-- character is digit 0-9c = c - 48elseif c >= 65 and c <= 90 then-- character is ascii a-zc = c - 55else-- must be ascii A-Zc = c - 61endr = r + c * k-- accumulate this base62 character's valuek = k * 62-- bump for nextend -- for ireturn rend --[[--------------------------< 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 namesmust be recognizable as legitimate month names with proper capitalization, and that the date string must match oneof the recognized date formats, no error checking is done here; return nil else]]local function decode_date (date_str)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 digitsendif date_str:match ('^%d%d%d%d%-%d%d%-%d%d$') then-- already an iso format date, return western digits formreturn date_str, 'iso';endfor k, v in pairs (patterns) dolocal c1, c2, c3 = mw.ustring.match (date_str, patterns[k][1]);-- c1 .. c3 are captured but we don't know what they holdif c1 then-- set on matcht = {-- 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 numbert.m = month_num[t.m];-- replace valid month name with a numberelsereturn nil, 'iso';-- not a valid date form because month not validendreturn mw.ustring.format ('%.4d-%.2d-%.2d', t.y, t.m, t.d), k;-- return date in iso formatendendreturn nil, 'iso';-- date could not be decoded; return nil and default iso dateend--[[--------------------------< makeDate >-----------------------Given year, month, day numbers, (zero-padded or not) return a full date in df formatwhere df may be one of:mdy, dmy, iso, ymdon entry, year, month, day are presumed to be correct for the date that they represent; all are requiredin 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 makeDate (year, month, day, df)local format = {['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)if non_western_digits then--this wiki uses non-western digits?date = mw.ustring.gsub (date, '%d', digits);-- convert this wiki's non-western digits to western digitsendreturn mw.getContentLanguage():formatDate (format[df], date);end--[[--------------------------< I S _ V A L I D _ D A T E >----------------------------------------------------Returns true if date is after 31 December 1899 (why is 1900 the min year? shouldn't the internet's date-of-birthbe min year?), not after today's date, and represents a valid date (29 February 2017 is not a valid date).  AppliesGregorian leapyear rules.all arguments are required]]local function is_valid_date (year, month, day)local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};local month_length;local y, m, d;local today = os.date ('*t');-- fetch a table of current date partsif not year or '' == year or not month or '' == month or not day or '' == day thenreturn false;-- something missingendy = tonumber (year);m = tonumber (month);d = tonumber (day);if 1900 > y or today.year < y or 1 > m or 12 < m then-- year and month are within boundsTODO: 1900?return false;endif (2==m) then-- if Februarymonth_length = 28;-- then 28 days unlessif (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 Februaryendelsemonth_length=days_in_month[m];endif 1 > d or month_length < d then-- day is within boundsreturn false;end-- here when date parts represent a valid datereturn os.time({['year']=y, ['month']=m, ['day']=d, ['hour']=0}) <= os.time();-- date at midnight must be less than or equal to current date/timeend--[[--------------------------< decodeWebciteDate >-----------------------Given a URI-path to Webcite (eg. /67xHmVFWP) return the encoded date in df formatreturns date string in df format - webcite date is a unix timestamp encoded as bae62or the string 'query']]local function decodeWebciteDate(path, df)local dt = {};local decode;dt = mw.text.split(path, "/")-- valid URL formats that are not base62-- http://www.webcitation.org/query?id=1138911916587475-- http://www.webcitation.org/query?url=http..&date=2012-06-01+21:40:03-- http://www.webcitation.org/1138911916587475-- http://www.webcitation.org/cache/73e53dd1f16cf8c5da298418d2a6e452870cf50e-- http://www.webcitation.org/getfile.php?fileid=1c46e791d68e89e12d0c2532cc3cf629b8bc8c8eif dt[2]:find ('query', 1, true) or dt[2]:find ('cache', 1, true) ordt[2]:find ('getfile', 1, true) ortonumber(dt[2]) thenreturn 'query';enddecode = base62(dt[2]);-- base62 string -> exponential numberif not decode thenreturn nil;-- nil return when dt[2] contains characters not in %wenddt = os.date('*t', string.format("%d", decode):sub(1,10))-- exponential number -> text -> first 10 characters (a unix timestamp) -> a table of date partsdecode = makeDate (dt.year, dt.month, dt.day, 'iso');-- date comparisons are all done in iso format with western digitsif non_western_digits then--this wiki uses non-western digits?decode = mw.ustring.gsub (decode, '%d', digits);-- convert this wiki's non-western digits to western digitsendreturn decode;end--[[--------------------------< decodeWaybackDate >-----------------------Given a URI-path to Wayback (eg. /web/20160901010101/http://example.com )or Library of Congress Web Archives (/all/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 numbersecond return value is an appropriate 'message' may or may not be formatted]]local function decodeWaybackDate(path, df)local msg, snapdate;snapdate = path:gsub ('^/all/', ''):gsub ('^/web/', ''):gsub ('^/', '');-- remove leading '/all/', leading '/web/' or leading '/'snapdate = snapdate:match ('^[^/]+');-- get timestampif snapdate == "*" then-- eg. /web/*/http.. or /all/*/http..return 'index';-- return indicator that this url has an index dateendsnapdate = snapdate:gsub ('%a%a_%d?$', ''):gsub ('%-', '');-- from date, remove any trailing "re_", dashesmsg = '';if snapdate:match ('%*$') then-- a trailing '*' causes calendar display at archive .orgsnapdate = snapdate:gsub ('%*$', '');-- remove so not part of length calc latermsg = inlineRed (err_warn_msgs.ts_cal, 'warning');-- make a messageendif not tonumber(snapdate) thenreturn nil, 'ts_nan';-- return nil (fatal error flag) and message selectorendlocal 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 messageendlocal year, month, day = snapdate:match ('(%d%d%d%d)(%d%d)(%d%d)');-- no need for snapdatelong hereif not is_valid_date (year, month, day) thenreturn '', inlineRed (err_warn_msgs.ts_date, 'error');-- return empty string and error messageendsnapdate = table.concat ({year, month, day}, '-');-- date comparisons are all done in iso formatif 14 == dlen thenreturn snapdate, msg;-- return date with message if anyelsereturn snapdate, msg .. inlineRed (err_warn_msgs.ts_len, 'warning');-- return date with warning message(s)endend--[[--------------------------< decodeArchiveisDate >-----------------------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 20160828144552returns 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 decodeArchiveisDate(path, df)local snapdateif path:match ('^/%w+$') then-- short form url path is '/' followed by some number of base 62 digits and nothing elsereturn "short link"-- e.g. http://archive.is/hD1qzendsnapdate = mw.text.split (path, '/')[2]:gsub('[%.%-]', '');-- get snapshot date, e.g. 2016.08.28-144552; remove periods and hyphenslocal dlen = string.len(snapdate)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 messageendlocal year, month, day = snapdate:match ('(%d%d%d%d)(%d%d)(%d%d)');-- no need for snapdatelong hereif not is_valid_date (year, month, day) thenreturn '', inlineRed (err_warn_msgs.ts_date, 'error');-- return empty string and error messageendsnapdate = table.concat ({year, month, day}, '-');-- date comparisons are all done in iso formatif 14 == dlen thenreturn snapdate;-- return dateelsereturn snapdate, inlineRed (err_warn_msgs.ts_len, 'warning');-- return date with warning messageend 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. subdomainsif services[host] thenindex = host;elsefor k, _ in pairs (services) doif host:find ('%f[%a]'..k:gsub ('([%.%-])', '%%%1')) thenindex = k;break;endendendif index thenlocal out = {''};-- empty string in [1] so that concatenated result has leading single spaceulx.url1.service = services[index][4] or 'other';tracking = services[index][5] or categories.other;-- build tail stringif false == services[index][1] then-- select prefixtable.insert (out, prefixes.at);elseif true == services[index][1] thentable.insert (out, prefixes.atthe);elsetable.insert (out, services[index][1]);endtable.insert (out, make_wikilink (services[index][2], services[index][3], no_link));-- add article wikilinkif services[index][6] then-- add tail postfix if it existstable.insert (out, services[index][6]);endulx.url1.tail = table.concat (out, ' ');-- put it all together; result has leading space characterelse-- here when unknown archiveulx.url1.service = 'other';tracking = categories.unknown;ulx.url1.tail = table.concat ({'', prefixes.at, host, inlineRed (err_warn_msgs.unknown_url, error)}, ' ');endtrack[tracking] = 1end--[[--------------------------< parseExtraArgs >-----------------------Parse numbered arguments starting at 2, such as url2..url10, date2..date10, title2..title10For 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, argtitlej = 2for i = 2, config.maxurls doargurl = "url" .. iif args[argurl] thenargurl2 = "url" .. julx[argurl2] = {}ulx[argurl2]["url"] = args[argurl]argdate = "date" .. jif args[argdate] thenulx[argurl2]["date"] = args[argdate]elseulx[argurl2]["date"] = inlineRed (err_warn_msgs.date_miss, 'warning');endargtitle = "title" .. jif args[argtitle] thenulx[argurl2]["title"] = args[argtitle]elseulx[argurl2]["title"] = nilendj = j + 1endendif j == 2 thenreturn 0elsereturn j - 2endend--[[--------------------------< 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 '';end--[[--------------------------< createRendering >-----------------------Return a rendering of the data in ulx[][]]]local function createRendering()local displayfieldlocal 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 messageif 'none' == ulx.url1.format then-- For {{wayback}}, {{webcite}}table.insert (out, '[');-- open extlink markuptable.insert (out, ulx.url1.url);-- add urlif ulx.url1.title thentable.insert (out, ' ')-- the required spacetable.insert (out, ulx.url1.title)-- the titletable.insert (out, ']');-- close extlink markuptable.insert (out, ulx.url1.tail);-- tail textif ulx.url1.date thentable.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 texttable.insert (out, ' ');-- insert a spacetable.insert (out, ulx.url1.date);-- add datetable.insert (out, ')');-- close date textendelse-- no titleif index_date then-- when url date is 'index' table.insert (out, table.concat ({' ', s_text.Archive_index, ']'}));-- add the index link labeltable.insert (out, msg or '');-- add date mismatch message when url date is /*/ and |date= has valid dateelsetable.insert (out, table.concat ({' ', s_text.Archived, '] '}));-- add link label for url has timestamp date (will include mismatch message if there is one)endif ulx.url1.date thenif 'index' ~= ulx.url1.date thentable.insert (out, ulx.url1.date);-- add date when data is not 'index'endtable.insert (out, comma(ulx.url1.date));-- add ',' if date format is mdytable.insert (out, ulx.url1.tail);-- add tail textelse-- no datetable.insert (out, ulx.url1.tail);-- add tail textendendif 0 < ulx.url1.extraurls then-- For multiple archive URLslocal tot = ulx.url1.extraurls + 1table.insert (out, '.')-- terminate first urltable.insert (out, table.concat ({' ', s_text.addlarchives, ': '}));-- add header textfor i=2, tot do-- loop through the additionalslocal index = table.concat ({'url', i});-- make an indexdisplayfield = ulx[index]['title'] and 'title' or 'date';-- choose display texttable.insert (out, '[');-- open extlink markuptable.insert (out, ulx[index]['url']);-- add the urltable.insert (out, ' ');-- the required spacetable.insert (out, ulx[index][displayfield]);-- add the labeltable.insert (out, ']');-- close extlink markuptable.insert (out, i==tot and '.' or ', ');-- add terminatorendendreturn table.concat (out);-- make a big string and doneelse-- For {{cite archives}}if 'addlarchives' == ulx.url1.format then-- Multiple archive services table.insert (out, table.concat ({s_text.addlarchives, ': '}));-- add header textelse-- Multiple pages from the same archive table.insert (out, table.concat ({s_text.addlpages, ' '}));-- add header texttable.insert (out, ulx.url1.date);-- add date to header texttable.insert (out, ': ');-- close header textendlocal tot = ulx.url1.extraurls + 1;for i=1, tot do-- loop through the additionalslocal index = table.concat ({'url', i});-- make an indextable.insert (out, '[');-- open extlink markuptable.insert (out, ulx[index]['url']);-- add urltable.insert (out, ' ');-- add required spacedisplayfield = ulx[index]['title'];if 'addlarchives' == ulx.url1.format thenif not displayfield then displayfield = ulx[index]['date']endelse-- must be addlpagesif not displayfield then displayfield = table.concat ({s_text.Page, ' ', i});endendtable.insert (out, displayfield);-- add title, date, page label texttable.insert (out, ']');-- close extlink markuptable.insert (out, (i==tot and '.' or ', '));-- add terminatorendreturn table.concat (out);-- make a big string and doneendend--[[--------------------------< 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 equivalentsTODO: return error message if multiple aliases of the same canonical parameter name are found?returns two tables:new_args - holds canonical form parameters and their values either from translation or because the parameter was already in canonical formorigin - maps canonical-form parameter names to their untranslated (local language) form for error messaging in the local languageunrecognized parameters are ignored]]local function parameter_name_xlate (args, params, enum_params)local name;-- holds modifiable name of the parameter name during evaluationlocal enum;-- for enumerated parameters, holds the enumerator during evaluationlocal found = false;-- flag used to break out of nested for loopslocal new_args = {};-- a table that holds canonical and translated parameter k/v pairslocal origin = {};-- a table that maps original (local language) parameter names to their canonical name for local language error messaginglocal unnamed_params;-- set true when unsupported positional parameters are detectedfor k, v in pairs (args) do-- loop through all of the arguments in the args tablename = k;-- copy of original parameter nameif 'string' == type (k) thenif non_western_digits then-- true when non-western digits supported at this wikiname = mw.ustring.gsub (name, '%d', digits);-- convert this wiki's non-western digits to western digitsendenum = name:match ('%d+$');-- get parameter enumerator if it exists; nil elseif not enum then-- no enumerator so looking for non-enumnerated parameters-- TODO: insert shortcut here? if params[name] then name holds the canonical parameter name; no need to search furtherfor pname, aliases in pairs (params) do-- loop through each parameter the params tablefor _, alias in ipairs (aliases) do-- loop through each alias in the parameter's aliases tableif name == alias thennew_args[pname] = v;-- create a new entry in the new_args tableorigin [pname] = k;-- create an entry to make canonical parameter name to original local language parameter namefound = true;-- flag so that we can break out of these nested for loopsbreak;-- no need to search the rest of the aliases table for name so go on to the next k, v pairendendif found then-- true when we found an alias that matched namefound = false;-- reset the flagbreak;-- go do next args k/v pairendendelse-- enumerated parametersname = 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 furtherfor pname, aliases in pairs (enum_params) do-- loop through each parameter the num_params tablefor _, alias in ipairs (aliases) do-- loop through each alias in the parameter's aliases tableif name == alias thenpname = pname:gsub ('#$', enum);-- replace the '#' place holder with the actual enumeratornew_args[pname] = v;-- create a new entry in the new_args tableorigin [pname] = k;-- create an entry to make canonical parameter name to original local language parameter namefound = true;-- flag so that we can break out of these nested for loopsbreak;-- no need to search the rest of the aliases table for name so go on to the next k, v pairendendif found then-- true when we found an alias that matched namefound = false;-- reset the flagbreak;-- go do next args k/v pairendendendelseunnamed_params = true;-- flag for unsupported positional parametersendend-- for k, vreturn new_args, origin, unnamed_params;end--[[--------------------------< W E B A R C H I V E >----------------------------------------------------------template entry point]]local function webarchive(frame)local args = getArgs (frame);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 declarationsconfig = data.config;if data.digits.enable thendigits = data.digits;-- for i18n; table of digits in the local wiki's languagenon_western_digits = true;-- use_non_western_digitsenderr_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 languageprefixes = 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 usedlocal unnamed_params;-- boolean set to true when template call has unnamed parametersargs, origin, unnamed_params = parameter_name_xlate (args, data.params, data.enum_params);-- translate parameter names in args to Englishlocal date, format, msg, udate, uri, url;local ldf = 'iso';-- when there is no |date= parameter, render url dates in iso formatif args.url and args.url1 then-- URL argument (first)return inlineError (data.crit_err_msgs.conflicting, {origin.url, origin.url1});endurl = args.url or args.url1;if not url thenreturn 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 testsif mw.ustring.find( url, "https://web.http", 1, true ) then-- track bug - TODO: IAbot bug; not known if the bug has been fixed; deferredtrack[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; deferredtrack[categories.error] = 1;return inlineError (data.crit_err_msgs.iabot2);end]]if not (url:lower():find ('^http') or url:find ('^//')) thenreturn inlineError (data.crit_err_msgs.invalid_url );endulx.url1 = {}ulx.url1.url = urlulx.url1.extraurls = parseExtraArgs(args)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 malformedif not good or nil == uri.host then-- abandon when ulx.url1.url is malformedreturn inlineError (data.crit_err_msgs.invalid_url);endserviceName(uri.host, args.nolink)if args.date and args.date1 then-- Date argumentreturn inlineError (data.crit_err_msgs.conflicting, {origin.date, origin.date1});enddate = args.date or args.date1;date = date and date:gsub (' +', ' ');-- replace multiple spaces with a single spaceif date and config.verifydates thenif '*' == date thendate = 'index';ldf = 'iso';-- set to default formatelsedate, ldf = decode_date (date);-- get an iso format date from date and get date's original formatendendif 'wayback' == ulx.url1.service or 'locwebarchives' == ulx.url1.service thenif date thenif config.verifydates thenif ldf thenudate, 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 returnreturn inlineError (data.crit_err_msgs[msg]);endif udate ~= date then-- date comparison using iso format datesdate = udate;msg = table.concat ({inlineRed (err_warn_msgs.mismatch, 'warning'),-- add warning messagemsg,-- add message if there is one});endendendelse-- no |date=udate, msg = decodeWaybackDate (uri.path);if not udate then-- this is the only 'fatal' error returnreturn inlineError (data.crit_err_msgs[msg]);endif '' == udate then date = nil;-- unsetelsedate = udate;endendelseif 'webcite' == ulx.url1.service thenif date thenif config.verifydates thenif ldf thenudate = decodeWebciteDate (uri.path);-- get the url date in iso formatif 'query' ~= udate then-- skip if queryif udate ~= date then-- date comparison using iso format datesdate = udate;msg = table.concat ({inlineRed (err_warn_msgs.mismatch, 'warning'),});endendendendelsedate = decodeWebciteDate( uri.path, "iso" )if date == "query" thendate = nil;-- unsetmsg = inlineRed (err_warn_msgs.date_miss, 'warning');elseif not date then-- invalid base62 stringdate = inlineRed (err_warn_msgs.date1, 'error');endendelseif 'archiveis' == ulx.url1.service thenif date thenif config.verifydates thenif ldf thenudate, msg = decodeArchiveisDate (uri.path)-- get the url date in iso formatif 'short link' ~= udate then-- skip if short linkif udate ~= date then-- date comparison using iso format datesdate = udate;msg = table.concat ({inlineRed (err_warn_msgs.mismatch, 'warning'),-- add warning messagemsg,-- add message if there is one});endendendendelse-- no |date=udate, msg = decodeArchiveisDate( uri.path, "iso" )if udate == "short link" thendate = nil;-- unsetmsg = inlineRed (err_warn_msgs.date_miss, 'warning');elseif '' == udate thendate = nil;-- unsetelsedate = udate;endendelse-- some other serviceif not date thenmsg = inlineRed (err_warn_msgs.date_miss, 'warning');endendif 'index' == date thenulx.url1.date = date .. (msg or '');-- create index + message (if there is one)elseif date thenulx.url1.date = makeDate (date, nil, nil, ldf) .. (msg or '');-- create a date in the wiki's local language + message (if there is one)elseulx.url1.date = msg;endformat = args.format;-- Format argument if not format thenformat = "none"elsefor k, v in pairs (data.format_vals) do-- |format= accepts two specific values loop through a table of those valueslocal found;-- declare a nil flagfor _, p in ipairs (v) do-- loop through local language variantsif format == p then-- when |format= value matches format = k;-- use name from table keyfound = true;-- declare found so that we can break out of outer for loopbreak;-- break out of inner for loopendendif found thenbreak;endendif format == "addlpages" thenif not ulx.url1.date thenformat = "none"endelseif format == "addlarchives" thenformat = "addlarchives"elseformat = "none"endendulx.url1.format = formatif args.title and args.title1 then-- Title argumentreturn inlineError (data.crit_err_msgs.conflicting, {origin.title, origin.title1});endulx.url1.title = args.title or args.title1;local rend = createRendering()if not rend thenreturn inlineError (data.crit_err_msgs.unknown);endreturn rend .. ((unnamed_params and inlineRed (err_warn_msgs.unnamed_params, 'warning')) or '') .. createTracking();end--[[--------------------------< E X P O R T E D  F U N C T I O N S >------------------------------------------]]return {webarchive = webarchive};