Aaron Pham
2024-08-05 1224c7d32fd2e6d4029fd34aaf6aeb3ef234d239
refactor(comments): move script to files (#1308)

* refactor(comments): move script to files

for LSP, treesitter, and the whole galore.

Signed-off-by: Aaron Pham <contact@aarnphm.xyz>

* fix(type): support removeEventListener with CustomEventMap

Signed-off-by: Aaron Pham <contact@aarnphm.xyz>

* fix: parse bool to string first

Signed-off-by: Aaron Pham <contact@aarnphm.xyz>

* chore: address comments and test on branch

Signed-off-by: Aaron Pham <contact@aarnphm.xyz>

* revert: remove comments section from main quartz pages

Signed-off-by: Aaron Pham <contact@aarnphm.xyz>

---------

Signed-off-by: Aaron Pham <contact@aarnphm.xyz>
1 files added
2 files modified
130 ■■■■■ changed files
globals.d.ts 4 ●●●● patch | view | raw | blame | history
quartz/components/Comments.tsx 59 ●●●●● patch | view | raw | blame | history
quartz/components/scripts/comments.inline.ts 67 ●●●●● patch | view | raw | blame | history
globals.d.ts
@@ -4,6 +4,10 @@
      type: K,
      listener: (this: Document, ev: CustomEventMap[K]) => void,
    ): void
    removeEventListener<K extends keyof CustomEventMap>(
      type: K,
      listener: (this: Document, ev: CustomEventMap[K]) => void,
    ): void
    dispatchEvent<K extends keyof CustomEventMap>(ev: CustomEventMap[K] | UIEvent): void
  }
  interface Window {
quartz/components/Comments.tsx
@@ -1,4 +1,7 @@
import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types"
import { classNames } from "../util/lang"
// @ts-ignore
import script from "./scripts/comments.inline"
type Options = {
  provider: "giscus"
@@ -19,49 +22,23 @@
}
export default ((opts: Options) => {
  const Comments: QuartzComponent = (_props: QuartzComponentProps) => <div class="giscus"></div>
  Comments.afterDOMLoaded = `
    const changeTheme = (e) => {
      const theme = e.detail.theme
      const iframe = document.querySelector('iframe.giscus-frame')
      if (!iframe) {
        return
  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>
    )
      }
      iframe.contentWindow.postMessage({
        giscus: {
          setConfig: {
            theme: theme
          }
        }
      }, 'https://giscus.app')
    }
    document.addEventListener("nav", () => {
      const giscusContainer = document.querySelector(".giscus")
      const giscusScript = document.createElement("script")
      giscusScript.src = "https://giscus.app/client.js"
      giscusScript.async = true
      giscusScript.crossOrigin = "anonymous"
      giscusScript.setAttribute("data-loading", "lazy")
      giscusScript.setAttribute("data-emit-metadata", "0")
      giscusScript.setAttribute("data-repo", "${opts.options.repo}")
      giscusScript.setAttribute("data-repo-id", "${opts.options.repoId}")
      giscusScript.setAttribute("data-category", "${opts.options.category}")
      giscusScript.setAttribute("data-category-id", "${opts.options.categoryId}")
      giscusScript.setAttribute("data-mapping", "${opts.options.mapping ?? "url"}")
      giscusScript.setAttribute("data-strict", "${boolToStringBool(opts.options.strict ?? true)}")
      giscusScript.setAttribute("data-reactions-enabled", "${boolToStringBool(opts.options.reactionsEnabled ?? true)}")
      giscusScript.setAttribute("data-input-position", "${opts.options.inputPosition ?? "bottom"}")
      const theme = document.documentElement.getAttribute("saved-theme")
      giscusScript.setAttribute("data-theme", theme)
      giscusContainer.appendChild(giscusScript)
      document.addEventListener("themechange", changeTheme)
      window.addCleanup(() => document.removeEventListener("themechange", changeTheme))
    })`
  Comments.afterDOMLoaded = script
  return Comments
}) satisfies QuartzComponentConstructor<Options>
quartz/components/scripts/comments.inline.ts
New file
@@ -0,0 +1,67 @@
const changeTheme = (e: CustomEventMap["themechange"]) => {
  const theme = e.detail.theme
  const iframe = document.querySelector("iframe.giscus-frame") as HTMLIFrameElement
  if (!iframe) {
    return
  }
  if (!iframe.contentWindow) {
    return
  }
  iframe.contentWindow.postMessage(
    {
      giscus: {
        setConfig: {
          theme: theme,
        },
      },
    },
    "https://giscus.app",
  )
}
type GiscusElement = Omit<HTMLElement, "dataset"> & {
  dataset: DOMStringMap & {
    repo: `${string}/${string}`
    repoId: string
    category: string
    categoryId: string
    mapping: "url" | "title" | "og:title" | "specific" | "number" | "pathname"
    strict: string
    reactionsEnabled: string
    inputPosition: "top" | "bottom"
  }
}
document.addEventListener("nav", () => {
  const giscusContainer = document.querySelector(".giscus") as GiscusElement
  if (!giscusContainer) {
    return
  }
  const giscusScript = document.createElement("script")
  giscusScript.src = "https://giscus.app/client.js"
  giscusScript.async = true
  giscusScript.crossOrigin = "anonymous"
  giscusScript.setAttribute("data-loading", "lazy")
  giscusScript.setAttribute("data-emit-metadata", "0")
  giscusScript.setAttribute("data-repo", giscusContainer.dataset.repo)
  giscusScript.setAttribute("data-repo-id", giscusContainer.dataset.repoId)
  giscusScript.setAttribute("data-category", giscusContainer.dataset.category)
  giscusScript.setAttribute("data-category-id", giscusContainer.dataset.categoryId)
  giscusScript.setAttribute("data-mapping", giscusContainer.dataset.mapping)
  giscusScript.setAttribute("data-strict", giscusContainer.dataset.strict)
  giscusScript.setAttribute("data-reactions-enabled", giscusContainer.dataset.reactionsEnabled)
  giscusScript.setAttribute("data-input-position", giscusContainer.dataset.inputPosition)
  const theme = document.documentElement.getAttribute("saved-theme")
  if (theme) {
    giscusScript.setAttribute("data-theme", theme)
  }
  giscusContainer.appendChild(giscusScript)
  document.addEventListener("themechange", changeTheme)
  window.addCleanup(() => document.removeEventListener("themechange", changeTheme))
})