aboutsummaryrefslogtreecommitdiff
path: root/src/pages/Post.tsx
blob: 17022d28076135d7aa4b70316645add8b03e19d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import { useEffect, useState } from "react";
import { useParams, Link } from "react-router-dom";
import matter from "gray-matter";
import ReactMarkdown from "react-markdown";
import CodeSnippet from "../components/CodeSnippet";
import LinkWithIcon from "../components/LinkWithIcon";
import NotFoundPage from "./404Page";

interface PostMeta {
  title: string;
  date: string;
  cover?: string;
}

export default function Post() {
  const { slug } = useParams<{ slug: string }>();
  const [meta, setMeta] = useState<PostMeta | null>(null);
  const [content, setContent] = useState("");
  const [notFound, setNotFound] = useState(false);

  useEffect(() => {
    import(`../blog/${slug}.md?raw`)
      .then((m) => {
        const { data, content } = matter(m.default);
        setMeta(data as PostMeta);
        setContent(content);
      })
      .catch(() => setNotFound(true));
  }, [slug]);

  if (!meta) return null;
  if (notFound) return <NotFoundPage />;

  return (
    <article className="prose prose-zinc dark:prose-invert mx-auto px-4 py-10">
      <Link to="/blog" className="no-underline">
        ← Zurück zum Blog
      </Link>

      {meta.cover && (
        <img
          src={meta.cover}
          alt={meta.title}
          className="w-full h-60 object-cover rounded-lg my-6"
        />
      )}

      <h1>{meta.title}</h1>
      <p className="text-sm text-zinc-500 mb-8">
        {new Date(meta.date).toLocaleDateString("de-DE")}
      </p>
      
      <article className="markdown-body">
        <ReactMarkdown
          components={{
            code({ children }) {
              const text = String(children).replace(/\n$/, "");
              return <CodeSnippet code={text} initialLines={5} />;
            },

            a({ href = "", children, ...props }) {
              return (
                <LinkWithIcon href={href} {...props}>
                {children}
              </LinkWithIcon>
              );
            },
          }}
        >
          {content}
        </ReactMarkdown>
      </article>
    </article>
  );
}