diff --git a/.env.example b/.env.example
index 97ce54d..ede613c 100644
--- a/.env.example
+++ b/.env.example
@@ -6,6 +6,7 @@ NEXT_PUBLIC_UTTERANCES_REPO=
NEXT_PUBLIC_DISQUS_SHORTNAME=
NEXT_PUBLIC_CUSDIS_APPID=
NEXT_PUBLIC_CUSDIS_HOST=
+NEXT_PUBLIC_COMMENTO_URL=
MAILCHIMP_API_KEY=
diff --git a/.vscode/settings.json b/.vscode/settings.json
index bb6031b..83cf3ff 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -2,6 +2,7 @@
"cSpell.words": [
"alpn",
"blackhole",
+ "Commento",
"Cusdis",
"Disqus",
"dokodemo",
diff --git a/components/comments/Commento.tsx b/components/comments/Commento.tsx
new file mode 100644
index 0000000..51ebbd9
--- /dev/null
+++ b/components/comments/Commento.tsx
@@ -0,0 +1,30 @@
+import React, { useMemo, useState } from 'react'
+
+import siteMetadata from '@/data/siteMetadata'
+import { PostFrontMatter } from 'types/PostFrontMatter'
+import { useTheme } from 'next-themes'
+import ReactCommento from './commento/ReactCommento'
+
+interface Props {
+ frontMatter: PostFrontMatter
+}
+
+const Commento = ({ frontMatter }: Props) => {
+ const { resolvedTheme } = useTheme()
+ const commentsTheme = useMemo(() => {
+ switch (resolvedTheme) {
+ case 'light':
+ case 'dark':
+ return resolvedTheme
+ default:
+ return 'auto'
+ }
+ }, [resolvedTheme])
+ return (
+
+
+
+ )
+}
+
+export default Commento
diff --git a/components/comments/commento/ReactCommento.tsx b/components/comments/commento/ReactCommento.tsx
new file mode 100644
index 0000000..227bcf0
--- /dev/null
+++ b/components/comments/commento/ReactCommento.tsx
@@ -0,0 +1,83 @@
+import { createRef } from 'preact'
+import React, { useLayoutEffect, useMemo, useRef } from 'react'
+
+interface DataAttributes {
+ [key: string]: string | boolean | undefined
+}
+
+const insertScript = (
+ src: string,
+ id: string,
+ dataAttributes: DataAttributes,
+ onload = () => {}
+) => {
+ const script = window.document.createElement('script')
+ script.async = true
+ script.src = src
+ script.id = id
+ console.log(document.getElementById(id))
+ if (document.getElementById(id)) {
+ return
+ }
+ script.addEventListener('load', onload, { capture: true, once: true })
+
+ Object.entries(dataAttributes).forEach(([key, value]) => {
+ if (value === undefined) {
+ return
+ }
+ script.setAttribute(`data-${key}`, value.toString())
+ })
+
+ document.body.appendChild(script)
+
+ return () => {
+ script.remove()
+ }
+}
+
+const ReactCommento = ({
+ url,
+ cssOverride,
+ autoInit,
+ noFonts,
+ hideDeleted,
+ pageId,
+}: {
+ url: string
+ cssOverride?: string
+ autoInit?: boolean
+ noFonts?: boolean
+ hideDeleted?: boolean
+ pageId?: string
+}) => {
+ const containerId = useMemo(() => `commento-${Math.random().toString().slice(2, 8)}`, [])
+ const container = createRef()
+ const initializing = useRef(false)
+
+ useLayoutEffect(() => {
+ if (!window) {
+ return
+ }
+
+ window['commento'] = container.current
+
+ const removeScript = insertScript(
+ url,
+ `${containerId}-script`,
+ {
+ 'css-override': cssOverride,
+ 'auto-init': autoInit,
+ 'no-fonts': noFonts,
+ 'hide-deleted': hideDeleted,
+ 'page-id': pageId,
+ 'id-root': containerId,
+ },
+ () => {
+ removeScript()
+ }
+ )
+ }, [autoInit, cssOverride, hideDeleted, noFonts, pageId, url, containerId, container])
+
+ return
+}
+export default ReactCommento
diff --git a/components/comments/index.tsx b/components/comments/index.tsx
index 9e30231..8d59051 100644
--- a/components/comments/index.tsx
+++ b/components/comments/index.tsx
@@ -32,6 +32,12 @@ const CusdisComponent = dynamic(
},
{ ssr: false }
)
+const CommentoComponent = dynamic(
+ () => {
+ return import('@/components/comments/Commento')
+ },
+ { ssr: false }
+)
const Comments = ({ frontMatter }: Props) => {
let term
@@ -63,6 +69,9 @@ const Comments = ({ frontMatter }: Props) => {
{siteMetadata.comment && siteMetadata.comment.provider === 'cusdis' && (
)}
+ {siteMetadata.comment && siteMetadata.comment.provider === 'commento' && (
+
+ )}
)
}
diff --git a/data/siteMetadata.js b/data/siteMetadata.js
index 6a7eb5e..9edd783 100644
--- a/data/siteMetadata.js
+++ b/data/siteMetadata.js
@@ -40,7 +40,7 @@ const siteMetadata = {
// content security policy in the `next.config.js` file.
// Select a provider and use the environment variables associated to it
// https://vercel.com/docs/environment-variables
- provider: 'cusdis', // supported providers: giscus, utterances, disqus
+ provider: 'commento', // supported providers: giscus, utterances, disqus
giscusConfig: {
// Visit the link below, and follow the steps in the 'configuration' section
// https://giscus.app/
@@ -82,6 +82,9 @@ const siteMetadata = {
appId: process.env.NEXT_PUBLIC_CUSDIS_APPID,
host: process.env.NEXT_PUBLIC_CUSDIS_HOST,
},
+ commentoConfig: {
+ url: process.env.NEXT_PUBLIC_COMMENTO_URL,
+ },
},
}
diff --git a/next.config.js b/next.config.js
index 225c42a..cb1522a 100644
--- a/next.config.js
+++ b/next.config.js
@@ -10,7 +10,7 @@ const ContentSecurityPolicy = `
img-src * blob: data:;
media-src 'none';
connect-src *;
- font-src 'self';
+ font-src 'self' comment.ivanli.cc;
frame-src giscus.app comment.ivanli.cc
`
diff --git a/package-lock.json b/package-lock.json
index b56132e..d987b05 100644
Binary files a/package-lock.json and b/package-lock.json differ
diff --git a/package.json b/package.json
index dabc5c0..53e82a3 100644
--- a/package.json
+++ b/package.json
@@ -27,6 +27,7 @@
"postcss": "^8.4.17",
"preact": "^10.11.1",
"react": "18.2.0",
+ "react-commento": "^1.0.0",
"react-cusdis": "^2.1.3",
"react-dom": "18.2.0",
"reading-time": "1.5.0",