Skip to content
This repository was archived by the owner on Jan 24, 2023. It is now read-only.

Commit 90d48ca

Browse files
fix: Fix failure to copy description (#29)
Instead of copying the PR title and body from the HTML elements, which may not exist yet, use the GitHub API to query the necessary metadata. If the API query fails, attempt to make the PR body HTML elements load by opening the PR description for edit and immediately canceling the edit. Closes #11 Co-authored-by: Zach Whaley <[email protected]>
1 parent 8b90a20 commit 90d48ca

File tree

1 file changed

+70
-19
lines changed

1 file changed

+70
-19
lines changed

content.js

Lines changed: 70 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,34 @@ function debug(message) {
66
console.debug(`squashed-merge-message: ${message}`);
77
}
88

9-
function copyPrDescription() {
9+
async function copyPrDescription() {
1010
debug('copy PR description');
11-
const prTitleEl = document.getElementById('issue_title');
12-
if (!prTitleEl) {
13-
warn('failed to find PR title element');
14-
return;
15-
};
1611

17-
const prNumberMatch = window.location.pathname.match('/pull/(?<pr_number>[0-9]+)$');
18-
if (!prNumberMatch) {
19-
warn('failed to find match for PR number in URL');
12+
const match = window.location.pathname.match('^/(?<repo>[^/]+/[^/]+)/pull/(?<pr_number>[0-9]+)$');
13+
if (!match) {
14+
warn('failed to find match for repo and PR number in URL');
2015
return;
2116
};
17+
const repo = match.groups['repo'];
18+
const prNumber = match.groups['pr_number'];
2219

23-
let prBodyEl = document.querySelector('.comment-form-textarea[name="issue[body]"]');
24-
if (!prBodyEl) {
25-
prBodyEl = document.querySelector('.comment-form-textarea[name="pull_request[body]"]');
26-
if (!prBodyEl) {
27-
warn('failed to find PR body element');
28-
return;
29-
};
30-
};
20+
let prMetadata = null;
21+
22+
// For public repos, prefer the API.
23+
if (window.location.host === 'github.com') {
24+
prMetadata = await getPrMetadataFromApi(repo, prNumber);
25+
}
26+
27+
// If that fails, try manipulating the document.
28+
if (!prMetadata) {
29+
prMetadata = await getPrMetadataFromDocument();
30+
}
31+
32+
// If that fails... we fail!
33+
if (!prMetadata) {
34+
warn('failed to pull PR metadata from document or API');
35+
return;
36+
}
3137

3238
// When using auto-merge, GitHub has two text fields with the same ID.
3339
const titleFields = document.querySelectorAll('[id=merge_title_field]');
@@ -43,10 +49,10 @@ function copyPrDescription() {
4349
return;
4450
};
4551

46-
const commitTitle = `${prTitleEl.value} (#${prNumberMatch.groups['pr_number']})`;
52+
const commitTitle = `${prMetadata.title} (#${prNumber})`;
4753

4854
// Remove leading HTML comments
49-
let commitBody = prBodyEl.textContent.replace(/^<!--.*?-->\n*/gs, '');
55+
let commitBody = prMetadata.body.replace(/^<!--.*?-->\n*/gs, '').trim();
5056

5157
// Preserve and de-duplicate co-authors
5258
const coauthors = new Set(messageFields[0].value.match(/Co-authored-by: .*/g));
@@ -58,6 +64,51 @@ function copyPrDescription() {
5864
messageFields.forEach(f => f.value = commitBody);
5965
}
6066

67+
async function getPrMetadataFromDocument() {
68+
await makePrDescriptionAppear();
69+
70+
const prTitleEl = document.getElementById('issue_title');
71+
if (!prTitleEl) {
72+
warn('failed to find PR title element');
73+
return null;
74+
}
75+
76+
let prBodyEl = document.querySelector('.comment-form-textarea[name="issue[body]"]');
77+
if (!prBodyEl) {
78+
prBodyEl = document.querySelector('.comment-form-textarea[name="pull_request[body]"]');
79+
if (!prBodyEl) {
80+
warn('failed to find PR body element');
81+
return null;
82+
}
83+
}
84+
85+
return {
86+
title: prTitleEl.value,
87+
body: prBodyEl.textContent,
88+
};
89+
}
90+
91+
async function getPrMetadataFromApi(repo, prNumber) {
92+
const response = await fetch(`https://api.github.com/repos/${repo}/pulls/${prNumber}`);
93+
const prMetadata = await response.json();
94+
return {
95+
// These could be null in some cases, so replace nulls with empty strings.
96+
title: prMetadata.title || '',
97+
body: prMetadata.body || '',
98+
};
99+
}
100+
101+
async function makePrDescriptionAppear() {
102+
const detailsButton = document.querySelector('.timeline-comment-actions details:last-child summary[role="button"]');
103+
detailsButton.click();
104+
const editButton = await waitForElement('details-menu > button.dropdown-item.btn-link.js-comment-edit-button');
105+
editButton.click();
106+
const cancelButton = await waitForElement('button.js-comment-cancel-button.btn-danger.btn');
107+
cancelButton.click();
108+
const commitText = document.getElementById('merge_message_field');
109+
commitText.focus();
110+
}
111+
61112
function waitForElement(selector) {
62113
debug(`wait for element ${selector}`);
63114
return new Promise(resolve => {

0 commit comments

Comments
 (0)