use typst::diag::{FileError, FileResult};
use typst::foundations::{Bytes, Datetime};
use typst::syntax::{FileId, Source, VirtualPath};
use typst::text::{Font, FontBook};
use typst::utils::LazyHash;
use typst::{Library, LibraryExt};
pub struct WasmWorld {
main_id: FileId,
main_source: Source,
font_book: LazyHash<FontBook>,
fonts: Vec<Font>,
library: LazyHash<Library>,
}
impl WasmWorld {
pub fn new(typst_content: String) -> Self {
let fonts = Self::load_embedded_fonts();
let font_book = LazyHash::new(FontBook::from_fonts(&fonts));
let main_id = FileId::new(None, VirtualPath::new("/main.typ"));
let main_source = Source::new(main_id, typst_content);
Self {
main_id,
main_source,
font_book,
fonts,
library: LazyHash::new(Library::default()),
}
}
fn load_embedded_fonts() -> Vec<Font> {
let font_data: &[&[u8]] = &[
include_bytes!("fonts/LiberationSans-Regular.ttf"),
include_bytes!("fonts/LiberationSans-Bold.ttf"),
include_bytes!("fonts/LiberationSans-Italic.ttf"),
include_bytes!("fonts/LiberationSans-BoldItalic.ttf"),
include_bytes!("fonts/LiberationSerif-Regular.ttf"),
include_bytes!("fonts/LiberationSerif-Bold.ttf"),
include_bytes!("fonts/LiberationSerif-Italic.ttf"),
include_bytes!("fonts/LiberationSerif-BoldItalic.ttf"),
include_bytes!("fonts/LiberationMono-Regular.ttf"),
include_bytes!("fonts/LiberationMono-Bold.ttf"),
include_bytes!("fonts/LiberationMono-Italic.ttf"),
include_bytes!("fonts/LiberationMono-BoldItalic.ttf"),
];
font_data
.iter()
.filter_map(|data| Font::new(Bytes::new(*data), 0))
.collect()
}
}
impl typst::World for WasmWorld {
fn library(&self) -> &LazyHash<Library> {
&self.library
}
fn book(&self) -> &LazyHash<FontBook> {
&self.font_book
}
fn main(&self) -> FileId {
self.main_id
}
fn source(&self, id: FileId) -> FileResult<Source> {
if id == self.main_id {
Ok(self.main_source.clone())
} else {
Err(FileError::NotFound(
id.vpath().as_rootless_path().to_path_buf(),
))
}
}
fn file(&self, id: FileId) -> FileResult<Bytes> {
Err(FileError::NotFound(
id.vpath().as_rootless_path().to_path_buf(),
))
}
fn font(&self, index: usize) -> Option<Font> {
self.fonts.get(index).cloned()
}
fn today(&self, _offset: Option<i64>) -> Option<Datetime> {
let now = js_sys::Date::new_0();
let year = now.get_full_year() as i32;
let month = now.get_month() as u8 + 1;
let day = now.get_date() as u8;
Datetime::from_ymd(year, month, day)
}
}