From 545d65e7dae8fb7c688f29cfc72a96f366bc9c1a Mon Sep 17 00:00:00 2001 From: 2kwonhee Date: Thu, 18 Sep 2025 00:54:58 +0900 Subject: [PATCH] feat(Giscus): persist discussions via commentId - require frontmatter commentId when giscus uses mapping "specific" so each page keeps its discussion - clear prior giscus embeds on SPA navigation before reinjecting and skip when term is missing - keep layout.ts wrapping Comments with a commentId guard --- quartz/components/Comments.tsx | 12 +++++++++++- quartz/components/scripts/comments.inline.ts | 13 +++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/quartz/components/Comments.tsx b/quartz/components/Comments.tsx index a7315214f..58ddc926f 100644 --- a/quartz/components/Comments.tsx +++ b/quartz/components/Comments.tsx @@ -35,6 +35,15 @@ export default ((opts: Options) => { return <> } + const mapping = opts.options.mapping ?? "url" + const commentId = fileData.frontmatter?.commentId as string | undefined + + if (mapping === "specific" && !commentId) { + const identifier = fileData.filePath ?? fileData.slug ?? "unknown" + console.warn(`[Quartz] Missing commentId for page ${identifier}, skipping giscus mounting.`) + return <> + } + return (
{ data-repo-id={opts.options.repoId} data-category={opts.options.category} data-category-id={opts.options.categoryId} - data-mapping={opts.options.mapping ?? "url"} + data-mapping={mapping} + data-term={mapping === "specific" ? commentId : undefined} data-strict={boolToStringBool(opts.options.strict ?? true)} data-reactions-enabled={boolToStringBool(opts.options.reactionsEnabled ?? true)} data-input-position={opts.options.inputPosition ?? "bottom"} diff --git a/quartz/components/scripts/comments.inline.ts b/quartz/components/scripts/comments.inline.ts index 2b876bf6b..a1de1655f 100644 --- a/quartz/components/scripts/comments.inline.ts +++ b/quartz/components/scripts/comments.inline.ts @@ -56,6 +56,7 @@ type GiscusElement = Omit & { reactionsEnabled: string inputPosition: "top" | "bottom" lang: string + term?: string } } @@ -65,6 +66,15 @@ document.addEventListener("nav", () => { return } + giscusContainer + .querySelectorAll("iframe.giscus-frame, script[src*='giscus.app']") + .forEach((node) => node.remove()) + + if (giscusContainer.dataset.mapping === "specific" && !giscusContainer.dataset.term) { + console.warn("[Giscus] mapping='specific' but data-term is missing; skipping widget injection.") + return + } + const giscusScript = document.createElement("script") giscusScript.src = "https://giscus.app/client.js" giscusScript.async = true @@ -76,6 +86,9 @@ document.addEventListener("nav", () => { giscusScript.setAttribute("data-category", giscusContainer.dataset.category) giscusScript.setAttribute("data-category-id", giscusContainer.dataset.categoryId) giscusScript.setAttribute("data-mapping", giscusContainer.dataset.mapping) + if (giscusContainer.dataset.term) { + giscusScript.setAttribute("data-term", giscusContainer.dataset.term) + } giscusScript.setAttribute("data-strict", giscusContainer.dataset.strict) giscusScript.setAttribute("data-reactions-enabled", giscusContainer.dataset.reactionsEnabled) giscusScript.setAttribute("data-input-position", giscusContainer.dataset.inputPosition)