Skip to content

fix(desktop): keep exported links working from folders named with #, ? or % - #5320

Merged
Jocs merged 1 commit into
marktext:developfrom
Dev-next-gen:fix/export-link-dirname-special-chars
Sep 14, 2026
Merged

Jocs merged 1 commit into
marktext:developfrom
Dev-next-gen:fix/export-link-dirname-special-chars

Conversation

@Dev-next-gen

Copy link
Copy Markdown
Contributor

No issue filed for this one; it is the export-side twin of #5212 / #5301.

Summary

After #5301 fixed relative images in the editor for documents living in a folder named with #, ? or %, I looked for other places that build a file:// URL from window.DIRNAME and found resolveLocalLinkHref, which rewrites relative links when exporting to styled HTML or PDF (#1688). It still pastes the raw directory into the URL.

With a document in /home/me/C# 100%25 what?/ and a link [notes](./notes.md), the exported link is file:///home/me/C# 100%25 what?/notes.md. A browser reads that as the path /home/me/C, a fragment starting at #, and %25 gets decoded to %, so the link points nowhere once the HTML is opened.

The fix is the same as in muya's getImageSrc: escape %, ? and # in the directory only. The markdown href is already URL-form, so it is left alone and keeps its own #fragment and %20-style escapes.

Type of change

  • Bug fix (non-breaking, fixes an issue)
  • New feature (non-breaking, adds functionality)
  • Breaking change (causes existing functionality to change)
  • Documentation update

Test plan

  • New tests added: test/unit/specs/resolveLinkHref.spec.ts covers the escaped directory, a link that carries its own fragment and %20, and checks that new URL() on the result gives back the real path with no hash or query. All three fail on develop and pass with the change; exportHtml.spec.ts and export-header-footer-diagram.spec.ts still pass, and pnpm run lint / pnpm run typecheck are clean.
  • Manually tested on: I only ran the unit tests (Linux), I did not record an export from the packaged app.

Notes for reviewers [optional]

The same raw window.DIRNAME join exists for images in util/resolveImageSrc.ts (resolveLocalImageSrc, used by export and print). I left it out because that file is already modified by the open #4789 and I did not want to conflict with it; happy to follow up once that settles.


By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.

AI tools used

…? or %

resolveLocalLinkHref joined the raw window.DIRNAME into a file:// URL, so a
`#` or `?` in the document's folder name started a fragment or query in the
exported HTML / PDF link, and a literal `%xx` in the name was percent-decoded.
Escape those characters in the directory only, as getImageSrc does in muya
since marktext#5301: the markdown link is already URL-form and keeps its own fragment.

@Jocs Jocs left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Verified the bug and the fix on macOS against a real export, not only the unit tests. A document in C# 100%25 what?/ exported to styled HTML and PDF from develop has every relative link cut off at /C, and clicking one in Chrome opens an error page. The PR build produces C%23 100%2525 what%3F/… links that open the right file and keep their own #fragment. Links from ordinary folders (plain-dir, my notes 中文) are unchanged. The three new specs fail on develop and pass with the change.

Non-blocking: when you do the resolveLocalImageSrc follow-up, which has the same bug (an exported <img> from that folder fails to load), consider moving encodeDirnameForUrl into a shared desktop util rather than adding a third copy.

Thanks!

@Jocs
Jocs merged commit b267efb into marktext:develop Sep 14, 2026
10 checks passed
Jocs added a commit that referenced this pull request Sep 14, 2026
… ? or % (#5335) (#5337)

resolveLocalImageSrc joined the raw window.DIRNAME into a file:// URL, so
a `#` or `?` in the document's folder name started a fragment or query in
the exported HTML / PDF image, and a literal `%xx` in the name was
percent-decoded. Escape those characters in the directory only, as
resolveLocalLinkHref does since #5320: the markdown image path is already
URL-form and keeps its own query and escapes.

localPathToFileUrl and encodeDirnameForUrl move into util/fileUrl.ts so the
image and link resolvers share them.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_019p11VSo6R74VD94ezRFNGb
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