Модуль:Transclude: различия между версиями
Mansur700 (обсуждение | вклад) (Новая страница: «local M={} --------------------------------------------------------- -- Функции для работы с параметрами вызвавшего шабл...») |
Mansur700 (обсуждение | вклад) Нет описания правки |
||
Строка 1: | Строка 1: | ||
local | local p={} | ||
-- | -- Вызывает внутренний шаблон с аргументами объемлющего шаблона | ||
function p.call(frame) | |||
function | local template = frame.args[1] | ||
local args = frame:getParent().args | |||
return frame:expandTemplate{ title=template, args=args } | |||
end | |||
-- Общая реализация для forall и call | |||
local function forallImpl(args, separator, conjunction, func) | |||
-- нумерованные ключи из args | |||
local keys = {} | |||
-- перебор в произвольном порядке, даже для нумерованных ключей | |||
for key, value in pairs(args) do | |||
if type(key) == 'number' and value and value ~= '' then | |||
table.insert(keys, key) | |||
end | |||
end | |||
table.sort(keys) | |||
local results = {} | |||
for _, key in ipairs(keys) do | |||
local value = func(args[key]) | |||
table.insert(results, value) | |||
end | |||
return mw.text.listToText(results, separator, conjunction) | |||
end | end | ||
function | -- Вызывает внутренний шаблон, передавая ему нумерованные параметры объемлющего шаблона по-одному | ||
function p.forall(frame) | |||
local template = frame.args[1] | local template = frame.args[1] | ||
local separator = frame.args.separator or '' | local separator = frame.args.separator or '' | ||
local conjunction = frame.args.conjunction or separator | local conjunction = frame.args.conjunction or separator | ||
local args = frame:getParent().args | |||
local | local func = function(value) | ||
return frame:expandTemplate{ title = template, args = {value} } -- или другой frame? | |||
end | end | ||
return | return forallImpl(args, separator, conjunction, func) | ||
end | end | ||
function | -- Берёт нумерованные аргументы объемлющего шаблона и склеивает их в единую строку | ||
function p.join(frame) | |||
local separator = frame.args[1] or '' | |||
local conjunction = frame.args[2] or separator | |||
local args = frame:getParent().args | |||
local func = function(value) | |||
return value | |||
end | |||
return forallImpl(args, separator, conjunction, func) | |||
end | end | ||
function | -- Служебная функция: удаляет дубликаты из отсортированного массива с нумерованными индексами | ||
local function deleteDuplicates(args) | |||
local res = {} | |||
for key, value in pairs(args) do | |||
if args[key+1] ~= value then | |||
table.insert(res, value) | |||
end | |||
end | |||
return res | |||
end | end | ||
function | -- Вызывает внутренний шаблон несколько раз, передавая в него блоки аргументов объемлющего шаблона | ||
function p.npc(frame) | |||
local args = frame:getParent().args | |||
local templateFrame = frame:getParent() | |||
local template = frame.args[1] | |||
-- определение, блоки аргументов с какими номерами нужны: | |||
-- если в объемлющем шаблоне есть "параметр12" и в вызове модуля есть "параметр", то вызывается 12-й блок | |||
local nums = {} | |||
for key, _ in pairs(args) do | |||
local main, num = string.match(key, '^(.-)%s*(%d*)$') | |||
num = tonumber(num) | |||
-- учитывать "параметр12", только если задано "параметр" | |||
if num and frame.args[main] then | |||
table.insert(nums, num) | |||
end | |||
end | |||
table.sort(nums) | |||
nums = deleteDuplicates(nums) | |||
-- проходить по нужным номерам блоков по возрастанию и однократно | |||
-- подставлять в шаблон: | |||
-- 1. общие аргументы данного модуля | |||
-- 2. аргументы объемлющего шаблона вида "параметр12" как "параметр" в 12-й блок | |||
local results = {} | |||
for _, blockNum in ipairs(nums) do | |||
-- общие аргументы модуля, которые передаются в каждый блок | |||
local blockArgs = mw.clone(frame.args) | |||
-- metatable ломает expandTemplate | |||
setmetatable(blockArgs, nil) | |||
for key, value in pairs(args) do | |||
local main, num = string.match(key, '^(.-)%s*(%d*)$') | |||
num = tonumber(num) | |||
-- передавать "параметр12" как "параметр" в 12-й блок, только если есть "параметр" в вызове модуля | |||
if blockNum == num and frame.args[main] then | |||
blockArgs[main] = value | |||
end | |||
end | |||
local blockText = templateFrame:expandTemplate{ title=template; args=blockArgs } | |||
table.insert(results, blockText) | |||
end | |||
return table.concat(results) | |||
end | end | ||
-- Действует аналогично forall по числовой переменной, изменяющейся (по умолчанию, от 1) до f.args[2]. | |||
function p.cycle(f) | |||
local | local tf,ac,op=f:getParent(), {}, f.args.output or 'inline'; | ||
local | local sep=''; | ||
if op == 'newline' then | |||
sep='\n'; | |||
end | end | ||
for p,k in pairs(f.args) do | for p,k in pairs(f.args) do | ||
if type(p)=='number' then | if type(p)=='number' then | ||
Строка 127: | Строка 126: | ||
f.args[2]:match('%.%.%s*(%S.*)%s*$') or f.args[2] or ''; | f.args[2]:match('%.%.%s*(%S.*)%s*$') or f.args[2] or ''; | ||
fh=tonumber(fh) or fh:match('^%s*(.-)%s*$'); | fh=tonumber(fh) or fh:match('^%s*(.-)%s*$'); | ||
s=tonumber(s); | |||
local acr={}; | local acr={}; | ||
if not | if not s then error('Начало цикла «'..s..'» — не число') end | ||
local function dc() | local function dc(order) | ||
local r=tf:expandTemplate{ title=f.args[1]; args={s,unpack(ac)} } | |||
if order == 'desc' then | |||
s=s-1; | |||
else | |||
s=s+1; | |||
end | |||
if r~='' then table.insert(acr,r); return r end | |||
end | end | ||
if type(fh)=='number' then | if type(fh)=='number' then | ||
if fh > s then | |||
while s<=fh do dc('asc') end | |||
else | |||
while s>=fh do dc('desc') end | |||
end | |||
elseif fh~='' then | elseif fh~='' then | ||
while tf:expandTemplate{ title=fh; args={s,unpack(ac)} } do dc() end | while tf:expandTemplate{ title=fh; args={s,unpack(ac)} } do dc('asc') end | ||
else | else | ||
while dc() do end | while dc('asc') do end | ||
end | end | ||
return table.concat(acr) | return table.concat(acr, sep) | ||
end | end | ||
return p | |||
return |
Текущая версия от 16:11, 31 января 2022
Внимание! Это один из самых используемых модулей. |
Этот модуль относится к критическим. У него очень много включений или он используется с подстановкой. Из-за опасности вандализма или ошибочного редактирования он был защищён. |
Этот модуль содержит функции, позволяющие вызывать внутренний шаблон из объемлющего шаблона после некоторой обработки параметров. Под объемлющим шаблоном имеется в виду шаблон, в котором написано {{#invoke:Transclude|...
, например, {{Пиктограммы СГС}}. В вызове модуля указывается название функции и внутренний шаблон, вроде {{Пиктограммы СГС/основа}}, который собственно и обрабатывает аргументы, полученные от объемлющего шаблона.
Функция | Код объемлющего шаблона | Код его вызова | Результат |
---|---|---|---|
call | {{#invoke:Transclude|call|внутренний шаблон}}<br>дополнение
|
{{объемлющий шаблон|1|2|3}}
|
{{внутренний шаблон|1|2|3}}<br>дополнение
|
forall | {{#invoke:Transclude|forall|внутренний шаблон}}
|
{{объемлющий шаблон|1|2|3}}
|
{{внутренний шаблон|1}}
|
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>
.
Примеры использования:
- Простой: Шаблон:Пиктограммы СГС вызывает Шаблон:Пиктограммы СГС/основа, см. Шаблон:Пиктограммы СГС/тесты.
- Более продвинутый: Шаблон:Falseredirect вызывает Шаблон:Falseredirect/основа, см. Шаблон:Falseredirect/тесты.
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.
См. также[править код]
local p={}
-- Вызывает внутренний шаблон с аргументами объемлющего шаблона
function p.call(frame)
local template = frame.args[1]
local args = frame:getParent().args
return frame:expandTemplate{ title=template, args=args }
end
-- Общая реализация для forall и call
local function forallImpl(args, separator, conjunction, func)
-- нумерованные ключи из args
local keys = {}
-- перебор в произвольном порядке, даже для нумерованных ключей
for key, value in pairs(args) do
if type(key) == 'number' and value and value ~= '' then
table.insert(keys, key)
end
end
table.sort(keys)
local results = {}
for _, key in ipairs(keys) do
local value = func(args[key])
table.insert(results, value)
end
return mw.text.listToText(results, separator, conjunction)
end
-- Вызывает внутренний шаблон, передавая ему нумерованные параметры объемлющего шаблона по-одному
function p.forall(frame)
local template = frame.args[1]
local separator = frame.args.separator or ''
local conjunction = frame.args.conjunction or separator
local args = frame:getParent().args
local func = function(value)
return frame:expandTemplate{ title = template, args = {value} } -- или другой frame?
end
return forallImpl(args, separator, conjunction, func)
end
-- Берёт нумерованные аргументы объемлющего шаблона и склеивает их в единую строку
function p.join(frame)
local separator = frame.args[1] or ''
local conjunction = frame.args[2] or separator
local args = frame:getParent().args
local func = function(value)
return value
end
return forallImpl(args, separator, conjunction, func)
end
-- Служебная функция: удаляет дубликаты из отсортированного массива с нумерованными индексами
local function deleteDuplicates(args)
local res = {}
for key, value in pairs(args) do
if args[key+1] ~= value then
table.insert(res, value)
end
end
return res
end
-- Вызывает внутренний шаблон несколько раз, передавая в него блоки аргументов объемлющего шаблона
function p.npc(frame)
local args = frame:getParent().args
local templateFrame = frame:getParent()
local template = frame.args[1]
-- определение, блоки аргументов с какими номерами нужны:
-- если в объемлющем шаблоне есть "параметр12" и в вызове модуля есть "параметр", то вызывается 12-й блок
local nums = {}
for key, _ in pairs(args) do
local main, num = string.match(key, '^(.-)%s*(%d*)$')
num = tonumber(num)
-- учитывать "параметр12", только если задано "параметр"
if num and frame.args[main] then
table.insert(nums, num)
end
end
table.sort(nums)
nums = deleteDuplicates(nums)
-- проходить по нужным номерам блоков по возрастанию и однократно
-- подставлять в шаблон:
-- 1. общие аргументы данного модуля
-- 2. аргументы объемлющего шаблона вида "параметр12" как "параметр" в 12-й блок
local results = {}
for _, blockNum in ipairs(nums) do
-- общие аргументы модуля, которые передаются в каждый блок
local blockArgs = mw.clone(frame.args)
-- metatable ломает expandTemplate
setmetatable(blockArgs, nil)
for key, value in pairs(args) do
local main, num = string.match(key, '^(.-)%s*(%d*)$')
num = tonumber(num)
-- передавать "параметр12" как "параметр" в 12-й блок, только если есть "параметр" в вызове модуля
if blockNum == num and frame.args[main] then
blockArgs[main] = value
end
end
local blockText = templateFrame:expandTemplate{ title=template; args=blockArgs }
table.insert(results, blockText)
end
return table.concat(results)
end
-- Действует аналогично forall по числовой переменной, изменяющейся (по умолчанию, от 1) до f.args[2].
function p.cycle(f)
local tf,ac,op=f:getParent(), {}, f.args.output or 'inline';
local sep='';
if op == 'newline' then
sep='\n';
end
for p,k in pairs(f.args) do
if type(p)=='number' then
if p>2 then ac[p-1]=k end
else ac[p]=k
end
end
local s,fh = f.args[2]:match('^%s*(%-?%d+)%s*%.%.') or 1,
f.args[2]:match('%.%.%s*(%S.*)%s*$') or f.args[2] or '';
fh=tonumber(fh) or fh:match('^%s*(.-)%s*$');
s=tonumber(s);
local acr={};
if not s then error('Начало цикла «'..s..'» — не число') end
local function dc(order)
local r=tf:expandTemplate{ title=f.args[1]; args={s,unpack(ac)} }
if order == 'desc' then
s=s-1;
else
s=s+1;
end
if r~='' then table.insert(acr,r); return r end
end
if type(fh)=='number' then
if fh > s then
while s<=fh do dc('asc') end
else
while s>=fh do dc('desc') end
end
elseif fh~='' then
while tf:expandTemplate{ title=fh; args={s,unpack(ac)} } do dc('asc') end
else
while dc('asc') do end
end
return table.concat(acr, sep)
end
return p