Skip to content

Commit 037f72b

Browse files
MaxWebZwxiaoguang
andauthored
fix: prevent double markdown link brackets when pasting URL (#34745)
When adding a link using the "Add a link" button in comment editor, pasting a URL resulted in incorrect Markdown formatting (double brackets) instead of replacing the placeholder text. This fix adds a context check to prevent creating a new markdown link when we're already inside an existing one. Fixes #34740 --------- Co-authored-by: wxiaoguang <[email protected]>
1 parent 4cbb482 commit 037f72b

File tree

2 files changed

+26
-7
lines changed

2 files changed

+26
-7
lines changed

web_src/js/features/comp/EditorUpload.test.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {removeAttachmentLinksFromMarkdown} from './EditorUpload.ts';
1+
import {pasteAsMarkdownLink, removeAttachmentLinksFromMarkdown} from './EditorUpload.ts';
22

33
test('removeAttachmentLinksFromMarkdown', () => {
44
expect(removeAttachmentLinksFromMarkdown('a foo b', 'foo')).toBe('a foo b');
@@ -12,3 +12,13 @@ test('removeAttachmentLinksFromMarkdown', () => {
1212
expect(removeAttachmentLinksFromMarkdown('a <img src="/attachments/foo"> b', 'foo')).toBe('a b');
1313
expect(removeAttachmentLinksFromMarkdown('a <img src="/attachments/foo" width="100"/> b', 'foo')).toBe('a b');
1414
});
15+
16+
test('preparePasteAsMarkdownLink', () => {
17+
expect(pasteAsMarkdownLink({value: 'foo', selectionStart: 0, selectionEnd: 0}, 'bar')).toBeNull();
18+
expect(pasteAsMarkdownLink({value: 'foo', selectionStart: 0, selectionEnd: 0}, 'https://gitea.com')).toBeNull();
19+
expect(pasteAsMarkdownLink({value: 'foo', selectionStart: 0, selectionEnd: 3}, 'bar')).toBeNull();
20+
expect(pasteAsMarkdownLink({value: 'foo', selectionStart: 0, selectionEnd: 3}, 'https://gitea.com')).toBe('[foo](https://gitea.com)');
21+
expect(pasteAsMarkdownLink({value: '..(url)', selectionStart: 3, selectionEnd: 6}, 'https://gitea.com')).toBe('[url](https://gitea.com)');
22+
expect(pasteAsMarkdownLink({value: '[](url)', selectionStart: 3, selectionEnd: 6}, 'https://gitea.com')).toBeNull();
23+
expect(pasteAsMarkdownLink({value: 'https://example.com', selectionStart: 0, selectionEnd: 19}, 'https://gitea.com')).toBeNull();
24+
});

web_src/js/features/comp/EditorUpload.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,17 +118,26 @@ export function removeAttachmentLinksFromMarkdown(text: string, fileUuid: string
118118
return text;
119119
}
120120

121-
function handleClipboardText(textarea: HTMLTextAreaElement, e: ClipboardEvent, text: string, isShiftDown: boolean) {
121+
export function pasteAsMarkdownLink(textarea: {value: string, selectionStart: number, selectionEnd: number}, pastedText: string): string | null {
122+
const {value, selectionStart, selectionEnd} = textarea;
123+
const selectedText = value.substring(selectionStart, selectionEnd);
124+
const trimmedText = pastedText.trim();
125+
const beforeSelection = value.substring(0, selectionStart);
126+
const afterSelection = value.substring(selectionEnd);
127+
const isInMarkdownLink = beforeSelection.endsWith('](') && afterSelection.startsWith(')');
128+
const asMarkdownLink = selectedText && isUrl(trimmedText) && !isUrl(selectedText) && !isInMarkdownLink;
129+
return asMarkdownLink ? `[${selectedText}](${trimmedText})` : null;
130+
}
131+
132+
function handleClipboardText(textarea: HTMLTextAreaElement, e: ClipboardEvent, pastedText: string, isShiftDown: boolean) {
122133
// pasting with "shift" means "paste as original content" in most applications
123134
if (isShiftDown) return; // let the browser handle it
124135

125136
// when pasting links over selected text, turn it into [text](link)
126-
const {value, selectionStart, selectionEnd} = textarea;
127-
const selectedText = value.substring(selectionStart, selectionEnd);
128-
const trimmedText = text.trim();
129-
if (selectedText && isUrl(trimmedText) && !isUrl(selectedText)) {
137+
const pastedAsMarkdown = pasteAsMarkdownLink(textarea, pastedText);
138+
if (pastedText) {
130139
e.preventDefault();
131-
replaceTextareaSelection(textarea, `[${selectedText}](${trimmedText})`);
140+
replaceTextareaSelection(textarea, pastedAsMarkdown);
132141
}
133142
// else, let the browser handle it
134143
}

0 commit comments

Comments
 (0)