博客近期文章功能

版本信息:

Nexo:4.0.0
Next:7.5.0

实现

初步方法

一开始想实现这个功能时,是参考网上的写法来写的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
     <!--近期文章版块 began-->
                         {% if theme.recent_posts %}
                                 <div class="links-of-blogroll motion-element {{ "links-of-blogroll-" + theme.recent_posts_layout }}">
                                     <div class="links-of-blogroll-title">
                                         <i class="fa fa-history fa-{{ theme.recent_posts_icon | lower }}" aria-hidden="true"></i>
                                         {{ theme.recent_posts_title }}
                                     </div>
                                     <ul class="links-of-blogroll-list">
                                         {% set posts = site.posts.sort('-date') %}
                                        {% for post in posts.slice('0', '5') %}
                                            <li class='my-links-of-blogroll-li'>
                                                <a href="{{ url_for(post.path) }}" title="{{ post.title }}" target="_blank">{{ post.title }}</a>
                                            </li>
                                        {% endfor %}
                                    </ul>
                                </div>
                        {% endif %}
                        <!--近期文章版块 end-->

插入到sidebar.swig中。

主题配置文件中加入:

1
2
3
4
     #近期文章
     recent_posts_title: 近期文章
     recent_posts_layout: block
     recent_posts: true

效果

查看效果发现网页未能获取到文章的path与title。
1

开始调试:

检查函数方法:

检查sort与slice是否有问题,用排除法:
添加多个文章,发现能截取5个文章,说明slice正常。
去除sort方法,不执行排序,然后查看网页效果,发现仍未能获取到,说明问题不在sort方法上。

还尝试了换不同方法的写法来排序:sort(‘date’,-1)等,出现报错等。

检查变量:

查看Nexo官方文档,发现site.posts是获取整个网页的文章,site是网页变量,posts是全部文章的属性。
尝试单独输出site或site.posts,发现这是一个封装好的object,无法查看其中的内容。

检查版本问题:

之前安装Hexo我是按照网上一个教程:

1
npm install -g hexo

但查看Hexo官方文档的安装方法,却是这样的:

1
npm install -g hexo-cli

不同安装方法,最后安装的Next的主题默认版本都不同,
教程:Next 7.5.0
官方:Next 5.1.4

发现使用Next 5.1.4插入上述代码,成功实现近期文章效果,成功获取。
而且发现5.1.4的文件与7.5.0有一定的区别。
一开始我的解决办法是想干脆将博客转到Next 5.1.4算了,但发现旧版主题网页的显示效果没有新版的好,而且迁移过程耗费精力,就放弃了。

新的解决办法

查看官方文档

开始查看Next的github官网文档,发现7.5.0更换了模板引擎,使用了Nunjucks作为模板引擎。
提出issue,官方人员提示我尝试使用toArray()来解决。

修改

在修改为:

1
site.posts.toArray()

执行出现报错,然后去除sort和slice,再次执行,成功实现。

然后再依次加上slice和sort,发现当使用sort方法时出现报错。

考虑到要同时兼顾Nunjucks的写法来使用,查看文档:

1
sort(arr, reverse, caseSens, attr)

用JavaScript中的arr.sort函数排序arr。如果reverse为true,则会返回相反的 排序结果。默认状态下排序不会区分大小写,但你可以将caseSens设置为true来让排序 区分大小写。我们可以用attr来指定要比较的属性。

不同sort写法

然后尝试了不同的写法:

1
site.posts.toArray().sort('-date')

或:

1
2
3
site.posts.toArray().sort(function(a,b){
return a.date - b.date
})

还有默认的:

1
2
3
site.posts.sort()

site.posts.sort(Reverse = True)

报错

都出现了类似的报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
     (报错代码片段):
     ERROR Render HTML failed: 404.html
     TypeError: Cannot read property 'replace' of null
     at Hexo.externalLinkFilter (E:\hexo\node_modules\hexo\lib\plugins\filter\after_render\external_link.js:45:15)
     at Hexo.tryCatcher (E:\hexo\node_modules\bluebird\js\release\util.js:16:23)
     at Hexo. (E:\hexo\node_modules\bluebird\js\release\method.js:15:34)
     at Promise.each.filter (E:\hexo\node_modules\hexo\lib\extend\filter.js:60:50)
     at tryCatcher (E:\hexo\node_modules\bluebird\js\release\util.js:16:23)
     at Object.gotValue (E:\hexo\node_modules\bluebird\js\release\reduce.js:166:18)
    at Object.gotAccum (E:\hexo\node_modules\bluebird\js\release\reduce.js:155:25)
    at Object.tryCatcher (E:\hexo\node_modules\bluebird\js\release\util.js:16:23)
    at Promise._settlePromiseFromHandler (E:\hexo\node_modules\bluebird\js\release\promise.js:547:31)
    at Promise._settlePromise (E:\hexo\node_modules\bluebird\js\release\promise.js:604:18)
    at Promise._settlePromiseCtx (E:\hexo\node_modules\bluebird\js\release\promise.js:641:10)
    at _drainQueueStep (E:\hexo\node_modules\bluebird\js\release\async.js:97:12)
    at _drainQueue (E:\hexo\node_modules\bluebird\js\release\async.js:86:9)
    at Async._drainQueues (E:\hexo\node_modules\bluebird\js\release\async.js:102:5)
    at Immediate.Async.drainQueues [as _onImmediate] (E:\hexo\node_modules\bluebird\js\release\async.js:15:14)
    at runCallback (timers.js:705:18)
    at tryOnImmediate (timers.js:676:5)
    at processImmediate (timers.js:658:5)
    ERROR Render HTML failed: categories/index.html
    TypeError: Cannot read property 'replace' of null
    at Hexo.externalLinkFilter (E:\hexo\node_modules\hexo\lib\plugins\filter\after_render\external_link.js:45:15)
    at Hexo.tryCatcher (E:\hexo\node_modules\bluebird\js\release\util.js:16:23)
    at Hexo. (E:\hexo\node_modules\bluebird\js\release\method.js:15:34)
    at Promise.each.filter (E:\hexo\node_modules\hexo\lib\extend\filter.js:60:50)
    at tryCatcher (E:\hexo\node_modules\bluebird\js\release\util.js:16:23)
    at Object.gotValue (E:\hexo\node_modules\bluebird\js\release\reduce.js:166:18)
    at Object.gotAccum (E:\hexo\node_modules\bluebird\js\release\reduce.js:155:25)

思考

经静下心来思考,想到既然:

1
site.posts.sort('-date')

这样不报错,而:

1
site.posts.toArray().sort('-date')

转换为数组后再排序就报错。

为何不试下:

1
site.posts.sort('-date').toArray()

先排序好再转换为数组?

成功实现

修改过后重新部署,成功实现!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!--近期文章版块 began-->
{% if theme.recent_posts %}
<div class="links-of-blogroll motion-element {{ "links-of-blogroll-" + theme.recent_posts_layout }}">
<div class="links-of-blogroll-title">
<i class="fa fa-history fa-{{ theme.recent_posts_icon | lower }}" aria-hidden="true"></i>
{{ theme.recent_posts_title }}
</div>
<ul class="links-of-blogroll-list">
{% set posts = site.posts.sort('-date').toArray() %}
{% for post in posts.slice(0,5) %}
<li class='my-links-of-blogroll-li'>
<a href="{{ url_for(post.path) }}" title= "{{ post.title }}" target="_blank">{{ post.title }}</a>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
<!--近期文章版块 end-->

2

成功实现新版Next主题的近期文章功能。
这其中的修改要兼顾Nexo和Next主题模板引擎Nunjucks!