Skip to content

fix: remove encodeURI for image links#128

Merged
bingryan merged 1 commit into
bingryan:masterfrom
Lamply:master
Jul 2, 2026
Merged

fix: remove encodeURI for image links#128
bingryan merged 1 commit into
bingryan:masterfrom
Lamply:master

Conversation

@Lamply

@Lamply Lamply commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Fixes a bug where Chinese (and other non-ASCII) filenames were incorrectly encoded as URL-encoded strings (e.g., %E6%B5%8B%E8%AF%95.png) when exporting images with fileNameEncode disabled. This happened because encodeURI() was applied to the file name, which is unnecessary since modern file systems natively support UTF-8 filenames. Additionally, the decodeURI call lacked error handling, which could cause export failures when filenames contained invalid percent-encoded sequences.

Changes

  • Removed the unnecessary encodeURI(fileName) call in the image export logic, so Chinese filenames are written as-is to the file system.
  • Added a try...catch block around decodeURIComponent to gracefully handle malformed URI sequences, logging a warning and falling back to the original link if decoding fails.

Testing

  1. In the plugin settings, disable fileNameEncode.
  2. Insert an image with a Chinese filename (e.g., 测试.png) into a note.
  3. Export the note and verify that the exported file retains the original Chinese filename instead of being URL-encoded.
  4. Test with filenames containing invalid % sequences to ensure no export crash occurs.

No breaking changes expected.

Summary by CodeRabbit

  • Bug Fixes
    • Improved embedded image link handling during export by making URL decoding more robust and using safer fallback behavior when decoding fails.
    • Fixed image path/hash generation consistency, especially when image filenames contain special characters or when filename encoding is toggled.
    • Resolved edge cases where some image references could fail to export correctly, with fallback logic preserving more links.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 00b4c98b-6c2e-455b-9f55-f72334d2711f

📥 Commits

Reviewing files that changed from the base of the PR and between 0efdf7f and 0bbcf78.

📒 Files selected for processing (1)
  • src/utils.ts
💤 Files with no reviewable changes (1)
  • src/utils.ts

📝 Walkthrough

Walkthrough

Image URL decoding now uses guarded decodeURIComponent with fallback stripping in two copy paths, filename handling keeps raw names when encoding is disabled, and the non-HTML image replacement branches are removed.

Changes

Image link decoding update

Layer / File(s) Summary
tryCopyImage decoding and filename handling
src/utils.ts
Replaces decodeURI with a guarded decodeURIComponent fallback and computes imageLinkMd5 from raw fileName when fileNameEncode is disabled.
tryCopyMarkdownByRead decoding and filename handling
src/utils.ts
Applies the same decodeURIComponent fallback for image URL decoding and switches the hash/path component from encodeURI(fileName) to raw fileName when fileNameEncode is disabled.
Image replacement branch removal
src/utils.ts
Removes the GFM and default image replacement branches that previously handled non-HTML image output.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: removing encodeURI from image link handling.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src/utils.ts (2)

348-353: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Fallback path leaves the link still percent-encoded, which can break downstream resolution.

When decodeURIComponent throws, the fallback only strips ../ from the still-encoded urlEncodedImageLink. That value then flows into path.parse(path.basename(imageLink)).name (fileName) and plugin.app.metadataCache.getFirstLinkpathDest(imageLink, contentPath), both of which expect a normal (decoded) vault-relative path. On decode failure, link resolution will likely silently miss the real file instead of crashing — an improvement over the previous unguarded decodeURI crash, but still a soft failure mode worth surfacing more clearly (e.g., skip/log the specific image rather than proceeding with a mismatched path).

Also applies to: 861-866

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/utils.ts` around lines 348 - 353, The fallback in the image-link decoding
logic still leaves `imageLink` percent-encoded after `decodeURIComponent` fails,
which can break downstream lookup in `path.parse(...).name` and
`plugin.app.metadataCache.getFirstLinkpathDest(...)`. Update the try/catch
around the `decodeURIComponent(urlEncodedImageLink)` flow in `src/utils.ts` so
the failure path does not continue with a mismatched encoded path; instead,
surface the specific bad image via logging and skip processing that entry, or
otherwise ensure the fallback produces a normalized vault-relative path before
it reaches the file resolution logic.

347-358: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate decode-with-fallback logic across two functions.

The identical try { decodeURIComponent(...).replace(/\.\.\//g, "") } catch { ... } block is now duplicated verbatim in tryCopyImage and tryCopyMarkdownByRead. Consider extracting a shared helper (e.g. safeDecodeImageLink(link: string): string) to avoid drift between the two copies going forward.

♻️ Suggested helper extraction
+function safeDecodeImageLink(urlEncodedImageLink: string): string {
+    try {
+        return decodeURIComponent(urlEncodedImageLink).replace(/\.\.\//g, "");
+    } catch (e) {
+        console.warn(`Unable to decode URI: ${urlEncodedImageLink}`);
+        return urlEncodedImageLink.replace(/\.\.\//g, "");
+    }
+}

Then call safeDecodeImageLink(urlEncodedImageLink) at both sites.

Also applies to: 860-866

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/utils.ts` around lines 347 - 358, The decode-with-fallback block is
duplicated in tryCopyImage and tryCopyMarkdownByRead, so extract it into a
shared helper such as safeDecodeImageLink(link: string): string in src/utils.ts
and have both call sites use it instead of inlining the try/catch. Keep the
helper responsible for decodeURIComponent, the ../ sanitization, and the
console.warn fallback so the behavior stays identical while avoiding drift
between the two functions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/utils.ts`:
- Around line 348-353: The fallback in the image-link decoding logic still
leaves `imageLink` percent-encoded after `decodeURIComponent` fails, which can
break downstream lookup in `path.parse(...).name` and
`plugin.app.metadataCache.getFirstLinkpathDest(...)`. Update the try/catch
around the `decodeURIComponent(urlEncodedImageLink)` flow in `src/utils.ts` so
the failure path does not continue with a mismatched encoded path; instead,
surface the specific bad image via logging and skip processing that entry, or
otherwise ensure the fallback produces a normalized vault-relative path before
it reaches the file resolution logic.
- Around line 347-358: The decode-with-fallback block is duplicated in
tryCopyImage and tryCopyMarkdownByRead, so extract it into a shared helper such
as safeDecodeImageLink(link: string): string in src/utils.ts and have both call
sites use it instead of inlining the try/catch. Keep the helper responsible for
decodeURIComponent, the ../ sanitization, and the console.warn fallback so the
behavior stays identical while avoiding drift between the two functions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8d740376-5d50-4eeb-8536-2fa7b9f610ea

📥 Commits

Reviewing files that changed from the base of the PR and between 4df6f25 and 0efdf7f.

📒 Files selected for processing (1)
  • src/utils.ts

@bingryan
bingryan merged commit 71c4c99 into bingryan:master Jul 2, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants