@lizardbyte/contribkit 2025.315.185528 → 2025.327.11019

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,18 +11,45 @@ This is a fork of [sponsorkit](https://github.com/antfu-collective/sponsorkit) t
11
11
 
12
12
  Supports:
13
13
 
14
- - [**GitHub Sponsors**](https://github.com/sponsors)
15
- - [**Patreon**](https://www.patreon.com/)
16
- - [**OpenCollective**](https://opencollective.com/)
17
- - [**Afdian**](https://afdian.com/)
18
- - [**Polar**](https://polar.sh/)
19
- - [**Liberapay**](https://liberapay.com/)
14
+ - Contributors:
15
+ - [**CrowdIn**](https://crowdin.com)
16
+ - [**GitHub**](https://github.com)
17
+ - [**Gitlab**](https://gitlab.com)
18
+ - Sponsors:
19
+ - [**GitHub Sponsors**](https://github.com/sponsors)
20
+ - [**Patreon**](https://www.patreon.com/)
21
+ - [**OpenCollective**](https://opencollective.com/)
22
+ - [**Afdian**](https://afdian.com/)
23
+ - [**Polar**](https://polar.sh/)
24
+ - [**Liberapay**](https://liberapay.com/)
20
25
 
21
26
  ## Usage
22
27
 
23
28
  Create `.env` file with:
24
29
 
25
30
  ```ini
31
+ ;; Contributors
32
+
33
+ ; CrowdInContributors provider.
34
+ CONTRIBKIT_CROWDIN_TOKEN=
35
+ CONTRIBKIT_CROWDIN_PROJECT_ID=
36
+ CONTRIBKIT_CROWDIN_MIN_TRANSLATIONS=1
37
+
38
+ ; GitHubContributors provider.
39
+ ; Token requires the `public_repo` and `read:user` scopes.
40
+ CONTRIBKIT_GITHUB_CONTRIBUTORS_TOKEN=
41
+ CONTRIBKIT_GITHUB_CONTRIBUTORS_LOGIN=
42
+ CONTRIBKIT_GITHUB_CONTRIBUTORS_MIN=1
43
+ CONTRIBKIT_GITHUB_CONTRIBUTORS_REPO=
44
+
45
+ ; GitlabContributors provider.
46
+ ; Token requires the `read_api` and `read_user` scopes.
47
+ CONTRIBKIT_GITLAB_CONTRIBUTORS_TOKEN=
48
+ CONTRIBKIT_GITLAB_CONTRIBUTORS_MIN=1
49
+ CONTRIBKIT_GITLAB_CONTRIBUTORS_REPO_ID=
50
+
51
+ ;; Sponsors
52
+
26
53
  ; GitHub provider.
27
54
  ; Token requires the `read:user` and `read:org` scopes.
28
55
  CONTRIBKIT_GITHUB_TOKEN=
@@ -64,6 +91,11 @@ CONTRIBKIT_LIBERAPAY_LOGIN=
64
91
 
65
92
  > Only one provider is required to be configured.
66
93
 
94
+ > ![NOTE]
95
+ > The contributor providers are intended to be separated from each other, unlike the sponsor providers.
96
+ > This will require different env variables to be set for each provider, and to be created from separate
97
+ > commands.
98
+
67
99
  Run:
68
100
 
69
101
  ```base
@@ -77,9 +77,8 @@ class Queue {
77
77
  }
78
78
 
79
79
  * drain() {
80
- let current;
81
- while ((current = this.dequeue()) !== undefined) {
82
- yield current;
80
+ while (this.#head) {
81
+ yield this.dequeue();
83
82
  }
84
83
  }
85
84
  }
package/dist/cli.d.mts CHANGED
@@ -1,2 +1,2 @@
1
1
 
2
- export { }
2
+ export { };
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import cac from 'cac';
2
- import { S as SvgComposer, i as generateBadge, p as partitionTiers, t as tierPresets, v as version, l as loadConfig, k as resolveProviders, j as guessProviders, r as resolveAvatars, q as outputFormats, s as svgToPng, g as svgToWebp } from './shared/contribkit.QISHqB4U.mjs';
2
+ import { S as SvgComposer, i as generateBadge, p as partitionTiers, t as tierPresets, v as version, l as loadConfig, k as resolveProviders, j as guessProviders, r as resolveAvatars, q as outputFormats, s as svgToPng, g as svgToWebp } from './shared/contribkit.ClLqkpuL.mjs';
3
3
  import fs from 'node:fs';
4
4
  import fsp from 'node:fs/promises';
5
5
  import { resolve, dirname, relative, join } from 'node:path';
@@ -9,9 +9,10 @@ import { consola } from 'consola';
9
9
  import { Buffer } from 'node:buffer';
10
10
  import 'unconfig';
11
11
  import 'dotenv';
12
+ import 'node:crypto';
12
13
  import 'ofetch';
13
14
  import 'sharp';
14
- import 'node:crypto';
15
+ import '@crowdin/crowdin-api-client';
15
16
 
16
17
  function notNullish(v) {
17
18
  return v != null;
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Buffer as Buffer$1 } from 'node:buffer';
2
- import * as consola from 'consola';
2
+ import { consola } from 'consola';
3
3
 
4
4
  declare function genSvgImage(x: number, y: number, size: number, radius: number, base64Image: string, imageFormat: ImageFormat): string;
5
5
  declare function generateBadge(x: number, y: number, sponsor: Sponsor, preset: BadgePreset, radius: number, imageFormat: ImageFormat): Promise<string>;
@@ -83,7 +83,7 @@ interface Sponsorship {
83
83
  }
84
84
  declare const outputFormats: readonly ["svg", "png", "webp", "json"];
85
85
  type OutputFormat = typeof outputFormats[number];
86
- type ProviderName = 'github' | 'patreon' | 'opencollective' | 'afdian' | 'polar' | 'liberapay';
86
+ type ProviderName = 'github' | 'patreon' | 'opencollective' | 'afdian' | 'polar' | 'liberapay' | 'githubContributors' | 'gitlabContributors' | 'crowdinContributors';
87
87
  type GitHubAccountType = 'user' | 'organization';
88
88
  interface ProvidersConfig {
89
89
  github?: {
@@ -208,6 +208,76 @@ interface ProvidersConfig {
208
208
  */
209
209
  login?: string;
210
210
  };
211
+ githubContributors?: {
212
+ /**
213
+ * User id of your GitHub account.
214
+ *
215
+ * Will read from `CONTRIBKIT_GITHUB_CONTRIBUTORS_LOGIN` environment variable if not set.
216
+ */
217
+ login?: string;
218
+ /**
219
+ * GitHub Token that have access to your sponsorships.
220
+ *
221
+ * Will read from `CONTRIBKIT_GITHUB_CONTRIBUTORS_TOKEN` environment variable if not set.
222
+ *
223
+ * @deprecated It's not recommended set this value directly, pass from env or use `.env` file.
224
+ */
225
+ token?: string;
226
+ /**
227
+ * The minimum number of contributions to be considered a sponsor.
228
+ *
229
+ * @default 1
230
+ */
231
+ minContributions?: number;
232
+ /**
233
+ * The repository to fetch contributors from.
234
+ *
235
+ * Will read from `CONTRIBKIT_GITHUB_CONTRIBUTORS_REPO` environment variable if not set.
236
+ */
237
+ repo?: string;
238
+ };
239
+ gitlabContributors?: {
240
+ /**
241
+ * Gitlab Token that have access contributors.
242
+ *
243
+ * Will read from `CONTRIBKIT_GITLAB_CONTRIBUTORS_TOKEN` environment variable if not set.
244
+ *
245
+ * @deprecated It's not recommended set this value directly, pass from env or use `.env` file.
246
+ */
247
+ token?: string;
248
+ /**
249
+ * The minimum number of contributions to be considered a sponsor.
250
+ *
251
+ * @default 1
252
+ */
253
+ minContributions?: number;
254
+ /**
255
+ * The repository ID to fetch contributors from.
256
+ *
257
+ * Will read from `CONTRIBKIT_GITLAB_CONTRIBUTORS_REPO_ID` environment variable if not set.
258
+ */
259
+ repoId?: number;
260
+ };
261
+ crowdinContributors?: {
262
+ /**
263
+ * The Crowdin API token.
264
+ *
265
+ * Will read from `CONTRIBKIT_CROWDIN_TOKEN` environment variable if not set.
266
+ */
267
+ token?: string;
268
+ /**
269
+ * The project id on Crowdin.
270
+ *
271
+ * Will read from `CONTRIBKIT_CROWDIN_PROJECT_ID` environment variable if not set.
272
+ */
273
+ projectId?: number;
274
+ /**
275
+ * The minimum number of translations to be considered a sponsor.
276
+ *
277
+ * @default 100
278
+ */
279
+ minTranslations?: number;
280
+ };
211
281
  }
212
282
  interface ContribkitRenderOptions {
213
283
  /**
@@ -486,9 +556,13 @@ declare const ProvidersMap: {
486
556
  afdian: Provider;
487
557
  polar: Provider;
488
558
  liberapay: Provider;
559
+ githubContributors: Provider;
560
+ gitlabContributors: Provider;
561
+ crowdinContributors: Provider;
489
562
  };
490
563
  declare function guessProviders(config: ContribkitConfig): ProviderName[];
491
564
  declare function resolveProviders(names: (ProviderName | Provider)[]): Provider[];
492
565
  declare function fetchSponsors(config: ContribkitConfig): Promise<Sponsorship[]>;
493
566
 
494
- export { type BadgePreset, type CircleRenderOptions, type ContribkitConfig, type ContribkitMainConfig, type ContribkitRenderOptions, type ContribkitRenderer, FALLBACK_AVATAR, type GitHubAccountType, GitHubProvider, type ImageFormat, type OutputFormat, type Provider, type ProviderName, type ProvidersConfig, ProvidersMap, type Sponsor, type SponsorMatcher, type Sponsorship, SvgComposer, type Tier, type TierPartition, defaultConfig, defaultInlineCSS, defaultTiers, defineConfig, fetchGitHubSponsors, fetchSponsors, genSvgImage, generateBadge, guessProviders, loadConfig, makeQuery, outputFormats, partitionTiers, presets, resizeImage, resolveAvatars, resolveProviders, svgToPng, svgToWebp, tierPresets };
567
+ 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 };
568
+ export type { BadgePreset, CircleRenderOptions, ContribkitConfig, ContribkitMainConfig, ContribkitRenderOptions, ContribkitRenderer, GitHubAccountType, ImageFormat, OutputFormat, Provider, ProviderName, ProvidersConfig, Sponsor, SponsorMatcher, Sponsorship, Tier, TierPartition };
package/dist/index.mjs CHANGED
@@ -1,9 +1,10 @@
1
- export { F as FALLBACK_AVATAR, G as GitHubProvider, P as ProvidersMap, S as SvgComposer, c as defaultConfig, b as defaultInlineCSS, a as defaultTiers, d as defineConfig, n as fetchGitHubSponsors, m as fetchSponsors, h as genSvgImage, i as generateBadge, j as guessProviders, l as loadConfig, o as makeQuery, q as outputFormats, p as partitionTiers, e as presets, f as resizeImage, r as resolveAvatars, k as resolveProviders, s as svgToPng, g as svgToWebp, t as tierPresets } from './shared/contribkit.QISHqB4U.mjs';
1
+ export { F as FALLBACK_AVATAR, G as GitHubProvider, P as ProvidersMap, S as SvgComposer, c as defaultConfig, b as defaultInlineCSS, a as defaultTiers, d as defineConfig, n as fetchGitHubSponsors, m as fetchSponsors, h as genSvgImage, i as generateBadge, j as guessProviders, l as loadConfig, o as makeQuery, q as outputFormats, p as partitionTiers, e as presets, f as resizeImage, r as resolveAvatars, k as resolveProviders, s as svgToPng, g as svgToWebp, t as tierPresets } from './shared/contribkit.ClLqkpuL.mjs';
2
2
  import 'unconfig';
3
3
  import 'node:process';
4
4
  import 'dotenv';
5
+ import 'node:crypto';
5
6
  import 'node:buffer';
6
7
  import 'consola';
7
8
  import 'ofetch';
8
9
  import 'sharp';
9
- import 'node:crypto';
10
+ import '@crowdin/crowdin-api-client';
@@ -1,11 +1,12 @@
1
1
  import { loadConfig as loadConfig$1 } from 'unconfig';
2
2
  import process from 'node:process';
3
3
  import dotenv from 'dotenv';
4
+ import crypto, { createHash } from 'node:crypto';
4
5
  import { Buffer } from 'node:buffer';
5
6
  import { consola } from 'consola';
6
7
  import { $fetch, ofetch } from 'ofetch';
7
8
  import sharp from 'sharp';
8
- import { createHash } from 'node:crypto';
9
+ import { ProjectsGroups, Reports } from '@crowdin/crowdin-api-client';
9
10
 
10
11
  const none = {
11
12
  avatar: {
@@ -179,12 +180,28 @@ function loadEnv() {
179
180
  liberapay: {
180
181
  login: process.env.CONTRIBKIT_LIBERAPAY_LOGIN || process.env.LIBERAPAY_LOGIN
181
182
  },
182
- outputDir: process.env.CONTRIBKIT_DIR
183
+ outputDir: process.env.CONTRIBKIT_DIR,
184
+ githubContributors: {
185
+ login: process.env.CONTRIBKIT_GITHUB_CONTRIBUTORS_LOGIN,
186
+ token: process.env.CONTRIBKIT_GITHUB_CONTRIBUTORS_TOKEN,
187
+ minContributions: Number(process.env.CONTRIBKIT_GITHUB_CONTRIBUTORS_MIN) || 1,
188
+ repo: process.env.CONTRIBKIT_GITHUB_CONTRIBUTORS_REPO
189
+ },
190
+ gitlabContributors: {
191
+ token: process.env.CONTRIBKIT_GITLAB_CONTRIBUTORS_TOKEN,
192
+ minContributions: Number(process.env.CONTRIBKIT_GITLAB_CONTRIBUTORS_MIN) || 1,
193
+ repoId: Number(process.env.CONTRIBKIT_GITLAB_CONTRIBUTORS_REPO_ID)
194
+ },
195
+ crowdinContributors: {
196
+ token: process.env.CONTRIBKIT_CROWDIN_TOKEN,
197
+ projectId: Number(process.env.CONTRIBKIT_CROWDIN_PROJECT_ID),
198
+ minTranslations: Number(process.env.CONTRIBKIT_CROWDIN_MIN_TRANSLATIONS) || 1
199
+ }
183
200
  };
184
201
  return JSON.parse(JSON.stringify(config));
185
202
  }
186
203
 
187
- const version = "2025.315.185528";
204
+ const version = "2025.327.11019";
188
205
 
189
206
  async function fetchImage(url) {
190
207
  const arrayBuffer = await $fetch(url, {
@@ -265,10 +282,16 @@ async function loadConfig(inlineConfig = {}) {
265
282
  const { config = {} } = await loadConfig$1({
266
283
  sources: [
267
284
  {
268
- files: "sponsorkit.config"
285
+ files: "contrib.config"
269
286
  },
270
287
  {
271
288
  files: "contribkit.config"
289
+ },
290
+ {
291
+ files: "sponsor.config"
292
+ },
293
+ {
294
+ files: "sponsorkit.config"
272
295
  }
273
296
  ],
274
297
  merge: true
@@ -321,9 +344,8 @@ function partitionTiers(sponsors, tiers, includePastSponsors) {
321
344
  return tierMappings;
322
345
  }
323
346
 
324
- let id = 0;
325
347
  function genSvgImage(x, y, size, radius, base64Image, imageFormat) {
326
- const cropId = `c${id++}`;
348
+ const cropId = `c${crypto.createHash("md5").update(base64Image).digest("hex").slice(0, 6)}`;
327
349
  return `
328
350
  <clipPath id="${cropId}">
329
351
  <rect x="${x}" y="${y}" width="${size}" height="${size}" rx="${size * radius}" ry="${size * radius}" />
@@ -503,6 +525,65 @@ function md5(token, params, ts, userId) {
503
525
  return createHash("md5").update(`${token}params${params}ts${ts}user_id${userId}`).digest("hex");
504
526
  }
505
527
 
528
+ const CrowdinContributorsProvider = {
529
+ name: "crowdinContributors",
530
+ fetchSponsors(config) {
531
+ return fetchCrowdinContributors(
532
+ config.crowdinContributors?.token || config.token,
533
+ config.crowdinContributors?.projectId || 0,
534
+ config.crowdinContributors?.minTranslations || 1
535
+ );
536
+ }
537
+ };
538
+ async function fetchCrowdinContributors(token, projectId, minTranslations = 1) {
539
+ if (!token)
540
+ throw new Error("Crowdin token is required");
541
+ if (!projectId)
542
+ throw new Error("Crowdin project ID is required");
543
+ const credentials = {
544
+ token
545
+ };
546
+ const projectsGroups = new ProjectsGroups(credentials);
547
+ const project = await projectsGroups.getProject(projectId);
548
+ const reports = new Reports(credentials);
549
+ const dateTo = (/* @__PURE__ */ new Date()).toISOString();
550
+ const dateFrom = project.data.createdAt;
551
+ const createReportRequestBody = {
552
+ name: "top-members",
553
+ schema: {
554
+ unit: "words",
555
+ format: "json",
556
+ dateFrom,
557
+ dateTo
558
+ }
559
+ };
560
+ const createReport = await reports.generateReport(projectId, createReportRequestBody);
561
+ await new Promise((resolve) => setTimeout(resolve, 5e3));
562
+ const report = await reports.downloadReport(projectId, createReport.data.identifier);
563
+ const reportRaw = await fetch(report.data.url);
564
+ const reportData = await reportRaw.json();
565
+ const contributors = reportData.data.filter((entry) => entry.translated > minTranslations).map((entry) => ({
566
+ member: entry.user,
567
+ translations: entry.translated
568
+ }));
569
+ return contributors.filter(Boolean).map(({ member, translations }) => ({
570
+ sponsor: {
571
+ type: "User",
572
+ login: member.username,
573
+ name: member.username,
574
+ // fullName is also available
575
+ avatarUrl: member.avatarUrl,
576
+ linkUrl: `https://crowdin.com/profile/${member.username}`
577
+ },
578
+ isOneTime: false,
579
+ monthlyDollars: translations,
580
+ privacyLevel: "PUBLIC",
581
+ tierName: "Translator",
582
+ createdAt: member.joinedAt,
583
+ provider: "crowdinContributors"
584
+ }));
585
+ }
586
+
506
587
  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
507
588
  const DATA_URL_DEFAULT_MIME_TYPE = 'text/plain';
508
589
  const DATA_URL_DEFAULT_CHARSET = 'us-ascii';
@@ -939,6 +1020,149 @@ function makeQuery(login, type, activeOnly = true, cursor) {
939
1020
  }`;
940
1021
  }
941
1022
 
1023
+ const GitHubContributorsProvider = {
1024
+ name: "githubContributors",
1025
+ fetchSponsors(config) {
1026
+ if (!config.githubContributors?.repo)
1027
+ throw new Error("GitHub repository is required");
1028
+ return fetchGitHubContributors(
1029
+ config.githubContributors?.token || config.token,
1030
+ config.githubContributors?.login || config.login,
1031
+ config.githubContributors.repo,
1032
+ config.githubContributors?.minContributions
1033
+ );
1034
+ }
1035
+ };
1036
+ async function fetchGitHubContributors(token, login, repo, minContributions = 1) {
1037
+ if (!token)
1038
+ throw new Error("GitHub token is required");
1039
+ if (!login)
1040
+ throw new Error("GitHub login is required");
1041
+ if (!repo)
1042
+ throw new Error("GitHub repository is required");
1043
+ const allContributors = [];
1044
+ let page = 1;
1045
+ let hasNextPage = true;
1046
+ while (hasNextPage) {
1047
+ const response = await $fetch(
1048
+ `https://api.github.com/repos/${login}/${repo}/contributors`,
1049
+ {
1050
+ query: {
1051
+ page: String(page),
1052
+ per_page: "100"
1053
+ },
1054
+ headers: {
1055
+ Authorization: `bearer ${token}`,
1056
+ Accept: "application/vnd.github.v3+json"
1057
+ }
1058
+ }
1059
+ );
1060
+ if (!response || !response.length)
1061
+ break;
1062
+ allContributors.push(...response);
1063
+ hasNextPage = response.length === 100;
1064
+ page++;
1065
+ }
1066
+ return allContributors.filter(
1067
+ (contributor) => contributor.type === "User" && contributor.contributions >= minContributions
1068
+ ).map((contributor) => ({
1069
+ sponsor: {
1070
+ type: "User",
1071
+ login: contributor.login,
1072
+ name: contributor.login,
1073
+ avatarUrl: contributor.avatar_url,
1074
+ linkUrl: contributor.url
1075
+ },
1076
+ isOneTime: false,
1077
+ monthlyDollars: contributor.contributions,
1078
+ privacyLevel: "PUBLIC",
1079
+ tierName: "Contributor",
1080
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1081
+ provider: "githubContributors"
1082
+ }));
1083
+ }
1084
+
1085
+ const GitlabContributorsProvider = {
1086
+ name: "gitlabContributors",
1087
+ fetchSponsors(config) {
1088
+ if (!config.gitlabContributors?.repoId)
1089
+ throw new Error("Gitlab repoId is required");
1090
+ return fetchGitlabContributors(
1091
+ config.gitlabContributors?.token || config.token,
1092
+ config.gitlabContributors.repoId,
1093
+ config.gitlabContributors?.minContributions
1094
+ );
1095
+ }
1096
+ };
1097
+ async function fetchGitlabContributors(token, repoId, minContributions = 1) {
1098
+ if (!token)
1099
+ throw new Error("Gitlab token is required");
1100
+ if (!repoId)
1101
+ throw new Error("Gitlab repoId is required");
1102
+ const allContributors = [];
1103
+ let page = 1;
1104
+ let hasNextPage = true;
1105
+ while (hasNextPage) {
1106
+ const response = await $fetch(
1107
+ `https://gitlab.com/api/v4/projects/${repoId}/repository/contributors`,
1108
+ {
1109
+ query: {
1110
+ page: String(page),
1111
+ per_page: "100",
1112
+ sort: "desc"
1113
+ },
1114
+ headers: {
1115
+ "PRIVATE-TOKEN": token,
1116
+ "Content-Type": "application/json"
1117
+ }
1118
+ }
1119
+ );
1120
+ if (!response || !response.length)
1121
+ break;
1122
+ allContributors.push(...response);
1123
+ hasNextPage = response.length === 100;
1124
+ page++;
1125
+ }
1126
+ const sponsorships = [];
1127
+ for (const contributor of allContributors) {
1128
+ if (contributor.commits < minContributions)
1129
+ continue;
1130
+ try {
1131
+ const userDetails = await $fetch("https://gitlab.com/api/v4/users", {
1132
+ query: {
1133
+ search: contributor.email
1134
+ },
1135
+ headers: {
1136
+ "PRIVATE-TOKEN": token,
1137
+ "Content-Type": "application/json"
1138
+ }
1139
+ });
1140
+ if (userDetails && userDetails.length > 0) {
1141
+ const user = userDetails[0];
1142
+ sponsorships.push({
1143
+ sponsor: {
1144
+ type: "User",
1145
+ login: user.username,
1146
+ name: user.username,
1147
+ // user.name is also available
1148
+ avatarUrl: user.avatar_url,
1149
+ linkUrl: user.web_url
1150
+ },
1151
+ isOneTime: false,
1152
+ monthlyDollars: contributor.commits,
1153
+ privacyLevel: "PUBLIC",
1154
+ tierName: "Contributor",
1155
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1156
+ provider: "gitlabContributors"
1157
+ });
1158
+ }
1159
+ } catch (error) {
1160
+ console.warn(`Failed to fetch user details for ${contributor.email}:`, error);
1161
+ }
1162
+ }
1163
+ return sponsorships;
1164
+ }
1165
+
942
1166
  const LiberapayProvider = {
943
1167
  name: "liberapay",
944
1168
  fetchSponsors(config) {
@@ -1409,7 +1633,10 @@ const ProvidersMap = {
1409
1633
  opencollective: OpenCollectiveProvider,
1410
1634
  afdian: AfdianProvider,
1411
1635
  polar: PolarProvider,
1412
- liberapay: LiberapayProvider
1636
+ liberapay: LiberapayProvider,
1637
+ githubContributors: GitHubContributorsProvider,
1638
+ gitlabContributors: GitlabContributorsProvider,
1639
+ crowdinContributors: CrowdinContributorsProvider
1413
1640
  };
1414
1641
  function guessProviders(config) {
1415
1642
  const items = [];
@@ -1425,6 +1652,12 @@ function guessProviders(config) {
1425
1652
  items.push("polar");
1426
1653
  if (config.liberapay && config.liberapay.login)
1427
1654
  items.push("liberapay");
1655
+ if (config.githubContributors?.login && config.githubContributors?.token)
1656
+ items.push("githubContributors");
1657
+ if (config.gitlabContributors?.token && config.gitlabContributors?.repoId)
1658
+ items.push("gitlabContributors");
1659
+ if (config.crowdinContributors?.token && config.crowdinContributors?.projectId)
1660
+ items.push("crowdinContributors");
1428
1661
  if (!items.length)
1429
1662
  items.push("github");
1430
1663
  return items;
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/LizardByte/contribkit.git"
7
7
  },
8
- "version": "2025.315.185528",
8
+ "version": "2025.327.11019",
9
9
  "description": "Toolkit for generating contributor images",
10
10
  "license": "MIT",
11
11
  "funding": "https://app.lizardbyte.dev",
@@ -46,6 +46,7 @@
46
46
  "release": "bumpp && pnpm publish"
47
47
  },
48
48
  "dependencies": {
49
+ "@crowdin/crowdin-api-client": "^1.41.2",
49
50
  "ansis": "^3.17.0",
50
51
  "cac": "^6.7.14",
51
52
  "consola": "^3.4.0",