@stats-forge/github-stats-forge-core 0.1.0 → 0.3.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.d.ts +23 -0
- package/build/api/contributed-to.d.ts.map +1 -0
- package/build/api/contributed-to.js +43 -0
- package/build/api/gist.d.ts +8 -15
- package/build/api/gist.d.ts.map +1 -1
- package/build/api/gist.js +14 -29
- package/build/api/handler.d.ts +16 -0
- package/build/api/handler.d.ts.map +1 -0
- package/build/api/handler.js +29 -0
- 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/params.d.ts +11 -5
- package/build/api/params.d.ts.map +1 -1
- package/build/api/params.js +26 -6
- package/build/api/pin.d.ts +11 -15
- package/build/api/pin.d.ts.map +1 -1
- package/build/api/pin.js +34 -46
- package/build/api/stats.d.ts +15 -22
- package/build/api/stats.d.ts.map +1 -1
- package/build/api/stats.js +59 -72
- package/build/api/top-langs.d.ts +11 -22
- package/build/api/top-langs.d.ts.map +1 -1
- package/build/api/top-langs.js +34 -51
- package/build/api/wakatime.d.ts +10 -24
- package/build/api/wakatime.d.ts.map +1 -1
- package/build/api/wakatime.js +27 -47
- package/build/cards/contributed-to.d.ts +19 -0
- package/build/cards/contributed-to.d.ts.map +1 -0
- package/build/cards/contributed-to.js +242 -0
- package/build/cards/gist.d.ts +1 -0
- package/build/cards/gist.d.ts.map +1 -1
- package/build/cards/gist.js +13 -9
- package/build/cards/repo.d.ts +12 -1
- package/build/cards/repo.d.ts.map +1 -1
- package/build/cards/repo.js +40 -18
- package/build/cards/stats.d.ts +15 -3
- package/build/cards/stats.d.ts.map +1 -1
- package/build/cards/stats.js +91 -76
- package/build/cards/top-languages.d.ts +13 -2
- package/build/cards/top-languages.d.ts.map +1 -1
- package/build/cards/top-languages.js +26 -9
- package/build/cards/wakatime.d.ts +13 -2
- package/build/cards/wakatime.d.ts.map +1 -1
- package/build/cards/wakatime.js +22 -9
- package/build/common/Card.d.ts +9 -0
- package/build/common/Card.d.ts.map +1 -1
- package/build/common/Card.js +44 -9
- package/build/common/I18n.d.ts +1 -1
- package/build/common/I18n.d.ts.map +1 -1
- package/build/common/I18n.js +4 -2
- package/build/common/brand.d.ts +76 -0
- package/build/common/brand.d.ts.map +1 -0
- package/build/common/brand.js +73 -0
- package/build/common/constants.d.ts +3 -1
- package/build/common/constants.d.ts.map +1 -1
- package/build/common/constants.js +3 -1
- package/build/common/date.d.ts +50 -3
- package/build/common/date.d.ts.map +1 -1
- package/build/common/date.js +104 -2
- package/build/common/icons.d.ts +4 -2
- package/build/common/icons.d.ts.map +1 -1
- package/build/common/icons.js +10 -5
- package/build/common/ops.d.ts +8 -3
- package/build/common/ops.d.ts.map +1 -1
- package/build/common/ops.js +8 -14
- package/build/common/render.d.ts +7 -1
- package/build/common/render.d.ts.map +1 -1
- package/build/common/render.js +69 -61
- package/build/fetchers/contributed-to.d.ts +62 -0
- package/build/fetchers/contributed-to.d.ts.map +1 -0
- package/build/fetchers/contributed-to.js +184 -0
- package/build/fetchers/graphql-error.d.ts +13 -0
- package/build/fetchers/graphql-error.d.ts.map +1 -0
- package/build/fetchers/graphql-error.js +29 -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/stats.d.ts +14 -8
- package/build/fetchers/stats.d.ts.map +1 -1
- package/build/fetchers/stats.js +72 -195
- package/build/fetchers/top-languages.d.ts.map +1 -1
- package/build/fetchers/top-languages.js +3 -18
- package/build/fetchers/types.d.ts +24 -0
- package/build/fetchers/types.d.ts.map +1 -1
- package/build/graphql/contributionsCollection.d.ts +9 -0
- package/build/graphql/contributionsCollection.d.ts.map +1 -0
- package/build/graphql/contributionsCollection.js +12 -0
- package/build/graphql/contributionsDocument.d.ts +5 -5
- package/build/graphql/contributionsDocument.d.ts.map +1 -1
- package/build/graphql/contributionsDocument.js +8 -15
- package/build/graphql/generated/contributed-to.d.ts +22 -0
- package/build/graphql/generated/contributed-to.d.ts.map +1 -0
- package/build/graphql/generated/contributed-to.js +11 -0
- package/build/graphql/generated/stats.d.ts +13 -1
- package/build/graphql/generated/stats.d.ts.map +1 -1
- package/build/graphql/generated/stats.js +2 -2
- package/build/graphql/graphqlDocument.d.ts +1 -1
- package/build/graphql/reposContributedToDocument.d.ts.map +1 -1
- package/build/graphql/reposContributedToDocument.js +11 -5
- package/build/translations.d.ts +64 -1
- package/build/translations.d.ts.map +1 -1
- package/build/translations.js +65 -1
- package/package.json +1 -1
- package/src/api/contributed-to.ts +84 -0
- package/src/api/gist.ts +20 -37
- package/src/api/handler.ts +42 -0
- package/src/api/index.ts +1 -0
- package/src/api/params.ts +48 -9
- package/src/api/pin.ts +33 -45
- package/src/api/stats.ts +78 -89
- package/src/api/top-langs.ts +34 -56
- package/src/api/wakatime.ts +33 -54
- package/src/cards/contributed-to.ts +373 -0
- package/src/cards/gist.ts +17 -8
- package/src/cards/repo.ts +44 -20
- package/src/cards/stats.ts +119 -90
- package/src/cards/top-languages.ts +27 -18
- package/src/cards/wakatime.ts +23 -13
- package/src/common/Card.ts +56 -11
- package/src/common/I18n.ts +4 -2
- package/src/common/brand.ts +109 -0
- package/src/common/constants.ts +4 -1
- package/src/common/date.ts +135 -3
- package/src/common/icons.ts +10 -5
- package/src/common/ops.ts +10 -19
- package/src/common/render.ts +75 -65
- package/src/fetchers/contributed-to.ts +271 -0
- package/src/fetchers/graphql-error.ts +36 -0
- package/src/fetchers/index.ts +3 -0
- package/src/fetchers/stats.ts +123 -274
- package/src/fetchers/top-languages.ts +5 -19
- package/src/fetchers/types.ts +26 -0
- package/src/graphql/contributionsCollection.ts +18 -0
- package/src/graphql/contributionsDocument.ts +11 -18
- package/src/graphql/generated/contributed-to.ts +25 -0
- package/src/graphql/generated/stats.ts +19 -6
- package/src/graphql/graphqlDocument.ts +1 -1
- package/src/graphql/queries/contributed-to.graphql +8 -0
- package/src/graphql/queries/stats.graphql +14 -2
- package/src/graphql/reposContributedToDocument.ts +11 -9
- package/src/translations.ts +77 -0
package/build/cards/stats.js
CHANGED
|
@@ -1,31 +1,50 @@
|
|
|
1
|
+
import { CARD_ICON, CARD_WIDTH, FONT_SIZE, FONT_WEIGHT, firefoxFontSize, font, } from '../common/brand.js';
|
|
1
2
|
import { Card } from '../common/Card.js';
|
|
2
3
|
import { getLightDarkColors } from '../common/color.js';
|
|
4
|
+
import { formatRange } from '../common/date.js';
|
|
3
5
|
import { CardError } from '../common/error.js';
|
|
4
6
|
import { I18n } from '../common/I18n.js';
|
|
5
7
|
import { icons, rankIcon } from '../common/icons.js';
|
|
6
8
|
import { buildSearchFilter, clampValue } from '../common/ops.js';
|
|
7
|
-
import { createTextNode, flexLayout, measureText } from '../common/render.js';
|
|
9
|
+
import { NUMBER_FORMATS, createTextNode, flexLayout, measureText } from '../common/render.js';
|
|
8
10
|
import { atRule, cssComment, el, rule } from '../markup/index.js';
|
|
9
11
|
import { statCardLocales, wakatimeCardLocales } from '../translations.js';
|
|
10
12
|
const CARD_MIN_WIDTH = 287;
|
|
11
|
-
const CARD_DEFAULT_WIDTH =
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const RANK_ONLY_CARD_DEFAULT_WIDTH = 290;
|
|
16
|
-
const STAT_FONT_SIZE = 14;
|
|
13
|
+
const CARD_DEFAULT_WIDTH = CARD_WIDTH.compact;
|
|
14
|
+
const RANK_CARD_DEFAULT_WIDTH = CARD_WIDTH.wide;
|
|
15
|
+
const RANK_ONLY_CARD_DEFAULT_WIDTH = CARD_WIDTH.compact;
|
|
16
|
+
const STAT_FONT_SIZE = FONT_SIZE.body;
|
|
17
17
|
/** Padding the card keeps at its edges; matches `Card`'s own `paddingX`. */
|
|
18
18
|
const CARD_PADDING_X = 25;
|
|
19
19
|
/** How far a stat row is translated into the card; see `createTextNode`. */
|
|
20
20
|
const STAT_ROW_X = 25;
|
|
21
21
|
/** Room the rank ring needs at the right edge, so a value never runs into it. */
|
|
22
22
|
const RANK_GUTTER = 120;
|
|
23
|
+
/** The ring's own `cx`, which its group's translation has to make up for. */
|
|
24
|
+
const RANK_CIRCLE_CX_OFFSET = 10;
|
|
23
25
|
/** `createTextNode`'s own label offset, which it applies only when icons are shown. */
|
|
24
26
|
const LABEL_X_OFFSET = 25;
|
|
25
27
|
/** Smallest gap kept between the longest label and its value. */
|
|
26
28
|
const LABEL_VALUE_GAP = 16;
|
|
27
29
|
/** Rank indicators the card can draw; the api validates `rank_icon` against this. */
|
|
28
30
|
const RANK_ICONS = ['default', 'github', 'percentile'];
|
|
31
|
+
/** Stats the card draws only when `show` names them. */
|
|
32
|
+
const SHOW_STATS = [
|
|
33
|
+
'contributions',
|
|
34
|
+
'prs_merged',
|
|
35
|
+
'prs_merged_percentage',
|
|
36
|
+
'reviews',
|
|
37
|
+
'discussions_started',
|
|
38
|
+
'discussions_answered',
|
|
39
|
+
'prs_authored',
|
|
40
|
+
'prs_commented',
|
|
41
|
+
'prs_reviewed',
|
|
42
|
+
'issues_authored',
|
|
43
|
+
'issues_commented',
|
|
44
|
+
'all_time_contribs',
|
|
45
|
+
];
|
|
46
|
+
/** Stats the card always draws, and so the ones `hide` has anything to remove. */
|
|
47
|
+
const HIDE_STATS = ['stars', 'commits', 'prs', 'issues', 'contribs'];
|
|
29
48
|
/** Long locales that need more space for text. Keep sorted alphabetically. */
|
|
30
49
|
const LONG_LOCALES = new Set([
|
|
31
50
|
'az',
|
|
@@ -80,22 +99,22 @@ const getProgressAnimation = ({ progress }) => atRule('@keyframes rankAnimation'
|
|
|
80
99
|
*/
|
|
81
100
|
const getStyles = ({ textColor, iconColor, ringColor, show_icons, progress, }) => [
|
|
82
101
|
rule('.stat', {
|
|
83
|
-
font:
|
|
102
|
+
font: font('regular', 'body'),
|
|
84
103
|
fill: textColor,
|
|
85
104
|
'font-variant-numeric': 'tabular-nums',
|
|
86
105
|
}),
|
|
87
|
-
|
|
106
|
+
firefoxFontSize(['.stat'], 'small'),
|
|
88
107
|
rule('.stagger', { opacity: 0, animation: 'fadeInAnimation 0.3s ease-in-out forwards' }),
|
|
89
108
|
rule('.rank-text', {
|
|
90
|
-
font:
|
|
109
|
+
font: font('bold', 'display'),
|
|
91
110
|
fill: textColor,
|
|
92
111
|
animation: 'scaleInAnimation 0.3s ease-in-out forwards',
|
|
93
112
|
}),
|
|
94
|
-
rule('.rank-percentile-header', { 'font-size':
|
|
95
|
-
rule('.rank-percentile-text', { 'font-size':
|
|
113
|
+
rule('.rank-percentile-header', { 'font-size': `${String(FONT_SIZE.body)}px` }),
|
|
114
|
+
rule('.rank-percentile-text', { 'font-size': `${String(FONT_SIZE.lead)}px` }),
|
|
96
115
|
cssComment('Labels recede so that the values read first.'),
|
|
97
|
-
rule('.not_bold', { 'font-weight':
|
|
98
|
-
rule('.bold', { 'font-weight':
|
|
116
|
+
rule('.not_bold', { 'font-weight': FONT_WEIGHT.regular, opacity: 0.75 }),
|
|
117
|
+
rule('.bold', { 'font-weight': FONT_WEIGHT.semibold }),
|
|
99
118
|
rule('.icon', {
|
|
100
119
|
fill: iconColor,
|
|
101
120
|
opacity: 0.75,
|
|
@@ -121,25 +140,25 @@ const getStyles = ({ textColor, iconColor, ringColor, show_icons, progress, }) =
|
|
|
121
140
|
getProgressAnimation({ progress }),
|
|
122
141
|
];
|
|
123
142
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
* @returns The label corresponding to the options.
|
|
143
|
+
* @returns What the commit count covers, for the stat's label.
|
|
127
144
|
*/
|
|
128
|
-
const
|
|
145
|
+
const getTotalCommitsRangeLabel = (include_all_commits, commitsRange, i18n) => include_all_commits
|
|
129
146
|
? ''
|
|
130
|
-
:
|
|
131
|
-
? ` (${
|
|
147
|
+
: commitsRange
|
|
148
|
+
? ` (${formatRange(commitsRange)})`
|
|
132
149
|
: ` (${i18n.t('wakatimecard.lastyear')})`;
|
|
133
150
|
/**
|
|
134
151
|
* Renders the stats card.
|
|
135
152
|
*
|
|
136
153
|
* @returns The stats card SVG object.
|
|
137
154
|
*/
|
|
138
|
-
const
|
|
139
|
-
const { name, totalStars, totalCommits, totalIssues, totalPRs, totalPRsMerged, mergedPRsPercentage, totalReviews, totalDiscussionsStarted, totalDiscussionsAnswered, contributedTo, allTimeContributedTo, totalPRsAuthored, totalPRsCommented, totalPRsReviewed, totalIssuesAuthored, totalIssuesCommented, totalContributions, rank, } = stats;
|
|
140
|
-
const { hide = [], show_icons = false, hide_title = false, hide_border = false, card_width, hide_rank = false, include_all_commits = false,
|
|
155
|
+
const renderCard = (stats, options = {}, username, repo = [], owner = []) => {
|
|
156
|
+
const { name, totalStars, totalCommits, commitsRange, totalIssues, totalPRs, totalPRsMerged, mergedPRsPercentage, totalReviews, totalDiscussionsStarted, totalDiscussionsAnswered, contributedTo, allTimeContributedTo, totalPRsAuthored, totalPRsCommented, totalPRsReviewed, totalIssuesAuthored, totalIssuesCommented, totalContributions, rank, } = stats;
|
|
157
|
+
const { hide = [], show_icons = false, hide_title = false, hide_border = false, card_width, hide_rank = false, include_all_commits = false, line_height = 25, text_bold = true, custom_title, border_radius, number_format = 'short', number_precision, locale, disable_animations = false, rank_icon = 'default', show = [], } = options;
|
|
141
158
|
const lheight = Number.parseInt(String(line_height), 10);
|
|
142
159
|
const { lightColors, darkColors } = getLightDarkColors(options);
|
|
160
|
+
// Typed against the exported list, so a stat drawn here cannot be missing from it.
|
|
161
|
+
const shows = (stat) => show.includes(stat);
|
|
143
162
|
const apostrophe = /s$/i.test(name.trim()) ? '' : 's';
|
|
144
163
|
const i18n = new I18n({
|
|
145
164
|
locale,
|
|
@@ -157,7 +176,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
|
|
|
157
176
|
id: 'stars',
|
|
158
177
|
},
|
|
159
178
|
};
|
|
160
|
-
if (
|
|
179
|
+
if (shows('contributions')) {
|
|
161
180
|
STATS['contributions'] = {
|
|
162
181
|
icon: icons.contributions,
|
|
163
182
|
label: i18n.t('statcard.contributions'),
|
|
@@ -167,7 +186,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
|
|
|
167
186
|
}
|
|
168
187
|
STATS['commits'] = {
|
|
169
188
|
icon: icons.commits,
|
|
170
|
-
label: `${i18n.t('statcard.commits')}${
|
|
189
|
+
label: `${i18n.t('statcard.commits')}${getTotalCommitsRangeLabel(include_all_commits, commitsRange, i18n)}`,
|
|
171
190
|
value: totalCommits,
|
|
172
191
|
id: 'commits',
|
|
173
192
|
};
|
|
@@ -177,7 +196,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
|
|
|
177
196
|
value: totalPRs,
|
|
178
197
|
id: 'prs',
|
|
179
198
|
};
|
|
180
|
-
if (
|
|
199
|
+
if (shows('prs_merged')) {
|
|
181
200
|
STATS['prs_merged'] = {
|
|
182
201
|
icon: icons.prs_merged,
|
|
183
202
|
label: i18n.t('statcard.prs-merged'),
|
|
@@ -185,7 +204,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
|
|
|
185
204
|
id: 'prs_merged',
|
|
186
205
|
};
|
|
187
206
|
}
|
|
188
|
-
if (
|
|
207
|
+
if (shows('prs_merged_percentage')) {
|
|
189
208
|
STATS['prs_merged_percentage'] = {
|
|
190
209
|
icon: icons.prs_merged_percentage,
|
|
191
210
|
label: i18n.t('statcard.prs-merged-percentage'),
|
|
@@ -196,7 +215,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
|
|
|
196
215
|
unitSymbol: '%',
|
|
197
216
|
};
|
|
198
217
|
}
|
|
199
|
-
if (
|
|
218
|
+
if (shows('reviews')) {
|
|
200
219
|
STATS['reviews'] = {
|
|
201
220
|
icon: icons.reviews,
|
|
202
221
|
label: i18n.t('statcard.reviews'),
|
|
@@ -210,7 +229,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
|
|
|
210
229
|
value: totalIssues,
|
|
211
230
|
id: 'issues',
|
|
212
231
|
};
|
|
213
|
-
if (
|
|
232
|
+
if (shows('discussions_started')) {
|
|
214
233
|
STATS['discussions_started'] = {
|
|
215
234
|
icon: icons.discussions_started,
|
|
216
235
|
label: i18n.t('statcard.discussions-started'),
|
|
@@ -218,7 +237,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
|
|
|
218
237
|
id: 'discussions_started',
|
|
219
238
|
};
|
|
220
239
|
}
|
|
221
|
-
if (
|
|
240
|
+
if (shows('discussions_answered')) {
|
|
222
241
|
STATS['discussions_answered'] = {
|
|
223
242
|
icon: icons.discussions_answered,
|
|
224
243
|
label: i18n.t('statcard.discussions-answered'),
|
|
@@ -228,7 +247,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
|
|
|
228
247
|
}
|
|
229
248
|
const repoFilter = encodeURIComponent(buildSearchFilter(repo, owner));
|
|
230
249
|
const encodedUsername = encodeURIComponent(username ?? '');
|
|
231
|
-
if (
|
|
250
|
+
if (shows('prs_authored')) {
|
|
232
251
|
STATS['prs_authored'] = {
|
|
233
252
|
icon: icons.prs,
|
|
234
253
|
label: i18n.t('statcard.prs-authored'),
|
|
@@ -237,7 +256,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
|
|
|
237
256
|
link: `https://github.com/search?q=${repoFilter}author%3A${encodedUsername}&type=pullrequests`,
|
|
238
257
|
};
|
|
239
258
|
}
|
|
240
|
-
if (
|
|
259
|
+
if (shows('prs_commented')) {
|
|
241
260
|
STATS['prs_commented'] = {
|
|
242
261
|
icon: icons.comments,
|
|
243
262
|
label: i18n.t('statcard.prs-commented'),
|
|
@@ -246,7 +265,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
|
|
|
246
265
|
link: `https://github.com/search?q=${repoFilter}commenter%3A${encodedUsername}+-author%3A${encodedUsername}&type=pullrequests`,
|
|
247
266
|
};
|
|
248
267
|
}
|
|
249
|
-
if (
|
|
268
|
+
if (shows('prs_reviewed')) {
|
|
250
269
|
STATS['prs_reviewed'] = {
|
|
251
270
|
icon: icons.reviews,
|
|
252
271
|
label: i18n.t('statcard.prs-reviewed'),
|
|
@@ -255,7 +274,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
|
|
|
255
274
|
link: `https://github.com/search?q=${repoFilter}reviewed-by%3A${encodedUsername}+-author%3A${encodedUsername}&type=pullrequests`,
|
|
256
275
|
};
|
|
257
276
|
}
|
|
258
|
-
if (
|
|
277
|
+
if (shows('issues_authored')) {
|
|
259
278
|
STATS['issues_authored'] = {
|
|
260
279
|
icon: icons.issues,
|
|
261
280
|
label: i18n.t('statcard.issues-authored'),
|
|
@@ -264,7 +283,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
|
|
|
264
283
|
link: `https://github.com/search?q=${repoFilter}author%3A${encodedUsername}&type=issues`,
|
|
265
284
|
};
|
|
266
285
|
}
|
|
267
|
-
if (
|
|
286
|
+
if (shows('issues_commented')) {
|
|
268
287
|
STATS['issues_commented'] = {
|
|
269
288
|
icon: icons.discussions_started,
|
|
270
289
|
label: i18n.t('statcard.issues-commented'),
|
|
@@ -274,14 +293,14 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
|
|
|
274
293
|
};
|
|
275
294
|
}
|
|
276
295
|
STATS['contribs'] = {
|
|
277
|
-
icon: icons.
|
|
296
|
+
icon: icons.repo,
|
|
278
297
|
label: i18n.t('statcard.contribs'),
|
|
279
298
|
value: contributedTo,
|
|
280
299
|
id: 'contribs',
|
|
281
300
|
};
|
|
282
|
-
if (
|
|
301
|
+
if (shows('all_time_contribs')) {
|
|
283
302
|
STATS['all_time_contribs'] = {
|
|
284
|
-
icon: icons.
|
|
303
|
+
icon: icons.repo,
|
|
285
304
|
label: i18n.t('statcard.all-time-contribs'),
|
|
286
305
|
value: allTimeContributedTo,
|
|
287
306
|
id: 'all_time_contribs',
|
|
@@ -304,27 +323,21 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
|
|
|
304
323
|
const progress = 100 - rank.percentile;
|
|
305
324
|
const calculateTextWidth = () => measureText(custom_title ||
|
|
306
325
|
(visibleStats.length > 0 ? i18n.t('statcard.title') : i18n.t('statcard.ranktitle')));
|
|
307
|
-
/*
|
|
308
|
-
When hide_rank=true, the minimum card width is 270 px + the title length and padding.
|
|
309
|
-
When hide_rank=false, the minimum card_width is 340 px + the icon width (if show_icons=true).
|
|
310
|
-
Numbers are picked by looking at existing dimensions on production.
|
|
311
|
-
*/
|
|
312
326
|
const iconWidth = show_icons && visibleStats.length > 0 ? 16 + /* padding */ 1 : 0;
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
? RANK_CARD_MIN_WIDTH
|
|
317
|
-
: RANK_ONLY_CARD_MIN_WIDTH) + iconWidth;
|
|
318
|
-
const defaultCardWidth = (hide_rank
|
|
327
|
+
// The icons ride inside the step's own slack, so a default card lands on the width grid;
|
|
328
|
+
// only the minimum, which has no slack, still has to make room for them.
|
|
329
|
+
const defaultCardWidth = hide_rank
|
|
319
330
|
? CARD_DEFAULT_WIDTH
|
|
320
331
|
: visibleStats.length > 0
|
|
321
332
|
? RANK_CARD_DEFAULT_WIDTH
|
|
322
|
-
: RANK_ONLY_CARD_DEFAULT_WIDTH
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
333
|
+
: RANK_ONLY_CARD_DEFAULT_WIDTH;
|
|
334
|
+
// Only a card sized by its own title can outgrow its step: the ranked layouts are fixed,
|
|
335
|
+
// so their step is also their floor.
|
|
336
|
+
const fittedWidth = hide_rank
|
|
337
|
+
? Math.max(defaultCardWidth, clampValue(50 /* padding */ + calculateTextWidth() * 2, CARD_MIN_WIDTH, Infinity) +
|
|
338
|
+
iconWidth)
|
|
339
|
+
: defaultCardWidth;
|
|
340
|
+
const width = card_width ? (Number.isNaN(card_width) ? fittedWidth : card_width) : fittedWidth;
|
|
328
341
|
// A value ends at the card's inner edge, clear of the rank ring — or right after
|
|
329
342
|
// the longest label, on a card too narrow for that.
|
|
330
343
|
const widestLabel = visibleStats.length > 0
|
|
@@ -351,6 +364,7 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
|
|
|
351
364
|
const card = new Card({
|
|
352
365
|
customTitle: custom_title,
|
|
353
366
|
defaultTitle: visibleStats.length > 0 ? i18n.t('statcard.title') : i18n.t('statcard.ranktitle'),
|
|
367
|
+
titlePrefixIcon: CARD_ICON.stats,
|
|
354
368
|
width,
|
|
355
369
|
height,
|
|
356
370
|
border_radius,
|
|
@@ -364,43 +378,31 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
|
|
|
364
378
|
card.disableAnimations();
|
|
365
379
|
}
|
|
366
380
|
/**
|
|
367
|
-
*
|
|
368
|
-
*
|
|
369
|
-
*
|
|
370
|
-
* width > RANK_CARD_DEFAULT_WIDTH: The default right padding of 70 px will be used.
|
|
371
|
-
* width < RANK_CARD_DEFAULT_WIDTH: The left and right padding will be enlarged
|
|
372
|
-
* equally from a certain minimum at RANK_CARD_MIN_WIDTH.
|
|
381
|
+
* The ring sits centred in the same gutter the values are kept clear of, so the gap
|
|
382
|
+
* between them holds at every width; a rank-only card has no values, so it centres.
|
|
373
383
|
*
|
|
374
384
|
* @returns Rank circle translation value.
|
|
375
385
|
*/
|
|
376
|
-
const calculateRankXTranslation = () =>
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
if (width > RANK_CARD_DEFAULT_WIDTH) {
|
|
380
|
-
const xMaxExpansion = minXTranslation + (450 - minCardWidth) / 2;
|
|
381
|
-
return xMaxExpansion + width - RANK_CARD_DEFAULT_WIDTH;
|
|
382
|
-
}
|
|
383
|
-
return minXTranslation + (width - minCardWidth) / 2;
|
|
384
|
-
}
|
|
385
|
-
return width / 2 + 20 - 10;
|
|
386
|
-
};
|
|
386
|
+
const calculateRankXTranslation = () => visibleStats.length > 0
|
|
387
|
+
? width - CARD_PADDING_X - RANK_GUTTER / 2 + RANK_CIRCLE_CX_OFFSET
|
|
388
|
+
: width / 2 + 20 - 10;
|
|
387
389
|
// Conditionally rendered elements
|
|
388
390
|
const rankCircle = !hide_rank &&
|
|
389
391
|
el('g', {
|
|
390
392
|
'data-testid': 'rank-circle',
|
|
391
393
|
transform: `translate(${calculateRankXTranslation()}, ${height / 2 - 50})`,
|
|
392
|
-
}, el('circle', { class: 'rank-circle-rim', cx: -
|
|
394
|
+
}, el('circle', { class: 'rank-circle-rim', cx: -RANK_CIRCLE_CX_OFFSET, cy: 8, r: 40 }), el('circle', { class: 'rank-circle', cx: -RANK_CIRCLE_CX_OFFSET, cy: 8, r: 40 }), el('g', { class: 'rank-text' }, rankIcon(rank_icon, rank.level, rank.percentile)));
|
|
393
395
|
// Accessibility Labels
|
|
394
396
|
const labels = visibleStats
|
|
395
397
|
.map(([key, stat]) => {
|
|
396
398
|
if (key === 'commits') {
|
|
397
|
-
return `${i18n.t('statcard.commits')} ${
|
|
399
|
+
return `${i18n.t('statcard.commits')} ${getTotalCommitsRangeLabel(include_all_commits, commitsRange, i18n)} : ${stat.value}`;
|
|
398
400
|
}
|
|
399
401
|
return `${stat.label}: ${stat.value}`;
|
|
400
402
|
})
|
|
401
403
|
.join(', ');
|
|
402
404
|
card.setAccessibilityLabel({
|
|
403
|
-
title: `${card.title},
|
|
405
|
+
title: `${card.title}, ${i18n.t('statcard.rank')}: ${rank.level}`,
|
|
404
406
|
desc: labels,
|
|
405
407
|
});
|
|
406
408
|
return card.render([
|
|
@@ -408,4 +410,17 @@ const renderStatsCard = (stats, options = {}, username, repo = [], owner = []) =
|
|
|
408
410
|
el('svg', { x: 0, y: 0 }, flexLayout({ items: statItems, gap: lheight, direction: 'column' })),
|
|
409
411
|
]);
|
|
410
412
|
};
|
|
411
|
-
|
|
413
|
+
/**
|
|
414
|
+
* The card, and the values each of its options accepts, keyed by the option's own name.
|
|
415
|
+
* They ride on the renderer so a list cannot be found without what draws it;
|
|
416
|
+
* the api handler forwards them onto its own export, which is what a UI reads.
|
|
417
|
+
*/
|
|
418
|
+
const renderStatsCard = Object.assign(renderCard, {
|
|
419
|
+
OPTIONS: {
|
|
420
|
+
rank_icon: RANK_ICONS,
|
|
421
|
+
show: SHOW_STATS,
|
|
422
|
+
hide: HIDE_STATS,
|
|
423
|
+
number_format: NUMBER_FORMATS,
|
|
424
|
+
},
|
|
425
|
+
});
|
|
426
|
+
export { renderStatsCard };
|
|
@@ -122,6 +122,17 @@ declare const getDefaultLanguagesCountByLayout: ({ layout, hide_progress, }: {
|
|
|
122
122
|
*
|
|
123
123
|
* @returns Language card SVG object.
|
|
124
124
|
*/
|
|
125
|
-
declare const
|
|
126
|
-
|
|
125
|
+
declare const renderCard: (topLangs: TopLangData, options?: CardOptions<TopLangOptions>) => string;
|
|
126
|
+
/**
|
|
127
|
+
* The card, and the values each of its options accepts, keyed by the option's own name.
|
|
128
|
+
* They ride on the renderer so a list cannot be found without what draws it;
|
|
129
|
+
* the api handler forwards them onto its own export, which is what a UI reads.
|
|
130
|
+
*/
|
|
131
|
+
declare const renderTopLanguages: typeof renderCard & {
|
|
132
|
+
OPTIONS: {
|
|
133
|
+
layout: readonly ["compact", "normal", "donut", "donut-vertical", "pie"];
|
|
134
|
+
stats_format: readonly ["percentages", "bytes"];
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
export { getLongestLang, degreesToRadians, radiansToDegrees, polarToCartesian, cartesianToPolar, getCircleLength, calculateCompactLayoutHeight, calculateNormalLayoutHeight, calculateDonutLayoutHeight, calculateDonutVerticalLayoutHeight, calculatePieLayoutHeight, donutCenterTranslation, trimTopLanguages, MIN_CARD_WIDTH, getDefaultLanguagesCountByLayout, renderTopLanguages, };
|
|
127
138
|
//# sourceMappingURL=top-languages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"top-languages.d.ts","sourceRoot":"","sources":["../../src/cards/top-languages.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"top-languages.d.ts","sourceRoot":"","sources":["../../src/cards/top-languages.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CARD_ICON, CARD_WIDTH, FONT_WEIGHT, firefoxFontSize, font } from '../common/brand.js';
|
|
1
2
|
import { Card } from '../common/Card.js';
|
|
2
3
|
import { getLightDarkColors, isPrefixedHexColor } from '../common/color.js';
|
|
3
4
|
import { formatBytes } from '../common/fmt.js';
|
|
@@ -5,9 +6,9 @@ import { I18n } from '../common/I18n.js';
|
|
|
5
6
|
import { DEFAULT_LANG_COLOR } from '../common/languageColors.js';
|
|
6
7
|
import { chunkArray, clampValue, lowercaseTrim } from '../common/ops.js';
|
|
7
8
|
import { createProgressNode, flexLayout, measureText } from '../common/render.js';
|
|
8
|
-
import { atRule,
|
|
9
|
+
import { atRule, el, rule } from '../markup/index.js';
|
|
9
10
|
import { langCardLocales } from '../translations.js';
|
|
10
|
-
const DEFAULT_CARD_WIDTH =
|
|
11
|
+
const DEFAULT_CARD_WIDTH = CARD_WIDTH.compact;
|
|
11
12
|
const MIN_CARD_WIDTH = 280;
|
|
12
13
|
const CARD_PADDING = 25;
|
|
13
14
|
const COMPACT_LAYOUT_BASE_HEIGHT = 90;
|
|
@@ -15,6 +16,8 @@ const MAXIMUM_LANGS_COUNT = 20;
|
|
|
15
16
|
const NORMAL_LAYOUT_DEFAULT_LANGS_COUNT = 5;
|
|
16
17
|
const COMPACT_LAYOUT_DEFAULT_LANGS_COUNT = 6;
|
|
17
18
|
const DONUT_LAYOUT_DEFAULT_LANGS_COUNT = 5;
|
|
19
|
+
/** Room for the chart that sits beside the language list. */
|
|
20
|
+
const DONUT_EXTRA_WIDTH = 50;
|
|
18
21
|
const PIE_LAYOUT_DEFAULT_LANGS_COUNT = 6;
|
|
19
22
|
const DONUT_VERTICAL_LAYOUT_DEFAULT_LANGS_COUNT = 6;
|
|
20
23
|
/** Layouts the card can draw; the api validates `layout` against this. */
|
|
@@ -499,7 +502,7 @@ const getDefaultLanguagesCountByLayout = ({ layout, hide_progress, }) => {
|
|
|
499
502
|
*
|
|
500
503
|
* @returns Language card SVG object.
|
|
501
504
|
*/
|
|
502
|
-
const
|
|
505
|
+
const renderCard = (topLangs, options = {}) => {
|
|
503
506
|
const { hide_title = false, hide_border = false, card_width, hide, hide_progress, hide_values, layout, custom_title, locale, langs_count = getDefaultLanguagesCountByLayout({ layout, hide_progress }), border_radius, disable_animations, stats_format = 'percentages', } = options;
|
|
504
507
|
const i18n = new I18n({
|
|
505
508
|
locale,
|
|
@@ -537,7 +540,9 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|
|
537
540
|
}
|
|
538
541
|
else if (layout === 'donut') {
|
|
539
542
|
height = calculateDonutLayoutHeight(langs.length);
|
|
540
|
-
|
|
543
|
+
// A donut defaults a step wider so the chart has its room; a width asked for
|
|
544
|
+
// explicitly keeps the extra it has always been given instead of being snapped.
|
|
545
|
+
width = width === DEFAULT_CARD_WIDTH ? CARD_WIDTH.standard : width + DONUT_EXTRA_WIDTH;
|
|
541
546
|
finalLayout = renderDonutLayout(langs, width, totalLanguageSize, stats_format, hide_values);
|
|
542
547
|
}
|
|
543
548
|
else {
|
|
@@ -546,6 +551,7 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|
|
546
551
|
const card = new Card({
|
|
547
552
|
customTitle: custom_title,
|
|
548
553
|
defaultTitle: i18n.t('langcard.title'),
|
|
554
|
+
titlePrefixIcon: CARD_ICON.topLanguages,
|
|
549
555
|
width,
|
|
550
556
|
height,
|
|
551
557
|
border_radius,
|
|
@@ -564,12 +570,12 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|
|
564
570
|
rule('to', { width: 'calc(100%-100px)' })),
|
|
565
571
|
atRule('@keyframes growWidthAnimation', rule('from', { width: 0 }), rule('to', { width: '100%' })),
|
|
566
572
|
rule('.stat', {
|
|
567
|
-
font:
|
|
573
|
+
font: font('regular', 'body'),
|
|
568
574
|
fill: textColor,
|
|
569
575
|
}),
|
|
570
|
-
|
|
571
|
-
rule('.bold', { 'font-weight':
|
|
572
|
-
rule('.lang-name', { font: '
|
|
576
|
+
firefoxFontSize(['.stat'], 'small'),
|
|
577
|
+
rule('.bold', { 'font-weight': FONT_WEIGHT.semibold }),
|
|
578
|
+
rule('.lang-name', { font: font('regular', 'micro'), fill: textColor }),
|
|
573
579
|
rule('.stagger', { opacity: 0, animation: 'fadeInAnimation 0.3s ease-in-out forwards' }),
|
|
574
580
|
rule('#rect-mask rect', { animation: 'slideInAnimation 1s ease-in-out forwards' }),
|
|
575
581
|
rule('.lang-progress', { animation: 'growWidthAnimation 0.6s ease-in-out forwards' }),
|
|
@@ -594,4 +600,15 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|
|
594
600
|
}
|
|
595
601
|
return card.render(el('svg', { 'data-testid': 'lang-items', x: CARD_PADDING }, finalLayout));
|
|
596
602
|
};
|
|
597
|
-
|
|
603
|
+
/**
|
|
604
|
+
* The card, and the values each of its options accepts, keyed by the option's own name.
|
|
605
|
+
* They ride on the renderer so a list cannot be found without what draws it;
|
|
606
|
+
* the api handler forwards them onto its own export, which is what a UI reads.
|
|
607
|
+
*/
|
|
608
|
+
const renderTopLanguages = Object.assign(renderCard, {
|
|
609
|
+
OPTIONS: {
|
|
610
|
+
layout: TOP_LANG_LAYOUTS,
|
|
611
|
+
stats_format: TOP_LANG_STATS_FORMATS,
|
|
612
|
+
},
|
|
613
|
+
});
|
|
614
|
+
export { getLongestLang, degreesToRadians, radiansToDegrees, polarToCartesian, cartesianToPolar, getCircleLength, calculateCompactLayoutHeight, calculateNormalLayoutHeight, calculateDonutLayoutHeight, calculateDonutVerticalLayoutHeight, calculatePieLayoutHeight, donutCenterTranslation, trimTopLanguages, MIN_CARD_WIDTH, getDefaultLanguagesCountByLayout, renderTopLanguages, };
|
|
@@ -24,6 +24,17 @@ interface WakaTimeOptions extends CommonCardOptions {
|
|
|
24
24
|
*
|
|
25
25
|
* @returns WakaTime card SVG.
|
|
26
26
|
*/
|
|
27
|
-
declare const
|
|
28
|
-
|
|
27
|
+
declare const renderCard: (stats?: Partial<WakaTimeData>, options?: CardOptions<WakaTimeOptions>) => string;
|
|
28
|
+
/**
|
|
29
|
+
* The card, and the values each of its options accepts, keyed by the option's own name.
|
|
30
|
+
* They ride on the renderer so a list cannot be found without what draws it;
|
|
31
|
+
* the api handler forwards them onto its own export, which is what a UI reads.
|
|
32
|
+
*/
|
|
33
|
+
declare const renderWakatimeCard: typeof renderCard & {
|
|
34
|
+
OPTIONS: {
|
|
35
|
+
layout: readonly ["compact", "normal"];
|
|
36
|
+
display_format: readonly ["time", "percent"];
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
export { renderWakatimeCard };
|
|
29
40
|
//# sourceMappingURL=wakatime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wakatime.d.ts","sourceRoot":"","sources":["../../src/cards/wakatime.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"wakatime.d.ts","sourceRoot":"","sources":["../../src/cards/wakatime.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,sBAAsB,CAAC;AAKvE,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAWnE,0EAA0E;AAC1E,QAAA,MAAM,gBAAgB,YAAI,SAAS,EAAE,QAAQ,CAAU,CAAC;AACxD,KAAK,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAExD,yFAAyF;AACzF,QAAA,MAAM,eAAe,YAAI,MAAM,EAAE,SAAS,CAAU,CAAC;AACrD,KAAK,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtD,UAAU,eAAgB,SAAQ,iBAAiB;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,cAAc,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,aAAa,CAAC;IAC9B,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAgND;;;;GAIG;AACH,QAAA,MAAM,UAAU,WACP,OAAO,CAAC,YAAY,CAAC,YACnB,WAAW,CAAC,eAAe,CAAC,KACpC,MAiNF,CAAC;AAEF;;;;GAIG;AACH,QAAA,MAAM,kBAAkB;;QAEpB,MAAM;QACN,cAAc;;CAEhB,CAAC;AAEH,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
|
package/build/cards/wakatime.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
import { CARD_ICON, CARD_WIDTH, FONT_WEIGHT, firefoxFontSize, font } from '../common/brand.js';
|
|
1
2
|
import { Card } from '../common/Card.js';
|
|
2
3
|
import { getLightDarkColors, isPrefixedHexColor } from '../common/color.js';
|
|
3
4
|
import { I18n } from '../common/I18n.js';
|
|
4
5
|
import { getLanguageColor } from '../common/languageColors.js';
|
|
5
6
|
import { clampValue, lowercaseTrim } from '../common/ops.js';
|
|
6
7
|
import { createProgressNode, flexLayout } from '../common/render.js';
|
|
7
|
-
import { atRule,
|
|
8
|
+
import { atRule, el, rule } from '../markup/index.js';
|
|
8
9
|
import { wakatimeCardLocales } from '../translations.js';
|
|
9
|
-
const DEFAULT_CARD_WIDTH =
|
|
10
|
+
const DEFAULT_CARD_WIDTH = CARD_WIDTH.wide;
|
|
10
11
|
const MIN_CARD_WIDTH = 250;
|
|
11
12
|
const COMPACT_LAYOUT_MIN_WIDTH = 400;
|
|
12
13
|
const DEFAULT_LINE_HEIGHT = 25;
|
|
@@ -118,13 +119,13 @@ const getStyles = ({ textColor }) => {
|
|
|
118
119
|
}
|
|
119
120
|
return [
|
|
120
121
|
rule('.stat', {
|
|
121
|
-
font:
|
|
122
|
+
font: font('regular', 'body'),
|
|
122
123
|
fill: textColor,
|
|
123
124
|
}),
|
|
124
|
-
|
|
125
|
+
firefoxFontSize(['.stat'], 'small'),
|
|
125
126
|
rule('.stagger', { opacity: 0, animation: 'fadeInAnimation 0.3s ease-in-out forwards' }),
|
|
126
|
-
rule('.not_bold', { 'font-weight':
|
|
127
|
-
rule('.bold', { 'font-weight':
|
|
127
|
+
rule('.not_bold', { 'font-weight': FONT_WEIGHT.regular }),
|
|
128
|
+
rule('.bold', { 'font-weight': FONT_WEIGHT.semibold }),
|
|
128
129
|
];
|
|
129
130
|
};
|
|
130
131
|
/** A bar the same color as the text behind it would be invisible, so it goes transparent. */
|
|
@@ -145,7 +146,7 @@ const normalizeCardWidth = ({ value, layout, }) => {
|
|
|
145
146
|
*
|
|
146
147
|
* @returns WakaTime card SVG.
|
|
147
148
|
*/
|
|
148
|
-
const
|
|
149
|
+
const renderCard = (stats = {}, options = {}) => {
|
|
149
150
|
let { languages = [] } = stats;
|
|
150
151
|
const { hide_title = false, hide_border = false, card_width, hide, line_height = DEFAULT_LINE_HEIGHT, hide_progress, custom_title, locale, layout, langs_count = languages.length, border_radius, display_format = 'time', disable_animations, } = options;
|
|
151
152
|
const normalizedWidth = normalizeCardWidth({ value: card_width, layout });
|
|
@@ -261,6 +262,7 @@ const renderWakatimeCard = (stats = {}, options = {}) => {
|
|
|
261
262
|
const card = new Card({
|
|
262
263
|
customTitle: custom_title,
|
|
263
264
|
defaultTitle: titleText,
|
|
265
|
+
titlePrefixIcon: CARD_ICON.wakatime,
|
|
264
266
|
width: normalizedWidth,
|
|
265
267
|
height,
|
|
266
268
|
border_radius,
|
|
@@ -279,7 +281,7 @@ const renderWakatimeCard = (stats = {}, options = {}) => {
|
|
|
279
281
|
// declaration and animate to the rect's own width, which is the reveal the mask wants.
|
|
280
282
|
rule('to', { width: 'calc(100%-100px)' })),
|
|
281
283
|
atRule('@keyframes growWidthAnimation', rule('from', { width: 0 }), rule('to', { width: '100%' })),
|
|
282
|
-
rule('.lang-name', { font:
|
|
284
|
+
rule('.lang-name', { font: font('regular', 'micro'), fill: textColor }),
|
|
283
285
|
rule('#rect-mask rect', { animation: 'slideInAnimation 1s ease-in-out forwards' }),
|
|
284
286
|
rule('.lang-progress', {
|
|
285
287
|
animation: 'growWidthAnimation 0.6s ease-in-out forwards',
|
|
@@ -306,4 +308,15 @@ const renderWakatimeCard = (stats = {}, options = {}) => {
|
|
|
306
308
|
});
|
|
307
309
|
return card.render(el('svg', { x: 0, y: 0, width: '100%' }, finalLayout));
|
|
308
310
|
};
|
|
309
|
-
|
|
311
|
+
/**
|
|
312
|
+
* The card, and the values each of its options accepts, keyed by the option's own name.
|
|
313
|
+
* They ride on the renderer so a list cannot be found without what draws it;
|
|
314
|
+
* the api handler forwards them onto its own export, which is what a UI reads.
|
|
315
|
+
*/
|
|
316
|
+
const renderWakatimeCard = Object.assign(renderCard, {
|
|
317
|
+
OPTIONS: {
|
|
318
|
+
layout: WAKATIME_LAYOUTS,
|
|
319
|
+
display_format: DISPLAY_FORMATS,
|
|
320
|
+
},
|
|
321
|
+
});
|
|
322
|
+
export { renderWakatimeCard };
|
package/build/common/Card.d.ts
CHANGED
|
@@ -59,6 +59,15 @@ declare class Card {
|
|
|
59
59
|
setTitle(text: string): void;
|
|
60
60
|
/** @returns The rendered card title. */
|
|
61
61
|
renderTitle(): MarkupElement;
|
|
62
|
+
/** Where the body starts, and so where the title band ends. */
|
|
63
|
+
private get bodyOffset();
|
|
64
|
+
/**
|
|
65
|
+
* The band behind the title. Its top corners follow the card's own and its bottom
|
|
66
|
+
* ones stay square, so it meets the body as an edge rather than a floating box.
|
|
67
|
+
*
|
|
68
|
+
* @returns The rendered title band.
|
|
69
|
+
*/
|
|
70
|
+
private renderTitleBand;
|
|
62
71
|
/** @returns The card's gradient definitions, or nothing when no color is a gradient. */
|
|
63
72
|
renderGradient(): Child;
|
|
64
73
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../src/common/Card.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../src/common/Card.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAKzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C;;GAEG;AACH,KAAK,cAAc,GAAG,CAAC,MAAM,EAAE,UAAU,KAAK,KAAK,CAAC,QAAQ,CAAC,CAAC;AA2C9D,cAAM,IAAI;IACR,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE;QAAE,KAAK,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE,CAAC;IACvD,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IACrB,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,KAAK,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,YAAY,EACV,KAAW,EACX,MAAY,EACZ,aAAiB,EACjB,MAAiD,EACjD,WAAW,EACX,YAAiB,EACjB,eAAe,GAChB,EAAE;QACD,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAEhB,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACnC,MAAM,CAAC,EAAE;YAAE,KAAK,EAAE,UAAU,CAAC;YAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAA;SAAE,CAAC;QACxD,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACjC,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,eAAe,CAAC,EAAE,KAAK,CAAC;KACzB,EAqBA;IAED,iBAAiB,IAAI,IAAI,CAExB;IAED,qBAAqB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAG5E;IAED;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QAAE,KAAK,EAAE,cAAc,CAAC;QAAC,IAAI,EAAE,cAAc,CAAA;KAAE,GAAG,IAAI,CAG7E;IAED,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAElC;IAED,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAQjC;IAED,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE3B;IAED,wCAAwC;IACxC,WAAW,IAAI,aAAa,CAqC3B;IAED,+DAA+D;IAC/D,OAAO,KAAK,UAAU,GAErB;IAED;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAYvB,wFAAwF;IACxF,cAAc,IAAI,KAAK,CAwBtB;IAED;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAqB5B,kCAAkC;IAClC,MAAM,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,CAoF1B;CACF;AAED,OAAO,EAAE,IAAI,EAAE,CAAC"}
|