typst-cffi 0.6.0

FFI to Typst
Documentation
// Copyright ©2025 The typst-cffi Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

use std::sync::Arc;

use typst::diag::{FileError, FileResult};
use typst::foundations::{Bytes, Datetime, Duration};
use typst::syntax::{FileId, RootedPath, Source, VirtualPath, VirtualRoot};
use typst::text::{Font, FontBook};
use typst::{self, Library, LibraryExt, World};
use typst_kit::fonts::{self,FontStore};
use typst_layout::PagedDocument;
use typst_utils::LazyHash;

use crate::document::Document;

fn default_font_store() -> FontStore {
    let mut store = FontStore::new();
    store.extend(fonts::system());
    store.extend(fonts::embedded());
    store
}

pub(crate) struct Compiler {
    src: Source,
    lib: LazyHash<Library>,
    store: Arc<FontStore>,
}

impl World for Compiler {
    fn library(&self) -> &LazyHash<Library> {
        &self.lib
    }

    fn book(&self) -> &LazyHash<FontBook> {
        self.store.book()
    }

    fn main(&self) -> FileId {
        self.src.id()
    }

    fn source(&self, id: FileId) -> FileResult<Source> {
        if id == self.src.id() {
            Ok(self.src.clone())
        } else {
            Err(FileError::NotFound(std::path::PathBuf::new()))
        }
    }

    fn file(&self, _id: FileId) -> FileResult<Bytes> {
        Err(FileError::NotFound(std::path::PathBuf::new()))
    }

    fn font(&self, i: usize) -> Option<Font> {
        self.store.font(i)
    }

    fn today(&self, _offset: Option<Duration>) -> Option<Datetime> {
        None
    }
}

pub(crate) fn compile(src: String) -> Result<Document, String> {
    let c = Compiler::new(src);

    match typst::compile::<PagedDocument>(&c).output {
        Err(err) => Err(format!("Compilation failed: {err:?}")),
        Ok(doc) => Ok(Document::new(doc)),
    }
}

impl Compiler {
    pub(crate) fn new(src: String) -> Compiler {
        let vpath = VirtualPath::new("file.typ").unwrap();
        let fid = RootedPath::new(VirtualRoot::Project, vpath).intern();
        let src = Source::new(fid, src);

        Compiler {
            src,
            lib: Library::default().into(),
            store: Arc::new(default_font_store()),
        }
    }
}