Interested Article - Hatnote
- 2021-08-06
- 1
Этот модуль относится к
критическим
. У него очень много включений или он используется с подстановкой. Из-за опасности вандализма или ошибочного редактирования он был защищён.
|
Прежде чем вносить какие-либо изменения в этот модуль, просьба
оттестировать
их в
/песочнице
и проверить результат на странице с
/контрольными примерами
. Вносить тестированные изменения в этот модуль следует ровно одной правкой.
|
Модуль предназначен для реализации hatnote-шаблонов (например, {{ основная статья }} , {{ см. также }} ). Также он содержит несколько функций для работы со ссылками и отслеживания ошибок. См. тесты на странице Шаблон:Основная статья/тесты .
Основные функции
Основные функции содержатся в таблице
p
, все функции можно вызывать как из других модулей, так и через
{{
}}
. При вызове из модуля функции принимают первым параметром таблицу с аргументами. Все описанные ниже параметры являются аргументами этой таблицы. Некоторые параметры принимают булевоподобные значения: их перечисление можно найти
здесь
.
parse_link
Принимает на вход ссылку, возвращает два значения: целевую страницу и видимую часть ссылки. Если ссылку не удалось разобрать, возвращает
nil
. Наличие квадратных скобок не обязательно.
format_link
Формирует вики-ссылку. Превращает
#
в ссылках на разделы в знак параграфа, отбитый пробелами, делая их более читабельными (см.
{{
ссылка на раздел
}}
).
Параметры:
- первый параметр: название целевой страницы или вики-ссылка.
-
второй параметр: название раздела. Параметр будет проигнорирован, если раздел уже задан в первом параметре через
#
. - третий параметр: видимый текст ссылки.
remove_precision
Убирает уточнение из первого параметра (см. {{ без уточнения }} ).
is_disambig
Функция, определяющая, является ли первый параметр страницей разрешения неоднозначности . Список шаблонов неоднозначностей берется со страницы MediaWiki:Disambiguationspage .
list
Формирует список из вики-ссылок.
Параметры:
- нумерованные параметры — ссылки на страницы.
-
| l1 =
,| l2 =
и т. д. — текст ссылок. -
| list_sep =
или| разделитель списка =
: разделитель списка, по умолчанию — «, ». -
| natural_join =
: при неложном значении вместо последнего разделителя выводится союз «и». -
| links_ns =
или| ПИ ссылок =
: ко всем ссылкам добавляется префикс указанного пространства имен. -
| bold_links =
или| ссылки болдом =
: при непустом и неложном значении каждая ссылка выделяется полужирным.
Возвращает таблицу, для неё предусмотрен метод
tostring()
и конкатенация. Именованные параметры этой таблицы — булевы переменные, истинные при обнаружении проблем. Отслеживаемые проблемы:
red_link
,
bad_format
,
formatted
,
unparsable_link
. Их описание
.
hatnote
Формирует код
<div class="hatnote">...</div>
.
Параметры:
- первый параметр — текст заметки.
-
| id =
: id заметки. -
| extraclasses =
: дополнительные классы заметки. -
| hide_disambig =
: при непустом и неложном значении к тексту добавляется классdabhide
, скрывающий подсветку для пользователей гаджета подсветки неоднозначностей .
main
Генерирует текст-заметку. Позволяет ссылаться на неограниченное число страниц. Синтаксис:
- вызов из вики-текста:
-
{{#invoke:Hatnote|main|префикс= префикс |префикс мн. ч.= префикс для нескольких ссылок |разделитель списка= разделитель списка |ПИ ссылок= пространство имен |extraclasses = дополнительные классы |точка= true / false |hide_disambig= true / false}}
- вызов из другого модуля:
-
-- подключение модуля local hatnote = require('Модуль:Hatnote').main -- пример использования без изменения категорий по умолчанию local res1 = hatnote{ 'Какая-то статья', l1 = 'Какой-нибудь текст ссылки', prefix = 'Основная статья:', prefix_plural = 'Основные статьи:', dot = true, nocat = args.nocat -- следует всегда передавать nocat, если он предусмотрен } -- и с изменением local res2 = hatnote({ 'Еще какая-то статья', prefix = 'См. также:', list_sep = '; ', natural_join = false, nocat = args.nocat }, { red_link = 'Википедия:Статьи с шаблоном «См. также» с красными ссылками' })
Параметры:
-
| prefix =
или| префикс =
: обязательный параметр, текст перед списком ссылок. -
| prefix_plural =
или| префикс мн. ч. =
: если ссылок несколько, для префикса вместо предыдущего параметра будет использован этот. -
| sep =
или| разделитель =
: разделитель между префиксом и списком ссылок. -
| dot =
или| точка =
: при непустом и неложном значении выводится точка в конце. -
| nocat =
: при непустом и неложном значении отключается категоризация. -
| empty_list_message =
: сообщение об ошибке, выводящееся при пустом списке ссылок. По умолчанию — «Не указано ни одной страницы». -
| preview_error =
: при непустом и неложном значении ошибка при пустом списке ссылок выводится только во время предпросмотра.
Функция также принимает все параметры функций
list
и
hatnote
и передает их без изменения в эти функции.
Вторым параметром (при вызове через другой модуль) функция принимает таблицу с переназначенными категориями. Их идентификаторы :
Служебные функции
Находятся в таблице
tr
, предназначены для отслеживания проблем и вывода сообщений об ошибках. Все функции можно вызывать только из других модулей.
define_categories
tr.define_categories(tracking_categories)
Создает объект, представляющий собой таблицу с категориями и функцией для их добавления. Первым параметром передается ассоциированный массив с идентификаторами отслеживающих категорий.
add
categories:add(type, nocat)
или
categories:add(category_name, nocat)
Добавляет в таблицу категории. Первый параметр — либо идентификатор, объявленный в
define_categories()
, либо название категории. Второй параметр — отключение категоризации.
error
tr.error(msg, categories, preview_only)
Выводит сообщение об ошибке. Если ошибка генерируется шаблоном, то отображается название этого шаблона; если прямым вызовом через {{ }} , то название вызываемого модуля.
Параметры:
-
msg
: текст сообщения. -
categories
: либо , возвращаемыйdefine_categories()
, либо строка с категориями. -
preview_only
: при непустом и неложном значении ошибка выводится только во время предпросмотра.
Отслеживаемые случаи
-
no_prefix
— не задан префикс. Также выводится сообщение об ошибке. -
no_links
— не задано ни одной ссылки. Также выводится сообщение об ошибке (либо в тексте статьи, либо только во время предварительного просмотра, подробнее см. ). -
red_link
— параметр содержит ссылку на несуществующую статью. -
bad_format
— параметр содержит разделитель{{ ! }}
вместо параметра| l x =
или лишние квадратные скобки. -
formatted
— параметр содержит<span
(в таком случае он не парсится, а выдаётся в готовом виде). Нужно для поддержки шаблонов {{ не переведено }} в качестве параметров. -
unparsable_link
— параметр содержит нестандартное оформление, которое не может быть разобрано модулем (например,{{ см. также | [https://example.com внешние ссылки] }}
или{{ см. также | посторонний текст помимо [[ссылка|ссылки]] }}
).
Использование в других модулях
Некоторые функции используются в следующих модулях ( ):
local get_args = require('Module:Arguments').getArgs
local mError
local yesno = function (v) return require('Module:Yesno')(v, true) end
local p, tr = {}, {}
local current_title = mw.title.getCurrentTitle()
local tracking_categories = {
no_prefix = 'Википедия:Страницы с модулем Hatnote без указания префикса',
no_links = 'Википедия:Страницы с модулем Hatnote без ссылок',
red_link = 'Википедия:Страницы с модулем Hatnote с красной ссылкой',
bad_format = 'Википедия:Страницы с модулем Hatnote с некорректно заполненными параметрами',
unparsable_link = 'Википедия:Страницы с модулем Hatnote с нечитаемой ссылкой',
formatted = 'Википедия:Страницы с модулем Hatnote с готовым форматированием',
}
local function index(t1, t2)
return setmetatable(t1, {__index = t2})
end
local function concat(e1, e2)
return tostring(e1) .. tostring(e2)
end
function tr.define_categories(tracked_cases)
local categories = setmetatable({}, {
__tostring = function (self) return table.concat(self) end,
__concat = concat
})
function categories:add(element, nocat)
if not nocat then
local cat_name
if tracked_cases and tracked_cases[element] then
cat_name = tracked_cases[element]
else
cat_name = element
end
table.insert(self, string.format('[[Категория:%s]]', cat_name))
end
end
return categories
end
function tr.error(msg, categories, preview_only)
local current_frame = mw.getCurrentFrame()
local parent_frame = current_frame:getParent()
local res_frame_title = parent_frame and parent_frame:getTitle() ~= current_title.prefixedText and
parent_frame:getTitle() or
current_frame:getTitle()
if not preview_only or current_frame:preprocess('{{REVISIONID}}') == '' then
mError = require('Module:Error')
return mError.error{
tag = 'div',
string.format('Ошибка в [[%s]]: %s.'
.. (preview_only and '<br><small>Это сообщение показывается только во время предпросмотра.</small>' or ''), res_frame_title, msg)
} .. categories
else
return categories
end
end
function p.parse_link(frame)
local args = get_args(frame)
local link = args[1]:gsub('\n', '')
local label
link = mw.text.trim(link:match('^%[%[([^%]]+)%]%]$') or link)
if link:sub(1, 1) == '/' then
label = link
link = current_title.prefixedText .. link
end
link = link:match(':?(.+)')
if link:match('|') then
link, label = link:match('^([^%|]+)%|(.+)$')
end
if not mw.title.new(link) then
return nil, nil
end
return link, label
end
function p.format_link(frame)
-- {{ссылка на раздел}}
local args = get_args(frame)
local link, section, label = args[1], args[2], args[3]
if not link then
link = current_title.prefixedText
if section then
link = '#' .. section
label = label or '§ ' .. section
end
else
local parsed_link, parsed_label = p.parse_link{link}
if parsed_link then
link = parsed_link
else
return link
end
if section and not link:match('#') then
link = link .. '#' .. section
if parsed_label then
parsed_label = parsed_label .. '#' .. section
end
end
label = (label or parsed_label or link):gsub('^([^#]-)#(.+)$', '%1 § %2')
end
if label and label ~= link then
return string.format('[[:%s|%s]]', link, label)
else
return string.format('[[:%s]]', link)
end
end
function p.remove_precision(frame)
-- {{без уточнения}}
local args = get_args(frame)
local title = args[1]
return title:match('^(.+)%s+%b()$') or title
end
function p.is_disambig(frame)
local args = get_args(frame)
local title = args[1]
local page = mw.title.new(title)
if not page or not page.exists or mw.title.equals(page, current_title) then
return false
end
local page_content = page:getContent()
local mw_list_content = mw.title.new('MediaWiki:Disambiguationspage'):getContent()
local lang = mw.language.getContentLanguage()
for template in mw.ustring.gmatch(mw_list_content, '%*%s?%[%[Шаблон:([^%]]+)') do
if page_content:match('{{' .. template) or page_content:match('{{' .. lang:lcfirst(template)) then
return true
end
end
return false
end
function p.list(frame)
local args = get_args(frame, {trim = false})
local list_sep = args.list_sep or args['разделитель списка'] or ', '
local last_list_sep = yesno(args.natural_join) ~= false and ' и ' or list_sep
local links_ns = args.links_ns or args['ПИ ссылок']
local bold_links = yesno(args.bold_links or args['ссылки болдом'])
local res_list = {}
local tracked = {
red_link = false,
bad_format = false,
formatted = false,
unparsable_link = false
}
local i = 1
while args[i] do
local link = args[i]
local label = args['l' .. i]
local element = ''
if link:match('<span') then -- TODO: переписать
tracked.formatted = true
element = link -- for {{не переведено}}
else
local bad_format = (link:match('|') or link:match('[%[%]]')) ~= nil
local parsed_link, parsed_label = p.parse_link{link}
if parsed_link then
tracked.bad_format = tracked.bad_format or bad_format
if links_ns then
parsed_label = parsed_label or parsed_link
parsed_link = mw.site.namespaces[links_ns].name .. ':' .. parsed_link
end
local title = mw.title.new(parsed_link)
tracked.red_link = tracked.red_link or not (title.isExternal or title.exists)
element = p.format_link{parsed_link, nil, label or parsed_label}
else
tracked.unparsable_link = true
element = link
end
end
if bold_links then
element = string.format('<b>%s</b>', element)
end
table.insert(res_list, element)
i = i + 1
end
return setmetatable(res_list, {
__index = tracked,
__tostring = function (self) return mw.text.listToText(self, list_sep, last_list_sep) end,
__concat = concat,
__pairs = function (self) return pairs(tracked) end
})
end
function p.hatnote(frame)
local args = get_args(frame)
local text = args[1]
local id = args.id
local extraclasses = args.extraclasses
local hide_disambig = yesno(args.hide_disambig)
local res = mw.html.create('div')
:attr('id', id)
:addClass('hatnote')
:addClass('navigation-not-searchable')
:addClass(extraclasses)
:wikitext(text)
if hide_disambig then
res:addClass('dabhide')
end
return res
end
function p.main(frame, _tracking_categories)
local args = get_args(frame, {trim = false})
local prefix = args.prefix or args['префикс']
local prefix_plural = args.prefix_plural or args['префикс мн. ч.']
local sep = args.sep or args['разделитель'] or ' '
local dot = yesno(args.dot or args['точка']) and '.' or ''
local nocat = yesno(args.nocat)
local preview_error = yesno(args.preview_error)
local empty_list_message = args.empty_list_message or 'Не указано ни одной страницы'
categories = tr.define_categories(index(_tracking_categories or {}, tracking_categories))
if not prefix then
categories:add('no_prefix', nocat)
return tr.error('Не указан префикс', categories)
end
if not args[1] then
categories:add('no_links', nocat)
return tr.error(empty_list_message, categories, preview_error)
end
if args[2] and prefix_plural then
prefix = prefix_plural
end
local list = p.list(args)
for k, v in pairs(list) do
if type(v) == 'boolean' and v then
categories:add(k, nocat)
end
end
return p.hatnote(index({prefix .. sep .. list .. dot}, args)) .. categories
end
return index(p, tr)
- 2021-08-06
- 1