import { useEffect, useState } from 'react'; import { useParams, Link } from 'react-router-dom'; import { blogPostsData } from '../data/blogPostsData'; import { NotFound } from './NotFound'; import style from '@styles/BlogPost.module.scss'; import { get } from 'http'; interface TableOfContentsItem { title: string; id: number; children?: TableOfContentsItem[]; } function dedent(str: string): string { const lines = str.split('\n'); while (lines.length > 0 && lines[0].trim() === '') { lines.shift(); } while (lines.length > 0 && lines[lines.length - 1].trim() === '') { lines.pop(); } const indents = lines .filter(line => line.trim().length > 0) .map(line => line.match(/^ */)![0].length); const minIndent = indents.length ? Math.min(...indents) : 0; return lines.map(line => line.slice(minIndent)).join('\n'); } export const BlogPost = () => { const { slug } = useParams<{ slug: string }>(); const [post, setPost] = useState(blogPostsData.find(post => post.slug === slug)); const [relatedPosts, setRelatedPosts] = useState(blogPostsData.slice(0, 3)); const [toc, setToc] = useState([]); useEffect(() => { const currentPost = blogPostsData.find(post => post.slug === slug); let id = 0; const toc: TableOfContentsItem[] = []; if (currentPost) { setPost(currentPost); const related = blogPostsData .filter(p => p.id !== currentPost.id) .filter(p => p.category === currentPost.category || p.tags.some(tag => currentPost.tags.includes(tag)) ) .slice(0, 3); setRelatedPosts(related); let newContent = ''; if (currentPost.content) { const content = dedent(currentPost.content); const lines = content.split('\n'); for (let i = 0; i < lines.length; i++) { if (/^#\s/.test(lines[i])) { newContent += `

${lines[i].replace(/^#+\s*/, '')}

\n`; toc.push({ title: lines[i].replace(/^#+\s*/, ''), id }); id++; } else if (/^##\s/.test(lines[i])) { newContent += `

${lines[i].replace(/^#+\s*/, '')}

\n`; if (toc.length > 0) { const parent = toc[toc.length - 1]; if (!parent.children) { parent.children = []; } parent.children.push({ title: lines[i].replace(/^#+\s*/, ''), id }); } id++; } else if (/^###\s/.test(lines[i])) { newContent += `

${lines[i].replace(/^#+\s*/, '')}

\n`; if (toc.length > 0) { const h2Parent = toc[toc.length - 1]; if (h2Parent.children && h2Parent.children.length > 0) { const h3Parent = h2Parent.children[h2Parent.children.length - 1]; if (!h3Parent.children) { h3Parent.children = []; } h3Parent.children.push({ title: lines[i].replace(/^#+\s*/, ''), id }); } } id++; } else if (/^\*\s/.test(lines[i])) { newContent += '\n'; } else if (/^\-\s/.test(lines[i])) { newContent += '
    \n'; for (; i < lines.length; i++) { if (/^\-\s/.test(lines[i])) { newContent += `
  1. ${lines[i].replace(/^\-\s/, '')}
  2. \n`; } else { break; } } newContent += '
\n'; } else { newContent += `

${lines[i]}

\n`; } } } newContent = newContent.replace(/\*\*(.*?)\*\*/g, '$1'); newContent = newContent.replace(/__(.*?)__/g, '$1'); newContent = newContent.replace(/\*(.*?)\*/g, '$1'); newContent = newContent.replace(/_(.*?)_/g, '$1'); newContent = newContent.replace(/`(.*?)`/g, '$1'); newContent = newContent.replace(/!\[(.*?)\]\((.*?)\)/g, '$1'); newContent = newContent.replace(/\[(.*?)\]\((.*?)\)/g, '$1'); const contentElement = document.getElementById('postContent'); contentElement!.innerHTML = newContent; setToc(toc); window.scrollTo(0, 0); } }, [slug]); if (!post) { return ; } return (
{/* Post Header */}
{post.category}
{/* Post Info */}

{post.title}

{post.date}
{post.author}
{post.readTime}
{post.commentCount} Comments
{/* Post Tags */}
{post.tags.map((tag, index) => ( {tag} ))}
{/* Share Section */}

Share this arcane knowledge

{/* Author Info */}
SecCodeSmith

SecCodeSmith

Digital blacksmith forging embedded systems and IoT solutions in the fires of innovation. Specializes in low-level firmware, communication protocols, and hardware-software integration for resource-constrained devices.

{/* Comments Section */}

Discussions ({post.commentCount})

{/* Sample Comments */}
User

Michael Chen

May 5, 2025 at 15:42

Excellent article! I've been struggling with I2C bus lockups in my weather station project. The recovery function you provided solved the issue. Have you considered adding a timeout mechanism to the SPI transfers for error detection?

Reply
{/* Comment Form */}

Leave your mark

); };