Если вы создаёте шаблоны на вашей вики, то рано или поздно вы научитесь использовать функции парсера, которые используются в написании сложного кода. Не важно, это {{#if:}}
или {{#switch:}}
— эти функции помогают создавать шаблоны с большим функционалом.
Но в какой-то момент вы можете столкнуться со следующей проблемой: использование большого количества #if
-условий делает шаблоны сложными для редактирования и чтения их исходного кода. Например если вы хотите добавить автоматизированную категоризацию на страницы об эпизодах по следующим правилам:
- Если введён параметр
{{{сезон}}}
, то шаблон добавит текст[[Категория:Эпизоды из {{{сезон}}} сезона]]
. - Если параметр
{{{сезон}}}
отсутствует, то шаблон добавит текст[[Категория:Эпизоды без сезонов]]
, что позволит искать такие страницы быстрее.
В шаблоне у вас получится примерно следующее:
{{#if:{{{сезон|}}}|[[Категория:Эпизоды из {{{сезон}}} сезона]]|[[Категория:Эпизоды без сезонов]]}}
Множество {{ }}
и [[ ]]
могут запутать уже на этом этапе, но это пока ещё терпимо… пока… А что если нам нужно добавить новое правило?
- Если введён параметр
{{{особый}}}
, который определяет является ли эпизод обычным или особым, то мы должны добавить[[Категория:Особые эпизоды из {{{сезон}}} сезона]]
.
Как мы можем это сделать? Можно попробовать что-то вроде этого:
{{#if:{{{сезон|}}}|{{#if:{{{особый|}}}|[[Категория:Особые эпизоды из {{{сезон}}} сезона]]|[[Категория:Эпизоды из {{{сезон}}} сезона]]}}|[[Категория:Эпизоды без сезонов]]}}
Теперь это стало труднее читать, не так ли? А ведь мы добавили только одно новое правило! Функции парсера прекрасно работают для простых шаблонов, но они становятся всё труднее и труднее когда вы пытаетесь добавить более сложную логику для шаблона. Так что мы должны делать в этом случае? Lua, как один из языков программирования, является куда более мощным инструментом, который помогает добавлять сложную логику в ваши шаблоны, при этом оставаясь простым для чтения (конечно при условии что вы с ним знакомы). Но перед тем, как мы переделаем пример выше на Lua, мы должны понять что это такое и как мы можем использовать этот язык на вики при помощи модулей.
Быстрый старт[]
Скрипты на Lua пишутся в пространстве имён Модуль:. Точно также, как и все названия шаблонов начинаются со слова Шаблон:, все скрипты на Lua на вики находятся на страницах, начинающихся со слова Модуль:. Большинство модулей выглядят примерно так:
local p = {}
function p.main(frame)
-- код
end
return p
Давайте кратко пробежимся по примеру выше:
local p
это переменная, которая хранит в себе пустую таблицу{}
. Она нужна для того, чтобы все функции, которые вы в неё будете писать, могли быть возвращены в конце (return
). Другие модули и обычные страницы могут использовать любые функции из возвращаемой таблицы.- Мы создаём функцию (
function
) под названиемmain
внутри таблицыp
.frame
это аргумент функции, который передаётся во все функции вызываемые с обычных страниц. Вы можете почитать об объекте frame подробнее, но сейчас для нас важно знать только то, что он хранит параметры, которые мы введём на обычной странице. Например: в «{{Шаблон|Первый|Второй|привет=мир}}
» этот объект может дать нам значенияпервого параметра
,второго параметра
и значение параметрапривет
, которое равномир
.
Держите в уме: main
это просто пример! Вы можете использовать любое допустимое значение как название функции.
Создание модуля[]
Теперь давайте напишем рабочий код! Сосредоточитесь на том, что находится внутри функции categorize
.
local p = {}
function p.categorize(frame)
local args = require('Dev:Arguments').getArgs(frame)
local season = args["сезон"]
local special = args["особый"]
if season then
if special then
return string.format( '[[Категория:Особый эпизод из %s сезона]]', season )
else
return string.format( '[[Категория:Эпизод из %s сезона]]', season )
end
else
return '[[Категория:Эпизоды без сезонов]]'
end
end
return p
Объяснение шаг за шагом[]
Давайте посмотрим на то, что находится внутри этого модуля.
- Получение параметров
- Существует множество способов получить введённые параметры, но самым рекомендуемым является использование глобального модуля Arguments, который доступен на всех вики. Этот модуль экспортирует функцию
getArgs
которая возварщает таблицу с аргументами из вашего объектаframe
. Если мы будем вызывать шаблон выше («{{Шаблон|Первый|Второй|привет=мир}}
»), то мы получим все аргументы в такой таблице:
{ "Первый", "Второй", ["привет"] = "мир" }
- Обратите внимание на то, что в Lua первым индексом таблицы является 1, а не 0 как во многих других языках программирования! Вы можете получить любой нужный параметр:
args[1]
(Первый),args[2]
(Второй) andargs["привет"]
(мир). При попытке получить информацию по индексу, которого не существует, вы получите значениеnil
, которое эквивалентноundefined
в JavaScript илиNone
в Python.
- Написание логики
- Вы должны быть знакомы с условием
if
в программировании. Синтаксис Lua может отличаться от того, что вы знаете, но его легко понять. - Прямо как в функциях парсера, сначала мы проверяем задан ли параметр
эпизод
. Если он не задан, то при его вызове мы получим значениеnil
из нашей таблицыargs
, что в данном случае эквивалентноfalse
(ложь
). - Другая часть, которая может показаться для вас незнакомой это вызов
string.format
. Lua имеет множество способов работать со строками и это один из них. Первым параметром этой функции является та строка, которую мы хотим вернуть, где символ%s
будет заменён на второй параметр (в данном случае мы подставляем вместо него значение переменнойseason
).- Если
season
задан, то проверить задан ли параметрspecial
.- Если
special
задан, то вернуть строку[[Категория:Особый эпизод из %s сезона]]
, где%s
будет заменён на знаечние переменнойseason
. - Иначе, вернуть строку
[[Категория:Эпизод из %s сезона]]
.
- Если
- Если
season
не задан, то вернуть строку[[Категория:Эпизоды без сезонов]]
.
- Если
- Прямо как в шаблонах, возвращаемое значение вставится на страницу.
Как я могу это использовать?[]
Если мы сохраним пример выше на страницу Модуль:Эпизод
, то его можно вызывать функцию categorize
из этого модуля на любую страницу при помощи функции {{#invoke:Эпизод|categorize|сезон=1}}
. Но вы должны избегать подобных вызовов. Несмотря на то, что этот синтаксис похож на вызов шаблона, новые редакторы всё-равно могут не понять что это такое: #invoke
? Что такое categorize
? Где находится этот шаблон?
Обычно редакторы не будут использовать модули напрямую, но будут вставлять их косвенно, через шаблоны. Например, в вашем шаблоне Шаблон:Карточка эпизода
вы вызываете этот модуль в конце: {{#invoke:Episode|categorize}}
.
Но погодите, а куда делся параметр сезон
? Откуда модуль будет знать значение этого параметра? На самом деле у объекта frame
есть доступ к любому параметру, введённому в шаблон {{Карточка эпизода}}
! А благодаря глобальному модулю Arguments, который мы использовали ранее, мы можем использовать эти параметры без необходимости в изменении кода модуля. Ну не красота ли это?
Заключение[]
Этот блог должен дать идеи того как вы можете использовать Lua для упрощения логики ваших шаблонов, надеемся что вы сможете применить эти знания, чтобы ваши шаблоны было легче поддерживать! Здесь представлен короткий список того когда вы должны использовать Lua:
- В ваших шаблонах слишком много функций парсера, особенно если они вложенные.
- Вам нужно обработать неопределённое кол-во введённых параметров. Вместо ручного добавления
{{{параметр 1}}}
,{{{параметр 2}}}
,{{{параметр 3}}}
и так далее, вы можете обработать их при помощи Lua. - Несмотря на та, что централизация данных на вики обычно является плохой практикой, иногда это является лучшим решением вашей проблемы. А лучшим способом централизовать данные являются модули на Lua.
Держите в уме что модули на Lua требуют кого-то, кто знает этот язык и способен поддерживать скрипты на нём. Следуйте стандартным практикам написания хорошего кода в ваших модулях чтобы другие люди могли понимать что они делают и легко исправлять их. Например: используйте «говорящие» названия для переменных (local ip
не даёт столько же полезной информации о переменной, сколько local item_price
) и разделяйте большие функции на несколько маленьких функций поменьше, чтобы упростить читаемость кода. И конечно — добавляйте комментарии к коду!
В вашем распоряжении все инструменты для создания мощных модулей для использования в ваших статьях, вместо того, чтобы полагаться только на функции парсера и другие «простейшие» функции.