@lizardbyte/contribkit
Version:
Toolkit for generating contributor images
600 lines (589 loc) • 19.7 kB
text/typescript
import { Buffer as Buffer$1 } from 'node:buffer';
import { consola } from 'consola';
declare function genSvgImage(x: number, y: number, size: number, radius: number, base64Image: string, imageFormat: ImageFormat): string;
declare function generateBadge(x: number, y: number, sponsor: Sponsor, preset: BadgePreset, radius: number, imageFormat: ImageFormat): Promise<string>;
declare class SvgComposer {
readonly config: Required<ContribkitRenderOptions>;
height: number;
body: string;
constructor(config: Required<ContribkitRenderOptions>);
addSpan(height?: number): this;
addTitle(text: string, classes?: string): this;
addText(text: string, classes?: string): this;
addRaw(svg: string): this;
addSponsorLine(sponsors: Sponsorship[], preset: BadgePreset): Promise<void>;
addSponsorGrid(sponsors: Sponsorship[], preset: BadgePreset): Promise<this>;
generateSvg(): string;
}
type ImageFormat = 'png' | 'webp';
interface BadgePreset {
boxWidth: number;
boxHeight: number;
avatar: {
size: number;
classes?: string;
};
name?: false | {
color?: string;
classes?: string;
maxLength?: number;
};
container?: {
sidePadding?: number;
};
classes?: string;
}
interface TierPartition {
monthlyDollars: number;
tier: Tier;
sponsors: Sponsorship[];
}
interface Provider {
name: string;
fetchSponsors: (config: ContribkitConfig) => Promise<Sponsorship[]>;
}
interface Sponsor {
type: 'User' | 'Organization';
login: string;
name: string;
avatarUrl: string;
avatarBuffer?: Buffer$1;
websiteUrl?: string;
linkUrl?: string;
/**
* Map of logins of other social accounts
*
* @example
* ```json
* {
* 'github': 'antfu',
* 'opencollective': 'antfu',
* }
* ```
*
* This would allow us to merge sponsors from different platforms.
*/
socialLogins?: Record<string, string>;
}
interface Sponsorship {
sponsor: Sponsor;
monthlyDollars: number;
privacyLevel?: 'PUBLIC' | 'PRIVATE';
tierName?: string;
createdAt?: string;
expireAt?: string;
isOneTime?: boolean;
provider?: ProviderName | string;
/**
* Raw data from provider
*/
raw?: any;
}
declare const outputFormats: readonly ["svg", "png", "webp", "json"];
type OutputFormat = typeof outputFormats[number];
type ProviderName = 'github' | 'patreon' | 'opencollective' | 'afdian' | 'polar' | 'liberapay' | 'githubContributors' | 'gitlabContributors' | 'crowdinContributors' | 'githubContributions';
type GitHubAccountType = 'user' | 'organization';
interface ProvidersConfig {
github?: {
/**
* User id of your GitHub account.
*
* Will read from `CONTRIBKIT_GITHUB_LOGIN` environment variable if not set.
*/
login?: string;
/**
* GitHub Token that have access to your sponsorships.
*
* Will read from `CONTRIBKIT_GITHUB_TOKEN` environment variable if not set.
*
* @deprecated It's not recommended set this value directly, pass from env or use `.env` file.
*/
token?: string;
/**
* The account type for sponsorships.
*
* Possible values are `user`(default) and `organization`.
* Will read from `CONTRIBKIT_GITHUB_TYPE` environment variable if not set.
*/
type?: GitHubAccountType;
};
patreon?: {
/**
* Patreon Token that have access to your sponsorships.
*
* Will read from `CONTRIBKIT_PATREON_TOKEN` environment variable if not set.
*
* @deprecated It's not recommended set this value directly, pass from env or use `.env` file.
*/
token?: string;
};
opencollective?: {
/**
* Api key of your OpenCollective account.
*
* Will read from `CONTRIBKIT_OPENCOLLECTIVE_KEY` environment variable if not set.
*
* @deprecated It's not recommended set this value directly, pass from env or use `.env` file.
*/
key?: string;
/**
* The id of your account.
*
* Will read from `CONTRIBKIT_OPENCOLLECTIVE_ID` environment variable if not set.
*/
id?: string;
/**
* The slug of your account.
*
* Will read from `CONTRIBKIT_OPENCOLLECTIVE_SLUG` environment variable if not set.
*/
slug?: string;
/**
* The GitHub handle of your account.
*
* Will read from `CONTRIBKIT_OPENCOLLECTIVE_GH_HANDLE` environment variable if not set.
*/
githubHandle?: string;
type?: string;
};
afdian?: {
/**
* The userId of your Afdian.
*
* Will read from `CONTRIBKIT_AFDIAN_USER_ID` environment variable if not set.
*
* @see https://afdian.net/dashboard/dev
*/
userId?: string;
/**
* Afdian Token that have access to your sponsorships.
*
* Will read from `CONTRIBKIT_AFDIAN_TOKEN` environment variable if not set.
*
* @see https://afdian.net/dashboard/dev
* @deprecated It's not recommended set this value directly, pass from env or use `.env` file.
*/
token?: string;
/**
* Exchange rate of USD to CNY
*
* @default 6.5
*/
exchangeRate?: number;
/**
* Include one-time purchases
* @default true
*/
includePurchases?: boolean;
/**
* One-time purchase effectivity period in days
* @default 30
*/
purchaseEffectivity?: number;
};
polar?: {
/**
* Polar token that have access to your sponsorships.
*
* Will read from `CONTRIBKIT_POLAR_TOKEN` environment variable if not set.
*
* @see https://polar.sh/settings
* @deprecated It's not recommended set this value directly, pass from env or use `.env` file.
*/
token?: string;
/**
* The name of the organization to fetch sponsorships from. If not set, it will fetch the sponsorships of the user.
*
* Will read from `CONTRIBKIT_POLAR_ORGANIZATION` environment variable if not set.
*/
organization?: string;
};
liberapay?: {
/**
* The name of the Liberapay profile.
*
* Will read from `CONTRIBKIT_LIBERAPAY_LOGIN` environment variable if not set.
*/
login?: string;
};
githubContributors?: {
/**
* User id of your GitHub account.
*
* Will read from `CONTRIBKIT_GITHUB_CONTRIBUTORS_LOGIN` environment variable if not set.
*/
login?: string;
/**
* GitHub Token that have access to your sponsorships.
*
* Will read from `CONTRIBKIT_GITHUB_CONTRIBUTORS_TOKEN` environment variable if not set.
*
* @deprecated It's not recommended set this value directly, pass from env or use `.env` file.
*/
token?: string;
/**
* The minimum number of contributions to be considered a sponsor.
*
* @default 1
*/
minContributions?: number;
/**
* The repository to fetch contributors from.
*
* Will read from `CONTRIBKIT_GITHUB_CONTRIBUTORS_REPO` environment variable if not set.
*/
repo?: string;
};
gitlabContributors?: {
/**
* Gitlab Token that have access contributors.
*
* Will read from `CONTRIBKIT_GITLAB_CONTRIBUTORS_TOKEN` environment variable if not set.
*
* @deprecated It's not recommended set this value directly, pass from env or use `.env` file.
*/
token?: string;
/**
* The minimum number of contributions to be considered a sponsor.
*
* @default 1
*/
minContributions?: number;
/**
* The repository ID to fetch contributors from.
*
* Will read from `CONTRIBKIT_GITLAB_CONTRIBUTORS_REPO_ID` environment variable if not set.
*/
repoId?: number;
};
crowdinContributors?: {
/**
* The Crowdin API token.
*
* Will read from `CONTRIBKIT_CROWDIN_TOKEN` environment variable if not set.
*/
token?: string;
/**
* The project id on Crowdin.
*
* Will read from `CONTRIBKIT_CROWDIN_PROJECT_ID` environment variable if not set.
*/
projectId?: number;
/**
* The minimum number of translations to be considered a sponsor.
*
* @default 100
*/
minTranslations?: number;
};
githubContributions?: {
/**
* GitHub user login to fetch contributions for.
*
* Will read from `CONTRIBKIT_GITHUB_CONTRIBUTIONS_LOGIN` environment variable if not set.
*/
login?: string;
/**
* GitHub Token that has access to read user contributions.
*
* Will read from `CONTRIBKIT_GITHUB_CONTRIBUTIONS_TOKEN` environment variable if not set.
*
* @deprecated It's not recommended set this value directly, pass from env or use `.env` file.
*/
token?: string;
/**
* Cap the maximum contribution count per organization/user.
* Useful to prevent one dominant contributor from overshadowing others in visualizations.
*
* @example 100 // Cap all contributions at 100 PRs max
*/
maxContributions?: number;
/**
* Apply logarithmic scaling to contribution counts.
* Useful to reduce the visual dominance of high contributors while maintaining relative differences.
*
* @default false
*/
logarithmicScaling?: boolean;
};
}
interface ContribkitRenderOptions {
/**
* Name of exported files
*
* @default 'sponsors'
*/
name?: string;
/**
* Renderer to use
*
* @default 'tiers'
*/
renderer?: 'tiers' | 'circles';
/**
* Output formats
*
* @default ['json', 'svg', 'png']
*/
formats?: OutputFormat[];
/**
* Compose the SVG
*/
customComposer?: (composer: SvgComposer, sponsors: Sponsorship[], config: ContribkitConfig) => PromiseLike<void> | void;
/**
* Filter of sponsorships to render in the final image.
*/
filter?: (sponsor: Sponsorship, all: Sponsorship[]) => boolean | void;
/**
* Tiers
*
* Only effective when using `tiers` renderer.
*/
tiers?: Tier[];
/**
* Options for rendering circles
*
* Only effective when using `circles` renderer.
*/
circles?: CircleRenderOptions;
/**
* Width of the image.
*
* @default 800
*/
width?: number;
/**
* Padding of image container
*/
padding?: {
top?: number;
bottom?: number;
};
/**
* Inline CSS of generated SVG
*/
svgInlineCSS?: string;
/**
* Whether to display the private sponsors
*
* @default false
*/
includePrivate?: boolean;
/**
* Whether to display the past sponsors
* Currently only works with GitHub provider
*
* @default auto detect based on tiers
*/
includePastSponsors?: boolean;
/**
* Format of embedded images
*
* @default 'webp'
*/
imageFormat?: ImageFormat;
/**
* Hook to modify sponsors data before rendering.
*/
onBeforeRenderer?: (sponsors: Sponsorship[]) => PromiseLike<void | Sponsorship[]> | void | Sponsorship[];
/**
* Hook to get or modify the SVG before writing.
*/
onSvgGenerated?: (svg: string) => PromiseLike<string | void | undefined | null> | string | void | undefined | null;
}
interface ContribkitConfig extends ProvidersConfig, ContribkitRenderOptions {
/**
* @deprecated use `github.login` instead
*/
login?: string;
/**
* @deprecated use `github.token` instead
*/
token?: string;
/**
* @default auto detect based on the config provided
*/
providers?: (ProviderName | Provider)[];
/**
* By pass cache
*/
force?: boolean;
/**
* Path to cache file
*
* @default './contribkit/.cache.json'
*/
cacheFile?: string;
/**
* Directory of output files.
*
* @default './contribkit'
*/
outputDir?: string;
/**
* Replace links in the sponsors data.
*/
replaceLinks?: Record<string, string> | (((sponsor: Sponsorship) => string) | Record<string, string>)[];
/**
* Replace avatar link in the sponsors data.
*/
replaceAvatars?: Record<string, string> | (((sponsor: Sponsorship) => string) | Record<string, string>)[];
/**
* Merge multiple sponsors, useful for combining sponsors from different providers.
*
* @example
* ```js
* mergeSponsors: [
* // Array of sponsor matchers
* [{ login: 'antfu', provider: 'github' }, { login: 'antfu', provider: 'patreon' }],
* // custom functions to find matched sponsors
* (sponsor, allSponsors) => {
* return allSponsors.filter(s => s.sponsor.login === sponsor.sponsor.login)
* }
* ]
* ```
*/
mergeSponsors?: (SponsorMatcher[] | ((sponsor: Sponsorship, allSponsors: Sponsorship[]) => Sponsorship[] | void))[];
/**
* Merge sponsorships from same sponsor on different providers,
* based on their connection account on each platform.
*
* @default false
*/
sponsorsAutoMerge?: boolean;
/**
* Hook to modify sponsors data for each provider.
*/
onSponsorsFetched?: (sponsors: Sponsorship[], provider: ProviderName | string) => PromiseLike<void | Sponsorship[]> | void | Sponsorship[];
/**
* Hook to modify merged sponsors data before fetching the avatars.
*/
onSponsorsAllFetched?: (sponsors: Sponsorship[]) => PromiseLike<void | Sponsorship[]> | void | Sponsorship[];
/**
* Hook to modify sponsors data before rendering.
*/
onSponsorsReady?: (sponsors: Sponsorship[]) => PromiseLike<void | Sponsorship[]> | void | Sponsorship[];
/**
* Url to fallback avatar.
* Setting false to disable fallback avatar.
*/
fallbackAvatar?: string | false | Buffer$1 | Promise<Buffer$1>;
/**
* Configs for multiple renders
*/
renders?: ContribkitRenderOptions[];
/**
* Prorates one-time to the current month's tier
*/
prorateOnetime?: boolean;
}
interface SponsorMatcher extends Partial<Pick<Sponsor, 'login' | 'name' | 'type'>> {
provider?: ProviderName | string;
}
type ContribkitMainConfig = Omit<ContribkitConfig, keyof ContribkitRenderOptions>;
interface ContribkitRenderer {
name: string;
renderSVG: (config: Required<ContribkitRenderOptions>, sponsors: Sponsorship[]) => Promise<string>;
}
interface CircleRenderOptions {
/**
* Min radius for sponsors
*
* @default 10
*/
radiusMin?: number;
/**
* Max radius for sponsors
*
* @default 300
*/
radiusMax?: number;
/**
* Radius for past sponsors
*
* @default 5
*/
radiusPast?: number;
/**
* Custom function to calculate the weight of the sponsor.
*
* When provided, `radiusMin`, `radiusMax` and `radiusPast` will be ignored.
*/
weightInterop?: (sponsor: Sponsorship, maxAmount: number) => number;
}
interface Tier {
/**
* The lower bound of the tier (inclusive)
*/
monthlyDollars?: number;
title?: string;
preset?: BadgePreset;
padding?: {
top?: number;
bottom?: number;
};
/**
* Replace the default composer with your own.
*/
compose?: (composer: SvgComposer, sponsors: Sponsorship[], config: ContribkitConfig) => void;
/**
* Compose the SVG before the main composer.
*/
composeBefore?: (composer: SvgComposer, tierSponsors: Sponsorship[], config: ContribkitConfig) => void;
/**
* Compose the SVG after the main composer.
*/
composeAfter?: (composer: SvgComposer, tierSponsors: Sponsorship[], config: ContribkitConfig) => void;
}
declare const defaultTiers: Tier[];
declare const defaultInlineCSS = "\ntext {\n font-weight: 300;\n font-size: 14px;\n fill: #777777;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\n}\n.contribkit-link {\n cursor: pointer;\n}\n.contribkit-tier-title {\n font-weight: 500;\n font-size: 20px;\n}\n";
declare const defaultConfig: ContribkitConfig;
declare const FALLBACK_AVATAR: Promise<Buffer<ArrayBufferLike>>;
declare const tierPresets: {
none: BadgePreset;
xs: BadgePreset;
small: BadgePreset;
base: BadgePreset;
medium: BadgePreset;
large: BadgePreset;
xl: BadgePreset;
};
/**
* @deprecated Use `tierPresets` instead
*/
declare const presets: {
none: BadgePreset;
xs: BadgePreset;
small: BadgePreset;
base: BadgePreset;
medium: BadgePreset;
large: BadgePreset;
xl: BadgePreset;
};
declare function defineConfig(config: ContribkitConfig): ContribkitConfig;
declare function loadConfig(inlineConfig?: ContribkitConfig): Promise<Required<ContribkitConfig>>;
declare function partitionTiers(sponsors: Sponsorship[], tiers: Tier[], includePastSponsors?: boolean): TierPartition[];
declare function resolveAvatars(ships: Sponsorship[], getFallbackAvatar: ContribkitConfig['fallbackAvatar'], t?: consola.ConsolaInstance): Promise<void[]>;
declare function resizeImage(image: Buffer$1, size: number | undefined, format: ImageFormat): Promise<Buffer$1<ArrayBufferLike>>;
declare function svgToPng(svg: string): Promise<Buffer$1<ArrayBufferLike>>;
declare function svgToWebp(svg: string): Promise<Buffer$1<ArrayBufferLike>>;
declare const GitHubProvider: Provider;
declare function fetchGitHubSponsors(token: string, login: string, type: GitHubAccountType, config: ContribkitConfig): Promise<Sponsorship[]>;
declare function makeQuery(login: string, type: GitHubAccountType, activeOnly?: boolean, cursor?: string): string;
declare const ProvidersMap: {
github: Provider;
patreon: Provider;
opencollective: Provider;
afdian: Provider;
polar: Provider;
liberapay: Provider;
githubContributors: Provider;
githubContributions: Provider;
gitlabContributors: Provider;
crowdinContributors: Provider;
};
declare function guessProviders(config: ContribkitConfig): ProviderName[];
declare function resolveProviders(names: (ProviderName | Provider)[]): Provider[];
declare function fetchSponsors(config: ContribkitConfig): Promise<Sponsorship[]>;
export { FALLBACK_AVATAR, GitHubProvider, ProvidersMap, SvgComposer, defaultConfig, defaultInlineCSS, defaultTiers, defineConfig, fetchGitHubSponsors, fetchSponsors, genSvgImage, generateBadge, guessProviders, loadConfig, makeQuery, outputFormats, partitionTiers, presets, resizeImage, resolveAvatars, resolveProviders, svgToPng, svgToWebp, tierPresets };
export type { BadgePreset, CircleRenderOptions, ContribkitConfig, ContribkitMainConfig, ContribkitRenderOptions, ContribkitRenderer, GitHubAccountType, ImageFormat, OutputFormat, Provider, ProviderName, ProvidersConfig, Sponsor, SponsorMatcher, Sponsorship, Tier, TierPartition };