fix(markdown): balanced parentheses inside autolinks (#41)

This commit is contained in:
hampus-fluxer 2026-01-06 03:19:13 +01:00 committed by GitHub
parent 39ac149810
commit 1ed066ca36
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 42 additions and 3 deletions

View File

@ -672,6 +672,24 @@ describe('Fluxer Markdown Parser', () => {
]);
});
test('urls with balanced parentheses inside autolinks', () => {
const input = 'Visit https://en.wikipedia.org/wiki/Chris_Messina_(inventor) for documentation.';
const flags = ParserFlags.ALLOW_AUTOLINKS;
const parser = new Parser(input, flags);
const {nodes: ast} = parser.parse();
expect(ast).toEqual([
{type: NodeType.Text, content: 'Visit '},
{
type: NodeType.Link,
text: undefined,
url: 'https://en.wikipedia.org/wiki/Chris_Messina_(inventor)',
escaped: false,
},
{type: NodeType.Text, content: ' for documentation.'},
]);
});
test('standard URLs with autolinks disabled', () => {
const input = 'Visit https://example.com and http://test.org';
const flags = 0;

View File

@ -314,10 +314,31 @@ export function extractUrlSegment(text: string, parserFlags: number): ParserResu
let end = prefixLength;
const textLength = text.length;
let parenthesesDepth = 0;
while (end < textLength && !StringUtils.isUrlTerminationChar(text[end])) {
end++;
if (end - prefixLength > MAX_LINK_URL_LENGTH) break;
while (end < textLength) {
const currentChar = text[end];
if (currentChar === '(') {
parenthesesDepth++;
end++;
} else if (currentChar === ')') {
if (parenthesesDepth > 0) {
parenthesesDepth--;
end++;
} else {
break;
}
} else if (StringUtils.isUrlTerminationChar(currentChar)) {
break;
} else {
end++;
}
if (end - prefixLength > MAX_LINK_URL_LENGTH) {
end = prefixLength + MAX_LINK_URL_LENGTH;
break;
}
}
let urlString = text.slice(0, end);