Очікує на перевірку

Модуль:Hatnote

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку
{{i}} Документація модуля[перегляд] [редагувати] [історія] [очистити кеш]

This is a meta-module that provides various functions for making hatnotes. It implements the {{hatnote}} template, for use in hatnotes at the top of pages, and the {{format link}} template, which is used to format a wikilink for use in hatnotes. It also contains a number of helper functions for use in other Lua hatnote modules.

Use from wikitext

The functions in this module cannot be used directly from #invoke, and must be used through templates instead. Please see Template:Hatnote and Template:Format link for documentation.

Use from other Lua modules

To load this module from another Lua module, use the following code.

local mHatnote = require('Module:Hatnote')

You can then use the functions as documented below.

Hatnote

mHatnote._hatnote(s, options)

Formats the string s as a hatnote. This encloses s in the tags <div class="hatnote">...</div>. Options are provided in the options table. Options include:

  • options.extraclasses - a string of extra classes to provide
  • options.selfref - if this is not nil or false, adds the class "selfref", used to denote self-references to Wikipedia (see Template:Selfref))

The CSS of the hatnote class is defined in MediaWiki:Common.css.

Example 1
mHatnote._hatnote('This is a hatnote.')

Produces: <div class="hatnote">This is a hatnote.</div>

Displays as:

Example 2
mHatnote._hatnote('This is a hatnote.', {extraclasses = 'boilerplate seealso', selfref = true})

Produces: <div class="hatnote boilerplate seealso selfref">This is a hatnote.</div>

Displayed as:

mHatnote._formatLink(link, display)

Formats link as a wikilink for display in hatnote templates, with optional display value display. Categories and files are automatically escaped with the colon trick, and links to sections are automatically formatted as page § section, rather than the MediaWiki default of page#section.

Examples
mHatnote._formatLink('Лев') ⊟ [[Lion]] ⊟ Помилка скрипту: Функції «formatLink» не існує.
mHatnote._formatLink('Лев#Етимологія') ⊟ [[Lion#Etymology|Lion § Etymology]] ⊟ Помилка скрипту: Функції «formatLink» не існує.
mHatnote._formatLink('Категорія:Леви') ⊟ [[:Category:Lions]] ⊟ Помилка скрипту: Функції «formatLink» не існує.
mHatnote._formatLink('Лев#Етимологія', 'Етимологія левів') ⊟ [[Лев#Етимологія|Етимологія левів]] ⊟ Помилка скрипту: Функції «formatLink» не існує.

Форматовані сторінки

mHatnote.formatPages(...)

Formats a list of pages using the _formatLink function, and returns the result as an array. For example, the code mHatnote.formatPages('Lion', 'Category:Lions', 'Lion#Etymology') would produce an array like {'[[Lion]]', '[[:Category:Lions]]', '[[Lion#Etymology|Lion § Etymology]]'}.

Format page tables

mHatnote.formatPageTables(...)

Takes a list of page/display tables, formats them with the _formatLink function, and returns the result as an array. Each item in the list must be a table. The first value in the table is the link, and is required. The second value in the table is the display value, and is optional. For example, the code mHatnote.formatPages({'Lion', 'the Lion article'}, {'Category:Lions'}, {'Lion#Etymology', 'the etymology of lion'}) would produce an array like {'[[Lion|the Lion article]]', '[[:Category:Lions]]', '[[Lion#Etymology|the etymology of lion]]'}.

Find namespace id

mHatnote.findNamespaceId(link, removeColon)

Finds the namespace id of the string link, which should be a valid page name, with or without the section name. This function will not work if the page name is enclosed with square brackets. When trying to parse the namespace name, colons are removed from the start of the link by default. This is helpful if users have specified colons when they are not strictly necessary. If you do not need to check for initial colons, set removeColon to false.

Examples
mHatnote.findNamespaceId('Lion') ⊟ 0
mHatnote.findNamespaceId('Category:Lions') ⊟ 14
mHatnote.findNamespaceId(':Category:Lions') ⊟ 14
mHatnote.findNamespaceId(':Category:Lions', false) ⊟ 0 (the namespace is detected as ":Category", rather than "Category")

Make wikitext error

mHatnote.makeWikitextError(msg, helpLink, addTrackingCategory)

Formats the string msg as a red wikitext error message, with optional link to a help page helpLink. Normally this function also adds Category:Hatnote templates with errors; however, if addTrackingCategory is not false after being passed through Module:Yesno, then the category is suppressed. This means that the category can be suppressed with addTrackingCategory values including "no", "n", 0, "false", and false.

Examples:

mHatnote.makeWikitextError('an error has occurred')Error: an error has occurred.
mHatnote.makeWikitextError('an error has occurred', 'Template:Example#Errors')Error: an error has occurred (help).

Examples

For examples of how this module is used in other Lua modules, see the following (listed in order of complexity):

local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
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 з готовим форматуваннням',
}
	
function p.defaultClasses(inline)
	-- Provides the default hatnote classes as a space-separated string; useful
	-- for hatnote-manipulation modules like [[Module:Hatnote group]].
	return
		(inline == 1 and 'hatnote-inline' or 'hatnote') .. ' ' ..
		'navigation-not-searchable'
end	

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.makeWikitextError(msg, helpLink, addTrackingCategory, title)
	-- Formats an error message to be returned to wikitext. If
	-- addTrackingCategory is not false after being returned from
	-- [[Module:Yesno]], and if we are not on a talk page, a tracking category
	-- is added.
	checkType('makeWikitextError', 1, msg, 'string')
	checkType('makeWikitextError', 2, helpLink, 'string', true)
	--yesno = require('Module:Yesno')
	title = title or mw.title.getCurrentTitle()
	-- Make the help link text.
	local helpText
	if helpLink then
		helpText = ' ([[' .. helpLink .. '|довідка]])'
	else
		helpText = ''
	end
	-- Make the category text.
	local category
	if not title.isTalkPage -- Don't categorise talk pages
		and title.namespace ~= 2 -- Don't categorise userspace
		and yesno(addTrackingCategory) ~= false -- Allow opting out
	then
		category = 'Шаблони Hatnote з помилками'
		category = mw.ustring.format(
			'[[%s:%s]]',
			mw.site.namespaces[14].name,
			category
		)
	else
		category = ''
	end
	return mw.ustring.format(
		'<strong class="error">Помилка: %s%s.</strong>%s',
		msg,
		helpText,
		category
	)
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 '§&nbsp;' .. 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 §&nbsp;%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, s)
	local args = get_args(frame)
	local text = s or args[1]
	local id = args.id
	local inline = args.inline
	local extraclasses = args.extraclasses
	local hide_disambig = yesno(args.hide_disambig)
	
	local res = mw.html.create(inline == 1 and 'span' or 'div')
		:attr('id', id)
		:addClass(p.defaultClasses(inline))
		:addClass(extraclasses)
		:addClass(args.selfref and 'selfref' or nil)
		:wikitext(text)
	
	if hide_disambig then
		res:addClass('dabhide')
	end
	
	return mw.getCurrentFrame():extensionTag{
		name = 'templatestyles', args = { src = 'Module:Hatnote/styles.css' }
	} .. tostring(res)
end

--------------------------------------------------------------------------------
-- Функція для виклику коду з англвікі
--------------------------------------------------------------------------------

function p.hatnote(frame)
	local args = get_args(frame)
	local s = args[1]
	if not s then
		return p.makeWikitextError(
			'текст не зазначено',
			'Шаблон:Hatnote#Помилки',
			args.category
		)
	end
	return p._hatnote(frame, s)
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)