Skip to content

Commit 04f3764

Browse files
committed
v1.0.2: fix PDF export on Windows
- HOME env fallback to USERPROFILE on Windows (get_home_dir, recovery, custom CSS) - Inherit system PATH + append platform-specific TeX directories - Latin Modern font detection across multiple TeX Live paths (Win/Mac) - Use Consolas as monofont fallback on Windows instead of SF NS Mono
1 parent 575399f commit 04f3764

5 files changed

Lines changed: 52 additions & 16 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "tauri-app",
33
"private": true,
4-
"version": "1.0.1",
4+
"version": "1.0.2",
55
"type": "module",
66
"scripts": {
77
"dev": "vite",

src-tauri/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mx"
3-
version = "1.0.1"
3+
version = "1.0.2"
44
description = "Fast, lightweight markdown editor for the AI era"
55
authors = ["Tony@Vibery Studio"]
66
edition = "2024"

src-tauri/src/lib.rs

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,9 @@ fn list_directory(path: String) -> Result<Vec<DirEntry>, String> {
9393

9494
#[tauri::command]
9595
fn get_home_dir() -> Result<String, String> {
96-
std::env::var("HOME").map_err(|e| e.to_string())
96+
std::env::var("HOME")
97+
.or_else(|_| std::env::var("USERPROFILE"))
98+
.map_err(|e| e.to_string())
9799
}
98100

99101
#[tauri::command]
@@ -239,7 +241,9 @@ struct RecoveryInfo {
239241
}
240242

241243
fn get_recovery_dir() -> Result<PathBuf, String> {
242-
let home = std::env::var("HOME").map_err(|e| e.to_string())?;
244+
let home = std::env::var("HOME")
245+
.or_else(|_| std::env::var("USERPROFILE"))
246+
.map_err(|e| e.to_string())?;
243247
let dir = PathBuf::from(home).join(".mx").join("recovery");
244248
fs::create_dir_all(&dir).map_err(|e| e.to_string())?;
245249
Ok(dir)
@@ -354,7 +358,15 @@ fn export_pdf_blocking(markdown_content: String, output_path: String, app: tauri
354358
let tmp_dir = std::env::temp_dir().join("mx_export");
355359
let _ = fs::create_dir_all(&tmp_dir);
356360
let tmp_md = tmp_dir.join("export.md");
357-
let path_env = "/Library/TeX/texbin:/opt/anaconda3/bin:/usr/local/bin:/usr/bin:/bin";
361+
362+
// Build PATH: inherit system PATH and append known TeX locations
363+
let sys_path = std::env::var("PATH").unwrap_or_default();
364+
let path_env = if cfg!(target_os = "windows") {
365+
// Windows: append common MiKTeX/TeX Live paths
366+
format!("{};C:\\Program Files\\MiKTeX\\miktex\\bin\\x64;C:\\texlive\\2024\\bin\\windows;C:\\texlive\\2025\\bin\\windows", sys_path)
367+
} else {
368+
format!("{}:/Library/TeX/texbin:/opt/anaconda3/bin:/usr/local/bin:/usr/bin:/bin", sys_path)
369+
};
358370

359371
// Step 1: Extract mermaid blocks, render to PNG via mermaid.ink API
360372
let mut processed = String::new();
@@ -391,7 +403,7 @@ fn export_pdf_blocking(markdown_content: String, output_path: String, app: tauri
391403

392404
let download = Command::new("curl")
393405
.args(["-sL", "--max-time", "30", "-o", png_file.to_str().unwrap(), &url])
394-
.env("PATH", path_env)
406+
.env("PATH", &path_env)
395407
.output();
396408

397409
if let Ok(r) = download {
@@ -435,12 +447,26 @@ fn export_pdf_blocking(markdown_content: String, output_path: String, app: tauri
435447
// Latin Modern = OpenType version of Computer Modern (default LaTeX font)
436448
// Falls back to Times New Roman if Latin Modern is not installed
437449
let lm_header = tmp_dir.join("fonts.tex");
438-
let lm_font_dir = "/usr/local/texlive/2025basic/texmf-dist/fonts/opentype/public/lm/";
439-
let use_latin_modern = Path::new(lm_font_dir).join("lmroman10-regular.otf").exists();
440-
if use_latin_modern {
450+
let lm_font_dirs: &[&str] = if cfg!(target_os = "windows") {
451+
&[
452+
"C:/texlive/2025/texmf-dist/fonts/opentype/public/lm/",
453+
"C:/texlive/2024/texmf-dist/fonts/opentype/public/lm/",
454+
]
455+
} else {
456+
&[
457+
"/usr/local/texlive/2025basic/texmf-dist/fonts/opentype/public/lm/",
458+
"/usr/local/texlive/2025/texmf-dist/fonts/opentype/public/lm/",
459+
"/usr/local/texlive/2024/texmf-dist/fonts/opentype/public/lm/",
460+
]
461+
};
462+
let lm_font_dir = lm_font_dirs.iter()
463+
.find(|d| Path::new(d).join("lmroman10-regular.otf").exists())
464+
.copied();
465+
let use_latin_modern = lm_font_dir.is_some();
466+
if let Some(dir) = lm_font_dir {
441467
let header = format!(
442468
"\\setmainfont[Path={dir},BoldFont=lmroman10-bold.otf,ItalicFont=lmroman10-italic.otf,BoldItalicFont=lmroman10-bolditalic.otf]{{lmroman10-regular.otf}}\n\\setmonofont[Path={dir}]{{lmmono10-regular.otf}}\n",
443-
dir = lm_font_dir
469+
dir = dir
444470
);
445471
let _ = fs::write(&lm_header, header);
446472
}
@@ -468,11 +494,19 @@ fn export_pdf_blocking(markdown_content: String, output_path: String, app: tauri
468494
args.push("-H".to_string());
469495
args.push(lm_header.to_str().unwrap().to_string());
470496
} else {
471-
// Fallback: Times New Roman + SF NS Mono
497+
// Fallback: Times New Roman + platform-appropriate mono font
472498
args.extend_from_slice(&[
473499
"-V".to_string(), "mainfont:Times New Roman".to_string(),
474-
"-V".to_string(), "monofont:.SF NS Mono".to_string(),
475500
]);
501+
if cfg!(target_os = "macos") {
502+
args.extend_from_slice(&[
503+
"-V".to_string(), "monofont:.SF NS Mono".to_string(),
504+
]);
505+
} else {
506+
args.extend_from_slice(&[
507+
"-V".to_string(), "monofont:Consolas".to_string(),
508+
]);
509+
}
476510
}
477511
}
478512

@@ -481,7 +515,7 @@ fn export_pdf_blocking(markdown_content: String, output_path: String, app: tauri
481515

482516
let mut child = Command::new("pandoc")
483517
.args(&args)
484-
.env("PATH", path_env)
518+
.env("PATH", &path_env)
485519
.stdin(std::process::Stdio::null())
486520
.stdout(std::process::Stdio::null())
487521
.stderr(std::process::Stdio::from(stderr_out))
@@ -810,7 +844,9 @@ fn replace_delimited<F: Fn(&str) -> String>(text: &str, open: &str, close: &str,
810844

811845
#[tauri::command]
812846
fn load_custom_css() -> Result<String, String> {
813-
let home = std::env::var("HOME").map_err(|e| e.to_string())?;
847+
let home = std::env::var("HOME")
848+
.or_else(|_| std::env::var("USERPROFILE"))
849+
.map_err(|e| e.to_string())?;
814850
let path = std::path::PathBuf::from(home).join(".mx").join("preview.css");
815851
if path.exists() {
816852
std::fs::read_to_string(&path).map_err(|e| e.to_string())

src-tauri/tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://schema.tauri.app/config/2",
33
"productName": "mx",
4-
"version": "1.0.1",
4+
"version": "1.0.2",
55
"identifier": "com.mx.editor",
66
"build": {
77
"beforeDevCommand": "npm run dev",

0 commit comments

Comments
 (0)