The long and stupid way is listed below, but hoping that someone has a way quicker and nicer solution. (Didn't have time to come up with a proper Node or Deno solution, so I spent better part of the day on this abomination.quote)
-
"Install" GitHub CLI and Pandoc
nix-shell -p gh pandoc
-
Export GitHub issues in JSON
The minimum GitHub issue properties required in the JavaScript snippet below:
gh issue list --json title,body,url,number
Use this to see all available issue properties (
-L
is needed to get more than 30 issues):gh issue list --json -L
One can filter the issues too if needed:
gh issue list --state all --json title,body,url,number,comments,labels
-
Copy the terminal output from the previous step to the JavaScript console in Chrome Dev Tools:
> issues = ...copy here...
-
On the same JavaScript console, copy and execute the following lines too:
// https://stackoverflow.com/questions/5282228/how-to-include-javascript-file-or-library-in-chrome-console async function loadScript(url) { let response = await fetch(url); let script = await response.text(); eval(script); } // Doesn't seem to work on the console without a top-level `await` await loadScript('https://cdnjs.cloudflare.com/ajax/libs/showdown/2.1.0/showdown.min.js'); // Needed to convert Markdown to HTML; see https://github.com/showdownjs/showdown const mdConverter = new showdown.Converter(); function issuesJSONToHTML(issues) { let h1 = document.createElement('h1'); h1.textContent = "Github issues"; let newBody = document.createElement('body'); // Convert `issues` array JSON and put into `newBody` issues. // `gh` outputs issues in reverse chronological order reverse(). map( (iss) => { let section = document.createElement('section'); let title = document.createElement('h2'); title.innerHTML = `<a href="${iss.url}">#${iss.number} (${iss.labels.map((label) => label.name).join('|')}): ${iss.title}</a>`; let body = document.createElement('blockquote'); body.className = 'issue-body'; body.innerHTML = mdConverter.makeHtml(iss.body); section.appendChild(title); section.appendChild(body); let resTitle = document.createElement('h3') resTitle.innerHTML = 'Response'; section.appendChild(resTitle); let commentsDiv = document.createElement('div'); commentsDiv.className = 'comments' iss.comments.forEach((comment) => { let comment_body = document.createElement('p'); comment_body.className = 'comment_body'; comment_body.innerHTML = mdConverter.makeHtml(comment.body); commentsDiv.appendChild(comment_body); }); section.appendChild(commentsDiv); return section; }). forEach( (iss) => { newBody.appendChild(iss); }) // Replace the site where the console is open // (this is mostly for instant testing) document.head.innerHTML = ` <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>GitHub issues</title> <style> body { font-family: Arial, sans-serif; margin: 20px; } h1, h2 { color: #333; } p { margin: 10px 0; line-height: 1.5; } section { margin-bottom: 30px; padding: 15px; border: 1px solid #ddd; border-radius: 8px; background-color: #f9f9f9; } .issue-body { font-weight: bold; } .comments { margin-top: 20px; padding: 10px; background-color: #f1f1f1; border-left: 4px solid #ccc; } .comment-body { margin: 10px 0; font-size: 0.9em; color: #555; } </style> `; document.body.innerHTML = newBody.outerHTML; return document.documentElement.outerHTML; }
-
Copy the HTML document to the system clipboard from the JavaScript console
copy(issuesJSONToHTML(issues))
-
Paste it into a text file (e.g.,
issues.html
) -
Convert the saved HTML file to a Word document on the terminal
pandoc issues.html -o issues.docx