fix(desktop): preserve matched URL parentheses
(cherry picked from commit 6e126d8575859f9ca7a6d20240e2e2ba61c74b7b)
This commit is contained in:
@@ -134,6 +134,24 @@ describe('preprocessMarkdown', () => {
|
||||
expect(output).toContain('<https://example.com/wiki/Foo_(bar)>')
|
||||
})
|
||||
|
||||
it('preserves a trailing balanced pair after an earlier stray closing paren', () => {
|
||||
const output = preprocessMarkdown('See https://example.com/a)(b)')
|
||||
|
||||
expect(output).toContain('<https://example.com/a)(b)>')
|
||||
})
|
||||
|
||||
it('strips three wrapper closing parens from raw-url autolinks', () => {
|
||||
const output = preprocessMarkdown('(((https://example.com/page)))')
|
||||
|
||||
expect(output).toBe('(((<https://example.com/page>)))')
|
||||
})
|
||||
|
||||
it('preserves an unmatched opening paren at the end of a raw URL', () => {
|
||||
const output = preprocessMarkdown('https://example.com/foo(')
|
||||
|
||||
expect(output).toContain('<https://example.com/foo(>')
|
||||
})
|
||||
|
||||
it('strips only the wrapper closing paren around balanced-paren URLs', () => {
|
||||
const output = preprocessMarkdown('(https://example.com/wiki/Foo_(bar))')
|
||||
|
||||
|
||||
@@ -211,29 +211,32 @@ function isUrlOnlyBlock(lines: string[]): boolean {
|
||||
// Strip only the *unbalanced* trailing `)` — the closing paren of a prose
|
||||
// wrapper like `(https://example.com/page)`, which the bare-URL matcher
|
||||
// greedily captures into the href. Parens that belong to the URL itself
|
||||
// (`…/wiki/Foo_(bar)`) stay intact: a trailing `)` is peeled only while the
|
||||
// URL holds more `)` than `(`. Count once, then trim from the end — the loop
|
||||
// only ever removes trailing closers, so `opens` never changes.
|
||||
// (`…/wiki/Foo_(bar)`) stay intact. Track normal left-to-right pairing and
|
||||
// peel only a suffix made entirely of unmatched closing parens; this avoids
|
||||
// sacrificing a valid trailing pair when an earlier stray `)` exists.
|
||||
function trimUnbalancedTrailingParens(url: string): string {
|
||||
let opens = 0
|
||||
let closes = 0
|
||||
let depth = 0
|
||||
let unmatchedSuffixStart: number | null = null
|
||||
|
||||
for (let index = 0; index < url.length; index += 1) {
|
||||
const char = url[index]
|
||||
|
||||
for (const char of url) {
|
||||
if (char === '(') {
|
||||
opens += 1
|
||||
depth += 1
|
||||
unmatchedSuffixStart = null
|
||||
} else if (char === ')') {
|
||||
closes += 1
|
||||
if (depth > 0) {
|
||||
depth -= 1
|
||||
unmatchedSuffixStart = null
|
||||
} else if (unmatchedSuffixStart === null) {
|
||||
unmatchedSuffixStart = index
|
||||
}
|
||||
} else {
|
||||
unmatchedSuffixStart = null
|
||||
}
|
||||
}
|
||||
|
||||
let end = url.length
|
||||
|
||||
while (closes > opens && url[end - 1] === ')') {
|
||||
closes -= 1
|
||||
end -= 1
|
||||
}
|
||||
|
||||
return url.slice(0, end)
|
||||
return unmatchedSuffixStart === null ? url : url.slice(0, unmatchedSuffixStart)
|
||||
}
|
||||
|
||||
function autoLinkRawUrls(text: string): string {
|
||||
|
||||
Reference in New Issue
Block a user