From 3ce75c09efac8020d8bffbf570f91d233b206722 Mon Sep 17 00:00:00 2001 From: PJ568 Date: Sun, 2 Jun 2024 11:18:02 +0800 Subject: [PATCH] feat(view): Add support for Giscus --- src/schema/comment/giscus.json | 115 ++++++++++++++++++++++++ src/view/comment/giscus.jsx | 156 +++++++++++++++++++++++++++++++++ 2 files changed, 271 insertions(+) create mode 100644 src/schema/comment/giscus.json create mode 100644 src/view/comment/giscus.jsx diff --git a/src/schema/comment/giscus.json b/src/schema/comment/giscus.json new file mode 100644 index 00000000..362e5762 --- /dev/null +++ b/src/schema/comment/giscus.json @@ -0,0 +1,115 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/comment/giscus.json", + "description": "Giscus comment plugin configurations", + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "giscus" + }, + "repo": { + "type": "string", + "description": "GitHub repository to which Giscus connects" + }, + "repoId": { + "type": "string", + "description": "GitHub repository id to which Giscus connects" + }, + "category": { + "type": "string", + "description": "The discussion category where new discussions will be created", + "default": "Announcements", + "nullable": true + }, + "categoryId": { + "type": "string", + "description": "Id code of the category of Github discussions which Giscus will access to" + }, + "mapping": { + "type": "string", + "description": "The mapping between the embedding page and the embedded discussion", + "enum": [ + "pathname", + "url", + "title", + "og:title", + "specific", + "number" + ], + "default": "pathname", + "nullable": true + }, + "strict": { + "type": "boolean", + "description": "Avoid mismatches due to GitHub's fuzzy searching method when there are multiple discussions with similar titles", + "default": false, + "nullable": true + }, + "reactionsEnabled": { + "type": "boolean", + "description": "Whether enable reactions", + "default": false, + "nullable": true + }, + "emitMetadata": { + "type": "boolean", + "description": "Whether will discussion emit metadata", + "default": false, + "nullable": true + }, + "inputPosition": { + "type": "string", + "description": "Where the input block will display", + "enum": [ + "top", + "bottom" + ], + "default": "top", + "nullable": true + }, + "theme": { + "type": "string", + "description": "Giscus look and feel", + "enum": [ + "light", + "light_high_contrast", + "light_protanopia", + "light_tritanopia", + "dark", + "dark_high_contrast", + "dark_protanopia", + "dark_tritanopia", + "dark_dimmed", + "preferred_color_scheme", + "transparent_dark", + "noborder_light", + "noborder_dark", + "noborder_gray", + "cobalt", + "purple_dark", + "custom" + ], + "default": "noborder_light", + "nullable": true + }, + "customThemeCss": { + "type": "string", + "description": "The url of custom Giscus theme css, only affect when theme is set to custom", + "nullable": true + }, + "lang": { + "type": "string", + "description": "Language of Giscus", + "default": "en", + "nullable": true + }, + "lazy": { + "type": "boolean", + "description": "Loading of the comments will be deferred until the user scrolls near the comments container", + "default": false, + "nullable": true + } + }, + "required": ["repo", "repoId", "categoryId"] +} diff --git a/src/view/comment/giscus.jsx b/src/view/comment/giscus.jsx new file mode 100644 index 00000000..0d5e2081 --- /dev/null +++ b/src/view/comment/giscus.jsx @@ -0,0 +1,156 @@ +/** + * Giscus comment JSX component. + * @module view/comment/giscus + */ +const { Component } = require('inferno'); +const { cacheComponent } = require('../../util/cache'); + +/** + * Giscus comment JSX component. + * + * @see https://giscus.app/ + * @example + * + */ +class Giscus extends Component { + render() { + const { repo, repoId, category, categoryId, mapping, term, strict, reactionsEnabled, emitMetadata, inputPosition, theme, customThemeCss, lang, lazy } = this.props; + if (!repo || !repoId || !categoryId) { + return ( +
+ You forgot to set the repo, repoId, or{' '} + categoryId for Giscus. Please set it in _config.yml. +
+ ); + } + if ((mapping == "specific" || mapping == "number") && !term) { + return ( +
+ You set mapping to specific or number, but did not set term for Giscus. Please set term in _config.yml. +
+ ); + } + const config = { repo }; + if (category) { + config['data-category'] = category; + } else { + config['data-category'] = 'Announcements'; + } + if(mapping) { + config['data-mapping'] = mapping; + } else { + config['data-mapping'] = 'pathname'; + } + if(strict) { + config['data-strict'] = 1; + } else { + config['data-strict'] = 0; + } + if(reactionsEnabled) { + config['data-reactions-enabled'] = 1; + } else { + config['data-reactions-enabled'] = 0; + } + if(emitMetadata) { + config['data-emit-metadata'] = 1; + } else { + config['data-emit-metadata'] = 0; + } + if(inputPosition) { + config['data-input-position'] = inputPosition; + } else { + config['data-input-position'] = 'top' + } + if (theme) { + if (theme == "custom") { + if (customThemeCss) { + config['data-theme'] = customThemeCss; + } else { + return ( +
+ You set theme to custom, but did not apply a customThemeCss for Giscus. Please set it in _config.yml. +
+ ); + } + } else { + config['data-theme'] = theme; + } + } else { + config['data-theme'] = 'noborder_light'; + } + if (lang) { + config['data-lang'] = lang; + } else { + config['data-lang'] = 'en'; + } + if (lazy) { + config['data-loading'] = 'lazy'; + } + return ( + + ); + } +} + +/** + * Cacheable Giscus comment JSX component. + *

+ * This class is supposed to be used in combination with the locals hexo filter + * ({@link module:hexo/filter/locals}). + * + * @see module:util/cache.cacheComponent + * @example + * + */ +Giscus.Cacheable = cacheComponent(Giscus, 'comment.giscus', (props) => { + const { repo, repoId, category, categoryId, mapping, term, strict, reactionsEnabled, emitMetadata, inputPosition, theme, customThemeCss, lang, lazy } = props.comment; + + return { + repo, + repoId, + category, + categoryId, + mapping, + term, + strict, + reactionsEnabled, + emitMetadata, + inputPosition, + theme, + customThemeCss, + lang, + lazy + }; +}); + +module.exports = Giscus;