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 -

- +