Skip to content

fix(tui): keep balanced parentheses in a markdown link's target - #7170

Merged
Hmbown merged 1 commit into
codewhale-hq:mainfrom
Lstarsky0:fix/link-target-balanced-parens
Oct 31, 2026
Merged

Hmbown merged 1 commit into
codewhale-hq:mainfrom
Lstarsky0:fix/link-target-balanced-parens

Conversation

@Lstarsky0

Copy link
Copy Markdown
Contributor

What and why

A [text](url) link ends at the first ), so a destination with parentheses of its own loses its last ). The hyperlink then points at a page that doesn't exist, and the ) shows after the label. Wikipedia articles with a qualifier and old Microsoft Learn pages ending in (v=vs.85) are common examples. This reply, at 100 columns:

See [Rust](https://en.wikipedia.org/wiki/Rust_(programming_language)) for the history.

The [function article](https://en.wikipedia.org/wiki/Function_(mathematics)) says the same as https://en.wikipedia.org/wiki/Function_(mathematics).

The old [API page](https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms123401(v=vs.85)) is archived.

Before:

● See Rust) for the history.
▏
▏ The function article) says the same as https://en.wikipedia.org/wiki/Function_(mathematics).
▏
▏ The old API page) is archived.

with these hyperlink targets:

Rust             -> https://en.wikipedia.org/wiki/Rust_(programming_language
function article -> https://en.wikipedia.org/wiki/Function_(mathematics
API page         -> https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms123401(v=vs.85

After:

● See Rust for the history.
▏
▏ The function article says the same as https://en.wikipedia.org/wiki/Function_(mathematics).
▏
▏ The old API page is archived.
Rust             -> https://en.wikipedia.org/wiki/Rust_(programming_language)
function article -> https://en.wikipedia.org/wiki/Function_(mathematics)
API page         -> https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms123401(v=vs.85)

The bare URL on the second line was already right: bare URLs keep balanced parentheses (bare_http_links_preserve_balanced_parentheses_in_target). A named link now ends at the first ) without a matching (, using the same has_unmatched_closing_delimiter check the bare URL path trims with. So [y](https://example.com/f((x))) keeps both, and (see [docs](https://example.com/docs)) and [z](https://example.com/z) (aside) link as before. A destination whose parentheses don't balance, like [x](https://example.com/a(b), is no longer a named link, as in CommonMark; it shows as written, with the bare URL inside it linked.

Issue

No-Issue: a markdown link whose URL has parentheses loses its last ); I searched and found no issue for it

How I tested it

  • Ran a debug build of this change and one of main at c4f1e72 in a pseudo-terminal at 100x30 with an empty HOME and a local mock OpenAI-compatible server replying with the text above, and recorded the OSC 8 targets in the output (OSC 8 is on by default outside Windows); the rows and targets above come from those runs. A second reply checked the nested, prose and unbalanced cases in the paragraph above.
  • cargo nextest run -p codewhale-tui -p codewhale-tui-kit --lib: 13628 of 13628 passed, with the 457 tests whose names match markdown, link, url, osc8 or inline among them.
  • cargo fmt --all -- --check, cargo clippy -p codewhale-tui -p codewhale-tui-kit with CI's flags (also on 1.99), cargo check -p codewhale-tui -p codewhale-tui-kit --all-targets and cargo +1.89.0 check -p codewhale-tui -p codewhale-tui-kit: clean.

Checklist

  • One focused change, on c4f1e72; it merges cleanly into current main
  • cargo fmt --all passes, and tests cover new or changed behavior — cargo fmt passes; no new test, per AGENTS.md, so the runs above stand in for one
  • If this adds or changes a user-facing feature, I updated its docs and its row in docs/features.toml (cargo test -p codewhale-tui --test feature_registry checks it) — n/a

A `[text](url)` link ended at the first `)`, so a destination with
parentheses of its own, like a Wikipedia article ending in
`_(programming_language)` or an old Microsoft Learn page ending in
`(v=vs.85)`, lost its last `)`. The hyperlink pointed at a page that
doesn't exist and the `)` showed after the label. Bare URLs already keep
balanced parentheses (bare_http_links_preserve_balanced_parentheses_in_target).

End the destination at the first `)` without a matching `(`, using the
has_unmatched_closing_delimiter check the bare URL path trims with. A
destination whose parentheses don't balance is no longer a link, as in
CommonMark, and shows as written.

Signed-off-by: Lstarsky0 <59827030+Lstarsky0@users.noreply.github.com>
@Lstarsky0
Lstarsky0 requested a review from Hmbown as a code owner October 31, 2026 13:11

@claude claude Bot 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.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@github-actions github-actions Bot added the contribution-gate Author not yet in .github/APPROVED_CONTRIBUTORS; a maintainer grants access with /lgtm label Oct 31, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-31T13:13:18.056827Z
We couldn’t complete this review. Comment @codex review to try again.
69ff817 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@Hmbown
Hmbown merged commit 9986831 into codewhale-hq:main Oct 31, 2026
28 checks passed
Hmbown pushed a commit that referenced this pull request Oct 31, 2026
Three @Lstarsky0 fixes merged as PRs (merges dc48701, 9986831,
b2db2c0). #7171 carried its own changelog edit; #7169 and #7170 did not.
They join the existing @Lstarsky0 Markdown and footer-status entries rather
than adding new bullets, and the CONTRIBUTORS.md and Contributors section
lines name all three.

Verified before merging, on origin/main ecd256c with all three PRs merged
together locally: cargo fmt --check clean; cargo test -p codewhale-tui-kit
--lib 214 passed; cargo test -p codewhale-tui --lib (history:: markdown
stream_chunk) 186 passed; dead-code, blocking-calls and locale-parity gates
pass (run by hand, since CI's ratchet steps are advisory on fork PRs). No
test or fixture asserted on the removed "Stream chunk timeout set to" status.
After this edit: check-contributor-credit.py passes (11 contributors since
v0.10.2, all three surfaces) and scripts/sync-changelog.sh reproduces
crates/tui/CHANGELOG.md byte for byte.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: CodeWhale Bot <bot@codewhale.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contribution-gate Author not yet in .github/APPROVED_CONTRIBUTORS; a maintainer grants access with /lgtm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants