diff options
| author | Anhgelus Morhtuuzh <william@herges.fr> | 2026-04-29 22:30:04 +0200 |
|---|---|---|
| committer | Anhgelus Morhtuuzh <william@herges.fr> | 2026-04-29 22:30:04 +0200 |
| commit | 78f399521661c82e45e627bbbdc8ce4daa9e5207 (patch) | |
| tree | 2671aa93feb01956aded5cef1e725f9aff4aa3a9 /lib/typst/src | |
| parent | 77ccdd8559383c25fc59fbcba38117102e5657b5 (diff) | |
style(typst): move in lib folder
Diffstat (limited to 'lib/typst/src')
| -rw-r--r-- | lib/typst/src/lib.rs | 52 | ||||
| -rw-r--r-- | lib/typst/src/world.rs | 88 |
2 files changed, 140 insertions, 0 deletions
diff --git a/lib/typst/src/lib.rs b/lib/typst/src/lib.rs new file mode 100644 index 0000000..5c2ee0d --- /dev/null +++ b/lib/typst/src/lib.rs @@ -0,0 +1,52 @@ +//! Based on https://github.com/zeon256/minimal-typst-svg-renderer +use std::ffi::{CStr, CString}; +use std::os::raw::c_char; + +use typst::layout::PagedDocument; +use typst_svg::svg_frame; + +use crate::world::MinimalWorld; + +mod world; + +pub fn compile(content: &str) -> String { + let world = MinimalWorld::new(content); + + let res = typst::compile::<PagedDocument>(&world); + + if !res.warnings.is_empty() { + eprintln!("Warnings: {:?}", res.warnings); + } + + let doc = res.output.expect("Error compiling typst"); + + svg_frame(&doc.pages[0].frame) +} + +pub fn escape_math(content: &str) -> String { + content.replace("$", r"\$").replace("\n", r"\ ") +} + +unsafe fn convert_call(source: *const c_char, f: fn(&str) -> String) -> *const c_char { + unsafe { + let res = f(CStr::from_ptr(source).to_str().unwrap()); + CString::new(res).unwrap().into_raw() + } +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn typst_generateSVG(source: *const c_char) -> *const c_char { + unsafe { convert_call(source, compile) } +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn typst_freeString(res: *mut c_char) { + unsafe { + drop(CString::from_raw(res)); + } +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn typst_escapeMath(source: *const c_char) -> *const c_char { + unsafe { convert_call(source, escape_math) } +} diff --git a/lib/typst/src/world.rs b/lib/typst/src/world.rs new file mode 100644 index 0000000..c2fe7c7 --- /dev/null +++ b/lib/typst/src/world.rs @@ -0,0 +1,88 @@ +//! Based on https://github.com/zeon256/minimal-typst-svg-renderer + +use std::path::PathBuf; + +use typst::Library; +use typst::LibraryExt; +use typst::World; +use typst::diag::{FileError, FileResult}; +use typst::foundations::{Bytes, Datetime}; +use typst::syntax::{FileId, Source}; +use typst::text::{Font, FontBook}; +use typst::utils::LazyHash; +use typst_kit::fonts::{FontSlot, Fonts}; + +/// Main interface that determines the environment for Typst. +pub struct MinimalWorld { + /// The content of a source. + source: Source, + + /// The standard library. + library: LazyHash<Library>, + + /// Metadata about all known fonts. + book: LazyHash<FontBook>, + + /// Metadata about all known fonts. + fonts: Vec<FontSlot>, +} + +impl MinimalWorld { + pub fn new(source: impl Into<String>) -> Self { + let mut searcher = Fonts::searcher(); + searcher.include_system_fonts(true); + #[cfg(feature = "embed-fonts")] + searcher.include_embedded_fonts(true); + let fonts = searcher.search(); + + Self { + library: LazyHash::new(Library::default()), + book: LazyHash::new(fonts.book), + fonts: fonts.fonts, + source: Source::detached(source), + } + } +} + +impl World for MinimalWorld { + /// Standard library. + fn library(&self) -> &LazyHash<Library> { + &self.library + } + + /// Metadata about all known Books. + fn book(&self) -> &LazyHash<FontBook> { + &self.book + } + + /// Accessing the main source file. + fn main(&self) -> FileId { + self.source.id() + } + + /// Accessing a specified source file (based on `FileId`). + fn source(&self, id: FileId) -> FileResult<Source> { + if id == self.source.id() { + Ok(self.source.clone()) + } else { + Err(FileError::NotFound(PathBuf::new())) + } + } + + /// Accessing a specified file (non-file). + fn file(&self, _id: FileId) -> FileResult<Bytes> { + Err(FileError::NotFound(PathBuf::new())) + } + + /// Accessing a specified font per index of font book. + fn font(&self, id: usize) -> Option<Font> { + self.fonts.get(id)?.get() + } + + /// Get the current date. + /// + /// Optionally, an offset in hours is given. + fn today(&self, _offset: Option<i64>) -> Option<Datetime> { + None + } +} |
