mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-10 10:06:15 -08:00
feat(website): add giscus blog comments
This commit is contained in:
1 parent
3096115e64
commit
738397c9ed
5 files changed
+101
No files matched your search
@@ -0,0 +1,28 @@
|
||||
# IPTVnator Website
|
||||
|
||||
The website is an Astro static site deployed to GitHub Pages at `https://4gray.github.io/iptvnator/`.
|
||||
|
||||
## Blog Comments
|
||||
|
||||
Blog posts render Giscus comments from `apps/website/src/components/GiscusComments.astro`.
|
||||
Giscus stores comments in GitHub Discussions for `4gray/iptvnator` and maps each page to a discussion by `pathname`, including the GitHub Pages base path such as `/iptvnator/blog/why-external-players-help/`.
|
||||
|
||||
The embed is wired to the dedicated `Blog comments` discussion category:
|
||||
|
||||
- Repository id: `MDEwOlJlcG9zaXRvcnkyMTMxOTQ3Mzg=`
|
||||
- Category id: `DIC_kwDODLUX8s4C9eBJ`
|
||||
- Mapping: `pathname`
|
||||
- Theme: `transparent_dark`
|
||||
|
||||
If the category is recreated, query the new category id:
|
||||
|
||||
```bash
|
||||
gh api graphql \
|
||||
-f owner=4gray \
|
||||
-f name=iptvnator \
|
||||
-f query='query($owner:String!, $name:String!) { repository(owner:$owner, name:$name) { discussionCategories(first:25) { nodes { id name slug isAnswerable } } } }'
|
||||
```
|
||||
|
||||
Then update `data-category-id` in `GiscusComments.astro`.
|
||||
|
||||
Moderation happens in GitHub Discussions. Maintainers can hide, delete, lock, or move discussions and comments from the repository Discussions UI.
|
||||
@@ -14,6 +14,13 @@
|
||||
"cwd": "apps/website"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"executor": "nx:run-commands",
|
||||
"dependsOn": ["build"],
|
||||
"options": {
|
||||
"command": "node --test tools/testing/website-giscus-comments.test.mjs"
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<section class="mt-16 border-t border-dashed border-surface-700/60 pt-10" aria-labelledby="blog-comments-heading">
|
||||
<div class="mb-6">
|
||||
<h2 id="blog-comments-heading" class="font-display text-2xl font-semibold tracking-tight text-surface-100">
|
||||
Comments
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="giscus min-h-40"></div>
|
||||
<script
|
||||
is:inline
|
||||
src="https://giscus.app/client.js"
|
||||
data-repo="4gray/iptvnator"
|
||||
data-repo-id="MDEwOlJlcG9zaXRvcnkyMTMxOTQ3Mzg="
|
||||
data-category="Blog comments"
|
||||
data-category-id="DIC_kwDODLUX8s4C9eBJ"
|
||||
data-mapping="pathname"
|
||||
data-strict="1"
|
||||
data-reactions-enabled="1"
|
||||
data-emit-metadata="0"
|
||||
data-input-position="bottom"
|
||||
data-theme="transparent_dark"
|
||||
data-lang="en"
|
||||
crossorigin="anonymous"
|
||||
loading="lazy"
|
||||
async
|
||||
></script>
|
||||
</section>
|
||||
@@ -1,5 +1,6 @@
|
||||
---
|
||||
import BaseLayout from './BaseLayout.astro';
|
||||
import GiscusComments from '../components/GiscusComments.astro';
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
@@ -150,6 +151,8 @@ const blogPostSchema = {
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<GiscusComments />
|
||||
</div>
|
||||
</article>
|
||||
</BaseLayout>
|
||||
@@ -0,0 +1,36 @@
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
|
||||
const postHtmlPath = new URL('../../dist/apps/website/blog/why-external-players-help/index.html', import.meta.url);
|
||||
|
||||
const expectedGiscusAttributes = {
|
||||
src: 'https://giscus.app/client.js',
|
||||
'data-repo': '4gray/iptvnator',
|
||||
'data-repo-id': 'MDEwOlJlcG9zaXRvcnkyMTMxOTQ3Mzg=',
|
||||
'data-category': 'Blog comments',
|
||||
'data-category-id': 'DIC_kwDODLUX8s4C9eBJ',
|
||||
'data-mapping': 'pathname',
|
||||
'data-strict': '1',
|
||||
'data-reactions-enabled': '1',
|
||||
'data-emit-metadata': '0',
|
||||
'data-input-position': 'bottom',
|
||||
'data-theme': 'transparent_dark',
|
||||
'data-lang': 'en',
|
||||
};
|
||||
|
||||
test('published blog posts include the Giscus comments embed configuration', async () => {
|
||||
const html = await readFile(postHtmlPath, 'utf8');
|
||||
const scriptMatch = html.match(/<script\b[^>]*giscus\.app\/client\.js[^>]*>/);
|
||||
|
||||
assert.ok(scriptMatch, 'Expected the blog post HTML to include the Giscus client script.');
|
||||
|
||||
const scriptTag = scriptMatch[0];
|
||||
for (const [name, value] of Object.entries(expectedGiscusAttributes)) {
|
||||
assert.match(scriptTag, new RegExp(`${name}="${value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}"`));
|
||||
}
|
||||
|
||||
assert.match(scriptTag, /\bloading="lazy"/);
|
||||
assert.match(scriptTag, /\bcrossorigin="anonymous"/);
|
||||
assert.match(scriptTag, /\basync/);
|
||||
});
|
||||
Reference in new issue
Block a user