1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2025-04-25 23:05:21 -04:00

add github activity graph to /projects

This commit is contained in:
Jake Jarvis 2025-04-18 18:48:08 -04:00
parent 98ea88dae9
commit ba62de355f
Signed by: jake
SSH Key Fingerprint: SHA256:nCkvAjYA6XaSPUqc4TfbBQTpzr8Xj7ritg/sGInCdkc
10 changed files with 540 additions and 160 deletions

View File

@ -30,8 +30,6 @@ const ContactSchema = v.object({
v.nonEmpty("Just do the stinkin CAPTCHA, human! 🤖"),
// very rudimentary length check based on Cloudflare's docs
// https://developers.cloudflare.com/turnstile/troubleshooting/testing/
v.minLength("XXXX.DUMMY.TOKEN.XXXX".length),
// "A Turnstile token can have up to 2048 characters."
// https://developers.cloudflare.com/turnstile/get-started/server-side-validation/
v.maxLength(2048),
v.readonly()
@ -48,7 +46,7 @@ export type ContactState = {
export const send = async (state: ContactState, payload: FormData): Promise<ContactState> => {
// TODO: remove after debugging why automated spam entries are causing 500 errors
console.debug("[contact form] received payload:", payload);
console.debug("[/contact] received payload:", payload);
try {
const data = v.safeParse(ContactSchema, Object.fromEntries(payload));
@ -80,7 +78,7 @@ export const send = async (state: ContactState, payload: FormData): Promise<Cont
});
if (!turnstileResponse || !turnstileResponse.ok) {
throw new Error(`[contact form] turnstile validation failed: ${turnstileResponse.status}`);
throw new Error(`[/contact] turnstile validation failed: ${turnstileResponse.status}`);
}
const turnstileData = (await turnstileResponse.json()) as { success: boolean };
@ -92,9 +90,9 @@ export const send = async (state: ContactState, payload: FormData): Promise<Cont
};
}
if (!env.RESEND_FROM_EMAIL) {
if (env.RESEND_FROM_EMAIL === "onboarding@resend.dev") {
// https://resend.com/docs/api-reference/emails/send-email
console.warn("[contact form] 'RESEND_FROM_EMAIL' is not set, falling back to onboarding@resend.dev.");
console.warn("[/contact] 'RESEND_FROM_EMAIL' is not set, falling back to onboarding@resend.dev.");
}
// send email
@ -109,7 +107,7 @@ export const send = async (state: ContactState, payload: FormData): Promise<Cont
return { success: true, message: "Thanks! You should hear from me soon." };
} catch (error) {
console.error("[contact form] fatal error:", error);
console.error("[/contact] fatal error:", error);
return {
success: false,

View File

@ -22,7 +22,7 @@ const HitCounter = async ({ slug }: { slug: string }) => {
</span>
);
} catch (error) {
console.error("[hit counter] fatal error:", error);
console.error("[/notes/[slug]/counter] fatal error:", error);
return <span title="Error getting views! :(">?</span>;
}

View File

@ -34,7 +34,7 @@ const getLocalImage = async (src: string): Promise<ArrayBuffer | string> => {
try {
if (!fs.existsSync(imagePath)) {
console.error(`[og-image] couldn't find an image file located at "${imagePath}"`);
console.error(`[/notes/[slug]/opengraph-image] couldn't find an image file located at "${imagePath}"`);
// return a 1x1 transparent gif if the image doesn't exist instead of crashing
return NO_IMAGE;
@ -43,7 +43,7 @@ const getLocalImage = async (src: string): Promise<ArrayBuffer | string> => {
// return the raw image data as a buffer
return Uint8Array.from(await fs.promises.readFile(imagePath)).buffer;
} catch (error) {
console.error(`[og-image] found "${imagePath}" but couldn't read it:`, error);
console.error(`[/notes/[slug]/opengraph-image] found "${imagePath}" but couldn't read it:`, error);
// fail silently and return a 1x1 transparent gif instead of crashing
return NO_IMAGE;
@ -256,7 +256,7 @@ const OpenGraphImage = async ({ params }: { params: Promise<{ slug: string }> })
}
);
} catch (error) {
console.error("[og-image] error generating image:", error);
console.error("[/notes/[slug]/opengraph-image] error generating open graph image:", error);
notFound();
}
};

View File

@ -0,0 +1,33 @@
.calendar {
--activity-0: #ebedf0;
--activity-1: #9be9a8;
--activity-2: #40c463;
--activity-3: #30a14e;
--activity-4: #216e39;
}
[data-theme="dark"] .calendar {
--activity-0: #252525;
--activity-1: #033a16;
--activity-2: #196c2e;
--activity-3: #2ea043;
--activity-4: #56d364;
}
.calendar :global(.react-activity-calendar) {
margin: 1em auto;
}
.calendar :global(.react-activity-calendar__count),
.calendar :global(.react-activity-calendar__legend-month) {
color: var(--colors-medium);
}
.calendar :global(.react-activity-calendar__legend-colors) {
color: var(--colors-medium-light);
}
.tooltip {
background-color: var(--colors-background-header);
color: var(--colors-text);
}

59
app/projects/calendar.tsx Normal file
View File

@ -0,0 +1,59 @@
"use client";
import { cloneElement } from "react";
import { ActivityCalendar } from "react-activity-calendar";
import { Tooltip } from "react-tooltip";
import clsx from "clsx";
import { format } from "date-fns";
import type { ComponentPropsWithoutRef } from "react";
import type { Activity } from "react-activity-calendar";
import styles from "./calendar.module.css";
import "react-tooltip/dist/react-tooltip.css";
export type CalendarProps = ComponentPropsWithoutRef<"div"> & {
data: Activity[];
};
const Calendar = ({ data, className, ...rest }: CalendarProps) => {
// heavily inspired by https://github.com/grubersjoe/react-github-calendar
return (
<div className={clsx(styles.calendar, className)} {...rest}>
<ActivityCalendar
data={data}
colorScheme="dark"
theme={{
// this isn't actually locked to dark mode, we just take over theming using CSS like everywhere else
dark: [
"var(--activity-0)",
"var(--activity-1)",
"var(--activity-2)",
"var(--activity-3)",
"var(--activity-4)",
],
}}
labels={{
totalCount: `{{count}} contributions in the last year`,
}}
maxLevel={4}
renderBlock={(block, activity) => (
<a
href={`https://github.com/jakejarvis?tab=overview&from=${activity.date}&to=${activity.date}`}
target="_blank"
rel="noopener"
>
{cloneElement(block, {
"data-tooltip-id": "activity-tooltip",
"data-tooltip-html": `${activity.count === 0 ? "No" : activity.count} contribution${activity.count === 1 ? "" : "s"} on ${format(activity.date, "MMMM do")}`,
})}
</a>
)}
fontSize={13}
/>
<Tooltip id="activity-tooltip" className={styles.tooltip} />
</div>
);
};
export default Calendar;

View File

@ -1,3 +1,8 @@
.heading {
font-weight: 400;
font-size: 1.4em;
}
.grid {
display: flex;
flex-flow: row wrap;

View File

@ -1,13 +1,16 @@
import { env } from "../../lib/env";
import { Suspense } from "react";
import { notFound } from "next/navigation";
import { graphql } from "@octokit/graphql";
import * as cheerio from "cheerio";
import { GitForkIcon, StarIcon } from "lucide-react";
import Calendar from "./calendar";
import PageTitle from "../../components/PageTitle";
import Link from "../../components/Link";
import RelativeTime from "../../components/RelativeTime";
import { addMetadata } from "../../lib/helpers/metadata";
import * as config from "../../lib/config";
import type { User } from "@octokit/graphql-schema";
import type { Repository, User } from "@octokit/graphql-schema";
import styles from "./page.module.css";
@ -19,81 +22,185 @@ export const metadata = addMetadata({
},
});
const getRepos = async () => {
// don't fail the entire site build if the required API key for this page is missing
if (!env.GITHUB_TOKEN) {
console.warn(`ERROR: I can't fetch any GitHub projects without "GITHUB_TOKEN" set! Disabling projects page.`);
const getContributions = async (): Promise<
Array<{
date: string;
count: number;
level: number;
}>
> => {
// thanks @grubersjoe! :) https://github.com/grubersjoe/github-contributions-api/blob/main/src/scrape.ts
try {
const response = await fetch(`https://github.com/users/${config.authorSocial.github}/contributions`, {
headers: {
referer: `https://github.com/${config.authorSocial.github}`,
"x-requested-with": "XMLHttpRequest",
},
cache: "force-cache",
next: {
revalidate: 43200, // 12 hours
tags: ["github-contributions"],
},
});
// just return a 404 since this page would be blank anyways
notFound();
const $ = cheerio.load(await response.text());
const days = $(".js-calendar-graph-table .ContributionCalendar-day")
.get()
.sort((a, b) => {
const dateA = a.attribs["data-date"] ?? "";
const dateB = b.attribs["data-date"] ?? "";
return dateA.localeCompare(dateB, "en");
});
const dayTooltips = $(".js-calendar-graph tool-tip")
.toArray()
// eslint-disable-next-line @typescript-eslint/no-explicit-any
.reduce<Record<string, any>>((map, elem) => {
map[elem.attribs["for"]] = elem;
return map;
}, {});
return days.map((day) => {
const attr = {
id: day.attribs["id"],
date: day.attribs["data-date"],
level: day.attribs["data-level"],
};
let count = 0;
if (dayTooltips[attr.id]) {
const text = dayTooltips[attr.id].firstChild;
if (text) {
const countMatch = text.data.trim().match(/^\d+/);
if (countMatch) {
count = parseInt(countMatch[0]);
}
}
}
const level = parseInt(attr.level);
return {
date: attr.date,
count,
level,
};
});
} catch (error) {
console.error("[/projects] Failed to fetch contributions:", error);
return [];
}
};
// https://docs.github.com/en/graphql/reference/objects#repository
const { user } = await graphql<{ user: User }>(
`
query ($username: String!, $sort: RepositoryOrderField!, $limit: Int) {
user(login: $username) {
repositories(
first: $limit
isLocked: false
isFork: false
ownerAffiliations: OWNER
privacy: PUBLIC
orderBy: { field: $sort, direction: DESC }
) {
edges {
node {
name
url
description
pushedAt
stargazerCount
forkCount
primaryLanguage {
const getRepos = async (): Promise<Repository[] | undefined> => {
try {
// https://docs.github.com/en/graphql/reference/objects#repository
const { user } = await graphql<{ user: User }>(
`
query ($username: String!, $sort: RepositoryOrderField!, $limit: Int) {
user(login: $username) {
repositories(
first: $limit
isLocked: false
isFork: false
ownerAffiliations: OWNER
privacy: PUBLIC
orderBy: { field: $sort, direction: DESC }
) {
edges {
node {
name
color
url
description
pushedAt
stargazerCount
forkCount
primaryLanguage {
name
color
}
}
}
}
}
}
}
`,
{
username: config.authorSocial.github,
sort: "STARGAZERS",
limit: 12,
headers: {
accept: "application/vnd.github.v3+json",
authorization: `token ${env.GITHUB_TOKEN}`,
},
request: {
// override fetch() to use next's extension to cache the response
// https://nextjs.org/docs/app/api-reference/functions/fetch#fetchurl-options
fetch: (url: string | URL | Request, options?: RequestInit) => {
return fetch(url, {
...options,
cache: "force-cache",
next: {
revalidate: 600, // 10 minutes
tags: ["github-api"],
},
});
`,
{
username: config.authorSocial.github,
sort: "STARGAZERS",
limit: 12,
headers: {
accept: "application/vnd.github.v3+json",
authorization: `token ${env.GITHUB_TOKEN}`,
},
},
}
);
request: {
// override fetch() to use next's extension to cache the response
// https://nextjs.org/docs/app/api-reference/functions/fetch#fetchurl-options
fetch: (url: string | URL | Request, options?: RequestInit) => {
return fetch(url, {
...options,
cache: "force-cache",
next: {
revalidate: 1800, // 30 minutes
tags: ["github-repos"],
},
});
},
},
}
);
return user.repositories.edges?.map((edge) => edge!.node);
return user.repositories.edges?.map((edge) => edge!.node as Repository);
} catch (error) {
console.error("[/projects] Failed to fetch repositories:", error);
return [];
}
};
const Page = async () => {
const repos = await getRepos();
// don't fail the entire site build if the required config for this page is missing, just return a 404 since this page
// would be blank anyways
if (!env.GITHUB_TOKEN) {
console.warn("[/projects] I can't fetch anything from GitHub without 'GITHUB_TOKEN' set!");
notFound();
}
if (!config.authorSocial?.github) {
console.warn(
"[/projects] I can't fetch anything from GitHub without 'authorSocial.github' set in lib/config/index.ts."
);
notFound();
}
// fetch the repos and contributions in parallel
const [contributions, repos] = await Promise.all([getContributions(), getRepos()]);
return (
<>
<PageTitle canonical="/projects">Projects</PageTitle>
<h2 className={styles.heading}>
<Link href={`https://github.com/${config.authorSocial.github}`} style={{ color: "inherit" }} plain>
Contribution activity
</Link>
</h2>
<Suspense fallback={null}>
<Calendar data={contributions} style={{ marginBottom: "2em" }} />
</Suspense>
<h2 className={styles.heading}>
<Link
href={`https://github.com/${config.authorSocial.github}?tab=repositories&sort=stargazers`}
style={{ color: "inherit" }}
plain
>
Popular repositories
</Link>
</h2>
<div className={styles.grid}>
{repos?.map((repo) => (
<div key={repo!.name} className={styles.card}>

View File

@ -1,6 +1,7 @@
.hr {
margin: 1.5em auto;
height: 0.175em;
max-width: calc(var(--max-width) - 1.5em);
height: 1px;
border: 0;
background-color: var(--colors-light);
}

View File

@ -31,6 +31,7 @@
"@t3-oss/env-nextjs": "^0.12.0",
"@upstash/redis": "^1.34.8",
"@vercel/analytics": "^1.5.0",
"cheerio": "^1.0.0",
"clsx": "^2.1.1",
"copy-to-clipboard": "^3.3.3",
"date-fns": "^4.1.0",
@ -43,6 +44,7 @@
"polished": "^4.3.1",
"prop-types": "^15.8.1",
"react": "19.1.0",
"react-activity-calendar": "^2.7.10",
"react-countup": "^6.5.3",
"react-dom": "19.1.0",
"react-innertext": "^1.1.5",
@ -51,6 +53,7 @@
"react-schemaorg": "^2.0.0",
"react-textarea-autosize": "^8.5.9",
"react-timeago": "^8.2.0",
"react-tooltip": "^5.28.1",
"react-turnstile": "^1.1.4",
"react-tweet": "^3.2.2",
"rehype-mdx-import-media": "^1.2.0",
@ -71,7 +74,7 @@
},
"devDependencies": {
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.24.0",
"@eslint/js": "^9.25.0",
"@jakejarvis/eslint-config": "^4.0.7",
"@types/mdx": "^2.0.13",
"@types/node": "^22.14.1",
@ -81,7 +84,7 @@
"@types/react-is": "^19.0.0",
"babel-plugin-react-compiler": "19.0.0-beta-ebf51a3-20250411",
"cross-env": "^7.0.3",
"eslint": "^9.24.0",
"eslint": "^9.25.0",
"eslint-config-next": "15.3.1-canary.13",
"eslint-config-prettier": "^10.1.2",
"eslint-plugin-css-modules": "^2.12.0",

352
pnpm-lock.yaml generated
View File

@ -47,6 +47,9 @@ importers:
'@vercel/analytics':
specifier: ^1.5.0
version: 1.5.0(next@15.3.1-canary.13(@babel/core@7.26.10)(babel-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)
cheerio:
specifier: ^1.0.0
version: 1.0.0
clsx:
specifier: ^2.1.1
version: 2.1.1
@ -83,6 +86,9 @@ importers:
react:
specifier: 19.1.0
version: 19.1.0
react-activity-calendar:
specifier: ^2.7.10
version: 2.7.10(react@19.1.0)
react-countup:
specifier: ^6.5.3
version: 6.5.3(react@19.1.0)
@ -107,6 +113,9 @@ importers:
react-timeago:
specifier: ^8.2.0
version: 8.2.0(react@19.1.0)
react-tooltip:
specifier: ^5.28.1
version: 5.28.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react-turnstile:
specifier: ^1.1.4
version: 1.1.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
@ -163,11 +172,11 @@ importers:
specifier: ^3.3.1
version: 3.3.1
'@eslint/js':
specifier: ^9.24.0
version: 9.24.0
specifier: ^9.25.0
version: 9.25.0
'@jakejarvis/eslint-config':
specifier: ^4.0.7
version: 4.0.7(eslint@9.24.0)
version: 4.0.7(eslint@9.25.0)
'@types/mdx':
specifier: ^2.0.13
version: 2.0.13
@ -193,38 +202,38 @@ importers:
specifier: ^7.0.3
version: 7.0.3
eslint:
specifier: ^9.24.0
version: 9.24.0
specifier: ^9.25.0
version: 9.25.0
eslint-config-next:
specifier: 15.3.1-canary.13
version: 15.3.1-canary.13(eslint@9.24.0)(typescript@5.8.3)
version: 15.3.1-canary.13(eslint@9.25.0)(typescript@5.8.3)
eslint-config-prettier:
specifier: ^10.1.2
version: 10.1.2(eslint@9.24.0)
version: 10.1.2(eslint@9.25.0)
eslint-plugin-css-modules:
specifier: ^2.12.0
version: 2.12.0(eslint@9.24.0)
version: 2.12.0(eslint@9.25.0)
eslint-plugin-import:
specifier: ^2.31.0
version: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.24.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0)(eslint@9.24.0)
version: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.25.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0)(eslint@9.25.0)
eslint-plugin-jsx-a11y:
specifier: ^6.10.2
version: 6.10.2(eslint@9.24.0)
version: 6.10.2(eslint@9.25.0)
eslint-plugin-mdx:
specifier: ^3.4.0
version: 3.4.0(eslint@9.24.0)
version: 3.4.0(eslint@9.25.0)
eslint-plugin-prettier:
specifier: ^5.2.6
version: 5.2.6(eslint-config-prettier@10.1.2(eslint@9.24.0))(eslint@9.24.0)(prettier@3.5.3)
version: 5.2.6(eslint-config-prettier@10.1.2(eslint@9.25.0))(eslint@9.25.0)(prettier@3.5.3)
eslint-plugin-react:
specifier: ^7.37.5
version: 7.37.5(eslint@9.24.0)
version: 7.37.5(eslint@9.25.0)
eslint-plugin-react-compiler:
specifier: 19.0.0-beta-ebf51a3-20250411
version: 19.0.0-beta-ebf51a3-20250411(eslint@9.24.0)
version: 19.0.0-beta-ebf51a3-20250411(eslint@9.25.0)
eslint-plugin-react-hooks:
specifier: ^5.2.0
version: 5.2.0(eslint@9.24.0)
version: 5.2.0(eslint@9.25.0)
husky:
specifier: ^9.1.7
version: 9.1.7
@ -435,10 +444,6 @@ packages:
resolution: {integrity: sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/core@0.12.0':
resolution: {integrity: sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/core@0.13.0':
resolution: {integrity: sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@ -447,8 +452,8 @@ packages:
resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/js@9.24.0':
resolution: {integrity: sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==}
'@eslint/js@9.25.0':
resolution: {integrity: sha512-iWhsUS8Wgxz9AXNfvfOPFSW4VfMXdVhp1hjkZVhXCrpgh/aLcc45rX6MPu+tIVUWDw0HfNwth7O28M1xDxNf9w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/object-schema@2.1.6':
@ -459,6 +464,15 @@ packages:
resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@floating-ui/core@1.6.9':
resolution: {integrity: sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==}
'@floating-ui/dom@1.6.13':
resolution: {integrity: sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==}
'@floating-ui/utils@0.2.9':
resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==}
'@giscus/react@3.1.0':
resolution: {integrity: sha512-0TCO2TvL43+oOdyVVGHDItwxD1UMKP2ZYpT6gXmhFOqfAJtZxTzJ9hkn34iAF/b6YzyJ4Um89QIt9z/ajmAEeg==}
peerDependencies:
@ -1228,6 +1242,9 @@ packages:
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
boolbase@1.0.0:
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
brace-expansion@1.1.11:
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
@ -1298,10 +1315,20 @@ packages:
character-reference-invalid@2.0.1:
resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
cheerio-select@2.1.0:
resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==}
cheerio@1.0.0:
resolution: {integrity: sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==}
engines: {node: '>=18.17'}
ci-info@4.2.0:
resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==}
engines: {node: '>=8'}
classnames@2.5.1:
resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==}
cli-cursor@5.0.0:
resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==}
engines: {node: '>=18'}
@ -1392,10 +1419,17 @@ packages:
resolution: {integrity: sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==}
engines: {node: '>=12 || >=16'}
css-select@5.1.0:
resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==}
css-tree@3.1.0:
resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==}
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
css-what@6.1.0:
resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==}
engines: {node: '>= 6'}
cssesc@3.0.0:
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
engines: {node: '>=4'}
@ -1521,6 +1555,9 @@ packages:
emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
encoding-sniffer@0.2.0:
resolution: {integrity: sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==}
entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'}
@ -1723,8 +1760,8 @@ packages:
resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
eslint@9.24.0:
resolution: {integrity: sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==}
eslint@9.25.0:
resolution: {integrity: sha512-MsBdObhM4cEwkzCiraDv7A6txFXEqtNXOb877TsSp2FCkBNl8JfVQrmiuDqC1IkejT6JLPzYBXx/xAiYhyzgGA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
hasBin: true
peerDependencies:
@ -2090,6 +2127,9 @@ packages:
htmlparser2@8.0.2:
resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==}
htmlparser2@9.1.0:
resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==}
human-signals@5.0.0:
resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
engines: {node: '>=16.17.0'}
@ -2099,6 +2139,10 @@ packages:
engines: {node: '>=18'}
hasBin: true
iconv-lite@0.6.3:
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
engines: {node: '>=0.10.0'}
ieee754@1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
@ -2740,6 +2784,9 @@ packages:
resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
nth-check@2.1.1:
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
object-assign@4.1.1:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
@ -2833,6 +2880,12 @@ packages:
parse-srcset@1.0.2:
resolution: {integrity: sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==}
parse5-htmlparser2-tree-adapter@7.1.0:
resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==}
parse5-parser-stream@7.1.2:
resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==}
parse5@7.2.1:
resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==}
@ -2958,6 +3011,11 @@ packages:
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
react-activity-calendar@2.7.10:
resolution: {integrity: sha512-O6ev2JxbsbmF7hPpRCkiXxQ+vGwXS5iUVwOCqtvlJnGhpyJ3ZJap7/qfIZA0WZcDj4gpQh2Dcvkmwh3yBXRrPQ==}
peerDependencies:
react: ^18.0.0 || ^19.0.0
react-countup@6.5.3:
resolution: {integrity: sha512-udnqVQitxC7QWADSPDOxVWULkLvKUWrDapn5i53HE4DPRVgs+Y5rr4bo25qEl8jSh+0l2cToJgGMx+clxPM3+w==}
peerDependencies:
@ -3008,6 +3066,12 @@ packages:
peerDependencies:
react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-tooltip@5.28.1:
resolution: {integrity: sha512-ZA4oHwoIIK09TS7PvSLFcRlje1wGZaxw6xHvfrzn6T82UcMEfEmHVCad16Gnr4NDNDh93HyN037VK4HDi5odfQ==}
peerDependencies:
react: '>=16.14.0'
react-dom: '>=16.14.0'
react-turnstile@1.1.4:
resolution: {integrity: sha512-oluyRWADdsufCt5eMqacW4gfw8/csr6Tk+fmuaMx0PWMKP1SX1iCviLvD2D5w92eAzIYDHi/krUWGHhlfzxTpQ==}
peerDependencies:
@ -3190,6 +3254,9 @@ packages:
resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
engines: {node: '>= 0.4'}
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
sax@1.4.1:
resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
@ -3541,6 +3608,10 @@ packages:
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
undici@6.21.2:
resolution: {integrity: sha512-uROZWze0R0itiAKVPsYhFov9LxrPMHLMEQFszeI2gCN6bnIIZ8twzBCJcN2LJrBBLfrP0t1FW0g+JmKVl8Vk1g==}
engines: {node: '>=18.17'}
unified-engine@11.2.2:
resolution: {integrity: sha512-15g/gWE7qQl9tQ3nAEbMd5h9HV1EACtFs6N9xaRBZICoCwnNGbal1kOs++ICf4aiTdItZxU2s/kYWhW7htlqJg==}
@ -3676,6 +3747,14 @@ packages:
engines: {node: '>= 10.13.0'}
hasBin: true
whatwg-encoding@3.1.1:
resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==}
engines: {node: '>=18'}
whatwg-mimetype@4.0.0:
resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==}
engines: {node: '>=18'}
which-boxed-primitive@1.1.1:
resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
engines: {node: '>= 0.4'}
@ -3970,9 +4049,9 @@ snapshots:
'@emotion/hash@0.9.2': {}
'@eslint-community/eslint-utils@4.6.1(eslint@9.24.0)':
'@eslint-community/eslint-utils@4.6.1(eslint@9.25.0)':
dependencies:
eslint: 9.24.0
eslint: 9.25.0
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.12.1': {}
@ -3987,10 +4066,6 @@ snapshots:
'@eslint/config-helpers@0.2.1': {}
'@eslint/core@0.12.0':
dependencies:
'@types/json-schema': 7.0.15
'@eslint/core@0.13.0':
dependencies:
'@types/json-schema': 7.0.15
@ -4009,7 +4084,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@eslint/js@9.24.0': {}
'@eslint/js@9.25.0': {}
'@eslint/object-schema@2.1.6': {}
@ -4018,6 +4093,17 @@ snapshots:
'@eslint/core': 0.13.0
levn: 0.4.1
'@floating-ui/core@1.6.9':
dependencies:
'@floating-ui/utils': 0.2.9
'@floating-ui/dom@1.6.13':
dependencies:
'@floating-ui/core': 1.6.9
'@floating-ui/utils': 0.2.9
'@floating-ui/utils@0.2.9': {}
'@giscus/react@3.1.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
giscus: 1.6.0
@ -4124,9 +4210,9 @@ snapshots:
wrap-ansi: 8.1.0
wrap-ansi-cjs: wrap-ansi@7.0.0
'@jakejarvis/eslint-config@4.0.7(eslint@9.24.0)':
'@jakejarvis/eslint-config@4.0.7(eslint@9.25.0)':
dependencies:
eslint: 9.24.0
eslint: 9.25.0
'@jridgewell/gen-mapping@0.3.8':
dependencies:
@ -4498,15 +4584,15 @@ snapshots:
'@types/unist@3.0.3': {}
'@typescript-eslint/eslint-plugin@8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.24.0)(typescript@5.8.3))(eslint@9.24.0)(typescript@5.8.3)':
'@typescript-eslint/eslint-plugin@8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.25.0)(typescript@5.8.3))(eslint@9.25.0)(typescript@5.8.3)':
dependencies:
'@eslint-community/regexpp': 4.12.1
'@typescript-eslint/parser': 8.30.1(eslint@9.24.0)(typescript@5.8.3)
'@typescript-eslint/parser': 8.30.1(eslint@9.25.0)(typescript@5.8.3)
'@typescript-eslint/scope-manager': 8.30.1
'@typescript-eslint/type-utils': 8.30.1(eslint@9.24.0)(typescript@5.8.3)
'@typescript-eslint/utils': 8.30.1(eslint@9.24.0)(typescript@5.8.3)
'@typescript-eslint/type-utils': 8.30.1(eslint@9.25.0)(typescript@5.8.3)
'@typescript-eslint/utils': 8.30.1(eslint@9.25.0)(typescript@5.8.3)
'@typescript-eslint/visitor-keys': 8.30.1
eslint: 9.24.0
eslint: 9.25.0
graphemer: 1.4.0
ignore: 5.3.2
natural-compare: 1.4.0
@ -4515,14 +4601,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/parser@8.30.1(eslint@9.24.0)(typescript@5.8.3)':
'@typescript-eslint/parser@8.30.1(eslint@9.25.0)(typescript@5.8.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.30.1
'@typescript-eslint/types': 8.30.1
'@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3)
'@typescript-eslint/visitor-keys': 8.30.1
debug: 4.4.0
eslint: 9.24.0
eslint: 9.25.0
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
@ -4532,12 +4618,12 @@ snapshots:
'@typescript-eslint/types': 8.30.1
'@typescript-eslint/visitor-keys': 8.30.1
'@typescript-eslint/type-utils@8.30.1(eslint@9.24.0)(typescript@5.8.3)':
'@typescript-eslint/type-utils@8.30.1(eslint@9.25.0)(typescript@5.8.3)':
dependencies:
'@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3)
'@typescript-eslint/utils': 8.30.1(eslint@9.24.0)(typescript@5.8.3)
'@typescript-eslint/utils': 8.30.1(eslint@9.25.0)(typescript@5.8.3)
debug: 4.4.0
eslint: 9.24.0
eslint: 9.25.0
ts-api-utils: 2.1.0(typescript@5.8.3)
typescript: 5.8.3
transitivePeerDependencies:
@ -4559,13 +4645,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.30.1(eslint@9.24.0)(typescript@5.8.3)':
'@typescript-eslint/utils@8.30.1(eslint@9.25.0)(typescript@5.8.3)':
dependencies:
'@eslint-community/eslint-utils': 4.6.1(eslint@9.24.0)
'@eslint-community/eslint-utils': 4.6.1(eslint@9.25.0)
'@typescript-eslint/scope-manager': 8.30.1
'@typescript-eslint/types': 8.30.1
'@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3)
eslint: 9.24.0
eslint: 9.25.0
typescript: 5.8.3
transitivePeerDependencies:
- supports-color
@ -4777,6 +4863,8 @@ snapshots:
base64-js@1.5.1: {}
boolbase@1.0.0: {}
brace-expansion@1.1.11:
dependencies:
balanced-match: 1.0.2
@ -4851,8 +4939,33 @@ snapshots:
character-reference-invalid@2.0.1: {}
cheerio-select@2.1.0:
dependencies:
boolbase: 1.0.0
css-select: 5.1.0
css-what: 6.1.0
domelementtype: 2.3.0
domhandler: 5.0.3
domutils: 3.2.2
cheerio@1.0.0:
dependencies:
cheerio-select: 2.1.0
dom-serializer: 2.0.0
domhandler: 5.0.3
domutils: 3.2.2
encoding-sniffer: 0.2.0
htmlparser2: 9.1.0
parse5: 7.2.1
parse5-htmlparser2-tree-adapter: 7.1.0
parse5-parser-stream: 7.1.2
undici: 6.21.2
whatwg-mimetype: 4.0.0
ci-info@4.2.0: {}
classnames@2.5.1: {}
cli-cursor@5.0.0:
dependencies:
restore-cursor: 5.1.0
@ -4936,11 +5049,21 @@ snapshots:
css-functions-list@3.2.3: {}
css-select@5.1.0:
dependencies:
boolbase: 1.0.0
css-what: 6.1.0
domhandler: 5.0.3
domutils: 3.2.2
nth-check: 2.1.1
css-tree@3.1.0:
dependencies:
mdn-data: 2.12.2
source-map-js: 1.2.1
css-what@6.1.0: {}
cssesc@3.0.0: {}
csstype@3.1.3: {}
@ -5054,6 +5177,11 @@ snapshots:
emoji-regex@9.2.2: {}
encoding-sniffer@0.2.0:
dependencies:
iconv-lite: 0.6.3
whatwg-encoding: 3.1.1
entities@4.5.0: {}
env-paths@2.2.1: {}
@ -5184,19 +5312,19 @@ snapshots:
escape-string-regexp@5.0.0: {}
eslint-config-next@15.3.1-canary.13(eslint@9.24.0)(typescript@5.8.3):
eslint-config-next@15.3.1-canary.13(eslint@9.25.0)(typescript@5.8.3):
dependencies:
'@next/eslint-plugin-next': 15.3.1-canary.13
'@rushstack/eslint-patch': 1.11.0
'@typescript-eslint/eslint-plugin': 8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.24.0)(typescript@5.8.3))(eslint@9.24.0)(typescript@5.8.3)
'@typescript-eslint/parser': 8.30.1(eslint@9.24.0)(typescript@5.8.3)
eslint: 9.24.0
'@typescript-eslint/eslint-plugin': 8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.25.0)(typescript@5.8.3))(eslint@9.25.0)(typescript@5.8.3)
'@typescript-eslint/parser': 8.30.1(eslint@9.25.0)(typescript@5.8.3)
eslint: 9.25.0
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.0(eslint-plugin-import@2.31.0)(eslint@9.24.0)
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.24.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0)(eslint@9.24.0)
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.24.0)
eslint-plugin-react: 7.37.5(eslint@9.24.0)
eslint-plugin-react-hooks: 5.2.0(eslint@9.24.0)
eslint-import-resolver-typescript: 3.10.0(eslint-plugin-import@2.31.0)(eslint@9.25.0)
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.25.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0)(eslint@9.25.0)
eslint-plugin-jsx-a11y: 6.10.2(eslint@9.25.0)
eslint-plugin-react: 7.37.5(eslint@9.25.0)
eslint-plugin-react-hooks: 5.2.0(eslint@9.25.0)
optionalDependencies:
typescript: 5.8.3
transitivePeerDependencies:
@ -5204,9 +5332,9 @@ snapshots:
- eslint-plugin-import-x
- supports-color
eslint-config-prettier@10.1.2(eslint@9.24.0):
eslint-config-prettier@10.1.2(eslint@9.25.0):
dependencies:
eslint: 9.24.0
eslint: 9.25.0
eslint-import-resolver-node@0.3.9:
dependencies:
@ -5216,26 +5344,26 @@ snapshots:
transitivePeerDependencies:
- supports-color
eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0)(eslint@9.24.0):
eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0)(eslint@9.25.0):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.4.0
eslint: 9.24.0
eslint: 9.25.0
get-tsconfig: 4.10.0
is-bun-module: 2.0.0
stable-hash: 0.0.5
tinyglobby: 0.2.12
unrs-resolver: 1.5.0
optionalDependencies:
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.24.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0)(eslint@9.24.0)
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.25.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0)(eslint@9.25.0)
transitivePeerDependencies:
- supports-color
eslint-mdx@3.4.0(eslint@9.24.0):
eslint-mdx@3.4.0(eslint@9.25.0):
dependencies:
acorn: 8.14.1
acorn-jsx: 5.3.2(acorn@8.14.1)
eslint: 9.24.0
eslint: 9.25.0
espree: 10.3.0
estree-util-visit: 2.0.0
remark-mdx: 3.1.0
@ -5252,24 +5380,24 @@ snapshots:
- bluebird
- supports-color
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.30.1(eslint@9.24.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0)(eslint@9.24.0):
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.30.1(eslint@9.25.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0)(eslint@9.25.0):
dependencies:
debug: 3.2.7
optionalDependencies:
'@typescript-eslint/parser': 8.30.1(eslint@9.24.0)(typescript@5.8.3)
eslint: 9.24.0
'@typescript-eslint/parser': 8.30.1(eslint@9.25.0)(typescript@5.8.3)
eslint: 9.25.0
eslint-import-resolver-node: 0.3.9
eslint-import-resolver-typescript: 3.10.0(eslint-plugin-import@2.31.0)(eslint@9.24.0)
eslint-import-resolver-typescript: 3.10.0(eslint-plugin-import@2.31.0)(eslint@9.25.0)
transitivePeerDependencies:
- supports-color
eslint-plugin-css-modules@2.12.0(eslint@9.24.0):
eslint-plugin-css-modules@2.12.0(eslint@9.25.0):
dependencies:
eslint: 9.24.0
eslint: 9.25.0
gonzales-pe: 4.3.0
lodash: 4.17.21
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.24.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0)(eslint@9.24.0):
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@9.25.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0)(eslint@9.25.0):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.8
@ -5278,9 +5406,9 @@ snapshots:
array.prototype.flatmap: 1.3.3
debug: 3.2.7
doctrine: 2.1.0
eslint: 9.24.0
eslint: 9.25.0
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.30.1(eslint@9.24.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0)(eslint@9.24.0)
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.30.1(eslint@9.25.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0)(eslint@9.25.0)
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
@ -5292,13 +5420,13 @@ snapshots:
string.prototype.trimend: 1.0.9
tsconfig-paths: 3.15.0
optionalDependencies:
'@typescript-eslint/parser': 8.30.1(eslint@9.24.0)(typescript@5.8.3)
'@typescript-eslint/parser': 8.30.1(eslint@9.25.0)(typescript@5.8.3)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
- supports-color
eslint-plugin-jsx-a11y@6.10.2(eslint@9.24.0):
eslint-plugin-jsx-a11y@6.10.2(eslint@9.25.0):
dependencies:
aria-query: 5.3.2
array-includes: 3.1.8
@ -5308,7 +5436,7 @@ snapshots:
axobject-query: 4.1.0
damerau-levenshtein: 1.0.8
emoji-regex: 9.2.2
eslint: 9.24.0
eslint: 9.25.0
hasown: 2.0.2
jsx-ast-utils: 3.3.5
language-tags: 1.0.9
@ -5317,10 +5445,10 @@ snapshots:
safe-regex-test: 1.1.0
string.prototype.includes: 2.0.1
eslint-plugin-mdx@3.4.0(eslint@9.24.0):
eslint-plugin-mdx@3.4.0(eslint@9.25.0):
dependencies:
eslint: 9.24.0
eslint-mdx: 3.4.0(eslint@9.24.0)
eslint: 9.25.0
eslint-mdx: 3.4.0(eslint@9.25.0)
mdast-util-from-markdown: 2.0.2
mdast-util-mdx: 3.0.0
micromark-extension-mdxjs: 3.0.0
@ -5336,32 +5464,32 @@ snapshots:
- remark-lint-file-extension
- supports-color
eslint-plugin-prettier@5.2.6(eslint-config-prettier@10.1.2(eslint@9.24.0))(eslint@9.24.0)(prettier@3.5.3):
eslint-plugin-prettier@5.2.6(eslint-config-prettier@10.1.2(eslint@9.25.0))(eslint@9.25.0)(prettier@3.5.3):
dependencies:
eslint: 9.24.0
eslint: 9.25.0
prettier: 3.5.3
prettier-linter-helpers: 1.0.0
synckit: 0.11.4
optionalDependencies:
eslint-config-prettier: 10.1.2(eslint@9.24.0)
eslint-config-prettier: 10.1.2(eslint@9.25.0)
eslint-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411(eslint@9.24.0):
eslint-plugin-react-compiler@19.0.0-beta-ebf51a3-20250411(eslint@9.25.0):
dependencies:
'@babel/core': 7.26.10
'@babel/parser': 7.27.0
'@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.26.10)
eslint: 9.24.0
eslint: 9.25.0
hermes-parser: 0.25.1
zod: 3.24.3
zod-validation-error: 3.4.0(zod@3.24.3)
transitivePeerDependencies:
- supports-color
eslint-plugin-react-hooks@5.2.0(eslint@9.24.0):
eslint-plugin-react-hooks@5.2.0(eslint@9.25.0):
dependencies:
eslint: 9.24.0
eslint: 9.25.0
eslint-plugin-react@7.37.5(eslint@9.24.0):
eslint-plugin-react@7.37.5(eslint@9.25.0):
dependencies:
array-includes: 3.1.8
array.prototype.findlast: 1.2.5
@ -5369,7 +5497,7 @@ snapshots:
array.prototype.tosorted: 1.1.4
doctrine: 2.1.0
es-iterator-helpers: 1.2.1
eslint: 9.24.0
eslint: 9.25.0
estraverse: 5.3.0
hasown: 2.0.2
jsx-ast-utils: 3.3.5
@ -5392,15 +5520,15 @@ snapshots:
eslint-visitor-keys@4.2.0: {}
eslint@9.24.0:
eslint@9.25.0:
dependencies:
'@eslint-community/eslint-utils': 4.6.1(eslint@9.24.0)
'@eslint-community/eslint-utils': 4.6.1(eslint@9.25.0)
'@eslint-community/regexpp': 4.12.1
'@eslint/config-array': 0.20.0
'@eslint/config-helpers': 0.2.1
'@eslint/core': 0.12.0
'@eslint/core': 0.13.0
'@eslint/eslintrc': 3.3.1
'@eslint/js': 9.24.0
'@eslint/js': 9.25.0
'@eslint/plugin-kit': 0.2.8
'@humanfs/node': 0.16.6
'@humanwhocodes/module-importer': 1.0.1
@ -5899,10 +6027,21 @@ snapshots:
domutils: 3.2.2
entities: 4.5.0
htmlparser2@9.1.0:
dependencies:
domelementtype: 2.3.0
domhandler: 5.0.3
domutils: 3.2.2
entities: 4.5.0
human-signals@5.0.0: {}
husky@9.1.7: {}
iconv-lite@0.6.3:
dependencies:
safer-buffer: 2.1.2
ieee754@1.2.1: {}
ignore@5.3.2: {}
@ -6806,6 +6945,10 @@ snapshots:
dependencies:
path-key: 4.0.0
nth-check@2.1.1:
dependencies:
boolbase: 1.0.0
object-assign@4.1.1: {}
object-inspect@1.13.4: {}
@ -6934,6 +7077,15 @@ snapshots:
parse-srcset@1.0.2: {}
parse5-htmlparser2-tree-adapter@7.1.0:
dependencies:
domhandler: 5.0.3
parse5: 7.2.1
parse5-parser-stream@7.1.2:
dependencies:
parse5: 7.2.1
parse5@7.2.1:
dependencies:
entities: 4.5.0
@ -7031,6 +7183,11 @@ snapshots:
queue-microtask@1.2.3: {}
react-activity-calendar@2.7.10(react@19.1.0):
dependencies:
date-fns: 4.1.0
react: 19.1.0
react-countup@6.5.3(react@19.1.0):
dependencies:
countup.js: 2.8.0
@ -7078,6 +7235,13 @@ snapshots:
dependencies:
react: 19.1.0
react-tooltip@5.28.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
'@floating-ui/dom': 1.6.13
classnames: 2.5.1
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
react-turnstile@1.1.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
react: 19.1.0
@ -7381,6 +7545,8 @@ snapshots:
es-errors: 1.3.0
is-regex: 1.2.1
safer-buffer@2.1.2: {}
sax@1.4.1: {}
scheduler@0.26.0: {}
@ -7855,6 +8021,8 @@ snapshots:
undici-types@6.21.0: {}
undici@6.21.2: {}
unified-engine@11.2.2:
dependencies:
'@types/concat-stream': 2.0.3
@ -8075,6 +8243,12 @@ snapshots:
- bufferutil
- utf-8-validate
whatwg-encoding@3.1.1:
dependencies:
iconv-lite: 0.6.3
whatwg-mimetype@4.0.0: {}
which-boxed-primitive@1.1.1:
dependencies:
is-bigint: 1.1.0