Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
模仿disqus的 SEE ALSO ON <blog> 功能,为静态博客添加“显示本站其他文章评论”的功能。 https://geektutu.com/post/blog-experience-7.html
/**
* Generate Comments JSON Data
*/
const https = require('https');
const fs = require('fs');
const github = {
client_id: '<your-client-id>',
client_secret: '<your-client-secret>',
repo: '<your-github-repo>',
owner: '<your-github-name>'
}
const PREFIX = `/repos/${github.owner}/${github.repo}/`
const AUTH = `&client_id=${github.client_id}&client_secret=${github.client_secret}`
const PAGING = '&sort=created&direction=desc&per_page=100'
class Comments {
constructor() {
this.comments = []
this.issueMap = []
this.obj = {}
}
deltaDate(old) {
let hours = (Date.now() - new Date(old)) / 1000 / 3600
let years = Math.floor(hours / 24 / 365)
if (years) {
return `${years}年前`
}
let months = Math.floor(hours / 24 / 30)
if (months) {
return `${months}月前`
}
let days = Math.floor(hours / 24)
if (days) {
return `${days}天前`
}
hours = Math.floor(hours)
return `${hours}小时前`
}
async parse() {
this.comments = await this.get(`issues/comments?${PAGING}`)
console.log(`comments.length: ${this.comments.length}`)
await this.writeComments()
}
async fetchIssue(issueUrl) {
let issueApi = issueUrl.slice(issueUrl.indexOf(PREFIX) + PREFIX.length)
if (!this.issueMap[issueApi]) {
let issue = await this.get(issueApi + '?')
issue.post = issue.labels.find(label => label.name.startsWith("/")).name
issue.title = issue.title.split('|')[0].trim()
this.issueMap[issueApi] = issue
}
return this.issueMap[issueApi]
}
async writeComments() {
let simpleComments = {}
for (const comment of this.comments) {
let issue = await this.fetchIssue(comment.issue_url)
if (issue.user.login === comment.user.login) {
continue
}
if (simpleComments[issue.post]) {
continue
}
simpleComments[issue.post] = {
title: issue.title,
url: issue.post,
count: issue.comments,
user: comment.user.login,
icon: comment.user.avatar_url,
date: this.deltaDate(comment.created_at),
body: comment.body.replace(/</g, " ").replace(/>/g, " ").replace(/\s+/g, " ").trim()
}
}
let obj = Object.keys(simpleComments).map(key => simpleComments[key])
fs.writeFileSync("comments.json", JSON.stringify(obj), { encoding: 'utf-8' });
console.log(`write ${obj.length} success!`)
}
get(api) {
let options = {
hostname: 'api.github.com',
path: `${PREFIX}${api}${AUTH}`,
headers: { 'User-Agent': 'Node Https Client' }
};
console.log(`GET ${options.path}`)
return new Promise((resolve, reject) => {
const req = https.get(options, (res) => {
let data = '';
res.on('data', (chunk) => data += chunk);
res.on('end', () => resolve(JSON.parse(data)));
});
req.on('error', (e) => reject(e));
req.end();
});
}
}
(async () => {
client = new Comments()
await client.parse()
})();
<div id="gitalk-related"></div>
<style>
#gitalk-related.dis-wrapper {
font-size: 14px;
margin: 70px 0;
overflow: hidden;
padding-bottom: 10px;
}
#gitalk-related * {
margin: 0;
padding: 0;
box-sizing: border-box;
text-decoration: none;
transform: none;
-webkit-transform: none;
}
#gitalk-related .dis-divide {
border-top: 2px solid #e7e9ee;
width: 100%;
float: left;
padding: 5px 10px;
margin-top: 20px;
text-align: center;
}
#gitalk-related .dis-item {
width: 50%;
float: left;
padding: 0px 10px;
margin-top: 20px;
height: 108px;
overflow: hidden;
}
#gitalk-related .dis-item-title {
font-size: 16px;
color: #6190e8;
font-weight: 500;
max-height: 3em;
line-height: 1.5;
overflow: hidden;
}
#gitalk-related .dis-item-des {
font-size: 0.85em;
}
#gitalk-related .dis-divide a,
#gitalk-related .dis-item-des,
#gitalk-related .dis-item-user {
color: rgba(30, 55, 70, .4);
}
#gitalk-related .dis-item-img {
width: 30px;
height: 30px;
margin-top: 3px;
}
#gitalk-related .dis-item-content {
display: flex;
}
#gitalk-related .dis-item-content>p {
padding-left: 10px;
color: #333;
line-height: 1.4em;
max-height: 4.2em;
overflow: hidden;
}
</style>
<script>
window.addEventListener('load', function () {
function render(comments) {
var template = '<a href="${comment.url}?utm_source=gitalk" class="dis-item-url"><h3 class="dis-item-title">${comment.title}</h3>' +
'<p class="dis-item-des">${comment.count} 评论 ● ${comment.date}</p>' +
'<div class="dis-item-content"><img class="dis-item-img" src="${comment.icon}" alt="icon"><p><b><span class="dis-item-user">${comment.user}</span></b>&nbsp;——&nbsp;${comment.body}</p></div>' +
'</a>'
var wrapper = get('#gitalk-related');
comments = shuffle(comments);
comments.slice(0, 4).forEach(function (c) {
var div = document.createElement('div');
div.classList.add('dis-item');
div.innerHTML = template.replace("${comment.url}", c.url)
.replace("${comment.title}", c.title)
.replace("${comment.count}", c.count)
.replace("${comment.date}", c.date)
.replace("${comment.icon}", c.icon)
.replace("${comment.user}", c.user)
.replace("${comment.body}", c.body)
wrapper.appendChild(div)
})
var p = document.createElement('p')
p.innerHTML = '<a href="https://geektutu.com/post/blog-experience-7.html">Gitalk Plus</a>';
p.classList.add('dis-divide');
wrapper.appendChild(p);
wrapper.classList.add('dis-wrapper')
}
function shuffle(a) {
for (var i = a.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
function get(str) { return document.querySelector(str) }
fetch('/comments.json').then(function (r) { return r.json() }).then(render).catch(function (e) { })
})
</script>
@geektutu

This comment has been minimized.

Copy link
Owner Author

geektutu commented Aug 23, 2019

效果

Gitalk-plus

@geektutu

This comment has been minimized.

Copy link
Owner Author

geektutu commented Aug 23, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.