use std::collections::BTreeMap;
use serde::Deserialize;
use wasm_bindgen::prelude::*;
use crate::{compile_world, world::TypstWorld, CompileOptions};
#[derive(Deserialize)]
struct CompileRequest {
source: String,
#[serde(default)]
files: BTreeMap<String, String>,
#[serde(default)]
inputs: BTreeMap<String, String>,
#[serde(default)]
pdf_standards: Vec<String>,
creation_timestamp: Option<i64>,
pages: Option<String>,
pdf_tags: Option<bool>,
}
impl CompileRequest {
fn options(&self) -> Result<CompileOptions, String> {
Ok(CompileOptions {
inputs: self.inputs.clone(),
pdf_standards: self
.pdf_standards
.iter()
.map(|name| name.parse())
.collect::<Result<_, _>>()?,
creation_timestamp: self.creation_timestamp,
pages: match &self.pages {
Some(pages) => pages
.split(',')
.map(|range| range.trim().parse())
.collect::<Result<_, _>>()?,
None => Vec::new(),
},
pdf_tags: self.pdf_tags.unwrap_or(true),
})
}
}
#[wasm_bindgen]
pub fn compile(request_json: &str) -> Result<Vec<u8>, JsValue> {
let request: CompileRequest = serde_json::from_str(request_json)
.map_err(|error| JsValue::from_str(&format!("invalid compile request JSON: {error}")))?;
let options = request
.options()
.map_err(|error| JsValue::from_str(&format!("invalid compile request: {error}")))?;
let world = TypstWorld::from_virtual(
request.source,
request
.files
.into_iter()
.map(|(path, contents)| (path, contents.into_bytes())),
&options,
)
.map_err(|error| JsValue::from_str(&error))?;
compile_world(&world, &options)
.map(|output| output.pdf)
.map_err(|error| JsValue::from_str(&error.to_string()))
}