feat: add disqus and commento comments providers

This commit is contained in:
Trần Đức Nam 2024-10-13 17:40:22 +07:00
parent c5d97db000
commit 1d58d69a7a
No known key found for this signature in database
4 changed files with 134 additions and 33 deletions

View File

@ -52,6 +52,9 @@ const config: QuartzConfig = {
},
},
},
comments: {
provider: "commento",
},
},
plugins: {
transformers: [

View File

@ -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
*/

View File

@ -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 (
<div
class={classNames(displayClass, "giscus")}
data-repo={opts.options.repo}
data-repo-id={opts.options.repoId}
data-category={opts.options.category}
data-category-id={opts.options.categoryId}
data-mapping={opts.options.mapping ?? "url"}
data-strict={boolToStringBool(opts.options.strict ?? true)}
data-reactions-enabled={boolToStringBool(opts.options.reactionsEnabled ?? true)}
data-input-position={opts.options.inputPosition ?? "bottom"}
></div>
)
switch (cfg.comments?.provider) {
case "giscus":
return (
<div id="comment" data-provider={cfg.comments.provider}>
<div
class={classNames(displayClass, "giscus")}
data-repo={cfg.comments?.repo}
data-repo-id={cfg.comments?.repoId}
data-category={cfg.comments?.category}
data-category-id={cfg.comments?.categoryId}
data-mapping={cfg.comments?.mapping ?? "url"}
data-strict={boolToStringBool(cfg.comments?.strict ?? true)}
data-reactions-enabled={boolToStringBool(cfg.comments?.reactionsEnabled ?? true)}
data-input-position={cfg.comments?.inputPosition ?? "bottom"}
></div>
</div>
)
case "commento":
return (
<div id="comment" data-provider={cfg.comments.provider}>
<div
id="commento"
data-host={cfg.comments?.host ?? "cdn.commento.io"}
data-css-override={cfg.comments?.cssOverride ?? ""}
data-no-fonts={cfg.comments?.noFonts ?? true}
data-hide-deleted={cfg.comments?.hideDeleted ?? false}
></div>
</div>
)
case "disqus":
return (
<div id="comment" data-provider={cfg.comments.provider}>
<div id="disqus_thread" data-short-name={cfg.comments?.shortName}></div>
</div>
)
default:
return <></>
}
}
Comments.afterDOMLoaded = script
return Comments
}) satisfies QuartzComponentConstructor<Options>
}) satisfies QuartzComponentConstructor

View File

@ -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<HTMLElement, "dataset"> & {
}
}
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<HTMLElement, "dataset"> & {
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<HTMLElement, "dataset"> & {
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()
}
})