前言

关于我博客的整个搭建过程可以参照我知乎这篇文章

有涉及到修改源码的部分,Butterfly 版本3.8.3

优先考虑顺序:插件 > 自定义css > 魔改(改源码)

背景板

该调整不涉及源码修改。原先的主题分为了上中下三层结构,我觉得过于花了,统一改为了一种背景,文章栏与侧边栏透明思路也简单,只留背景,其余部分去色,替换为背景图的方式,背景0.9透明,主题色做出了调整,可以在主题文件中的theme_color中修改

效果预览(旧)

image-20210808145943484

配置

在themes/source/css下创建自己的css文件
image-20210808150305780
加入以下代码,前提是将_config.butterfly文件中的background不能为空且与index_img一致
首先是调整背景板为一体(但在暗黑模式下,页脚还会出现阴影快)

1
2
3
4
5
6
7
8
9
10
11
12
13
/* 页脚去色 */
#footer {
background: none;
}
/* 使用opacity可以设置当前透明度,避免切换dark模式产生颜色单一的问题 */
/* 文章栏变色 */
#recent-posts>.recent-post-item,.layout_page>div:first-child:not(.recent-posts),.layout_post>#page,.layout_post>#post,.read-mode .layout_post>#post {
opacity: 0.9;
}
/* 侧边栏去色 */
#aside-content .card-widget {
opacity: 0.9;
}

替换为阿里图标

效果预览

image-20210808151146237

配置

阿里巴巴矢量图标库提供了三种引入方案,其实也就是两种,一种单色,一种多色(需要改源码)既然都是引入,不会真有人自己写css吧
推荐symbol引入这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。本教程来源于这篇文章

新建图标

  1. 进入阿里巴巴矢量图标库 , 注册登录
  2. 加入自己需要的图标
  3. 添加到项目中
    image-20210908211946137

引入图标

官方提供了三种方式,我只列举我的彩色实现方案,彩色的本质是因为它是一个svg,源码中不支持这种能力,所以需要调整源码

  1. 修改 [root]\themes\butterfly\layout\includes\header\menu_item.pug
    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
      if theme.menu
    //- for mobile sidebar
    - let sidebarChildHide = theme.hide_sidebar_menu_child ? 'hide' : ''

    .menus_items
    each value, label in theme.menu
    if typeof value !== 'object'
    .menus_item
    a.site-page(href=url_for(trim(value.split('||')[0])))
    if value.split('||')[1]
    - i.fa-fw(class=trim(value.split('||')[1]))
    + - var icon_value = trim(value.split('||')[1])
    + if icon_value.substring(0,2)=="fa"
    + i.fa-fw(class=icon_value)
    + else if icon_value.substring(0,4)=="icon"
    + svg.icon(aria-hidden="true")
    + use(xlink:href=`#`+ icon_value)
    span=' '+label
    else
    .menus_item
    a.site-page(href='javascript:void(0);')
    if label.split('||')[1]
    - i.fa-fw(class=trim(label.split('||')[1]))
    + - var icon_label = trim(label.split('||')[1])
    + if icon_label.substring(0,2)=="fa"
    + i.fa-fw(class=icon_label)
    + else if icon_label.substring(0,4)=="icon"
    + svg.icon(aria-hidden="true")
    + use(xlink:href=`#`+ icon_label)
    span=' '+ trim(label.split('||')[0])
    i.fas.fa-chevron-down.expand(class=sidebarChildHide)
    ul.menus_item_child
    each val,lab in value
    li
    a.faa-parent.animated-hover.site-page.child(href=url_for(trim(val.split('||')[0])))
    if val.split('||')[1]
    - i.fa-fw(class=trim(val.split('||')[1]))
    + - var icon_val = trim(val.split('||')[1])
    + if icon_val.substring(0,2)=="fa"
    + i.fa-fw(class=icon_val)
    + else if icon_val.substring(0,4)=="icon"
    + svg.icon(aria-hidden="true")
    + use(xlink:href=`#`+ icon_val)
    span=' '+ lab
  2. 直接复制版
    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    if theme.menu
    //- for mobile sidebar
    - let sidebarChildHide = theme.hide_sidebar_menu_child ? 'hide' : ''

    .menus_items
    each value, label in theme.menu
    if typeof value !== 'object'
    .menus_item
    a.site-page(href=url_for(trim(value.split('||')[0])))
    if value.split('||')[1]
    - var icon_value = trim(value.split('||')[1])
    if icon_value.substring(0,2)=="fa"
    i.fa-fw(class=icon_value)
    else if icon_value.substring(0,4)=="icon"
    svg.icon(aria-hidden="true")
    use(xlink:href=`#`+ icon_value)
    span=' '+label
    else
    .menus_item
    a.site-page(href='javascript:void(0);')
    if label.split('||')[1]
    - var icon_label = trim(label.split('||')[1])
    if icon_label.substring(0,2)=="fa"
    i.fa-fw(class=icon_label)
    else if icon_label.substring(0,4)=="icon"
    svg.icon(aria-hidden="true")
    use(xlink:href=`#`+ icon_label)
    span=' '+ trim(label.split('||')[0])
    i.fas.fa-chevron-down.expand(class=sidebarChildHide)
    ul.menus_item_child
    each val,lab in value
    li
    a.site-page.child(href=url_for(trim(val.split('||')[0])))
    if val.split('||')[1]
    - var icon_val = trim(val.split('||')[1])
    if icon_val.substring(0,2)=="fa"
    i.fa-fw(class=icon_val)
    else if icon_val.substring(0,4)=="icon"
    svg.icon(aria-hidden="true")
    use(xlink:href=`#`+ icon_val)
    span=' '+ lab
  3. 使用方式
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    menu:
    首页: / || icon-shouye_huaban
    文章 || icon-wenzhang :
    归档: /archives/ || icon-shijianzhou
    标签: /tags/ || icon-biaoqian-copy-copy
    分类: /categories/ || icon-ziyuan
    闲言碎语: /talk/ || icon-liuyanban
    友情链接: /link/ || icon-lianjie
    留言板: /board/ || icon-xiaoxi
    关于: /about/ || icon-bixin1
    上面是菜单的,接下来替换social图标
  4. 修改 [root]\themes\butterfly\layout\includes\header\social.pug, 替换为以下代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    each value, title in theme.social
    a.social-icon(href=url_for(trim(value.split('||')[0])) target="_blank" title=title === undefined ? '' : trim(title))
    if value.split('||')[1]
    - var icon_value = trim(value.split('||')[1])
    if icon_value.substring(0,2)=="fa"
    i.fa-fw(class=icon_value)
    else if icon_value.substring(0,4)=="icon"
    svg.icon(aria-hidden="true")
    use(xlink:href=`#`+ icon_value)
  5. 使用方式
    1
    2
    3
    4
    social:
    gitee: https://github.com/bigli97 || icon-gitee
    zhihu: https://www.zhihu.com/people/da-hu-you-55-56 || icon-zhihu
    juejin: https://juejin.cn/user/2093100615603101 || icon-juejin

说说

不怕折腾的可以考虑。我这里配置了两套,一个手机发用于首页顶部显示,一个电脑发用于闲言碎语

前置要求 参照官方文档的LeanCloud 的相关准备环节,一定要每一步都配置
调用方式 采用插件的方式

  1. 前往 LeanCloud 国际版,注册账号。
  2. 注册完成之后根据 LeanCloud 的提示绑定手机号和邮箱。
  3. 绑定完成之后点击创建应用,应用名称随意,接着在结构化数据中创建 class,命名为 shuoshuo
  4. 在你新建的应用中找到结构化数据下的用户。点击添加用户,输入想用的用户名及密码。
  5. 回到结构化数据中,点击 class 下的 shuoshuo。找到权限,在 Class 访问权限中将 add_fields 以及 create 权限设置为指定用户,输入你刚才输入的用户名会自动匹配。为了安全起见,将 deleteupdate 也设置为跟它们一样的权限。
  6. 然后新建一个名为atComment的class,权限什么的使用默认的即可。
  7. 点击 class 下的 _User 添加列,列名称为 img,默认值填上你这个账号想要用的发布说说的头像url,这一项不进行配置,说说头像会显示为默认头像 —— Artitalk 的 logo。
  8. 在最菜单栏中找到设置-> 应用 keys,记下来 AppIDAppKey ,一会会用。
  9. 最后将 _User 中的权限全部调为指定用户,或者数据创建者,为了保证不被篡改用户数据已达到强制发布说说。
效果预览

image-20210808155431123

配置

安装Artitalk插件

1
npm install hexo-butterfly-artitalk

修改主题配置文件

1
2
3
4
5
6
7
8
9
artitalk:
enable: true
appId: 你的appId
appKey: 你的appKey
path: talk(标签路径,如果没有会给你自动生成)
js:
option:
serverURL: 国内用户必填,对应 LeanCloud 创建的应用中绑定的 API 域名
front_matter:

前置要求 参照该作者的教程配置好所需的云函数
涉及到了腾讯云存储,其实最后也就是需要调用请求的一个方式就可以随时随地发送了
调用方式 我目前找到的有一个edge插件发送,还有ios的快捷指令发送,相关文档可查看小康HEO的文章

效果预览

image-20210808161528776

评论

前期用的valine,后来换为了twikoo,主要是valine不好管理,但配置起来挺快的,而twikoo配置起来会麻烦一点,不怕折腾的推荐twikoo
这里就只说下twikoo吧,valine有兴趣可以看官方文档

效果预览

image-20210808162322884

配置

twikoo官方文档推荐了4种云函数部署方式,官方建议Vercel部署 ,优点是免费
同样,严格按照步骤来,不过这里我推荐观看视频教程,我当时就给整晕了

  1. 申请 MongoDB (opens new window)账号
  2. 创建免费 MongoDB 数据库,区域推荐选择 AWS / N. Virginia (us-east-1)
  3. 在 Clusters 页面点击 CONNECT,按步骤设置允许所有 IP 地址的连接(为什么? (opens new window)),创建数据库用户,并记录数据库连接字符串,请将连接字符串中的 <password> 修改为数据库密码
  4. 申请 Vercel (opens new window)账号
  5. 点击以下按钮将 Twikoo 一键部署到 Vercel
  6. 添加环境变量 MONGODB_URI 到 Vercel,值为第 3 步的数据库连接字符串
  7. Vercel 环境地址(包含 https:// 前缀)即为您的环境 id

留言板

加了一个效果,npm插件的方式,很奈斯,来源于作者Akilar

效果预览

image-20210808163935

配置

安装插件

1
npm install hexo-butterfly-envelope --save

主题配置文件添加如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
envelope_comment:
enable: true
cover: https://ae01.alicdn.com/kf/U5bb04af32be544c4b41206d9a42fcacfd.jpg # 信笺封面图
message: # 信笺内容,支持多行
- 有什么想问的?
- 有什么想说的?
- 有什么想吐槽的?
bottom: 自动书记人偶竭诚为您服务! # 信笺结束语,只能单行
height: # 调整信笺划出高度,默认1050px
path: # 【可选】comments 的路径名称。默认为 comments , 生成的页面为 comments/index.html
front_matter: # 【可选】comments页面的 front_matter 配置
title: 留言板
comments: false
aside: false

古诗词

来源于HEO,需要修改源码,我把诗词这块转移到了banner图中

效果预览

image-20210808164644725

配置

在themes/butterfly/layout/includes/widget下新建card_poem.pug

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#card-poem.card-widget
#poem_sentence
#poem_info
#poem_dynasty
#poem_author
script(src='https://cdn.jsdelivr.net/gh/zhheo/JS-Heo@main/poem/jinrishici.js', charset='utf-8')
script(type='text/javascript').
jinrishici.load(function(result) {
var sentence = document.querySelector("#poem_sentence")
var author = document.querySelector("#poem_author")
var dynasty = document.querySelector("#poem_dynasty")

var sentenceText = result.data.content
sentenceText = sentenceText.substr(0, sentenceText.length - 1);
sentence.innerHTML = sentenceText
dynasty.innerHTML = result.data.origin.dynasty
author.innerHTML = result.data.origin.author + '《' + result.data.origin.title + '》'
});

在themes/butterfly/layout/includes/widget/index.pug下添加

1
!=partial('includes/widget/card_poem', {}, {cache: true})

位置如下

image-20210808165528320

在主题中引入两个css

1
2
- <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/zhheo/JS-Heo@main/mainColor/heoMainColor.css">
- <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/zhheo/JS-Heo@main/poem/poem.css">

历史上的今天

一个很有意思的插件,来源于小冰

效果预览

配置
1
npm i hexo-history-calendar --save

在hexo的配置文件中添加如下

1
2
3
4
5
6
7
8
9
history_calendar:
priority: 4 #优先级
enable: true #是否开启
enable_page: all #all表示全站,/表示仅主页
layout: #保持默认
type: class
name: sticky_layout
index: 0
temple_html: '<div class="card-widget card-history"><div class="card-content"><div class="item-headline"><i class="fas fa-clock fa-spin"></i><span>那年今日</span></div><div id="history-baidu" style="height: 100px;overflow: hidden"><div class="history_swiper-container" id="history-container" style="width: 100%;height: 100%"><div class="swiper-wrapper" id="history_container_wrapper" style="height:20px"></div></div></div></div>'

微博热搜

对于我这种不想下微博,又只想看热搜的人来说是再适合不过了,来源于这篇文章
该技术通过增加侧边栏模块,爬虫的方式实现,同理知乎的热搜如果能爬到,也可用同样的方式

效果预览

image-20210908221117188

配置
  1. 创建card_weibo.js,或者直接引用现成的js路径

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    fetch('https://weibo-top-api.vercel.app/api').then(data => data.json()).then(data => {
    let html = '<style>.weibo-new{background:#ff3852}.weibo-hot{background:#ff9406}.weibo-jyzy{background:#ffc000}.weibo-recommend{background:#00b7ee}.weibo-adrecommend{background:#febd22}.weibo-friend{background:#8fc21e}.weibo-boom{background:#bd0000}.weibo-topic{background:#ff6f49}.weibo-topic-ad{background:#4dadff}.weibo-boil{background:#f86400}#weibo-container{overflow-y:auto;-ms-overflow-style:none;scrollbar-width:none}#weibo-container::-webkit-scrollbar{display:none}.weibo-list-item{display:flex;flex-direction:row;justify-content:space-between;flex-wrap:nowrap}.weibo-title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:auto}.weibo-num{float:right}.weibo-hotness{display:inline-block;padding:0 6px;transform:scale(.8) translateX(-3px);color:#fff;border-radius:8px}</style>'
    html += '<div class="weibo-list">'
    let hotness = {
    '爆': 'weibo-boom',
    '热': 'weibo-hot',
    '沸': 'weibo-boil',
    '新': 'weibo-new',
    '荐': 'weibo-recommend',
    '影': 'weibo-jyzy',
    '剧': 'weibo-jyzy',
    '综': 'weibo-jyzy'
    }
    for (let item of data) {
    html += '<div class="weibo-list-item"><div class="weibo-hotness ' + hotness[(item.hot || '荐')] + '">' + (item.hot || '荐') + '</div>'
    + '<span class="weibo-title"><a title="' + item.title + '"href="' + item.url + '" target="_blank" rel="external nofollow noreferrer">' + item.title + '</a></span>'
    + '<div class="weibo-num"><span>' + item.num + '</span></div></div>'
    }
    html += '</div>'
    document.getElementById('weibo-container').innerHTML = html
    }).catch(function (error) {
    console.log(error);
    });
  2. 在 config.butterfly.yml 增加以下内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    aside:
    enable: true
    hide: true
    button: true
    ...
    + card_weibo:
    + enable: true

    # CDN
    # Don't modify the following settings unless you know how they work
    # 非必要請不要修改
    CDN:
    # main
    main_css: /css/index.css
    jquery: https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js
    main: /js/main.js
    utils: /js/utils.js

    + #weibo
    + card_weibo: https://cdn.jsdelivr.net/gh/Eurkon/CDN/hexo/js/card_weibo.js
  3. 在 [root]\themes\butterfly\layout\includes\widget 目录下创建 card_weibo.pug 文件,添加以下内容

    1
    2
    3
    4
    5
    6
    7
    8
    if theme.aside.card_weibo.enable
    .card-widget.card-weibo
    .card-content
    .item-headline
    i.fab.fa-weibo
    span= _p('微博热搜')
    #weibo-container(style="width: 100%; height: 150px;font-size: 95%;")
    script(defer data-pjax src=url_for(theme.CDN.card_weibo))
  4. 在 [Blogroot]\themes\butterfly\layout\includes\widget\index.pug 文件中增加以下内容。

    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
      #aside-content.aside-content
    //- post
    if is_post()
    if showToc && theme.toc.style_simple
    .sticky_layout
    include ./card_post_toc.pug
    else
    !=partial('includes/widget/card_author', {}, {cache: true})
    !=partial('includes/widget/card_announcement', {}, {cache: true})
    .sticky_layout
    if showToc
    include ./card_post_toc.pug
    + !=partial('includes/widget/card_weibo', {}, {cache: true})
    !=partial('includes/widget/card_recent_post', {}, {cache: true})
    !=partial('includes/widget/card_ad', {}, {cache: true})
    else
    //- page
    !=partial('includes/widget/card_author', {}, {cache: true})
    !=partial('includes/widget/card_announcement', {}, {cache: true})
    .sticky_layout
    + !=partial('includes/widget/card_weibo', {}, {cache: true})
    !=partial('includes/widget/card_recent_post', {}, {cache: true})
    !=partial('includes/widget/card_ad', {}, {cache: true})
    !=partial('includes/widget/card_newest_comment', {}, {cache: true})
    !=partial('includes/widget/card_categories', {}, {cache: true})
    !=partial('includes/widget/card_tags', {}, {cache: true})
    !=partial('includes/widget/card_archives', {}, {cache: true})
    !=partial('includes/widget/card_webinfo', {}, {cache: true})
    !=partial('includes/widget/card_self', {}, {cache: true})
  5. hexo三连

    1
    hexo clean && hexo g && hexo s

    附加git代码地址