index/objects/typesetting/
typst.rs1use std::rc::Rc;
2
3use typst::{foundations::Bytes, layout::Abs, text::Font};
4use typst_as_lib::TypstTemplate;
5use typst_svg::svg_merged;
6use wasm_bindgen::prelude::*;
7
8use crate::{objects::vector_object::VectorObjectBuilder, utils::font_face::FontFace};
9
10#[wasm_bindgen]
12pub struct Typst {
13 source: Rc<String>,
15}
16
17#[wasm_bindgen]
18impl Typst {
19 #[wasm_bindgen(constructor, return_description = "A new Typst object.")]
21 pub fn new(
22 #[wasm_bindgen(param_description = "The source of the Typst object.")]
23 source: String,
24 ) -> Typst {
25 Typst { source: Rc::new(source) }
26 }
27 #[wasm_bindgen(getter, return_description = "The source of the Typst object.")]
29 pub fn source(&self) -> String {
30 self.source.to_string()
31 }
32 #[wasm_bindgen(return_description = "The SVG string.")]
34 pub fn to_svg(
35 &self,
36 #[wasm_bindgen(param_description = "The font faces to use when rendering the Typst object.")]
37 font_faces: Option<Vec<FontFace>>
38 ) -> Result<String, JsError> {
39 let fonts = font_faces.unwrap_or(Vec::new())
40 .iter()
41 .map(|font_face| font_face.data())
42 .map(|font_data| Font::new(Bytes::new(font_data), 0))
43 .collect::<Vec<Option<Font>>>();
44 if fonts.iter().any(|font| font.is_none()) {
45 return Err(JsError::new("Failed to load font."));
46 }
47 let fonts = fonts.into_iter().map(|font| font.unwrap()).collect::<Vec<Font>>();
48 let template = TypstTemplate::new(self.source()).add_fonts(fonts);
49 let doc = template
50 .compile()
51 .output
52 .map_err(|_| JsError::new("Failed to render Typst object."))?;
53 let padding = Abs::zero();
54 let svg = svg_merged(&doc, padding);
55 Ok(svg)
56 }
57 #[wasm_bindgen(return_description = "A VectorObjectBuilder representing the typesetting object.")]
59 pub fn vector_object_builder(
60 &self,
61 #[wasm_bindgen(param_description = "The FontFaces to use when rendering the Typst object, if any.")]
62 font_faces: Option<Vec<FontFace>>,
63 ) -> Result<VectorObjectBuilder, JsError> {
64 let svg = self.to_svg(font_faces.clone())?;
65 let builder = VectorObjectBuilder::from_svg(svg, font_faces, None);
66 Ok(builder)
67 }
68}