Skip to content

Commit 1a0a675

Browse files
committed
fix(macos): fix can't open file by double click file in Finder and open -a in commandline
Changes: - Add decode_file_url() function using percent_encoding crate - Handle file:/// and file://localhost/ URL formats used by macOS - Add percent-encoding = "2.3" to Cargo.toml (explicit dependency) - Update Cargo.lock with percent-encoding dependency - Add error logging for file path validation failures This patch ensures proper decoding of URL-encoded file paths including UTF-8 multi-byte characters (e.g., Chinese filenames) when files are opened via `open -a markdown-viewer FILE.md` command. The percent_encoding crate is already included as a transitive dependency through Tauri, so this doesn't add a new dependency to the final binary.
1 parent 5dc1718 commit 1a0a675

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

src-tauri/Cargo.lock

Lines changed: 1 addition & 0 deletions
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 & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,5 @@ notify = "6.0"
3030
tokio = { version = "1.0", features = ["fs"] }
3131
html-escape = "0.2"
3232
regex = "1.0"
33+
percent-encoding = "2.3"
3334

src-tauri/src/lib.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use syntect::parsing::SyntaxSet;
1111
use syntect::highlighting::ThemeSet;
1212
use syntect::html::highlighted_html_for_string;
1313
use regex;
14+
use percent_encoding::percent_decode_str;
1415

1516

1617
// Security constants
@@ -129,6 +130,31 @@ fn create_secure_regex(pattern: &str) -> Result<regex::Regex, String> {
129130
.map_err(|e| format!("Failed to create regex: {}", e))
130131
}
131132

133+
// Decode file:// URL using percent_encoding crate (already included via Tauri dependencies)
134+
// Supports UTF-8 multi-byte characters including Chinese characters
135+
fn decode_file_url(url_str: &str) -> String {
136+
// Step 1: Decode URL-encoded string to UTF-8 using percent_encoding crate
137+
// This automatically handles UTF-8 multi-byte characters (including Chinese)
138+
let decoded_url = percent_decode_str(url_str)
139+
.decode_utf8_lossy()
140+
.to_string();
141+
142+
// Step 2: Now handle file:// prefix and format on the decoded string
143+
let mut path = decoded_url.trim_start_matches("file://").to_string();
144+
145+
// Handle file:/// or file://localhost/ formats
146+
// macOS typically uses file:///absolute/path format (three slashes)
147+
if path.starts_with("//") {
148+
// file:////path -> /path (remove extra slashes)
149+
path = path.trim_start_matches("//").to_string();
150+
} else if path.starts_with("localhost/") {
151+
// file://localhost/path -> path
152+
path = path.trim_start_matches("localhost/").to_string();
153+
}
154+
155+
path
156+
}
157+
132158
// Security validation functions
133159
fn validate_file_path(file_path: &str) -> Result<PathBuf, String> {
134160
let path = Path::new(file_path);
@@ -746,10 +772,9 @@ pub fn run() {
746772
let app_handle = _app_handle;
747773
// Find the first markdown file in the opened URLs
748774
for url in urls {
749-
// Convert URL to string and handle file:// URLs
750775
let url_str = url.as_str();
751776
let file_path = if url_str.starts_with("file://") {
752-
url_str.trim_start_matches("file://").to_string()
777+
decode_file_url(url_str)
753778
} else {
754779
url_str.to_string()
755780
};
@@ -766,6 +791,9 @@ pub fn run() {
766791

767792
// Also try to emit the event to the frontend if it's ready
768793
let _ = app_handle.emit("file-opened-via-os", &validated_str);
794+
} else {
795+
// Add error log for debugging
796+
eprintln!("Failed to validate file path: {}", file_path);
769797
}
770798
break;
771799
}

0 commit comments

Comments
 (0)