Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Архитектура Light

Документ для новых контрибьюторов: как устроен фреймворк, где проходят границы между крейтами и что происходит от HTML-шаблона до кадра в окне.

Крейты воркспейса

КрейтРоль
light-fw-coreЯдро: виртуальный DOM, реактивность, layout, paint, окно, a11y, валидация.
light-fw-htmlПарсер HTML-шаблонов: теги, атрибуты, директивы, {{ … }}, <include>.
light-fw-macrosПроцедурные макросы #[template] и #[proxy].
lightМета-крейт: реэкспортирует ядро, макросы и подключённые компоненты.
light-fw-element-formКомпонент-элемент: <checkbox>, <radio>, <select>, <option>.
light-fw-behavior-validationКомпонент-поведение: required, :validator, @validate.
light-fw-cliБинарник light: команды check, add, search, publish, …
light-fw-cli-coreЛогика CLI без привязки к терминалу: анализ, план, применение, lock.
light-demoДемонстрационное приложение и примеры.

Зависимости направлены внутрь: компоненты и CLI зависят от ядра, ядро не знает о прикладном коде. light — тонкая обёртка, чтобы приложение могло писать use light::prelude::*; и не указывать внутренние крейты напрямую.

Компиляция шаблона

  1. #[template("templates/app.html")] читает файл относительно CARGO_MANIFEST_DIR.
  2. light-fw-html разбирает разметку в дерево Node/Element/Attr и сегменты текста Literal/Path.
  3. light-fw-macros обходит дерево, разрешает <include src="...">, проверяет директивы и генерирует Rust-код.
  4. Сгенерированный код реализует Component::render: он собирает VElement из NodeKind, стилей и обработчиков событий.
  5. #[proxy] добавляет к структуре реактивные геттеры/сеттеры и new().

Ошибки разметки и неизвестные атрибуты становятся ошибками компиляции с указанием файла и строки. В рантайме HTML уже не парсится.

*.html ──light-fw-html──▶ AST ──light-fw-macros──▶ Rust-код Component::render
                                                        │
                                                        ▼
                                                   VElement

Рантайм: от состояния до кадра

Component::render()
        │
        ▼
   VElement (новое дерево)
        │
        ├── сравнение с предыдущим деревом (vdom::diff)
        │
        ▼
   набор операций (Op)
        │
        ▼
   Dom / виртуальное дерево окна
        │
        ▼
   layout: размеры и позиции узлов
        │
        ▼
   paint: Canvas → RGBA-буфер
        │
        ▼
   RendererBackend::present()

Основные слои light-fw-core:

  • vdom — VElement, NodeKind, стили, события и diff. Ключи узлов стабильны между отрисовками; diff обновляет только изменившиеся узлы.
  • reactive — свойства Proxy, наблюдатели и запрос перерисовки. Изменение свойства помечает окно грязным, после чего цикл окна повторяет render → diff → layout → paint.
  • layout — вычисление Rect для каждого узла: колонки/строки, отступы, проценты, min/max-размеры, выравнивание, z-order и повреждённые области.
  • window — цикл winit: события мыши/клавиатуры/размера, вызов Component::dispatch, управление окнами, загрузка шрифта и отрисовка.
  • window::paint — программная растеризация: прямоугольники, границы, текст через ab_glyph, фокусное кольцо и элементы форм.
  • a11y — построение дерева AccessKit, роли, фокус, клавиатурная навигация и объявления.
  • validation — required, пользовательские валидаторы и поиск кнопки отправки формы.

События приходят из winit, преобразуются в vdom::Event и передаются компоненту. Компонент меняет реактивные свойства; дальнейшая перерисовка инициируется наблюдателями, а не ручным вызовом render.

Рендеринг и RendererBackend

Растеризация не зависит от графического API. window::paint::Canvas пишет пиксели в RGBA8-буфер, а бэкенд отвечает только за владение буфером и показ кадра:

#![allow(unused)]
fn main() {
pub trait RendererBackend {
    fn resize(&mut self, width: u32, height: u32) -> Result<()>;
    fn size(&self) -> (u32, u32);
    fn frame_mut(&mut self) -> &mut [u8];
    fn present(&mut self) -> Result<()>;

    // clear / draw_rect / draw_text по умолчанию работают через Canvas
}
}

Реализации:

  • SoftbufferBackend — основной путь. Хранит RGBA8-кадр, при present перекладывает его в 0x00RRGGBB и отдаёт в softbuffer. Не тянет wgpu/naga, даёт меньший бинарник.
  • WgpuBackend — альтернатива через pixels/wgpu (фича wgpu-backend) для сравнения и запасного пути.
  • NullBackend — используется, когда графический бэкенд не включён: layout и ввод работают, кадр остаётся в памяти.

Если включены обе фичи, выбирается softbuffer-backend. Это зафиксировано в docs/DESIGN_PRINCIPLES.md: по умолчанию — минимальный footprint.

CLI

light-fw-cli — тонкий слой clap над light-fw-cli-core. Ядро CLI не зависит от терминала и запускает внешние процессы через трейт CommandRunner, поэтому планы и ошибки тестируются с мок-раннером.

Типичный изменяющий сценарий (add, remove, update, init):

аргументы → plan_* (только чтение) → подтверждение → backup::create
          → apply_* (мутации) → cargo check → backup::restore при ошибке

Ключевые модули light-fw-cli-core:

  • scan / project — поиск *.html, разбор через light-fw-html, сопоставление тегов/атрибутов/директив со встроенным registry.toml.
  • registry — статический каталог официальных компонентов, их версии, требования к ядру и фичи мета-крейта.
  • fetch / search — разрешение компонентов: workspace → vendor/ → встроенный реестр → crates.io. Сеть скрыта за RemoteRegistry.
  • edit — правки Cargo.toml через toml_edit с сохранением форматирования: зависимости, фичи, dep:-токены.
  • lockfile — генерация light.lock из фактического Cargo.toml.
  • publish — топологический порядок по cargo metadata, pre-flight гейты, классификация ошибок crates.io и публикация.
  • backup — снимки файлов перед мутацией и откат при ошибке.

Команды чтения (check, suggest, doctor, search) ничего не пишут на диск. Команды изменения (add, remove, update, lock, init, vendor) сначала строят план, а затем применяют его атомарно с резервной копией.

Фичи и границы

Возможности ядра включаются Cargo-фичами: элементы, окно, backend, a11y, layout-расширения. Фича light/elements-form включает и light-fw-core, и компонент формы; light/validation — поведение валидации. Код выключенных возможностей не попадает в бинарник.

При добавлении публичного поля в Style, NodeKind, Interaction, WindowConfig, VElement или Event сначала запускайте cargo build --all-features и cargo test --all-features: компилятор и снапшоты покажут все места, которые нужно обновить.

С чего начать

  • Понять модель компонентов — docs/COMPONENT_MODEL.md.
  • Написать свой компонент — docs/COMPONENT_AUTHORING.md и docs/EXTERNAL_COMPONENTS.md.
  • Посмотреть пользовательские команды — docs/guide.md.
  • Разобраться в решениях по размеру и фичам — docs/DESIGN_PRINCIPLES.md.