本文实现了如何在butterfly主题中添加最新文章标签,其他主题可以在相应位置进行比较添加。

预览效果

最新文章预览效果

本教程来自于Leonus几行代码实现最新文章标志,样式部分进行的修改。
由于本站文章主页的datatime不知道为什么没有classpost-meta-date-created这个选择器,所以暂时采用旧版。

实现教程

非修改源码方案

  1. 新建[BlogSource]/themes/butterfly/source/js/custom/newest_post.js文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // 旧版,本站采用
    // 确保其他页面第一个不添加
    if (location.pathname == '/') newPost();

    // 最新文章
    function newPost() {
    // 获取此类名而不是获取recent-post-item是因为一些插件也会使用recent-post-item类。
    // 所以获取recent-post-info可以确保每一篇都是文章。
    let ls = document.querySelectorAll('.recent-post-info')
    for (let i = 0; i < ls.length; i++) {
    // 如果是置顶则跳过,所以如果你最新文章置顶的话就无法添加标志,只会给到置顶下面最新的文章。
    // 不过一般来说置顶文章都会是早期文章,实在不行置顶之后再写一篇😂
    if (ls[i].querySelector('.sticky')) continue;
    let className = '';
    // 封面在右则在左边添加,否则在右边
    // 其实你也可以直接放在左边,我之所以这样弄是为了避免和分类图标冲突
    if (ls[i].previousSibling.classList.contains('right')) className = 'newPost-left';
    else className = 'newPost-right';
    ls[i].innerHTML += '<span class="' + className + '">最 新</span>';
    return
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // 新代码,利用创建时间来判断
    // 确保其他页面第一个不添加
    if (location.pathname == '/') newPost();

    // 最新文章
    function newPost() {
    let ls = document.querySelectorAll('.recent-post-info')
    // 先让时间和索引值都等于第一个的
    let time = new Date(ls[0].querySelector('.post-meta-date-created').getAttribute('datetime')).getTime();
    let index = 0
    // 遍历数组,如果有时间比time大的则替换
    ls.forEach((i, num) => {
    let t = new Date(i.querySelector('.post-meta-date-created').getAttribute('datetime')).getTime()
    if (t > time) {
    time = t;
    index = num
    }
    })
    // 单数在右,双数在左
    let className = index % 2 == 0 ? 'newPost-right' : 'newPost-left'
    ls[index].innerHTML += '<span class="' + className + '">最 新</span>';
    // 如果你不想让其一左一右,可以注释上面的启用下面的
    // ls[index].innerHTML += '<span class="newPost-left">最 新</span>';
    }
  2. 新建[BlogSource]/themes/butterfly/source/css/custom/newest_post.css文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    .newPost-left,
    .newPost-right::before {
    content: "new";
    width: 3rem;
    height: 2rem;
    border-radius: 8px;
    text-align: center;
    line-height: 2rem;
    color: #fff;
    position: absolute;
    top: 8px;
    left: 8px;
    background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
    background-size: 400% 400%;
    animation: gradient 15s ease infinite;
    }
  3. 引入[BlogSource]/themes/butterfly/source/js/custom/newest_post.js文件
    1
    2
    3
    4
    inject:
    bottom:
    # 引入自定义js,判断最新文章
    - <script defer="" src="/js/custom/newest_post.js" data-pjax=""></script>

加上data-pjax是为了由于开启pjax引起切换页面后失效

修改源码方案

来自Butterfly文章卡片加上最新文章标志 | 轻笑Chuckle

  1. 修改\blog\themes\butterfly\layout\includes\mixins\post-ui.pug加上三行:

    1
    2
    3
    4
    .recent-post-info
    + if (numberone !== 1 && is_current('/') && (!article.top || (article.new && article.top)))
    + span.newPost 最新
    + - var numberone = 1
  2. 在你的自定义css文件中,添加如下代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    /* 最新文章图标 */
    .newPost {
    position: absolute;
    top: 0;
    color: rgba(255, 255, 255, 0.92);
    padding: 0 15px;
    background-color: #49b0f5b9;
    border-radius: 0 0 10px 10px;
    right: 40px;
    }
    @media screen and (max-width:600px){
    .newPost {
    right: 0px;
    padding: 0 12px;
    border-radius: 0 10px 0px 10px;
    }
    }

当首页没有置顶时,会给第一个卡片加上最新标志
当首页有置顶时,会给非置顶的第一个卡片加上最新标志

显然,这里有bug,如果置顶里的文章就是最新的咋办?
只需要在文章头部加上new: true就行了

稍微有点麻烦,所以,建议最新的文章就没必要置顶了,反正不置顶也在第一个

1
2
3
4
5
---
title: aaaaaaaaaa
top: 1
+ new: true
---

最后

  1. 非修改源码方案需要每次加载js,会多吃一些性能,但是避免了修改源码以及置顶和最新文章冲突的判断
  2. 修改源码方案无需重复加载资源,性能比第一种好,但是需要改动源码以及可能发生置顶与最新文章冲突以及其他可能情况出现

补充

看到Butterfly给首页首个文章卡片加个class | 轻笑Chuckle解决了我一直以来想加class的想法。

修改\themes\butterfly\layout\includes\mixins\post-ui.pug

1
2
3
4
5
6
7
8
9
10
11
mixin postUI(posts)
each article , index in page.posts.data
- .recent-post-item
+ if (firstpost !== 1 && is_current('/'))
+ - var firstpost = 1
+ .recent-post-item.firstpost-item
+ //首页首个文章卡片的具体的内容(cv原来的就行)
+ else
+ .recent-post-item
+ //其余文章卡片的具体的内容(cv原来的就行)

评论区Heo方案,减少代码冗余

1
2
3
4
5
6
7
mixin postUI(posts)
each article , index in page.posts.data
- .recent-post-item
+ if (article.hide !== true && article.top !== true)
+ - let lastPost = fristpost !== 1 && is_current('/') ? true : false
+ - var fristpost = 1
+ .recent-post-item(class= (lastPost === true) ? 'lastestpost-item' : '')

这样,首页第一个文章卡片就会多一个firstpost-item,控制这个class就能控制样式了