Skip to content

Commit f981c76

Browse files
committed
feat: Utterance 댓글 기능 추가
1 parent 2a8f9c4 commit f981c76

File tree

3 files changed

+87
-5
lines changed

3 files changed

+87
-5
lines changed

.vitepress/theme/index.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,12 @@ import { h } from "vue";
33
import type { Theme } from "vitepress";
44
import DefaultTheme from "vitepress/theme";
55
import PostCardList from "@/components/PostCardList/PostCardList.vue";
6+
import PostLayout from "@/components/PostLayout/PostLayout.vue";
67
import "./style.css";
78

89
export default {
910
extends: DefaultTheme,
10-
Layout: () => {
11-
return h(DefaultTheme.Layout, null, {
12-
// https://vitepress.dev/guide/extending-default-theme#layout-slots
13-
});
14-
},
11+
Layout: PostLayout,
1512
enhanceApp({ app, router, siteData }) {
1613
app.component("PostCardList", PostCardList);
1714
},
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<script setup lang="ts">
2+
import { onMounted, onBeforeUnmount, watch, ref, nextTick, toRef, type Ref } from "vue";
3+
4+
const props = defineProps<{
5+
theme: string;
6+
}>();
7+
8+
const containerRef = ref<HTMLDivElement | null>(null);
9+
10+
function mountUtterances(theme: string) {
11+
const container = containerRef.value;
12+
if (!container) return;
13+
14+
if (container.querySelector("iframe.utterances-frame")) return;
15+
16+
const script = document.createElement("script");
17+
18+
script.src = "https://utteranc.es/client.js";
19+
script.async = true;
20+
script.crossOrigin = "anonymous";
21+
22+
script.setAttribute("repo", "toothlessdev/toothlessdev-comments");
23+
script.setAttribute("issue-term", "pathname");
24+
script.setAttribute("label", "blog-comment");
25+
script.setAttribute("theme", theme);
26+
27+
container.appendChild(script);
28+
}
29+
30+
function setUtterancesTheme(theme: string) {
31+
const iframe = containerRef.value?.querySelector<HTMLIFrameElement>("iframe.utterances-frame");
32+
if (!iframe?.contentWindow) return;
33+
iframe.contentWindow.postMessage({ type: "set-theme", theme }, "https://utteranc.es");
34+
}
35+
36+
onMounted(async () => {
37+
await nextTick();
38+
mountUtterances(props.theme);
39+
});
40+
41+
watch(toRef(props, "theme"), (t) => {
42+
if (!containerRef.value?.querySelector("iframe.utterances-frame")) {
43+
mountUtterances(t);
44+
return;
45+
}
46+
setUtterancesTheme(t);
47+
});
48+
49+
onBeforeUnmount(() => {
50+
const container = containerRef.value;
51+
if (!container) return;
52+
53+
container.querySelector("iframe.utterances-frame")?.remove();
54+
});
55+
</script>
56+
57+
<template>
58+
<div ref="containerRef" />
59+
</template>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<script setup>
2+
import { computed } from "vue";
3+
import { useData } from "vitepress";
4+
import DefaultTheme from "vitepress/theme";
5+
import PostComment from "@/components/PostComment/PostComment.vue";
6+
const { Layout } = DefaultTheme;
7+
8+
const COMMENT_THEME_DARK = "photon-dark";
9+
const COMMENT_THEME_LIGHT = "github-light";
10+
11+
const { frontmatter, page, isDark } = useData();
12+
13+
const commentTheme = computed(() => (isDark.value ? COMMENT_THEME_DARK : COMMENT_THEME_LIGHT));
14+
</script>
15+
16+
<template>
17+
<Layout>
18+
<template #doc-after>
19+
<PostComment
20+
v-if="frontmatter.comment"
21+
:key="page.relativePath"
22+
:theme="commentTheme"
23+
></PostComment>
24+
</template>
25+
</Layout>
26+
</template>

0 commit comments

Comments
 (0)