Repository navigation
fix(shared): hosted thread URLs inside other links stay as written #36298
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,10 +10,23 @@ const V2_PREFIX = `${THREAD_LINK_PROTOCOL}://v2/`; | |
| const HOSTED_PREFIX = `${DEFAULT_HOSTED_APP_URL}/threads/`; | ||
| const HOSTED_SEGMENT = "[A-Za-z0-9_%-]+"; | ||
| const HOSTED_LINK = `${HOSTED_PREFIX.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&")}${HOSTED_SEGMENT}/${HOSTED_SEGMENT}`; | ||
| // Code comes first in the alternation so a link written inside a code span or fence is skipped. | ||
| // A labeled link's destination may be angle-bracketed, as CommonMark allows: [label](<href>). | ||
| const THREAD_HREF = String.raw`t3-thread:\/\/v[12]\/`; | ||
| // A label stops at any bracket, so a run of unclosed brackets is scanned once, not once per bracket. | ||
| const LABEL = String.raw`[^[\]\n]*`; | ||
| // Earlier alternatives claim text so later ones cannot match inside it: an escaped character opens | ||
| // nothing, code is literal, and a link to anywhere else keeps a thread URL in its label or href. | ||
| const THREAD_LINK_OUTSIDE_CODE = new RegExp( | ||
| String.raw`(?<fence>(\`{3,}|~{3,})[\s\S]*?(?:\2|$))|(?<span>(\`+)[^\n]*?\4)|\[(?<label>[^\]\n]*)\]\((?:<(?<angleHref>t3-thread:\/\/v[12]\/[^\s<>]+|${HOSTED_LINK})>|(?<href>t3-thread:\/\/v[12]\/[^\s>)]+|${HOSTED_LINK}))\)|<(?<autolink>t3-thread:\/\/v[12]\/[^\s<>]+|${HOSTED_LINK})>|(?<bare>${HOSTED_LINK})(?![\w%/?#-])`, | ||
| [ | ||
| String.raw`\\[!-/:-@[-\`{-~]`, | ||
| String.raw`(?<fence>(\`{3,}|~{3,})[\s\S]*?(?:\2|$))`, | ||
| String.raw`(?<span>(\`+)[^\n]*?\4)`, | ||
| // A labeled link's destination may be angle-bracketed, as CommonMark allows: [label](<href>). | ||
| String.raw`\[(?<label>${LABEL})\]\((?:<(?<angleHref>${THREAD_HREF}[^\s<>]+|${HOSTED_LINK})>|(?<href>${THREAD_HREF}[^\s>)]+|${HOSTED_LINK}))\)`, | ||
| String.raw`\[${LABEL}\]\((?:<[^<>\n]*>|[^\s()]*(?:\([^\s()]*\)[^\s()]*)*)(?:[ \t]+(?:"[^"\n]*"|'[^'\n]*'))?\)`, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Recognize destination whitespace before scanning inside a link. CommonMark permits whitespace between the parentheses and the destination. (spec.commonmark.org) For Accept optional destination whitespace, including trailing whitespace without a title. Add this form to the regression table.
|
||
| String.raw`<(?<autolink>${THREAD_HREF}[^\s<>]+|${HOSTED_LINK})>`, | ||
| // After a URL character the hosted link is part of a longer URL, such as a redirect target. | ||
| String.raw`(?<![A-Za-z0-9%/?#=&@+-])(?<bare>${HOSTED_LINK})(?![\w%/?#-])`, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check the surrounding URL, not only its preceding character. For Consume the surrounding URL before considering embedded hosted links. Keep standalone parenthesized hosted links eligible, as the existing regression case requires. Blocking every preceding
|
||
| ].join("|"), | ||
| "g", | ||
| ); | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Allow escaped brackets inside labels.
For
[a \[ https://app.t3.codes/threads/there/t1](https://example.com),LABELstops at the escaped[. Escaped brackets are valid label content. (spec.commonmark.org)Neither Markdown-link alternative claims the outer link. The bare-link alternative then rewrites the hosted URL inside its label and extracts an unrelated thread reference. The escape alternative cannot protect a link whose label scan already failed.
Consume escape pairs within
LABEL, while continuing to stop at unescaped brackets. Add this input to the regression table.