feat: 增加 aside 最新評論部件

style: 部分css調整和html優化
improvements: 刪除pwa中的theme-color配置,默認生成meta theme-color  close #340
improvements: 優化最後更新時間顯示(1小時內顯示 剛剛,1小時到24小時 顯示 xx小時前,1天到365天 顯示 xx天前,365天后直接顯示日期)
pull/353/head
Jerry 4 years ago
parent ee6f62f4bc
commit fe97d2e63f

@ -644,6 +644,25 @@ runtimeshow:
enable: false
publish_date:
# Aside widget - Newest Comments
newest_comments:
enable: false
limit: 6
avatar: true
leancloud:
enable: false
appId: # leancloud application app id
appKey: # leancloud application app key
serverURL: # This configuration is suitable for domestic custom domain name users, overseas version will be automatically detected (no need to manually fill in)
default_avatar: mp # mp/identicon/monsterid/wavatar/retro/robohash/blank
github_issues:
enable: false
repo:
disqus:
enable: false
forum:
api_key:
# Bottom right button (右下角按鈕)
# --------------------------------------
@ -763,7 +782,6 @@ lazyload:
# pwa:
# enable: false
# manifest: /image/pwa/manifest.json
# theme_color: "#fff"
# apple_touch_icon: /image/pwa/apple-touch-icon.png
# favicon_32_32: /image/pwa/32.png
# favicon_16_16: /image/pwa/16.png

@ -70,12 +70,20 @@ aside:
unit: days
last_push_date:
name: Last Push
zero_day: Today
suffix: days ago
site_wordcount: Total Count
site_uv_name: UV
site_pv_name: PV
more_button: More
card_newest_comments:
heading: Newest Comments
loading_text: loading...
zero_day: Today
day: days ago
date_suffix:
one_hour: Just
hours: hours ago
day: days ago
donate: Donate
share: Share

@ -70,12 +70,20 @@ aside:
unit: days
last_push_date:
name: Last Push
zero_day: Today
suffix: days ago
site_wordcount: Total Count
site_uv_name: UV
site_pv_name: PV
more_button: More
card_newest_comments:
heading: Newest Comments
loading_text: loading...
zero_day: Today
day: days ago
date_suffix:
one_hour: Just
hours: hours ago
day: days ago
donate: Donate
share: Share

@ -72,12 +72,20 @@ aside:
unit:
last_push_date:
name: 最后更新时间
zero_day: 今天
suffix: 天前
site_wordcount: 本站总字数
site_uv_name: 本站访客数
site_pv_name: 本站总访问量
more_button: 查看更多
card_newest_comments:
heading: 最新评论
loading_text: 正在加载中...
zero_day: 今天
day: 天前
date_suffix:
one_hour: 刚刚
hours: 小時前
day: 天前
donate: 打赏
share: 分享

@ -72,12 +72,20 @@ aside:
unit:
last_push_date:
name: 最後更新時間
zero_day: 今天
suffix: 天前
site_wordcount: 本站總字數
site_uv_name: 本站訪客數
site_pv_name: 本站總訪問量
more_button: 檢視更多
card_newest_comments:
heading: 最新評論
loading_text: 正在加載中...
zero_day: 今天
day: 天前
date_suffix:
one_hour: 剛剛
hours: 小時前
day: 天前
donate: 打賞
share: 分享

@ -44,10 +44,16 @@ div
if theme.busuanzi.site_uv || theme.busuanzi.site_pv || theme.busuanzi.page_pv
script(async src=url_for(theme.CDN.busuanzi))
!=fragment_cache('injectBottom', function(){return injectHtml(theme.inject.bottom)})
!=partial('includes/third-party/prismjs', {}, {cache:theme.fragment_cache})
if theme.aside.enable && theme.newest_comments.enable
if theme.pjax.enable
!=partial('includes/third-party/newest-comments/index', {}, {cache:theme.fragment_cache})
else if (!is_post() && page.aside !== false)
!=partial('includes/third-party/newest-comments/index', {}, {cache:theme.fragment_cache})
!=fragment_cache('injectBottom', function(){return injectHtml(theme.inject.bottom)})
!=partial('includes/third-party/effect', {}, {cache:theme.fragment_cache})
!=partial('includes/third-party/chat/index', {}, {cache:theme.fragment_cache})

@ -17,6 +17,7 @@
- else pageKeywords = Array.isArray(config.keywords) ? (config.keywords).join(','): ([]).join(',') || config.keywords
- var pageAuthor = config.email ? config.author + ',' + config.email : config.author
- var pageCopyright = config.copyright || config.author
- var themeColor = theme.display_mode === 'dark' ? '#0d0d0d' : '#ffffff'
meta(charset='UTF-8')
meta(http-equiv="X-UA-Compatible" content="IE=edge")
@ -28,13 +29,15 @@ if pageKeywords
meta(name="author" content=pageAuthor)
meta(name="copyright" content=pageCopyright)
meta(name ="format-detection" content="telephone=no")
!=favicon_tag(theme.favicon || config.favicon)
link(rel="canonical" href=urlNoIndex())
meta(name="theme-color" content=themeColor)
if theme.disable_baidu_transformation
meta(http-equiv="Cache-Control" content="no-transform")
meta(http-equiv="Cache-Control" content="no-siteapp")
!=favicon_tag(theme.favicon || config.favicon)
link(rel="canonical" href=urlNoIndex())
//- 預解析
!=partial('includes/head/preconnect', {}, {cache:theme.fragment_cache})

@ -95,11 +95,13 @@
})
}
let last_push_date = 'undefined';
let date_suffix = 'undefined';
if (theme.aside.card_webinfo.last_push_date) {
last_push_date = JSON.stringify({
zeroDay: _p("aside.card_webinfo.last_push_date.zero_day"),
suffix: _p("aside.card_webinfo.last_push_date.suffix")
date_suffix = JSON.stringify({
one_hour: _p("date_suffix.one_hour"),
hours: _p("date_suffix.hours"),
day: _p('date_suffix.day')
})
}
@ -122,7 +124,7 @@ script.
message_next: '!{_p("Snackbar.bookmark.message_next")}'
},
runtime: '!{theme.runtimeshow.enable ? _p("aside.card_webinfo.runtime.unit") : ""}',
last_push_date: !{last_push_date},
date_suffix: !{date_suffix},
copyright: !{copyright},
ClickShowText: !{ClickShowText},
medium_zoom: !{theme.medium_zoom},

@ -3,13 +3,13 @@ if theme.darkmode.enable
var activateDarkMode = function () {
document.documentElement.setAttribute('data-theme', 'dark')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#000')
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
}
}
var activateLightMode = function () {
document.documentElement.setAttribute('data-theme', 'light')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#fff')
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
}
}

@ -1,6 +1,4 @@
link(rel="manifest" href=url_for(theme.pwa.manifest))
if(theme.pwa.theme_color)
meta(name="theme-color" content=theme.pwa.theme_color)
if(theme.pwa.theme_color)
meta(name="msapplication-TileColor" content=theme.pwa.theme_color)
if(theme.pwa.apple_touch_icon)

@ -24,7 +24,8 @@ html(lang=config.language data-theme=theme.display_mode)
div!= body
else
block content
include widget/index.pug
if theme.aside.enable && page.aside !== false
!=partial('includes/widget/index', {}, {cache:theme.fragment_cache})
else
main#content-inner.layout_post
if body

@ -0,0 +1,71 @@
script.
window.addEventListener('load', () => {
const changeContent = (content) => {
if (content === '') return content
content = content.replace(/<[^>]+>/g,"") // remove html tag
content = content.replace(/(http(s?):)([/|.|\w|\s|-])*\.(?:jpg|jpeg|gif|png|webp)/g, '') // remove image link
content = content.replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi, '') // remove url
if (content.length > 150) {
content = content.substring(0,150) + '...'
}
return content
}
const getDisqusComment = () => {
let disqusArray = []
$.getJSON('https://disqus.com/api/3.0/forums/listPosts.json?forum=!{theme.newest_comments.disqus.forum}&related=thread&limit=!{theme.newest_comments.limit}&api_key=!{theme.newest_comments.disqus.api_key}', function(data){
$.each(data.response, (i, item) => {
disqusArray.push({
'avatar': item.author.avatar.cache,
'content': changeContent(item.message),
'nick': item.author.name,
'url': item.url,
'date': item.createdAt
})
})
// set expiry to 10 min
saveToLocal.set('disqus-newest-comments', JSON.stringify(disqusArray), 10/(60*24))
generateHtml(disqusArray)
})
}
const generateHtml = array => {
let result = ''
for (let i = 0; i < array.length; i++) {
result += '<div class=\'aside-list-item\'>'
if (!{theme.newest_comments.avatar}) {
result += `<a href='${array[i].url}' class="thumbnail"><img src='${array[i].avatar}'></a>`
}
result += `<div class='content'>
<a class='comment' href='${array[i].url}'>${array[i].content}</a>
<div class='name'><span>${array[i].nick}</span><time> / ${diffDate(array[i].date, true)}</time></div>
</div></div>`
}
let $dom = document.querySelector('.card-newest-comments .aside-list')
$dom.innerHTML= result
window.pjax && window.pjax.refresh($dom)
}
const newestCommentInit = () => {
if (document.querySelector('.card-newest-comments .aside-list')) {
const data = saveToLocal.get('disqus-newest-comments')
if (data) {
generateHtml(JSON.parse(data))
} else {
getDisqusComment()
}
}
}
newestCommentInit()
document.addEventListener('pjax:complete', newestCommentInit)
})

@ -0,0 +1,71 @@
script.
window.addEventListener('load', () => {
const changeContent = (content) => {
if (content === '') return content
content = content.replace(/<[^>]+>/g,"") // remove html tag
content = content.replace(/(http(s?):)([/|.|\w|\s|-])*\.(?:jpg|jpeg|gif|png|webp)/g, '') // remove image link
content = content.replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi, '') // remove url
if (content.length > 150) {
content = content.substring(0,150) + '...'
}
return content
}
const getGithubIssues = () => {
let githubArray = []
$.getJSON('https://api.github.com/repos/!{theme.newest_comments.github_issues.repo}/issues/comments?sort=updated&direction=desc&per_page=!{theme.newest_comments.limit}&page=1', (data) => {
$.each(data, (index, item) => {
githubArray.push({
'avatar': item.user.avatar_url,
'content': changeContent(item.body),
'nick': item.user.login,
'url': item.html_url,
'date': item.updated_at
})
})
saveToLocal.set('github-newest-comments', JSON.stringify(githubArray), 10/(60*24))
generateHtml(githubArray)
})
}
const generateHtml = array => {
let result = ''
for (let i = 0; i < array.length; i++) {
result += '<div class=\'aside-list-item\'>'
if (!{theme.newest_comments.avatar}) {
result += `<a href='${array[i].url}' class="thumbnail"><img src='${array[i].avatar}'></a>`
}
result += `<div class='content'>
<a class='comment' href='${array[i].url}'>${array[i].content}</a>
<div class='name'><span>${array[i].nick}</span><time> / ${diffDate(array[i].date, true)}</time></div>
</div></div>`
}
let $dom = document.querySelector('.card-newest-comments .aside-list')
$dom.innerHTML= result
window.pjax && window.pjax.refresh($dom)
}
const newestCommentInit = () => {
if (document.querySelector('.card-newest-comments .aside-list')) {
const data = saveToLocal.get('github-newest-comments')
if (data) {
generateHtml(JSON.parse(data))
} else {
getGithubIssues()
}
}
}
newestCommentInit()
document.addEventListener('pjax:complete', newestCommentInit)
})

@ -0,0 +1,6 @@
if theme.newest_comments.leancloud.enable
include ./leancloud.pug
else if theme.newest_comments.github_issues.enable
include ./github-issues.pug
else if theme.newest_comments.disqus.enable
include ./disqus-comment.pug

@ -0,0 +1,98 @@
script(src="https://cdn.jsdelivr.net/npm/blueimp-md5@2.17.0/js/md5.min.js")
script.
window.addEventListener('load', () => {
const changeContent = (content) => {
if (content === '') return content
content = content.replace(/<[^>]+>/g,"") // remove html tag
content = content.replace(/(http(s?):)([/|.|\w|\s|-])*\.(?:jpg|jpeg|gif|png|webp)/g, '') // remove image link
content = content.replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi, '') // remove url
if (content.length > 150) {
content = content.substring(0,150) + '...'
}
return content
}
const getIcon = (icon, mail) => {
if (icon) return icon
let defaultIcon = '!{theme.newest_comments.leancloud.default_avatar}' || '404'
let iconUrl = `https://gravatar.loli.net/avatar/${md5(mail.toLowerCase())}?d=${defaultIcon}`
return iconUrl
}
const generateHtml = array => {
let result = ''
for (let i = 0; i < array.length; i++) {
result += '<div class=\'aside-list-item\'>'
if (!{theme.newest_comments.avatar}) {
result += `<a href='${array[i].url}' class="thumbnail"><img src='${getIcon(array[i].avatar, array[i].mail)}'></a>`
}
result += `<div class='content'>
<a class='comment' href='${array[i].url}'>${array[i].content}</a>
<div class='name'><span>${array[i].nick}</span><time> / ${diffDate(array[i].date, true)}</time></div>
</div></div>`
}
let $dom = document.querySelector('.card-newest-comments .aside-list')
$dom.innerHTML= result
window.pjax && window.pjax.refresh($dom)
}
const getValineData = () => {
if (!(AV.applicationId && (AV.applicationKey || AV.masterKey))) {
const dataInit = {
appId: '!{theme.newest_comments.leancloud.appId}',
appKey: '!{theme.newest_comments.leancloud.appKey}'
}
if (!{theme.newest_comments.leancloud.serverURL ? true : false}) {
dataInit.serverURL= '!{theme.newest_comments.leancloud.serverURL}'
}
AV.init(dataInit)
}
const query = new AV.Query('Comment');
query.descending('createdAt').limit(!{theme.newest_comments.limit})
var valineArray = []
query.find().then(comments => {
comments.forEach(comment => {
valineArray.push({
'avatar': comment.get('QQAvatar'),
'content': changeContent(comment.get('comment')),
'mail': comment.get('mail'),
'nick': comment.get('nick'),
'url': comment.get('url'),
'date': comment.createdAt,
})
})
}).then(function() {
saveToLocal.set('leancloud-newest-comments', JSON.stringify(valineArray), 10/(60*24))
generateHtml(valineArray)
})
}
const newestCommentInit = () => {
if (document.querySelector('.card-newest-comments .aside-list')) {
const data = saveToLocal.get('leancloud-newest-comments')
if (data) {
generateHtml(JSON.parse(data))
} else {
if (typeof window.AV === 'object') {
getValineData()
} else {
$.getScript('https://cdn.jsdelivr.net/npm/leancloud-storage@4.6.1/dist/av-min.js', getValineData)
}
}
}
}
newestCommentInit()
document.addEventListener('pjax:complete', newestCommentInit)
})

@ -0,0 +1,7 @@
.card-widget.card-newest-comments
.card-content
.item-headline
i.fas.fa-bolt
span= _p('aside.card_newest_comments.heading')
.aside-list
span= _p('aside.card_newest_comments.loading_text')

@ -1,31 +1,31 @@
.card-widget.card-webinfo
.card-content
.item-headline
i.fas.fa-chart-line
span= _p('aside.card_webinfo.headline')
i.fas.fa-chart-line
span= _p('aside.card_webinfo.headline')
.webinfo
if theme.aside.card_webinfo.post_count
.webinfo-item
.webinfo-article-name= _p('aside.card_webinfo.article_name') + " :"
.webinfo-article-count= site.posts.length
.item-name= _p('aside.card_webinfo.article_name') + " :"
.item-count= site.posts.length
if theme.runtimeshow.enable
.webinfo-item
.webinfo-runtime-name= _p('aside.card_webinfo.runtime.name') + " :"
#webinfo-runtime-count.webinfo-runtime-count(publish_date=theme.runtimeshow.publish_date)
.item-name= _p('aside.card_webinfo.runtime.name') + " :"
.item-count#runtimeshow(data-publishDate=date_xml(theme.runtimeshow.publish_date))
if theme.wordcount.enable && theme.wordcount.total_wordcount
.webinfo-item
.webinfo-site-wordcount-name=_p('aside.card_webinfo.site_wordcount') + " :"
.webinfo-site-wordcount=totalcount(site)
.item-name=_p('aside.card_webinfo.site_wordcount') + " :"
.item-count=totalcount(site)
if theme.busuanzi.site_uv
.webinfo-item
.webinfo-site-uv-name= _p('aside.card_webinfo.site_uv_name') + " :"
.webinfo-site-uv-count#busuanzi_value_site_uv
.webinfo-item
.item-name= _p('aside.card_webinfo.site_uv_name') + " :"
.item-count#busuanzi_value_site_uv
if theme.busuanzi.site_pv
.webinfo-item
.webinfo-site-name= _p('aside.card_webinfo.site_pv_name') + " :"
.webinfo-site-pv-count#busuanzi_value_site_pv
.item-name= _p('aside.card_webinfo.site_pv_name') + " :"
.item-count#busuanzi_value_site_pv
if theme.aside.card_webinfo.last_push_date
.webinfo-item
.webinfo-last-push-date-name= _p('aside.card_webinfo.last_push_date.name') + " :"
.webinfo-last-push-date(last-push-date=date(Date.now(), config.date_format))
.item-name= _p('aside.card_webinfo.last_push_date.name') + " :"
.item-count#last-push-date(data-lastPushDate=date_xml(Date.now()))

@ -1,20 +1,20 @@
if theme.aside.enable
if page.aside !== false
#aside_content.aside_content
if theme.aside.card_author.enable
!=partial('includes/widget/card_author', {}, {cache:theme.fragment_cache})
.sticky_layout
if theme.aside.card_announcement.enable
!=partial('includes/widget/card_announcement', {}, {cache:theme.fragment_cache})
if theme.aside.card_recent_post.enable
!=partial('includes/widget/card_recent_post', {}, {cache:theme.fragment_cache})
if theme.ad && theme.ad.aside
!=partial('includes/widget/card_ad', {}, {cache:theme.fragment_cache})
if theme.aside.card_categories.enable
!=partial('includes/widget/card_categories', {}, {cache:theme.fragment_cache})
if theme.aside.card_tags.enable
!=partial('includes/widget/card_tags', {}, {cache:theme.fragment_cache})
if theme.aside.card_archives.enable
!=partial('includes/widget/card_archives', {}, {cache:theme.fragment_cache})
if theme.aside.card_webinfo.enable
!=partial('includes/widget/card_webinfo', {}, {cache:theme.fragment_cache})
#aside_content.aside_content
if theme.aside.card_author.enable
include ./card_author.pug
.sticky_layout
if theme.aside.card_announcement.enable
include ./card_announcement.pug
if theme.aside.card_recent_post.enable
include ./card_recent_post.pug
if theme.newest_comments.enable
include ./card_newest_comment.pug
if theme.ad && theme.ad.aside
include ./card_ad.pug
if theme.aside.card_categories.enable
include ./card_categories.pug
if theme.aside.card_tags.enable
include ./card_tags.pug
if theme.aside.card_archives.enable
include ./card_archives.pug
if theme.aside.card_webinfo.enable
include ./card_webinfo.pug

@ -91,6 +91,6 @@ hexo.extend.helper.register('aside_categories', function (categories, options) {
return `<ul class="card-category-list">
${list[0]}
${moreButton()}
${moreButton()}
</ul>`
})

@ -104,20 +104,29 @@
.aside-list
margin: 10px 0 -15px
& > span
display: block
margin-bottom: .5rem
text-align: center
& > .aside-list-item
display: flex
align-items: center
margin-bottom: 10px
padding: .3rem 0
&:first-child
padding-top: 0
&:not(:last-child)
border-bottom: 1px dashed #f5f5f5
&:last-child
margin-bottom: .3rem
// padding 8px 0
// border-bottom: 1px dashed #f5f5f5
// height: 4.72em
.thumbnail
// float: left
overflow: hidden
width: w = 4.2em
height: w
border-radius: w
& > img
width: 100%
@ -134,19 +143,19 @@
word-break: break-all
& > .name
@extend .limit-one-line
@extend .limit-more-line
-webkit-line-clamp: 1
& > time
& > time,
& > .name
color: $theme-meta-color
font-size: 85%
& > .comment
font-size: 90%
& > .title,
& > .comment
@extend .limit-more-line
color: var(--font-color)
font-size: 95%
line-height: 1.5
-webkit-line-clamp: 2

@ -123,6 +123,9 @@ if hexo-config('darkmode.enable') || hexo-config('display_mode') == 'dark'
.gist,
.aplayer
filter: brightness(.7)
#aside_content .aside-list > .aside-list-item:not(:last-child)
border-bottom: 1px dashed alpha(#FFFFFF, .1)
//
// hexo-blog-encrypt

@ -618,9 +618,9 @@ const addCopyright = () => {
* 網頁運行時間
*/
const addRuntime = () => {
const $runtimeCount = $('#webinfo-runtime-count')
const $runtimeCount = $('#runtimeshow')
if ($runtimeCount.length) {
const publishDate = $runtimeCount.attr('publish_date')
const publishDate = $runtimeCount.attr('data-publishDate')
$runtimeCount.text(diffDate(publishDate) + ' ' + GLOBAL_CONFIG.runtime)
}
}
@ -629,17 +629,12 @@ const addRuntime = () => {
* 最後一次更新時間
*/
const addLastPushDate = () => {
const $lastPushDateItem = $('.webinfo-last-push-date')
const $lastPushDateItem = $('#last-push-date')
if ($lastPushDateItem.length) {
const lastPushDate = $lastPushDateItem.attr('last-push-date')
const diffDay = diffDate(lastPushDate)
if (diffDay < 1) {
$lastPushDateItem.text(GLOBAL_CONFIG.last_push_date.zeroDay)
} else if (diffDay > 365) {
$lastPushDateItem.text(lastPushDate)
} else {
$lastPushDateItem.text(diffDay + ' ' + GLOBAL_CONFIG.last_push_date.suffix)
}
const lastPushDate = $lastPushDateItem.attr('data-lastPushDate')
const diffDay = diffDate(lastPushDate, true)
console.log(diffDay)
$lastPushDateItem.text(diffDay)
}
}
@ -810,7 +805,7 @@ const refreshFn = function () {
addLightBox()
scrollFn()
GLOBAL_CONFIG.runtime && addRuntime()
GLOBAL_CONFIG.last_push_date !== undefined && addLastPushDate()
addLastPushDate()
addTableWrap()
clickFnOfTagHide()
tabsFn.clickFnOfTabs()

@ -97,12 +97,26 @@ const initJustifiedGallery = function (selector) {
})
}
const diffDate = d => {
const diffDate = (d, more = false) => {
const dateNow = new Date()
const datePost = new Date(d.replace(/-/g, '/'))
const datePost = new Date(d)
const dateDiff = dateNow.getTime() - datePost.getTime()
const dayDiff = Math.floor(dateDiff / (24 * 3600 * 1000))
return dayDiff
let result
if (more) {
if (dateDiff <= 3600000) { // < 1 hour
result = GLOBAL_CONFIG.date_suffix.one_hour
} else if (dateDiff < 3600000 * 24) { // 1 hour < x < 24 hours
result = Math.floor(dateDiff / 3600000) + ' ' + GLOBAL_CONFIG.date_suffix.hours
} else if (dayDiff >= 1 || dayDiff < 365) { // 1 day < x < 365 days
result = dayDiff + ' ' + GLOBAL_CONFIG.date_suffix.day
} else { // > 365 days
result = d.toLocaleDateString().replace(/\//g, '-')
}
} else {
result = dayDiff
}
return result
}
const loadComment = (dom, callback) => {

Loading…
Cancel
Save