This is an automated email from the ASF dual-hosted git repository.

hsluoyz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/casbin-website.git

commit acd68b88c8a95efd52383652574912912d9875be
Author: Yang Luo <[email protected]>
AuthorDate: Mon Oct 12 00:27:02 2026 +0800

    feat: load giscus comments only after opt-in
---
 src/components/GiscusComments/index.js | 72 ++++++++++++++++++++++++++++++++++
 src/theme/BlogPostPaginator/index.js   | 20 +---------
 src/theme/DocPaginator/index.js        | 20 +---------
 static/.htaccess                       |  3 ++
 4 files changed, 79 insertions(+), 36 deletions(-)

diff --git a/src/components/GiscusComments/index.js 
b/src/components/GiscusComments/index.js
new file mode 100644
index 000000000..8d1353fa3
--- /dev/null
+++ b/src/components/GiscusComments/index.js
@@ -0,0 +1,72 @@
+import React, {useEffect, useState} from "react";
+import Giscus from "@giscus/react";
+import Translate from "@docusaurus/Translate";
+import {useColorMode} from "@docusaurus/theme-common";
+
+// ASF privacy policy: third-party content may only load after the visitor 
opts in.
+const consentKey = "casbin-giscus-consent";
+
+export default function GiscusComments() {
+  const {colorMode} = useColorMode();
+  const [consented, setConsented] = useState(false);
+
+  useEffect(() => {
+    try {
+      setConsented(localStorage.getItem(consentKey) === "1");
+    } catch (e) {
+      // localStorage may be unavailable
+    }
+  }, []);
+
+  const setConsent = (value) => {
+    try {
+      if (value) {
+        localStorage.setItem(consentKey, "1");
+      } else {
+        localStorage.removeItem(consentKey);
+      }
+    } catch (e) {
+      // localStorage may be unavailable
+    }
+    setConsented(value);
+  };
+
+  return (
+    <div id="comments" className="margin-top--lg">
+      {consented ? (
+        <>
+          <Giscus
+            repo="apache/casbin"
+            repoId="MDEwOlJlcG9zaXRvcnk4NzYxNzUwOA=="
+            category="Docs comments"
+            categoryId="DIC_kwDOBTjv5M4CRIiA"
+            mapping="pathname"
+            strict="0"
+            reactionsEnabled="1"
+            emitMetadata="0"
+            inputPosition="top"
+            theme={colorMode}
+            lang="en"
+            loading="lazy"
+          />
+          <button className="button button--link padding-horiz--none" 
type="button" onClick={() => setConsent(false)}>
+            <Translate>Hide comments</Translate>
+          </button>
+        </>
+      ) : (
+        <div className="padding--md" style={{border: "1px solid 
var(--ifm-color-emphasis-300)", borderRadius: "var(--ifm-global-radius)"}}>
+          <p>
+            <Translate
+              values={{giscus: <a href="https://giscus.app/"; target="_blank" 
rel="noopener noreferrer">giscus</a>}}
+            >
+              {"Comments are powered by {giscus} and GitHub Discussions. They 
load from giscus.app and GitHub only after you click the button below."}
+            </Translate>
+          </p>
+          <button className="button button--primary" type="button" onClick={() 
=> setConsent(true)}>
+            <Translate>Show comments</Translate>
+          </button>
+        </div>
+      )}
+    </div>
+  );
+}
diff --git a/src/theme/BlogPostPaginator/index.js 
b/src/theme/BlogPostPaginator/index.js
index b6d11e658..68f836790 100644
--- a/src/theme/BlogPostPaginator/index.js
+++ b/src/theme/BlogPostPaginator/index.js
@@ -1,28 +1,12 @@
 import React from "react";
 import BlogPostPaginator from "@theme-original/BlogPostPaginator";
-import Giscus from "@giscus/react";
-import {useColorMode} from "@docusaurus/theme-common";
+import GiscusComments from "@site/src/components/GiscusComments";
 
 export default function BlogPostPaginatorWrapper(props) {
   return (
     <>
       <BlogPostPaginator {...props} />
-      <br />
-      <Giscus
-        id="comments"
-        repo="casbin/casbin"
-        repoId="MDEwOlJlcG9zaXRvcnk4NzYxNzUwOA=="
-        category="Docs comments"
-        categoryId="DIC_kwDOBTjv5M4CRIiA"
-        mapping="pathname"
-        strict="0"
-        reactionsEnabled="1"
-        emitMetadata="0"
-        inputPosition="top"
-        theme={useColorMode().colorMode}
-        lang="en"
-        loading="lazy"
-      />
+      <GiscusComments />
     </>
   );
 }
diff --git a/src/theme/DocPaginator/index.js b/src/theme/DocPaginator/index.js
index 31c26cf50..06a11bde5 100644
--- a/src/theme/DocPaginator/index.js
+++ b/src/theme/DocPaginator/index.js
@@ -1,28 +1,12 @@
 import React from "react";
 import DocPaginator from "@theme-original/DocPaginator";
-import Giscus from "@giscus/react";
-import {useColorMode} from "@docusaurus/theme-common";
+import GiscusComments from "@site/src/components/GiscusComments";
 
 export default function DocPaginatorWrapper(props) {
   return (
     <>
       <DocPaginator {...props} />
-      <br />
-      <Giscus
-        id="comments"
-        repo="casbin/casbin"
-        repoId="MDEwOlJlcG9zaXRvcnk4NzYxNzUwOA=="
-        category="Docs comments"
-        categoryId="DIC_kwDOBTjv5M4CRIiA"
-        mapping="pathname"
-        strict="0"
-        reactionsEnabled="1"
-        emitMetadata="0"
-        inputPosition="top"
-        theme={useColorMode().colorMode}
-        lang="en"
-        loading="lazy"
-      />
+      <GiscusComments />
     </>
   );
 }
diff --git a/static/.htaccess b/static/.htaccess
new file mode 100644
index 000000000..f657ec2ea
--- /dev/null
+++ b/static/.htaccess
@@ -0,0 +1,3 @@
+# CSP permissions for casbin.apache.org - approved by ASF Data Privacy on 
2026-10-11 ([email protected], "CSP exception request for casbin.apache.org: 
giscus").
+# giscus.app: GitHub Discussions comments under docs and blog posts, loaded 
only after the visitor clicks "Show comments".
+SetEnv CSP_PROJECT_DOMAINS "https://giscus.app/";


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to