@@ -93,7 +93,9 @@ fn list_directory(path: String) -> Result<Vec<DirEntry>, String> {
9393
9494#[ tauri:: command]
9595fn 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
241243fn 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]
812846fn 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 ( ) )
0 commit comments