mirror of
https://github.com/priyanshujain/margin.git
synced 2026-10-02 19:17:03 +00:00
feat(pdf): embed Typst compiler with compile_pdf command
This commit is contained in:
1 parent
29c412849e
commit
e21db2be5d
4 files changed
+7011
No files matched your search
Generated
+6937
File diff suppressed because it is too large.
Load diff
@@ -22,4 +22,8 @@ tauri = { version = "2", features = [] }
|
|||||||
tauri-plugin-opener = "2"
|
tauri-plugin-opener = "2"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
|
base64 = "0.22"
|
||||||
|
typst = "0.14.2"
|
||||||
|
typst-pdf = "0.14.2"
|
||||||
|
typst-as-lib = "0.15.5"
|
||||||
|
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
|
mod pdf;
|
||||||
|
|
||||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
pub fn run() {
|
pub fn run() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.plugin(tauri_plugin_opener::init())
|
.plugin(tauri_plugin_opener::init())
|
||||||
|
.invoke_handler(tauri::generate_handler![pdf::compile_pdf])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running margin");
|
.expect("error while running margin");
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
use base64::Engine;
|
||||||
|
use base64::engine::general_purpose::STANDARD;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use typst::diag::{Severity, SourceDiagnostic};
|
||||||
|
use typst::layout::PagedDocument;
|
||||||
|
use typst_as_lib::TypstEngine;
|
||||||
|
|
||||||
|
static LITERATA: &[u8] = include_bytes!("../../public/fonts/Literata-VF.ttf");
|
||||||
|
static LITERATA_ITALIC: &[u8] = include_bytes!("../../public/fonts/Literata-Italic-VF.ttf");
|
||||||
|
static HANKEN: &[u8] = include_bytes!("../../public/fonts/HankenGrotesk-VF.ttf");
|
||||||
|
static HANKEN_ITALIC: &[u8] = include_bytes!("../../public/fonts/HankenGrotesk-Italic-VF.ttf");
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct ImageInput {
|
||||||
|
path: String,
|
||||||
|
data: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile(source: String, images: &[ImageInput]) -> Result<Vec<u8>, String> {
|
||||||
|
let mut binaries: Vec<(&str, Vec<u8>)> = Vec::with_capacity(images.len());
|
||||||
|
for image in images {
|
||||||
|
let bytes = STANDARD
|
||||||
|
.decode(image.data.as_bytes())
|
||||||
|
.map_err(|e| format!("failed to decode image \"{}\": {e}", image.path))?;
|
||||||
|
binaries.push((image.path.as_str(), bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
let engine = TypstEngine::builder()
|
||||||
|
.main_file(source)
|
||||||
|
.fonts([LITERATA, LITERATA_ITALIC, HANKEN, HANKEN_ITALIC])
|
||||||
|
.with_static_file_resolver(binaries)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let document: PagedDocument = engine.compile().output.map_err(|e| format_diagnostics(&e))?;
|
||||||
|
|
||||||
|
typst_pdf::pdf(&document, &Default::default()).map_err(|d| format_source_diagnostics(&d))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn compile_pdf(source: String, images: Vec<ImageInput>) -> Result<tauri::ipc::Response, String> {
|
||||||
|
compile(source, &images).map(tauri::ipc::Response::new)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_diagnostics(error: &typst_as_lib::TypstAsLibError) -> String {
|
||||||
|
match error {
|
||||||
|
typst_as_lib::TypstAsLibError::TypstSource(diagnostics) => format_source_diagnostics(diagnostics),
|
||||||
|
other => other.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_source_diagnostics(diagnostics: &[SourceDiagnostic]) -> String {
|
||||||
|
diagnostics
|
||||||
|
.iter()
|
||||||
|
.map(|diagnostic| {
|
||||||
|
let kind = match diagnostic.severity {
|
||||||
|
Severity::Error => "error",
|
||||||
|
Severity::Warning => "warning",
|
||||||
|
};
|
||||||
|
let mut message = format!("{kind}: {}", diagnostic.message);
|
||||||
|
for hint in &diagnostic.hints {
|
||||||
|
message.push_str(&format!("\n hint: {hint}"));
|
||||||
|
}
|
||||||
|
message
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n")
|
||||||
|
}
|
||||||
Reference in new issue
Block a user