Для документации этого модуля может быть создана страница Модуль:CiteWeb/doc
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;"> ' .. 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 local is_webcitation_archive = false; if is(args['archive-url']) then if mw.ustring.find(args['archive-url'], 'webcitation.org', 1, true) then is_webcitation_archive = true 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(';') .. ' ' .. 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(';') .. ' ' .. replace(args['coauthors'], '^(.-)%.?$', '%1.') .. ': ') end table.insert(str, '</i> ') end -- Редактор if is(args['editor']) then table.insert(str, ' ' .. args['editor'] .. ': ') end -- URL, заголовок local link; local title = replace(replace(args['title'] or '', '%[', '['), '%]', ']'); local dot = needDot(title); if (urlstatus == 'dead' or urlstatus == 'unfit') and is(args['archive-url']) and not is_webcitation_archive 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, ' <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, ' (' .. args['format'] .. ')') end -- Пометка о недоступности if (urlstatus == 'dead' or urlstatus == 'unfit') and (not is(args['archive-url']) or is_webcitation_archive) then dot = true; table.insert(str, frame:expandTemplate { title = 'ref-info', args = { 'недоступная ссылка — [//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, ' <i>' .. args['website'] .. '</i>') end -- Страницы if is(args['pages']) then dot = true; table.insert(str, ' ' .. args['pages']) end -- Страница if is(args['page']) then dot = true; table.insert(str, ' ' .. args['page']) end -- Место, издательство if is(args['publisher']) then insertDot(str, is(args['subtitle']), dot) dot = true; table.insert(str, ' '); if is(args['location']) then table.insert(str, args['location'] .. ': ') end table.insert(str, args['publisher']) end -- Дата if is(args['date']) then dot = true; table.insert(str, ' (' .. formatDate('j xg Y', args['date']) .. ')') elseif is(args['year']) then dot = true; if is(args['month']) then table.insert(str, ' (' .. args['month'] .. ' ' .. args['year'] .. ')') else table.insert(str, ' (' .. args['year'] .. ')') end end -- Точка insertDot(str, is(args['subtitle']), dot) -- DOI if is(args['doi']) then table.insert(str, ' [[Идентификатор цифрового объекта|doi]]:[http://dx.doi.org/' .. args['doi'] .. ' ' .. args['doi'] .. '].') end -- Описание if is(args['description']) then table.insert(str, ' — ' .. args['description']) insertDot(str, true, needDot(args['description'])) end -- Цитата if is(args['quote']) then table.insert(str, ' — «' .. args['quote'] .. '»') insertDot(str, true, needDot(args['quote'])) end -- Дата обращения if is(args['access-date']) then table.insert(str, ' <small>Дата обращения: ' .. formatDate('j xg Y', args['access-date']) .. '.</small>') end -- Дата архивирования if is(args['archive-date']) and is(args['archive-url']) then if urlstatus == 'live' or is_webcitation_archive then table.insert(str, ' <small>[' .. args['archive-url'] .. ' Архивировано] ' .. formatDate('j xg Y', args['archive-date']) .. ' года.</small>') elseif urlstatus == 'unfit' then table.insert(str, ' <small>Архивировано ' .. formatDate('j xg Y', args['archive-date']) .. ' года.</small>') else table.insert(str, ' <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;