Skip to content

Commit 630a005

Browse files
committed
chore: add biome pre-commit hook
1 parent b594820 commit 630a005

5 files changed

Lines changed: 92 additions & 75 deletions

File tree

.pre-commit-config.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@ repos:
1111
name: check that hooks apply
1212
description: check that all the hooks apply to the repository
1313

14+
- repo: https://github.com/biomejs/pre-commit
15+
rev: v2.3.8
16+
hooks:
17+
- id: biome-check
18+
name: run biome
19+
description: format and lint JS, TS, JSON, CSS, and related files with Biome
20+
args: [--write]
21+
files: \.(cjs|css|cts|js|json|jsonc|jsx|mjs|mts|ts|tsx)$
22+
1423
- repo: local
1524
hooks:
1625
- id: prettier

biome.json

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{
2+
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
3+
"files": {
4+
"includes": [
5+
"**",
6+
"!docs/bootstrap",
7+
"!docs/images",
8+
"!docs/featured.json",
9+
"!docs/manifest.json",
10+
"!docs/users.json"
11+
]
12+
},
13+
"formatter": {
14+
"enabled": true,
15+
"indentStyle": "space",
16+
"indentWidth": 2,
17+
"lineWidth": 88
18+
},
19+
"javascript": {
20+
"formatter": {
21+
"quoteStyle": "single",
22+
"semicolons": "always",
23+
"trailingCommas": "all"
24+
}
25+
},
26+
"json": {
27+
"formatter": {
28+
"trailingCommas": "none"
29+
}
30+
},
31+
"linter": {
32+
"enabled": true,
33+
"rules": {
34+
"recommended": true,
35+
"complexity": {
36+
"noImportantStyles": "off"
37+
},
38+
"correctness": {
39+
"noUnusedFunctionParameters": "off",
40+
"useParseIntRadix": "off"
41+
},
42+
"style": {
43+
"noDescendingSpecificity": "off"
44+
},
45+
"suspicious": {
46+
"noAssignInExpressions": "off",
47+
"useIterableCallbackReturn": "off"
48+
}
49+
}
50+
}
51+
}

docs/script.js

Lines changed: 26 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,7 @@ function pickRandomUser(event) {
9393
// Find the card element for the random user
9494
if (!randomUser.card || !randomUser.card.isConnected) {
9595
// Attempt to find the card in the DOM by data-login as a fallback
96-
const fallbackCard = document.querySelector(
97-
`[data-login="${randomUser.login}"]`,
98-
);
96+
const fallbackCard = document.querySelector(`[data-login="${randomUser.login}"]`);
9997
if (fallbackCard) {
10098
randomUser.card = fallbackCard;
10199
} else {
@@ -116,7 +114,7 @@ function pickRandomUser(event) {
116114
// Scroll near the card (with a small offset to avoid landing exactly on it)
117115
const cardRect = randomUser.card.getBoundingClientRect();
118116
const scrollOffset = cardRect.top + window.scrollY - 100; // 100px offset from top
119-
window.scrollTo({top: Math.max(0, scrollOffset), behavior: 'smooth'});
117+
window.scrollTo({ top: Math.max(0, scrollOffset), behavior: 'smooth' });
120118

121119
// Highlight the card
122120
randomUser.card.classList.remove('highlight');
@@ -134,7 +132,7 @@ function pickRandomUser(event) {
134132

135133
async function fetchAndPrepareUsers() {
136134
try {
137-
const res = await fetch('users.json', {cache: 'no-store'});
135+
const res = await fetch('users.json', { cache: 'no-store' });
138136
if (!res.ok) throw new Error(`Failed to fetch users.json: ${res.status}`);
139137
const users = await res.json();
140138
const prepared = users.map(prepareUserFromJson);
@@ -143,8 +141,7 @@ async function fetchAndPrepareUsers() {
143141
isDataLoaded = true;
144142
const total = allUsers.length;
145143
document.getElementById('totalCount').textContent = total.toLocaleString();
146-
document.getElementById('totalCountDesktop').textContent =
147-
total.toLocaleString();
144+
document.getElementById('totalCountDesktop').textContent = total.toLocaleString();
148145
} catch (err) {
149146
console.error(err);
150147
const loadingStates = document.querySelectorAll('.loading-state');
@@ -156,8 +153,7 @@ async function fetchAndPrepareUsers() {
156153
if (spinner) spinner.style.display = 'none';
157154
if (loadingMessage) loadingMessage.style.display = 'none';
158155
if (errorMessage) {
159-
errorMessage.textContent =
160-
'Unable to load users. Please try again later.';
156+
errorMessage.textContent = 'Unable to load users. Please try again later.';
161157
errorMessage.style.display = 'block';
162158
}
163159
});
@@ -169,7 +165,7 @@ async function fetchAndPrepareUsers() {
169165
*/
170166
async function loadFeaturedUser() {
171167
try {
172-
const res = await fetch('featured.json', {cache: 'no-store'});
168+
const res = await fetch('featured.json', { cache: 'no-store' });
173169
if (!res.ok) {
174170
return;
175171
}
@@ -235,8 +231,7 @@ function updateFeaturedInfo(elements, user) {
235231
elements.name.textContent = user.name || user.login;
236232

237233
if (user.location) {
238-
elements.location.querySelector('.location-text').textContent =
239-
user.location;
234+
elements.location.querySelector('.location-text').textContent = user.location;
240235
elements.location.style.display = 'flex';
241236
} else {
242237
elements.location.style.display = 'none';
@@ -269,8 +264,7 @@ function updateFeaturedLanguages(elements, user) {
269264
}
270265

271266
function prepareUserFromJson(user) {
272-
const getNum = (v, def = 0) =>
273-
v === 'N/A' || v == null ? def : parseInt(v, 10);
267+
const getNum = (v, def = 0) => (v === 'N/A' || v == null ? def : parseInt(v, 10));
274268
const safeLower = (v) => (v ? String(v).toLowerCase() : '');
275269
const normalizeDate = (v) => (v ? new Date(v).toISOString() : '');
276270
const topLangs = Array.isArray(user.top_languages) ? user.top_languages : [];
@@ -301,10 +295,8 @@ function prepareUserFromJson(user) {
301295
following_display: user.following_display || formatDisplay(user.following),
302296
repos_display: user.repos_display || formatDisplay(user.public_repos),
303297
gists_display: user.gists_display || formatDisplay(user.public_gists),
304-
sponsors_display:
305-
user.sponsors_display || formatDisplay(user.sponsors_count),
306-
sponsoring_display:
307-
user.sponsoring_display || formatDisplay(user.sponsoring_count),
298+
sponsors_display: user.sponsors_display || formatDisplay(user.sponsors_count),
299+
sponsoring_display: user.sponsoring_display || formatDisplay(user.sponsoring_count),
308300
stars_display: formatDisplay(user.total_stars),
309301
raw: user,
310302
};
@@ -337,7 +329,7 @@ function extractLocation() {
337329
* @returns {Object} Object with sponsors and sponsoring counts
338330
*/
339331
function extractStats() {
340-
return {sponsors: 0, sponsoring: 0};
332+
return { sponsors: 0, sponsoring: 0 };
341333
}
342334

343335
// ============================================================================
@@ -436,7 +428,7 @@ function exportFilteredJSON() {
436428
const userData = filteredUsers.map((user) => user.raw);
437429

438430
const jsonString = JSON.stringify(userData, null, 2);
439-
const blob = new Blob([jsonString], {type: 'application/json'});
431+
const blob = new Blob([jsonString], { type: 'application/json' });
440432

441433
const url = URL.createObjectURL(blob);
442434

@@ -477,7 +469,7 @@ function exportFilteredCSV() {
477469
...rows.map((row) => headers.map((h) => escapeCSV(row[h])).join(',')),
478470
].join('\n');
479471

480-
const blob = new Blob([csv], {type: 'text/csv;charset=utf-8'});
472+
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
481473

482474
const url = URL.createObjectURL(blob);
483475

@@ -513,8 +505,7 @@ function getActiveFilters() {
513505
.getElementById('languageFilter')
514506
.value.toLowerCase()
515507
.trim(),
516-
lastRepoActivityFilter: document.getElementById('lastRepoActivityFilter')
517-
.value,
508+
lastRepoActivityFilter: document.getElementById('lastRepoActivityFilter').value,
518509
lastCommitFilter: document.getElementById('lastCommitFilter').value,
519510
};
520511
}
@@ -547,18 +538,10 @@ function getDateRanges() {
547538
return {
548539
oneWeekAgo: new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000),
549540
oneMonthAgo: new Date(now.getFullYear(), now.getMonth() - 1, now.getDate()),
550-
sixMonthsAgo: new Date(
551-
now.getFullYear(),
552-
now.getMonth() - 6,
553-
now.getDate(),
554-
),
541+
sixMonthsAgo: new Date(now.getFullYear(), now.getMonth() - 6, now.getDate()),
555542
oneYearAgo: new Date(now.getFullYear() - 1, now.getMonth(), now.getDate()),
556543
twoYearsAgo: new Date(now.getFullYear() - 2, now.getMonth(), now.getDate()),
557-
fiveYearsAgo: new Date(
558-
now.getFullYear() - 5,
559-
now.getMonth(),
560-
now.getDate(),
561-
),
544+
fiveYearsAgo: new Date(now.getFullYear() - 5, now.getMonth(), now.getDate()),
562545
};
563546
}
564547

@@ -608,8 +591,7 @@ function matchesSearch(user, searchTerm) {
608591
*/
609592
function matchesFollowerRange(user, filters) {
610593
return (
611-
user.followers >= filters.minFollowers &&
612-
user.followers <= filters.maxFollowers
594+
user.followers >= filters.minFollowers && user.followers <= filters.maxFollowers
613595
);
614596
}
615597

@@ -700,20 +682,12 @@ function matchesLanguage(user, languageFilter) {
700682

701683
function matchesRepoActivity(user, activityFilter, dateRanges) {
702684
if (activityFilter === 'any' || !user.last_repo_pushed_at) return true;
703-
return matchesDateByRange(
704-
user.last_repo_pushed_at,
705-
activityFilter,
706-
dateRanges,
707-
);
685+
return matchesDateByRange(user.last_repo_pushed_at, activityFilter, dateRanges);
708686
}
709687

710688
function matchesCommitActivity(user, commitFilter, dateRanges) {
711689
if (commitFilter === 'any' || !user.last_public_commit_at) return true;
712-
return matchesDateByRange(
713-
user.last_public_commit_at,
714-
commitFilter,
715-
dateRanges,
716-
);
690+
return matchesDateByRange(user.last_public_commit_at, commitFilter, dateRanges);
717691
}
718692

719693
function matchesDateByRange(dateString, rangeKey, dateRanges) {
@@ -772,17 +746,13 @@ function getSortedUsers(sortBy) {
772746
'stars-desc': (a, b) => b.total_stars - a.total_stars,
773747
'stars-asc': (a, b) => a.total_stars - b.total_stars,
774748
'last-repo-desc': (a, b) =>
775-
new Date(b.last_repo_pushed_at || 0) -
776-
new Date(a.last_repo_pushed_at || 0),
749+
new Date(b.last_repo_pushed_at || 0) - new Date(a.last_repo_pushed_at || 0),
777750
'last-repo-asc': (a, b) =>
778-
new Date(a.last_repo_pushed_at || 0) -
779-
new Date(b.last_repo_pushed_at || 0),
751+
new Date(a.last_repo_pushed_at || 0) - new Date(b.last_repo_pushed_at || 0),
780752
'last-commit-desc': (a, b) =>
781-
new Date(b.last_public_commit_at || 0) -
782-
new Date(a.last_public_commit_at || 0),
753+
new Date(b.last_public_commit_at || 0) - new Date(a.last_public_commit_at || 0),
783754
'last-commit-asc': (a, b) =>
784-
new Date(a.last_public_commit_at || 0) -
785-
new Date(b.last_public_commit_at || 0),
755+
new Date(a.last_public_commit_at || 0) - new Date(b.last_public_commit_at || 0),
786756
'name-asc': (a, b) => a.name.localeCompare(b.name),
787757
'name-desc': (a, b) => b.name.localeCompare(a.name),
788758
'ratio-followers-following': (a, b) => {
@@ -991,10 +961,8 @@ function updateCounts(sortedUsers) {
991961
const visibleCount = sortedUsers.length;
992962
const totalCount = allUsers.length;
993963

994-
document.getElementById('visibleCount').textContent =
995-
visibleCount.toLocaleString();
996-
document.getElementById('totalCount').textContent =
997-
totalCount.toLocaleString();
964+
document.getElementById('visibleCount').textContent = visibleCount.toLocaleString();
965+
document.getElementById('totalCount').textContent = totalCount.toLocaleString();
998966

999967
document.getElementById('visibleCountDesktop').textContent =
1000968
visibleCount.toLocaleString();
@@ -1073,9 +1041,7 @@ const FILTER_LABELS = {
10731041
function getControlDisplayValue(element) {
10741042
if (!element) return '';
10751043
if (element.tagName === 'SELECT') {
1076-
return (
1077-
element.options[element.selectedIndex]?.textContent.trim() || element.value
1078-
);
1044+
return element.options[element.selectedIndex]?.textContent.trim() || element.value;
10791045
}
10801046
return element.value.trim();
10811047
}

docs/service-worker.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const PRECACHE_URLS = [
1919
'bootstrap/js/popper.min.js',
2020
'manifest.json',
2121
];
22-
const CACHE_EXPIRATION = {'users.json': 3 * DAY_SECONDS};
22+
const CACHE_EXPIRATION = { 'users.json': 3 * DAY_SECONDS };
2323

2424
function getCache() {
2525
return caches.open(PRECACHE);
@@ -76,9 +76,7 @@ function handleExpiringFile(event, filename, maxAgeMs) {
7676

7777
function handleDefaultFetch(event) {
7878
event.respondWith(
79-
caches
80-
.match(event.request)
81-
.then((cached) => cached || fetch(event.request)),
79+
caches.match(event.request).then((cached) => cached || fetch(event.request)),
8280
);
8381
}
8482

@@ -96,8 +94,7 @@ self.addEventListener('fetch', (event) => {
9694
const url = event.request.url;
9795
if (!url.startsWith(self.location.origin)) return null;
9896
for (const [filename, maxAgeMs] of Object.entries(CACHE_EXPIRATION)) {
99-
if (url.endsWith(filename))
100-
return handleExpiringFile(event, filename, maxAgeMs);
97+
if (url.endsWith(filename)) return handleExpiringFile(event, filename, maxAgeMs);
10198
}
10299
return handleDefaultFetch(event);
103100
});

docs/styles.css

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
}
44

55
body {
6-
font-family: 'Arial', sans-serif;
6+
font-family: "Arial", sans-serif;
77
background: #f0f2f5;
88
margin: 0;
99
padding: 0;
@@ -441,17 +441,13 @@ h1 {
441441
}
442442

443443
.featured-user-section::before {
444-
content: '';
444+
content: "";
445445
position: absolute;
446446
top: -50%;
447447
right: -50%;
448448
width: 200%;
449449
height: 200%;
450-
background: radial-gradient(
451-
circle,
452-
rgba(255, 255, 255, 0.1) 0%,
453-
transparent 70%
454-
);
450+
background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, transparent 70%);
455451
animation: pulse 15s ease-in-out infinite;
456452
}
457453

@@ -928,8 +924,6 @@ footer {
928924
}
929925
}
930926

931-
932-
933927
/* Fine-tune mobile card widths for small breakpoints */
934928
@media (min-width: 401px) and (max-width: 540px) {
935929
.card {

0 commit comments

Comments
 (0)