Optimizations + minor cleanups
All checks were successful
Docker Deploy / build-and-push (push) Successful in 4m15s
All checks were successful
Docker Deploy / build-and-push (push) Successful in 4m15s
This commit is contained in:
@@ -1,10 +1,5 @@
|
||||
import { Icon } from "astro-icon/components";
|
||||
import type {
|
||||
IconType,
|
||||
LucideIcon,
|
||||
AstroIconName,
|
||||
CustomIconComponent,
|
||||
} from "../types";
|
||||
import type { IconType, LucideIcon, AstroIconName } from "../types";
|
||||
|
||||
interface IconRendererProps {
|
||||
icon: IconType;
|
||||
@@ -22,10 +17,6 @@ function isAstroIconName(icon: IconType): icon is AstroIconName {
|
||||
return typeof icon === "string";
|
||||
}
|
||||
|
||||
function isCustomComponent(icon: IconType): icon is CustomIconComponent {
|
||||
return typeof icon === "function" && !isLucideIcon(icon);
|
||||
}
|
||||
|
||||
export default function IconRenderer({
|
||||
icon,
|
||||
size,
|
||||
@@ -41,11 +32,10 @@ export default function IconRenderer({
|
||||
return <Icon name={icon} class={className} {...props} />;
|
||||
}
|
||||
|
||||
if (isCustomComponent(icon)) {
|
||||
if (typeof icon === "function") {
|
||||
const CustomComponent = icon;
|
||||
return <CustomComponent class={className} {...props} />;
|
||||
}
|
||||
|
||||
// Fallback
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -32,26 +32,15 @@ export default function NavigationBar({ currentPath }: NavigationBarProps) {
|
||||
}
|
||||
};
|
||||
|
||||
// Set initial path
|
||||
updatePath();
|
||||
|
||||
// Listen for Astro's view transition events
|
||||
const handleAstroNavigation = () => {
|
||||
updatePath();
|
||||
};
|
||||
|
||||
// Listen for astro:page-load event which fires after navigation completes
|
||||
document.addEventListener("astro:page-load", handleAstroNavigation);
|
||||
|
||||
// Also listen for astro:after-swap as a backup
|
||||
document.addEventListener("astro:after-swap", handleAstroNavigation);
|
||||
|
||||
// Listen for regular navigation events as fallback
|
||||
document.addEventListener("astro:page-load", updatePath);
|
||||
document.addEventListener("astro:after-swap", updatePath);
|
||||
window.addEventListener("popstate", updatePath);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("astro:page-load", handleAstroNavigation);
|
||||
document.removeEventListener("astro:after-swap", handleAstroNavigation);
|
||||
document.removeEventListener("astro:page-load", updatePath);
|
||||
document.removeEventListener("astro:after-swap", updatePath);
|
||||
window.removeEventListener("popstate", updatePath);
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -61,7 +61,7 @@ export default function ResumeDownloadButton({
|
||||
Generating PDF...
|
||||
</>
|
||||
) : (
|
||||
<>Download Resume</>
|
||||
"Download Resume"
|
||||
)}
|
||||
</button>
|
||||
{error && <div class="mt-2 text-error text-sm">{error}</div>}
|
||||
|
||||
@@ -218,8 +218,8 @@ export default function ResumeSettingsModal({
|
||||
role="tab"
|
||||
class={`px-4 py-2 rounded-full text-sm font-bold transition-all duration-200 ${
|
||||
activeTab === "edit"
|
||||
? "btn btn-primary font-bold shadow-sm"
|
||||
: "text-base-content/70 hover:text-base-content font-bold hover:bg-base-200"
|
||||
? "btn btn-primary shadow-sm"
|
||||
: "text-base-content/70 hover:text-base-content hover:bg-base-200"
|
||||
}`}
|
||||
onClick={() => setActiveTab("edit")}
|
||||
>
|
||||
|
||||
@@ -9,7 +9,7 @@ I change what I use _constantly_ in order to find something that feels just
|
||||
right. I wanted to share them here and update them here so when someone asks, I
|
||||
can just point them to this article.
|
||||
|
||||
1. VSCodium - The joys of VSCode and its extension ecosystem, but without Microsoft's insane amount of tracking and AI slop
|
||||
1. Zed - Zed is a performany open-source code editor that allows you to configure away all of the AI and signin features. Performs well and has its own extensive extension ecosystem. My config to clean it up can be found [here](https://git.atri.dad/atridad/zed-config).
|
||||
3. Ghostty - A Zig based terminal emulator by one of the founders of Hashicorp. Runs great on MacOS and Linux. No windows for those who are into that.
|
||||
4. Bitwarden - An open-source password manager. Easy to self host with Vaultwarden and with the recent updates, it has SSH Agent support!
|
||||
5. iA Writer - A minimalist Markdown editor. For MacOS and Windows only, but really the MacOS version is the most mature. Awesome for focus.
|
||||
|
||||
@@ -6,23 +6,14 @@ export const GET: APIRoute = async () => {
|
||||
const posts = await getCollection('posts');
|
||||
|
||||
// Get the raw content from each post
|
||||
const postsWithContent = await Promise.all(
|
||||
posts.map(async (post) => {
|
||||
const { Content } = await post.render();
|
||||
|
||||
// Get the raw markdown content by reading the file
|
||||
const rawContent = post.body;
|
||||
|
||||
return {
|
||||
slug: post.slug,
|
||||
title: post.data.title,
|
||||
description: post.data.description,
|
||||
pubDate: post.data.pubDate.toISOString().split('T')[0],
|
||||
tags: post.data.tags || [],
|
||||
content: rawContent
|
||||
};
|
||||
})
|
||||
);
|
||||
const postsWithContent = posts.map((post) => ({
|
||||
slug: post.slug,
|
||||
title: post.data.title,
|
||||
description: post.data.description,
|
||||
pubDate: post.data.pubDate.toISOString().split('T')[0],
|
||||
tags: post.data.tags || [],
|
||||
content: post.body
|
||||
}));
|
||||
|
||||
return new Response(JSON.stringify(postsWithContent), {
|
||||
status: 200,
|
||||
|
||||
@@ -3,7 +3,6 @@ import { config } from "../../../config";
|
||||
import * as TOML from "@iarna/toml";
|
||||
import { renderToStream } from "@react-pdf/renderer";
|
||||
import { ResumeDocument } from "../../../pdf/ResumeDocument";
|
||||
import React from "react";
|
||||
|
||||
async function getSimpleIconPath(iconName: string): Promise<string> {
|
||||
try {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
/** @jsxImportSource react */
|
||||
import React from "react";
|
||||
import {
|
||||
Document,
|
||||
Page,
|
||||
@@ -9,7 +8,6 @@ import {
|
||||
Link,
|
||||
Svg,
|
||||
Path,
|
||||
Font,
|
||||
} from "@react-pdf/renderer";
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
|
||||
@@ -92,29 +92,25 @@ export async function fetchGiteaInfoFromUrl(
|
||||
return fetchGiteaRepoInfo(config);
|
||||
}
|
||||
|
||||
const MINUTE_MS = 60_000;
|
||||
const HOUR_MS = 3_600_000;
|
||||
const DAY_MS = 86_400_000;
|
||||
|
||||
const pluralize = (n: number, unit: string) => `${n} ${unit}${n !== 1 ? "s" : ""} ago`;
|
||||
|
||||
export function formatRelativeTime(dateString: string): string {
|
||||
if (!dateString) return "Unknown";
|
||||
|
||||
const date = new Date(dateString);
|
||||
const now = new Date();
|
||||
const diffMs = now.getTime() - date.getTime();
|
||||
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
||||
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
||||
const diffMinutes = Math.floor(diffMs / (1000 * 60));
|
||||
const diffMs = Date.now() - new Date(dateString).getTime();
|
||||
const diffMinutes = Math.floor(diffMs / MINUTE_MS);
|
||||
const diffHours = Math.floor(diffMs / HOUR_MS);
|
||||
const diffDays = Math.floor(diffMs / DAY_MS);
|
||||
|
||||
if (diffMinutes < 60) {
|
||||
return `${diffMinutes} minute${diffMinutes !== 1 ? "s" : ""} ago`;
|
||||
} else if (diffHours < 24) {
|
||||
return `${diffHours} hour${diffHours !== 1 ? "s" : ""} ago`;
|
||||
} else if (diffDays < 30) {
|
||||
return `${diffDays} day${diffDays !== 1 ? "s" : ""} ago`;
|
||||
} else if (diffDays < 365) {
|
||||
const months = Math.floor(diffDays / 30);
|
||||
return `${months} month${months !== 1 ? "s" : ""} ago`;
|
||||
} else {
|
||||
const years = Math.floor(diffDays / 365);
|
||||
return `${years} year${years !== 1 ? "s" : ""} ago`;
|
||||
}
|
||||
if (diffMinutes < 60) return pluralize(diffMinutes, "minute");
|
||||
if (diffHours < 24) return pluralize(diffHours, "hour");
|
||||
if (diffDays < 30) return pluralize(diffDays, "day");
|
||||
if (diffDays < 365) return pluralize(Math.floor(diffDays / 30), "month");
|
||||
return pluralize(Math.floor(diffDays / 365), "year");
|
||||
}
|
||||
|
||||
export function formatRepoSize(sizeKb: number): string {
|
||||
|
||||
Reference in New Issue
Block a user