Модуль:Партал

Зьвесткі зь Вікіпэдыі — вольнай энцыкляпэдыі
Перайсьці да навігацыі Перайсьці да пошуку

Дакумэнтацыю да гэтага модуля можна стварыць у Модуль:Партал/Дакумэнтацыя

--[==[ Гэты модуль — перапісаны на Lua код шаблёну {{Партал}}.
-- Мае дзьве вонкавыя функцыі:
-- p.portal, якая складае сьпіс парталаў;
-- p.image, якая ўтварае назву выяву для асобна ўзятага парталу.

-- Зьвесткі пра выявы парталаў захоўваюцца ў падмодулях [[Модуль:Партал/выявы]], пералічаных ніжэй:
-- [[Модуль:Партал/выявы/а]]		— для парталаў, якія пачынаюцца зь літары «А».
-- [[Модуль:Партал/выявы/б]]		— для парталаў, якія пачынаюцца зь літары «Б».
-- [[Модуль:Партал/выявы/в]]		— для парталаў, якія пачынаюцца зь літары «В».
-- [[Модуль:Партал/выявы/г]]		— для парталаў, якія пачынаюцца зь літары «Г».
-- [[Модуль:Партал/выявы/д]]		— для парталаў, якія пачынаюцца зь літары «Д».
-- [[Модуль:Партал/выявы/е]]		— для парталаў, якія пачынаюцца зь літары «Е».
-- [[Модуль:Партал/выявы/ё]]		— для парталаў, якія пачынаюцца зь літары «Ё».
-- [[Модуль:Партал/выявы/ж]]		— для парталаў, якія пачынаюцца зь літары «Ж».
-- [[Модуль:Партал/выявы/з]]		— для парталаў, якія пачынаюцца зь літары «З».
-- [[Модуль:Партал/выявы/і]]		— для парталаў, якія пачынаюцца зь літары «І».
-- [[Модуль:Партал/выявы/к]]		— для парталаў, якія пачынаюцца зь літары «К».
-- [[Модуль:Партал/выявы/л]]		— для парталаў, якія пачынаюцца зь літары «Л».
-- [[Модуль:Партал/выявы/м]]		— для парталаў, якія пачынаюцца зь літары «М».
-- [[Модуль:Партал/выявы/н]]		— для парталаў, якія пачынаюцца зь літары «Н».
-- [[Модуль:Партал/выявы/о]]		— для парталаў, якія пачынаюцца зь літары «О».
-- [[Модуль:Партал/выявы/п]]		— для парталаў, якія пачынаюцца зь літары «П».
-- [[Модуль:Партал/выявы/р]]		— для парталаў, якія пачынаюцца зь літары «Р».
-- [[Модуль:Партал/выявы/с]]		— для парталаў, якія пачынаюцца зь літары «С».
-- [[Модуль:Партал/выявы/т]]		— для парталаў, якія пачынаюцца зь літары «Т».
-- [[Модуль:Партал/выявы/у]]		— для парталаў, якія пачынаюцца зь літары «У».
-- [[Модуль:Партал/выявы/ф]]		— для парталаў, якія пачынаюцца зь літары «Ф».
-- [[Модуль:Партал/выявы/х]]		— для парталаў, якія пачынаюцца зь літары «Х».
-- [[Модуль:Партал/выявы/ц]]		— для парталаў, якія пачынаюцца зь літары «Ц».
-- [[Модуль:Партал/выявы/ч]]		— для парталаў, якія пачынаюцца зь літары «Ч».
-- [[Модуль:Партал/выявы/ш]]		— для парталаў, якія пачынаюцца зь літары «Ш».
-- [[Модуль:Партал/выявы/э]]		— для парталаў, якія пачынаюцца зь літары «Э».
-- [[Модуль:Партал/выявы/ю]]		— для парталаў, якія пачынаюцца зь літары «Ю».
-- [[Модуль:Партал/выявы/я]]		— для парталаў, якія пачынаюцца зь літары «Я».
-- [[Модуль:Партал/выявы/іншыя]]	— для парталаў, якія пачынаюцца зь якіх-кольвек іншых сымбаляў.
--                                    Сюды ўлучаюцца і лічбы, і літары лацінскага альфабэту, і дыякрытычныя знакі.
-- [[Модуль:Партал/выявы/альт]]		— для альтэрнатыўных назваў існых парталаў. Зь любых пачатковых літараў.
--
-- Падстаронкі са зьвесткамі пра выявы падзеленыя па першай літары дзеля зьмяншэньня нагрузкі на сэрвэр у выпадку зьмяненьняў ці дапаўненьняў.
-- Зьмяшчэньне ўсіх выяваў на падстаронцы [[Модуль:Партал/выявы]] ў выпадку абнаўленьня аднае з выяваў
-- прыводзіла б да перазагрузкі ўсіх старонак, якія карыстаюцца гэтым модулем.
]==]

local p = {}

local function matchImagePage(s)
	-- Шукае адпаведную падстаронку выяваў па назьве парталу
	-- і першай літары ягонай назвы ў ніжнім рэгістры.
	if type(s) ~= 'string' or #s < 1 then return end
	local firstLetter = mw.ustring.sub(s, 1, 1)
	local imagePage
	if mw.ustring.find(firstLetter, '^[а-я]') then
		imagePage = 'Модуль:Партал/выявы/' .. firstLetter
	else
		imagePage = 'Модуль:Партал/выявы/іншыя'
	end
	return mw.loadData(imagePage)[s]
end

local function getAlias(s)
	-- Вяртае альтэрнатыву з падстаронкі альтэрнатыўных зьвестак пра выявы.
	local aliasData = mw.loadData('Модуль:Партал/выявы/альт')
	for portal, aliases in pairs(aliasData) do
		for _, alias in ipairs(aliases) do
			if alias == s then
				return portal
			end
		end
	end
end

local function getImageName(s)
	-- Вяртае назву выявы для ўваходнага радку.
	local default = 'Portal-puzzle.svg|link=|alt='
	if type(s) ~= 'string' or #s < 1 then
		return default
	end
	s = mw.ustring.lower(s)
	return matchImagePage(s) or matchImagePage(getAlias(s)) or default
end

function p._portal(portals, args)
	-- Будуе рамку парталу для шаблёну {{Партал}}.
	local root = mw.html.create('div')
		:attr('role', 'navigation')
		:attr('aria-label', 'Portals')
		:addClass('noprint portal plainlist')
		:addClass(args.left and 'tleft' or 'tright')
		:css('margin', args.margin or (args.left == 'yes' and '0 1em 1em 0') or '0 0 1em 1em')
		:css('border', 'solid #aaa 1px')
		:newline()

	-- Запачаткоўвае сьпіс. Адпавядае пачатку вікі-табліцы ў старым [[Шаблён:Партал]].
	local listroot = root:tag('ul')
		:css('display', 'table')
		:css('box-sizing', 'border-box')
		:css('padding', '1ex')
		:css('max-width', '175px')
		:css('width', type(args.boxsize) == 'string' and (args.boxsize .. 'px') or nil)
		:css('background', '#f9f9f9')
		:css('font-size', '85%')
		:css('line-height', '110%')
		:css('font-style', 'italic')
		:css('font-weight', 'bold')

	-- Выводзіць парталы, зададзеныя ў пазыцыйных аргумэнтах.
	for _, portal in ipairs(portals) do
		local image = getImageName(portal)

		-- Генэруе html-код для выявы і назвы парталу.
		listroot
			:newline()
			:tag('li')
				:css('display', 'table-row')
				:tag('span')
					:css('display', 'table-cell')
					:css('padding', '0.2em')
					:css('vertical-align', 'middle')
					:css('text-align', 'center')
					:wikitext(string.format('[[Файл:%s|32x28пкс|class=noviewer]]', image))
					:done()
				:tag('span')
					:css('display', 'table-cell')
					:css('padding', '0.2em 0.2em 0.2em 0.3em')
					:css('vertical-align', 'middle')
					:css('text-align', 'center')
					:wikitext(string.format('Вікіпэдыя мае партал\n«[[Партал:%s|%s]]»', portal, portal, args['break'] and '<br />' or ' '))
	end
	return tostring(root)
end

function p._image(portals)
	-- Абгортачная функцыя, каб getImageName() была дасяжная праз #invoke.
	local name = getImageName(portals[1])
	return name:match('^(.-)|') or name -- ДАРАБІЦЬ: зрабіць больш элегантны спосаб аддзяляць рамкі і інш. ад назвы выявы
end

local function getAllImageTables()
	-- Вяртае масіў з усімі падстаронкамі выяваў (без альтэрнатываў), загружаны mw.loadData.
	local images = {}
	for i, subpage in ipairs{'а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж', 'з', 'і', 'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'э', 'ю', 'я', 'іншыя'} do
		images[i] = mw.loadData('Модуль:Партал/выявы/' .. subpage)
	end
	return images
end

function p._displayAll(portals, args)
	-- Выводзіць усе парталы, якія маюць зьвязаныя выявы. Функцыя прызначаная не для артыкулаў, а толькі для службовага выкарыстаньня.
	local lang = mw.language.getContentLanguage()
	local count = 1
	for _, imageTable in ipairs(getAllImageTables()) do
		for portal in pairs(imageTable) do
			portals[count] = lang:ucfirst(portal)
			count = count + 1
		end
	end
	return p._portal(portals, args)
end

function p._imageDupes()
	-- Шукае падстаронкі на прадмет дублікатаў выяваў. Калі такія выявы існуюць, гэта не абавязкова памылка,
	-- бо розныя парталы могуць карыстацца аднымі і тымі ж выявамі. Аднак функцыя дапамагае вызначыць выявы,
	-- якія варта перамясьціць на падстаронку альтэрнатыўных назваў.
	local exists, dupes = {}, {}
	for _, imageTable in ipairs(getAllImageTables()) do
		for portal, image in pairs(imageTable) do
			if not exists[image] then
				exists[image] = portal
			else
				table.insert(dupes, string.format('Выява «[[:Файл:%s|%s]]» выкарыстоўваецца ў парталах «%s» і «%s».', image, image, exists[image], portal))
			end
		end
	end
	if #dupes < 1 then
		return 'Дубляваныя выявы адсутнічаюць.'
	else
		return 'Знойдзеныя такія дубляваныя выявы:\n* ' .. table.concat(dupes, '\n* ')
	end
end

local function processPortalArgs(args)
	-- Апрацоўвае табліцу аргумэнтаў і вяртае дзьве табліцы: масіў назваў парталаў дзеля апрацоўкі ў ipairs, і табліцу
	-- найменных аргумэнтаў, якія вызначаюць налады стыляў і інш. Карыстацца ipairs даводзіцца, паколькі нам патрэбныя
        -- сьпісы ўсіх парталаў у тым парадку, у якім яны былі перададзеныя ў шаблён, а таксама неабходна яўна зьвяртацца да
        -- пазыцыйных аргумэнтаў, напрыклад {{Партал|2=Хрысьціянства}}. Паводзіны ipairs у выпадку, калі прысутнічаюць пустыя
        -- значэньні, нявызначаныя, таму мусім пераканацца, што ўсе яны выдаленыя.
	args = type(args) == 'table' and args or {}
	local portals = {}
	local namedArgs = {}
	for k, v in pairs(args) do
		if type(k) == 'number' and type(v) == 'string' then -- Правяраем, ці ня маем нерадковых назваў парталаў.
			table.insert(portals, k)
		elseif type(k) ~= 'number' then
			namedArgs[k] = v
		end
	end
	table.sort(portals)
	for i, v in ipairs(portals) do
		portals[i] = args[v]
	end
	return portals, namedArgs
end

local function makeWrapper(funcName)
	-- Апрацоўвае вонкавыя аргумэнты і перадае ў іншыя функцыі.
	return function (frame)
		-- Пры выкліку праз #invoke узяць аргумэнты, перададзеныя ў шаблёне
		-- альбо ў #invoke. Інакш лічым, што аргумэнты перададзеныя наўпрост
		-- з адладачнай кансолі ці зь іншага Lua-модулю.
		local origArgs
		if type(frame.getParent) == 'function' then
			origArgs = frame:getParent().args
			for k, v in pairs(frame.args) do
				origArgs = frame.args
				break
			end
		else
			origArgs = frame
		end
		-- Абразае пропусты і выдаляе пустыя аргумэнты.
		local args = {}
		for k, v in pairs(origArgs) do
			if type(v) == 'string' then
				v = mw.text.trim(v)
			end
			if v ~= '' then
				args[k] = v
			end
		end
		if args[1] == nil then
			args[1] = mw.title.getCurrentTitle().rootText -- Хак: калі няма аргумэнтаў, узяць назву старонкі, зь якой выкліканы шаблён
		end
		return p[funcName](processPortalArgs(args)) -- перадае ў функцыю дзьве табліцы: масіў назваў парталаў і табліцу найменаваных аргумэнтаў.
	end
end

for _, funcName in ipairs{'portal', 'image', 'imageDupes', 'displayAll'} do
	p[funcName] = makeWrapper('_' .. funcName)
end

return p