From 1d58d69a7a72abf98869b5691afae8762238f55e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=E1=BA=A7n=20=C4=90=E1=BB=A9c=20Nam?= Date: Sun, 13 Oct 2024 17:40:22 +0700 Subject: [PATCH] feat: add disqus and commento comments providers --- quartz.config.ts | 3 + quartz/cfg.ts | 27 ++++++++ quartz/components/Comments.tsx | 69 ++++++++++++-------- quartz/components/scripts/comments.inline.ts | 68 +++++++++++++++++-- 4 files changed, 134 insertions(+), 33 deletions(-) diff --git a/quartz.config.ts b/quartz.config.ts index e96ee4843..11b42425b 100644 --- a/quartz.config.ts +++ b/quartz.config.ts @@ -52,6 +52,9 @@ const config: QuartzConfig = { }, }, }, + comments: { + provider: "commento", + }, }, plugins: { transformers: [ diff --git a/quartz/cfg.ts b/quartz/cfg.ts index 85527a093..933b0188c 100644 --- a/quartz/cfg.ts +++ b/quartz/cfg.ts @@ -43,6 +43,31 @@ export type Analytics = projectId?: string } +export type Comments = + | null + | { + provider: "giscus" + repo: `${string}/${string}` + repoId: string + category: string + categoryId: string + mapping?: "url" | "title" | "og:title" | "specific" | "number" | "pathname" + strict?: boolean + reactionsEnabled?: boolean + inputPosition?: "top" | "bottom" + } + | { + provider: "commento" + host?: string + cssOverride?: string + noFonts?: boolean + hideDeleted?: boolean + } + | { + provider: "disqus" + shortName: string + } + export interface GlobalConfiguration { pageTitle: string pageTitleSuffix?: string @@ -56,6 +81,8 @@ export interface GlobalConfiguration { ignorePatterns: string[] /** Whether to use created, modified, or published as the default type of date */ defaultDateType: ValidDateType + /** Comments for page */ + comments: Comments /** Base URL to use for CNAME files, sitemaps, and RSS feeds that require an absolute URL. * Quartz will avoid using this as much as possible and use relative URLs most of the time */ diff --git a/quartz/components/Comments.tsx b/quartz/components/Comments.tsx index 8e4494026..b4d033351 100644 --- a/quartz/components/Comments.tsx +++ b/quartz/components/Comments.tsx @@ -3,42 +3,53 @@ import { classNames } from "../util/lang" // @ts-ignore import script from "./scripts/comments.inline" -type Options = { - provider: "giscus" - options: { - repo: `${string}/${string}` - repoId: string - category: string - categoryId: string - mapping?: "url" | "title" | "og:title" | "specific" | "number" | "pathname" - strict?: boolean - reactionsEnabled?: boolean - inputPosition?: "top" | "bottom" - } -} - function boolToStringBool(b: boolean): string { return b ? "1" : "0" } -export default ((opts: Options) => { +export default (() => { const Comments: QuartzComponent = ({ displayClass, cfg }: QuartzComponentProps) => { - return ( -
- ) + switch (cfg.comments?.provider) { + case "giscus": + return ( +
+
+
+ ) + case "commento": + return ( +
+
+
+ ) + case "disqus": + return ( +
+
+
+ ) + default: + return <> + } } Comments.afterDOMLoaded = script return Comments -}) satisfies QuartzComponentConstructor +}) satisfies QuartzComponentConstructor diff --git a/quartz/components/scripts/comments.inline.ts b/quartz/components/scripts/comments.inline.ts index 4ab29f087..463470bd3 100644 --- a/quartz/components/scripts/comments.inline.ts +++ b/quartz/components/scripts/comments.inline.ts @@ -1,4 +1,4 @@ -const changeTheme = (e: CustomEventMap["themechange"]) => { +const changeGiscusTheme = (e: CustomEventMap["themechange"]) => { const theme = e.detail.theme const iframe = document.querySelector("iframe.giscus-frame") as HTMLIFrameElement if (!iframe) { @@ -34,7 +34,7 @@ type GiscusElement = Omit & { } } -document.addEventListener("nav", () => { +function setupGiscus() { const giscusContainer = document.querySelector(".giscus") as GiscusElement if (!giscusContainer) { return @@ -62,6 +62,66 @@ document.addEventListener("nav", () => { giscusContainer.appendChild(giscusScript) - document.addEventListener("themechange", changeTheme) - window.addCleanup(() => document.removeEventListener("themechange", changeTheme)) + document.addEventListener("themechange", changeGiscusTheme) + window.addCleanup(() => document.removeEventListener("themechange", changeGiscusTheme)) +} + +type CommentoElement = Omit & { + dataset: DOMStringMap & { + host: string + cssOverride: string + noFonts: string + hideDeleted: string + } +} + +function setupCommento() { + const commentoContainer = document.querySelector("#commento") as CommentoElement + if (!commentoContainer) { + return + } + + const commentoScript = document.createElement("script") + commentoScript.src = "https://" + commentoContainer.dataset.host + "/js/commento.js" + commentoScript.defer = true + commentoScript.setAttribute("data-css-override", commentoContainer.dataset.cssOverride) + commentoScript.setAttribute("data-no-fonts", commentoContainer.dataset.noFonts) + commentoScript.setAttribute("data-hide-deleted", commentoContainer.dataset.hideDeleted) + + commentoContainer.appendChild(commentoScript) +} + +type DisqusElement = Omit & { + dataset: DOMStringMap & { + shortName: string + } +} + +function setupDisqus() { + const disqusContainer = document.querySelector("#disqus_thread") as DisqusElement + if (!disqusContainer) { + return + } + + const disqusScript = document.createElement("script") + disqusScript.src = "https://" + disqusContainer.dataset.shortName + ".disqus.com/embed.js" + disqusScript.setAttribute("data-timestamp", "" + +new Date()) + + disqusContainer.appendChild(disqusScript) +} + +document.addEventListener("nav", () => { + const commentContainer = document.querySelector("#comment") + if (!commentContainer) { + return + } + const provider = commentContainer.getAttribute("data-provider") + switch (provider) { + case "giscus": + setupGiscus() + case "commento": + setupCommento() + case "disqus": + setupDisqus() + } })