@stats-forge/github-stats-forge-core 0.0.1 → 0.1.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/README.md +0 -10
- package/build/api/api-result.d.ts +6 -7
- package/build/api/api-result.d.ts.map +1 -1
- package/build/api/api-result.js +4 -5
- package/build/api/gist.d.ts +3 -10
- package/build/api/gist.d.ts.map +1 -1
- package/build/api/gist.js +4 -11
- package/build/api/index.d.ts +12 -12
- package/build/api/params.d.ts +11 -8
- package/build/api/params.d.ts.map +1 -1
- package/build/api/params.js +16 -14
- package/build/api/pin.d.ts +3 -19
- package/build/api/pin.d.ts.map +1 -1
- package/build/api/pin.js +6 -22
- package/build/api/stats.d.ts +10 -4
- package/build/api/stats.d.ts.map +1 -1
- package/build/api/stats.js +6 -32
- package/build/api/top-langs.d.ts +12 -6
- package/build/api/top-langs.d.ts.map +1 -1
- package/build/api/top-langs.js +6 -26
- package/build/api/wakatime.d.ts +13 -5
- package/build/api/wakatime.d.ts.map +1 -1
- package/build/api/wakatime.js +4 -21
- package/build/calculateRank.d.ts +0 -9
- package/build/calculateRank.d.ts.map +1 -1
- package/build/calculateRank.js +12 -17
- package/build/cards/gist.d.ts +2 -4
- package/build/cards/gist.d.ts.map +1 -1
- package/build/cards/gist.js +27 -36
- package/build/cards/options.d.ts +1 -1
- package/build/cards/repo.d.ts +2 -4
- package/build/cards/repo.d.ts.map +1 -1
- package/build/cards/repo.js +61 -93
- package/build/cards/stats.d.ts +3 -8
- package/build/cards/stats.d.ts.map +1 -1
- package/build/cards/stats.js +119 -165
- package/build/cards/top-languages.d.ts +5 -31
- package/build/cards/top-languages.d.ts.map +1 -1
- package/build/cards/top-languages.js +176 -384
- package/build/cards/wakatime.d.ts +4 -6
- package/build/cards/wakatime.d.ts.map +1 -1
- package/build/cards/wakatime.js +118 -185
- package/build/common/Card.d.ts +14 -62
- package/build/common/Card.d.ts.map +1 -1
- package/build/common/Card.js +97 -199
- package/build/common/I18n.d.ts +0 -6
- package/build/common/I18n.d.ts.map +1 -1
- package/build/common/I18n.js +3 -6
- package/build/common/color.d.ts +4 -17
- package/build/common/color.d.ts.map +1 -1
- package/build/common/color.js +67 -49
- package/build/common/config.d.ts +4 -14
- package/build/common/config.d.ts.map +1 -1
- package/build/common/config.js +3 -16
- package/build/common/constants.d.ts +4 -2
- package/build/common/constants.d.ts.map +1 -1
- package/build/common/constants.js +3 -1
- package/build/common/date.d.ts +0 -2
- package/build/common/date.d.ts.map +1 -1
- package/build/common/date.js +0 -2
- package/build/common/emojiMap.d.ts +8 -0
- package/build/common/emojiMap.d.ts.map +1 -0
- package/build/common/emojiMap.js +10 -0
- package/build/common/emojiMap.json +1915 -0
- package/build/common/error.d.ts +1 -10
- package/build/common/error.d.ts.map +1 -1
- package/build/common/error.js +1 -10
- package/build/common/fmt.d.ts +3 -15
- package/build/common/fmt.d.ts.map +1 -1
- package/build/common/fmt.js +7 -35
- package/build/common/http.d.ts +2 -7
- package/build/common/http.d.ts.map +1 -1
- package/build/common/http.js +8 -17
- package/build/common/icons.d.ts +18 -20
- package/build/common/icons.d.ts.map +1 -1
- package/build/common/icons.js +103 -67
- package/build/common/languageColors.d.ts +0 -1
- package/build/common/languageColors.d.ts.map +1 -1
- package/build/common/languageColors.js +1 -4
- package/build/common/languageColors.json +18 -2
- package/build/common/ops.d.ts +3 -14
- package/build/common/ops.d.ts.map +1 -1
- package/build/common/ops.js +19 -30
- package/build/common/render.d.ts +28 -82
- package/build/common/render.d.ts.map +1 -1
- package/build/common/render.js +175 -211
- package/build/common/retryer.d.ts +2 -7
- package/build/common/retryer.d.ts.map +1 -1
- package/build/common/retryer.js +4 -11
- package/build/fetchers/gist.d.ts +2 -5
- package/build/fetchers/gist.d.ts.map +1 -1
- package/build/fetchers/gist.js +1 -5
- package/build/fetchers/index.d.ts +12 -12
- package/build/fetchers/repo.d.ts +2 -11
- package/build/fetchers/repo.d.ts.map +1 -1
- package/build/fetchers/repo.js +20 -33
- package/build/fetchers/stats.d.ts +2 -32
- package/build/fetchers/stats.d.ts.map +1 -1
- package/build/fetchers/stats.js +27 -86
- package/build/fetchers/top-languages.d.ts +2 -9
- package/build/fetchers/top-languages.d.ts.map +1 -1
- package/build/fetchers/top-languages.js +15 -31
- package/build/fetchers/types.d.ts +1 -1
- package/build/fetchers/wakatime.d.ts +2 -6
- package/build/fetchers/wakatime.d.ts.map +1 -1
- package/build/fetchers/wakatime.js +1 -5
- package/build/graphql/contributionsDocument.d.ts +3 -3
- package/build/graphql/contributionsDocument.d.ts.map +1 -1
- package/build/graphql/contributionsDocument.js +0 -1
- package/build/graphql/generated/gist.d.ts +1 -1
- package/build/graphql/generated/repo.d.ts +1 -1
- package/build/graphql/generated/stats.d.ts +3 -3
- package/build/graphql/generated/top-languages.d.ts +2 -2
- package/build/graphql/graphqlDocument.d.ts +0 -1
- package/build/graphql/graphqlDocument.d.ts.map +1 -1
- package/build/graphql/graphqlDocument.js +0 -1
- package/build/graphql/reposContributedToDocument.d.ts +4 -5
- package/build/graphql/reposContributedToDocument.d.ts.map +1 -1
- package/build/graphql/reposContributedToDocument.js +0 -2
- package/build/markup/css.d.ts +35 -0
- package/build/markup/css.d.ts.map +1 -0
- package/build/markup/css.js +64 -0
- package/build/markup/element.d.ts +41 -0
- package/build/markup/element.d.ts.map +1 -0
- package/build/markup/element.js +127 -0
- package/build/markup/html.d.ts +13 -0
- package/build/markup/html.d.ts.map +1 -0
- package/build/markup/html.js +27 -0
- package/build/markup/index.d.ts +9 -0
- package/build/markup/index.d.ts.map +1 -0
- package/build/markup/index.js +6 -0
- package/build/markup/serialize.d.ts +16 -0
- package/build/markup/serialize.d.ts.map +1 -0
- package/build/markup/serialize.js +17 -0
- package/build/themes/index.d.ts +332 -333
- package/build/themes/index.d.ts.map +1 -1
- package/build/themes/index.js +1 -1
- package/build/translations.d.ts +2 -6
- package/build/translations.d.ts.map +1 -1
- package/build/translations.js +621 -628
- package/package.json +17 -26
- package/src/api/api-result.ts +10 -9
- package/src/api/gist.ts +11 -18
- package/src/api/index.ts +12 -12
- package/src/api/params.ts +27 -21
- package/src/api/pin.ts +13 -28
- package/src/api/stats.ts +13 -39
- package/src/api/top-langs.ts +13 -33
- package/src/api/wakatime.ts +11 -28
- package/src/calculateRank.ts +12 -23
- package/src/cards/gist.ts +40 -43
- package/src/cards/options.ts +1 -1
- package/src/cards/repo.ts +97 -107
- package/src/cards/stats.ts +165 -184
- package/src/cards/top-languages.ts +297 -413
- package/src/cards/wakatime.ts +193 -221
- package/src/common/Card.ts +165 -217
- package/src/common/I18n.ts +3 -6
- package/src/common/color.ts +80 -57
- package/src/common/config.ts +5 -18
- package/src/common/constants.ts +5 -2
- package/src/common/date.ts +0 -2
- package/src/common/emojiMap.json +1915 -0
- package/src/common/emojiMap.ts +13 -0
- package/src/common/error.ts +2 -11
- package/src/common/fmt.ts +7 -44
- package/src/common/http.ts +9 -15
- package/src/common/icons.ts +117 -42
- package/src/common/languageColors.json +18 -2
- package/src/common/languageColors.ts +1 -4
- package/src/common/ops.ts +26 -34
- package/src/common/render.ts +279 -232
- package/src/common/retryer.ts +8 -15
- package/src/fetchers/gist.ts +8 -12
- package/src/fetchers/index.ts +12 -12
- package/src/fetchers/repo.ts +27 -40
- package/src/fetchers/stats.ts +44 -102
- package/src/fetchers/top-languages.ts +26 -40
- package/src/fetchers/types.ts +1 -1
- package/src/fetchers/wakatime.ts +5 -9
- package/src/graphql/contributionsDocument.ts +7 -5
- package/src/graphql/generated/gist.ts +1 -1
- package/src/graphql/generated/repo.ts +1 -1
- package/src/graphql/generated/stats.ts +2 -2
- package/src/graphql/generated/top-languages.ts +2 -2
- package/src/graphql/graphqlDocument.ts +0 -1
- package/src/graphql/reposContributedToDocument.ts +6 -7
- package/src/markup/css.ts +118 -0
- package/src/markup/element.ts +246 -0
- package/src/markup/html.ts +34 -0
- package/src/markup/index.ts +9 -0
- package/src/markup/serialize.ts +27 -0
- package/src/themes/index.ts +1 -1
- package/src/translations.ts +622 -629
- package/build/cards/index.d.ts +0 -11
- package/build/cards/index.d.ts.map +0 -1
- package/build/cards/index.js +0 -7
- package/build/common/html.d.ts +0 -8
- package/build/common/html.d.ts.map +0 -1
- package/build/common/html.js +0 -14
- package/build/index.d.ts +0 -15
- package/build/index.d.ts.map +0 -1
- package/build/index.js +0 -10
- package/src/_emoji-name-map.d.ts +0 -10
- package/src/_github-username-regex.d.ts +0 -4
- package/src/cards/index.ts +0 -21
- package/src/common/html.ts +0 -17
- package/src/index.ts +0 -18
package/src/cards/wakatime.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { Card } from '../common/Card.
|
|
2
|
-
import { getLightDarkColors, isPrefixedHexColor } from '../common/color.
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import type {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import { Card } from '../common/Card.ts';
|
|
2
|
+
import { getLightDarkColors, isPrefixedHexColor } from '../common/color.ts';
|
|
3
|
+
import { I18n } from '../common/I18n.ts';
|
|
4
|
+
import { getLanguageColor } from '../common/languageColors.ts';
|
|
5
|
+
import { clampValue, lowercaseTrim } from '../common/ops.ts';
|
|
6
|
+
import { createProgressNode, flexLayout } from '../common/render.ts';
|
|
7
|
+
import type { WakaTimeData, WakaTimeLang } from '../fetchers/types.ts';
|
|
8
|
+
import type { Child, CssChild, MarkupElement } from '../markup/index.ts';
|
|
9
|
+
import { atRule, cssComment, el, rule } from '../markup/index.ts';
|
|
10
|
+
import { wakatimeCardLocales } from '../translations.ts';
|
|
11
|
+
|
|
12
|
+
import type { CardOptions, CommonCardOptions } from './options.ts';
|
|
12
13
|
|
|
13
14
|
const DEFAULT_CARD_WIDTH = 495;
|
|
14
15
|
const MIN_CARD_WIDTH = 250;
|
|
@@ -44,22 +45,14 @@ interface WakaTimeOptions extends CommonCardOptions {
|
|
|
44
45
|
/**
|
|
45
46
|
* Creates the no coding activity SVG node.
|
|
46
47
|
*
|
|
47
|
-
* @param props The function properties.
|
|
48
|
-
* @param props.text No coding activity translated text.
|
|
49
48
|
* @returns No coding activity SVG node string.
|
|
50
49
|
*/
|
|
51
|
-
const noCodingActivityNode = ({ text }: { text: string }):
|
|
52
|
-
|
|
53
|
-
<text x="25" y="11" class="stat bold">${encodeHTML(text)}</text>
|
|
54
|
-
`;
|
|
55
|
-
};
|
|
50
|
+
const noCodingActivityNode = ({ text }: { text: string }): MarkupElement =>
|
|
51
|
+
el('text', { x: 25, y: 11, class: 'stat bold' }, text);
|
|
56
52
|
|
|
57
53
|
/**
|
|
58
54
|
* Format language value.
|
|
59
55
|
*
|
|
60
|
-
* @param args The function arguments.
|
|
61
|
-
* @param args.lang The language object.
|
|
62
|
-
* @param args.display_format The display format of the language node.
|
|
63
56
|
* @returns The formatted language value.
|
|
64
57
|
*/
|
|
65
58
|
const formatLanguageValue = ({
|
|
@@ -68,18 +61,11 @@ const formatLanguageValue = ({
|
|
|
68
61
|
}: {
|
|
69
62
|
display_format: DisplayFormat;
|
|
70
63
|
lang: WakaTimeLang;
|
|
71
|
-
}): string => {
|
|
72
|
-
return display_format === 'percent' ? `${lang.percent.toFixed(2)} %` : lang.text;
|
|
73
|
-
};
|
|
64
|
+
}): string => (display_format === 'percent' ? `${lang.percent.toFixed(2)} %` : lang.text);
|
|
74
65
|
|
|
75
66
|
/**
|
|
76
67
|
* Create compact WakaTime layout.
|
|
77
68
|
*
|
|
78
|
-
* @param args The function arguments.
|
|
79
|
-
* @param args.lang The languages array.
|
|
80
|
-
* @param args.x The x position of the language node.
|
|
81
|
-
* @param args.y The y position of the language node.
|
|
82
|
-
* @param args.display_format The display format of the language node.
|
|
83
69
|
* @returns The compact layout language SVG node.
|
|
84
70
|
*/
|
|
85
71
|
const createCompactLangNode = ({
|
|
@@ -92,35 +78,32 @@ const createCompactLangNode = ({
|
|
|
92
78
|
x: number;
|
|
93
79
|
y: number;
|
|
94
80
|
display_format: DisplayFormat;
|
|
95
|
-
}):
|
|
81
|
+
}): MarkupElement => {
|
|
96
82
|
if (!Number.isFinite(x)) {
|
|
97
|
-
throw new
|
|
83
|
+
throw new TypeError(`Invalid x: "${x}"`);
|
|
98
84
|
}
|
|
99
85
|
if (!Number.isFinite(y)) {
|
|
100
|
-
throw new
|
|
86
|
+
throw new TypeError(`Invalid y: "${y}"`);
|
|
101
87
|
}
|
|
102
88
|
|
|
103
89
|
const color = getLanguageColor(lang.name);
|
|
104
90
|
const value = formatLanguageValue({ display_format, lang });
|
|
105
91
|
|
|
106
|
-
return
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
92
|
+
return el(
|
|
93
|
+
'g',
|
|
94
|
+
{ transform: `translate(${x}, ${y})` },
|
|
95
|
+
el('circle', { cx: 5, cy: 6, r: 5, fill: color }),
|
|
96
|
+
el(
|
|
97
|
+
'text',
|
|
98
|
+
{ 'data-testid': 'lang-name', x: 15, y: 10, class: 'lang-name' },
|
|
99
|
+
`${lang.name} - ${value}`,
|
|
100
|
+
),
|
|
101
|
+
);
|
|
114
102
|
};
|
|
115
103
|
|
|
116
104
|
/**
|
|
117
105
|
* Create WakaTime language text node item.
|
|
118
106
|
*
|
|
119
|
-
* @param args The function arguments.
|
|
120
|
-
* @param args.langs The language objects.
|
|
121
|
-
* @param args.y The y position of the language node.
|
|
122
|
-
* @param args.display_format The display format of the language node.
|
|
123
|
-
* @param args.card_width Width in px of the card.
|
|
124
107
|
* @returns The language text node items.
|
|
125
108
|
*/
|
|
126
109
|
const createLanguageTextNode = ({
|
|
@@ -133,7 +116,7 @@ const createLanguageTextNode = ({
|
|
|
133
116
|
y: number;
|
|
134
117
|
display_format: DisplayFormat;
|
|
135
118
|
card_width: number;
|
|
136
|
-
}): Array<
|
|
119
|
+
}): Array<Child> => {
|
|
137
120
|
const LEFT_X = 25;
|
|
138
121
|
const RIGHT_X_BASE = 230;
|
|
139
122
|
const rightOffset = (card_width - DEFAULT_CARD_WIDTH) / 2;
|
|
@@ -153,14 +136,6 @@ const createLanguageTextNode = ({
|
|
|
153
136
|
/**
|
|
154
137
|
* Create WakaTime text item.
|
|
155
138
|
*
|
|
156
|
-
* @param args The function arguments.
|
|
157
|
-
* @param args.id The id of the text node item.
|
|
158
|
-
* @param args.label The label of the text node item.
|
|
159
|
-
* @param args.value The value of the text node item.
|
|
160
|
-
* @param args.index The index of the text node item.
|
|
161
|
-
* @param args.percent Percentage of the text node item.
|
|
162
|
-
* @param args.hideProgress Whether to hide the progress bar.
|
|
163
|
-
* @param args.progressBarWidth The width of the progress bar.
|
|
164
139
|
* @returns The text SVG node.
|
|
165
140
|
*/
|
|
166
141
|
const createTextNode = ({
|
|
@@ -179,87 +154,89 @@ const createTextNode = ({
|
|
|
179
154
|
percent: number;
|
|
180
155
|
hideProgress?: boolean | undefined;
|
|
181
156
|
progressBarWidth: number;
|
|
182
|
-
}):
|
|
157
|
+
}): MarkupElement => {
|
|
183
158
|
if (!Number.isFinite(index)) {
|
|
184
|
-
throw new
|
|
159
|
+
throw new TypeError(`Invalid index: "${index}"`);
|
|
185
160
|
}
|
|
186
161
|
if (!Number.isFinite(progressBarWidth)) {
|
|
187
|
-
throw new
|
|
162
|
+
throw new TypeError(`Invalid progressBarWidth: "${progressBarWidth}"`);
|
|
188
163
|
}
|
|
189
164
|
|
|
190
165
|
const staggerDelay = (index + 3) * 150;
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
166
|
+
|
|
167
|
+
return el(
|
|
168
|
+
'g',
|
|
169
|
+
{
|
|
170
|
+
class: 'stagger',
|
|
171
|
+
style: `animation-delay: ${staggerDelay}ms`,
|
|
172
|
+
transform: 'translate(25, 0)',
|
|
173
|
+
},
|
|
174
|
+
el('text', { class: 'stat bold', y: 12.5, 'data-testid': id }, `${label}:`),
|
|
175
|
+
el(
|
|
176
|
+
'text',
|
|
177
|
+
{
|
|
178
|
+
class: 'stat',
|
|
179
|
+
x: hideProgress ? HIDDEN_PROGRESSBAR_PADDING : PROGRESSBAR_PADDING + progressBarWidth,
|
|
180
|
+
y: 12.5,
|
|
181
|
+
},
|
|
182
|
+
value,
|
|
183
|
+
),
|
|
184
|
+
!hideProgress &&
|
|
185
|
+
createProgressNode({
|
|
194
186
|
x: 110,
|
|
195
187
|
y: 4,
|
|
196
188
|
progress: percent,
|
|
197
189
|
width: progressBarWidth,
|
|
198
190
|
delay: staggerDelay + 300,
|
|
199
|
-
})
|
|
200
|
-
|
|
201
|
-
return `
|
|
202
|
-
<g class="stagger" style="animation-delay: ${staggerDelay}ms" transform="translate(25, 0)">
|
|
203
|
-
<text class="stat bold" y="12.5" data-testid="${encodeHTML(id)}">${encodeHTML(label)}:</text>
|
|
204
|
-
<text
|
|
205
|
-
class="stat"
|
|
206
|
-
x="${hideProgress ? HIDDEN_PROGRESSBAR_PADDING : PROGRESSBAR_PADDING + progressBarWidth}"
|
|
207
|
-
y="12.5"
|
|
208
|
-
>${encodeHTML(value)}</text>
|
|
209
|
-
${String(cardProgress)}
|
|
210
|
-
</g>
|
|
211
|
-
`;
|
|
191
|
+
}),
|
|
192
|
+
);
|
|
212
193
|
};
|
|
213
194
|
|
|
214
195
|
/**
|
|
215
196
|
* Recalculating percentages so that, compact layout's progress bar does not break when
|
|
216
197
|
* hiding languages.
|
|
217
|
-
*
|
|
218
|
-
* @param languages The languages array.
|
|
219
198
|
*/
|
|
220
199
|
const recalculatePercentages = (languages: Array<WakaTimeLang>): void => {
|
|
221
|
-
const totalSum = languages.reduce((
|
|
222
|
-
const weight =
|
|
223
|
-
|
|
224
|
-
language.percent =
|
|
225
|
-
}
|
|
200
|
+
const totalSum = languages.reduce((sum, language) => sum + language.percent, 0);
|
|
201
|
+
const weight = Number((100 / totalSum).toFixed(2));
|
|
202
|
+
for (const language of languages) {
|
|
203
|
+
language.percent = Number((language.percent * weight).toFixed(2));
|
|
204
|
+
}
|
|
226
205
|
};
|
|
227
206
|
|
|
228
207
|
/**
|
|
229
208
|
* Retrieves CSS styles for a card.
|
|
230
209
|
*
|
|
231
|
-
* @param colors The colors to use for the card.
|
|
232
|
-
* @param colors.textColor The text color.
|
|
233
210
|
* @returns Card CSS styles.
|
|
234
211
|
*/
|
|
235
|
-
const getStyles = ({ textColor }: { textColor: string }):
|
|
212
|
+
const getStyles = ({ textColor }: { textColor: string }): Array<CssChild> => {
|
|
236
213
|
if (!isPrefixedHexColor(textColor)) {
|
|
237
214
|
throw new Error(`Invalid text color: "${textColor}"`);
|
|
238
215
|
}
|
|
239
216
|
|
|
240
|
-
return
|
|
241
|
-
.stat {
|
|
242
|
-
font: 600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
}
|
|
252
|
-
.
|
|
253
|
-
|
|
254
|
-
`;
|
|
217
|
+
return [
|
|
218
|
+
rule('.stat', {
|
|
219
|
+
font: `600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif`,
|
|
220
|
+
fill: textColor,
|
|
221
|
+
}),
|
|
222
|
+
atRule(
|
|
223
|
+
'@supports(-moz-appearance: auto)',
|
|
224
|
+
cssComment('Selector detects Firefox'),
|
|
225
|
+
rule('.stat', { 'font-size': '12px' }),
|
|
226
|
+
),
|
|
227
|
+
rule('.stagger', { opacity: 0, animation: 'fadeInAnimation 0.3s ease-in-out forwards' }),
|
|
228
|
+
rule('.not_bold', { 'font-weight': 400 }),
|
|
229
|
+
rule('.bold', { 'font-weight': 700 }),
|
|
230
|
+
];
|
|
255
231
|
};
|
|
256
232
|
|
|
233
|
+
/** A bar the same color as the text behind it would be invisible, so it goes transparent. */
|
|
234
|
+
const progressBackground = (titleColor: string, textColor: string): string =>
|
|
235
|
+
textColor === titleColor ? '#fff0' : textColor;
|
|
236
|
+
|
|
257
237
|
/**
|
|
258
238
|
* Normalize incoming width (string or number) and clamp to minimum.
|
|
259
239
|
*
|
|
260
|
-
* @param args The function arguments.
|
|
261
|
-
* @param args.layout The incoming layout value.
|
|
262
|
-
* @param args.value The incoming width value.
|
|
263
240
|
* @returns The normalized width value.
|
|
264
241
|
*/
|
|
265
242
|
const normalizeCardWidth = ({
|
|
@@ -269,7 +246,7 @@ const normalizeCardWidth = ({
|
|
|
269
246
|
value?: number | undefined;
|
|
270
247
|
layout?: WakaTimeLayout | undefined;
|
|
271
248
|
}): number => {
|
|
272
|
-
if (value === undefined || isNaN(value)) {
|
|
249
|
+
if (value === undefined || Number.isNaN(value)) {
|
|
273
250
|
return DEFAULT_CARD_WIDTH;
|
|
274
251
|
}
|
|
275
252
|
return Math.max(layout === 'compact' ? COMPACT_LAYOUT_MIN_WIDTH : MIN_CARD_WIDTH, value);
|
|
@@ -278,13 +255,11 @@ const normalizeCardWidth = ({
|
|
|
278
255
|
/**
|
|
279
256
|
* Renders WakaTime card.
|
|
280
257
|
*
|
|
281
|
-
* @param stats WakaTime stats.
|
|
282
|
-
* @param options Card options.
|
|
283
258
|
* @returns WakaTime card SVG.
|
|
284
259
|
*/
|
|
285
260
|
const renderWakatimeCard = (
|
|
286
261
|
stats: Partial<WakaTimeData> = {},
|
|
287
|
-
options: CardOptions<WakaTimeOptions> = {
|
|
262
|
+
options: CardOptions<WakaTimeOptions> = {},
|
|
288
263
|
): string => {
|
|
289
264
|
let { languages = [] } = stats;
|
|
290
265
|
const {
|
|
@@ -321,7 +296,7 @@ const renderWakatimeCard = (
|
|
|
321
296
|
translations: wakatimeCardLocales,
|
|
322
297
|
});
|
|
323
298
|
|
|
324
|
-
const lheight = parseInt(String(line_height), 10);
|
|
299
|
+
const lheight = Number.parseInt(String(line_height), 10);
|
|
325
300
|
|
|
326
301
|
const langsCount = clampValue(langs_count, 1, langs_count);
|
|
327
302
|
|
|
@@ -331,11 +306,10 @@ const renderWakatimeCard = (
|
|
|
331
306
|
.filter((language) => language.hours || language.minutes)
|
|
332
307
|
.slice(0, langsCount);
|
|
333
308
|
|
|
334
|
-
//
|
|
335
|
-
// but if rank circle is visible clamp the minimum height to `150`
|
|
309
|
+
// A short language list would otherwise draw a stub card, so 150 is the floor.
|
|
336
310
|
let height = Math.max(45 + (filteredLanguages.length + 1) * lheight, 150);
|
|
337
311
|
|
|
338
|
-
let finalLayout:
|
|
312
|
+
let finalLayout: Child;
|
|
339
313
|
|
|
340
314
|
// RENDER COMPACT LAYOUT
|
|
341
315
|
if (layout === 'compact') {
|
|
@@ -345,87 +319,94 @@ const renderWakatimeCard = (
|
|
|
345
319
|
// progressOffset holds the previous language's width and used to offset the next language
|
|
346
320
|
// so that we can stack them one after another, like this: [--][----][---]
|
|
347
321
|
let progressOffset = 0;
|
|
348
|
-
const compactProgressBar = filteredLanguages
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
322
|
+
const compactProgressBar = filteredLanguages.map((language) => {
|
|
323
|
+
const progress = ((width - COMPACT_LAYOUT_PROGRESSBAR_PADDING) * language.percent) / 100;
|
|
324
|
+
const x = progressOffset;
|
|
325
|
+
progressOffset += progress;
|
|
326
|
+
|
|
327
|
+
return el('rect', {
|
|
328
|
+
mask: 'url(#rect-mask)',
|
|
329
|
+
'data-testid': 'lang-progress',
|
|
330
|
+
x,
|
|
331
|
+
y: 0,
|
|
332
|
+
width: progress,
|
|
333
|
+
height: 8,
|
|
334
|
+
fill: getLanguageColor(language.name),
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
finalLayout = [
|
|
339
|
+
el(
|
|
340
|
+
'mask',
|
|
341
|
+
{ id: 'rect-mask' },
|
|
342
|
+
el('rect', {
|
|
343
|
+
x: COMPACT_LAYOUT_PROGRESSBAR_PADDING,
|
|
344
|
+
y: 0,
|
|
345
|
+
width: width - 2 * COMPACT_LAYOUT_PROGRESSBAR_PADDING,
|
|
346
|
+
height: 8,
|
|
347
|
+
fill: 'white',
|
|
348
|
+
rx: 5,
|
|
349
|
+
}),
|
|
350
|
+
),
|
|
351
|
+
compactProgressBar,
|
|
352
|
+
filteredLanguages.length > 0
|
|
353
|
+
? createLanguageTextNode({
|
|
354
|
+
y: 25,
|
|
355
|
+
langs: filteredLanguages,
|
|
356
|
+
display_format,
|
|
357
|
+
card_width: normalizedWidth,
|
|
358
|
+
})
|
|
359
|
+
: noCodingActivityNode({
|
|
360
|
+
text: stats.is_coding_activity_visible
|
|
361
|
+
? stats.is_other_usage_visible
|
|
362
|
+
? i18n.t('wakatimecard.nocodingactivity')
|
|
363
|
+
: i18n.t('wakatimecard.nocodedetails')
|
|
364
|
+
: i18n.t('wakatimecard.notpublic'),
|
|
365
|
+
}),
|
|
366
|
+
];
|
|
392
367
|
} else {
|
|
393
368
|
finalLayout = flexLayout({
|
|
394
|
-
items:
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
?
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
369
|
+
items:
|
|
370
|
+
filteredLanguages.length > 0
|
|
371
|
+
? filteredLanguages.map((language, index) =>
|
|
372
|
+
createTextNode({
|
|
373
|
+
id: language.name,
|
|
374
|
+
label: language.name,
|
|
375
|
+
value: formatLanguageValue({ display_format, lang: language }),
|
|
376
|
+
index,
|
|
377
|
+
percent: language.percent,
|
|
378
|
+
hideProgress: hide_progress,
|
|
379
|
+
progressBarWidth: normalizedWidth - TOTAL_TEXT_WIDTH,
|
|
380
|
+
}),
|
|
381
|
+
)
|
|
382
|
+
: [
|
|
383
|
+
noCodingActivityNode({
|
|
384
|
+
text: stats.is_coding_activity_visible
|
|
385
|
+
? stats.is_other_usage_visible
|
|
386
|
+
? i18n.t('wakatimecard.nocodingactivity')
|
|
387
|
+
: i18n.t('wakatimecard.nocodedetails')
|
|
388
|
+
: i18n.t('wakatimecard.notpublic'),
|
|
389
|
+
}),
|
|
390
|
+
],
|
|
415
391
|
gap: lheight,
|
|
416
392
|
direction: 'column',
|
|
417
|
-
})
|
|
393
|
+
});
|
|
418
394
|
}
|
|
419
395
|
|
|
420
396
|
// Get title range text
|
|
421
397
|
let titleText = i18n.t('wakatimecard.title');
|
|
422
398
|
switch (stats.range) {
|
|
423
|
-
case 'last_7_days':
|
|
399
|
+
case 'last_7_days': {
|
|
424
400
|
titleText += ` (${i18n.t('wakatimecard.last7days')})`;
|
|
425
401
|
break;
|
|
426
|
-
|
|
402
|
+
}
|
|
403
|
+
case 'last_year': {
|
|
427
404
|
titleText += ` (${i18n.t('wakatimecard.lastyear')})`;
|
|
428
405
|
break;
|
|
406
|
+
}
|
|
407
|
+
default: {
|
|
408
|
+
break;
|
|
409
|
+
}
|
|
429
410
|
}
|
|
430
411
|
|
|
431
412
|
const card = new Card({
|
|
@@ -444,58 +425,49 @@ const renderWakatimeCard = (
|
|
|
444
425
|
card.setHideBorder(hide_border);
|
|
445
426
|
card.setHideTitle(hide_title);
|
|
446
427
|
card.setCSS({
|
|
447
|
-
light: ({ titleColor, textColor }) =>
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
width: 0
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
width: calc(100%-100px)
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
width:
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
fill:
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
dark: ({ titleColor, textColor }) => `
|
|
476
|
-
${getStyles({ textColor })}
|
|
477
|
-
.lang-name { fill: ${textColor} }
|
|
478
|
-
.lang-progress { fill: ${titleColor}; }
|
|
479
|
-
.progress-background { fill: ${textColor === titleColor ? '#fff0' /* transparent */ : textColor}; }
|
|
480
|
-
`,
|
|
428
|
+
light: ({ titleColor, textColor }) => [
|
|
429
|
+
getStyles({ textColor }),
|
|
430
|
+
atRule(
|
|
431
|
+
'@keyframes slideInAnimation',
|
|
432
|
+
rule('from', { width: 0 }),
|
|
433
|
+
// Invalid on purpose — `calc` needs spaces around its `-`. Browsers drop the
|
|
434
|
+
// declaration and animate to the rect's own width, which is the reveal the mask wants.
|
|
435
|
+
rule('to', { width: 'calc(100%-100px)' }),
|
|
436
|
+
),
|
|
437
|
+
atRule(
|
|
438
|
+
'@keyframes growWidthAnimation',
|
|
439
|
+
rule('from', { width: 0 }),
|
|
440
|
+
rule('to', { width: '100%' }),
|
|
441
|
+
),
|
|
442
|
+
rule('.lang-name', { font: "400 11px 'Segoe UI', Ubuntu, Sans-Serif", fill: textColor }),
|
|
443
|
+
rule('#rect-mask rect', { animation: 'slideInAnimation 1s ease-in-out forwards' }),
|
|
444
|
+
rule('.lang-progress', {
|
|
445
|
+
animation: 'growWidthAnimation 0.6s ease-in-out forwards',
|
|
446
|
+
fill: titleColor,
|
|
447
|
+
}),
|
|
448
|
+
rule('.progress-background', { fill: progressBackground(titleColor, textColor) }),
|
|
449
|
+
],
|
|
450
|
+
dark: ({ titleColor, textColor }) => [
|
|
451
|
+
getStyles({ textColor }),
|
|
452
|
+
rule('.lang-name', { fill: textColor }),
|
|
453
|
+
rule('.lang-progress', { fill: titleColor }),
|
|
454
|
+
rule('.progress-background', { fill: progressBackground(titleColor, textColor) }),
|
|
455
|
+
],
|
|
481
456
|
});
|
|
482
457
|
|
|
483
458
|
// `role="img"` hides the inner text from assistive tech, so everything the card
|
|
484
459
|
// shows has to be repeated here.
|
|
485
460
|
card.setAccessibilityLabel({
|
|
486
461
|
title: card.title,
|
|
487
|
-
desc:
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
462
|
+
desc:
|
|
463
|
+
filteredLanguages.length > 0
|
|
464
|
+
? filteredLanguages
|
|
465
|
+
.map((lang) => `${lang.name}: ${formatLanguageValue({ display_format, lang })}`)
|
|
466
|
+
.join(', ')
|
|
467
|
+
: i18n.t('wakatimecard.nocodingactivity'),
|
|
492
468
|
});
|
|
493
469
|
|
|
494
|
-
return card.render(
|
|
495
|
-
<svg x="0" y="0" width="100%">
|
|
496
|
-
${finalLayout}
|
|
497
|
-
</svg>
|
|
498
|
-
`);
|
|
470
|
+
return card.render(el('svg', { x: 0, y: 0, width: '100%' }, finalLayout));
|
|
499
471
|
};
|
|
500
472
|
|
|
501
473
|
export { DISPLAY_FORMATS, WAKATIME_LAYOUTS, renderWakatimeCard };
|