From 0d4e02b55400a6e265c7acb28efa7e2721591900 Mon Sep 17 00:00:00 2001 From: PKief Date: Fri, 7 Jun 2019 23:24:10 +0200 Subject: [PATCH] #448 Add contributors script --- .../scripts/contributors/contributor.ts | 21 ++++ src/scripts/contributors/contributors.css | 14 +++ src/scripts/contributors/contributors.html | 77 +++++++++++++ src/scripts/contributors/index.ts | 103 ++++++++++++++++++ 4 files changed, 215 insertions(+) create mode 100644 src/models/scripts/contributors/contributor.ts create mode 100644 src/scripts/contributors/contributors.css create mode 100644 src/scripts/contributors/contributors.html create mode 100644 src/scripts/contributors/index.ts diff --git a/src/models/scripts/contributors/contributor.ts b/src/models/scripts/contributors/contributor.ts new file mode 100644 index 0000000000..722fdcf1ce --- /dev/null +++ b/src/models/scripts/contributors/contributor.ts @@ -0,0 +1,21 @@ +export interface Contributor { + login: string; + id: number; + node_id: string; + avatar_url: string; + gravatar_id: string; + url: string; + html_url: string; + followers_url: string; + following_url: string; + gists_url: string; + starred_url: string; + subscriptions_url: string; + organizations_url: string; + repos_url: string; + events_url: string; + received_events_url: string; + type: string; + site_admin: boolean; + contributions: number; +} diff --git a/src/scripts/contributors/contributors.css b/src/scripts/contributors/contributors.css new file mode 100644 index 0000000000..0fc6ccc9f7 --- /dev/null +++ b/src/scripts/contributors/contributors.css @@ -0,0 +1,14 @@ +ul { + list-style: none; +} + +li { + width: 50px; + height: 50px; + float: left; +} + +img { + width: 100%; + height: 100%; +} \ No newline at end of file diff --git a/src/scripts/contributors/contributors.html b/src/scripts/contributors/contributors.html new file mode 100644 index 0000000000..c6500f5aa9 --- /dev/null +++ b/src/scripts/contributors/contributors.html @@ -0,0 +1,77 @@ + \ No newline at end of file diff --git a/src/scripts/contributors/index.ts b/src/scripts/contributors/index.ts new file mode 100644 index 0000000000..6955d7d367 --- /dev/null +++ b/src/scripts/contributors/index.ts @@ -0,0 +1,103 @@ +import * as https from 'https'; +import * as fs from 'fs'; +import * as path from 'path'; +import * as painter from '../helpers/painter'; +import { Contributor } from '../../models/scripts/contributors/contributor'; + +/** + * Parse link header + * @param linkHeader Link header as string + * @returns Object that contains the page numbers of `prev`, `next` and `last`. + */ +const parseLinkHeader = (linkHeader: string) => { + const nextPagePattern = new RegExp(/\bpage=(\d)[^>]*>;\srel="next"/); + const lastPagePattern = new RegExp(/\bpage=(\d)[^>]*>;\srel="last"/); + const prevPagePattern = new RegExp(/\bpage=(\d)[^>]*>;\srel="prev"/); + + const nextPage = nextPagePattern.exec(linkHeader); + const lastPage = lastPagePattern.exec(linkHeader); + const prevPage = prevPagePattern.exec(linkHeader); + + return { nextPage, lastPage, prevPage }; +}; + +/** + * Get all contributors from GitHub API. + */ +const fetchContributors = (page: string): Promise<{ contributorsOfPage: Contributor[], nextPage: string }> => { + return new Promise((resolve, reject) => { + const requestOptions: https.RequestOptions = { + method: 'GET', + hostname: 'api.github.com', + path: `/repos/pkief/vscode-material-icon-theme/contributors?page=${page}`, + port: 443, + headers: { + 'link': 'next', + 'accept': 'application/json', + 'User-Agent': 'Contributors script', + }, + }; + + const req = https.request(requestOptions, (res) => { + const { nextPage, lastPage, prevPage } = parseLinkHeader(res.headers.link.toString()); + console.log('> Material Icon Theme:', painter.yellow(`[${page}/${lastPage ? lastPage[1] : +prevPage[1] + 1}] Loading contributors from GitHub...`)); + const result = []; + res.on('data', (data: Buffer) => { + result.push(data); + }); + + res.on('end', () => { + try { + const buffer = Buffer.concat(result); + const bufferAsString = buffer.toString('utf8'); + const contributorsOfPage = JSON.parse(bufferAsString); + resolve({ contributorsOfPage, nextPage: nextPage ? nextPage[1] : undefined }); + } catch (error) { + reject(error); + } + }); + }); + + req.on('error', (error) => { + console.error(error); + reject(error); + }); + + req.end(); + }); +}; + +const createContributorsList = (contributors: Contributor[]) => { + const list = contributors.map(c => { + return `
  • ${c.login}
  • `; + }).join('\n'); + + const htmlDoctype = ``; + const styling = ``; + const generatedHtml = `${htmlDoctype}${styling}`; + + const outputPath = path.join(__dirname, 'contributors.html'); + fs.writeFileSync(outputPath, generatedHtml); +}; + +const init = async () => { + const contributorsList: Contributor[] = []; + let page = '1'; + + // iterate over the pages of GitHub API + while (page !== undefined) { + const result = await fetchContributors(page); + contributorsList.push(...result.contributorsOfPage); + page = result.nextPage; + } + + if (contributorsList.length > 0) { + console.log('> Material Icon Theme:', painter.green(`Successfully fetched all contributors from GitHub!`)); + } else { + console.log('> Material Icon Theme:', painter.red(`Error: Could not fetch contributors from GitHub!`)); + throw Error(); + } + createContributorsList(contributorsList); +}; + +init();