UNPKG

@johnbillion/ghsvg

Version:

Create an SVG of your GitHub Sponsors

85 lines 4.06 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import * as axios from 'axios'; import * as fs from 'fs'; import * as path from 'path'; export function compareDeps(a, b) { function clipNum(dep) { return Number.parseInt(/clip-(\d+)/.exec(dep)[1]); } return clipNum(a) >= clipNum(b) ? 1 : -1; } export function createSVG(data, ghsOptions) { return __awaiter(this, void 0, void 0, function* () { const imageFormat = 'png'; const imageWidth = ghsOptions.svgImageWidth; const svgWidth = ghsOptions.svgWidth; const imageSpacing = ghsOptions.svgImageSpace; const rows = Math.floor(svgWidth / (imageWidth + imageSpacing)); const radius = Math.floor(imageWidth / 2); const defs = []; const images = []; let count = 0; const cacheDir = 'cache'; if (!fs.existsSync(cacheDir)) { fs.mkdirSync(cacheDir); } yield Promise.all(data.map((sponsor, index) => __awaiter(this, void 0, void 0, function* () { const imageX = index % rows; const imageY = Math.floor(index / rows); const locationX = imageX * (imageWidth + imageSpacing); const locationY = imageY * (imageWidth + imageSpacing); const avatarCache = path.join(cacheDir, sponsor.avatarUrl.split('/u/')[1].split('?')[0] + '.' + imageFormat); const avatar = yield getAvatar(sponsor.avatarUrl, avatarCache, imageFormat); defs.push(` <clipPath id="clip-${index}"> <circle cx="${locationX + radius}" cy="${locationY + radius}" r="${radius}"/> </clipPath>`); images.push(` <a xlink:href="${sponsor.htmlUrl || sponsor.url}" class="sponsor-svg" target="_blank" id="${sponsor.login}"> <image clip-path="url(#clip-${index})" x="${locationX}" y="${locationY}" width="${imageWidth}" height="${imageWidth}" xlink:href="${avatar}"/> </a>`); if (!ghsOptions.quiet) { process.stdout.write(`Fetching sponsors avatars ${Math.floor((++count / data.length) * 100)} % complete... \r`); } }))); return `<?xml version="1.0" encoding="utf-8"?> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${svgWidth}" height="${Math.ceil(data.length / rows) * (imageWidth + imageSpacing)}"> <defs> ${defs.sort(compareDeps).join('\n')} </defs> <style>.sponsor-svg { cursor: pointer; }</style> ${images.sort(compareDeps).join('\n')} </svg> `; }); } export function getBase64Image(data, format) { return `data:image/${format};base64,${Buffer.from(data).toString('base64')}`; } export function getAvatar(avatarUrl, avatarCache, format) { return __awaiter(this, void 0, void 0, function* () { if (!fs.existsSync(avatarCache)) { return yield new Promise((resolve, reject) => { axios.default .get(avatarUrl, { responseType: 'arraybuffer' }) .then(resp => { fs.writeFileSync(avatarCache, resp.data, { mode: 0o644 }); resolve(getBase64Image(resp.data, format)); }) .catch(function (err) { reject(err); }); }); } else { return getBase64Image(fs.readFileSync(avatarCache), format); } }); } //# sourceMappingURL=svg.js.map