Skip to content

Instantly share code, notes, and snippets.

@alpha-beta-soup
Forked from toraritte/github_issues_to_docx.md
Last active September 12, 2024 22:48
Show Gist options
  • Save alpha-beta-soup/11de7fd5750f1a715c625b3b20a54a53 to your computer and use it in GitHub Desktop.
Save alpha-beta-soup/11de7fd5750f1a715c625b3b20a54a53 to your computer and use it in GitHub Desktop.
A long and stupid way to save GitHub issues in Word DOCX format

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)

  1. "Install" GitHub CLI and Pandoc

    nix-shell -p gh pandoc
    
  2. 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
    
  3. Copy the terminal output from the previous step to the JavaScript console in Chrome Dev Tools:

    > issues = ...copy here...
    
  4. 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;
    }
  5. Copy the HTML document to the system clipboard from the JavaScript console

    copy(issuesJSONToHTML(issues))
  6. Paste it into a text file (e.g., issues.html)

  7. Convert the saved HTML file to a Word document on the terminal

    pandoc issues.html -o issues.docx
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment