Skip to content

Commit

Permalink
feat: comments section powered by utterances
Browse files Browse the repository at this point in the history
  • Loading branch information
EATSTEAK committed Aug 20, 2024
1 parent 0455a9a commit d64a1db
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 120 deletions.
28 changes: 28 additions & 0 deletions src/components/Comments.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { type Component, createEffect } from "solid-js";
import theme from "../utils/theme.ts";

export const Comments: Component<{}> = () => {
const [isDarkTheme, _] = theme;
let sectionRef: HTMLDivElement;
const utterances = () => {
const utterancesScript = document.createElement("script");
utterancesScript.src = "https://utteranc.es/client.js";
utterancesScript.setAttribute("repo", "eatsteak/eatsteak.dev");
utterancesScript.setAttribute("issue-term", "pathname");
utterancesScript.setAttribute("label", "blog");
utterancesScript.setAttribute(
"theme",
isDarkTheme() ? "dark-blue" : "github-light",
);
utterancesScript.crossOrigin = "anonymous";
utterancesScript.async = true;
return utterancesScript;
};
createEffect(() => {
if (sectionRef) {
sectionRef.innerHTML = "";
sectionRef.appendChild(utterances());
}
}, [isDarkTheme]);
return <section class="comments" ref={sectionRef}></section>;
};
247 changes: 127 additions & 120 deletions src/layouts/BlogPost.astro
Original file line number Diff line number Diff line change
@@ -1,148 +1,155 @@
---
import { getCollection, type CollectionEntry } from "astro:content";
import {getCollection, type CollectionEntry} from "astro:content";
import Layout from "./Layout.astro";
import { Profile } from "../components/Profile";
import { FormattedDate } from "../components/FormattedDate";
import { Topics } from "../components/Topics";
import { CategoryLabel } from "../components/CategoryLabel";
import {Profile} from "../components/Profile";
import {FormattedDate} from "../components/FormattedDate";
import {Topics} from "../components/Topics";
import {CategoryLabel} from "../components/CategoryLabel";
import "../styles/prose.css";
import { Counter } from "../components/Counter";
import { CATEGORIES } from "../consts";
import {Counter} from "../components/Counter";
import {Comments} from "../components/Comments";
import {CATEGORIES} from "../consts";
import PostItem from "../components/PostItem.astro";
import { getReadingTime } from "../utils/reading-time";
import { MinutesRead } from "../components/MinutesRead";
import type { MarkdownHeading } from "astro";
import { TableOfContents } from "../components/TableOfContents";
import {getReadingTime} from "../utils/reading-time";
import {MinutesRead} from "../components/MinutesRead";
import type {MarkdownHeading} from "astro";
import {TableOfContents} from "../components/TableOfContents";
type Props = CollectionEntry<"blog">["data"] & {
slug: string;
minutesRead: number | undefined;
headings: MarkdownHeading[];
slug: string;
minutesRead: number | undefined;
headings: MarkdownHeading[];
};
const {
slug,
title,
description,
pubDate,
updatedDate,
heroImage,
category,
topics,
minutesRead,
headings,
slug,
title,
description,
pubDate,
updatedDate,
heroImage,
category,
topics,
minutesRead,
headings,
} = Astro.props;
const allPosts = (await getCollection("blog")).sort(
(a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf(),
(a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf(),
);
const recentPostsInCategory = allPosts
.filter((post) => post.data.hidden !== true && post.slug !== slug)
.filter(
(post) =>
(CATEGORIES[post.data.category ?? "uncategorized"]?.id ??
"uncategorized") === (category ?? "uncategorized"),
)
.slice(0, 3);
.filter((post) => post.data.hidden !== true && post.slug !== slug)
.filter(
(post) =>
(CATEGORIES[post.data.category ?? "uncategorized"]?.id ??
"uncategorized") === (category ?? "uncategorized"),
)
.slice(0, 3);
function buildToc(headings: MarkdownHeading[]): TocHeading[] {
const toc: TocHeading[] = [];
const parentHeadings = new Map();
headings.forEach((h) => {
const heading = { ...h, subheadings: [] };
parentHeadings.set(heading.depth, heading);
if (heading.depth === 2) {
toc.push(heading);
} else {
parentHeadings.get(heading.depth - 1).subheadings.push(heading);
}
});
return toc;
const toc: TocHeading[] = [];
const parentHeadings = new Map();
headings.forEach((h) => {
const heading = {...h, subheadings: []};
parentHeadings.set(heading.depth, heading);
if (heading.depth === 2) {
toc.push(heading);
} else {
parentHeadings.get(heading.depth - 1).subheadings.push(heading);
}
});
return toc;
}
const toc = buildToc(headings);
---

<Layout
title={`${title} - EATSTEAK.DEV`}
description={description}
image={`/card/og/${slug}.png`}
title={`${title} - EATSTEAK.DEV`}
description={description}
image={`/card/og/${slug}.png`}
>
<main class="flex flex-col w-full">
<section
class="self-center flex justify-center items-stretch w-full p-8 xl:p-0"
>
<article class="self-center w-full max-w-screen-md pb-16">
<section class="mb-2 image min-h-[16rem]">
{heroImage && <img class="max-w-100%" src={heroImage} alt="" />}
</section>
<section class="prose">
<div class="title mb-8">
<CategoryLabel category={category ?? "uncategorized"} />
<h1>{title}</h1>
<div class="flex flex-wrap line-between-flex-items">
<div class="date text-gray-500">
<FormattedDate dateTime={pubDate} client:only="solid-js" />
{
updatedDate && (
<span>
<main class="flex flex-col w-full">
<section
class="self-center flex justify-center items-stretch w-full p-8 xl:p-0"
>
<article class="self-center w-full max-w-screen-md pb-16">
<section class="mb-2 image min-h-[16rem]">
{heroImage && <img class="max-w-100%" src={heroImage} alt=""/>}
</section>
<section class="prose">
<div class="title mb-8">
<CategoryLabel category={category ?? "uncategorized"}/>
<h1>{title}</h1>
<div class="flex flex-wrap line-between-flex-items">
<div class="date text-gray-500">
<FormattedDate dateTime={pubDate} client:only="solid-js"/>
{
updatedDate && (
<span>
게시, <FormattedDate
dateTime={updatedDate}
client:only="solid-js"
/>{" "}
수정
dateTime={updatedDate}
client:only="solid-js"
/>
{" "}
수정
</span>
)
}
</div>
{minutesRead && <MinutesRead minutesRead={minutesRead} />}
<Counter path={Astro.url.pathname} client:only="solid-js" />
</div>
{
topics && (
<div class="topics mt-2 mb-8">
<Topics topics={topics} />
)
}
</div>
{minutesRead &&
<MinutesRead minutesRead={minutesRead}/>}
<Counter path={Astro.url.pathname} client:only="solid-js"/>
</div>
{
topics && (
<div class="topics mt-2 mb-8">
<Topics topics={topics}/>
</div>
)
}
</div>
<div class="content">
<slot/>
</div>
</section>
<section class="pt-8">
<hr/>
<Comments client:only="solid-js"/>
</section>
</article>
<section class="hidden self-stretch lg:block pt-[16rem] max-w-xs">
<div class="py-8 pl-8 sticky top-0">
<TableOfContents tocHeadings={toc} client:only="solid-js"/>
</div>
</section>
</section>
<section
class="py-16 flex flex-col items-center bg-slate-50 dark:bg-slate-900 transition-colors"
>
<div class="flex flex-col gap-8 w-full max-w-screen-lg p-8 xl:p-0">
<div class="w-full">
<Profile/>
</div>
<div class="w-full">
<h3>같은 분류의 최신 글</h3>
<div class="mt-4 flex flex-col gap-2">
{
recentPostsInCategory.map((post) => (
<PostItem
post={post}
minutesRead={getReadingTime(post.body)}
/>
))
}
{
recentPostsInCategory.length === 0 && (
<p class="mx-auto my-8">읽을 수 있는 글이 없습니다.</p>
)
}
</div>
</div>
)
}
</div>
<div class="content">
<slot />
</div>
</div>
</section>
</article>
<section class="hidden self-stretch lg:block pt-[16rem] max-w-xs">
<div class="py-8 pl-8 sticky top-0">
<TableOfContents tocHeadings={toc} client:only="solid-js" />
</div>
</section>
</section>
<section
class="py-16 flex flex-col items-center bg-slate-50 dark:bg-slate-900 transition-colors"
>
<div class="flex flex-col gap-8 w-full max-w-screen-lg p-8 xl:p-0">
<div class="w-full px-1">
<Profile />
</div>
<div class="w-full">
<h3>같은 분류의 최신 글</h3>
<div class="mt-4 flex flex-col gap-2">
{
recentPostsInCategory.map((post) => (
<PostItem
post={post}
minutesRead={getReadingTime(post.body)}
/>
))
}
{
recentPostsInCategory.length === 0 && (
<p class="mx-auto my-8">읽을 수 있는 글이 없습니다.</p>
)
}
</div>
</div>
</div>
</section>
</main>
</main>
</Layout>

0 comments on commit d64a1db

Please sign in to comment.