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