Изменения

local p = {};

require('strict');
local listRef = require('Module:Languages').list_ref;
local boxDate = require('Module:Calendar').bxDate;

local error_cats = {
['noname_param'] = 'К:Википедия:Cite web (некорректное использование: непустой неименованный параметр)',
['empty_title'] = 'К:Википедия:Cite web (некорректное использование: не указан title)',
['empty_url'] = 'К:Википедия:Cite web (некорректное использование: не указан url)',
['bad_archive'] = 'К:Википедия:Cite web (некорректное использование: параметры архивации)',
['deadlink'] = 'К:Википедия:Cite web (недоступные ссылки без архивной копии)',
-- ['bad_lang'] = 'К:Википедия:Cite web (неверный код языка)',
-- ['deadlink_old'] = 'К:Википедия:Cite web (устаревшие параметры мёртвых ссылок)',
['empty_lang'] = 'К:Википедия:Cite web (не указан язык)',
['bad_url'] = 'К:Википедия:Cite web (некорректный url)',
['webcitation_no'] = 'К:Википедия:Cite web (заменить webcitation-архив: deadlink no)',
['webcitation_yes'] = 'К:Википедия:Cite web (заменить webcitation-архив: deadlink yes)',
}
local errors = {
['noname_param'] = '{{error|Все параметры шаблона {{tl|cite web}} должны [[T:cite web#Неименованные_параметры|иметь имя]].}}',
['empty_title'] = '{{error|Необходимо задать параметр {{code|title{{=}}}} в шаблоне {{tl|cite web}}.}}',
['empty_url'] = '{{error|Необходимо задать параметр {{code|url{{=}}}} в шаблоне {{tl|cite web}}.}}',
['bad_archive'] = '{{error|Если в шаблоне {{tl|cite web}} задаётся параметр {{code|archive-url{{=}}}}, должен задаваться и параметр {{code|archive-date{{=}}}}, и наоборот.}}',
}
local replace_params = {
['accessdate'] = 'access-date',
['archivedate'] = 'archive-date',
['archiveurl'] = 'archive-url',
['authorlink'] = 'author-link',
['first1'] = 'first',
['last1'] = 'last',
['deadurl'] = 'deadlink',
['dead-url'] = 'deadlink',
['language'] = 'lang',
['datepublished'] = 'date',
['work'] = 'website',
}

-- проверка существования переменной. возврат её, или nil если пустая
local function is(var)
if (var == '' or var == nil) then return nil else return var end
end

-- замена устаревших аргументов на их аналоги
local function prepareArgs(args)
local bad_args = {};
local new_args = {};
for param, value in pairs(args) do
if is(replace_params[param]) and not is(args[replace_params[param]]) then
param = replace_params[param];
end
new_args[param] = value;
end
return new_args, bad_args
end

-- добавление скрытого языка
local function hiddenRef(code)
return '<span class="hidden-ref" style="display:none;">&nbsp;' .. code .. '</span>'
end

local function insertDot(str, small, insert)
if insert == false then
return
end
if small then
table.insert(str, '<small>.</small>')
else
table.insert(str, '.')
end
end

local function needDot(source_str)
if mw.ustring.find(source_str, '[.?!:…]»?$') ~= nil then
return false
else
return true
end
end

local function nowiki(text)
local frame = mw.getCurrentFrame();
return frame:callParserFunction('#tag', { 'nowiki', text })
end

local function replace(source_str, pattern, replace)
return mw.ustring.gsub(source_str, pattern, replace)
end

-- форматирование даты; в случае ошибки - возврат переданного значения без изменений
local function formatDate(strFormat, txtDateIn, params)
local txtDateOut, date, status = boxDate(txtDateIn, strFormat, params)
if status.brk then
return txtDateIn
else
return txtDateOut
end
end

-- отрисовка ошибки по коду
local function expandError(code)
return mw.getCurrentFrame():preprocess(errors[code]) .. ' '
end

-- отрисовка всех категорий по их кодам
local function expandCats(cats)
local str = {};
local frame = mw.getCurrentFrame();
for _, cat in pairs(cats) do
table.insert(str, '[[' .. error_cats[cat] .. ']]')
end
return frame:preprocess(table.concat(str))
end

-- разделение их
local function splitBySlash(string)
local args = {};
local iterator = mw.ustring.gmatch(string, "[^/]+");

for w in iterator do
table.insert(args, w)
end
return args
end

-- оборачиваем главную ссылку в span с указанным языком (может быть полезно для rtl)
local function wrapLang(link, langs)
local lang_code = 'und';

if is(langs) then
local args = splitBySlash(langs);
if #args ~= 0 then
lang_code = args[1];
end
end

return '<span lang="' .. lang_code .. '">' .. link .. '</span>'
end

-- обёртка в тег цитирования
local function wrapCite(str, args)
if is(args['ref']) then
table.insert(str, 1, '<span class="citation" id="CITEREF' .. mw.uri.anchorEncode(args['ref']) .. '">');
if is(args['date']) then
table.insert(str, 2,
'<span class="citation" id="CITEREF' ..
mw.uri.anchorEncode(args['ref'] .. formatDate('Y', args['date'])) .. '">');
table.insert(str, '</span>');
end
else
table.insert(str, 1, '<span class="citation">');
end

table.insert(str, '</span>');
end

-- генерирум список языков (аргумент - список языков через слеш)
local function refLang(lang)
local args = splitBySlash(lang);

local frame = mw.getCurrentFrame();
frame.args = args

local lang_result = listRef(frame)
local hidden = false;

if #args == 1 and args[1] == 'ru' then
hidden = true;
end

return lang_result, hidden
end

function p.render(frame)
local str = {}
local cats = {}

local pFrame = frame:getParent();
local args = mw.clone(pFrame.args);
setmetatable(args, nil);

args = prepareArgs(args);

-- Проверки
-- Проверка отсутствия неименованных параметров
if is(args[1]) or is(args[2]) or is(args[3]) or is(args[4]) or is(args[5]) or is(args[6]) then
table.insert(str, expandError('noname_param'));
table.insert(cats, 'noname_param');
end

-- Проверка корректности заполнения параметров archiveurl и archivedate
if (is(args['archive-date']) ~= nil and is(args['archive-url']) == nil) or
(is(args['archive-date']) == nil and is(args['archive-url']) ~= nil) then
table.insert(str, expandError('bad_archive'));
table.insert(cats, 'bad_archive');
end

-- Проверка устаревших параметров мёртвых ссылок
-- if is(args['dead-url']) or is(args['deadurl']) then
-- table.insert(cats, error_cats['deadlink_old'])
-- end

local urlstatus = 'live';
if args['url-status'] == 'live' or args['url-status'] == 'dead' or args['url-status'] == 'unfit' then
urlstatus = args['url-status']
elseif args['deadlink'] == 'yes' then
urlstatus = 'dead'
elseif args['deadlink'] == 'unfit' then
urlstatus = 'unfit'
end

if is(args['archive-url']) then
if mw.ustring.find(args['archive-url'], 'webcitation.org', 1, true) then
if urlstatus == 'dead' or urlstatus == 'unfit' then
table.insert(cats, 'webcitation_yes')
else
table.insert(cats, 'webcitation_no')
end
end
elseif urlstatus == 'dead' then
table.insert(cats, 'deadlink')
end

-- Проверка заполнения параметра url
if is(args['url']) then
if mw.ustring.find(args['url'], '^https?://', 1, false) ~= 1 and
mw.ustring.find(args['url'], '^ftp://', 1, false) ~= 1 or mw.ustring.find(args['url'], ' ', 1, true) ~= nil then
table.insert(cats, 'bad_url')
end
else
table.insert(str, expandError('empty_url'));
table.insert(cats, 'empty_url')
end

-- Проверка заполнения параметра title
if not is(args['title']) then
table.insert(str, expandError('empty_title'));
table.insert(cats, 'empty_title')
elseif not is(args['lang']) and mw.ustring.find(args['title'], '^[0-9А-яЁё«»:;,…!? %(%)%.—№%/%&%#+-]+$') == nil then
table.insert(cats, 'empty_lang')
end

-- Формирование вывода
-- Автор
if is(args['author']) or is(args['last']) then
table.insert(str, '<i>')

local author = args['author'];
if is(args['last']) then
author = args['last']
if is(args['first']) then
author = author .. ', ' .. args['first']
end
elseif not is(args['last2']) and not is(args['coauthors']) then
author = replace(author, '^(%[*)(.-[^%.%]])(%]*)$', '%1%2%3.')
end

if is(args['author-link']) then
table.insert(str, '[[' .. args['author-link'] .. '|' .. author .. "]]")
else
table.insert(str, author)
end

-- Дополнительные сведения об авторах
for i = 2, 5 do
if is(args['last' .. i]) then
local author = nowiki(';') .. '&#32;' .. args['last' .. i];
if is(args['first' .. i]) then
author = author .. ', ' .. args['first' .. i]
end
table.insert(str, author)
end
end

if is(args['coauthors']) then
table.insert(str, nowiki(';') .. '&#32;' .. replace(args['coauthors'], '^(.-)%.?$', '%1.') .. ':&#32;')
end

table.insert(str, '</i>&#32;')
end

-- Редактор
if is(args['editor']) then
table.insert(str, ' ' .. args['editor'] .. ':&#32;')
end

-- URL, заголовок
local link;
local title = replace(replace(args['title'] or '', '%[', '&#91;'), '%]', '&#93;');
local dot = needDot(title);

if (urlstatus == 'dead' or urlstatus == 'unfit') and is(args['archive-url']) then
link = '[' .. (args['archive-url'] or '') .. ' ' .. title .. ']'
elseif urlstatus == 'unfit' then
link = title
else
link = '[' .. (args['url'] or '') .. ' ' .. title .. ']'
end
table.insert(str, wrapLang(link, args['lang']))

-- Подзаголовок
if is(args['subtitle']) then
insertDot(str, false, dot)
table.insert(str, '&#32;<small>' .. args['subtitle'] .. '</small>')
dot = needDot(args['subtitle']);
end

-- Отображение названия языка источника
local langs;
local hidden = false;
if is(args['lang']) then
langs, hidden = refLang(args['lang']);
else
langs = frame:expandTemplate { title = 'ref-und' };
hidden = true;
end
if hidden == true then
langs = hiddenRef(langs);
else
dot = true;
end
table.insert(str, langs)

-- Формат источника
if is(args['format']) then
dot = true;
table.insert(str, '&#32;(' .. args['format'] .. ')')
end

-- Пометка о недоступности
if (urlstatus == 'dead' or urlstatus == 'unfit') and not is(args['archive-url']) then
dot = true;
table.insert(str,
frame:expandTemplate { title = 'ref-info',
args = { 'недоступная ссылка&nbsp;— [//web.archive.org/web/*/' ..
args['url'] .. ' <i>история</i>]' } })
end

-- Название сайта или проекта
if is(args['website']) then
insertDot(str, is(args['subtitle']), dot)
dot = true;
table.insert(str, '&#32;<i>' .. args['website'] .. '</i>')
end

-- Страницы
if is(args['pages']) then
dot = true;
table.insert(str, '&#32;' .. args['pages'])
end

-- Страница
if is(args['page']) then
dot = true;
table.insert(str, '&#32;' .. args['page'])
end

-- Место, издательство
if is(args['publisher']) then
insertDot(str, is(args['subtitle']), dot)
dot = true;
table.insert(str, '&#32;');
if is(args['location']) then
table.insert(str, args['location'] .. ':&#32;')
end
table.insert(str, args['publisher'])
end

-- Дата
if is(args['date']) then
dot = true;
table.insert(str, '&#32;(' .. formatDate('j xg Y', args['date']) .. ')')
elseif is(args['year']) then
dot = true;
if is(args['month']) then
table.insert(str, '&#32;(' .. args['month'] .. ' ' .. args['year'] .. ')')
else
table.insert(str, '&#32;(' .. args['year'] .. ')')
end
end

-- Точка
insertDot(str, is(args['subtitle']), dot)

-- DOI
if is(args['doi']) then
table.insert(str,
'&#32;[[Идентификатор цифрового объекта|doi]]:[http://dx.doi.org/' ..
args['doi'] .. ' ' .. args['doi'] .. '].')
end

-- Описание
if is(args['description']) then
table.insert(str, '&nbsp;— ' .. args['description'])
insertDot(str, true, needDot(args['description']))
end

-- Цитата
if is(args['quote']) then
table.insert(str, '&nbsp;— «' .. args['quote'] .. '»')
insertDot(str, true, needDot(args['quote']))
end

-- Дата обращения
if is(args['access-date']) then
table.insert(str, '&#32;<small>Дата обращения: ' ..
formatDate('j xg Y', args['access-date']) .. '.</small>')
end

-- Дата архивирования
if is(args['archive-date']) and is(args['archive-url']) then
if urlstatus == 'live' then
table.insert(str,
'&#32;<small>[' ..
args['archive-url'] ..
' Архивировано] ' ..
formatDate('j xg Y', args['archive-date']) .. ' года.</small>')
elseif urlstatus == 'unfit' then
table.insert(str,
'&#32;<small>Архивировано ' ..
formatDate('j xg Y', args['archive-date']) .. ' года.</small>')
else
table.insert(str,
'&#32;<small>Архивировано из [' ..
args['url'] ..
' оригинала] ' ..
formatDate('j xg Y', args['archive-date']) .. ' года.</small>')
end
end

wrapCite(str, args);

if #cats ~= 0 and mw.title.getCurrentTitle():inNamespace(0) then
table.insert(str, expandCats(cats));
end

return table.concat(str)
end

return p;
Анонимный участник