texl_core/lib.rs
1
2//! The texl template engine.
3//!
4//! A texl template is text with embedded `<% ... %>` tags. Each tag contains an
5//! expression in [Swan](swan_core), and rendering replaces the tag with the
6//! value of its expression:
7//!
8//! ```text
9//! Hello <% name %>, you have <% list.size messages %> new messages.
10//! ```
11//!
12//! The [Texl manual](https://onlabsorg.github.io/texl/book/) explains how to
13//! write templates. This documentation covers the Rust API.
14//!
15//! # Overview
16//!
17//! - [`template::render`] renders a template in a given [`Scope`](swan_core::value::Scope).
18//! It is the low-level entry point.
19//! - [`Engine`] adds what a full application needs: globals shared by every
20//! template, loaders that fetch documents by URI, `texl.import` with relative
21//! URIs, and a cache.
22//! - [`helpers`] connects the engine to the host's async runtime.
23//!
24//! # Async rendering
25//!
26//! Rendering is `async` because a tag may return a Swan promise, for example
27//! the result of `texl.import`, and rendering waits for it. The futures are
28//! single-threaded (`!Send`). With tokio, run them on a `LocalSet` and pass a
29//! spawner that calls `tokio::task::spawn_local`:
30//!
31//! ```ignore
32//! use texl_core::{Engine, helpers::spawner_fn};
33//!
34//! let engine = Engine::new(Some(spawner_fn(|task| { tokio::task::spawn_local(task); })));
35//! let text = tokio::task::LocalSet::new().run_until(engine.render("<% 6 * 7 %>")).await;
36//! ```
37//!
38//! Without a runtime, pass `None` and drive the futures yourself, calling
39//! [`helpers::run_pending`] to run the background tasks.
40
41#![warn(missing_docs)]
42
43pub mod helpers;
44pub mod template;
45pub mod engine;
46
47pub use engine::{Engine, LoaderFn, loader_fn};