Decode percent-encoded data URI parameters - #2547
Newman Gao (bozarnr) wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
No unresolved review issues were identified, and regression coverage is included.
Review effort: Lite
Findings: None
What changed in this PR
Updates data URI parsing to decode percent-encoded metadata parameters, including charset, before conversion.
Changes:
- Decode parameter values with
urllib.parse.unquote. - Add regression coverage for encoded charset and content values.
| File | Description |
|---|---|
packages/markitdown/tests/test_module_misc.py |
Tests percent-encoded data URI parsing. |
packages/markitdown/src/markitdown/_uri_utils.py |
Decodes data URI parameter values. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
PRABHU KIRAN VANDRANKI (VANDRANKI)
left a comment
There was a problem hiding this comment.
Community review, does not clear the merge gate.
I read the diff and the full parse_data_uri function in packages/markitdown/src/markitdown/_uri_utils.py on main to check how the changed line interacts with the rest of the parsing.
The function splits the data URI header on ;, pops a trailing base64 flag (checked as an exact-match string comparison on parts[-1], unaffected by this change) and the mime type (parts.pop(0), also unaffected), then parses the remaining key=value parts into the attributes dict. Before this fix, the value half of each key=value pair was stored raw, with no percent-decoding, even though the body of the data URI (content = ... unquote_to_bytes(data)) was already correctly percent-decoded. That's an inconsistency: a produced URI like data:text/plain;charset=utf%2D8,Hello%2C%20World%21 would give attributes["charset"] == "utf%2D8" instead of "utf-8", which would break any caller doing a codec/charset lookup with that value.
The fix wraps the value in unquote(value). I traced the new test case by hand: meta = "text/plain;charset=utf%2D8" splits into ["text/plain", "charset=utf%2D8"], mime_type pops "text/plain", the remaining part splits into key="charset", value="utf%2D8", and unquote("utf%2D8") correctly gives "utf-8" (%2D is -). That matches the test's assertion.
This is a narrow, correctly scoped fix (only the attribute-value branch changes, not the base64-flag or bare-flag branches, which don't need decoding since they're compared as exact tokens) and the new test exercises the actual percent-encoded case rather than just re-asserting the old behavior.
Summary
charsetvalues so downstream stream decoding receives the declared charsetValidation
data:text/plain;charset=utf%2D8,...python -m py_compile packages/markitdown/src/markitdown/_uri_utils.py packages/markitdown/tests/test_module_misc.pygit diff --checkThe existing base64-data URI work addresses escapes in the payload. This change covers the independent metadata parameter path consumed by
MarkItDown.convert_uri().