giscus / giscus Goto Github PK
View Code? Open in Web Editor NEWA comment system powered by GitHub Discussions. :octocat: :speech_balloon: :gem:
Home Page: https://giscus.app
License: MIT License
A comment system powered by GitHub Discussions. :octocat: :speech_balloon: :gem:
Home Page: https://giscus.app
License: MIT License
Following #86.
GitHub's GraphQL API has a limit of 5000 query points/hour.
giscus authenticates as the app (bot) for the following operations:
repositoryId
and categoryIds
)For all other operations (posting comments, reactions, etc.) giscus authenticates as the user, so the 5000 points/hour limit is imposed on the user. In this case, I think the 5000 points/hour limit is generous. Going beyond that limit is highly unlikely, but possible (e.g. if the user also uses GitHub's API by other means).
The bot hitting the 5000 points/hour is more likely, especially if we have a lot of users (or maybe a few but with high traffic). At the very least, I think we should handle this case. A possible solution is to show an error message indicating the rate limit and a hint to sign in. Though at this point I think it wouldn't be much effort to also handle the case where the user already hits the rate limit.
For reference, utterances only sends a warning to the console when it hits the rate limit. It's also much easier to detect it on the REST API since you can just check the header. With the GraphQL API, you need to explicitly include rateLimit
in the query.
The feature is gone after GitHub removed it from the markdown renderer API. I guess we'll need to insert the element ourselves.
Right now, we need users to create the discussion before embedding it on a webpage.
Utterances allows automatic issue creation when the queried term doesn't exist. Discussion creation is a bit more complicated than issue creation.
To create an issue, we only need:
On the other hand, to create a discussion, we need:
repositoryId
(not owner/name
)categoryId
(not category name)We need to query for both of those before we can create a new discussion. We can retrieve them both in a single query, but still...
An alternative would be to fetch both of them in the onboarding process (on the homepage). Then, the generated installation script would be something like:
<script src="https://giscussions.vercel.app/client.js"
repo="{repositoryId}"
term="pathname"
category="{categoryId}
theme="dark_dimmed"
crossorigin="anonymous"
async>
</script>
Thus, the repositoryId
and categoryId
is baked into the widget. However, we cannot use repositoryId
when searching for discussions; we need to use the owner/repo
format. We can choose to include both repositoryId
and owner/repo
in the installation script, but that's a bit redundant ๐ฌ
Unrelated: If we used
discussionNumber
to fetch the discussion, we can userepositoryId
because we'd access the discussion directly. However, that means the discussion is already created.
Anyway, then we would somehow pass that information to CommentBox
, and try to create a new discussion if it fails to post a comment.
Utterances supports origin allowlisting using utterances.json
. This is helpful to prevent unknown sites from using giscus with any user's repository discussions.
I've already done this in #18 but for some reason GitHub throws FORBIDDEN
errors. Maybe we need to ping some hubbers and see what's the issue?
Is it possible to switch to other services?
the console printed many warnings like this:
HTTP Referrer header: Length is over โ4096โ bytes limit - stripping referrer header down to origin: โhttps://giscus.app/โ
browser: firefox
To help new contributors, it would be nice if we have a contributing guide. It should at least cover:
First off, thanks for this project, I love it!
I don't like a full refresh on each page change so I added barba.js in order to load the pages over AJAX instead. This obviously broke giscus, I hacked around a solution that involves changing the iframe src
on page change via JS but I was wondering if there's a better way to solve this.
I don't know if that's possible but will you consider adding a JS client API so that we can programmatically load the discussion?
You can see my tiny js code here and you can see it in action at https://games-on-whales.github.io/gow/
This would be useful for standard Jekyll (Markdown) users (like me) who use Jekyll for blogging and want Giscus to follow Jekyll's blog post layout.
I'm no security expert. There certainly are things that can be changed to improve the security aspect of this project. They are things like:
<iframe>
tag and how the widget page behaves with itlocalStorage
The list is non-exhaustive, so this is just more like a placeholder issue.
This feature would show reactions to the main post above comments and allow a user to add reactions. This could be optional or enabled by default. Something that could look like this:
image taken from utterance/utterances#340
This is the missing piece of the puzzle! We need to create an installation script that automatically determines the correct query params for https://giscussions.vercel.app/widget, handle iFrameResizer stuff, etc.
How come did I not come up with this sooner???
It's shorter, it's also a play on Disqus, and, well... I don't know.
Should we do this??????????????
When creating a discussion category, there's an option to make it an "Open ended discussion" vs "Question / Answer". Discussions created in the latter category would have StackOverflow-style "selected answer" and other features enabled.
I don't know if this makes sense if we're embedding the discussion's comments on a webpage, though. I mean, we don't even include the discussion content itself, so...
When starting this project, I chose Tailwind for a few reasons:
github-syntax-light
) to match GitHub's design.However, when I started adding support for themes and other complex Markdown features (e.g. permalink code snippets), it started to become trickier to apply the correct style. It's not Tailwind's fault, it's just that the generated HTML is optimized for use with @primer
's utilities, e.g. @primer/components, @primer/css, @primer/primitives.
Downsides to switching the frameworks/libraries used are:
@primer
stuff@primer/css
and it increased the build output by tens of kilobytes. Considering that the current size is only ~30KB and we managed to get it running quite beautifully, I really want to keep it small.I'm no expert on accessibility, but this is one thing we definitely should do. I don't think I have added any aria
attributes (sorry!) to the elements because I'd rather have a separate commit that deals with this. Help would be much appreciated!
Hi, I just saw this project and it looks great!
GitHub Discussions supports different sort orders for replies: newest/oldest/top first. This is configurable via buttons (on the right):
It would be great if these buttons would be also available on the embedded giscus form. Also, it would be cool if we could configure the default sort order for the comment form, e.g. via the javascript init function.
Right now it looks like giscus only supports oldest first ordering. Would it be possible to add custom orderings or is this not supported by GitHub's dicussion API?
We useSWRInfinite
to implement cursor-based pagination. However, we need nested pagination in order to show more than 100 replies (the limit) to a comment. I haven't found an "easy" way to implement it with SWR. The key is to handle SWR key
(heh) elegantly so that it can keep track of the pages correctly.
Thus, we might need to evaluate other data-fetching libraries such as react-query.
Or... we could fetch the remaining replies separately as a state for the Comment
. Hmm...
Still... what kind of comment would get more than 100 replies anyway? ๐คฃ
Add the ability to have multiple search criteria like data-mapping="title|og:title"
. The page actually created automatically would be according to 1st criterial in the list.
In case one changes the criteria later, the conversations will not get unlinked from the page.
This is hard... I want to do it myself but I don't know how it should look like ๐ฌ
See https://giscus.vercel.app and first comment, seems clipboard button got broken
I'd love to be able to hide the text "XX reactions". Could we consider exposing that? I can't seem to do it via CSS due to iframe cross-domain.
Perhaps a way to take inline CSS? Should I develop a new theme instead?
There's still a lot of places in the code where we can do error handling better. This is a placeholder issue for those improvements.
Discovered this when using Giscus with Jekyll as part of mmistakes/minimal-mistakes#3022
The PR takes the repository name from a setting, which in my case was SeanKilleen/seankilleen.github.io
.
Giscus failed with a 400 error when retrieving comments, so thought there was no discussion topic, and therefore kept creating new discussion topics.
I think the issue is that the GitHub API or similar might be failing with a repo name that contains uppercase characters. I'll see if I can submit a PR to make that behavior case insensitive.
Hello,
This project is fantastic!
I have one gripe, and I'm happy to say it's a small one. I'm running giscus as a component in a Gatsby (React SSR) project. It seems to work perfectly, but there is a warning that comes up when a new post is loaded with giscus at the bottom:
[iFrameSizer][Host page: iFrameResizer0] [iFrame requested init] IFrame(iFrameResizer0) not found
This warning multiplies when new posts are loaded (e.g. the 1st post I click will have none, the 2nd will have one, the 3rd will have two and the 4th will have four).
I believe this means the following line in client.js
is being run before the child exists, but I am unsure:
loadScript('https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.1/iframeResizer.min.js', function () {
return iFrameResize({ checkOrigin: [giscusOrigin], resizeFrom: 'child' });
});
Maybe it's my implementation? Here is the TSX component I've written for handling the script:
import React from "react"
type DataProps = {
className?: string
}
const Comment: React.FC<DataProps> = ({ className }) => {
// Used for https://giscus.app/
// https://creativcoder.dev/how-to-add-github-utterances-blog
const commentBox = React.createRef<HTMLInputElement>()
React.useEffect(() => {
const scriptEl = document.createElement("script")
scriptEl.async = true
scriptEl.src = "https://giscus.app/client.js"
scriptEl.setAttribute("data-repo", "<STUFF>")
scriptEl.setAttribute("data-repo-id", "<STUFF>")
scriptEl.setAttribute("data-category", "Announcements")
scriptEl.setAttribute("data-category-id", "<STUFF>")
scriptEl.setAttribute("data-mapping", "title")
scriptEl.setAttribute("data-reactions-enabled", "1")
scriptEl.setAttribute("data-theme", "preferred_color_scheme")
scriptEl.setAttribute("crossorigin", "anonymous")
if (commentBox && commentBox.current) {
while (commentBox.current.firstChild)
if (commentBox.current.lastChild)
commentBox.current.removeChild(commentBox.current.lastChild)
commentBox.current.appendChild(scriptEl)
}
})
return (<div ref={commentBox} className={`comments ${className}`} />)
}
export default Comment
Because these warnings don't affect functionally, this should be a low-priority issue.
Any help with this would be appreciated, thank you!
Right now, all GraphQL API calls for mutations are passed through /api/graphql
before they are sent to GitHub. This is necessary because of community/community#3622. Once that is resolved, we can safely drop the passthru API.
Somewhat related, but for later:
Note that querying for discussions data will still need to be proxied through /api/discussions
because GitHub's GraphQL API requires authentication for all requests. We're using a trick by authenticating as the app in order to get a token that can be used to fetch discussions data without signing in.
However, this means that GraphQL query string should be composed on the server. If we let the client compose the query and just use the passthru API (and supplying the token if the request doesn't have one), users can abuse this to run queries as the application.
We can remove /api/discussions
once GitHub allows unauthenticated requests for their GraphQL API. (This is unlikely to happen in the near future, though.)
We use the webcrypto library to encrypt and decrypt user tokens. The encryption stuff is taken from this gist, while the flow is taken from utterances-oauth.
Node has built-in webcrypto as of version 15. However, it's not yet available on Vercel's serverless functions (which runs on AWS Lambda, I think?). They only use LTS releases of Node (currently Node 14). The latest LTS release, Node 16, was just released a few weeks ago. Looking at the time it took AWS to support Node 12 and 14, it's unlikely that Node 16 will land until at least a few months from now.
When Node 16 lands on Vercel, we can revert 3a52b18 to fix this issue.
However, I do believe that it's completely possible to achieve the same functionality using Node's crypto
library (available on older Node versions), but I don't really know how. I'm no expert at cryptography, so I don't have enough confidence to pull this off.
Hello!
I just discovered this commenting system and it seems to be nice. I tried till no utterances, but I am a little reluctant to try it on my blog as there is no localization option. Not so much work on this issue Will it be hard to add it to giscus?
Thank you and keep up the good work!
The README says the below:
Can be self-hosted! ๐คณ
Could you please provide instructions on how to do so? I myself am thinking of hosting it on cloudflare where my website already lives along with the same domain.
Also, can we self host the bot too? That would be helpful.
GFM, in comments, has a lot of features, some of which we may not have covered. This issue serves as a placeholder for any edge cases/features that we need to cover in order to match GitHub's set of features.
Themes are always nice! This is a placeholder issue for theme proposals.
I'll probably need to write a guide on how to do it, but you basically just need to create a new file in styles/themes
following the other ones that already exist, then register it in here.
New themes should be able to provide a good contrast (at least in respect to the containing page's background). This tool might help: https://wave.webaim.org
Right now, the KebabHorizontalIcon
is there just as a placeholder. We'll need to implement this, eventually.
GitHub:
I think we only need the "Copy link" and "Quote reply" menu items. For "Hide" and "Delete", I don't know if it's worth the effort. For "Edit", it would be awesome, but I imagine it wouldn't be so easy to implement. The thing is, if users really need to "Edit", "Hide", and "Delete" (or even "Report content"), they can always jump on GitHub ๐
If a post is edited the ability to see the edit history when clicking the "edited" link
Right now, on page load, preferred_color_scheme respects the system color scheme.
But, what if you're on a device that changes the system color scheme automatically? In those cases, giscus does not update and requires a page reload to continue respecting the system color scheme.
You could potentially solve this by using addEventListener
to apply state changes like so:
const [mQuery, setMQuery] = React.useState<string>("light")
React.useEffect(() => {
let mediaQuery = window.matchMedia("(prefers-color-scheme: dark)")
// Listening for changes.
mediaQuery.addEventListener("change", e => {
setMQuery(e.matches ? "dark" : "light")
})
// On initial load.
setMQuery(mediaQuery.matches ? "dark" : "light")
}
FYI, that code snippet is untested.
This issue serves as a tracker for other issues that need to be resolved as we work towards 1.0 (do we even have versioning?). I'm currently listing these down so that I don't forget when I need to create separate issues later.
discussionNumber
, <title>
, og:title
, etc.) (#34)KebabHorizontalIcon
menu (add copy link and quote reply options) (#36)@peculiar/webcrypto
with built-in Node crypto
module (#29)@primer
and other GitHub stuff (CSS libraries, components, etc.) (#41)I'm just copying the variables from @primer/primitives and GitHub's website. There are a lot of unused variables in the current theme files. It would be nice if we could remove them at build time. I tried using PurgeCSS but I couldn't find the right configuration that plays well with the project's setup.
If the only option is to trim down the theme files, I'm also okay with it, as long as it's easy enough to re-add any variables that we need in the future.
I think we can leverage getAppAccessToken()
to post comments as the bot, allowing visitors to leave comments without signing in. Maybe we should also add a signature like
Anonymous wrote:
at the beginning of the posted comment, to indicate that it was made by an anonymous user (not the bot itself).
The thing is, we shouldn't pass the token directly to the client, because that would let users misuse the token to act as the bot. We need to create a new API route for addDiscussionComment
and addDiscussionReply
, and that's not something I'm really keen on.
Also, I'm not sure how/where the sign in buttons should be placed...
Edit:
Also mentioned below: anonymity and comments tend to not go well together. If implemented, this should be an opt-in feature.
Currently, we search for discussions using the generic query string described in "Searching discussions."
On my personal website, I'm currently using the embedding page's pathname
as the identifier for the discussion title.
Utterances supports:
pathname
URL
<title>
og:title
meta
tagFor 1-5, I think we can still use the current logic. Most (if not all) of the work would only need to be done in the client installation script. This is because we should be able to just pass whatever the resulting string is to the search query string.
However, for 6, we'll need to access the discussion directly instead of using search. This is essentially the way we did it before 8d69b3c. Thus, we need to dynamically change the GraphQL query string based on the method that's used.
To make it easier for users who rely on preferred-color-scheme
to configure their website's theme, we should add an option that supports it.
I think mapping the dark theme to dark
and the light theme to light
should be enough.
Right now, we only show This comment has been deleted
or This comment has been hidden
with no toggle to show the actual comment.
This is how the toggle should look like (see laymonage/discussions-playground#4 (reply in thread)):
This shouldn't be too hard to do, I just haven't found the time.
First, superb project - thanks!
I have an issue with the width of the giscus iFrame, where it only takes what looks to be 25% of the available width. Is there a way to control that?
I'm not an HTML guru, but it looks to be something around iFrameResizer?
Example: https://vaparo.github.io/about/
The comment widget has default width and border style.
Hello there,
This is an awesome project, thank you for making this.
I was wondering if there is any way to get the number of comments/replies/reactions or the discussion URL from the parent page.
I have two use cases for this:
I tried to query the dom, but the browser doesn't allow cross-origin iframes to be inspected from the parent window.
Are there any existing ways to achieve this?
If not, seeing that the iframe already sends messages to the parent window, would it possible to send some basic metadata about the discussion to the parent?
I took a quick look at the code and couldn't make much sense of it on the first go. But if you are unable to find time to make any changes, would you accept a PR? I could use any pointers if you have, on where to start.
Thanks & Regards
Sarath
Utterances has a nice landing page and onboarding steps that we could follow. We'll need something like this to showcase the project and to make installations a breeze.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.