gh-load-pull-request 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Formatters for gh-load-pull-request
3
+ * Contains functions for converting PR data to markdown and JSON formats
4
+ */
5
+
6
+ /**
7
+ * Format a date string for display
8
+ * @param {string} dateStr - ISO date string
9
+ * @returns {string} Formatted date string
10
+ */
11
+ export function formatDate(dateStr) {
12
+ if (!dateStr) {
13
+ return '';
14
+ }
15
+ const date = new Date(dateStr);
16
+ return date
17
+ .toISOString()
18
+ .replace('T', ' ')
19
+ .replace(/\.\d+Z$/, ' UTC');
20
+ }
21
+
22
+ /**
23
+ * Convert PR data to JSON format
24
+ * @param {Object} data - PR data from loadPullRequest
25
+ * @param {Array} downloadedImages - Array of downloaded image info
26
+ * @returns {string} JSON string
27
+ */
28
+ export function convertToJson(data, downloadedImages = []) {
29
+ const { pr, files, comments, reviewComments, reviews, commits } = data;
30
+
31
+ return JSON.stringify(
32
+ {
33
+ pullRequest: {
34
+ number: pr.number,
35
+ title: pr.title,
36
+ state: pr.state,
37
+ draft: pr.draft,
38
+ merged: pr.merged,
39
+ url: pr.html_url,
40
+ author: {
41
+ login: pr.user.login,
42
+ url: `https://github.com/${pr.user.login}`,
43
+ },
44
+ createdAt: pr.created_at,
45
+ updatedAt: pr.updated_at,
46
+ mergedAt: pr.merged_at,
47
+ closedAt: pr.closed_at,
48
+ mergedBy: pr.merged_by
49
+ ? {
50
+ login: pr.merged_by.login,
51
+ url: `https://github.com/${pr.merged_by.login}`,
52
+ }
53
+ : null,
54
+ base: {
55
+ ref: pr.base.ref,
56
+ sha: pr.base.sha,
57
+ },
58
+ head: {
59
+ ref: pr.head.ref,
60
+ sha: pr.head.sha,
61
+ },
62
+ additions: pr.additions,
63
+ deletions: pr.deletions,
64
+ changedFiles: pr.changed_files,
65
+ labels: pr.labels?.map((l) => ({ name: l.name, color: l.color })) || [],
66
+ assignees:
67
+ pr.assignees?.map((a) => ({
68
+ login: a.login,
69
+ url: `https://github.com/${a.login}`,
70
+ })) || [],
71
+ requestedReviewers:
72
+ pr.requested_reviewers?.map((r) => ({
73
+ login: r.login,
74
+ url: `https://github.com/${r.login}`,
75
+ })) || [],
76
+ milestone: pr.milestone
77
+ ? { title: pr.milestone.title, number: pr.milestone.number }
78
+ : null,
79
+ body: pr.body,
80
+ },
81
+ commits: commits.map((c) => ({
82
+ sha: c.sha,
83
+ message: c.commit.message,
84
+ author: c.author?.login || c.commit.author?.name || 'unknown',
85
+ url: c.html_url,
86
+ date: c.commit.author?.date,
87
+ })),
88
+ files: files.map((f) => ({
89
+ filename: f.filename,
90
+ status: f.status,
91
+ additions: f.additions,
92
+ deletions: f.deletions,
93
+ previousFilename: f.previous_filename,
94
+ patch: f.patch,
95
+ })),
96
+ reviews: reviews.map((r) => ({
97
+ id: r.id,
98
+ author: r.user.login,
99
+ state: r.state,
100
+ body: r.body,
101
+ submittedAt: r.submitted_at,
102
+ })),
103
+ reviewComments: reviewComments.map((c) => ({
104
+ id: c.id,
105
+ author: c.user.login,
106
+ body: c.body,
107
+ path: c.path,
108
+ line: c.line,
109
+ createdAt: c.created_at,
110
+ diffHunk: c.diff_hunk,
111
+ reviewId: c.pull_request_review_id,
112
+ })),
113
+ comments: comments.map((c) => ({
114
+ id: c.id,
115
+ author: c.user.login,
116
+ body: c.body,
117
+ createdAt: c.created_at,
118
+ })),
119
+ downloadedImages: downloadedImages.map((img) => ({
120
+ originalUrl: img.originalUrl,
121
+ localPath: img.relativePath,
122
+ format: img.format,
123
+ })),
124
+ },
125
+ null,
126
+ 2
127
+ );
128
+ }
129
+
130
+ /**
131
+ * Generate markdown for metadata section
132
+ * @param {Object} pr - Pull request data
133
+ * @returns {string} Markdown content
134
+ */
135
+ export function generateMetadataMarkdown(pr) {
136
+ let markdown = `## Metadata\n\n`;
137
+
138
+ markdown += `| Field | Value |\n`;
139
+ markdown += `|-------|-------|\n`;
140
+ markdown += `| **Number** | #${pr.number} |\n`;
141
+ markdown += `| **URL** | ${pr.html_url} |\n`;
142
+ markdown += `| **Author** | [@${pr.user.login}](https://github.com/${pr.user.login}) |\n`;
143
+ markdown += `| **State** | ${pr.state}${pr.merged ? ' (merged)' : pr.draft ? ' (draft)' : ''} |\n`;
144
+ markdown += `| **Created** | ${formatDate(pr.created_at)} |\n`;
145
+ markdown += `| **Updated** | ${formatDate(pr.updated_at)} |\n`;
146
+
147
+ if (pr.merged_at) {
148
+ markdown += `| **Merged** | ${formatDate(pr.merged_at)} |\n`;
149
+ if (pr.merged_by) {
150
+ markdown += `| **Merged by** | [@${pr.merged_by.login}](https://github.com/${pr.merged_by.login}) |\n`;
151
+ }
152
+ }
153
+ if (pr.closed_at && !pr.merged_at) {
154
+ markdown += `| **Closed** | ${formatDate(pr.closed_at)} |\n`;
155
+ }
156
+
157
+ markdown += `| **Base** | \`${pr.base.ref}\` |\n`;
158
+ markdown += `| **Head** | \`${pr.head.ref}\` |\n`;
159
+ markdown += `| **Additions** | +${pr.additions} |\n`;
160
+ markdown += `| **Deletions** | -${pr.deletions} |\n`;
161
+ markdown += `| **Changed Files** | ${pr.changed_files} |\n`;
162
+ markdown += '\n';
163
+
164
+ if (pr.labels && pr.labels.length > 0) {
165
+ markdown += `**Labels:** ${pr.labels.map((l) => `\`${l.name}\``).join(', ')}\n\n`;
166
+ }
167
+
168
+ if (pr.assignees && pr.assignees.length > 0) {
169
+ markdown += `**Assignees:** ${pr.assignees.map((a) => `[@${a.login}](https://github.com/${a.login})`).join(', ')}\n\n`;
170
+ }
171
+
172
+ if (pr.requested_reviewers && pr.requested_reviewers.length > 0) {
173
+ markdown += `**Requested Reviewers:** ${pr.requested_reviewers.map((r) => `[@${r.login}](https://github.com/${r.login})`).join(', ')}\n\n`;
174
+ }
175
+
176
+ if (pr.milestone) {
177
+ markdown += `**Milestone:** ${pr.milestone.title}\n\n`;
178
+ }
179
+
180
+ return markdown;
181
+ }
182
+
183
+ /**
184
+ * Generate markdown for commits section
185
+ * @param {Array} commits - Array of commit data
186
+ * @returns {string} Markdown content
187
+ */
188
+ export function generateCommitsMarkdown(commits) {
189
+ if (commits.length === 0) {
190
+ return '';
191
+ }
192
+
193
+ let markdown = `## Commits (${commits.length})\n\n`;
194
+
195
+ for (const commit of commits) {
196
+ const message = commit.commit.message.split('\n')[0];
197
+ const sha = commit.sha.substring(0, 7);
198
+ const author =
199
+ commit.author?.login || commit.commit.author?.name || 'unknown';
200
+ const authorLink = commit.author
201
+ ? `[@${author}](https://github.com/${author})`
202
+ : author;
203
+ markdown += `- [\`${sha}\`](${commit.html_url}) ${message} — ${authorLink}\n`;
204
+ }
205
+
206
+ markdown += '\n';
207
+ return markdown;
208
+ }
209
+
210
+ /**
211
+ * Generate markdown for files changed section
212
+ * @param {Array} files - Array of file data
213
+ * @returns {string} Markdown content
214
+ */
215
+ export function generateFilesMarkdown(files) {
216
+ if (files.length === 0) {
217
+ return '';
218
+ }
219
+
220
+ let markdown = `## Files Changed (${files.length})\n\n`;
221
+ markdown += `| Status | File | Changes |\n`;
222
+ markdown += `|--------|------|--------:|\n`;
223
+
224
+ for (const file of files) {
225
+ const statusIcon =
226
+ file.status === 'added'
227
+ ? '🆕 Added'
228
+ : file.status === 'removed'
229
+ ? '🗑️ Removed'
230
+ : file.status === 'modified'
231
+ ? '✏️ Modified'
232
+ : file.status === 'renamed'
233
+ ? '📝 Renamed'
234
+ : `📄 ${file.status}`;
235
+ const changes = `+${file.additions} -${file.deletions}`;
236
+ let filename = file.filename;
237
+ if (file.status === 'renamed' && file.previous_filename) {
238
+ filename = `${file.previous_filename} → ${file.filename}`;
239
+ }
240
+ markdown += `| ${statusIcon} | \`${filename}\` | ${changes} |\n`;
241
+ }
242
+
243
+ markdown += '\n';
244
+ return markdown;
245
+ }