Skip to content

Commit ac18969

Browse files
committed
credits
1 parent 1b0f666 commit ac18969

File tree

11 files changed

+1195
-1
lines changed

11 files changed

+1195
-1
lines changed

.vitepress/data/authors.data.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { Octokit } from "octokit";
2+
import { createContentLoader, DefaultTheme } from "vitepress";
3+
4+
const GITHUB_TOKEN = process.env.GITHUB_TOKEN || "";
5+
const octokit = new Octokit({ auth: GITHUB_TOKEN });
6+
7+
export default {
8+
async load() {
9+
const authors = new Map<string, { files: number; login: string }>();
10+
const authorsNoGitHub = new Map<string, { files: number; login: string }>();
11+
12+
const markdownData = await createContentLoader(["**/*.md"], {
13+
globOptions: {
14+
ignore: ["node_modules/**/*", "translated/**/*", "versions/**/*"],
15+
},
16+
}).load();
17+
18+
markdownData.forEach(async (file) => {
19+
file.frontmatter["authors"]?.forEach((login: string) => {
20+
const author = authors.get(login) || { login, files: 0 };
21+
author.files++;
22+
authors.set(login, author);
23+
});
24+
25+
file.frontmatter["authors-nogithub"]?.forEach((login: string) => {
26+
const author = authorsNoGitHub.get(login) || { login, files: 0 };
27+
author.files++;
28+
authorsNoGitHub.set(login, author);
29+
});
30+
});
31+
32+
const authorsArray = await Promise.all(
33+
Array.from(authors.values()).map(async (author) => {
34+
try {
35+
if (!GITHUB_TOKEN) throw new Error("GITHUB_TOKEN is unset");
36+
const { data } = await octokit.rest.users.getByUsername({
37+
username: author.login,
38+
});
39+
40+
return {
41+
avatar: data.avatar_url,
42+
links: [{ icon: "github", link: data.html_url }],
43+
name: data.login,
44+
number: author.files,
45+
} as DefaultTheme.TeamMember & { number: number };
46+
} catch (error) {
47+
//console.error(error);
48+
return {
49+
name: author.login,
50+
number: author.files,
51+
};
52+
}
53+
})
54+
);
55+
56+
const authorsNoGitHubArray = Array.from(authorsNoGitHub.values()).map(
57+
(author) =>
58+
({
59+
name: author.login,
60+
number: author.files,
61+
} as DefaultTheme.TeamMember & { number: number })
62+
);
63+
64+
return [
65+
...authorsArray.filter((author) => !!author),
66+
...authorsNoGitHubArray,
67+
]
68+
.sort((a, b) => a.name.localeCompare(b.name))
69+
.sort((a, b) => b.number - a.number);
70+
},
71+
};

.vitepress/data/committers.data.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { Octokit } from "octokit";
2+
import { DefaultTheme } from "vitepress";
3+
4+
const GITHUB_TOKEN = process.env.GITHUB_TOKEN || "";
5+
const octokit = new Octokit({ auth: GITHUB_TOKEN });
6+
7+
export default {
8+
async load() {
9+
const contributors = await (async () => {
10+
try {
11+
if (!GITHUB_TOKEN) throw new Error("GITHUB_TOKEN is unset");
12+
return await octokit.paginate(octokit.rest.repos.listContributors, {
13+
owner: "FabricMC",
14+
repo: "fabric-docs",
15+
});
16+
} catch (error) {
17+
console.error(error);
18+
return [];
19+
}
20+
})();
21+
22+
return contributors
23+
.filter(
24+
(contributor) =>
25+
contributor.login && contributor.login !== "FabricMCBot"
26+
)
27+
.map(
28+
(contributor) =>
29+
({
30+
avatar: contributor.avatar_url,
31+
links: [{ icon: "github", link: contributor.html_url }],
32+
name: contributor.login,
33+
number: contributor.contributions,
34+
} as DefaultTheme.TeamMember & { number: number })
35+
)
36+
.sort((a, b) => a.name.localeCompare(b.name))
37+
.sort((a, b) => b.number - a.number);
38+
},
39+
};
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { Octokit } from "octokit";
2+
import { DefaultTheme } from "vitepress";
3+
4+
const GITHUB_TOKEN = process.env.GITHUB_TOKEN || "";
5+
const octokit = new Octokit({ auth: GITHUB_TOKEN });
6+
7+
export default {
8+
async load() {
9+
const members = await (async () => {
10+
try {
11+
if (!GITHUB_TOKEN) throw new Error("GITHUB_TOKEN is unset");
12+
return await octokit.paginate(octokit.rest.teams.listMembersInOrg, {
13+
org: "FabricMC",
14+
team_slug: "documentation",
15+
});
16+
} catch (error) {
17+
console.error(error);
18+
return [];
19+
}
20+
})();
21+
22+
return (
23+
await Promise.all(
24+
members.map(async (member) => ({
25+
val: await (async () => {
26+
try {
27+
if (!GITHUB_TOKEN) throw new Error("GITHUB_TOKEN is unset");
28+
return await octokit.paginate(octokit.rest.orgs.listForUser, {
29+
username: member.login,
30+
});
31+
} catch (error) {
32+
console.error(error);
33+
return [{ login: "FabricMC" }];
34+
}
35+
})(),
36+
member,
37+
}))
38+
)
39+
)
40+
.filter(
41+
(result) =>
42+
result.val.map((org) => org.login).includes("FabricMC") &&
43+
result.member.login !== "FabricMCBot"
44+
)
45+
.map(
46+
(result) =>
47+
({
48+
avatar: result.member.avatar_url,
49+
links: [{ icon: "github", link: result.member.html_url }],
50+
name: result.member.login,
51+
} as DefaultTheme.TeamMember)
52+
)
53+
.sort((a, b) => a.name.localeCompare(b.name));
54+
},
55+
};
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import {
2+
default as Client,
3+
default as crowdin,
4+
} from "@crowdin/crowdin-api-client";
5+
import { DefaultTheme } from "vitepress";
6+
7+
const CROWDIN_TOKEN = process.env.CROWDIN_TOKEN || "";
8+
const PROJECT_ID = 647524;
9+
const { sourceFilesApi, reportsApi } = (() => {
10+
try {
11+
//@ts-expect-error https://github.com/crowdin/crowdin-api-client-js/issues/98
12+
return new crowdin.default({ token: CROWDIN_TOKEN }) as Client;
13+
} catch (error) {
14+
return { sourceFilesApi: {}, reportsApi: {} } as Client;
15+
}
16+
})();
17+
18+
export default {
19+
async load() {
20+
if (!CROWDIN_TOKEN) return [];
21+
const { data: directories } = await sourceFilesApi.listProjectDirectories(
22+
PROJECT_ID,
23+
{
24+
filter: "fabric-docs",
25+
}
26+
);
27+
28+
const { data: files } = await sourceFilesApi
29+
.withFetchAll()
30+
.listProjectFiles(PROJECT_ID, {
31+
directoryId: directories[0].data.directoryId,
32+
filter: "**",
33+
});
34+
35+
let report: any[] = [];
36+
try {
37+
const identifier = (
38+
await reportsApi.generateReport(PROJECT_ID, {
39+
name: "contribution-raw-data",
40+
schema: {
41+
unit: "words",
42+
mode: "translations",
43+
fileIds: files.map((f) => f.data.id),
44+
},
45+
})
46+
).data.identifier;
47+
48+
while (
49+
(await reportsApi.checkReportStatus(PROJECT_ID, identifier)).data
50+
.status !== "finished"
51+
) {
52+
setTimeout(() => {}, 2000);
53+
}
54+
55+
report = (
56+
await (
57+
await fetch(
58+
(
59+
await reportsApi.downloadReport(PROJECT_ID, identifier)
60+
).data.url
61+
)
62+
).json()
63+
).data;
64+
} catch (error) {
65+
console.error(error);
66+
}
67+
68+
const translators = new Map<
69+
string,
70+
{
71+
words: number;
72+
languages: Set<string>;
73+
avatar: string;
74+
username: string;
75+
}
76+
>();
77+
78+
report.forEach((entry) => {
79+
if (entry.user.username === "REMOVED_USER") return;
80+
81+
const user = translators.get(entry.user.username) || {
82+
words: 0,
83+
languages: new Set<string>(),
84+
avatar: entry.user.avatarUrl,
85+
username: entry.user.username,
86+
};
87+
user.words += entry.translated;
88+
user.languages.add(entry.language.name);
89+
translators.set(user.username, user);
90+
});
91+
92+
return Array.from(translators.values())
93+
.map(
94+
(contributor) =>
95+
({
96+
avatar: contributor.avatar,
97+
links: [
98+
{
99+
icon: "crowdin",
100+
link: `https://crowdin.com/profile/${contributor.username}`,
101+
},
102+
],
103+
name: contributor.username,
104+
number: contributor.words,
105+
} as DefaultTheme.TeamMember & { number: number })
106+
)
107+
.sort((a, b) => a.name.localeCompare(b.name))
108+
.sort((a, b) => b.number - a.number);
109+
},
110+
};

.vitepress/i18n.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,33 @@ export const getLocales = () => {
131131
},
132132
},
133133

134+
credits: {
135+
authors: {
136+
description: {
137+
plural: resolver("credits.authors.description.plural"),
138+
singular: resolver("credits.authors.description.singular"),
139+
},
140+
title: resolver("credits.authors"),
141+
},
142+
committers: {
143+
description: {
144+
plural: resolver("credits.committers.description.plural"),
145+
singular: resolver("credits.committers.description.singular"),
146+
},
147+
title: resolver("credits.committers"),
148+
},
149+
maintainers: {
150+
title: resolver("credits.maintainers"),
151+
},
152+
translators: {
153+
description: {
154+
plural: resolver("credits.translators.description.plural"),
155+
singular: resolver("credits.translators.description.singular"),
156+
},
157+
title: resolver("credits.translators"),
158+
},
159+
},
160+
134161
darkModeSwitchLabel: resolver("mode_switcher"),
135162

136163
darkModeSwitchTitle: resolver("mode_dark"),

.vitepress/types.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,72 @@ export namespace Fabric {
4040
};
4141
}
4242

43+
export interface CreditsOptions {
44+
authors: {
45+
description: {
46+
/**
47+
* @default "%d pages"
48+
*/
49+
plural: string;
50+
51+
/**
52+
* @default "1 page"
53+
*/
54+
singular: string;
55+
};
56+
57+
/**
58+
* @default "Pages Written"
59+
*/
60+
title: string;
61+
};
62+
63+
committers: {
64+
description: {
65+
/**
66+
* @default "%d contributions"
67+
*/
68+
plural: string;
69+
70+
/**
71+
* @default "1 contribution"
72+
*/
73+
singular: string;
74+
};
75+
76+
/**
77+
* @default "Contributions on GitHub"
78+
*/
79+
title: string;
80+
};
81+
82+
maintainers: {
83+
/**
84+
* @default "Maintenance"
85+
*/
86+
title: string;
87+
};
88+
89+
translators: {
90+
description: {
91+
/**
92+
* @default "%d words"
93+
*/
94+
plural: string;
95+
96+
/**
97+
* @default "1 word"
98+
*/
99+
singular: string;
100+
};
101+
102+
/**
103+
* @default "Translations on Crowdin"
104+
*/
105+
title: string;
106+
};
107+
}
108+
43109
export interface DownloadOptions {
44110
/**
45111
* Set custom text for download button.
@@ -157,6 +223,7 @@ export namespace Fabric {
157223
export interface ThemeConfig extends Versioned.ThemeConfig {
158224
authors: AuthorsOptions;
159225
banner: BannerOptions;
226+
credits: CreditsOptions;
160227
download: DownloadOptions;
161228
env: EnvOptions;
162229
notFound: NotFoundOptions;

0 commit comments

Comments
 (0)