什么是 GitHub Issues
经常逛 GitHub 的童鞋,都应该知道这个功能,有人理解 GitHub 的 issue 功能,就如同 TODO list。你可以把所有想要在下一步完成的工作,如 feature 添加、bug 修复等,都写成一个个的 issue ,放在上面。既可以作为提醒,也可以统一管理。另外,每一次 commit 都可以选择性的与某个 issue 关联。比如在 message 中添加 #n,就可以与第 n 个 issue 进行关联。具体可以看一下知乎里面别人对 《github issue是做什么的?
》的解答。而本博客的评论数据存储 issues 仓库地址为
https://github.com/jangdelong/blog_comments/issues,仓库里面并没有放置托管代码。总之,像我现在要用 github Issues 来制作评论系统的,其实就是把数据存储到 github issues,简单的说可以把 github issues 理解为一个免费的数据库。
三、评论系统实现
预备工作
-
创建 OAuth applications。评论需要涉及 GitHub 授权登录,所以在这里你先要有一个 GitHub application。GitHub 授权登录遵循
OAuth 2.0 标准。OAuth applications 创建如下图所示,填写上面相应的内容。
[图片上传中...(image-d1f3af-1512351059452-2)]
Application name:你的站点名称;
Homepage URL:你的站点主页链接;
Application description:站点描述;
Authorization callback URL:GitHub 授权成功后返回地址
创建成功之后会生成一个 Client ID 和一个 Client Secret。
- GitHub REST API v3
GitHub 提供了很多方便第三方开发的 API,当然,github issues 的增删改查 API 也在其中,有了这些 API,你才能各种施展奇技淫巧,比如我们现在要写的评论系统。另外,有人怀疑我们应不应该“滥用”这些 API,但是,个人觉得,既然,GitHub 提供了这些 API,就是说明要开放给大家这些权限,应该就不怕你“滥用”。那么,要满足我们现在的需求需要哪些 API 呢,下面我列举一下,以我的账号为例,jangdelong 为 Github 名,blog_comments 为仓库名。
GET: https://api.github.com/repos/jangdelong/blog_comments/issues
获取所有issues信息
GET: https://api.github.com/repos/jangdelong/blog_comments/issues/11
获取某个issue下的信息 (11 为 issue 编号 )
GET: https://api.github.com/repos/jangdelong/blog_comments/issues/11/
comments 获取某个issue下的评论
GET: https://api.github.com/repos/jangdelong/blog_comments/issues/comments/111/reactions
获取评论 ID 为 111 下的所有 reactions(reactions 包含顶[+1]、踩[-1]、喜欢[heart]等字段)
POST: https://api.github.com/repos/jangdelong/blog_comments/issues
创建一个 issue
POST: https://api.github.com/repos/jangdelong/blog_comments/issues/11/comments
在编号为 11 的 issue 下创建一条评论
POST: https://api.github.com/repos/jangdelong/blog_comments/issues/comments/111/reactions
在 ID 为 111 的评论下创建一条 reactions(如 heart)
POST:https://developer.github.com/v3/markdown/
markdown 语法解析接口
整体设计
流程图:
|--> 显示已登录
|--> 已登录 --> |--> 加载评论列表 --> 分页加载
| |--> 其他
| |--> 评论操作 --> 成功/失败 |
开始 --> GitHub 授权登录 ? --> | |--> 结束
| |--> 显示未登录 |
|--> 未登录 --> |--> 加载评论列表 --> 分页加载
|--> 其他
|--> 评论操作 --> 提示未登录状态
效果图:
[图片上传失败...(image-76545-1512351059451)]
因此,我们可以将评论系统分为列表(list)、评论框(box)、顶部登录状态栏(signbar)等部分。View 部分的代码组织为:
// 为了减少全局变量,整个网站就暴露一个全局变量 JELON
var JELON = JELON || {};
;(function (JL) {
...
JL.Renders = {
// 列表模块
list: {
tpl: ...,
...
},
// 评论框模块
box: {
tpl: ...,
...
},
// 顶部登录状态栏
signBar: {
tpl: ...,
...
},
... // 其他模块视图
};
...
})(JELON);
视图部分的代码组织好之后,根据 GitHub 提供的各种 API,我们将其封装到 Requests 里面去,组织如下:
// 为了减少全局变量,整个网站就暴露一个全局变量 JELON
var JELON = JELON || {};
;(function (JL) {
...
JL.Requests = {
// 根据 label 获取 issue 编号
getIssueNumberByLabel: function () { ... },
// 创建 issue
createIssue: function () { ... },
// 根据 issue 编号获取评论列表
getCommentListByIssueNumber: function () { ... },
// 根据评论 ID 获取 reactions (即点赞数据)
getReactionsByCommentId: function () { ... },
// markdown 解析
markdown: function () { ... },
// 通过 code 获取 access_token
getAccessToken: function () { ... },
// 利用 access_token 去获取 GitHub 用户信息
getUserInfo: function () { ... },
// 创建评论
createComment: function () { ... },
// 创建 reactions (点赞)
createReaction: function () { ... }
};
...
})(JELON);
接下来是封装事件操作,我们将其封装到 Actions 里面去,代码组织如下:
// 为了减少全局变量,整个网站就暴露一个全局变量 JELON
var JELON = JELON || {};
;(function (JL) {
...
JL.Actions = {
// 初始加载,如列表、登录状态等
init: function () { ... },
// 登出操作
signOut: function () { ... },
// 列表翻页跳转
pageJump: function () { ... },
// 编辑预览
editPreviewSwitch: function () { ... },
// 提交评论操作
postComment: function () { ... },
// 点赞操作
like: function () { ... }
};
...
})(JELON);
程序入口:
// 为了减少全局变量,整个网站就暴露一个全局变量 JELON
var JELON = JELON || {};
;(function (JL) {
...
JL.Comment = function (options) {
JL.options = options || {};
$('comments').innerHTML = [
this.Renders.signBar.tpl,
this.Renders.box.tpl,
this.Renders.tips,
this.Renders.list.tpl
].join('');
JL.Actions.init();
};
...
})(JELON);
登录流程
GitHub 授权登录是不可或缺的功能,用只有登录之后才能进行评论。前面有提到,GitHub 授权登录是遵循一个 OAuth 2.0 标准。以下是 OAuth 2.0 的一个运作流程,可以让我们更好的理解它。
[图片上传失败...(image-83fe16-1512351059450)]
那么,GitHub 授权登录是怎么样按照这个标准来运作的呢,接下来简单介绍一下,如果要更加详细深入了解的话,你也可以访问
-
用户发起重定向请求授权服务器换取 code
`GET http://github.com/login/oauth/authorize`
-
拿到 code 之后,利用 client_id、client_secret 和 code 去换取 token_access。(client_id 和 client_secret 前面的预备工作里有提到)
`POST https://github.com/login/oauth/access_token`
-
获取到 token_access 之后,我们就可以用 token_access 去获取已登录的用户的信息了
`GET https://api.github.com/user`
通过以上3个步骤,GitHub 授权登录就算是完成了。
四、评论系统如何使用
-
引入评论系统相关的 css、js 。引入相关样式和脚本之后,在你的页面加入以下代码:
<link rel="stylesheet" href="样式路径"> <script src="脚本路径"></script> <div id="comment" class="comment"> </div> <script> JELON.Comment({ container: 'comments', // 评论框容器id或对象,留空是默认为 comments label: '<%- post.slug %>' || '<%- post.path %>', // 文章标签 owner: '<%- theme.comment.owner %>', // GitHub application 创建者 repo: '<%- theme.comment.repo %>', // issue 所在仓库名 clientId: '<%- theme.comment.client_id %>', // GitHub application client_id clientSecret: '<%- theme.comment.client_secret %>' // GitHub application client_secret }); </script>
-
由于这个评论系统是要集成到个人的主题上去的,所以要跟 hexo-theme-xups 搭配使用,hexo-theme-xups 主题链接为
https://github.com/jangdelong/hexo-theme-xups,目前最新的主题(带有GitHub 登录评论功能),后面会更新上去,往后当然也会陆续进行更新和优化,欢迎多多 star。
五、遇到的问题
遇到的问题主要有三个,一个是创建 label 权限问题,一个是跨域问题,另外一个 GitHub 授权登录兼容性问题。
-
创建 label 权限问题(目前未解决)。label 是一个连接文章和 issue 关系的纽带,因为我们要用 label 去查询 issue number,后面的流程才能走下去。如今遇到的问题是,对于新文章来说,只能是我自己本人账号(GitHub Application)创建者才能创建带有 label 的 issue。参考了 GitHub 的接口(
POST /repos/:owner/:repo/issues
)文档,上面说> Labels to associate with this issue. NOTE: Only users with push access can set labels for new issues. Labels are silently dropped otherwise.
-
跨域问题(暂时解决了)。主要是通过 code 去换取 token_access 的
POST https://github.com/login/oauth/access_token
这个接口跨域,暂时解决方案是
使用https://cors-anywhere.herokuapp.com/https://github.com/login/oauth/access_token
进行转发。参见:https://github.com/Rob--W/cor...
。
GitHub 授权登录兼容性问题(暂时不解决)。经过简单的测试,发现 PC 端兼容性问题主要是一些老版本的浏览器,其中包括一些老版本的谷歌浏览器(版本号55.x.xxxx.xx);而移动端的主要是 UC 浏览器无法实现 GitHub 授权登录。