@dytsou/github-readme-stats 1.0.1
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/LICENSE +21 -0
- package/api/gist.js +98 -0
- package/api/index.js +146 -0
- package/api/pin.js +114 -0
- package/api/status/pat-info.js +193 -0
- package/api/status/up.js +129 -0
- package/api/top-langs.js +163 -0
- package/api/wakatime.js +129 -0
- package/package.json +102 -0
- package/readme.md +412 -0
- package/src/calculateRank.js +87 -0
- package/src/cards/gist.js +151 -0
- package/src/cards/index.js +4 -0
- package/src/cards/repo.js +199 -0
- package/src/cards/stats.js +607 -0
- package/src/cards/top-languages.js +968 -0
- package/src/cards/types.d.ts +67 -0
- package/src/cards/wakatime.js +482 -0
- package/src/common/Card.js +294 -0
- package/src/common/I18n.js +41 -0
- package/src/common/access.js +69 -0
- package/src/common/api-utils.js +221 -0
- package/src/common/blacklist.js +10 -0
- package/src/common/cache.js +153 -0
- package/src/common/color.js +194 -0
- package/src/common/envs.js +15 -0
- package/src/common/error.js +84 -0
- package/src/common/fmt.js +90 -0
- package/src/common/html.js +43 -0
- package/src/common/http.js +24 -0
- package/src/common/icons.js +63 -0
- package/src/common/index.js +13 -0
- package/src/common/languageColors.json +651 -0
- package/src/common/log.js +14 -0
- package/src/common/ops.js +124 -0
- package/src/common/render.js +261 -0
- package/src/common/retryer.js +97 -0
- package/src/common/worker-adapter.js +148 -0
- package/src/common/worker-env.js +48 -0
- package/src/fetchers/gist.js +114 -0
- package/src/fetchers/repo.js +118 -0
- package/src/fetchers/stats.js +350 -0
- package/src/fetchers/top-languages.js +192 -0
- package/src/fetchers/types.d.ts +118 -0
- package/src/fetchers/wakatime.js +109 -0
- package/src/index.js +2 -0
- package/src/translations.js +1105 -0
- package/src/worker.ts +116 -0
- package/themes/README.md +229 -0
- package/themes/index.js +467 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import { Card } from "../common/Card.js";
|
|
4
|
+
import { getCardColors } from "../common/color.js";
|
|
5
|
+
import { kFormatter, wrapTextMultiline } from "../common/fmt.js";
|
|
6
|
+
import { encodeHTML, escapeCSSValue } from "../common/html.js";
|
|
7
|
+
import { I18n } from "../common/I18n.js";
|
|
8
|
+
import { icons } from "../common/icons.js";
|
|
9
|
+
import { clampValue, parseEmojis } from "../common/ops.js";
|
|
10
|
+
import {
|
|
11
|
+
flexLayout,
|
|
12
|
+
measureText,
|
|
13
|
+
iconWithLabel,
|
|
14
|
+
createLanguageNode,
|
|
15
|
+
} from "../common/render.js";
|
|
16
|
+
import { repoCardLocales } from "../translations.js";
|
|
17
|
+
|
|
18
|
+
const ICON_SIZE = 16;
|
|
19
|
+
const DESCRIPTION_LINE_WIDTH = 59;
|
|
20
|
+
const DESCRIPTION_MAX_LINES = 3;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Retrieves the repository description and wraps it to fit the card width.
|
|
24
|
+
*
|
|
25
|
+
* @param {string} label The repository description.
|
|
26
|
+
* @param {string} textColor The color of the text.
|
|
27
|
+
* @returns {string} Wrapped repo description SVG object.
|
|
28
|
+
*/
|
|
29
|
+
const getBadgeSVG = (label, textColor) => {
|
|
30
|
+
const safeTextColor = escapeCSSValue(textColor);
|
|
31
|
+
return `
|
|
32
|
+
<g data-testid="badge" class="badge" transform="translate(320, -18)">
|
|
33
|
+
<rect stroke="${safeTextColor}" stroke-width="1" width="70" height="20" x="-12" y="-14" ry="10" rx="10"></rect>
|
|
34
|
+
<text
|
|
35
|
+
x="23" y="-5"
|
|
36
|
+
alignment-baseline="central"
|
|
37
|
+
dominant-baseline="central"
|
|
38
|
+
text-anchor="middle"
|
|
39
|
+
fill="${safeTextColor}"
|
|
40
|
+
>
|
|
41
|
+
${encodeHTML(label)}
|
|
42
|
+
</text>
|
|
43
|
+
</g>
|
|
44
|
+
`;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @typedef {import("../fetchers/types").RepositoryData} RepositoryData Repository data.
|
|
49
|
+
* @typedef {import("./types").RepoCardOptions} RepoCardOptions Repo card options.
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Renders repository card details.
|
|
54
|
+
*
|
|
55
|
+
* @param {RepositoryData} repo Repository data.
|
|
56
|
+
* @param {Partial<RepoCardOptions>} options Card options.
|
|
57
|
+
* @returns {string} Repository card SVG object.
|
|
58
|
+
*/
|
|
59
|
+
const renderRepoCard = (repo, options = {}) => {
|
|
60
|
+
const {
|
|
61
|
+
name,
|
|
62
|
+
nameWithOwner,
|
|
63
|
+
description,
|
|
64
|
+
primaryLanguage,
|
|
65
|
+
isArchived,
|
|
66
|
+
isTemplate,
|
|
67
|
+
starCount,
|
|
68
|
+
forkCount,
|
|
69
|
+
} = repo;
|
|
70
|
+
const {
|
|
71
|
+
hide_border = false,
|
|
72
|
+
title_color,
|
|
73
|
+
icon_color,
|
|
74
|
+
text_color,
|
|
75
|
+
bg_color,
|
|
76
|
+
show_owner = false,
|
|
77
|
+
theme = "default_repocard",
|
|
78
|
+
border_radius,
|
|
79
|
+
border_color,
|
|
80
|
+
locale,
|
|
81
|
+
description_lines_count,
|
|
82
|
+
} = options;
|
|
83
|
+
|
|
84
|
+
const lineHeight = 10;
|
|
85
|
+
const header = show_owner ? nameWithOwner : name;
|
|
86
|
+
const langName = (primaryLanguage && primaryLanguage.name) || "Unspecified";
|
|
87
|
+
const langColor = (primaryLanguage && primaryLanguage.color) || "#333";
|
|
88
|
+
const descriptionMaxLines = description_lines_count
|
|
89
|
+
? clampValue(description_lines_count, 1, DESCRIPTION_MAX_LINES)
|
|
90
|
+
: DESCRIPTION_MAX_LINES;
|
|
91
|
+
|
|
92
|
+
const desc = parseEmojis(description || "No description provided");
|
|
93
|
+
const multiLineDescription = wrapTextMultiline(
|
|
94
|
+
desc,
|
|
95
|
+
DESCRIPTION_LINE_WIDTH,
|
|
96
|
+
descriptionMaxLines,
|
|
97
|
+
);
|
|
98
|
+
const descriptionLinesCount = description_lines_count
|
|
99
|
+
? clampValue(description_lines_count, 1, DESCRIPTION_MAX_LINES)
|
|
100
|
+
: multiLineDescription.length;
|
|
101
|
+
|
|
102
|
+
const descriptionSvg = multiLineDescription
|
|
103
|
+
.map((line) => `<tspan dy="1.2em" x="25">${encodeHTML(line)}</tspan>`)
|
|
104
|
+
.join("");
|
|
105
|
+
|
|
106
|
+
const height =
|
|
107
|
+
(descriptionLinesCount > 1 ? 120 : 110) +
|
|
108
|
+
descriptionLinesCount * lineHeight;
|
|
109
|
+
|
|
110
|
+
const i18n = new I18n({
|
|
111
|
+
locale,
|
|
112
|
+
translations: repoCardLocales,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// returns theme based colors with proper overrides and defaults
|
|
116
|
+
const colors = getCardColors({
|
|
117
|
+
title_color,
|
|
118
|
+
icon_color,
|
|
119
|
+
text_color,
|
|
120
|
+
bg_color,
|
|
121
|
+
border_color,
|
|
122
|
+
theme,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const svgLanguage = primaryLanguage
|
|
126
|
+
? createLanguageNode(langName, langColor)
|
|
127
|
+
: "";
|
|
128
|
+
|
|
129
|
+
const totalStars = kFormatter(starCount);
|
|
130
|
+
const totalForks = kFormatter(forkCount);
|
|
131
|
+
const svgStars = iconWithLabel(
|
|
132
|
+
icons.star,
|
|
133
|
+
totalStars,
|
|
134
|
+
"stargazers",
|
|
135
|
+
ICON_SIZE,
|
|
136
|
+
);
|
|
137
|
+
const svgForks = iconWithLabel(
|
|
138
|
+
icons.fork,
|
|
139
|
+
totalForks,
|
|
140
|
+
"forkcount",
|
|
141
|
+
ICON_SIZE,
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
const starAndForkCount = flexLayout({
|
|
145
|
+
items: [svgLanguage, svgStars, svgForks],
|
|
146
|
+
sizes: [
|
|
147
|
+
measureText(langName, 12),
|
|
148
|
+
ICON_SIZE + measureText(`${totalStars}`, 12),
|
|
149
|
+
ICON_SIZE + measureText(`${totalForks}`, 12),
|
|
150
|
+
],
|
|
151
|
+
gap: 25,
|
|
152
|
+
}).join("");
|
|
153
|
+
|
|
154
|
+
const card = new Card({
|
|
155
|
+
defaultTitle: header.length > 35 ? `${header.slice(0, 35)}...` : header,
|
|
156
|
+
titlePrefixIcon: icons.contribs,
|
|
157
|
+
width: 400,
|
|
158
|
+
height,
|
|
159
|
+
border_radius,
|
|
160
|
+
colors,
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
card.disableAnimations();
|
|
164
|
+
card.setHideBorder(hide_border);
|
|
165
|
+
card.setHideTitle(false);
|
|
166
|
+
// Sanitize color values to prevent XSS
|
|
167
|
+
const safeTextColor = escapeCSSValue(colors.textColor);
|
|
168
|
+
const safeIconColor = escapeCSSValue(colors.iconColor);
|
|
169
|
+
card.setCSS(`
|
|
170
|
+
.description { font: 400 13px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${safeTextColor} }
|
|
171
|
+
.gray { font: 400 12px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${safeTextColor} }
|
|
172
|
+
.icon { fill: ${safeIconColor} }
|
|
173
|
+
.badge { font: 600 11px 'Segoe UI', Ubuntu, Sans-Serif; }
|
|
174
|
+
.badge rect { opacity: 0.2 }
|
|
175
|
+
`);
|
|
176
|
+
|
|
177
|
+
return card.render(`
|
|
178
|
+
${
|
|
179
|
+
isTemplate
|
|
180
|
+
? // @ts-ignore
|
|
181
|
+
getBadgeSVG(i18n.t("repocard.template"), colors.textColor)
|
|
182
|
+
: isArchived
|
|
183
|
+
? // @ts-ignore
|
|
184
|
+
getBadgeSVG(i18n.t("repocard.archived"), colors.textColor)
|
|
185
|
+
: ""
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
<text class="description" x="25" y="-5">
|
|
189
|
+
${descriptionSvg}
|
|
190
|
+
</text>
|
|
191
|
+
|
|
192
|
+
<g transform="translate(30, ${height - 75})">
|
|
193
|
+
${starAndForkCount}
|
|
194
|
+
</g>
|
|
195
|
+
`);
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
export { renderRepoCard };
|
|
199
|
+
export default renderRepoCard;
|