This allows for all of the Typst compilation to be offloaded to the typst crate. The main issue to solve now is compiling Typst functions into Rust, so documentation can be automatically generated.
CQEA2ZDITRMPXKCO5T346QH7JJOOGOPRC66F3MG6VEMEQGLYYUZAC HEIF2O2ELHA3M7K77CK7AHBZ4656AUS3QW5M4E2DUY7ECOLVWKIAC 2N3KOCP74PCK2ETO5PCWBDR5PA57DDNT2KR4JLBPZPQPA56SAR4QC GYTRFADRDO4SYXV6V3PEPGGFIRDHQH5YBTKEJCWFAIZ5CX4P46NAC C73UJ7ZYG4EE3YTK3N66GXPNWJHEBSRE4PDQBWMN6SKQ3U6ZYKXAC BMG4FSHNV54VXDHNUVGZOMXQJWLFSUF3M5NCN7GJETNIF3QTHELQC REI53XR4WDH5EKLTXTFVTOVWCCFRWTFH4GQS6DSNM5LSRFTX7HJQC BSJYWOYSJRERQ45AD7RN3364RYQ5P3IM76S67262VLFZPFO3B5JQC let file_contents = std::fs::read_to_string(&file).expect("Unable to read file");let untyped_tree = typst::syntax::parse(&file_contents);let typst_ast = typst::syntax::ast::Markup::from_untyped(&untyped_tree).expect("Unable to parse Typst file");let xilem_expressions = typst_to_xilem(typst_ast);
let typst_ast = eval::eval_file(&file);let xilem_expressions = typst_to_xilem(typst_ast.content());
fn typst_expr_to_xilem(expression: &typst::syntax::ast::Expr) -> syn::Expr {match expression {typst::syntax::ast::Expr::Text(text) => syn::Expr::Lit(literal_string(text.get().as_str())),typst::syntax::ast::Expr::Space(space) => syn::Expr::Lit(literal_string(" ")),typst::syntax::ast::Expr::Heading(heading) => {let level = HeaderLevel::from(heading.level());let expressions = typst_to_xilem(heading.body());xilem_html_element(level.into(), expressions)
fn typst_expr_to_xilem(value: &typst::eval::Value) -> syn::Expr {match value {typst::eval::Value::Str(string) => syn::Expr::Lit(literal_string(string.as_str())),typst::eval::Value::Content(content) => {let supported_content = content::SupportedContent::downcast(content).unwrap();supported_content.to_xilem().unwrap()
fn typst_to_xilem(root: typst::syntax::ast::Markup) -> Vec<syn::Expr> {let xilem_expressions = root.exprs().collect::<Vec<_>>()
fn typst_to_xilem(root: typst::model::Content) -> Vec<syn::Expr> {let children = if let Some(typst::eval::Value::Array(array)) = root.get_by_name("children") {array} else {panic!();};let xilem_expressions = children
use std::path::Path;use comemo::{Prehashed, Track};use typst::diag::{FileError, FileResult};use typst::eval::{Bytes, Datetime, Library, Module};use typst::font::{Font, FontBook};use typst::syntax::{FileId, Source, VirtualPath};use typst::World;struct EvalWorld {library: Prehashed<Library>,font_book: Prehashed<FontBook>,main: Source,}impl EvalWorld {fn new(main_file: impl AsRef<Path>) -> std::io::Result<Self> {let main_data = std::fs::read_to_string(main_file.as_ref())?;let main_id = FileId::new(None, VirtualPath::new(main_file));Ok(Self {library: Prehashed::new(typst_library::build()),font_book: Prehashed::new(FontBook::new()),main: Source::new(main_id, main_data),})}}impl World for EvalWorld {fn library(&self) -> &Prehashed<Library> {&self.library}fn book(&self) -> &Prehashed<FontBook> {&self.font_book}fn main(&self) -> Source {self.main.clone()}fn source(&self, id: FileId) -> FileResult<Source> {let bytes = self.file(id)?;let text = String::from_utf8_lossy(bytes.as_slice());let source = Source::new(id, text.to_string());Ok(source)}fn file(&self, id: FileId) -> FileResult<Bytes> {let path = id.vpath().as_rootless_path();match std::fs::read(path) {Ok(bytes) => Ok(Bytes::from(bytes)),Err(io_error) => Err(FileError::from_io(io_error, path)),}}fn font(&self, _index: usize) -> Option<Font> {None}fn today(&self, _offset: Option<i64>) -> Option<Datetime> {None}}pub fn eval_file(main_file: impl AsRef<Path>) -> Module {let world = EvalWorld::new(main_file).unwrap();let route = typst::eval::Route::default();let mut tracer = typst::eval::Tracer::default();typst::eval::eval((&world as &dyn World).track(),route.track(),tracer.track_mut(),&world.main(),).unwrap()}
use typst::model::Content;use typst_library::meta::HeadingElem;use typst_library::text::{SpaceElem, TextElem};use crate::{literal_string, xilem_html_element};#[derive(Debug)]pub enum SupportedContent<'a> {Heading(&'a HeadingElem),Text(&'a TextElem),Space(&'a SpaceElem),}impl<'a> SupportedContent<'a> {pub fn downcast(value: &'a Content) -> Option<Self> {if let Some(heading) = value.to::<HeadingElem>() {Some(Self::Heading(heading))} else if let Some(text) = value.to::<TextElem>() {Some(Self::Text(text))} else if let Some(space) = value.to::<SpaceElem>() {Some(Self::Space(space))} else {dbg!(value);None}}pub fn to_xilem(&self) -> Option<syn::Expr> {Some(match self {SupportedContent::Heading(heading) => {let body_text = Self::downcast(heading.body())?;xilem_html_element("h1", vec![body_text.to_xilem()?])}SupportedContent::Text(text) => syn::Expr::Lit(literal_string(text.text().as_str())),SupportedContent::Space(_space) => syn::Expr::Lit(literal_string(" ")),})}}
typst-library = { git = "https://github.com/typst/typst" }
[[package]]name = "biblatex"version = "0.8.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2e41df82f0d1c4919d946bb0c7c3d179b6071246243d308a1bdee6cfecee3bc7"dependencies = ["numerals","paste","strum","unicode-normalization","unscanny",][[package]]name = "bincode"version = "1.3.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"dependencies = ["serde",][[package]]name = "bit-set"version = "0.5.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"dependencies = ["bit-vec",][[package]]name = "bit-vec"version = "0.6.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
[[package]]name = "bytecheck"version = "0.6.11"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627"dependencies = ["bytecheck_derive","ptr_meta","simdutf8",][[package]]name = "bytecheck_derive"version = "0.6.11"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61"dependencies = ["proc-macro2","quote","syn 1.0.109",]
[[package]]name = "chinese-number"version = "0.7.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d9cec9efb10b00914876c7e7b1fdaec572b888443b4046cd11ba91eb8c5a1ccb"dependencies = ["chinese-variant","enum-ordinalize","num-bigint","num-traits",][[package]]name = "chinese-variant"version = "1.0.9"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "aeea139b89efab957972956e5d3e4efb66a6c261f726abf6911040cc8ef700f7"[[package]]name = "ciborium"version = "0.2.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926"dependencies = ["ciborium-io","ciborium-ll","serde",][[package]]name = "ciborium-io"version = "0.2.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656"
name = "ciborium-ll"version = "0.2.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b"dependencies = ["ciborium-io","half",][[package]]name = "citationberg"version = "0.1.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4c857faf24e89710f105b623c174508070a9e11e056a749f251ca4c56f59ad88"dependencies = ["quick-xml 0.28.2","serde",][[package]]
][[package]]name = "csv"version = "1.3.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe"dependencies = ["csv-core","itoa","ryu","serde",][[package]]name = "csv-core"version = "0.1.11"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70"dependencies = ["memchr",
name = "embedded-io"version = "0.4.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"[[package]]name = "enum-ordinalize"version = "3.1.15"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "1bf1fa3f06bbff1ea5b1a9c7b14aa992a39657db60a2759457328d7e058f49ee"dependencies = ["num-bigint","num-traits","proc-macro2","quote","syn 2.0.38",][[package]]
name = "half"version = "1.8.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"[[package]]name = "hashbrown"version = "0.12.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"dependencies = ["ahash 0.7.7",][[package]]
[[package]]name = "hayagriva"version = "0.4.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c5af3d464a6b5ae882f15fe1da4e696fd96b77fee78ded933e0ad81d1d87cbc5"dependencies = ["biblatex","ciborium","citationberg","indexmap","numerals","paste","rkyv","serde","serde_yaml","thiserror","unic-langid","unicode-segmentation","unscanny","url",]
[[package]]name = "hypher"version = "0.1.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "94bf16dd62ea2bec617a6f8a3e1ba03107311783069a647787ac689d1f35321e"[[package]]name = "icu_collections"version = "1.3.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "3907b2246e8dd5a29ead8a965e7c0c8a90e9b928e614a4279257d45c5e553e91"dependencies = ["displaydoc","serde","yoke","zerofrom","zerovec",][[package]]name = "icu_locid"version = "1.3.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f284eb342dc49d3e9d9f3b188489d76b5d22dfb1d1a5e0d1941811253bac625c"dependencies = ["displaydoc","litemap","tinystr","writeable","zerovec",][[package]]name = "icu_locid_transform"version = "1.3.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "6551daf80882d8e68eee186cc19e132d8bde1b1f059a79b93384a5ca0e8fc5e7"dependencies = ["displaydoc","icu_locid","icu_locid_transform_data","icu_provider","tinystr","zerovec",][[package]]name = "icu_locid_transform_data"version = "1.3.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2a741eba5431f75eb2f1f9022d3cffabcadda6771e54fb4e77c8ba8653e4da44"[[package]]name = "icu_properties"version = "1.3.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "3477ae70f8ca8dc08ff7574b5398ed0a2f2e4e6b66bdff2558a92ed67e262be1"dependencies = ["displaydoc","icu_collections","icu_locid_transform","icu_properties_data","icu_provider","serde","tinystr","zerovec",][[package]]name = "icu_properties_data"version = "1.3.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "98507b488098f45eb95ef495612a2012e4d8ad6095dda86cb2f1728aa2204a60"[[package]]name = "icu_provider"version = "1.3.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "68acdef80034b5e35d8524e9817479d389a4f9774f3f0cbe1bf3884d80fd5934"dependencies = ["displaydoc","icu_locid","icu_provider_macros","postcard","serde","stable_deref_trait","tinystr","writeable","yoke","zerofrom","zerovec",][[package]]name = "icu_provider_adapters"version = "1.3.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "36b380ef2d3d93b015cd0563d7e0d005cc07f82a5503716dbc191798d0079e1d"dependencies = ["icu_locid","icu_locid_transform","icu_provider","tinystr","zerovec",][[package]]name = "icu_provider_blob"version = "1.3.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c31326d28c7f95a964a4f0ee86c24002da5f6db907e3bcb079949b4ff103b6a9"dependencies = ["icu_provider","postcard","serde","writeable","zerovec",][[package]]name = "icu_provider_macros"version = "1.3.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2060258edfcfe32ca7058849bf0f146cb5c59aadbedf480333c0d0002f97bc99"dependencies = ["proc-macro2","quote","syn 2.0.38",][[package]]name = "icu_segmenter"version = "1.3.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "bcb3c1981ce2187a745f391a741cb14e77453325acb3b2e014b05da51c0a39f2"dependencies = ["core_maths","displaydoc","icu_collections","icu_locid","icu_provider","icu_segmenter_data","serde","utf8_iter","zerovec",][[package]]name = "icu_segmenter_data"version = "1.3.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9703f6713044d1c0a1335a6d78ffece4c9380582416ace6feeb608e84d279fc7"
[[package]]name = "line-wrap"version = "0.1.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9"dependencies = ["safemem",][[package]]name = "linked-hash-map"version = "0.5.6"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
name = "lipsum"version = "0.9.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9c5e9ef2d2ad6fe67a59ace27c203c8d3a71d195532ee82e3bbe0d5f9a9ca541"dependencies = ["rand","rand_chacha",][[package]]name = "litemap"version = "0.7.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "77a1a2647d5b7134127971a6de0d533c49de2159167e7f259c427195f87168a1"[[package]]
][[package]]name = "ptr_meta"version = "0.1.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1"dependencies = ["ptr_meta_derive",][[package]]name = "ptr_meta_derive"version = "0.1.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"dependencies = ["proc-macro2","quote","syn 1.0.109",][[package]]name = "quick-xml"version = "0.28.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "0ce5e73202a820a31f8a0ee32ada5e21029c81fd9e3ebf668a40832e4219d9d1"dependencies = ["memchr","serde",
][[package]]name = "radium"version = "0.7.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"[[package]]name = "rand"version = "0.8.5"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"dependencies = ["rand_core",][[package]]name = "rand_chacha"version = "0.3.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"dependencies = ["ppv-lite86","rand_core",
][[package]]name = "rkyv"version = "0.7.42"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58"dependencies = ["bitvec","bytecheck","hashbrown 0.12.3","ptr_meta","rend","rkyv_derive","seahash","tinyvec","uuid",][[package]]name = "rkyv_derive"version = "0.7.42"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d"dependencies = ["proc-macro2","quote","syn 1.0.109",
[[package]]name = "strum"version = "0.24.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"dependencies = ["strum_macros",][[package]]name = "strum_macros"version = "0.24.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"dependencies = ["heck","proc-macro2","quote","rustversion","syn 1.0.109",]
][[package]]name = "synstructure"version = "0.13.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06"dependencies = ["proc-macro2","quote","syn 2.0.38","unicode-xid",][[package]]name = "syntect"version = "5.1.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e02b4b303bf8d08bfeb0445cba5068a3d306b6baece1d5582171a9bf49188f91"dependencies = ["bincode","bitflags 1.3.2","fancy-regex","flate2","fnv","once_cell","plist","regex-syntax 0.7.5","serde","serde_json","thiserror","walkdir","yaml-rust",][[package]]name = "tap"version = "1.0.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"[[package]]name = "thiserror"version = "1.0.50"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"dependencies = ["thiserror-impl",][[package]]name = "thiserror-impl"version = "1.0.50"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"dependencies = ["proc-macro2","quote","syn 2.0.38",
name = "typst-library"version = "0.9.0"source = "git+https://github.com/typst/typst#3a1e47913d874647e5d8d013a7e21beca96453d6"dependencies = ["az","chinese-number","ciborium","comemo","csv","ecow","hayagriva","hypher","icu_properties","icu_provider","icu_provider_adapters","icu_provider_blob","icu_segmenter","indexmap","kurbo","lipsum","log","once_cell","roxmltree","rustybuzz","serde_json","serde_yaml","smallvec","syntect","time","toml","tracing","ttf-parser","typed-arena","typst","unicode-bidi","unicode-math-class","unicode-script","unicode-segmentation",][[package]]
name = "unic-langid"version = "0.9.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "398f9ad7239db44fd0f80fe068d12ff22d78354080332a5077dc6f52f14dcf2f"dependencies = ["unic-langid-impl",][[package]]name = "unic-langid-impl"version = "0.9.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e35bfd2f2b8796545b55d7d3fd3e89a0613f68a0d1c8bc28cb7ff96b411a35ff"dependencies = ["serde","tinystr",][[package]]
[[package]]name = "unicode-xid"version = "0.2.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"[[package]]name = "unsafe-libyaml"version = "0.2.9"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa"
][[package]]name = "writeable"version = "0.5.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c0af0c3d13faebf8dda0b5256fa7096a2d5ccb662f7b9f54a40fe201077ab1c2"[[package]]name = "wyz"version = "0.5.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"dependencies = ["tap",
name = "yoke"version = "0.7.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "61e38c508604d6bbbd292dadb3c02559aa7fff6b654a078a36217cad871636e4"dependencies = ["serde","stable_deref_trait","yoke-derive","zerofrom",][[package]]name = "yoke-derive"version = "0.7.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d5e19fb6ed40002bab5403ffa37e53e0e56f914a4450c8765f533018db1db35f"dependencies = ["proc-macro2","quote","syn 2.0.38","synstructure",][[package]]
[[package]]name = "zerofrom-derive"version = "0.1.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e6a647510471d372f2e6c2e6b7219e44d8c574d24fdc11c610a61455782f18c3"dependencies = ["proc-macro2","quote","syn 2.0.38","synstructure",][[package]]name = "zerovec"version = "0.10.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "1194130c5b155bf8ae50ab16c86ab758cd695cf9ad176d2f870b744cbdbb572e"dependencies = ["serde","yoke","zerofrom","zerovec-derive",][[package]]name = "zerovec-derive"version = "0.10.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "acabf549809064225ff8878baedc4ce3732ac3b07e7c7ce6e5c2ccdbc485c324"dependencies = ["proc-macro2","quote","syn 2.0.38",]