From 6ef97bb5f78e154b4a984bf903a309f70ffe142a Mon Sep 17 00:00:00 2001 From: Timothy Pidashev Date: Tue, 28 Jan 2025 10:17:01 -0800 Subject: [PATCH] Update post index, rss feed, 404 page --- src/package.json | 1 + src/pnpm-lock.yaml | 10 +++++ src/src/components/404/glitched-text.tsx | 56 ++++++++++++++++++++++++ src/src/components/blog/header.tsx | 38 ++++++++++++++++ src/src/components/blog/post-list.tsx | 7 +-- src/src/pages/404.astro | 8 ++-- src/src/pages/blog/index.astro | 3 ++ src/src/pages/rss.ts | 13 +++++- 8 files changed, 124 insertions(+), 12 deletions(-) create mode 100644 src/src/components/404/glitched-text.tsx create mode 100644 src/src/components/blog/header.tsx diff --git a/src/package.json b/src/package.json index 9d16e8b..ba22f1d 100644 --- a/src/package.json +++ b/src/package.json @@ -22,6 +22,7 @@ "@astrojs/sitemap": "^3.2.1", "@react-hook/intersection-observer": "^3.1.2", "lucide-react": "^0.468.0", + "marked": "^15.0.6", "react": "^18.3.1", "react-dom": "^18.3.1", "react-responsive": "^10.0.0", diff --git a/src/pnpm-lock.yaml b/src/pnpm-lock.yaml index 12976b4..58ac0bb 100644 --- a/src/pnpm-lock.yaml +++ b/src/pnpm-lock.yaml @@ -23,6 +23,9 @@ importers: lucide-react: specifier: ^0.468.0 version: 0.468.0(react@18.3.1) + marked: + specifier: ^15.0.6 + version: 15.0.6 react: specifier: ^18.3.1 version: 18.3.1 @@ -1353,6 +1356,11 @@ packages: markdown-table@3.0.4: resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} + marked@15.0.6: + resolution: {integrity: sha512-Y07CUOE+HQXbVDCGl3LXggqJDbXDP2pArc2C1N1RRMN0ONiShoSsIInMd5Gsxupe7fKLpgimTV+HOJ9r7bA+pg==} + engines: {node: '>= 18'} + hasBin: true + matchmediaquery@0.4.2: resolution: {integrity: sha512-wrZpoT50ehYOudhDjt/YvUJc6eUzcdFPdmbizfgvswCKNHD1/OBOHYJpHie+HXpu6bSkEGieFMYk6VuutaiRfA==} @@ -3717,6 +3725,8 @@ snapshots: markdown-table@3.0.4: {} + marked@15.0.6: {} + matchmediaquery@0.4.2: dependencies: css-mediaquery: 0.1.2 diff --git a/src/src/components/404/glitched-text.tsx b/src/src/components/404/glitched-text.tsx new file mode 100644 index 0000000..bd0ef07 --- /dev/null +++ b/src/src/components/404/glitched-text.tsx @@ -0,0 +1,56 @@ +import React, { useState, useEffect } from "react"; + +const GlitchText = () => { + const originalText = 'Error 404'; + const [characters, setCharacters] = useState( + originalText.split("").map(char => ({ char, isGlitched: false })) + ); + const glitchChars = "!<>-_\\/[]{}—=+*^?#________"; + + useEffect(() => { + const glitchInterval = setInterval(() => { + if (Math.random() < 0.2) { // 20% chance to trigger glitch + setCharacters(prev => { + return originalText.split('').map((originalChar, index) => { + if (Math.random() < 0.3) { // 30% chance to glitch each character + return { + char: glitchChars[Math.floor(Math.random() * glitchChars.length)], + isGlitched: true + }; + } + return { char: originalChar, isGlitched: false }; + }); + }); + + // Reset after short delay + setTimeout(() => { + setCharacters(originalText.split('').map(char => ({ + char, + isGlitched: false + }))); + }, 100); + } + }, 50); + + return () => clearInterval(glitchInterval); + }, []); + + return ( +
+

+ + {characters.map((charObj, index) => ( + + {charObj.char} + + ))} + +

+
+ ); +}; + +export default GlitchText; diff --git a/src/src/components/blog/header.tsx b/src/src/components/blog/header.tsx new file mode 100644 index 0000000..4e25020 --- /dev/null +++ b/src/src/components/blog/header.tsx @@ -0,0 +1,38 @@ +import React from "react"; +import { RssIcon, TagIcon, TrendingUpIcon } from "lucide-react"; + +export const BlogHeader = () => { + return ( +
+

+ Latest Thoughts
+ & Writings +

+
+ + + RSS Feed + + + + + Browse Tags + + + + + Most Popular + +
+
+ ); +}; diff --git a/src/src/components/blog/post-list.tsx b/src/src/components/blog/post-list.tsx index 6215fc0..c024d2b 100644 --- a/src/src/components/blog/post-list.tsx +++ b/src/src/components/blog/post-list.tsx @@ -27,12 +27,7 @@ const formatDate = (dateString: string) => { export const BlogPostList = ({ posts }: BlogPostListProps) => { return ( -
-

- Latest Thoughts
- & Writings -

- +
    {posts.map((post) => (
  • diff --git a/src/src/pages/404.astro b/src/src/pages/404.astro index 48a7b53..dde8857 100644 --- a/src/src/pages/404.astro +++ b/src/src/pages/404.astro @@ -1,16 +1,16 @@ --- import IndexLayout from "@/layouts/index.astro"; - +import GlitchText from "@/components/404/glitched-text"; const title = "404 Not Found"; ---
    -

    404

    -

    Whoops! This page doesn't exist.

    + +

    Whoops! This page doesn't exist :(

    diff --git a/src/src/pages/blog/index.astro b/src/src/pages/blog/index.astro index bd16b94..29d3e41 100644 --- a/src/src/pages/blog/index.astro +++ b/src/src/pages/blog/index.astro @@ -1,7 +1,9 @@ --- import { getCollection } from "astro:content"; import ContentLayout from "@/layouts/content.astro"; +import { BlogHeader } from "@/components/blog/header"; import { BlogPostList } from "@/components/blog/post-list"; + const posts = (await getCollection("blog", ({ data }) => { return data.isDraft !== true; })).sort((a, b) => { @@ -22,5 +24,6 @@ const posts = (await getCollection("blog", ({ data }) => { title="Blog | Timothy Pidashev" description="My experiences and technical insights into software development and the ever-evolving world of programming." > + diff --git a/src/src/pages/rss.ts b/src/src/pages/rss.ts index 019c2d9..2f9bdd1 100644 --- a/src/src/pages/rss.ts +++ b/src/src/pages/rss.ts @@ -5,16 +5,25 @@ import type { APIContext } from "astro"; export async function GET(context: APIContext) { const blog = await getCollection("blog"); + const sortedPosts = blog + .sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf()); + return rss({ title: "Timothy Pidashev", description: "My experiences and technical insights into software development and the ever-evolving world of programming.", site: context.site!, - items: blog.map((post) => ({ + items: sortedPosts.map((post) => ({ title: post.data.title, pubDate: post.data.date, description: post.data.description, link: `/blog/${post.slug}/`, + author: post.data.author, + categories: post.data.tags, + enclosure: post.data.image ? { + url: new URL(`blog/${post.slug}/thumbnail.png`, context.site).toString(), + type: 'image/jpeg', + length: 0 + } : undefined })), - customData: `en-us`, }); }