Skip to content

Commit 59bedba

Browse files
committed
feat(view): Add support for Giscus
1 parent 742346a commit 59bedba

2 files changed

Lines changed: 272 additions & 0 deletions

File tree

src/schema/comment/giscus.json

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$id": "/comment/giscus.json",
4+
"description": "Giscus comment plugin configurations",
5+
"type": "object",
6+
"properties": {
7+
"type": {
8+
"type": "string",
9+
"const": "giscus"
10+
},
11+
"repo": {
12+
"type": "string",
13+
"description": "GitHub repository to which Giscus connects"
14+
},
15+
"repoId": {
16+
"type": "string",
17+
"description": "GitHub repository id to which Giscus connects"
18+
},
19+
"category": {
20+
"type": "string",
21+
"description": "The discussion category where new discussions will be created",
22+
"default": "Announcements",
23+
"nullable": true
24+
},
25+
"categoryId": {
26+
"type": "string",
27+
"description": "Id code of the category of Github discussions which Giscus will access to"
28+
},
29+
"mapping": {
30+
"type": "string",
31+
"description": "The mapping between the embedding page and the embedded discussion",
32+
"enum": [
33+
"pathname",
34+
"url",
35+
"title",
36+
"og:title",
37+
"specific",
38+
"number"
39+
],
40+
"default": "pathname",
41+
"nullable": true
42+
},
43+
"strict": {
44+
"type": "boolean",
45+
"description": "Avoid mismatches due to GitHub's fuzzy searching method when there are multiple discussions with similar titles",
46+
"default": false,
47+
"nullable": true
48+
},
49+
"reactionsEnabled": {
50+
"type": "boolean",
51+
"description": "Whether enable reactions",
52+
"default": false,
53+
"nullable": true
54+
},
55+
"emitMetadata": {
56+
"type": "boolean",
57+
"description": "Whether will discussion emit metadata",
58+
"default": false,
59+
"nullable": true
60+
},
61+
"inputPosition": {
62+
"type": "string",
63+
"description": "Where the input block will display",
64+
"enum": [
65+
"top",
66+
"bottom"
67+
],
68+
"default": "top",
69+
"nullable": true
70+
},
71+
"theme": {
72+
"type": "string",
73+
"description": "Giscus look and feel",
74+
"enum": [
75+
"light",
76+
"light_high_contrast",
77+
"light_protanopia",
78+
"light_tritanopia",
79+
"dark",
80+
"dark_high_contrast",
81+
"dark_protanopia",
82+
"dark_tritanopia",
83+
"dark_dimmed",
84+
"preferred_color_scheme",
85+
"transparent_dark",
86+
"noborder_light",
87+
"noborder_dark",
88+
"noborder_gray",
89+
"cobalt",
90+
"purple_dark",
91+
"custom"
92+
],
93+
"default": "noborder_light",
94+
"nullable": true
95+
},
96+
"customThemeCss": {
97+
"type": "string",
98+
"description": "The url of custom Giscus theme css, only affect when theme is set to custom",
99+
"nullable": true
100+
},
101+
"lang": {
102+
"type": "string",
103+
"description": "Language of Giscus",
104+
"default": "en",
105+
"nullable": true
106+
},
107+
"lazy": {
108+
"type": "boolean",
109+
"description": "Loading of the comments will be deferred until the user scrolls near the comments container",
110+
"default": false,
111+
"nullable": true
112+
}
113+
},
114+
"required": ["repo", "repoId", "categoryId"]
115+
}
116+

src/view/comment/giscus.jsx

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
/**
2+
* Giscus comment JSX component.
3+
* @module view/comment/giscus
4+
*/
5+
const { Component } = require('inferno');
6+
const { cacheComponent } = require('../../util/cache');
7+
8+
/**
9+
* Giscus comment JSX component.
10+
*
11+
* @see https://giscus.app/
12+
* @example
13+
* <Giscus
14+
* repo="usr/repo"
15+
* repoId="X_xxxxxxxxxx"
16+
* category="******"
17+
* categoryId="XXX_xxxxxxxxxxxxxxxx"
18+
* mapping="******"
19+
* strict={0}
20+
* reactionsEnabled={0}
21+
* emitMetadata={0}
22+
* inputPosition="******"
23+
* theme="******"
24+
* lang="******"
25+
* lazy="******" />
26+
*/
27+
class Giscus extends Component {
28+
render() {
29+
const { repo, repoId, category, categoryId, mapping, term, strict, reactionsEnabled, emitMetadata, inputPosition, theme, customThemeCss, lang, lazy } = this.props;
30+
if (!repo || !repoId || !categoryId) {
31+
return (
32+
<div class="notification is-danger">
33+
You forgot to set the <code>repo</code>, <code>repoId</code>, or{' '}
34+
<code>categoryId</code> for Giscus. Please set it in <code>_config.yml</code>.
35+
</div>
36+
);
37+
}
38+
if ((mapping == "specific" || mapping == "number") && !term) {
39+
return (
40+
<div class="notification is-danger">
41+
You set <code>mapping</code> to <code>specific</code> or <code>number</code>, but did not set <code>term</code> for Giscus. Please set <code>term</code> in <code>_config.yml</code>.
42+
</div>
43+
);
44+
}
45+
const config = { repo };
46+
if (category) {
47+
config['data-category'] = category;
48+
} else {
49+
config['data-category'] = 'Announcements';
50+
}
51+
if(mapping) {
52+
config['data-mapping'] = mapping;
53+
} else {
54+
config['data-mapping'] = 'pathname';
55+
}
56+
if(strict) {
57+
config['data-strict'] = 1;
58+
} else {
59+
config['data-strict'] = 0;
60+
}
61+
if(reactionsEnabled) {
62+
config['data-reactions-enabled'] = 1;
63+
} else {
64+
config['data-reactions-enabled'] = 0;
65+
}
66+
if(emitMetadata) {
67+
config['data-emit-metadata'] = 1;
68+
} else {
69+
config['data-emit-metadata'] = 0;
70+
}
71+
if(inputPosition) {
72+
config['data-input-position'] = inputPosition;
73+
} else {
74+
config['data-input-position'] = 'top'
75+
}
76+
if (theme) {
77+
if (theme == "custom") {
78+
if (customThemeCss) {
79+
config['data-theme'] = customThemeCss;
80+
} else {
81+
return (
82+
<div class="notification is-danger">
83+
You set <code>theme</code> to <code>custom</code>, but did not apply a <code>customThemeCss</code> for Giscus. Please set it in <code>_config.yml</code>.
84+
</div>
85+
);
86+
}
87+
} else {
88+
config['data-theme'] = theme;
89+
}
90+
} else {
91+
config['data-theme'] = 'noborder_light';
92+
}
93+
if (lang) {
94+
config['data-lang'] = lang;
95+
} else {
96+
config['data-lang'] = 'en';
97+
}
98+
if (lazy) {
99+
config['data-loading'] = 'lazy';
100+
}
101+
return (
102+
<script
103+
src="https://giscus.app/client.js"
104+
{...config}
105+
crossorigin="anonymous"
106+
async={true}></script>
107+
);
108+
}
109+
}
110+
111+
/**
112+
* Cacheable Giscus comment JSX component.
113+
* <p>
114+
* This class is supposed to be used in combination with the <code>locals</code> hexo filter
115+
* ({@link module:hexo/filter/locals}).
116+
*
117+
* @see module:util/cache.cacheComponent
118+
* @example
119+
* <Giscus.Cacheable
120+
* comment={{
121+
* repo="******"
122+
* repo-id="******"
123+
* category="******"
124+
* category-id="******"
125+
* mapping="="******""
126+
* strict="0"
127+
* reactions-enabled="0"
128+
* emit-metadata="0"
129+
* input-position="="******""
130+
* theme="******"
131+
* lang="en"
132+
* loading="lazy"
133+
* }} />
134+
*/
135+
Giscus.Cacheable = cacheComponent(Giscus, 'comment.giscus', (props) => {
136+
const { repo, repoId, category, categoryId, mapping, term, strict, reactionsEnabled, emitMetadata, inputPosition, theme, customThemeCss, lang, lazy } = props.comment;
137+
138+
return {
139+
repo,
140+
repoId,
141+
category,
142+
categoryId,
143+
mapping,
144+
term,
145+
strict,
146+
reactionsEnabled,
147+
emitMetadata,
148+
inputPosition,
149+
theme,
150+
customThemeCss,
151+
lang,
152+
lazy
153+
};
154+
});
155+
156+
module.exports = Giscus;

0 commit comments

Comments
 (0)