-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathgitlab-textarea-paste.js
More file actions
51 lines (46 loc) · 1.83 KB
/
gitlab-textarea-paste.js
File metadata and controls
51 lines (46 loc) · 1.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// Plugin: Convert pasted Drupal.org issue URLs to Markdown links with issue title on GitLab MR pages
// Listens for paste events in textareas and replaces Drupal.org issue URLs with [Issue Title](URL)
const DRUPAL_ISSUE_URL =
/https?:\/\/www\.drupal\.org\/(?:project\/[^/]+\/issues|node|i)\/(\d+)[^\s]*/g;
function fetchIssueTitle(issueId) {
return fetch(`https://www.drupal.org/api-d7/node/${issueId}.json`)
.then((response) => response.json())
.then((data) => (data && data.title) || null)
.catch(() => null);
}
function handlePaste(e) {
const pasted = e.clipboardData.getData("text");
const matches = [...pasted.matchAll(DRUPAL_ISSUE_URL)];
if (matches.length === 0) return;
e.preventDefault();
const textarea = e.target;
const start = textarea.selectionStart;
const end = textarea.selectionEnd;
let replaced = pasted;
let pending = matches.length;
matches.forEach(async ([match, issueId]) => {
const title = await fetchIssueTitle(issueId);
const cleanTitle = title ? title.trim().replace(/\s+/g, " ") : "";
const md = title ? `[${cleanTitle}](${match})` : match;
replaced = replaced.replace(match, md);
pending--;
if (pending === 0) {
textarea.value =
textarea.value.slice(0, start) + replaced + textarea.value.slice(end);
const newPos = start + replaced.length;
textarea.setSelectionRange(newPos, newPos);
}
});
}
function attachToAllTextareas() {
document.querySelectorAll("textarea").forEach((ta) => {
if (!ta._drupalPasteAttached) {
ta.addEventListener("paste", handlePaste);
ta._drupalPasteAttached = true;
}
});
}
// Attach on load and on DOM changes (for dynamically loaded textareas)
attachToAllTextareas();
const observer = new MutationObserver(attachToAllTextareas);
observer.observe(document.body, { childList: true, subtree: true });