Для Zig представили zt — типобезпечні HTML-шаблони з перевіркою під час збирання
Бібліотека zt під час збирання перетворює HTML-шаблони на код Zig, щоб компілятор перевіряв типи й параметри. Динамічні значення за замовчуванням екрануються, але проєкт поки не є зрілим.
У матеріалі, опублікованому 12 жовтня 2026 року, розробник zio та Dusty розповів про zt — бібліотеку HTML-шаблонів для Zig. Як пише автор у «Type-safe HTML templating in Zig», шаблони перетворюються на код Zig під час zig build: параметри перевіряє компілятор, а динамічні значення за замовчуванням екрануються. Бібліотекою вже користуються кілька людей, але сам автор поки не вважає проєкт зрілим.
Як влаштовані шаблони zt
Шаблон у zt схожий на HTML зі вставками Zig, а не на набір викликів для побудови розмітки. У ньому можна оголосити параметри з типами, підключити модель із коду застосунку, вивести її поля та використовувати звичайні if, for і switch. Наприклад, сторінка може приймати необов’язкового користувача й показувати різні блоки для відвідувача, який увійшов у систему, та гостя.
Під час збирання zt розбирає шаблон і створює код Zig. Застосунок може імпортувати готовий шаблон і викликати його рендеринг, а шаблон — імпортувати типи застосунку. Тому помилки в назві поля або невідповідний тип аргументу виявляються під час компіляції, а не після відкриття сторінки. Повідомлення компілятора вказує на згенерований код; коментарі в ньому допомагають знайти відповідне місце у вихідному шаблоні.
Результат рендерингу записується безпосередньо в std.Io.Writer. Його можна надсилати в сокет або збирати в буфері; проміжне представлення HTML для цього не потрібне. У Dusty виклик рендерингу HTML-відповіді додатково приховує деталі роботи з writer. Автор окремо попереджає, що наведений ним простий приклад запису до стандартного виводу не в усіх ситуаціях коректно обробляє помилки, пов’язані зі скасуванням операцій std.Io.
Для повторюваної розмітки передбачені компоненти, які можна передавати як значення. Макети можуть обгортати вкладені шаблони через @children — це спосіб зібрати спільну структуру сторінки без окремого механізму успадкування шаблонів. Так код сторінки залишається поруч зі звичною HTML-розміткою, але його вхідні дані не перетворюються на неявні змінні.
Безпека та відкриті питання
Динамічні значення за замовчуванням екрануються і в тексті, і в атрибутах. Для URL-атрибутів, зокрема href і src, передбачена перевірка небезпечних схем. Виводити HTML без екранування можна, але це потрібно явно позначити записом {!value}. Крім того, парсер вимагає закривати елементи, щоб у шаблоні не було незавершеної розмітки.
Екранування та перевірка URL-схем допомагають уникнути поширених причин XSS, хоча не захищають від усіх можливих помилок. Вимога закривати елементи розв’язує інше завдання: допомагає не отримати некоректну розмітку. Можливість вставити сирий HTML при цьому залишається — використовувати її чи ні, вирішує розробник.
Одна частина синтаксису ще обговорюється. Якщо рядок починається з if, for або switch, парсер сприймає його як код. Через це звичайний текст, що починається з такого слова, може спричинити помилку розбору: його доведеться помістити всередину елемента або оформити як рядковий вираз. Автор розглядає варіант із явними @if, @for і @switch, але остаточного рішення в матеріалі не називає. Термінів виходу зрілішої версії він теж не вказує.
Що це означає для вебпроєктів
Для розробника, який уже будує серверну частину на Zig, zt розв’язує практичне завдання: як віддавати HTML, не складаючи його конкатенацією рядків і не втрачаючи перевірки типів. Автор показує використання в Dusty та згадує TODO-застосунок із htmx, де шаблони працюють разом з іншими частинами його вебстека.
Для власника сайту чи маркетолога це не означає, що проєкт потрібно переводити на Zig. Користь тут вужча: якщо команда вже обрала такий стек, помилки в даних шаблону можна виявляти під час збирання, а екранування не потрібно додавати вручну для кожного значення. Водночас варто враховувати молодість бібліотеки та відкрите питання із синтаксисом, перш ніж покладатися на неї у великому наборі сторінок.
Моя думка
Мені подобається цей напрям: замість ще одного шару між даними та сторінкою zt використовує компілятор Zig і записує результат безпосередньо у writer. Особливо цінне поєднання типізованих параметрів з екрануванням за замовчуванням. Але я б оцінювала інструмент на конкретному завданні й перевіряла, наскільки зручно підтримувати шаблони після генерації коду, особливо коли доводиться розбирати помилки компіляції.
Для звичайного лендингу я б не обирала новий стек лише заради шаблонізатора: серверний рендеринг або статичні сторінки часто простіші в підтримці. А от команді, яка вже пише вебзастосунок на Zig, за zt цікаво стежити. Тут розв’язується реальне завдання — отримувати HTML без ручного складання рядків, — хоча проєкт поки залишає питання відкритими.
Джерела
Звідки новина. Текст — переказ своїми словами, факти — з джерела, думка — автора.
- Type-safe HTML templating in Zig lalinsky.com
фулстек-розробниця
Проєктую вебсервіси й магазини, а вільний час присвячую експериментам із чергами, кешем і збиранням. Люблю, коли інструмент розв’язує реальну задачу, а не додає ще один рівень абстракції.
Усі публікації автораСхожі статті
У Chrome 157 з’явився HTML-in-Canvas для інтерактивного DOM усередині графічних сцен
У стабільній версії Chrome 157 з’явився HTML-in-Canvas. API дає змогу вбудовувати інтерактивний HTML у графічні сцени, зберігаючи доступність тексту, форм та інших DOM-елементів.
Представлено Proa — Rust-фреймворк із серверним рендерингом і виведенням у різних форматах
На Hacker News представили Proa — вебфреймворк на Rust для серверного рендерингу та виведення компонентів у HTML і Markdown. Автори пропонують випробувати його на одному маршруті чинного проєкту.
Bez генерує браузерний рушій за вебспецифікаціями й тестами
Bez створює браузерний рушій за вебспецифікаціями, звіряючи результат із Chromium, Firefox і WebKit. Проєкт поки на ранній стадії, а опубліковані показники не означають готовності рушія.
Обговорення 4
Ділноза Рахімова
Цікаво, як zt поводиться, якщо тип моделі змінюється після написання шаблону: помилку видно вже під час збирання? І чи можна якось явно позначити значення, яке не треба екранувати, щоб не відкрити XSS-вразливість випадково?
Етері Тевдорадзе Автор публікації
@dilnoza.qa Так, у шаблону типізовані параметри, тож якщо поле моделі перейменувати або змінити його тип, очікувана користь саме в тому, що це виявиться під час `zig build`, а не вже на сторінці. Динамічні значення zt екранує за замовчуванням; для довільного HTML потрібен явний шлях обходу цього захисту, але через незрілість бібліотеки я б перевіряла його конкретний API перед використанням і тримала такі місця мінімальними. Для типового тексту користувача безпечніше лишити автоекранування, а не знімати його «про всяк випадок».
Еймантас Ейдукас
@dilnoza.qa якщо зміна типу моделі порушує поля чи параметри шаблону, згенерований код має не пройти компіляцію під час збирання. У публікації сказано, що динамічні значення екрануються за замовчуванням, але механізм явного вимкнення екранування автор не описує — тут варто перевірити документацію zt, перш ніж вважати такий escape hatch безпечним.
Дієго Замора
@dilnoza.qa, тут ще важливо розрізняти типову перевірку й довіру до вмісту: компілятор може спіймати перейменоване поле моделі на `zig build`, але навіть значення типу `[]const u8` не обов’язково безпечне для вставки в будь-який контекст HTML. Я б для обходу екранування хотів бачити окремий явний тип або функцію на кшталт `SafeHtml`, а не просто прапорець у шаблоні — у статті цей механізм поки не описаний.