Модуль:Hatnote

Материал из Frog Archive, свободного справочника
Перейти к навигации Перейти к поиску

Для документации этого модуля может быть создана страница Модуль:Hatnote/doc

local get_args = require('Module:Arguments').getArgs
local mError = require('Module:Error')
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 с некорректно заполненными параметрами'
}

local function index(t1, t2)
	return setmetatable(t1, {__index = t2})
end

local function concat(e1, e2) 
	return tostring(e1) .. tostring(e2)
end

function tr.make_categories(tracking_categories)
	local categories = setmetatable({}, {
		__tostring = function (self) return table.concat(self) end, 
		__concat = concat
	})
	
	function categories:add(type, nocat)
		if not nocat then
			table.insert(self, string.format('[[Категория:%s]]', tracking_categories[type]))
		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
		return mError.error{string.format('Ошибка в [[%s]]: %s', res_frame_title, msg)} .. categories
	else 
		return categories
	end
end

local function parse_link(link, label)
	link = link:gsub('\n', '')
	link = link:match('%[%[:?([^%]]+)%]%]') or link:match(':?(.+)')
	if link:match('|') then
		link, label = link:match('^([^%|]+)%|(.+)$')
	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.text
		if section then
			link = '#' .. section
			label = label or '§ ' .. section
		end
	else
		link, label = parse_link(link, label)
		if section and not link:match('#') then
			link = link .. '#' .. section
		end
		
		label = (label or link):gsub('^([^#]-)#(.+)$', '%1 § %2')
	end
	
	return string.format('[[:%s|%s]]', link, label or link)
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.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 = ''
	local tracked = {
		red_link = false,
		bad_format = false
	}
	
    local i = 1
	while args[i] do
		local link = args[i]
		local label = args['l' .. i]
		
		tracked.bad_format = tracked.bad_format or link:match('|') or link:match('[%[%]]')
		link, label = parse_link(link, label)
		
		if links_ns then
			label = label or link
			link = mw.site.namespaces[links_ns].name .. ':' .. link
		end
		tracked.red_link = tracked.red_link or not mw.title.new(link).exists
		
        local element = p.format_link{link, nil, label}
        if bold_links then
			element = string.format('<b>%s</b>', element)
		end
		
        if res ~= '' then
        	if args[i] and not args[i + 1] then
        		res = res .. last_list_sep
    		else
    			res = res .. list_sep
        	end
        end
        
		res = res .. element
        i = i + 1
	end
	
	return setmetatable({res}, {
		__index = tracked,
		__tostring = function (self) return self[1] end,
		__concat = concat
	})
end

function p.hatnote(frame)
	local args = get_args(frame)
	local text = args[1]
	local extraclasses = args.extraclasses
	local hide_disambig = yesno(args.hide_disambig)
	
	local res = mw.html.create('div')
		:addClass('hatnote')
		: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)
	
	categories = tr.make_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('Не указано ни одной страницы', categories, preview_error)
	end
	
	if args[2] and prefix_plural then
		prefix = prefix_plural
	end
	
	local list = p.list(args)
	if list.red_link then
		categories:add('red_link', nocat)
	end
	if list.bad_format then
		categories:add('bad_format', nocat)
	end
	
	return p.hatnote(index({prefix .. sep .. list .. dot}, args)) .. categories
end

return index(p, tr)