@stats-forge/github-stats-forge-core 0.3.0 → 0.4.0
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/build/api/contributed-to.js +1 -1
- package/build/api/gist.js +1 -1
- package/build/api/index.d.ts +1 -0
- package/build/api/index.d.ts.map +1 -1
- package/build/api/index.js +1 -0
- package/build/api/organization.d.ts +29 -0
- package/build/api/organization.d.ts.map +1 -0
- package/build/api/organization.js +53 -0
- package/build/api/params.js +1 -1
- package/build/api/pin.js +1 -1
- package/build/api/stats.js +1 -1
- package/build/api/top-langs.js +1 -1
- package/build/api/wakatime.js +1 -1
- package/build/cards/{contributed-to.d.ts → contributed-to/index.d.ts} +3 -3
- package/build/cards/contributed-to/index.d.ts.map +1 -0
- package/build/cards/{contributed-to.js → contributed-to/index.js} +31 -30
- package/build/cards/contributed-to/locales.d.ts +38 -0
- package/build/cards/contributed-to/locales.d.ts.map +1 -0
- package/build/cards/contributed-to/locales.js +39 -0
- package/build/cards/{gist.d.ts → gist/index.d.ts} +3 -3
- package/build/cards/gist/index.d.ts.map +1 -0
- package/build/cards/{gist.js → gist/index.js} +20 -15
- package/build/cards/gist/locales.d.ts +14 -0
- package/build/cards/gist/locales.d.ts.map +1 -0
- package/build/cards/gist/locales.js +15 -0
- package/build/cards/organization/index.d.ts +36 -0
- package/build/cards/organization/index.d.ts.map +1 -0
- package/build/cards/organization/index.js +225 -0
- package/build/cards/organization/locales.d.ts +47 -0
- package/build/cards/organization/locales.d.ts.map +1 -0
- package/build/cards/organization/locales.js +47 -0
- package/build/cards/{repo.d.ts → repo/index.d.ts} +3 -3
- package/build/cards/repo/index.d.ts.map +1 -0
- package/build/cards/{repo.js → repo/index.js} +20 -23
- package/build/cards/repo/locales.d.ts +129 -0
- package/build/cards/repo/locales.d.ts.map +1 -0
- package/build/cards/repo/locales.js +129 -0
- package/build/cards/{stats.d.ts → stats/index.d.ts} +3 -3
- package/build/cards/stats/index.d.ts.map +1 -0
- package/build/cards/{stats.js → stats/index.js} +38 -42
- package/build/cards/stats/locales.d.ts +621 -0
- package/build/cards/stats/locales.d.ts.map +1 -0
- package/build/cards/stats/locales.js +623 -0
- package/build/cards/{top-languages.d.ts → top-languages/index.d.ts} +3 -3
- package/build/cards/top-languages/index.d.ts.map +1 -0
- package/build/cards/{top-languages.js → top-languages/index.js} +13 -16
- package/build/cards/top-languages/locales.d.ts +103 -0
- package/build/cards/top-languages/locales.d.ts.map +1 -0
- package/build/cards/top-languages/locales.js +103 -0
- package/build/cards/{wakatime.d.ts → wakatime/index.d.ts} +3 -3
- package/build/cards/wakatime/index.d.ts.map +1 -0
- package/build/cards/{wakatime.js → wakatime/index.js} +22 -23
- package/build/cards/wakatime/locales.d.ts +250 -0
- package/build/cards/wakatime/locales.d.ts.map +1 -0
- package/build/cards/wakatime/locales.js +250 -0
- package/build/common/brand.d.ts +1 -0
- package/build/common/brand.d.ts.map +1 -1
- package/build/common/brand.js +1 -0
- package/build/common/error.d.ts +3 -1
- package/build/common/error.d.ts.map +1 -1
- package/build/common/error.js +3 -1
- package/build/common/icons.d.ts +5 -0
- package/build/common/icons.d.ts.map +1 -1
- package/build/common/icons.js +19 -4
- package/build/common/locales.d.ts +59 -0
- package/build/common/locales.d.ts.map +1 -0
- package/build/common/locales.js +59 -0
- package/build/common/localize.d.ts +60 -0
- package/build/common/localize.d.ts.map +1 -0
- package/build/common/localize.js +163 -0
- package/build/fetchers/index.d.ts +2 -1
- package/build/fetchers/index.d.ts.map +1 -1
- package/build/fetchers/index.js +1 -0
- package/build/fetchers/organization.d.ts +15 -0
- package/build/fetchers/organization.d.ts.map +1 -0
- package/build/fetchers/organization.js +115 -0
- package/build/fetchers/types.d.ts +38 -0
- package/build/fetchers/types.d.ts.map +1 -1
- package/build/graphql/generated/organization.d.ts +88 -0
- package/build/graphql/generated/organization.d.ts.map +1 -0
- package/build/graphql/generated/organization.js +59 -0
- package/package.json +1 -1
- package/src/api/contributed-to.ts +1 -1
- package/src/api/gist.ts +1 -1
- package/src/api/index.ts +1 -0
- package/src/api/organization.ts +90 -0
- package/src/api/params.ts +1 -1
- package/src/api/pin.ts +1 -1
- package/src/api/stats.ts +1 -1
- package/src/api/top-langs.ts +1 -1
- package/src/api/wakatime.ts +1 -1
- package/src/cards/{contributed-to.ts → contributed-to/index.ts} +42 -39
- package/src/cards/contributed-to/locales.ts +41 -0
- package/src/cards/{gist.ts → gist/index.ts} +23 -20
- package/src/cards/gist/locales.ts +17 -0
- package/src/cards/organization/index.ts +358 -0
- package/src/cards/organization/locales.ts +49 -0
- package/src/cards/{repo.ts → repo/index.ts} +23 -26
- package/src/cards/repo/locales.ts +131 -0
- package/src/cards/{stats.ts → stats/index.ts} +48 -56
- package/src/cards/stats/locales.ts +625 -0
- package/src/cards/{top-languages.ts → top-languages/index.ts} +17 -20
- package/src/cards/top-languages/locales.ts +105 -0
- package/src/cards/{wakatime.ts → wakatime/index.ts} +26 -27
- package/src/cards/wakatime/locales.ts +252 -0
- package/src/common/brand.ts +1 -0
- package/src/common/error.ts +4 -0
- package/src/common/icons.ts +20 -4
- package/src/common/locales.ts +61 -0
- package/src/common/localize.ts +251 -0
- package/src/fetchers/index.ts +2 -0
- package/src/fetchers/organization.ts +153 -0
- package/src/fetchers/types.ts +36 -0
- package/src/graphql/generated/organization.ts +109 -0
- package/src/graphql/queries/organization.graphql +57 -0
- package/build/cards/contributed-to.d.ts.map +0 -1
- package/build/cards/gist.d.ts.map +0 -1
- package/build/cards/repo.d.ts.map +0 -1
- package/build/cards/stats.d.ts.map +0 -1
- package/build/cards/top-languages.d.ts.map +0 -1
- package/build/cards/wakatime.d.ts.map +0 -1
- package/build/common/I18n.d.ts +0 -21
- package/build/common/I18n.d.ts.map +0 -1
- package/build/common/I18n.js +0 -34
- package/build/translations.d.ts +0 -1212
- package/build/translations.d.ts.map +0 -1
- package/build/translations.js +0 -1213
- package/src/common/I18n.ts +0 -50
- package/src/translations.ts +0 -1239
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { CARD_ICON, CARD_WIDTH, FONT_SIZE, FONT_WEIGHT, font } from '../../common/brand.js';
|
|
2
|
+
import { Card } from '../../common/Card.js';
|
|
3
|
+
import { getLightDarkColors } from '../../common/color.js';
|
|
4
|
+
import { CardError } from '../../common/error.js';
|
|
5
|
+
import { kFormatter } from '../../common/fmt.js';
|
|
6
|
+
import { icons } from '../../common/icons.js';
|
|
7
|
+
import { localize } from '../../common/localize.js';
|
|
8
|
+
import { parseEmojis } from '../../common/ops.js';
|
|
9
|
+
import { NUMBER_FORMATS, createTextNode, flexLayout, measureText, wrapTextMultiline, } from '../../common/render.js';
|
|
10
|
+
import { el, rule } from '../../markup/index.js';
|
|
11
|
+
import { orgCardLocales } from './locales.js';
|
|
12
|
+
const CARD_DEFAULT_WIDTH = CARD_WIDTH.standard;
|
|
13
|
+
/** Padding the card keeps at its edges; matches `Card`'s own `paddingX`. */
|
|
14
|
+
const CARD_PADDING_X = 25;
|
|
15
|
+
/** How far a stat row is translated into the card; see `createTextNode`. */
|
|
16
|
+
const STAT_ROW_X = 25;
|
|
17
|
+
/** `createTextNode`'s own label offset, which it applies only when icons are shown. */
|
|
18
|
+
const LABEL_X_OFFSET = 25;
|
|
19
|
+
/** Smallest gap kept between the longest label and its value. */
|
|
20
|
+
const LABEL_VALUE_GAP = 16;
|
|
21
|
+
const DESCRIPTION_FONT_SIZE = FONT_SIZE.meta;
|
|
22
|
+
const DESCRIPTION_LINE_HEIGHT_PX = 16;
|
|
23
|
+
const DESCRIPTION_MAX_LINES = 2;
|
|
24
|
+
/** Air between the description and the first stat row. */
|
|
25
|
+
const DESCRIPTION_GAP = 8;
|
|
26
|
+
/** Stats the card draws only when `show` names them. */
|
|
27
|
+
const SHOW_STATS = ['releases', 'commits', 'members', 'top_language', 'created'];
|
|
28
|
+
/** Stats the card always draws, and so the ones `hide` has anything to remove. */
|
|
29
|
+
const HIDE_STATS = ['repos', 'stars', 'forks', 'watchers', 'open_issues', 'open_prs'];
|
|
30
|
+
/**
|
|
31
|
+
* @returns Card CSS styles.
|
|
32
|
+
*/
|
|
33
|
+
const getStyles = ({ textColor, iconColor, show_icons, }) => [
|
|
34
|
+
rule('.stat', {
|
|
35
|
+
font: font('regular', 'body'),
|
|
36
|
+
fill: textColor,
|
|
37
|
+
'font-variant-numeric': 'tabular-nums',
|
|
38
|
+
}),
|
|
39
|
+
rule('.description', { font: font('regular', 'meta'), fill: textColor, opacity: 0.9 }),
|
|
40
|
+
rule('.stagger', { opacity: 0, animation: 'fadeInAnimation 0.3s ease-in-out forwards' }),
|
|
41
|
+
rule('.not_bold', { 'font-weight': FONT_WEIGHT.regular, opacity: 0.75 }),
|
|
42
|
+
rule('.bold', { 'font-weight': FONT_WEIGHT.semibold }),
|
|
43
|
+
rule('.icon', { fill: iconColor, opacity: 0.75, display: show_icons ? 'block' : 'none' }),
|
|
44
|
+
];
|
|
45
|
+
/**
|
|
46
|
+
* Renders the organization card.
|
|
47
|
+
*
|
|
48
|
+
* @returns The organization card SVG object.
|
|
49
|
+
*/
|
|
50
|
+
const renderCard = (organization, options = {}) => {
|
|
51
|
+
const { name, description, createdAt, publicRepos, totalStars, totalForks, totalWatchers, openIssues, openPRs, totalReleases, totalCommits, publicMembers, topLanguage, truncated, } = organization;
|
|
52
|
+
const { hide = [], show = [], show_icons = true, hide_title = false, hide_border = false, hide_description = false, card_width, line_height = 25, text_bold = true, custom_title, border_radius, number_format = 'short', locale, disable_animations = false, } = options;
|
|
53
|
+
const lheight = Number.parseInt(String(line_height), 10);
|
|
54
|
+
const { lightColors, darkColors } = getLightDarkColors(options);
|
|
55
|
+
// Typed against the exported list, so a stat drawn here cannot be missing from it.
|
|
56
|
+
const shows = (stat) => show.includes(stat);
|
|
57
|
+
const apostrophe = /s$/i.test(name.trim()) ? '' : 's';
|
|
58
|
+
const t = localize(orgCardLocales, locale);
|
|
59
|
+
/**
|
|
60
|
+
* A total the walk may have stopped short of reads as a lower bound.
|
|
61
|
+
*
|
|
62
|
+
* @returns The value, as the row draws it.
|
|
63
|
+
*/
|
|
64
|
+
const total = (value) => truncated
|
|
65
|
+
? `${number_format.toLowerCase() === 'long' ? String(value) : kFormatter(value)}+`
|
|
66
|
+
: value;
|
|
67
|
+
const STATS = {
|
|
68
|
+
repos: {
|
|
69
|
+
icon: icons.repo,
|
|
70
|
+
label: t.repos(),
|
|
71
|
+
value: publicRepos,
|
|
72
|
+
id: 'repos',
|
|
73
|
+
},
|
|
74
|
+
stars: {
|
|
75
|
+
icon: icons.star,
|
|
76
|
+
label: t.stars(),
|
|
77
|
+
value: total(totalStars),
|
|
78
|
+
id: 'stars',
|
|
79
|
+
},
|
|
80
|
+
forks: {
|
|
81
|
+
icon: icons.fork,
|
|
82
|
+
label: t.forks(),
|
|
83
|
+
value: total(totalForks),
|
|
84
|
+
id: 'forks',
|
|
85
|
+
},
|
|
86
|
+
watchers: {
|
|
87
|
+
icon: icons.watchers,
|
|
88
|
+
label: t.watchers(),
|
|
89
|
+
value: total(totalWatchers),
|
|
90
|
+
id: 'watchers',
|
|
91
|
+
},
|
|
92
|
+
open_issues: {
|
|
93
|
+
icon: icons.issues,
|
|
94
|
+
label: t.openIssues(),
|
|
95
|
+
value: total(openIssues),
|
|
96
|
+
id: 'open_issues',
|
|
97
|
+
},
|
|
98
|
+
open_prs: {
|
|
99
|
+
icon: icons.prs,
|
|
100
|
+
label: t.openPrs(),
|
|
101
|
+
value: total(openPRs),
|
|
102
|
+
id: 'open_prs',
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
if (shows('releases')) {
|
|
106
|
+
STATS['releases'] = {
|
|
107
|
+
icon: icons.tag,
|
|
108
|
+
label: t.releases(),
|
|
109
|
+
value: total(totalReleases),
|
|
110
|
+
id: 'releases',
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
if (shows('commits')) {
|
|
114
|
+
STATS['commits'] = {
|
|
115
|
+
icon: icons.commits,
|
|
116
|
+
label: t.commits(),
|
|
117
|
+
value: total(totalCommits),
|
|
118
|
+
id: 'commits',
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (shows('members')) {
|
|
122
|
+
STATS['members'] = {
|
|
123
|
+
icon: icons.people,
|
|
124
|
+
label: t.members(),
|
|
125
|
+
value: publicMembers,
|
|
126
|
+
id: 'members',
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
if (shows('top_language')) {
|
|
130
|
+
STATS['top_language'] = {
|
|
131
|
+
icon: icons.code,
|
|
132
|
+
label: t.topLanguage(),
|
|
133
|
+
value: topLanguage?.name ?? t.unspecifiedLanguage(),
|
|
134
|
+
id: 'top_language',
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
if (shows('created')) {
|
|
138
|
+
const year = new Date(createdAt).getUTCFullYear();
|
|
139
|
+
STATS['created'] = {
|
|
140
|
+
icon: icons.calendar,
|
|
141
|
+
label: t.created(),
|
|
142
|
+
value: Number.isNaN(year) ? '—' : String(year),
|
|
143
|
+
id: 'created',
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
const visibleStats = Object.entries(STATS).filter(([key]) => !hide.includes(key));
|
|
147
|
+
if (visibleStats.length === 0) {
|
|
148
|
+
throw new CardError('Could not render organization card.', {
|
|
149
|
+
code: 'invalid_param',
|
|
150
|
+
secondaryMessage: 'At least one stat is required.',
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
const width = card_width && !Number.isNaN(card_width) ? card_width : CARD_DEFAULT_WIDTH;
|
|
154
|
+
const desc = hide_description ? '' : parseEmojis(description || t.noDescription());
|
|
155
|
+
const descriptionLines = desc
|
|
156
|
+
? wrapTextMultiline(desc, width - 2 * CARD_PADDING_X, DESCRIPTION_FONT_SIZE, DESCRIPTION_MAX_LINES)
|
|
157
|
+
: [];
|
|
158
|
+
const statsTop = descriptionLines.length > 0
|
|
159
|
+
? descriptionLines.length * DESCRIPTION_LINE_HEIGHT_PX + DESCRIPTION_GAP
|
|
160
|
+
: 0;
|
|
161
|
+
const height = 45 + (visibleStats.length + 1) * lheight + statsTop;
|
|
162
|
+
// A value ends at the card's inner edge — or right after the longest label,
|
|
163
|
+
// on a card too narrow for that.
|
|
164
|
+
const widestLabel = Math.max(...visibleStats.map(([, stat]) => measureText(`${stat.label}:`, FONT_SIZE.body)));
|
|
165
|
+
const valueAnchorX = Math.round(Math.max(width - CARD_PADDING_X - STAT_ROW_X, (show_icons ? LABEL_X_OFFSET : 0) + widestLabel + LABEL_VALUE_GAP));
|
|
166
|
+
const statItems = visibleStats.map(([, stat], index) => createTextNode({
|
|
167
|
+
icon: stat.icon,
|
|
168
|
+
label: stat.label,
|
|
169
|
+
value: stat.value,
|
|
170
|
+
id: stat.id,
|
|
171
|
+
index,
|
|
172
|
+
showIcons: show_icons,
|
|
173
|
+
shiftValuePos: 0,
|
|
174
|
+
valueAnchorX,
|
|
175
|
+
bold: text_bold,
|
|
176
|
+
labelBold: false,
|
|
177
|
+
numberFormat: number_format,
|
|
178
|
+
}));
|
|
179
|
+
const card = new Card({
|
|
180
|
+
customTitle: custom_title,
|
|
181
|
+
defaultTitle: t.title({ name, apostrophe }),
|
|
182
|
+
titlePrefixIcon: CARD_ICON.organization,
|
|
183
|
+
width,
|
|
184
|
+
height,
|
|
185
|
+
border_radius,
|
|
186
|
+
colors: { light: lightColors, dark: darkColors },
|
|
187
|
+
});
|
|
188
|
+
card.setHideBorder(hide_border);
|
|
189
|
+
card.setHideTitle(hide_title);
|
|
190
|
+
const cardStyles = ({ textColor, iconColor }) => getStyles({ textColor, iconColor, show_icons });
|
|
191
|
+
card.setCSS({ light: cardStyles, dark: cardStyles });
|
|
192
|
+
if (disable_animations) {
|
|
193
|
+
card.disableAnimations();
|
|
194
|
+
}
|
|
195
|
+
// `role="img"` hides the inner text from assistive tech, so everything the card
|
|
196
|
+
// shows has to be repeated here.
|
|
197
|
+
card.setAccessibilityLabel({
|
|
198
|
+
title: card.title,
|
|
199
|
+
desc: [
|
|
200
|
+
desc && `${desc}.`,
|
|
201
|
+
visibleStats.map(([, stat]) => `${stat.label}: ${String(stat.value)}`).join(', '),
|
|
202
|
+
]
|
|
203
|
+
.filter(Boolean)
|
|
204
|
+
.join(' '),
|
|
205
|
+
});
|
|
206
|
+
const descriptionSvg = descriptionLines.length > 0 &&
|
|
207
|
+
el('text', { class: 'description', 'data-testid': 'description', x: CARD_PADDING_X, y: -5 }, descriptionLines.map((line) => el('tspan', { dy: '1.2em', x: CARD_PADDING_X }, line)));
|
|
208
|
+
return card.render([
|
|
209
|
+
descriptionSvg,
|
|
210
|
+
el('g', { transform: `translate(0, ${statsTop})` }, flexLayout({ items: statItems, gap: lheight, direction: 'column' })),
|
|
211
|
+
]);
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
* The card, and the values each of its options accepts, keyed by the option's own name.
|
|
215
|
+
* They ride on the renderer so a list cannot be found without what draws it;
|
|
216
|
+
* the api handler forwards them onto its own export, which is what a UI reads.
|
|
217
|
+
*/
|
|
218
|
+
const renderOrganizationCard = Object.assign(renderCard, {
|
|
219
|
+
OPTIONS: {
|
|
220
|
+
show: SHOW_STATS,
|
|
221
|
+
hide: HIDE_STATS,
|
|
222
|
+
number_format: NUMBER_FORMATS,
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
export { renderOrganizationCard };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** The organization card's labels in the locales they have been translated into. */
|
|
2
|
+
declare const orgCardLocales: {
|
|
3
|
+
readonly title: {
|
|
4
|
+
readonly en: "{name}'{apostrophe} GitHub Organization";
|
|
5
|
+
};
|
|
6
|
+
readonly noDescription: {
|
|
7
|
+
readonly en: "No description provided";
|
|
8
|
+
};
|
|
9
|
+
readonly repos: {
|
|
10
|
+
readonly en: "Public repositories";
|
|
11
|
+
};
|
|
12
|
+
readonly stars: {
|
|
13
|
+
readonly en: "Total stars";
|
|
14
|
+
};
|
|
15
|
+
readonly forks: {
|
|
16
|
+
readonly en: "Total forks";
|
|
17
|
+
};
|
|
18
|
+
readonly watchers: {
|
|
19
|
+
readonly en: "Total watchers";
|
|
20
|
+
};
|
|
21
|
+
readonly openIssues: {
|
|
22
|
+
readonly en: "Open issues";
|
|
23
|
+
};
|
|
24
|
+
readonly openPrs: {
|
|
25
|
+
readonly en: "Open PRs";
|
|
26
|
+
};
|
|
27
|
+
readonly releases: {
|
|
28
|
+
readonly en: "Releases";
|
|
29
|
+
};
|
|
30
|
+
readonly commits: {
|
|
31
|
+
readonly en: "Commits";
|
|
32
|
+
};
|
|
33
|
+
readonly members: {
|
|
34
|
+
readonly en: "Public members";
|
|
35
|
+
};
|
|
36
|
+
readonly topLanguage: {
|
|
37
|
+
readonly en: "Top language";
|
|
38
|
+
};
|
|
39
|
+
readonly created: {
|
|
40
|
+
readonly en: "Created";
|
|
41
|
+
};
|
|
42
|
+
readonly unspecifiedLanguage: {
|
|
43
|
+
readonly en: "Unspecified";
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
export { orgCardLocales };
|
|
47
|
+
//# sourceMappingURL=locales.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/cards/organization/locales.ts"],"names":[],"mappings":"AAEA,oFAAoF;AACpF,QAAA,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2ClB,CAAC;AAEH,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { defineLocales } from '../../common/localize.js';
|
|
2
|
+
/** The organization card's labels in the locales they have been translated into. */
|
|
3
|
+
const orgCardLocales = defineLocales({
|
|
4
|
+
title: {
|
|
5
|
+
en: `{name}'{apostrophe} GitHub Organization`,
|
|
6
|
+
},
|
|
7
|
+
noDescription: {
|
|
8
|
+
en: 'No description provided',
|
|
9
|
+
},
|
|
10
|
+
repos: {
|
|
11
|
+
en: 'Public repositories',
|
|
12
|
+
},
|
|
13
|
+
stars: {
|
|
14
|
+
en: 'Total stars',
|
|
15
|
+
},
|
|
16
|
+
forks: {
|
|
17
|
+
en: 'Total forks',
|
|
18
|
+
},
|
|
19
|
+
watchers: {
|
|
20
|
+
en: 'Total watchers',
|
|
21
|
+
},
|
|
22
|
+
openIssues: {
|
|
23
|
+
en: 'Open issues',
|
|
24
|
+
},
|
|
25
|
+
openPrs: {
|
|
26
|
+
en: 'Open PRs',
|
|
27
|
+
},
|
|
28
|
+
releases: {
|
|
29
|
+
en: 'Releases',
|
|
30
|
+
},
|
|
31
|
+
commits: {
|
|
32
|
+
en: 'Commits',
|
|
33
|
+
},
|
|
34
|
+
members: {
|
|
35
|
+
en: 'Public members',
|
|
36
|
+
},
|
|
37
|
+
topLanguage: {
|
|
38
|
+
en: 'Top language',
|
|
39
|
+
},
|
|
40
|
+
created: {
|
|
41
|
+
en: 'Created',
|
|
42
|
+
},
|
|
43
|
+
unspecifiedLanguage: {
|
|
44
|
+
en: 'Unspecified',
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
export { orgCardLocales };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { RepositoryData } from '
|
|
2
|
-
import type { CardOptions, CommonCardOptions } from '
|
|
1
|
+
import type { RepositoryData } from '../../fetchers/types.ts';
|
|
2
|
+
import type { CardOptions, CommonCardOptions } from '../options.ts';
|
|
3
3
|
interface RepoCardOptions extends CommonCardOptions {
|
|
4
4
|
locale: string;
|
|
5
5
|
show_owner: boolean;
|
|
@@ -31,4 +31,4 @@ declare const renderRepoCard: typeof renderCard & {
|
|
|
31
31
|
};
|
|
32
32
|
};
|
|
33
33
|
export { renderRepoCard };
|
|
34
|
-
//# sourceMappingURL=
|
|
34
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cards/repo/index.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAG9D,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAqBpE,UAAU,eAAgB,SAAQ,iBAAiB;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,uBAAuB,EAAE,MAAM,CAAC;IAChC,gBAAgB,EAAE,MAAM,CAAC;IACzB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAuCD;;;;GAIG;AACH,QAAA,MAAM,UAAU,SAAU,cAAc,YAAW,WAAW,CAAC,eAAe,CAAC,KAAQ,MAiRtF,CAAC;AAEF;;;;GAIG;AACH,QAAA,MAAM,cAAc;;QAEhB,IAAI;QACJ,aAAa;;CAEf,CAAC;AAEH,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { CARD_ICON, CARD_WIDTH, FONT_SIZE, FONT_WEIGHT, font } from '
|
|
2
|
-
import { Card } from '
|
|
3
|
-
import { getLightDarkColors } from '
|
|
4
|
-
import { kFormatter } from '
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { buildSearchFilter, clampValue, parseEmojis } from '
|
|
8
|
-
import { NUMBER_FORMATS, countWrappedLines, wrapTextMultiline, createLanguageNode, createTextNode, flexLayout, iconWithLabel, measureText, wrappedTextNode, wrappedTextStyles, } from '
|
|
9
|
-
import { el, rule } from '
|
|
10
|
-
import { repoCardLocales } from '
|
|
1
|
+
import { CARD_ICON, CARD_WIDTH, FONT_SIZE, FONT_WEIGHT, font } from '../../common/brand.js';
|
|
2
|
+
import { Card } from '../../common/Card.js';
|
|
3
|
+
import { getLightDarkColors } from '../../common/color.js';
|
|
4
|
+
import { kFormatter } from '../../common/fmt.js';
|
|
5
|
+
import { icons } from '../../common/icons.js';
|
|
6
|
+
import { localize } from '../../common/localize.js';
|
|
7
|
+
import { buildSearchFilter, clampValue, parseEmojis } from '../../common/ops.js';
|
|
8
|
+
import { NUMBER_FORMATS, countWrappedLines, wrapTextMultiline, createLanguageNode, createTextNode, flexLayout, iconWithLabel, measureText, wrappedTextNode, wrappedTextStyles, } from '../../common/render.js';
|
|
9
|
+
import { el, rule } from '../../markup/index.js';
|
|
10
|
+
import { repoCardLocales } from './locales.js';
|
|
11
11
|
const ICON_SIZE = 16;
|
|
12
12
|
const CARD_DEFAULT_WIDTH = CARD_WIDTH.standard;
|
|
13
13
|
const X_OFFSET = 25;
|
|
@@ -52,10 +52,7 @@ const renderCard = (repo, options = {}) => {
|
|
|
52
52
|
: show.length >= 2
|
|
53
53
|
? CARD_DEFAULT_WIDTH + 30
|
|
54
54
|
: CARD_DEFAULT_WIDTH;
|
|
55
|
-
const
|
|
56
|
-
locale,
|
|
57
|
-
translations: repoCardLocales,
|
|
58
|
-
});
|
|
55
|
+
const t = localize(repoCardLocales, locale);
|
|
59
56
|
// Typed against the exported list, so a stat drawn here cannot be missing from it.
|
|
60
57
|
const shows = (stat) => show.includes(stat);
|
|
61
58
|
const repoFilter = encodeURIComponent(buildSearchFilter([nameWithOwner], []));
|
|
@@ -64,7 +61,7 @@ const renderCard = (repo, options = {}) => {
|
|
|
64
61
|
if (shows('prs_authored')) {
|
|
65
62
|
STATS['prs_authored'] = {
|
|
66
63
|
icon: icons.prs,
|
|
67
|
-
label:
|
|
64
|
+
label: t.prsAuthored(),
|
|
68
65
|
value: totalPRsAuthored,
|
|
69
66
|
id: 'prs_authored',
|
|
70
67
|
link: `https://github.com/search?q=${repoFilter}author%3A${encodedUsername}&type=pullrequests`,
|
|
@@ -73,7 +70,7 @@ const renderCard = (repo, options = {}) => {
|
|
|
73
70
|
if (shows('prs_commented')) {
|
|
74
71
|
STATS['prs_commented'] = {
|
|
75
72
|
icon: icons.comments,
|
|
76
|
-
label:
|
|
73
|
+
label: t.prsCommented(),
|
|
77
74
|
value: totalPRsCommented,
|
|
78
75
|
id: 'prs_commented',
|
|
79
76
|
link: `https://github.com/search?q=${repoFilter}commenter%3A${encodedUsername}+-author%3A${encodedUsername}&type=pullrequests`,
|
|
@@ -82,7 +79,7 @@ const renderCard = (repo, options = {}) => {
|
|
|
82
79
|
if (shows('prs_reviewed')) {
|
|
83
80
|
STATS['prs_reviewed'] = {
|
|
84
81
|
icon: icons.reviews,
|
|
85
|
-
label:
|
|
82
|
+
label: t.prsReviewed(),
|
|
86
83
|
value: totalPRsReviewed,
|
|
87
84
|
id: 'prs_reviewed',
|
|
88
85
|
link: `https://github.com/search?q=${repoFilter}reviewed-by%3A${encodedUsername}+-author%3A${encodedUsername}&type=pullrequests`,
|
|
@@ -91,7 +88,7 @@ const renderCard = (repo, options = {}) => {
|
|
|
91
88
|
if (shows('issues_authored')) {
|
|
92
89
|
STATS['issues_authored'] = {
|
|
93
90
|
icon: icons.issues,
|
|
94
|
-
label:
|
|
91
|
+
label: t.issuesAuthored(),
|
|
95
92
|
value: totalIssuesAuthored,
|
|
96
93
|
id: 'issues_authored',
|
|
97
94
|
link: `https://github.com/search?q=${repoFilter}author%3A${encodedUsername}&type=issues`,
|
|
@@ -100,7 +97,7 @@ const renderCard = (repo, options = {}) => {
|
|
|
100
97
|
if (shows('issues_commented')) {
|
|
101
98
|
STATS['issues_commented'] = {
|
|
102
99
|
icon: icons.discussions_started,
|
|
103
|
-
label:
|
|
100
|
+
label: t.issuesCommented(),
|
|
104
101
|
value: totalIssuesCommented,
|
|
105
102
|
id: 'issues_commented',
|
|
106
103
|
link: `https://github.com/search?q=${repoFilter}commenter%3A${encodedUsername}+-author%3A${encodedUsername}&type=issues`,
|
|
@@ -125,9 +122,9 @@ const renderCard = (repo, options = {}) => {
|
|
|
125
122
|
const extraLHeight = Number.parseInt(String(line_height), 10);
|
|
126
123
|
const lineHeight = 10;
|
|
127
124
|
const header = show_owner ? nameWithOwner : name;
|
|
128
|
-
const langName = primaryLanguage?.name ||
|
|
125
|
+
const langName = primaryLanguage?.name || t.unspecifiedLanguage();
|
|
129
126
|
const langColor = primaryLanguage?.color || '#333';
|
|
130
|
-
const desc = parseEmojis(description ||
|
|
127
|
+
const desc = parseEmojis(description || t.noDescription());
|
|
131
128
|
const descriptionBoxWidth = card_width - 2 * X_OFFSET;
|
|
132
129
|
let descriptionLinesCount;
|
|
133
130
|
let descriptionSvg;
|
|
@@ -243,9 +240,9 @@ const renderCard = (repo, options = {}) => {
|
|
|
243
240
|
});
|
|
244
241
|
return card.render([
|
|
245
242
|
isTemplate
|
|
246
|
-
? getBadgeSVG(
|
|
243
|
+
? getBadgeSVG(t.template(), card_width - CARD_DEFAULT_WIDTH)
|
|
247
244
|
: isArchived
|
|
248
|
-
? getBadgeSVG(
|
|
245
|
+
? getBadgeSVG(t.archived(), card_width - CARD_DEFAULT_WIDTH)
|
|
249
246
|
: undefined,
|
|
250
247
|
descriptionSvg,
|
|
251
248
|
el('g', { transform: `translate(30, ${height - 75 - extraHeight})` }, starAndForkCount),
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/** The repo card's labels in the locales they have been translated into. */
|
|
2
|
+
declare const repoCardLocales: {
|
|
3
|
+
readonly noDescription: {
|
|
4
|
+
readonly en: "No description provided";
|
|
5
|
+
};
|
|
6
|
+
readonly unspecifiedLanguage: {
|
|
7
|
+
readonly en: "Unspecified";
|
|
8
|
+
};
|
|
9
|
+
readonly template: {
|
|
10
|
+
readonly en: "Template";
|
|
11
|
+
readonly ar: "قالب";
|
|
12
|
+
readonly az: "Şablon";
|
|
13
|
+
readonly bg: "Шаблон";
|
|
14
|
+
readonly bn: "টেমপ্লেট";
|
|
15
|
+
readonly ca: "Plantilla";
|
|
16
|
+
readonly cn: "模板";
|
|
17
|
+
readonly 'zh-tw': "模板";
|
|
18
|
+
readonly cs: "Šablona";
|
|
19
|
+
readonly de: "Vorlage";
|
|
20
|
+
readonly sw: "Kigezo";
|
|
21
|
+
readonly ur: "سانچہ";
|
|
22
|
+
readonly es: "Plantilla";
|
|
23
|
+
readonly fa: "الگو";
|
|
24
|
+
readonly fi: "Malli";
|
|
25
|
+
readonly fr: "Modèle";
|
|
26
|
+
readonly hi: "खाका";
|
|
27
|
+
readonly sa: "प्रारूपम्";
|
|
28
|
+
readonly hu: "Sablon";
|
|
29
|
+
readonly it: "Template";
|
|
30
|
+
readonly ja: "テンプレート";
|
|
31
|
+
readonly kr: "템플릿";
|
|
32
|
+
readonly nl: "Sjabloon";
|
|
33
|
+
readonly 'pt-pt': "Modelo";
|
|
34
|
+
readonly 'pt-br': "Modelo";
|
|
35
|
+
readonly np: "टेम्पलेट";
|
|
36
|
+
readonly el: "Πρότυπο";
|
|
37
|
+
readonly ro: "Șablon";
|
|
38
|
+
readonly ru: "Шаблон";
|
|
39
|
+
readonly 'uk-ua': "Шаблон";
|
|
40
|
+
readonly id: "Pola";
|
|
41
|
+
readonly ml: "ടെംപ്ലേറ്റ്";
|
|
42
|
+
readonly my: "ပုံစံ";
|
|
43
|
+
readonly ta: "டெம்ப்ளேட்";
|
|
44
|
+
readonly sk: "Šablóna";
|
|
45
|
+
readonly tr: "Şablon";
|
|
46
|
+
readonly pl: "Szablony";
|
|
47
|
+
readonly uz: "Shablon";
|
|
48
|
+
readonly vi: "Mẫu";
|
|
49
|
+
readonly se: "Mall";
|
|
50
|
+
readonly he: "תבנית";
|
|
51
|
+
readonly fil: "Suleras";
|
|
52
|
+
readonly th: "เทมเพลต";
|
|
53
|
+
readonly sr: "Шаблон";
|
|
54
|
+
readonly 'sr-latn': "Šablon";
|
|
55
|
+
readonly no: "Mal";
|
|
56
|
+
readonly be: "Шаблон";
|
|
57
|
+
};
|
|
58
|
+
readonly archived: {
|
|
59
|
+
readonly en: "Archived";
|
|
60
|
+
readonly ar: "مُؤرشف";
|
|
61
|
+
readonly az: "Arxiv";
|
|
62
|
+
readonly bg: "Архивирани";
|
|
63
|
+
readonly bn: "আর্কাইভড";
|
|
64
|
+
readonly ca: "Arxivats";
|
|
65
|
+
readonly cn: "已归档";
|
|
66
|
+
readonly 'zh-tw': "已封存";
|
|
67
|
+
readonly cs: "Archivováno";
|
|
68
|
+
readonly de: "Archiviert";
|
|
69
|
+
readonly sw: "Hifadhiwa kwenye kumbukumbu";
|
|
70
|
+
readonly ur: "محفوظ شدہ";
|
|
71
|
+
readonly es: "Archivados";
|
|
72
|
+
readonly fa: "بایگانیشده";
|
|
73
|
+
readonly fi: "Arkistoitu";
|
|
74
|
+
readonly fr: "Archivé";
|
|
75
|
+
readonly hi: "संग्रहीत";
|
|
76
|
+
readonly sa: "संगृहीतम्";
|
|
77
|
+
readonly hu: "Archivált";
|
|
78
|
+
readonly it: "Archiviata";
|
|
79
|
+
readonly ja: "アーカイブ済み";
|
|
80
|
+
readonly kr: "보관됨";
|
|
81
|
+
readonly nl: "Gearchiveerd";
|
|
82
|
+
readonly 'pt-pt': "Arquivados";
|
|
83
|
+
readonly 'pt-br': "Arquivados";
|
|
84
|
+
readonly np: "अभिलेख राखियो";
|
|
85
|
+
readonly el: "Αρχειοθετημένα";
|
|
86
|
+
readonly ro: "Arhivat";
|
|
87
|
+
readonly ru: "Архивирован";
|
|
88
|
+
readonly 'uk-ua': "Архивований";
|
|
89
|
+
readonly id: "Arsip";
|
|
90
|
+
readonly ml: "ശേഖരിച്ചത്";
|
|
91
|
+
readonly my: "သိုလှောင်ပြီး";
|
|
92
|
+
readonly ta: "காப்பகப்படுத்தப்பட்டது";
|
|
93
|
+
readonly sk: "Archivované";
|
|
94
|
+
readonly tr: "Arşiv";
|
|
95
|
+
readonly pl: "Zarchiwizowano";
|
|
96
|
+
readonly uz: "Arxivlangan";
|
|
97
|
+
readonly vi: "Đã Lưu Trữ";
|
|
98
|
+
readonly se: "Arkiverade";
|
|
99
|
+
readonly he: "גנוז";
|
|
100
|
+
readonly fil: "Naka-arkibo";
|
|
101
|
+
readonly th: "เก็บถาวร";
|
|
102
|
+
readonly sr: "Архивирано";
|
|
103
|
+
readonly 'sr-latn': "Arhivirano";
|
|
104
|
+
readonly no: "Arkivert";
|
|
105
|
+
readonly be: "Архіваваны";
|
|
106
|
+
};
|
|
107
|
+
readonly prsAuthored: {
|
|
108
|
+
readonly en: "my created PRs";
|
|
109
|
+
readonly 'zh-tw': "我所創建的拉取請求";
|
|
110
|
+
};
|
|
111
|
+
readonly prsCommented: {
|
|
112
|
+
readonly en: "my commented PRs";
|
|
113
|
+
readonly 'zh-tw': "我所參與的拉取請求";
|
|
114
|
+
};
|
|
115
|
+
readonly prsReviewed: {
|
|
116
|
+
readonly en: "my reviewed PRs";
|
|
117
|
+
readonly 'zh-tw': "我所審核的拉取請求";
|
|
118
|
+
};
|
|
119
|
+
readonly issuesAuthored: {
|
|
120
|
+
readonly en: "my created issues";
|
|
121
|
+
readonly 'zh-tw': "我所創建的議題";
|
|
122
|
+
};
|
|
123
|
+
readonly issuesCommented: {
|
|
124
|
+
readonly en: "my commented issues";
|
|
125
|
+
readonly 'zh-tw': "我所參與的議題";
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
export { repoCardLocales };
|
|
129
|
+
//# sourceMappingURL=locales.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/cards/repo/locales.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6HnB,CAAC;AAEH,OAAO,EAAE,eAAe,EAAE,CAAC"}
|