fix(web): make Windows file links clickable - #6237

Closed
peculiarnewbie wants to merge 4 commits into
pingdotgg:mainfrom
peculiarnewbie:fix/windows-markdown-file-links
Closed

fix(web): make Windows file links clickable#6237
peculiarnewbie wants to merge 4 commits into
pingdotgg:mainfrom
peculiarnewbie:fix/windows-markdown-file-links

Conversation

@peculiarnewbie

@peculiarnewbiepeculiarnewbie commented Aug 11, 2026

Copy link
Copy Markdown

Problem

On Windows, Markdown links with direct drive paths such as [artifact](C:/Users/.../artifact.mp4) rendered as blue text with no usable target. rehype-sanitize interpreted the drive letter as a URL scheme and removed the href before React Markdown's URL transform could normalize it.

Fix

Rewrite only Windows drive-path link destinations to the already-allowed file:/// form while the document is still Markdown AST. The existing URL transform then restores the drive path and sends it through T3 Code's existing file-link renderer. Forward- and backslash drive paths, including encoded and unencoded Unicode segments, are canonicalized to the same lookup key, while unsafe schemes remain subject to the normal sanitizer.

Absolute Windows paths outside the workspace also remain absolute in tooltips and copied paths. The composer's existing mention-chip behavior is unchanged and out of scope.

Before

The label looked like a link, but it had no target and could not be clicked.

Before: Windows drive-path link rendered without a usable target

After

The same destination reaches the existing file-link component; hovering reveals the full path and the link is actionable.

After: Windows drive-path link rendered as an actionable file chip

Verification

  • vp test run apps/web/src/markdown-links.test.ts apps/web/src/markdown-links-rendering.test.tsx apps/web/src/filePathDisplay.test.ts — 46 tests passed
  • vp run --filter @t3tools/web typecheck
  • Targeted vp lint and vp fmt --check for all six changed files
  • Manually verified in the Windows web client; desktop inherits the same web renderer

Implemented with GPT-5.6-Sol in the Codex harness via T3 Code.


Note

Medium Risk
Touches markdown href sanitization and file-link resolution, which are security-adjacent URL handling paths. Scope is narrow and unsafe schemes still go through the existing sanitizer.

Overview
Fixes Windows drive-path markdown links (e.g. C:/... or C:\\...) that rendered as non-clickable text because rehype-sanitize treated the drive letter as a URL scheme and stripped the href.

Adds remarkRewriteWindowsFileLinks, which rewrites only Windows drive destinations to allowed file:/// form in mdast before sanitization. The existing URL transform then restores the drive path for the normal file-link renderer. Also canonicalizes backslash/unicode variants into a shared lookup key via normalizeMarkdownFileLinkHrefKey.

Separately, formatWorkspaceRelativePath now treats Windows drive paths as absolute, so paths outside the workspace stay absolute in tooltips/copied paths instead of getting a workspace label prefix.

Reviewed by Cursor Bugbot for commit 2e03244. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix Windows file path links to be clickable in chat markdown

  • Adds remarkRewriteWindowsFileLinks remark plugin to convert Windows drive-path links (e.g. C:\foo) into file:///C:/... URIs before HTML sanitization, preventing the sanitizer from stripping them.
  • Adds normalizeMarkdownFileLinkHrefKey to produce stable canonical keys for Windows file links regardless of backslashes or percent-encoding, replacing the local helper in ChatMarkdown.tsx.
  • Fixes formatWorkspaceRelativePath in filePathDisplay.ts to avoid prefixing absolute Windows drive paths with the workspace label.

Macroscope summarized 2e03244.

@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8c280e0d-dd44-4bf0-9dab-3c58ad0bb2c3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 11, 2026
@peculiarnewbie
peculiarnewbieforce-pushed the fix/windows-markdown-file-links branch from a1e59dc to f3024d6CompareAugust 11, 2026 22:31
@peculiarnewbie
peculiarnewbie marked this pull request as draft August 11, 2026 22:34
@peculiarnewbie
peculiarnewbie deleted the fix/windows-markdown-file-links branch August 11, 2026 22:37
@macroscopeapp

macroscopeappBot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved 2e03244

Straightforward bug fix making Windows file paths clickable in markdown by converting them to file:// URIs before HTML sanitization. Changes are self-contained with good test coverage, including verification that unsafe schemes remain blocked.

You can customize Macroscope's approvability policy. Learn more.

macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 11, 2026
@peculiarnewbie
peculiarnewbieforce-pushed the fix/windows-markdown-file-links branch from f3024d6 to 6717343CompareAugust 11, 2026 23:17
@github-actionsgithub-actionsBot added size:M 30-99 changed lines (additions + deletions). and removed size:S 10-29 changed lines (additions + deletions). labels Aug 11, 2026
@peculiarnewbie
peculiarnewbie marked this pull request as ready for review August 11, 2026 23:33
Comment threadapps/web/src/markdown-links.ts
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 11, 2026 23:40

Dismissing prior approval to re-evaluate 6717343

macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 12, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 71371ee. Configure here.

Comment threadapps/web/src/markdown-links.ts
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 12, 2026 00:20

Dismissing prior approval to re-evaluate 2e03244

@Defmon3

Copy link
Copy Markdown

Confirmed on Windows. We reproduced drive-letter Windows Markdown links failing to open, then tested the current PR head (2e03244) in our downstream build. The links now resolve and open correctly, including the chat rendering path with line breaks. Thanks for the fix.

@carlosesl1

Copy link
Copy Markdown

I reproduced one remaining gap with the current PR head: valid angle-bracketed destinations containing spaces or balanced parentheses survive the Markdown pipeline, but MARKDOWN_LINK_HREF_PATTERN misses them. That leaves markdownFileLinkMetaByHref empty, so the anchor falls through to the external-link path instead of the existing file-link behavior.

I opened a small, tested follow-up against this branch: peculiarnewbie#1

It keeps the precomputed map as the fast path and falls back to resolving the parsed/normalized href. Regression coverage uses the issue reproduction: <C:/Users/Carlos/My Project/docs/Plan (final).md>. All 43 focused tests, web typecheck, targeted lint, and formatting checks pass.

@CDVolvikCDVolvik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

46/46 across markdown-links.test.ts, markdown-links-rendering.test.tsx and filePathDisplay.test.ts on Linux (Node 24).

I went looking for a mismatch between the rendering test's pipeline and the real one, since markdown-links-rendering.test.tsx builds its own ReactMarkdown rather than rendering ChatMarkdown. There isn't one today. The test uses

protocols: { ...defaultSchema.protocols,href: [...(defaultSchema.protocols?.href??[]),"file"]}urlTransform={(href)=>rewriteMarkdownFileUriHref(href)??defaultUrlTransform(href)}

and ChatMarkdown uses exactly the same protocol list in CHAT_MARKDOWN_SANITIZE_SCHEMA, plus

constmarkdownUrlTransform=useCallback((href: string)=>{returnrewriteMarkdownFileUriHref(href)??defaultUrlTransform(href);},[]);

So the behaviour is faithfully mirrored. Worth flagging anyway, because the mirroring is by hand and there are now three things that have to stay in step: the file protocol entry, remarkRewriteWindowsFileLinks sitting in the remark list, and that urlTransform. Drop any one of them from ChatMarkdown and every test in the new file still passes, because the test supplies its own. CHAT_MARKDOWN_SANITIZE_SCHEMA and markdownUrlTransform are both module-local, so exporting them and importing them into the test would turn this from a parallel implementation into an actual guard, without changing what is asserted.

The still removes unsafe schemes case is the right instinct given this widens what survives sanitization. One more worth adding next to it: a single-letter scheme that is not a drive path. WINDOWS_DRIVE_PATH_PATTERN keys off [A-Za-z]:, and the reason javascript: is safe is that it is many letters, not one. Something like [x](c:/Users/x) versus a genuine one-letter scheme would pin that the widening is limited to drive paths rather than to any short scheme.

isAbsolutePath in filePathDisplay.ts only matches a forward slash after the drive letter:

returnpath.startsWith("/")||/^[A-Za-z]:\//.test(path);

That is fine where it is called, since the value has already been through normalizeMarkdownLinkDestination, but the function name reads general and the next caller will not necessarily normalize first. C:\Users\... returns false from a function called isAbsolutePath. Either accepting both separators or naming it for the normalized input would stop that being a trap later.

@CDVolvikCDVolvik mentioned this pull request Aug 14, 2026
4 tasks
@fbal98

Copy link
Copy Markdown

we need this merged

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8081, which fixes Windows drive-path file links in chat without weakening Markdown URL sanitization. Your work is credited in #8081.

@t3dotggt3dotgg closed this Aug 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M30-99 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@peculiarnewbie@Defmon3@carlosesl1@fbal98@t3dotgg@CDVolvik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix(web): make Windows file links clickable - #6237

Closed
peculiarnewbie wants to merge 4 commits into
pingdotgg:mainfrom
peculiarnewbie:fix/windows-markdown-file-links
Closed

fix(web): make Windows file links clickable#6237
peculiarnewbie wants to merge 4 commits into
pingdotgg:mainfrom
peculiarnewbie:fix/windows-markdown-file-links

Conversation

@peculiarnewbie

@peculiarnewbiepeculiarnewbie commented Aug 11, 2026

Copy link
Copy Markdown

Problem

On Windows, Markdown links with direct drive paths such as [artifact](C:/Users/.../artifact.mp4) rendered as blue text with no usable target. rehype-sanitize interpreted the drive letter as a URL scheme and removed the href before React Markdown's URL transform could normalize it.

Fix

Rewrite only Windows drive-path link destinations to the already-allowed file:/// form while the document is still Markdown AST. The existing URL transform then restores the drive path and sends it through T3 Code's existing file-link renderer. Forward- and backslash drive paths, including encoded and unencoded Unicode segments, are canonicalized to the same lookup key, while unsafe schemes remain subject to the normal sanitizer.

Absolute Windows paths outside the workspace also remain absolute in tooltips and copied paths. The composer's existing mention-chip behavior is unchanged and out of scope.

Before

The label looked like a link, but it had no target and could not be clicked.

Before: Windows drive-path link rendered without a usable target

After

The same destination reaches the existing file-link component; hovering reveals the full path and the link is actionable.

After: Windows drive-path link rendered as an actionable file chip

Verification

  • vp test run apps/web/src/markdown-links.test.ts apps/web/src/markdown-links-rendering.test.tsx apps/web/src/filePathDisplay.test.ts — 46 tests passed
  • vp run --filter @t3tools/web typecheck
  • Targeted vp lint and vp fmt --check for all six changed files
  • Manually verified in the Windows web client; desktop inherits the same web renderer

Implemented with GPT-5.6-Sol in the Codex harness via T3 Code.


Note

Medium Risk
Touches markdown href sanitization and file-link resolution, which are security-adjacent URL handling paths. Scope is narrow and unsafe schemes still go through the existing sanitizer.

Overview
Fixes Windows drive-path markdown links (e.g. C:/... or C:\\...) that rendered as non-clickable text because rehype-sanitize treated the drive letter as a URL scheme and stripped the href.

Adds remarkRewriteWindowsFileLinks, which rewrites only Windows drive destinations to allowed file:/// form in mdast before sanitization. The existing URL transform then restores the drive path for the normal file-link renderer. Also canonicalizes backslash/unicode variants into a shared lookup key via normalizeMarkdownFileLinkHrefKey.

Separately, formatWorkspaceRelativePath now treats Windows drive paths as absolute, so paths outside the workspace stay absolute in tooltips/copied paths instead of getting a workspace label prefix.

Reviewed by Cursor Bugbot for commit 2e03244. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix Windows file path links to be clickable in chat markdown

  • Adds remarkRewriteWindowsFileLinks remark plugin to convert Windows drive-path links (e.g. C:\foo) into file:///C:/... URIs before HTML sanitization, preventing the sanitizer from stripping them.
  • Adds normalizeMarkdownFileLinkHrefKey to produce stable canonical keys for Windows file links regardless of backslashes or percent-encoding, replacing the local helper in ChatMarkdown.tsx.
  • Fixes formatWorkspaceRelativePath in filePathDisplay.ts to avoid prefixing absolute Windows drive paths with the workspace label.

Macroscope summarized 2e03244.

@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8c280e0d-dd44-4bf0-9dab-3c58ad0bb2c3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 11, 2026
@peculiarnewbie
peculiarnewbieforce-pushed the fix/windows-markdown-file-links branch from a1e59dc to f3024d6CompareAugust 11, 2026 22:31
@peculiarnewbie
peculiarnewbie marked this pull request as draft August 11, 2026 22:34
@peculiarnewbie
peculiarnewbie deleted the fix/windows-markdown-file-links branch August 11, 2026 22:37
@macroscopeapp

macroscopeappBot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved 2e03244

Straightforward bug fix making Windows file paths clickable in markdown by converting them to file:// URIs before HTML sanitization. Changes are self-contained with good test coverage, including verification that unsafe schemes remain blocked.

You can customize Macroscope's approvability policy. Learn more.

macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 11, 2026
@peculiarnewbie
peculiarnewbieforce-pushed the fix/windows-markdown-file-links branch from f3024d6 to 6717343CompareAugust 11, 2026 23:17
@github-actionsgithub-actionsBot added size:M 30-99 changed lines (additions + deletions). and removed size:S 10-29 changed lines (additions + deletions). labels Aug 11, 2026
@peculiarnewbie
peculiarnewbie marked this pull request as ready for review August 11, 2026 23:33
Comment threadapps/web/src/markdown-links.ts
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 11, 2026 23:40

Dismissing prior approval to re-evaluate 6717343

macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 12, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 71371ee. Configure here.

Comment threadapps/web/src/markdown-links.ts
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 12, 2026 00:20

Dismissing prior approval to re-evaluate 2e03244

@Defmon3

Copy link
Copy Markdown

Confirmed on Windows. We reproduced drive-letter Windows Markdown links failing to open, then tested the current PR head (2e03244) in our downstream build. The links now resolve and open correctly, including the chat rendering path with line breaks. Thanks for the fix.

@carlosesl1

Copy link
Copy Markdown

I reproduced one remaining gap with the current PR head: valid angle-bracketed destinations containing spaces or balanced parentheses survive the Markdown pipeline, but MARKDOWN_LINK_HREF_PATTERN misses them. That leaves markdownFileLinkMetaByHref empty, so the anchor falls through to the external-link path instead of the existing file-link behavior.

I opened a small, tested follow-up against this branch: peculiarnewbie#1

It keeps the precomputed map as the fast path and falls back to resolving the parsed/normalized href. Regression coverage uses the issue reproduction: <C:/Users/Carlos/My Project/docs/Plan (final).md>. All 43 focused tests, web typecheck, targeted lint, and formatting checks pass.

@CDVolvikCDVolvik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

46/46 across markdown-links.test.ts, markdown-links-rendering.test.tsx and filePathDisplay.test.ts on Linux (Node 24).

I went looking for a mismatch between the rendering test's pipeline and the real one, since markdown-links-rendering.test.tsx builds its own ReactMarkdown rather than rendering ChatMarkdown. There isn't one today. The test uses

protocols: { ...defaultSchema.protocols,href: [...(defaultSchema.protocols?.href??[]),"file"]}urlTransform={(href)=>rewriteMarkdownFileUriHref(href)??defaultUrlTransform(href)}

and ChatMarkdown uses exactly the same protocol list in CHAT_MARKDOWN_SANITIZE_SCHEMA, plus

constmarkdownUrlTransform=useCallback((href: string)=>{returnrewriteMarkdownFileUriHref(href)??defaultUrlTransform(href);},[]);

So the behaviour is faithfully mirrored. Worth flagging anyway, because the mirroring is by hand and there are now three things that have to stay in step: the file protocol entry, remarkRewriteWindowsFileLinks sitting in the remark list, and that urlTransform. Drop any one of them from ChatMarkdown and every test in the new file still passes, because the test supplies its own. CHAT_MARKDOWN_SANITIZE_SCHEMA and markdownUrlTransform are both module-local, so exporting them and importing them into the test would turn this from a parallel implementation into an actual guard, without changing what is asserted.

The still removes unsafe schemes case is the right instinct given this widens what survives sanitization. One more worth adding next to it: a single-letter scheme that is not a drive path. WINDOWS_DRIVE_PATH_PATTERN keys off [A-Za-z]:, and the reason javascript: is safe is that it is many letters, not one. Something like [x](c:/Users/x) versus a genuine one-letter scheme would pin that the widening is limited to drive paths rather than to any short scheme.

isAbsolutePath in filePathDisplay.ts only matches a forward slash after the drive letter:

returnpath.startsWith("/")||/^[A-Za-z]:\//.test(path);

That is fine where it is called, since the value has already been through normalizeMarkdownLinkDestination, but the function name reads general and the next caller will not necessarily normalize first. C:\Users\... returns false from a function called isAbsolutePath. Either accepting both separators or naming it for the normalized input would stop that being a trap later.

@CDVolvikCDVolvik mentioned this pull request Aug 14, 2026
4 tasks
@fbal98

Copy link
Copy Markdown

we need this merged

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8081, which fixes Windows drive-path file links in chat without weakening Markdown URL sanitization. Your work is credited in #8081.

@t3dotggt3dotgg closed this Aug 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M30-99 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@peculiarnewbie@Defmon3@carlosesl1@fbal98@t3dotgg@CDVolvik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(web): make Windows file links clickable - #6237

Closed
peculiarnewbie wants to merge 4 commits into
pingdotgg:mainfrom
peculiarnewbie:fix/windows-markdown-file-links
Closed

fix(web): make Windows file links clickable#6237
peculiarnewbie wants to merge 4 commits into
pingdotgg:mainfrom
peculiarnewbie:fix/windows-markdown-file-links

Conversation

@peculiarnewbie

@peculiarnewbiepeculiarnewbie commented Aug 11, 2026

Copy link
Copy Markdown

Problem

On Windows, Markdown links with direct drive paths such as [artifact](C:/Users/.../artifact.mp4) rendered as blue text with no usable target. rehype-sanitize interpreted the drive letter as a URL scheme and removed the href before React Markdown's URL transform could normalize it.

Fix

Rewrite only Windows drive-path link destinations to the already-allowed file:/// form while the document is still Markdown AST. The existing URL transform then restores the drive path and sends it through T3 Code's existing file-link renderer. Forward- and backslash drive paths, including encoded and unencoded Unicode segments, are canonicalized to the same lookup key, while unsafe schemes remain subject to the normal sanitizer.

Absolute Windows paths outside the workspace also remain absolute in tooltips and copied paths. The composer's existing mention-chip behavior is unchanged and out of scope.

Before

The label looked like a link, but it had no target and could not be clicked.

Before: Windows drive-path link rendered without a usable target

After

The same destination reaches the existing file-link component; hovering reveals the full path and the link is actionable.

After: Windows drive-path link rendered as an actionable file chip

Verification

  • vp test run apps/web/src/markdown-links.test.ts apps/web/src/markdown-links-rendering.test.tsx apps/web/src/filePathDisplay.test.ts — 46 tests passed
  • vp run --filter @t3tools/web typecheck
  • Targeted vp lint and vp fmt --check for all six changed files
  • Manually verified in the Windows web client; desktop inherits the same web renderer

Implemented with GPT-5.6-Sol in the Codex harness via T3 Code.


Note

Medium Risk
Touches markdown href sanitization and file-link resolution, which are security-adjacent URL handling paths. Scope is narrow and unsafe schemes still go through the existing sanitizer.

Overview
Fixes Windows drive-path markdown links (e.g. C:/... or C:\\...) that rendered as non-clickable text because rehype-sanitize treated the drive letter as a URL scheme and stripped the href.

Adds remarkRewriteWindowsFileLinks, which rewrites only Windows drive destinations to allowed file:/// form in mdast before sanitization. The existing URL transform then restores the drive path for the normal file-link renderer. Also canonicalizes backslash/unicode variants into a shared lookup key via normalizeMarkdownFileLinkHrefKey.

Separately, formatWorkspaceRelativePath now treats Windows drive paths as absolute, so paths outside the workspace stay absolute in tooltips/copied paths instead of getting a workspace label prefix.

Reviewed by Cursor Bugbot for commit 2e03244. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix Windows file path links to be clickable in chat markdown

  • Adds remarkRewriteWindowsFileLinks remark plugin to convert Windows drive-path links (e.g. C:\foo) into file:///C:/... URIs before HTML sanitization, preventing the sanitizer from stripping them.
  • Adds normalizeMarkdownFileLinkHrefKey to produce stable canonical keys for Windows file links regardless of backslashes or percent-encoding, replacing the local helper in ChatMarkdown.tsx.
  • Fixes formatWorkspaceRelativePath in filePathDisplay.ts to avoid prefixing absolute Windows drive paths with the workspace label.

Macroscope summarized 2e03244.

@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8c280e0d-dd44-4bf0-9dab-3c58ad0bb2c3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 11, 2026
@peculiarnewbie
peculiarnewbieforce-pushed the fix/windows-markdown-file-links branch from a1e59dc to f3024d6CompareAugust 11, 2026 22:31
@peculiarnewbie
peculiarnewbie marked this pull request as draft August 11, 2026 22:34
@peculiarnewbie
peculiarnewbie deleted the fix/windows-markdown-file-links branch August 11, 2026 22:37
@macroscopeapp

macroscopeappBot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved 2e03244

Straightforward bug fix making Windows file paths clickable in markdown by converting them to file:// URIs before HTML sanitization. Changes are self-contained with good test coverage, including verification that unsafe schemes remain blocked.

You can customize Macroscope's approvability policy. Learn more.

macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 11, 2026
@peculiarnewbie
peculiarnewbieforce-pushed the fix/windows-markdown-file-links branch from f3024d6 to 6717343CompareAugust 11, 2026 23:17
@github-actionsgithub-actionsBot added size:M 30-99 changed lines (additions + deletions). and removed size:S 10-29 changed lines (additions + deletions). labels Aug 11, 2026
@peculiarnewbie
peculiarnewbie marked this pull request as ready for review August 11, 2026 23:33
Comment threadapps/web/src/markdown-links.ts
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 11, 2026 23:40

Dismissing prior approval to re-evaluate 6717343

macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 12, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 71371ee. Configure here.

Comment threadapps/web/src/markdown-links.ts
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 12, 2026 00:20

Dismissing prior approval to re-evaluate 2e03244

@Defmon3

Copy link
Copy Markdown

Confirmed on Windows. We reproduced drive-letter Windows Markdown links failing to open, then tested the current PR head (2e03244) in our downstream build. The links now resolve and open correctly, including the chat rendering path with line breaks. Thanks for the fix.

@carlosesl1

Copy link
Copy Markdown

I reproduced one remaining gap with the current PR head: valid angle-bracketed destinations containing spaces or balanced parentheses survive the Markdown pipeline, but MARKDOWN_LINK_HREF_PATTERN misses them. That leaves markdownFileLinkMetaByHref empty, so the anchor falls through to the external-link path instead of the existing file-link behavior.

I opened a small, tested follow-up against this branch: peculiarnewbie#1

It keeps the precomputed map as the fast path and falls back to resolving the parsed/normalized href. Regression coverage uses the issue reproduction: <C:/Users/Carlos/My Project/docs/Plan (final).md>. All 43 focused tests, web typecheck, targeted lint, and formatting checks pass.

@CDVolvikCDVolvik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

46/46 across markdown-links.test.ts, markdown-links-rendering.test.tsx and filePathDisplay.test.ts on Linux (Node 24).

I went looking for a mismatch between the rendering test's pipeline and the real one, since markdown-links-rendering.test.tsx builds its own ReactMarkdown rather than rendering ChatMarkdown. There isn't one today. The test uses

protocols: { ...defaultSchema.protocols,href: [...(defaultSchema.protocols?.href??[]),"file"]}urlTransform={(href)=>rewriteMarkdownFileUriHref(href)??defaultUrlTransform(href)}

and ChatMarkdown uses exactly the same protocol list in CHAT_MARKDOWN_SANITIZE_SCHEMA, plus

constmarkdownUrlTransform=useCallback((href: string)=>{returnrewriteMarkdownFileUriHref(href)??defaultUrlTransform(href);},[]);

So the behaviour is faithfully mirrored. Worth flagging anyway, because the mirroring is by hand and there are now three things that have to stay in step: the file protocol entry, remarkRewriteWindowsFileLinks sitting in the remark list, and that urlTransform. Drop any one of them from ChatMarkdown and every test in the new file still passes, because the test supplies its own. CHAT_MARKDOWN_SANITIZE_SCHEMA and markdownUrlTransform are both module-local, so exporting them and importing them into the test would turn this from a parallel implementation into an actual guard, without changing what is asserted.

The still removes unsafe schemes case is the right instinct given this widens what survives sanitization. One more worth adding next to it: a single-letter scheme that is not a drive path. WINDOWS_DRIVE_PATH_PATTERN keys off [A-Za-z]:, and the reason javascript: is safe is that it is many letters, not one. Something like [x](c:/Users/x) versus a genuine one-letter scheme would pin that the widening is limited to drive paths rather than to any short scheme.

isAbsolutePath in filePathDisplay.ts only matches a forward slash after the drive letter:

returnpath.startsWith("/")||/^[A-Za-z]:\//.test(path);

That is fine where it is called, since the value has already been through normalizeMarkdownLinkDestination, but the function name reads general and the next caller will not necessarily normalize first. C:\Users\... returns false from a function called isAbsolutePath. Either accepting both separators or naming it for the normalized input would stop that being a trap later.

@CDVolvikCDVolvik mentioned this pull request Aug 14, 2026
4 tasks
@fbal98

Copy link
Copy Markdown

we need this merged

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8081, which fixes Windows drive-path file links in chat without weakening Markdown URL sanitization. Your work is credited in #8081.

@t3dotggt3dotgg closed this Aug 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M30-99 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@peculiarnewbie@Defmon3@carlosesl1@fbal98@t3dotgg@CDVolvik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(web): make Windows file links clickable - #6237

Closed
peculiarnewbie wants to merge 4 commits into
pingdotgg:mainfrom
peculiarnewbie:fix/windows-markdown-file-links
Closed

fix(web): make Windows file links clickable#6237
peculiarnewbie wants to merge 4 commits into
pingdotgg:mainfrom
peculiarnewbie:fix/windows-markdown-file-links

Conversation

@peculiarnewbie

@peculiarnewbiepeculiarnewbie commented Aug 11, 2026

Copy link
Copy Markdown

Problem

On Windows, Markdown links with direct drive paths such as [artifact](C:/Users/.../artifact.mp4) rendered as blue text with no usable target. rehype-sanitize interpreted the drive letter as a URL scheme and removed the href before React Markdown's URL transform could normalize it.

Fix

Rewrite only Windows drive-path link destinations to the already-allowed file:/// form while the document is still Markdown AST. The existing URL transform then restores the drive path and sends it through T3 Code's existing file-link renderer. Forward- and backslash drive paths, including encoded and unencoded Unicode segments, are canonicalized to the same lookup key, while unsafe schemes remain subject to the normal sanitizer.

Absolute Windows paths outside the workspace also remain absolute in tooltips and copied paths. The composer's existing mention-chip behavior is unchanged and out of scope.

Before

The label looked like a link, but it had no target and could not be clicked.

Before: Windows drive-path link rendered without a usable target

After

The same destination reaches the existing file-link component; hovering reveals the full path and the link is actionable.

After: Windows drive-path link rendered as an actionable file chip

Verification

  • vp test run apps/web/src/markdown-links.test.ts apps/web/src/markdown-links-rendering.test.tsx apps/web/src/filePathDisplay.test.ts — 46 tests passed
  • vp run --filter @t3tools/web typecheck
  • Targeted vp lint and vp fmt --check for all six changed files
  • Manually verified in the Windows web client; desktop inherits the same web renderer

Implemented with GPT-5.6-Sol in the Codex harness via T3 Code.


Note

Medium Risk
Touches markdown href sanitization and file-link resolution, which are security-adjacent URL handling paths. Scope is narrow and unsafe schemes still go through the existing sanitizer.

Overview
Fixes Windows drive-path markdown links (e.g. C:/... or C:\\...) that rendered as non-clickable text because rehype-sanitize treated the drive letter as a URL scheme and stripped the href.

Adds remarkRewriteWindowsFileLinks, which rewrites only Windows drive destinations to allowed file:/// form in mdast before sanitization. The existing URL transform then restores the drive path for the normal file-link renderer. Also canonicalizes backslash/unicode variants into a shared lookup key via normalizeMarkdownFileLinkHrefKey.

Separately, formatWorkspaceRelativePath now treats Windows drive paths as absolute, so paths outside the workspace stay absolute in tooltips/copied paths instead of getting a workspace label prefix.

Reviewed by Cursor Bugbot for commit 2e03244. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix Windows file path links to be clickable in chat markdown

  • Adds remarkRewriteWindowsFileLinks remark plugin to convert Windows drive-path links (e.g. C:\foo) into file:///C:/... URIs before HTML sanitization, preventing the sanitizer from stripping them.
  • Adds normalizeMarkdownFileLinkHrefKey to produce stable canonical keys for Windows file links regardless of backslashes or percent-encoding, replacing the local helper in ChatMarkdown.tsx.
  • Fixes formatWorkspaceRelativePath in filePathDisplay.ts to avoid prefixing absolute Windows drive paths with the workspace label.

Macroscope summarized 2e03244.

@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8c280e0d-dd44-4bf0-9dab-3c58ad0bb2c3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 11, 2026
@peculiarnewbie
peculiarnewbieforce-pushed the fix/windows-markdown-file-links branch from a1e59dc to f3024d6CompareAugust 11, 2026 22:31
@peculiarnewbie
peculiarnewbie marked this pull request as draft August 11, 2026 22:34
@peculiarnewbie
peculiarnewbie deleted the fix/windows-markdown-file-links branch August 11, 2026 22:37
@macroscopeapp

macroscopeappBot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved 2e03244

Straightforward bug fix making Windows file paths clickable in markdown by converting them to file:// URIs before HTML sanitization. Changes are self-contained with good test coverage, including verification that unsafe schemes remain blocked.

You can customize Macroscope's approvability policy. Learn more.

macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 11, 2026
@peculiarnewbie
peculiarnewbieforce-pushed the fix/windows-markdown-file-links branch from f3024d6 to 6717343CompareAugust 11, 2026 23:17
@github-actionsgithub-actionsBot added size:M 30-99 changed lines (additions + deletions). and removed size:S 10-29 changed lines (additions + deletions). labels Aug 11, 2026
@peculiarnewbie
peculiarnewbie marked this pull request as ready for review August 11, 2026 23:33
Comment threadapps/web/src/markdown-links.ts
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 11, 2026 23:40

Dismissing prior approval to re-evaluate 6717343

macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 12, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 71371ee. Configure here.

Comment threadapps/web/src/markdown-links.ts
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 12, 2026 00:20

Dismissing prior approval to re-evaluate 2e03244

@Defmon3

Copy link
Copy Markdown

Confirmed on Windows. We reproduced drive-letter Windows Markdown links failing to open, then tested the current PR head (2e03244) in our downstream build. The links now resolve and open correctly, including the chat rendering path with line breaks. Thanks for the fix.

@carlosesl1

Copy link
Copy Markdown

I reproduced one remaining gap with the current PR head: valid angle-bracketed destinations containing spaces or balanced parentheses survive the Markdown pipeline, but MARKDOWN_LINK_HREF_PATTERN misses them. That leaves markdownFileLinkMetaByHref empty, so the anchor falls through to the external-link path instead of the existing file-link behavior.

I opened a small, tested follow-up against this branch: peculiarnewbie#1

It keeps the precomputed map as the fast path and falls back to resolving the parsed/normalized href. Regression coverage uses the issue reproduction: <C:/Users/Carlos/My Project/docs/Plan (final).md>. All 43 focused tests, web typecheck, targeted lint, and formatting checks pass.

@CDVolvikCDVolvik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

46/46 across markdown-links.test.ts, markdown-links-rendering.test.tsx and filePathDisplay.test.ts on Linux (Node 24).

I went looking for a mismatch between the rendering test's pipeline and the real one, since markdown-links-rendering.test.tsx builds its own ReactMarkdown rather than rendering ChatMarkdown. There isn't one today. The test uses

protocols: { ...defaultSchema.protocols,href: [...(defaultSchema.protocols?.href??[]),"file"]}urlTransform={(href)=>rewriteMarkdownFileUriHref(href)??defaultUrlTransform(href)}

and ChatMarkdown uses exactly the same protocol list in CHAT_MARKDOWN_SANITIZE_SCHEMA, plus

constmarkdownUrlTransform=useCallback((href: string)=>{returnrewriteMarkdownFileUriHref(href)??defaultUrlTransform(href);},[]);

So the behaviour is faithfully mirrored. Worth flagging anyway, because the mirroring is by hand and there are now three things that have to stay in step: the file protocol entry, remarkRewriteWindowsFileLinks sitting in the remark list, and that urlTransform. Drop any one of them from ChatMarkdown and every test in the new file still passes, because the test supplies its own. CHAT_MARKDOWN_SANITIZE_SCHEMA and markdownUrlTransform are both module-local, so exporting them and importing them into the test would turn this from a parallel implementation into an actual guard, without changing what is asserted.

The still removes unsafe schemes case is the right instinct given this widens what survives sanitization. One more worth adding next to it: a single-letter scheme that is not a drive path. WINDOWS_DRIVE_PATH_PATTERN keys off [A-Za-z]:, and the reason javascript: is safe is that it is many letters, not one. Something like [x](c:/Users/x) versus a genuine one-letter scheme would pin that the widening is limited to drive paths rather than to any short scheme.

isAbsolutePath in filePathDisplay.ts only matches a forward slash after the drive letter:

returnpath.startsWith("/")||/^[A-Za-z]:\//.test(path);

That is fine where it is called, since the value has already been through normalizeMarkdownLinkDestination, but the function name reads general and the next caller will not necessarily normalize first. C:\Users\... returns false from a function called isAbsolutePath. Either accepting both separators or naming it for the normalized input would stop that being a trap later.

@CDVolvikCDVolvik mentioned this pull request Aug 14, 2026
4 tasks
@fbal98

Copy link
Copy Markdown

we need this merged

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8081, which fixes Windows drive-path file links in chat without weakening Markdown URL sanitization. Your work is credited in #8081.

@t3dotggt3dotgg closed this Aug 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M30-99 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@peculiarnewbie@Defmon3@carlosesl1@fbal98@t3dotgg@CDVolvik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix(web): make Windows file links clickable - #6237

Closed
peculiarnewbie wants to merge 4 commits into
pingdotgg:mainfrom
peculiarnewbie:fix/windows-markdown-file-links
Closed

fix(web): make Windows file links clickable#6237
peculiarnewbie wants to merge 4 commits into
pingdotgg:mainfrom
peculiarnewbie:fix/windows-markdown-file-links

Conversation

@peculiarnewbie

@peculiarnewbiepeculiarnewbie commented Aug 11, 2026

Copy link
Copy Markdown

Problem

On Windows, Markdown links with direct drive paths such as [artifact](C:/Users/.../artifact.mp4) rendered as blue text with no usable target. rehype-sanitize interpreted the drive letter as a URL scheme and removed the href before React Markdown's URL transform could normalize it.

Fix

Rewrite only Windows drive-path link destinations to the already-allowed file:/// form while the document is still Markdown AST. The existing URL transform then restores the drive path and sends it through T3 Code's existing file-link renderer. Forward- and backslash drive paths, including encoded and unencoded Unicode segments, are canonicalized to the same lookup key, while unsafe schemes remain subject to the normal sanitizer.

Absolute Windows paths outside the workspace also remain absolute in tooltips and copied paths. The composer's existing mention-chip behavior is unchanged and out of scope.

Before

The label looked like a link, but it had no target and could not be clicked.

Before: Windows drive-path link rendered without a usable target

After

The same destination reaches the existing file-link component; hovering reveals the full path and the link is actionable.

After: Windows drive-path link rendered as an actionable file chip

Verification

  • vp test run apps/web/src/markdown-links.test.ts apps/web/src/markdown-links-rendering.test.tsx apps/web/src/filePathDisplay.test.ts — 46 tests passed
  • vp run --filter @t3tools/web typecheck
  • Targeted vp lint and vp fmt --check for all six changed files
  • Manually verified in the Windows web client; desktop inherits the same web renderer

Implemented with GPT-5.6-Sol in the Codex harness via T3 Code.


Note

Medium Risk
Touches markdown href sanitization and file-link resolution, which are security-adjacent URL handling paths. Scope is narrow and unsafe schemes still go through the existing sanitizer.

Overview
Fixes Windows drive-path markdown links (e.g. C:/... or C:\\...) that rendered as non-clickable text because rehype-sanitize treated the drive letter as a URL scheme and stripped the href.

Adds remarkRewriteWindowsFileLinks, which rewrites only Windows drive destinations to allowed file:/// form in mdast before sanitization. The existing URL transform then restores the drive path for the normal file-link renderer. Also canonicalizes backslash/unicode variants into a shared lookup key via normalizeMarkdownFileLinkHrefKey.

Separately, formatWorkspaceRelativePath now treats Windows drive paths as absolute, so paths outside the workspace stay absolute in tooltips/copied paths instead of getting a workspace label prefix.

Reviewed by Cursor Bugbot for commit 2e03244. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix Windows file path links to be clickable in chat markdown

  • Adds remarkRewriteWindowsFileLinks remark plugin to convert Windows drive-path links (e.g. C:\foo) into file:///C:/... URIs before HTML sanitization, preventing the sanitizer from stripping them.
  • Adds normalizeMarkdownFileLinkHrefKey to produce stable canonical keys for Windows file links regardless of backslashes or percent-encoding, replacing the local helper in ChatMarkdown.tsx.
  • Fixes formatWorkspaceRelativePath in filePathDisplay.ts to avoid prefixing absolute Windows drive paths with the workspace label.

Macroscope summarized 2e03244.

@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8c280e0d-dd44-4bf0-9dab-3c58ad0bb2c3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 11, 2026
@peculiarnewbie
peculiarnewbieforce-pushed the fix/windows-markdown-file-links branch from a1e59dc to f3024d6CompareAugust 11, 2026 22:31
@peculiarnewbie
peculiarnewbie marked this pull request as draft August 11, 2026 22:34
@peculiarnewbie
peculiarnewbie deleted the fix/windows-markdown-file-links branch August 11, 2026 22:37
@macroscopeapp

macroscopeappBot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved 2e03244

Straightforward bug fix making Windows file paths clickable in markdown by converting them to file:// URIs before HTML sanitization. Changes are self-contained with good test coverage, including verification that unsafe schemes remain blocked.

You can customize Macroscope's approvability policy. Learn more.

macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 11, 2026
@peculiarnewbie
peculiarnewbieforce-pushed the fix/windows-markdown-file-links branch from f3024d6 to 6717343CompareAugust 11, 2026 23:17
@github-actionsgithub-actionsBot added size:M 30-99 changed lines (additions + deletions). and removed size:S 10-29 changed lines (additions + deletions). labels Aug 11, 2026
@peculiarnewbie
peculiarnewbie marked this pull request as ready for review August 11, 2026 23:33
Comment threadapps/web/src/markdown-links.ts
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 11, 2026 23:40

Dismissing prior approval to re-evaluate 6717343

macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 12, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 71371ee. Configure here.

Comment threadapps/web/src/markdown-links.ts
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 12, 2026 00:20

Dismissing prior approval to re-evaluate 2e03244

@Defmon3

Copy link
Copy Markdown

Confirmed on Windows. We reproduced drive-letter Windows Markdown links failing to open, then tested the current PR head (2e03244) in our downstream build. The links now resolve and open correctly, including the chat rendering path with line breaks. Thanks for the fix.

@carlosesl1

Copy link
Copy Markdown

I reproduced one remaining gap with the current PR head: valid angle-bracketed destinations containing spaces or balanced parentheses survive the Markdown pipeline, but MARKDOWN_LINK_HREF_PATTERN misses them. That leaves markdownFileLinkMetaByHref empty, so the anchor falls through to the external-link path instead of the existing file-link behavior.

I opened a small, tested follow-up against this branch: peculiarnewbie#1

It keeps the precomputed map as the fast path and falls back to resolving the parsed/normalized href. Regression coverage uses the issue reproduction: <C:/Users/Carlos/My Project/docs/Plan (final).md>. All 43 focused tests, web typecheck, targeted lint, and formatting checks pass.

@CDVolvikCDVolvik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

46/46 across markdown-links.test.ts, markdown-links-rendering.test.tsx and filePathDisplay.test.ts on Linux (Node 24).

I went looking for a mismatch between the rendering test's pipeline and the real one, since markdown-links-rendering.test.tsx builds its own ReactMarkdown rather than rendering ChatMarkdown. There isn't one today. The test uses

protocols: { ...defaultSchema.protocols,href: [...(defaultSchema.protocols?.href??[]),"file"]}urlTransform={(href)=>rewriteMarkdownFileUriHref(href)??defaultUrlTransform(href)}

and ChatMarkdown uses exactly the same protocol list in CHAT_MARKDOWN_SANITIZE_SCHEMA, plus

constmarkdownUrlTransform=useCallback((href: string)=>{returnrewriteMarkdownFileUriHref(href)??defaultUrlTransform(href);},[]);

So the behaviour is faithfully mirrored. Worth flagging anyway, because the mirroring is by hand and there are now three things that have to stay in step: the file protocol entry, remarkRewriteWindowsFileLinks sitting in the remark list, and that urlTransform. Drop any one of them from ChatMarkdown and every test in the new file still passes, because the test supplies its own. CHAT_MARKDOWN_SANITIZE_SCHEMA and markdownUrlTransform are both module-local, so exporting them and importing them into the test would turn this from a parallel implementation into an actual guard, without changing what is asserted.

The still removes unsafe schemes case is the right instinct given this widens what survives sanitization. One more worth adding next to it: a single-letter scheme that is not a drive path. WINDOWS_DRIVE_PATH_PATTERN keys off [A-Za-z]:, and the reason javascript: is safe is that it is many letters, not one. Something like [x](c:/Users/x) versus a genuine one-letter scheme would pin that the widening is limited to drive paths rather than to any short scheme.

isAbsolutePath in filePathDisplay.ts only matches a forward slash after the drive letter:

returnpath.startsWith("/")||/^[A-Za-z]:\//.test(path);

That is fine where it is called, since the value has already been through normalizeMarkdownLinkDestination, but the function name reads general and the next caller will not necessarily normalize first. C:\Users\... returns false from a function called isAbsolutePath. Either accepting both separators or naming it for the normalized input would stop that being a trap later.

@CDVolvikCDVolvik mentioned this pull request Aug 14, 2026
4 tasks
@fbal98

Copy link
Copy Markdown

we need this merged

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8081, which fixes Windows drive-path file links in chat without weakening Markdown URL sanitization. Your work is credited in #8081.

@t3dotggt3dotgg closed this Aug 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M30-99 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@peculiarnewbie@Defmon3@carlosesl1@fbal98@t3dotgg@CDVolvik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(web): make Windows file links clickable - #6237

Closed
peculiarnewbie wants to merge 4 commits into
pingdotgg:mainfrom
peculiarnewbie:fix/windows-markdown-file-links
Closed

fix(web): make Windows file links clickable#6237
peculiarnewbie wants to merge 4 commits into
pingdotgg:mainfrom
peculiarnewbie:fix/windows-markdown-file-links

Conversation

@peculiarnewbie

@peculiarnewbiepeculiarnewbie commented Aug 11, 2026

Copy link
Copy Markdown

Problem

On Windows, Markdown links with direct drive paths such as [artifact](C:/Users/.../artifact.mp4) rendered as blue text with no usable target. rehype-sanitize interpreted the drive letter as a URL scheme and removed the href before React Markdown's URL transform could normalize it.

Fix

Rewrite only Windows drive-path link destinations to the already-allowed file:/// form while the document is still Markdown AST. The existing URL transform then restores the drive path and sends it through T3 Code's existing file-link renderer. Forward- and backslash drive paths, including encoded and unencoded Unicode segments, are canonicalized to the same lookup key, while unsafe schemes remain subject to the normal sanitizer.

Absolute Windows paths outside the workspace also remain absolute in tooltips and copied paths. The composer's existing mention-chip behavior is unchanged and out of scope.

Before

The label looked like a link, but it had no target and could not be clicked.

Before: Windows drive-path link rendered without a usable target

After

The same destination reaches the existing file-link component; hovering reveals the full path and the link is actionable.

After: Windows drive-path link rendered as an actionable file chip

Verification

  • vp test run apps/web/src/markdown-links.test.ts apps/web/src/markdown-links-rendering.test.tsx apps/web/src/filePathDisplay.test.ts — 46 tests passed
  • vp run --filter @t3tools/web typecheck
  • Targeted vp lint and vp fmt --check for all six changed files
  • Manually verified in the Windows web client; desktop inherits the same web renderer

Implemented with GPT-5.6-Sol in the Codex harness via T3 Code.


Note

Medium Risk
Touches markdown href sanitization and file-link resolution, which are security-adjacent URL handling paths. Scope is narrow and unsafe schemes still go through the existing sanitizer.

Overview
Fixes Windows drive-path markdown links (e.g. C:/... or C:\\...) that rendered as non-clickable text because rehype-sanitize treated the drive letter as a URL scheme and stripped the href.

Adds remarkRewriteWindowsFileLinks, which rewrites only Windows drive destinations to allowed file:/// form in mdast before sanitization. The existing URL transform then restores the drive path for the normal file-link renderer. Also canonicalizes backslash/unicode variants into a shared lookup key via normalizeMarkdownFileLinkHrefKey.

Separately, formatWorkspaceRelativePath now treats Windows drive paths as absolute, so paths outside the workspace stay absolute in tooltips/copied paths instead of getting a workspace label prefix.

Reviewed by Cursor Bugbot for commit 2e03244. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix Windows file path links to be clickable in chat markdown

  • Adds remarkRewriteWindowsFileLinks remark plugin to convert Windows drive-path links (e.g. C:\foo) into file:///C:/... URIs before HTML sanitization, preventing the sanitizer from stripping them.
  • Adds normalizeMarkdownFileLinkHrefKey to produce stable canonical keys for Windows file links regardless of backslashes or percent-encoding, replacing the local helper in ChatMarkdown.tsx.
  • Fixes formatWorkspaceRelativePath in filePathDisplay.ts to avoid prefixing absolute Windows drive paths with the workspace label.

Macroscope summarized 2e03244.

@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8c280e0d-dd44-4bf0-9dab-3c58ad0bb2c3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 11, 2026
@peculiarnewbie
peculiarnewbieforce-pushed the fix/windows-markdown-file-links branch from a1e59dc to f3024d6CompareAugust 11, 2026 22:31
@peculiarnewbie
peculiarnewbie marked this pull request as draft August 11, 2026 22:34
@peculiarnewbie
peculiarnewbie deleted the fix/windows-markdown-file-links branch August 11, 2026 22:37
@macroscopeapp

macroscopeappBot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved 2e03244

Straightforward bug fix making Windows file paths clickable in markdown by converting them to file:// URIs before HTML sanitization. Changes are self-contained with good test coverage, including verification that unsafe schemes remain blocked.

You can customize Macroscope's approvability policy. Learn more.

macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 11, 2026
@peculiarnewbie
peculiarnewbieforce-pushed the fix/windows-markdown-file-links branch from f3024d6 to 6717343CompareAugust 11, 2026 23:17
@github-actionsgithub-actionsBot added size:M 30-99 changed lines (additions + deletions). and removed size:S 10-29 changed lines (additions + deletions). labels Aug 11, 2026
@peculiarnewbie
peculiarnewbie marked this pull request as ready for review August 11, 2026 23:33
Comment threadapps/web/src/markdown-links.ts
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 11, 2026 23:40

Dismissing prior approval to re-evaluate 6717343

macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 12, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 71371ee. Configure here.

Comment threadapps/web/src/markdown-links.ts
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 12, 2026 00:20

Dismissing prior approval to re-evaluate 2e03244

@Defmon3

Copy link
Copy Markdown

Confirmed on Windows. We reproduced drive-letter Windows Markdown links failing to open, then tested the current PR head (2e03244) in our downstream build. The links now resolve and open correctly, including the chat rendering path with line breaks. Thanks for the fix.

@carlosesl1

Copy link
Copy Markdown

I reproduced one remaining gap with the current PR head: valid angle-bracketed destinations containing spaces or balanced parentheses survive the Markdown pipeline, but MARKDOWN_LINK_HREF_PATTERN misses them. That leaves markdownFileLinkMetaByHref empty, so the anchor falls through to the external-link path instead of the existing file-link behavior.

I opened a small, tested follow-up against this branch: peculiarnewbie#1

It keeps the precomputed map as the fast path and falls back to resolving the parsed/normalized href. Regression coverage uses the issue reproduction: <C:/Users/Carlos/My Project/docs/Plan (final).md>. All 43 focused tests, web typecheck, targeted lint, and formatting checks pass.

@CDVolvikCDVolvik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

46/46 across markdown-links.test.ts, markdown-links-rendering.test.tsx and filePathDisplay.test.ts on Linux (Node 24).

I went looking for a mismatch between the rendering test's pipeline and the real one, since markdown-links-rendering.test.tsx builds its own ReactMarkdown rather than rendering ChatMarkdown. There isn't one today. The test uses

protocols: { ...defaultSchema.protocols,href: [...(defaultSchema.protocols?.href??[]),"file"]}urlTransform={(href)=>rewriteMarkdownFileUriHref(href)??defaultUrlTransform(href)}

and ChatMarkdown uses exactly the same protocol list in CHAT_MARKDOWN_SANITIZE_SCHEMA, plus

constmarkdownUrlTransform=useCallback((href: string)=>{returnrewriteMarkdownFileUriHref(href)??defaultUrlTransform(href);},[]);

So the behaviour is faithfully mirrored. Worth flagging anyway, because the mirroring is by hand and there are now three things that have to stay in step: the file protocol entry, remarkRewriteWindowsFileLinks sitting in the remark list, and that urlTransform. Drop any one of them from ChatMarkdown and every test in the new file still passes, because the test supplies its own. CHAT_MARKDOWN_SANITIZE_SCHEMA and markdownUrlTransform are both module-local, so exporting them and importing them into the test would turn this from a parallel implementation into an actual guard, without changing what is asserted.

The still removes unsafe schemes case is the right instinct given this widens what survives sanitization. One more worth adding next to it: a single-letter scheme that is not a drive path. WINDOWS_DRIVE_PATH_PATTERN keys off [A-Za-z]:, and the reason javascript: is safe is that it is many letters, not one. Something like [x](c:/Users/x) versus a genuine one-letter scheme would pin that the widening is limited to drive paths rather than to any short scheme.

isAbsolutePath in filePathDisplay.ts only matches a forward slash after the drive letter:

returnpath.startsWith("/")||/^[A-Za-z]:\//.test(path);

That is fine where it is called, since the value has already been through normalizeMarkdownLinkDestination, but the function name reads general and the next caller will not necessarily normalize first. C:\Users\... returns false from a function called isAbsolutePath. Either accepting both separators or naming it for the normalized input would stop that being a trap later.

@CDVolvikCDVolvik mentioned this pull request Aug 14, 2026
4 tasks
@fbal98

Copy link
Copy Markdown

we need this merged

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8081, which fixes Windows drive-path file links in chat without weakening Markdown URL sanitization. Your work is credited in #8081.

@t3dotggt3dotgg closed this Aug 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M30-99 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@peculiarnewbie@Defmon3@carlosesl1@fbal98@t3dotgg@CDVolvik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(web): make Windows file links clickable - #6237

Closed
peculiarnewbie wants to merge 4 commits into
pingdotgg:mainfrom
peculiarnewbie:fix/windows-markdown-file-links
Closed

fix(web): make Windows file links clickable#6237
peculiarnewbie wants to merge 4 commits into
pingdotgg:mainfrom
peculiarnewbie:fix/windows-markdown-file-links

Conversation

@peculiarnewbie

@peculiarnewbiepeculiarnewbie commented Aug 11, 2026

Copy link
Copy Markdown

Problem

On Windows, Markdown links with direct drive paths such as [artifact](C:/Users/.../artifact.mp4) rendered as blue text with no usable target. rehype-sanitize interpreted the drive letter as a URL scheme and removed the href before React Markdown's URL transform could normalize it.

Fix

Rewrite only Windows drive-path link destinations to the already-allowed file:/// form while the document is still Markdown AST. The existing URL transform then restores the drive path and sends it through T3 Code's existing file-link renderer. Forward- and backslash drive paths, including encoded and unencoded Unicode segments, are canonicalized to the same lookup key, while unsafe schemes remain subject to the normal sanitizer.

Absolute Windows paths outside the workspace also remain absolute in tooltips and copied paths. The composer's existing mention-chip behavior is unchanged and out of scope.

Before

The label looked like a link, but it had no target and could not be clicked.

Before: Windows drive-path link rendered without a usable target

After

The same destination reaches the existing file-link component; hovering reveals the full path and the link is actionable.

After: Windows drive-path link rendered as an actionable file chip

Verification

  • vp test run apps/web/src/markdown-links.test.ts apps/web/src/markdown-links-rendering.test.tsx apps/web/src/filePathDisplay.test.ts — 46 tests passed
  • vp run --filter @t3tools/web typecheck
  • Targeted vp lint and vp fmt --check for all six changed files
  • Manually verified in the Windows web client; desktop inherits the same web renderer

Implemented with GPT-5.6-Sol in the Codex harness via T3 Code.


Note

Medium Risk
Touches markdown href sanitization and file-link resolution, which are security-adjacent URL handling paths. Scope is narrow and unsafe schemes still go through the existing sanitizer.

Overview
Fixes Windows drive-path markdown links (e.g. C:/... or C:\\...) that rendered as non-clickable text because rehype-sanitize treated the drive letter as a URL scheme and stripped the href.

Adds remarkRewriteWindowsFileLinks, which rewrites only Windows drive destinations to allowed file:/// form in mdast before sanitization. The existing URL transform then restores the drive path for the normal file-link renderer. Also canonicalizes backslash/unicode variants into a shared lookup key via normalizeMarkdownFileLinkHrefKey.

Separately, formatWorkspaceRelativePath now treats Windows drive paths as absolute, so paths outside the workspace stay absolute in tooltips/copied paths instead of getting a workspace label prefix.

Reviewed by Cursor Bugbot for commit 2e03244. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix Windows file path links to be clickable in chat markdown

  • Adds remarkRewriteWindowsFileLinks remark plugin to convert Windows drive-path links (e.g. C:\foo) into file:///C:/... URIs before HTML sanitization, preventing the sanitizer from stripping them.
  • Adds normalizeMarkdownFileLinkHrefKey to produce stable canonical keys for Windows file links regardless of backslashes or percent-encoding, replacing the local helper in ChatMarkdown.tsx.
  • Fixes formatWorkspaceRelativePath in filePathDisplay.ts to avoid prefixing absolute Windows drive paths with the workspace label.

Macroscope summarized 2e03244.

@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8c280e0d-dd44-4bf0-9dab-3c58ad0bb2c3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 11, 2026
@peculiarnewbie
peculiarnewbieforce-pushed the fix/windows-markdown-file-links branch from a1e59dc to f3024d6CompareAugust 11, 2026 22:31
@peculiarnewbie
peculiarnewbie marked this pull request as draft August 11, 2026 22:34
@peculiarnewbie
peculiarnewbie deleted the fix/windows-markdown-file-links branch August 11, 2026 22:37
@macroscopeapp

macroscopeappBot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved 2e03244

Straightforward bug fix making Windows file paths clickable in markdown by converting them to file:// URIs before HTML sanitization. Changes are self-contained with good test coverage, including verification that unsafe schemes remain blocked.

You can customize Macroscope's approvability policy. Learn more.

macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 11, 2026
@peculiarnewbie
peculiarnewbieforce-pushed the fix/windows-markdown-file-links branch from f3024d6 to 6717343CompareAugust 11, 2026 23:17
@github-actionsgithub-actionsBot added size:M 30-99 changed lines (additions + deletions). and removed size:S 10-29 changed lines (additions + deletions). labels Aug 11, 2026
@peculiarnewbie
peculiarnewbie marked this pull request as ready for review August 11, 2026 23:33
Comment threadapps/web/src/markdown-links.ts
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 11, 2026 23:40

Dismissing prior approval to re-evaluate 6717343

macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 12, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 71371ee. Configure here.

Comment threadapps/web/src/markdown-links.ts
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 12, 2026 00:20

Dismissing prior approval to re-evaluate 2e03244

@Defmon3

Copy link
Copy Markdown

Confirmed on Windows. We reproduced drive-letter Windows Markdown links failing to open, then tested the current PR head (2e03244) in our downstream build. The links now resolve and open correctly, including the chat rendering path with line breaks. Thanks for the fix.

@carlosesl1

Copy link
Copy Markdown

I reproduced one remaining gap with the current PR head: valid angle-bracketed destinations containing spaces or balanced parentheses survive the Markdown pipeline, but MARKDOWN_LINK_HREF_PATTERN misses them. That leaves markdownFileLinkMetaByHref empty, so the anchor falls through to the external-link path instead of the existing file-link behavior.

I opened a small, tested follow-up against this branch: peculiarnewbie#1

It keeps the precomputed map as the fast path and falls back to resolving the parsed/normalized href. Regression coverage uses the issue reproduction: <C:/Users/Carlos/My Project/docs/Plan (final).md>. All 43 focused tests, web typecheck, targeted lint, and formatting checks pass.

@CDVolvikCDVolvik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

46/46 across markdown-links.test.ts, markdown-links-rendering.test.tsx and filePathDisplay.test.ts on Linux (Node 24).

I went looking for a mismatch between the rendering test's pipeline and the real one, since markdown-links-rendering.test.tsx builds its own ReactMarkdown rather than rendering ChatMarkdown. There isn't one today. The test uses

protocols: { ...defaultSchema.protocols,href: [...(defaultSchema.protocols?.href??[]),"file"]}urlTransform={(href)=>rewriteMarkdownFileUriHref(href)??defaultUrlTransform(href)}

and ChatMarkdown uses exactly the same protocol list in CHAT_MARKDOWN_SANITIZE_SCHEMA, plus

constmarkdownUrlTransform=useCallback((href: string)=>{returnrewriteMarkdownFileUriHref(href)??defaultUrlTransform(href);},[]);

So the behaviour is faithfully mirrored. Worth flagging anyway, because the mirroring is by hand and there are now three things that have to stay in step: the file protocol entry, remarkRewriteWindowsFileLinks sitting in the remark list, and that urlTransform. Drop any one of them from ChatMarkdown and every test in the new file still passes, because the test supplies its own. CHAT_MARKDOWN_SANITIZE_SCHEMA and markdownUrlTransform are both module-local, so exporting them and importing them into the test would turn this from a parallel implementation into an actual guard, without changing what is asserted.

The still removes unsafe schemes case is the right instinct given this widens what survives sanitization. One more worth adding next to it: a single-letter scheme that is not a drive path. WINDOWS_DRIVE_PATH_PATTERN keys off [A-Za-z]:, and the reason javascript: is safe is that it is many letters, not one. Something like [x](c:/Users/x) versus a genuine one-letter scheme would pin that the widening is limited to drive paths rather than to any short scheme.

isAbsolutePath in filePathDisplay.ts only matches a forward slash after the drive letter:

returnpath.startsWith("/")||/^[A-Za-z]:\//.test(path);

That is fine where it is called, since the value has already been through normalizeMarkdownLinkDestination, but the function name reads general and the next caller will not necessarily normalize first. C:\Users\... returns false from a function called isAbsolutePath. Either accepting both separators or naming it for the normalized input would stop that being a trap later.

@CDVolvikCDVolvik mentioned this pull request Aug 14, 2026
4 tasks
@fbal98

Copy link
Copy Markdown

we need this merged

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8081, which fixes Windows drive-path file links in chat without weakening Markdown URL sanitization. Your work is credited in #8081.

@t3dotggt3dotgg closed this Aug 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M30-99 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@peculiarnewbie@Defmon3@carlosesl1@fbal98@t3dotgg@CDVolvik
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix(web): make Windows file links clickable - #6237

Closed
peculiarnewbie wants to merge 4 commits into
pingdotgg:mainfrom
peculiarnewbie:fix/windows-markdown-file-links
Closed

fix(web): make Windows file links clickable#6237
peculiarnewbie wants to merge 4 commits into
pingdotgg:mainfrom
peculiarnewbie:fix/windows-markdown-file-links

Conversation

@peculiarnewbie

@peculiarnewbiepeculiarnewbie commented Aug 11, 2026

Copy link
Copy Markdown

Problem

On Windows, Markdown links with direct drive paths such as [artifact](C:/Users/.../artifact.mp4) rendered as blue text with no usable target. rehype-sanitize interpreted the drive letter as a URL scheme and removed the href before React Markdown's URL transform could normalize it.

Fix

Rewrite only Windows drive-path link destinations to the already-allowed file:/// form while the document is still Markdown AST. The existing URL transform then restores the drive path and sends it through T3 Code's existing file-link renderer. Forward- and backslash drive paths, including encoded and unencoded Unicode segments, are canonicalized to the same lookup key, while unsafe schemes remain subject to the normal sanitizer.

Absolute Windows paths outside the workspace also remain absolute in tooltips and copied paths. The composer's existing mention-chip behavior is unchanged and out of scope.

Before

The label looked like a link, but it had no target and could not be clicked.

Before: Windows drive-path link rendered without a usable target

After

The same destination reaches the existing file-link component; hovering reveals the full path and the link is actionable.

After: Windows drive-path link rendered as an actionable file chip

Verification

  • vp test run apps/web/src/markdown-links.test.ts apps/web/src/markdown-links-rendering.test.tsx apps/web/src/filePathDisplay.test.ts — 46 tests passed
  • vp run --filter @t3tools/web typecheck
  • Targeted vp lint and vp fmt --check for all six changed files
  • Manually verified in the Windows web client; desktop inherits the same web renderer

Implemented with GPT-5.6-Sol in the Codex harness via T3 Code.


Note

Medium Risk
Touches markdown href sanitization and file-link resolution, which are security-adjacent URL handling paths. Scope is narrow and unsafe schemes still go through the existing sanitizer.

Overview
Fixes Windows drive-path markdown links (e.g. C:/... or C:\\...) that rendered as non-clickable text because rehype-sanitize treated the drive letter as a URL scheme and stripped the href.

Adds remarkRewriteWindowsFileLinks, which rewrites only Windows drive destinations to allowed file:/// form in mdast before sanitization. The existing URL transform then restores the drive path for the normal file-link renderer. Also canonicalizes backslash/unicode variants into a shared lookup key via normalizeMarkdownFileLinkHrefKey.

Separately, formatWorkspaceRelativePath now treats Windows drive paths as absolute, so paths outside the workspace stay absolute in tooltips/copied paths instead of getting a workspace label prefix.

Reviewed by Cursor Bugbot for commit 2e03244. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Fix Windows file path links to be clickable in chat markdown

  • Adds remarkRewriteWindowsFileLinks remark plugin to convert Windows drive-path links (e.g. C:\foo) into file:///C:/... URIs before HTML sanitization, preventing the sanitizer from stripping them.
  • Adds normalizeMarkdownFileLinkHrefKey to produce stable canonical keys for Windows file links regardless of backslashes or percent-encoding, replacing the local helper in ChatMarkdown.tsx.
  • Fixes formatWorkspaceRelativePath in filePathDisplay.ts to avoid prefixing absolute Windows drive paths with the workspace label.

Macroscope summarized 2e03244.

@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8c280e0d-dd44-4bf0-9dab-3c58ad0bb2c3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Aug 11, 2026
@peculiarnewbie
peculiarnewbieforce-pushed the fix/windows-markdown-file-links branch from a1e59dc to f3024d6CompareAugust 11, 2026 22:31
@peculiarnewbie
peculiarnewbie marked this pull request as draft August 11, 2026 22:34
@peculiarnewbie
peculiarnewbie deleted the fix/windows-markdown-file-links branch August 11, 2026 22:37
@macroscopeapp

macroscopeappBot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved 2e03244

Straightforward bug fix making Windows file paths clickable in markdown by converting them to file:// URIs before HTML sanitization. Changes are self-contained with good test coverage, including verification that unsafe schemes remain blocked.

You can customize Macroscope's approvability policy. Learn more.

macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 11, 2026
@peculiarnewbie
peculiarnewbieforce-pushed the fix/windows-markdown-file-links branch from f3024d6 to 6717343CompareAugust 11, 2026 23:17
@github-actionsgithub-actionsBot added size:M 30-99 changed lines (additions + deletions). and removed size:S 10-29 changed lines (additions + deletions). labels Aug 11, 2026
@peculiarnewbie
peculiarnewbie marked this pull request as ready for review August 11, 2026 23:33
Comment threadapps/web/src/markdown-links.ts
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 11, 2026 23:40

Dismissing prior approval to re-evaluate 6717343

macroscopeapp[bot]
macroscopeappBot previously approved these changes Aug 12, 2026

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 71371ee. Configure here.

Comment threadapps/web/src/markdown-links.ts
@macroscopeapp
macroscopeappBot dismissed their stale reviewAugust 12, 2026 00:20

Dismissing prior approval to re-evaluate 2e03244

@Defmon3

Copy link
Copy Markdown

Confirmed on Windows. We reproduced drive-letter Windows Markdown links failing to open, then tested the current PR head (2e03244) in our downstream build. The links now resolve and open correctly, including the chat rendering path with line breaks. Thanks for the fix.

@carlosesl1

Copy link
Copy Markdown

I reproduced one remaining gap with the current PR head: valid angle-bracketed destinations containing spaces or balanced parentheses survive the Markdown pipeline, but MARKDOWN_LINK_HREF_PATTERN misses them. That leaves markdownFileLinkMetaByHref empty, so the anchor falls through to the external-link path instead of the existing file-link behavior.

I opened a small, tested follow-up against this branch: peculiarnewbie#1

It keeps the precomputed map as the fast path and falls back to resolving the parsed/normalized href. Regression coverage uses the issue reproduction: <C:/Users/Carlos/My Project/docs/Plan (final).md>. All 43 focused tests, web typecheck, targeted lint, and formatting checks pass.

@CDVolvikCDVolvik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

46/46 across markdown-links.test.ts, markdown-links-rendering.test.tsx and filePathDisplay.test.ts on Linux (Node 24).

I went looking for a mismatch between the rendering test's pipeline and the real one, since markdown-links-rendering.test.tsx builds its own ReactMarkdown rather than rendering ChatMarkdown. There isn't one today. The test uses

protocols: { ...defaultSchema.protocols,href: [...(defaultSchema.protocols?.href??[]),"file"]}urlTransform={(href)=>rewriteMarkdownFileUriHref(href)??defaultUrlTransform(href)}

and ChatMarkdown uses exactly the same protocol list in CHAT_MARKDOWN_SANITIZE_SCHEMA, plus

constmarkdownUrlTransform=useCallback((href: string)=>{returnrewriteMarkdownFileUriHref(href)??defaultUrlTransform(href);},[]);

So the behaviour is faithfully mirrored. Worth flagging anyway, because the mirroring is by hand and there are now three things that have to stay in step: the file protocol entry, remarkRewriteWindowsFileLinks sitting in the remark list, and that urlTransform. Drop any one of them from ChatMarkdown and every test in the new file still passes, because the test supplies its own. CHAT_MARKDOWN_SANITIZE_SCHEMA and markdownUrlTransform are both module-local, so exporting them and importing them into the test would turn this from a parallel implementation into an actual guard, without changing what is asserted.

The still removes unsafe schemes case is the right instinct given this widens what survives sanitization. One more worth adding next to it: a single-letter scheme that is not a drive path. WINDOWS_DRIVE_PATH_PATTERN keys off [A-Za-z]:, and the reason javascript: is safe is that it is many letters, not one. Something like [x](c:/Users/x) versus a genuine one-letter scheme would pin that the widening is limited to drive paths rather than to any short scheme.

isAbsolutePath in filePathDisplay.ts only matches a forward slash after the drive letter:

returnpath.startsWith("/")||/^[A-Za-z]:\//.test(path);

That is fine where it is called, since the value has already been through normalizeMarkdownLinkDestination, but the function name reads general and the next caller will not necessarily normalize first. C:\Users\... returns false from a function called isAbsolutePath. Either accepting both separators or naming it for the normalized input would stop that being a trap later.

@CDVolvikCDVolvik mentioned this pull request Aug 14, 2026
4 tasks
@fbal98

Copy link
Copy Markdown

we need this merged

@t3dotgg

Copy link
Copy Markdown
Member

Note

🤖 GPT-5.6 Sol responding on behalf of Theo

Closing in favor of merged #8081, which fixes Windows drive-path file links in chat without weakening Markdown URL sanitization. Your work is credited in #8081.

@t3dotggt3dotgg closed this Aug 25, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M30-99 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@peculiarnewbie@Defmon3@carlosesl1@fbal98@t3dotgg@CDVolvik