Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion packages/markitdown/src/markitdown/_uri_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import base64
import os
import re
from typing import Tuple, Dict
from urllib.request import url2pathname
from urllib.parse import urlparse, unquote_to_bytes
Expand All @@ -12,7 +13,14 @@ def file_uri_to_path(file_uri: str) -> Tuple[str | None, str]:
raise ValueError(f"Not a file URL: {file_uri}")

netloc = parsed.netloc if parsed.netloc else None
path = os.path.abspath(url2pathname(parsed.path))
uri_path = parsed.path
if os.name == "nt":
# ``url2pathname`` decodes escapes after detecting a drive prefix. A
# percent-encoded colon therefore looks root-relative during detection
# and becomes ``\C:\...`` only afterward, causing ``abspath`` to prepend
# the current drive. Decode just the drive separator before detection.
uri_path = re.sub(r"^/([A-Za-z])%3[aA](?=/|$)", r"/\1:", uri_path)
path = os.path.abspath(url2pathname(uri_path))
return netloc, path


Expand Down
9 changes: 8 additions & 1 deletion packages/markitdown/tests/test_module_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,6 @@ def test_file_uris() -> None:
netloc, path = file_uri_to_path(file_uri)
assert netloc is None
assert path == "/path/to/file.txt"

# Test file URI with no host
file_uri = "file:/path/to/file.txt"
netloc, path = file_uri_to_path(file_uri)
Expand All @@ -252,6 +251,14 @@ def test_file_uris() -> None:
assert path == "/path/to/file.txt"


@pytest.mark.skipif(os.name != "nt", reason="Windows drive-letter URI behavior")
def test_file_uri_with_percent_encoded_drive_colon() -> None:
_, unescaped_path = file_uri_to_path("file:///C:/Temp/example.md")
_, escaped_path = file_uri_to_path("file:///C%3A/Temp/example.md")

assert escaped_path == unescaped_path


def test_docx_comments() -> None:
# Test DOCX processing, with comments and setting style_map on init
markitdown_with_style_map = MarkItDown(style_map="comment-reference => ")
Expand Down