Модуль:Transclude

Материал из Энциклопедия автомобильных номеров мира
Перейти к навигации Перейти к поиску

Этот модуль содержит функции, позволяющие вызывать внутренний шаблон из объемлющего шаблона после некоторой обработки параметров. Под объемлющим шаблоном имеется в виду шаблон, в котором написано {{#invoke:Transclude|..., например, {{Пиктограммы СГС}}. В вызове модуля указывается название функции и внутренний шаблон, вроде {{Пиктограммы СГС/основа}}, который собственно и обрабатывает аргументы, полученные от объемлющего шаблона.

Функция Код объемлющего шаблона Код его вызова Результат
call {{#invoke:Transclude|call|внутренний шаблон}}<br>дополнение {{объемлющий шаблон|1|2|3}} {{внутренний шаблон|1|2|3}}<br>дополнение
forall {{#invoke:Transclude|forall|внутренний шаблон}} {{объемлющий шаблон|1|2|3}} {{внутренний шаблон|1}}
{{внутренний шаблон|2}}
{{внутренний шаблон|3}}
join {{#invoke:Transclude|join|<nowiki>, </nowiki>|<nowiki> и </nowiki>}} {{объемлющий шаблон|1|2|3}} 1, 2 и 3
npc {{#invoke:Transclude|npc|внутренний шаблон|вверху=|внизу=}}
{{объемлющий шаблон
|вверху1 = 11
|внизу1  = 12

|вверху2 = 21
|внизу2  = 22
}}
{{внутренний шаблон
|вверху = 11
|внизу  = 12
}}{{внутренний шаблон
|вверху = 21
|внизу  = 22
}}
cycle TODO TODO TODO

Методы

call

{{#invoke:Transclude|call|внутренний шаблон}}

Вызывает внутренний шаблон с аргументами объемлющего шаблона (того, в коде которого указан #invoke). Нужно для того, чтобы дописать к выводу внутреннего шаблона что-то новое. Передаются как нумерованные, так и именованные аргументы.

Например, объемлющий шаблон с кодом

{{#invoke:Transclude|call|внутренний шаблон}}<br>дополнение,

вызванный таким образом:

{{объемлющий шаблон|1|2|3}},

вернёт

{{внутренний шаблон|1|2|3}}<br>дополнение.

Пример использования: Шаблон:TRef.

forall

{{#invoke:Transclude|forall|внутренний шаблон}}
{{#invoke:Transclude|forall|внутренний шаблон|separator=разделитель|conjunction=последний разделитель}}

Вызывает внутренний шаблон, по одному передавая ему нумерованные параметры объемлющего шаблона (того, в коде которого указан #invoke). Параметры могут быть набраны в произвольном порядке и с пропусками, они будут отсортированы. Пустые параметры не пробрасываются.

Например, объемлющий шаблон с кодом

{{#invoke:Transclude|forall|внутренний шаблон}},

вызванный таким образом:

{{объемлющий шаблон|1|2|3}},

вернёт

{{внутренний шаблон|1}}{{внутренний шаблон|2}}{{внутренний шаблон|3}}.

Можно передать разделитель и последний разделитель через параметры separator и conjunction, по умолчанию они пусты. Если указан только separator, то conjunction заполняется из него. Например, объемлющий шаблон с кодом

{{#invoke:Transclude|forall|внутренний шаблон|separator=<nowiki>, </nowiki>|conjunction=<nowiki> и </nowiki>}},

вызванный таким образом:

{{объемлющий шаблон|1|2|3}},

вернёт

{{внутренний шаблон|1}}, {{внутренний шаблон|2}} и {{внутренний шаблон|3}},

а объемлющий шаблон с кодом

{{#invoke:Transclude|forall|внутренний шаблон|separator=<nowiki>, </nowiki>}},

вызванный таким образом:

{{объемлющий шаблон|1|2|3}},

вернёт

{{внутренний шаблон|1}}, {{внутренний шаблон|2}}, {{внутренний шаблон|3}}.

Если требуется, чтобы разделитель содержал пробел в начале или в конце, нужно заключить его в <nowiki></nowiki>.

Примеры использования:

join

{{#invoke:Transclude|join|разделитель|последний разделитель}}

Берёт нумерованные аргументы объемлющего шаблона (того, в коде которого указан #invoke) и склеивает их в единую строку. Пустые аргументы пропускаются. Используются разделитель и последний разделитель, указанные первым и вторым параметрами в вызове модуля. Если указан только первый параметр, второй заполняется из него.

Например, объемлющий шаблон с кодом

{{#invoke:Transclude|join|<nowiki>, </nowiki>|<nowiki> и </nowiki>}},

вызванный таким образом:

{{объемлющий шаблон|1|2|3}},

вернёт

1, 2 и 3,

а объемлющий шаблон с кодом

{{#invoke:Transclude|join|<nowiki>, </nowiki>}},

вызванный таким образом:

{{объемлющий шаблон|1|2|3}},

вернёт

1, 2, 3.

Если требуется, чтобы разделитель содержал пробел в начале или в конце, нужно заключить его в <nowiki></nowiki>.

Фактически аналогичен использованию #forall с внутренним шаблоном с кодом 1 и другим способом указания разделителей.

Пример использования: Шаблон:Luaman и Шаблон:Luaman/тесты (TODO: заменить на более внятный пример).

См. также: Модуль:Separated entries.

npc

{{#invoke:Transclude|npc|внутренний шаблон|параметр=|другой параметр=|…}}
{{#invoke:Transclude|npc|внутренний шаблон|общий параметр=значение|другой общий параметр=значение|…|параметр=|другой параметр=|…}}

Вызывает внутренний шаблон несколько раз, передавая в него блоки аргументов объемлющего шаблона (того, в коде которого указан #invoke). Параметр название12 передаётся как название в 12-й вызов шаблона. Для этого нужно указать в вызове модуля |название =.

Например, объемлющий шаблон с кодом

{{#invoke:Transclude|npc|внутренний шаблон|вверху=|внизу=}},

вызванный таким образом:

{{объемлющий шаблон
|вверху1 = 11
|внизу1  = 12

|вверху2 = 21
|внизу2  = 22

|вверху3 = 31
|внизу3  = 32
}}

возращает

{{внутренний шаблон
|вверху = 11
|внизу  = 12
}}{{внутренний шаблон
|вверху = 21
|внизу  = 22
}}{{внутренний шаблон
|вверху = 31
|внизу  = 32
}}

Можно также указать в вызове модуля общие аргументы, который будут передаваться в каждый вызов внутреннего шаблона. Например, объемлющий шаблон с кодом

{{#invoke:Transclude|npc|внутренний шаблон|общий={{{общий|}}}|вверху=|внизу=}},

вызванный таким образом:

{{объемлющий шаблон
|общий   = 0

|вверху1 = 11
|внизу1  = 12

|вверху2 = 21
|внизу2  = 22

|вверху3 = 31
|внизу3  = 32
}}

возращает

{{внутренний шаблон
|общий  = 0

|вверху = 11
|внизу  = 12
}}{{внутренний шаблон
|общий  = 0

|вверху = 21
|внизу  = 22
}}{{внутренний шаблон
|общий  = 0

|вверху = 31
|внизу  = 32
}}

Обратите внимание, что необходимо ставить вертикальную черту сразу после значения общего параметра, потому что вызовы модулей, в отличие от вызовов шаблонов, не обрезают пробелы:

{{#invoke:Transclude|npc|внутренний шаблон|общий={{{общий|}}}|вверху=|внизу=}}

или

{{#invoke:Transclude|npc|внутренний шаблон|
общий={{{общий|}}}|
вверху=|
внизу=}}

но не

{{#invoke:Transclude|npc|внутренний шаблон
|общий={{{общий|}}}
|вверху=
|внизу=}}

Замечания:

  • Общие параметры также учитываются вместе с остальными при выборе того, что передавать во внутренний шаблон: если в объемлющем шаблоне указан параметр общий12, он передастся в 12-й вызов внутреннего шаблона под названием общий и может заменить общий параметр.
  • Происходят вызовы внутреннего шаблона не для всех нумерованных блоков параметров, а только для непустых, так что могут быть пропуски. А именно, вызывается блок 12, если в объемлющем шаблоне есть параметр параметр12 и в вызове модуля есть параметр параметр. Рекомендуется, чтобы внутренний шаблон при вызове без параметров возвращал пустую строку.

Пример использования: Шаблон:Карточка вызывает Шаблон:Карточка/внизу.

cycle

{{#invoke:Transclude|cycle|имя шаблона|n|список параметров…}}

Действует аналогично #forall по числовой переменной, изменяющейся от 1 до n. Другое начало можно задать в виде «-10..10» вместо n, или в обратном порядке «10..-10». Также можно задать предел цикла в виде имени шаблона (если второго параметра нет или он имеет вид «1..», шаблон раскрывается, пока не пуст). Не увлекайтесь!

Замечание: номера нумерованных параметров шаблона при записи увеличить на 1.

Параметром output можно задать как выводить шаблоны.

  • newline — каждый шаблон на новой строке.
  • inline — все шаблоны в одну строку (по-умолчанию).

Тесты шаблона

См. Модуль:Transclude/tests и Шаблон:Test transclude.

См. также


-- <nowiki>
--------------------------------------------------------------------------------
-- Module that allows transcluding a template with all parent arguments.
-- Useful in `/i18n` template subpages that delegate to a `/layout` subpage.
--
-- @module transclude
-- @author [[User:ExE Boss]]
--------------------------------------------------------------------------------

require('strict')
local checkType = require('libraryUtil').checkType;

local p = {}
local INVALID_TITLES = {
	["."]	= true,
	[".."]	= true,
};

local function _ne(value)
	return value and value ~= ''
end

--------------------------------------------------------------------------------
-- Helper function that merges argument tables.
--
-- @function mergeArgs
-- @param {table} inArgs
-- @param {table} outArgs
--------------------------------------------------------------------------------
local function mergeArgs(inArgs, outArgs, opts)
	checkType("mergeArgs", 1, inArgs, "table");
	checkType("mergeArgs", 2, outArgs, "table");
	checkType("mergeArgs", 3, opts, "table", true);
	opts = opts or {}

	local ignoredParams = opts.ignoredParams;
	local ignoredPrefix = opts.ignoredPrefix;

	for name, value in pairs(inArgs) do
		if (type(name) == "string") then
			if not (
				(ignoredParams and ignoredParams[name] == true)
				or (ignoredPrefix and
					ignoredPrefix == name:sub(1, ignoredPrefix:len()))
			) then
				outArgs[name] = value;
			end
		else
			outArgs[name] = value;
		end
	end

	return outArgs;
end

-- Exported for testing:
p['#mergeArgs'] = mergeArgs;

local mt = {};

function mt.__index(_, name)
	if (
		type(name) ~= "string"
		or INVALID_TITLES[name]
		or mw.ustring.find(name, "#", nil, true)
	) then
		return nil;
	end

	local title = mw.title.new(name, "Template")
	if (not title) then
		return nil;
	end

	return function (frame)
		checkType('transclude["' .. name .. '"]', 1, frame, "table");
		local parentFrame = frame:getParent();

		local ignoredParams, ignoredPrefix;
		if _ne(frame.args["#ignoredParams"]) then
			ignoredParams = {};
            for m in mw.text.gsplit(frame.args["#ignoredParams"], '|', true) do
                ignoredParams[mw.text.trim(m)] = true;
            end
		end

		if _ne(frame.args['#ignoredPrefix']) then
			ignoredPrefix = frame.args['#ignoredPrefix'];
		end

		local args = {};
		if (parentFrame) then
			mergeArgs(parentFrame.args, args, {
				ignoredParams = ignoredParams,
				ignoredPrefix = ignoredPrefix,
			});
		end
		mergeArgs(frame.args, args, {
			ignoredPrefix = "#",
		});

		if (not title.exists) then
			return "[[:" .. title.fullText .. "]]";
		end

		return frame:expandTemplate{
			title = title,
			args = args,
		};
	end
end

return setmetatable(p, mt);