taiga
под капотом у темы · анатомия темы · часть 1 из 3

Гайд — это папка

проверено на v0.0.1 ~5 мин 597 слов

У этой статьи есть живой виджет, собственный скрипт и место под собственную обложку — и всё это лежит в одной папке рядом с текстом. Разберём контент-модель «статья = бандл» и посмотрим, почему она избавляет от правки шаблонов.

#Хочу живую картинку

Наивная модель такая: я пишу текст, и в одном месте мне нужна интерактивная иллюстрация. Кнопка, счётчик, что угодно. Кажется, дел на десять строк JS.

Теперь боль. В обычной теме эти десять строк некуда положить. Скрипт надо подключить в <head> — значит, править шаблон. Шаблон общий — значит, скрипт поедет на все страницы сразу. Чтобы не поехал, нужен реестр «какой скрипт какой странице» — значит, конфиг. Через месяц у тебя три статьи с виджетами и одна страница шаблона, которую страшно трогать. Текст живёт в одном месте, его код — в трёх других, и перенести статью целиком уже нельзя: она вросла в тему корнями.

#Статья — это папка

Здесь статья — это leaf bundle: папка, в которой лежит всё её хозяйство. Вот лента файлов бандла — той самой папки, из которой собрана эта страница:

Обязателен только index.md. Всё остальное — опциональные соседи: положил widgets.js рядом — тема сама его найдёт, минифицирует, отфингерпринтит и подключит только на этой странице. Положил widgets.css — то же самое со стилями. Положил og.png — обложка для соцсетей берётся авторская вместо сгенерированной.

Главная мысль

Всё, что нужно статье, лежит рядом со статьёй. Перенести гайд на другой сайт — значит перенести одну папку. Удалить — удалить одну папку. Никаких хвостов в шаблонах и конфигах.

#Два касания

Полный цикл «добавить живую иллюстрацию» — два касания. Первое: в тексте ставишь шорткод с идентификатором и заданием. Второе: в widgets.js регистрируешь инициализатор с тем же идентификатором:

inside/guide-is-a-bundle/widgets.js (фрагмент)
Taiga.widget("w-hello", function (root) {
  root.innerHTML = ""; // убираем статик-фолбэк
  // …кнопка, счётчик, бейдж — весь код в файле рядом
});

Ни шаблонов, ни <head>, ни реестров. У шорткода есть парная форма: внутрь кладётся статичный фолбэк, который живёт в точке монтирования, пока JS его не заменит, — а если JS выключен, остаётся насовсем. Страница без скриптов деградирует в осмысленный текст, а не в дыру.

Заметь, чего в примере выше нет: собственных стилей. Строительные классы — .w-row для строки контролов, .w-btn для кнопок, .w-num для крупной цифры, .w-cap для строки-вывода — лежат в CSS темы, и виджет выглядит родным, не привезя ни одного своего правила. widgets.css нужен только когда этого набора не хватает — и тогда он, как и всё остальное, просто кладётся в папку.

#Рантайм не даст упасть

Taiga.widget — это маленький рантайм в теме. Он ждёт DOM, находит точку монтирования по идентификатору и вызывает твой колбэк, обернув его в try/catch: упавший виджет напишет в консоль и не уронит соседей. А если точки монтирования нет — шорткод убрали из текста — инициализатор молча пропускается.

Ловушка

«Молча» — обоюдоострое слово. Идентификатор в шорткоде и в Taiga.widget(…) должны совпадать буква в букву: при опечатке рантайм решит, что шорткод убрали, и ты не получишь ни виджета, ни ошибки. Пустой квадрат на месте иллюстрации — первым делом сверь id.

А теперь проверь всё это на живом экземпляре. Виджет ниже смонтирован тем самым рантаймом из того самого widgets.js, что лежит в папке этой статьи:

Поиграй — нажми кнопку несколько раз, потом перезагрузи страницу: счётчик живёт в замыкании, а не в теме
Здесь живёт счётчик кликов. Сейчас ты видишь статичный фолбэк: включи JS — и он оживёт.

И последнее: механизм не привязан к гайдам. widgets.js подхватывается у любого бандла — страница с интерактивом здесь не отдельный тип со своим шаблоном, а обычная markdown-страница, рядом с которой лежит скрипт.

Теперь ты можешь добавить живую иллюстрацию в любой гайд, не открыв ни одного файла темы.

#Что дальше

Эта статья — часть серии, и слева от текста уже стоит панель с её оглавлением, а в кикере написано «часть 1 из 3». Руками это никто не набирал. Откуда тема всё знает — во второй части.