Skip to content

fix(components): end autolinks at non-ASCII punctuation - #336

Merged
lodystage[bot] merged 1 commit into
mainfrom
fix/markdown-autolink-cjk-boundary
Sep 4, 2026
Merged

fix(components): end autolinks at non-ASCII punctuation#336
lodystage[bot] merged 1 commit into
mainfrom
fix/markdown-autolink-cjk-boundary

Conversation

@lodystage

@lodystage lodystage Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

A GFM literal autolink only ends at ASCII whitespace, so CJK prose written without one gets swallowed into the destination. **https://github.com/LodyAI/Lody/pull/317**,分支 rendered as one link spanning https://…/pull/317**,分支 — the ** disappeared into the URL, so the strong it opened never closed and showed up as literal asterisks.

Two layers had the same gap:

  • Our own AUTOLINK_PATTERN / splitAutolinkTrailing only trimmed trailing punctuation, so https://example.com/a。然后 kept 。然后 — the loop stops at the first non-punctuation character, and is a letter.
  • GFM's literal autolink extension does the same upstream, which is what ate the strong closer.

Fix

  • New NON_ASCII_URL_BOUNDARY = /(?!\p{ASCII})[\p{P}\p{Z}]/u, applied in splitAutolinkTrailing and in a new mdast pass (trimNonAsciiAutolinkTail) that runs before the existing bold repair. The trimmed tail is re-parsed as inline markdown, and the destination is truncated only when it actually ends with that tail (raw or percent-encoded) — otherwise the node is left untouched rather than guessing at a cut point.
  • Dropped the bold repair's "suffix must contain inline markup" guard. With the tail cut, the suffix in this case is plain text, and the case the guard was originally added for (**https://example.com/path**segment) is already rejected by isValidStrongCloser.

Ordering is safe by construction: every boundary character is Markdown punctuation or whitespace, so a ** left text-final by the cut was already a valid strong closer in the source — the trim cannot manufacture one.

Deliberate scope

Non-ASCII letters stay in the URL, so https://zh.example.com/wiki/中文 still links whole; non-ASCII symbols like are also untouched, preserving the existing "€ is not Markdown punctuation" behaviour. A URL followed immediately by 汉字 with no punctuation (访问https://example.com吧) therefore still swallows the character. That is GFM-conformant, and cutting there would break CJK IRI paths, so I left it.

Verification

  • Full @lody/components suite: 421 files / 3042 tests passing
  • tsc --noEmit clean, oxlint clean
  • 5 new tests: the exact reported string, a bare URL before , a CJK path that must stay intact, and two splitAutolinkTrailing cases

🤖 Generated with Claude Code

A GFM literal autolink only ends at ASCII whitespace, so CJK prose written
without one is swallowed into the destination: `**https://.../pull/317**,分支`
rendered as a single link over `...317**,分支`, with the `**` never closing
the strong it opened.

Treat a non-ASCII punctuation mark or separator as the end of a bare URL in
both autolinkers — those never appear unencoded in a URL, while non-ASCII
letters still can (`/wiki/中文`). For GFM autolinks this runs as a pass before
the existing bold repair; every boundary character is Markdown punctuation or
whitespace, so a `**` left text-final by the cut was already a valid strong
closer in the source. That also makes the repair's "suffix must contain inline
markup" guard wrong — the swallowed suffix here is plain text — and the guard's
original case (`**https://example.com/path**segment`) is already covered by the
strong-closer validity check.

Model: claude-opus-5[1m]

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5fc5d52352

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

// (,。、)「」… ) never appear unencoded in a URL, so end the URL there.
// Non-ASCII letters still may (`/wiki/中文`), and symbols are left alone
// because they are not Markdown punctuation for strong-closer purposes.
const NON_ASCII_URL_BOUNDARY = /(?!\p{ASCII})[\p{P}\p{Z}]/u;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve valid punctuation inside international URLs

When a bare URL legitimately contains Unicode punctuation, this boundary truncates the link at the first such character. For example, https://ja.wikipedia.org/wiki/ハリー・ポッター is split at the common Japanese middle dot (, category \p{P}), producing a link only to .../ハリー; paths containing en dashes and similar valid characters break likewise in both autolinking passes. Restrict the boundary to known sentence delimiters or otherwise distinguish punctuation inside a URL from following prose.

Useful? React with 👍 / 👎.

@lodystage
lodystage Bot merged commit 3a1ea3f into main Sep 4, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant