Hexo+Github 博客 butterfly 主题 搭建过程【整理】

仅是记录一下搭建过程,方便自己后期维护与主题升级。一定要写一点功能就跑一边代码,我后面找不见报错真的令人头大!最好用webstorm这类可以历史回滚的编译器

本篇搭建记录基于2023年06月06日发布的butterfly 4.9.0,教程可能会滞后,以最新版本为准

一、前期准备

  1. Node.js 官网:让JAVAscript成为与PHP、Python、Perl、Ruby等服务器语言平起平坐的脚本语言
  2. Git 官网:开源分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理
  3. 注册一个GitHub账号,专门找了一篇含报错及解决办法的,注册名、密码、邮箱记好

这个时候可能有小伙伴要说了,这都是啥呢怎么都是汉字组在一起又看不懂了?我没学过JAVAscript,我电脑貌似装过但是不记得了…没关系!本篇从小白讲起!

两个软件安装完之后或不记得有没有,win+R输入cmd打开命令行窗口,依次输入三条命令

node -v
npm -v
git --version

如果和我的一样显示出来版本号,那就是之前安装过,如果没有安装过,去官网下载安装包傻瓜式安装即可(C盘小的同学记得换盘符!)

C:\Users\86158>node -v
v14.15.1

C:\Users\86158>npm -v
6.14.8

C:\Users\86158>git --version
git version 2.34.1.windows.1

接着在命令行中安装Hexo(警告WARN不影响)

npm install hexo-cli -g

同样检查一下安装成功了没有,运行命令会弹出来好多版本号就是成功了

hexo -v

第一次下载git需要配置,任意一个地方右击→Git Brush Here

git config --global user.name GC-ZF  #名称
git config --global user.email 1310446718@qq.com #邮箱

二、配置仓库

2.1 新建仓库

为什么要注册一个GitHub,建一个仓库?我们要利用Github作为服务器去存储我们的内容,以便别人去访问

新建一个仓库,注意为了让别人可以访问到仓库的名字一定一定是注册名.github.io

Hexo博客搭建01

2.2 关联仓库

接下来将Github与电脑进行绑定。每次把文件上传到仓库需要登录,十分麻烦,所以利用ssh就起到一个记住密码的作用,一劳永逸

Hexo博客搭建02

在任意文件夹右击鼠标→Git Bash Here,输完命令连续按三次回车

ssh-keygen -t rsa -C "用户名" -f "id_rsa_github"

Hexo博客搭建03

执行完命令后 C:\Users\用户名\.ssh 下多了俩文件,生成的id_rsa_github.pub以记事本打开,ctrl+A全选并ctrl+C复制文本内容,将公钥添加到github中,Title自定义

Hexo博客搭建04

检查是否绑定成功,注意区分大小写!输入yes弹出Hi 用户名!才算成功

ssh -T git@github.com

Hexo博客搭建05

三、本地博客

现在就要开始制作我们的博客啦!既然博客要放在我们的电脑本地,自己选一个合适的地方新建文件夹,我新建一个Blog,在Blog文件夹中右击鼠标→Git Bash Here,输入(Hexo帮咱们搭好的框架,拿着直接用就行了,关于美化第四点有)

hexo init	#初始化hexo博客

文件夹说明

  • node_modules: 依赖包
  • public:存放生成的页面(由hexo g生成)
  • scaffolds:生成文章的一些模板
  • source:用来存放你的文章
  • themes:主题
  • _config.yml: 博客的配置文件

之后启动服务器,并在浏览器网址输入localhost:4000

hexo s		#启动服务

Hexo博客搭建06

localhost:4000是本地网络,互联网并访问不到,这里我们只是测试一下,ctrl+C关闭本地服务器

四、发布博客到互联网

配置Github仓库

博客根目录\_config.yml(配置文件),打开方式随便一个编译器都可以,最下面修改deploy,注意一定是英文冒号,并且冒号后跟一个空格,repository地址在GitHub中

Hexo博客搭建07

# Deployment
## Docs: https://hexo.io/docs/one-command-deployment
deploy:
type: git
repository: https://github.com/GC-ZF/GC-ZF.github.io.git
branch: main

这个时候需要先安装deploy-git ,也就是部署的命令,这样你才能用命令部署到GitHub

npm install hexo-deployer-git --save

生成网站静态文件到 public 文件夹

hexo g		# 生成页面,hexo generate的缩写

上传本地文件到仓库,如果出现FATAL是网络问题,开个梯子之类

Hexo博客搭建08

hexo d		# 上传本地文件到仓库,hexo deploy的缩写

Hexo博客搭建09

现在我们就可以在任意网络下在浏览器访问用户名.github.io

发布文章

首先使用命令新建.md的文件,两个命令二选一(不支持手动新建)

hexo n "文件名字"	# hexo new "文件名字"

博客根目录\source\_posts下找到新建的文件,发现他已经帮我们写入了一些东西,默认模板修改博客根目录\source\scaffolds\post)

# 我的模板
title: {{ title }}
date: {{ date }}
top_img: 'https://picsum.photos/seed/picsum/1920/942' #文章封面 随机占位图,挺好用的,使用方法picsum.photos官网
cover: 'https://picsum.photos/seed/picsum/470/315' #文章顶部图
tags: #标签
categories: #分类
toc_number: #是否显示目录
updated: #最近更新日期
keywords: #关键字
description: # 文章描述
sticky: # 置顶 值越大优先权越高

写好之后,依次执行

hexo g		#生成页面
hexo d #上传本地文件到仓库

这里小补充一下,因为大部分同学既然有搭博客的想法那应该都知道markdown,没有markdown编辑器的同学,推荐Typora 官方中文站,关于markdown语法网上也大把大把

五、安装并配置Butterfly 主题

第五步可以直接看卷二兔的视频教程 哔哩哔哩,已经足够详细,有些小白可能在读Butterfly的文档时有很多疑惑,以下是我自己CV文档+整理的配置流程

上面一二三四步,终于来到了美化!hexo给咱们写好了一堆框架,给咱们了好多衣服裤子,怎么穿的好看就看咱们怎么搭配了,这里以hexo-theme-butterfly为模板为例子,以下三个链接是官方文档、仓库,咱们直接跟着文档走(至于为什么用这个取决于@超逸学长,我就是看了他的博客才有了搭博客的想法,而且他有一些的魔改步骤,如果没学过html基础,一定要仔仔细细跟着他的魔改走)

更换主题

在Hexo(我之前建的Blog)目录下,右击→Git Brash Here

git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly

修改 博客根目录\_config.yml

theme: butterfly

安装依赖

npm install hexo-renderer-pug hexo-renderer-stylus --save

依次执行,hexo clean hexo g hexo s三件套部署本地,每次改完yml配置文件都需要重新运行

hexo clean  # 清空public文件夹
hexo g # 生成页面
hexo s # 打开本地看下设置是否成功

升级建议

主题升级会覆盖博客根目录\them\butterfly\_config.yml,为了減少升级主题带来的不便,把博客根目录theme\butterfly\_config.yml 复制到 博客根目录 下,重命名为_config.butterfly.yml

设置个人资料

博客根目录\_config.yml

# Site
title: 张时贰 # 标题
subtitle: '小张同学' # 副标题
description: '环转码,热爱敲代码的小张!' # 个签
keywords: 博客,张时贰 # 浏览器搜索关键词
author: 张时贰 # 作者
language: zh-CN # 语言en/zh-CN/zh-TW
timezone: 'Asia/Shanghai' # 时区

标签页

Hexo博客搭建10

为我们的博客文章添加标签页(导航栏的标签按钮)

hexo new page tags 				# 新建标签页

生成source/tags/index.md,title自定义。访问http://localhost:4000/tags/即可看到效果

---
title: 标签页
date: 2022-04-29 18:08:39
type: "tags"
top_img: 'https://picsum.photos/1920/942' # 顶部图
---

分类页

为我们的博客文章添加分类页(导航栏的分类/归档按钮)

hexo new page categories

生成source/categories/index.md,title自定义。访问http://localhost:4000/categories/即可看到效果

---
title: categories
date: 2022-04-29 18:16:23
type: "categories"
top_img: 'https://picsum.photos/1920/942' #封面
---

友情连接

添加友情链接

hexo new page link

生成source/link/index.md,title自定义,访问http://localhost:4000/link/即可看到效果

---
title: link
date: 2022-04-29 18:22:47
type: "link"
top_img: 'https://picsum.photos/1920/942' #封面
---

在Hexo博客目录中的source/_data(如果没有 _data 文件夹,请自行创建),创建一个文件link.yml,或者直接写到source/link/index.md

- class_name: 友情链接
class_desc: 那些人,那些事
link_list:
- name: Hexo
link: https://hexo.io/zh-tw/
avatar: https://d33wubrfki0l68.cloudfront.net/6657ba50e702d84afb32fe846bed54fba1a77add/827ae/logo.svg
descr: 快速、简单且强大的网誌框架

- class_name: 网站
class_desc: 值得推荐的网站
link_list:
- name: Youtube
link: https://www.youtube.com/
avatar: https://i.loli.net/2020/05/14/9ZkGg8v3azHJfM1.png
descr: 视频网站
- name: Weibo
link: https://www.weibo.com/
avatar: https://i.loli.net/2020/05/14/TLJBum386vcnI1P.png
descr: 中国最大社交分享平台
- name: Twitter
link: https://twitter.com/
avatar: https://i.loli.net/2020/05/14/5VyHPQqR6LWF39a.png
descr: 社交分享平台

主题支持友情链接随机排序,只需要在顶部 front-matter 添加 random: true

404

修改主题配置文件_config.butterfly.yml,开启404界面,同样访问http://localhost:4000/404

# A simple 404 page
error_404:
enable: true
subtitle: '小张的页面丢啦' # 提示文字
background:

替换文章中无法显示的图片

# Replace Broken Images (替換無法顯示的圖片)
error_img:
flink: /Hexo_img/friend_404.gif # 友链头像
post_page: /Hexo_img/404.jpg # 文章页图片

以下是Butterfly 安裝文檔(三) 主題配置-1 | Butterfly

导航菜单

修改主题配置文件_config.butterfly.yml,先后顺序、中文命名自由设置

格式:/路径/ || 图标,图标可留空

menu:
主页: / || fas fa-home
阅读排行: /hot-article/ || fa-solid fa-book-bookmark
文章||fa-solid fa-pencil:
时间轴: /archives/ || fas fa-archive
标签: /tags/ || fas fa-tags
分类: /categories/ || fas fa-folder-open
友链||fas fa-list:
友人帐: /link/ || fas fa-link
朋友圈: /fcircle/ || fa-solid fa-user-group
我的||fa-solid fa-circle-user:
关于&留言: /about/ || fas fa-heart
备忘录: /talk/ || fa-solid fa-walkie-talkie
建站史: /history/ || fa-regular fa-clock
摸鱼: https://rv.zhsher.cn/Game_box/game/ || fa-solid fa-fish-fins
云盘: https://icloud.zhsher.cn || fa-solid fa-cloud
站点监控: https://status.zhsher.cn/status/friend || fa-fw fa fa-heartbeat
# 工具: /navigate/ || fa-solid fa-toolbox
虫洞: https://www.foreverblog.cn/go.html ||fa-solid fa-paper-plane

额外页面,以建站史为例,使用命令hexo new page history ,编写source/history/index.md

title: history	# 必填
date: 2022-05-01 15:56:57 # 必填
toc: true # 选填,显示一下目录
top_img: 'https://picsum.photos/1920/942' # 选填,顶部图片

默认子目录是展开的,如果你想要隐藏,在子目录里添加 hide

List||fas fa-list||hide:
Music: /music/ || fas fa-music
Movie: /movies/ || fas fa-video

导航栏设置

修改主题配置文件_config.butterfly.yml

nav:
logo: #image 网站logo
display_title: true # 是否显示网站标题
fixed: false # fixed navigation bar 导航栏是否常驻

代码框样式

修改主题配置文件_config.butterfly.yml

# Code Blocks (代碼相關)
# --------------------------------------

highlight_theme: mac light # darker / pale night / light / ocean / mac / mac light / false
highlight_copy: true # copy button 代码复制按钮
highlight_lang: true # show the code language 展示代码语言
highlight_shrink: false # 代码展开设置 true: 不展开需要点击 > / false: 展开过长时需要点击> | none: 不显示>
highlight_height_limit: 200 # unit: px 代码框高度 false时展开全部
code_word_wrap: true # 代码自动换行,false时不换行,代码块下方会有滚动条

code_word_wrap: true时需要额外配置

# 如果使用 highlight 渲染,在_config.yml中line_number改成false
highlight:
enable: true
line_number: false # <- 改这里
auto_detect: false
tab_replace:

# 如果使用 prismjs 渲染,在_config.yml中line_number改成false
prismjs:
enable: false
preprocess: true
line_number: false # <- 改这里
tab_replace: ''

社交图标

修改主题配置文件_config.butterfly.yml,图标查找矢量图标 Icons | Font Awesome,QQ移动端无法跳转,需要在官方开通服务

格式:图标名:url || 描述性文字 || color

# social settings (社交圖標設置)
# formal:
# icon: link || the description
social:
fab fa-github: https://github.com/GC-ZF || Github
fa-solid fa-c: https://blog.csdn.net/qq_49488584 || CSDN
fab fa-qq: http://wpa.qq.com/msgrd?v=3&uin=1310446718&site=qq&menu=yes || QQ
fas fa-envelope-open-text: mailto:1310446718@qq.com || Email

主页文章节选(自动节选和文章页description)

description在front-matter(即自动生成时MD时前面的内容)

  • description: 只显示description
  • both: 优先选择description,如果没有配置description,则显示自动节选的内容
  • auto_excerpt:只显示自动节选
  • false: 不显示文章内容

修改主题配置文件_config.butterfly.yml

index_post_content:
method: 2 # 模式2both
length: 500 # 节选长度

img

顶部图

如果不要显示顶部图,可直接配置 disable_top_img: true

图片存放位置博客根目录/source/Hexo_img,修改主题配置文件_config.butterfly.yml

主页封面图片

# The banner image of home page
index_img: /Hexo_img/background.png

文章详情页顶部图片,当没有在front-matter设置top_imgcover的情况下会显示该图

# If the banner of page not setting, it will show the top_img
default_top_img: /Hexo_img/default_top_img.jpeg

归档页顶部图片

# The banner image of archive page
archive_img: https://picsum.photos/1920/942

tag页顶部图

# If the banner of tag page not setting, it will show the top_img
# note: tag page, not tags page (子標签頁面的 top_img)
tag_img: https://picsum.photos/470/315

category页顶部图

#category页
# If the banner of category page not setting, it will show the top_img
# note: category page, not categories page (子分類頁面的 top_img)
category_img: https://picsum.photos/470/315

tag_per_imgcategory_per_img 是 3.2.0 新增的内容,可对 tag 和 category 进行单独的配置

并不推荐为每个 tag 和每个 category 都配置不同的顶部图,因为配置太多会拖慢生成速度

tag_per_img:
aplayer: https://xxxxxx.png
android: ddddddd.png

category_per_img:
随想: hdhdh.png
推荐: ddjdjdjd.png

文章封面

文章的markdown文档上,在Front-matter添加cover,并填上要显示的图片地址

如果不配置cover,可以设置显示默认的cover

如果不想在首页显示cover,可以设置为false,修改主题配置文件_config.butterfly.yml

cover:
# 是否显示文章封面
index_enable: true
aside_enable: true
archives_enable: true
# 封面显示的位置
# 三个值可配置 left , right , both
position: both
# 当没有设置cover时,默认的封面显示
#多个默认封面,随机显示一个 可配置图片链接/顔色/渐变色
default_cover:
- https://picsum.photos/id/1018/470/315
- https://picsum.photos/id/1044/470/315
- https://picsum.photos/id/1056/470/315

文章页相关配置

文章meta显示

修改主题配置文件_config.butterfly.yml,这个选项是用来显示文章的相关信息的

post_meta:
page:
date_type: both # created or updated or both 主页文章日期是创建日或者更新日或都显示
date_format: data # date/relative 显示日期还是相对日期
categories: true # true or false 主页是否显示分类
tags: false # true or false 主页是否显示标签
label: true # true or false 显示描述性文字
post:
date_type: both # created or updated or both 文章页日期是创建日或者更新日或都显示
date_format: date # date/relative 显示日期还是相对日期
categories: true # true or false 文章页是否显示分类
tags: true # true or false 文章页是否显示标签
label: true # true or false 显示描述性文字

文章版权

修改主题配置文件_config.butterfly.yml,博客文章底部展示文章版权和许可协议

post_copyright:
enable: true
decode: false
license: CC BY-NC-SA 4.0
license_url: https://creativecommons.org/licenses/by-nc-sa/4.0/

从3.0.0开始,支持对单独文章设置版权信息,可以在文章Front-matter单独设置

copyright_author: xxxx
copyright_author_href: https://xxxxxx.com
copyright_url: https://xxxxxx.com
copyright_info: 此文章版权归xxxxx所有,如有转载,请註明来自原作者

文章打赏

修改主题配置文件_config.butterfly.yml,给文章结尾设置打赏按钮

# Sponsor/reward
reward:
enable: true
QR_code:
- img: /Hexo_img/wechat.png
link:
text: 微信
- img: /Hexo_img/alipay.jpg
link:
text: 支付宝

TOC目录

修改主题配置文件_config.butterfly.yml,在文章页会有一个目录,用于显示TOC

toc:
post: true # 文章是否显示TOC
page: false # 普通页面是否显示TOC(自己新建的"友链""建站史"都算普通页面,只有文章才显示目录)
number: true # 是否显示章节数
expand: false # 是否展开TOC
style_simple: false # for post ,true文章页仅展示目录
scroll_percent: true # 是否显示滚动进度百分比

为特定文章配置

在文章md文件的头部,加入toc_number是否显示章节数和toc是否显示目录,并配置true或者false即可。

主题会优先判断文章Markdown的Front-matter是否有配置,如有,则以Front-matter的配置为准。否则,以主题配置文件中的配置为准

相关文章

修改主题配置文件_config.butterfly.yml,相关文章推荐的原理是根据文章tags的比重来推荐

related_post:
enable: true
limit: 6 # 显示推荐文章数目
date_type: created # or created or updated 文章日期显示创建日或者更新日

文章锚点

开启文章锚点后,当你在文章页进行滚动时,浏览器链接会根据标题ID进行替换
(注意: 每替换一次,会留下一个历史记录。所以如果一篇文章有很多锚点的话,网页的历史记录会很多)

修改主题配置文件_config.butterfly.yml,默认false

# anchor
anchor:
button:
enable: false
always_show: false
icon: # the unicode value of Font Awesome icon, such as '\3423'
auto_update: false # when you scroll in post, the URL will update according to header id.

文章过期提醒

可设置是否显示文章过期提醒,以更新时间为基准

  • limit_day: 距离更新时间多少天才显示文章过期提醒
  • message_prev : 天数之前的文字
  • message_next:天数之后的文字

修改主题配置文件_config.butterfly.yml

# Displays outdated notice for a post (文章过期提醒)
noticeOutdate:
enable: false # true开
style: flat # style: simple/flat
limit_day: 365 # When will it be shown #限制天数
position: top # position: top/bottom #文章顶部/底部
message_prev: It has been
message_next: days since the last update, the content of the article may be outdated.

文章编辑按钮

修改主题配置文件_config.butterfly.yml,在文章标题旁边显示一个编辑按钮,点击会跳转到对应的链接去

# Post edit
# Easily browse and edit blog source code online.
post_edit:
enable: false
# url: https://github.com/user-name/repo-name/edit/branch-name/subdirectory-name/
# For example: https://github.com/GC-ZF/Blog/edit/main/source/
url:

文章分页按钮

修改主题配置文件_config.butterfly.yml,设置分页的逻辑false时不显示分页

# post_pagination (分页)
# value: 1 || 2 || false
# 1: The 'next post' will link to old post
# 2: The 'next post' will link to new post
# false: disable pagination
post_pagination: 1 # 下一篇是旧文

头像

修改主题配置文件_config.butterfly.yml

avatar:
img: https://q1.qlogo.cn/g?b=qq&nk=1310446718&s=5 # 图片路径
effect: false # ture头像会一直转圈,false鼠标移上去会转

图片描述

可开启图片Figcaption描述文字显示,优先显示图片的 title 属性,然后是 alt 属性

修改主题配置文件_config.butterfly.yml,默认关闭

photofigcaption: false

复制相关配置

可配置网站是否可以复制、复制的内容是否添加版权信息

  • enable:是否开启网站复制权限
  • copyright:复制的内容后面加上版权信息
  • enable:是否开启复制版权信息添加
  • limit_count:字数限制,当复制文字大于这个字数限制时,将在复制的内容后面加上版权信息

修改主题配置文件_config.butterfly.yml

# copy settings
# copyright: Add the copyright information after copied content (複制的內容後面加上版權信息)
copy:
enable: true
copyright:
enable: true
limit_count: 50

Footer设置

博客年份

since是一个来展示你站点起始时间的选项。它位于页面的最底部

修改主题配置文件_config.butterfly.yml

# Footer Settings
# --------------------------------------
footer:
owner:
enable: true
since: 2022
custom_text: <div>满地都是六便士 我想抬头看月亮</div><div><a onclick="window.open('url')" class="footer-a">备:没服务器...</a></div>
copyright: true # Copyright of theme and framework

页脚自定义脚本(备案信息)

custom_text是一个给你用来在页脚自定义文本的选项。通常你可以在这里写声明文本等。支持 HTML。

修改主题配置文件_config.butterfly.yml

custom_text: Hi, welcome to my <a href="https://butterfly.js.org/">blog</a>!

对于部分人需要写 ICP 的,也可以写在 custom_text

custom_text: <a href="icp链接"><img class="icp-icon" src="icp图片"><span>备案号:xxxxxx</span></a>

右下角按钮

简繁转换

简体繁体互换,右下角会有简繁转换按钮

修改主题配置文件_config.butterfly.yml,默认关闭

translate:
enable: true
# 默认按钮显示文字(网站是简体,应设置为'default: 繁')
default:
#网站默认语言,1: 繁体中文, 2: 简体中文
defaultEncoding: 1
#延迟时间,若不在前, 要设定延迟翻译时间, 如100表示100ms,默认为0
translateDelay: 0
#当文字是简体时,按钮显示的文字
msgToTraditionalChinese: "繁"
#当文字是繁体时,按钮显示的文字
msgToSimplifiedChinese: "简"

夜间模式

右下角会有夜间模式按钮

修改主题配置文件_config.butterfly.yml,默认开启

# dark mode
darkmode:
enable: true
# Toggle Button to switch dark/light mode
button: true
# Switch dark/light mode automatically (自動切換 dark mode和 light mode)
# autoChangeMode: 1 Following System Settings, if the system doesn't support dark mode, it will switch dark mode between 6 pm to 6 am
# autoChangeMode: 2 Switch dark mode between 6 pm to 6 am
# autoChangeMode: false
autoChangeMode: 2
# Set the light mode time. The value is between 0 and 24. If not set, the default value is 6 and 18
start: # 8
end: # 22

V2.0.0 开始增加一个选项,可开启自动切换light mode 和 dark mode

  • autoChangeMode: 1 跟随系统而变化,不支持的浏览器/系统将按照时间晚上6点到早上6点之间切换为 dark mode

  • autoChangeMode: 2 只按照时间 晚上6点到早上6点之间切换为 dark mode,其余时间为light mode

  • autoChangeMode: false 取消自动切换

阅读模式

阅读模式下会去掉除文章外的内容,避免干扰阅读。只会出现在文章页面,右下角会有阅读模式按钮

修改主题配置文件_config.butterfly.yml,默认开启

readmode: true

滚动状态百分比

修改主题配置文件_config.butterfly.yml,默认开启

# show scroll percent in scroll-to-top button
rightside_scroll_percent: true

rightside_scroll_percent

按钮排序

修改主题配置文件_config.butterfly.yml,默认即可

# Don't modify the following settings unless you know how they work (非必要请不要修改 )
# Choose: readmode,translate,darkmode,hideAside,toc,chat,comment
# Don't repeat 不要重复
rightside_item_order:
enable: false
hide: # readmode,translate,darkmode,hideAside
show: # toc,chat,comment

侧边栏设置

侧边排版

可自行决定哪个项目需要显示,可决定位置,也可以设置不显示侧边栏

  • left侧边栏靠左边
  • right侧边栏靠右边
  • hide隐藏所有
  • display单独设置显示哪个

修改主题配置文件_config.butterfly.yml

aside:
enable: true
hide: false
button: true
mobile: true # display on mobile
position: right # left or right
display: # 单独设置
archive: true
tag: true
category: true
card_author: # 作者信息栏
enable: true
description:
button:
enable: true
icon: fab fa-github
text: Follow Me
link: https://github.com/GC-ZF
card_announcement: # 公告栏
enable: true
content: 在没有经济独立的前提下,一切自由都是诱拐,一切个性都是欺骗
card_recent_post: # 最近文章栏
enable: true
limit: 5 # if set 0 will show all
sort: date # date or updated
sort_order: 4 # Don't modify the setting unless you know how it works
card_categories: # 文章分类栏
enable: true
limit: 8 # if set 0 will show all
expand: none # none/true/false
sort_order: 5 # Don't modify the setting unless you know how it works
card_tags: # 文章标签栏
enable: true
limit: 40 # if set 0 will show all
color: false
orderby: random # Order of tags, random/name/length
order: 1 # Sort of order. 1, asc for ascending; -1, desc for descending
sort_order: 6 # Don't modify the setting unless you know how it works
card_archives: # 文章归档栏
enable: true
type: monthly # yearly or monthly
format: MMMM YYYY # eg: YYYY年MM月
order: -1 # Sort of order. 1, asc for ascending; -1, desc for descending
limit: 8 # if set 0 will show all
sort_order: 7 # Don't modify the setting unless you know how it works
card_webinfo: # 站点信息栏
enable: true
post_count: true
last_push_date: true
sort_order: 8 # Don't modify the setting unless you know how it works

访问人数统计

修改主题配置文件_config.butterfly.yml,默认全开。使用不蒜子统计

busuanzi:
site_uv: true
site_pv: true
page_pv: true

运行时间

网页已运行时间

修改主题配置文件_config.butterfly.yml,默认false

runtimeshow:
enable: true
publish_date: 5/1/2022 00:00:00
##网页开通时间
#格式: 月/日/年 时间
#也可以写成 年/月/日 时间

最新评论

最新评论只会在刷新时才会去读取,并不会实时变化

由于 API 有 访问次数限制,为了避免调用太多,主题默认存取期限为 10 分钟。也就是说,调用后资料会存在 localStorage 里,10分钟内刷新网站只会去 localStorage 读取资料。 10 分钟期限一过,刷新页面时才会去调取 API 读取新的数据。( 3.6.0 新增了 storage 配置,可自行配置缓存时间)

在侧边栏显示最新评论板块

修改主题配置文件_config.butterfly.yml,默认关闭

  • limit:显示数量
  • storage:设置缓存时间
  • avatar:是否显示头像
# Aside widget - Newest Comments
newest_comments:
enable: true
sort_order: 3 # Don't modify the setting unless you know how it works
limit: 6
storage: 10 # unit: mins, save data to localStorage
avatar: false # 头像

自定义添加栏目

自定义侧边栏 | Butterfly:在后续魔改中会用到,例如访客统计侧边栏

标签外挂

详见官方文档


以下来自Butterfly 安裝文檔(四) 主題配置-2 | Butterfly

评论

Valine一部分功能(表情库、邮件提醒等等)需要借助其它第三方。Valine配置Leancloud有个小坑,如果认证支付宝显示当前设备不支持刷脸,支付宝退出重登就好

改为livere(韩国)配置很快,大概五分钟就好,支持表情、图片,但是不能自定义评论框的样式,必须登录QQ等才能发表评论

2022.5.1 最后的倔强,还是喜欢免登录,更改评论为tiwkoo

小坑:MongoDB数据库配置时,连接字符串密码,mongodb+srv://xxxxxx:<password>@cluster0.i7omd.mongodb.net/myFirstDatabase?retryWrites=true&w=majority,替换密码时尖括号< >需要去掉

数据导出

2022.8.5 墙裂推荐twikoo。作者是95后小哥哥,人巨好,随时回复网友的各种疑难杂症Issues · imaegoo/twikoo。另外,熟读中文文档后,官网已有详细的特色简介,着重点名几个深得我心的功能!

  • 支持Valine、Disqus、Artalk、Twikoo数据迁移
  • 评论人工审核
  • 支持私有部署
  • 支持自建的兰空图床(本来是没有的,小哥专门加的)
  • 可以修改评论信息(参考下文)

关于数据迁移,我之前是部署在MongoDB,但是如果有自己服务器的话,评论延迟会快一点,参考作者教程评论数据导出教程 - iMaeGoo’s Blog,有一点点踩坑的地方,总结一下

根据作者说明,利用 MongoDB 数据库工具运行导出命令

mongoexport --uri 这里换成刚才复制的地址 --collection comment --type json --out twikoo-comments.json

可能出现的错误(耗费三小时与@二花,bing、谷歌、stack overflow、csdn,win、Mac、Ubuntu,轮番战斗!)

mongoexport --uri 这里换成刚才复制的地址 --collection comment --forceTableScan --type json --out twikoo-comments.json

Hexo博客搭建28

微软解决办法

连接有三种方法,用最下面有一个GUI工具

Hexo博客搭建29

没有工具可以先选择I do don have MongoDB Compass,或者官网找MongoDB Compass安装。打开软件连接数据库,uri默认1.12 or later,如果出现queryTxt ETIMEOUT超时,参考官网Error: queryTxt ETIMEOUT - MongoDB Developer Community Forums,换用1.11 or later

Hexo博客搭建30

连接数据库后,可以通过工具对评论修改、数据导出导入,如果忘记密码删除configADMIN_PASS:"xxxx",私有部署在文件夹db.json.1内删除ADMIN_PASS:"xxxx",之后重新打开博客设置。Vercel部署+Mongo Compass辅助或私有部署,四舍五入,也有了类似Typecho后台评论管理了嘿嘿

Hexo博客搭建31

数据备份

小tips:网站数据备份相当重要,宝塔可以直接对站点备份,但评论备份无法实现,服务器自带python环境,所以我做了一个python代码,利用crontab -e或宝塔面板中的计划任务定时备份,在目录下backuplog.txt会记录每一次备份日志

2022.09.27 新增无服务器备份方案:Twikoo评论定时备份方案 | 张时贰

Vercel部署,将代码存放在MongoDB 数据库工具同级路径下,按需修改30行(清理备份)、35行(MONGODB_URI)

"""
@Author:张时贰
@Date:2022年08月08日
@CSDN:张时贰
@Blog:zhsher.cn
"""
import os
from datetime import datetime
import sys


class Logger ( object ):
def __init__(self, fileN="Default.log"):
self.terminal = sys.stdout
self.log = open ( fileN, "a" )

def write(self, message):
self.terminal.write ( message )
self.log.write ( message )

def flush(self):
pass


sys.stdout = Logger ( "backuplog.txt" ) # 输出日志
print ( "--------------------------------------------------------------\n" )
now_time = datetime.now () # 当前时间
now_time_day = now_time.day # 日
data = f"{now_time.year}{now_time.month}{now_time.day}日"
delete_day = [ 15, 30 ] # 每月15、30号清空备份
if now_time_day in delete_day:
os.system ( 'rm *.json -f' ) # 删除所有json
print ( data + " 清空备份文件" )
# os.system ( 'rm backuplog.txt.txt -f' ) # 删除日志
MONGODB_URI = 'mongodb+srv://xxx:xxx@xxxxxxx/myFirstDatabase'
commond = 'mongoexport --uri ' + f'{MONGODB_URI}' + ' --collection comment --forceTableScan --type json --out ' + f"{now_time.year}{now_time.month}{now_time.day}日.json"
code = os.system ( commond )
if code == 0:
print ( data + " 备份成功" )
else:
print ( data + " 备份失败,请检查python文件中MONGODB_URI值是否正确" )
print ()

私有部署,代码存放位置任意,修改35行(原始路径)、36行(备份路径),都用绝对路径,但不要与私有部署在相同路径下,因为定时清理会清掉所有json文件

"""
@Author:张时贰
@Date:2022年08月08日
@CSDN:张时贰
@Blog:zhsher.cn
"""
import os
from datetime import datetime
import sys


class Logger ( object ):
def __init__(self, fileN="Default.log"):
self.terminal = sys.stdout
self.log = open ( fileN, "a" )

def write(self, message):
self.terminal.write ( message )
self.log.write ( message )

def flush(self):
pass


sys.stdout = Logger ( "backuplog.txt" ) # 输出日志
print ( "--------------------------------------------------------------\n" )
now_time = datetime.now () # 当前时间
now_time_day = now_time.day # 日
data = f"{now_time.year}{now_time.month}{now_time.day}日"
delete_day = [ 15, 30 ] # 每月15、30号清空备份
if now_time_day in delete_day:
os.system ( 'rm *.json -f' ) # 删除所有json
print ( data + " 清空备份文件" )
# os.system ( 'rm backuplog.txt.txt -f' ) # 删除日志
init_path='/xxxxx/bin/db.json.1'
backup_path='/xxxxx/bin/backup/'
init_path='"'+init_path+'"'
backup_path='"'+backup_path+f"/{now_time.year}{now_time.month}{now_time.day}日.json"+'"'
commond = 'cp '+init_path+" "+backup_path
code = os.system ( commond )
if code == 0:
print ( data + " 备份成功" )
else:
print ( data + " 备份失败,请检查python文件中init_path和backup_path是否正确或备份路径是否有读写权限" )
print ()

在线聊天

感觉也用不到…,想弄看文档吧Butterfly 安裝文檔(四) 主題配置-2 | Butterfly

分享

官方提供三种格式,本博客使用的默认服务商sharejs

sharejs:
enable: true
sites: facebook,twitter,wechat,weibo,qq #想要显示的内容

本地搜索

安装依赖

npm install hexo-generator-search --save

修改主题配置文件_config.butterfly.yml,默认关闭,preload代表预加载

# Local search
local_search:
enable: true
preload: true
CDN:

广告

影响阅读体验,不加!

数学

主题自带足矣,第三方插件:Butterfly 安裝文檔(四) 主題配置-2 | Butterfly

美化

自定义主题色

可以修改大部分UI颜色,默认全注释不修改,我使用的默认

修改主题配置文件_config.butterfly.yml颜色值必须被双引号包裹,就像”#000”而不是#000。否则将会在构建的时候报错!

theme_color:
enable: true
main: "#49B1F5"
paginator: "#00c4b6"
button_hover: "#FF7242"
text_selection: "#00c4b6"
link_color: "#99a9bf"
meta_color: "#858585"
hr_color: "#A4D8FA"
code_foreground: "#F47466"
code_background: "rgba(27, 31, 35, .05)"
toc_color: "#00c4b6"
blockquote_padding_color: "#49b1f5"
blockquote_background_color: "#49b1f5"
scrollbar_color: "#49b1f5"

网站背景

默认显示白色,可设置图片或者颜色,修改主题配置文件_config.butterfly.yml

# 图片格式 url(http://xxxxxx.com/xxx.jpg)
# 颜色(HEX值/RGB值/颜色单词/渐变色)
# 留空 不显示背景
background: url(/Hexo_img/config/background.png)

background:’#49B202’

footer背景

修改主题配置文件_config.butterfly.yml

  • 留空/false: 显示默认的颜色
  • img链接:图片的链接,显示所配置的图片
    颜色(HEX值 - #0000FF,RGB值 - rgb(0,0,255),颜色单词 - orange,渐变色 - linear-gradient( 135deg, #E2B0FF 10%, #9F44D3 100%))
  • true:显示跟 top_img 一样

小tip,用rgba(255,255,255,0)使页脚透明

# footer是否显示图片背景(与top_img一致)
footer_bg: true

打字效果

修改主题配置文件_config.butterfly.yml

# Typewriter Effect (打字效果)
# https://github.com/disjukr/activate-power-mode
activate_power_mode:
enable: true
colorful: true # open particle animation (冒光特效)
shake: true # open shake (抖动特效)
mobile: false

背景特效

修改主题配置文件_config.butterfly.yml,三选一

# Background effects (背景特效)
# --------------------------------------

# canvas_ribbon (静止彩带)
# See: https://github.com/hustcc/ribbon.js
canvas_ribbon:
enable: false # PC端
size: 150
alpha: 0.6
zIndex: -1
click_to_change: false
mobile: false # 移动端

# Fluttering Ribbon (动态彩带)
canvas_fluttering_ribbon:
enable: false # PC端
mobile: false # 移动端

#星空特效
# canvas_nest
# https://github.com/hustcc/canvas-nest.js
canvas_nest:
enable: true # PC端
color: '0,0,255' #color of lines, default: '0,0,0'; RGB values: (R,G,B).(note: use ',' to separate.)
opacity: 0.7 # the opacity of line (0~1), default: 0.5.
zIndex: -1 # z-index property of the background, default: -1.
count: 99 # the number of lines, default: 99.
mobile: false # 移动端

鼠标点击效果

修改主题配置文件_config.butterfly.yml,三选一

# Mouse click effects: fireworks (鼠標點擊效果: 煙火特效)
fireworks:
enable: false # PC端
zIndex: 9999 # -1 or 9999
mobile: false # 移动端

# Mouse click effects: Heart symbol (鼠標點擊效果: 愛心)
click_heart:
enable: false # PC端
mobile: false # 移动端

# Mouse click effects: words (鼠標點擊效果: 文字)
ClickShowText:
enable: true # PC端
text:
-
-
-
-
-
-
fontSize: 15px
random: false
mobile: false # 移动端

页面美化

会改变ol、ul、h1-h5的样式

field配置生效的区域

  • post 只在文章页生效
  • site 在全站生效

修改主题配置文件_config.butterfly.yml

# 美化页面显示
beautify:
enable: true
field: site # site/post
title-prefix-icon: '\f0c1'
title-prefix-icon-color: "#F47466"

title-prefix-icon填写的是开始使用 – Font Awesome 中文网的icon的Unicode数

未开启美化

开启美化

自定义字体和字体大小(未设置)

全局字体

可自行设置字体的font-family,如不需要配置,请留空

修改主题配置文件_config.butterfly.yml

# Global font settings
# Don't modify the following settings unless you know how they work (非必要不要修改)
font:
global-font-size:
code-font-size:
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Lato, Roboto, "PingFang SC", "Microsoft JhengHei", "Microsoft YaHei", sans-serif
code-font-family: consolas, Menlo, "PingFang SC", "Microsoft JhengHei", "Microsoft YaHei", sans-serif
blog标题字体

可自行设置字体的font-family,如不需要配置,请留空。如不需要使用网络字体,只需要把font_link留空就行

修改主题配置文件_config.butterfly.yml

# Font settings for the site title and site subtitle
# 左上角网站名字 主页居中网站名字
blog_title_font:
font_link: https://fonts.googleapis.com/css?family=Titillium+Web&display=swap
font-family: Titillium Web, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft JhengHei', 'Microsoft YaHei', sans-serif

网站副标题

修改主题配置文件_config.butterfly.yml,可设置主页中显示的网站副标题或者喜欢的座右铭,将enable设置为true开启,默认关闭

# the subtitle on homepage (主頁subtitle)
subtitle:
enable: true
# Typewriter Effect (打字效果)
effect: true
# Customize typed.js (配置typed.js)
# https://github.com/mattboldt/typed.js/#customization
typed_option:
# source 調用第三方服務
# source: false 關閉調用
# source: 1 調用一言網的一句話(簡體) https://hitokoto.cn/
# source: 2 調用一句網(簡體) https://yijuzhan.com/
# source: 3 調用今日詩詞(簡體) https://www.jinrishici.com/
# subtitle 會先顯示 source , 再顯示 sub 的內容
source: false
# 如果關閉打字效果,subtitle 只會顯示 sub 的第一行文字
sub:
- 劝君莫惜金缕衣,劝君惜取少年时
- 花开堪折直须折,莫待无花空折枝
- 出自金缕衣

修改副标题字体样式,位置\themes\butterfly\source\css\_layout\head.styl,43行

#site-subtitle
color: var(--white) //此处修改为白色
font-size: 1.05em // 字体大小
+minWidth768()
font-size: 1.40em // 字体大小

主页top_img大小

默认的显示为全屏。site-info的区域会居中显示

注意:index_top_img_height的值不能使用百分比,2个都不填的话,会使用默认值

修改主题配置文件_config.butterfly.yml

# 主页设置
# 默认top_img全屏,site_info在中间
# 使用默认, 都无需填写(建议默认)
index_site_info_top: # 主页标题距离顶部距离 例如 300px/300em/300rem/10%
index_top_img_height: #主页top_img高度 例如 300px/300em/300rem 不能使用百分比

页面加载动画preloader

当进入网页时,因为加载速度的问题,可能会导致top_img图片出现断层显示,或者网页加载不全而出现等待时间,开启preloader后,会显示加载动画,等页面加载完,加载动画会消失

自定义动画参考学长Hexo 添加加载动画 | 超逸の博客

修改主题配置文件_config.butterfly.yml

# 加载动画 Loading Animation
preloader:
enable: false
# source
# 1. fullpage-loading
# 2. pace (progress bar)
source: 1
# pace theme (see https://codebyzach.github.io/pace/)
pace_css_url:

PWA(未配置)

渐进式增强 Web 应用,访客在安装插件Lighthouse后可离线缓存博客内容,用处不大

字数统计

安装

npm install hexo-wordcount --save

修改主题配置文件_config.butterfly.yml

# wordcount (字數統計)
wordcount:
enable: true
post_wordcount: true
min2read: true
total_wordcount: true

图片大图查看

修改主题配置文件_config.butterfly.yml,二选一,默认第二个

# Lightbox (圖片大圖查看模式)
# --------------------------------------
# You can only choose one, or neither (只能選擇一個 或者 兩個都不選)

# medium-zoom
# https://github.com/francoischalifour/medium-zoom
medium_zoom: false

# fancybox
# http://fancyapps.com/fancybox/3/
fancybox: true

Snackbar弹窗

修改主题配置文件_config.butterfly.yml

# Snackbar (Toast Notification 彈窗)
# https://github.com/polonel/SnackBar
# position 彈窗位置
# 可選 top-left / top-center / top-right / bottom-left / bottom-center / bottom-right
snackbar:
enable: true
position: top-right
bg_light: '#49b1f5' # The background color of Toast Notification in light mode
bg_dark: '#1f1f1f' # The background color of Toast Notification in dark mode

其它配置

CSS前缀

弊端大,跳过

Open Graph

在 head 里增加一些 meta 资料,例如缩略图、标题、时间等等。当你分享网页到一些平台时,平台会读取 Open Graph 的内容,展示缩略图,标题等等信息

修改主题配置文件_config.butterfly.yml

# Open graph meta tags
# https://developers.facebook.com/docs/sharing/webmasters/
Open_Graph_meta:
enable: true
option:
# twitter_card:
# twitter_image:
# twitter_id:
# twitter_site:
# google_plus:
# fb_admins:
# fb_app_id:

Instantpage

鼠标悬停到链接上超过 65 毫秒时,Instantpage 会对该链接进行预加载,可以提升访问速度,默认关闭

修改主题配置文件_config.butterfly.yml

# https://instant.page/
# prefetch (预加载)
instantpage: true

Pangu

自动在网页中所有的中文字和半形的英文、数字、符号之间插入空白。

修改主题配置文件_config.butterfly.yml

# https://github.com/vinta/pangu.js
# Insert a space between Chinese character and English character (中英文之間添加空格)
pangu:
enable: true
field: site # site/post

Pjax

当用户点击链接,通过ajax更新页面需要变化的部分,然后使用HTML5的pushState修改浏览器的URL地址,这样可以不用重复加载相同的资源(css/js), 从而提升网页的加载速度

修改主题配置文件_config.butterfly.yml

# Pjax [Beta]
# It may contain bugs and unstable, give feedback when you find the bugs.
# https://github.com/MoOx/pjax
pjax:
enable: true
exclude:
- /music/
- /no-pjax/

对于一些第三方插件,有些并不支持 pjax 。可以把网页加入到 exclude 里,这个网页会被 pjax 排除在外。点击该网页会重新加载网站,使用pjax后,一些自己DIY的js可能会无效

Inject自定义CSS JS

修改主题配置文件_config.butterfly.yml,后面会具体应用实践

inject:
head:
- <link rel="stylesheet" href="css/xxx.css">
bottom:
- <script src="js/xxx.js"></script>

以下来自Butterfly 安裝文檔(六) 進階教程 | Butterfly,自定义代码配色、自定义侧边栏未记录

音乐

文档:Butterfly添加全局吸底Aplayer教程 | Butterfly

插件:hexo-tag-aplayer | Github

md文件内可以通过html的方式直接引入

<div class="aplayer" data-id="000PeZCQ1i4XVs" data-server="tencent" data-type="artist" data-mutex="true" data-preload="auto" data-theme="#3F51B5"></div>

也可以通过插件写进文章中,主题会自动渲染为html格式,见仁见智,选自己喜欢的就行

安装

npm install --save hexo-tag-aplayer

修改配置文件 _config.yml ,新增配置,之后在需要使用音乐的文章Front-matter添加aplayer: true

aplayer:
meting: true
asset_inject: false

更多示例参考插件文档

<!-- 简单示例 (id, server, type)  -->
{% meting "60198" "netease" "playlist" %}

<!-- 进阶示例 -->
{% meting "60198" "netease" "playlist" "autoplay" "mutex:false" "listmaxheight:340px" "preload:none" "theme:#ad7a86"%}

电影

文档:butterfly-plugins/hexo-butterfly-douban | Github

说说

本博客目前使用Leancloud国内部署+Artitalk.js

无服务器首推Heo哥的静态,免部署好实现,之后KK Api可以动态发文。有服务器首推Memos。见仁见智选合适自己的就好

全局吸底播放器

Butterfly添加全局吸底Aplayer教程 | Butterfly

修改主题配置文件_config.butterfly.yml,开启aplayerInject

# Inject the css and script (aplayer/meting)
aplayerInject:
enable: true
per_page: true

插入 Aplayer html,例如网易云,找一个歌单点击分享,复制链接,把网址里的id换一下(其它平台data-server参考官方文档)

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
bottom:
# - <script src="xxxx"></script>
- <div class="aplayer no-destroy" data-id="60198" data-server="netease" data-type="playlist" data-fixed="true" data-autoplay="false"> </div>

icon矢量图标

主题内置:矢量图标 Icons | Font Awesome,例如社交信息中的Github,直接填写图标名称即可

fab fa-github: https://github.com/GC-ZF || Github

引入第三方iconfont-阿里巴巴矢量图标库,挑选图标加入自己账户中,修改主题配置文件_config.butterfly.yml

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="//at.alicdn.com/t/c/font_xxxx.css"> # 图标库的地址

调整样式,新建source/css/alico.css

/* 第三方图标样式 */
.iconfont {
font-size: 18px;
}

使用格式:iconfont 图标名称

iconfont icon-github: https://github.com/GC-ZF || Github

至此主题文档已全部介绍完成

其它配置

网站图标,修改主题配置文件_config.butterfly.yml

# Favicon(网站图标)
favicon: /img/favicon.png

图片懒加载,图片没加载出来的时候,出现一个动图转转转的文章页样式,修改主题配置文件_config.butterfly.yml

# Lazyload (圖片懶加載)
# https://github.com/verlok/vanilla-lazyload
lazyload:
enable: true
field: site # site/post
placeholder: /Hexo_img/loading.gif # 懒加载图片
blur: true # 高斯模糊

六、优化

博客备份(版本控制)

及时对博客备份是一个好习惯!不会的同学根据卷二兔的视频跟着走。通过git版本控制还可以做历史回滚操作,git功能十分强大,B站看一些视频就可以掌握啦!

在Github新建一个私有仓库,例如地址为https://github.com/GC-ZF/Blog-Backups.git

在博客根路径下执行,之后出现.git文件

git init -b main

新建.gitignore文件,创建忽略规则(这些文件是可以二次下载的所以忽略上传)

.DS_Store
Thumbs.db
db.json
*.log
node_modules/
public/
.deploy*/
.vscode/
/.idea/
.deploy_git*/
.idea
themes/butterfly/.git
themes/webstack/.git

上传仓库

git add .
git commit -m "我的第一次提交"
git remote add origin 仓库地址url
git push --set-upstream origin main

当博客更改后需要备份时

git add .
git commit -m "我的备份"
git push

当需要重新获取博客文件时,npm install会检查package.json里记录了那些依赖,所以就不用一个一个安了

git clone 仓库地址
# 重新下载主题文件
git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly
npm install
hexo g
hexo s

自动化部署

此节较长,参考:Hexo博客利用Github Action自动化部署 | 张时贰

前面做了版本控制,一个仓库用来存放源文件,一个仓库github.io用来存放静态文件,而每次都需要繁琐的八条命令!

hexo clean
hexo g
hexo algolia
gulp
hexo d
git add .
git commit -m "提交博客"
git push

渲染静态文件还需要等候,有没有什么办法可以仅通过三条git命令达到部署需求?Github Action!通过push私有仓库触发Action自动构建静态文件并推送给github.io仓库、服务器、vercel等平台

Hexo博客搭建35

简化命令

每次输入hexo clean && hexo g && hexo s十分费事,可以简化命令

原文地址:通过alias自定义终端命令实现Hexo博客的高效使用,简化你的终端命令 | 张洪Heo

Mac设备可以参考Heo哥,我这里提供win下方案

修改[BlogRoot]/package.json,追加一行自定义命令

  "scripts": {
"build": "hexo generate",
"clean": "hexo clean",
"deploy": "hexo deploy",
"server": "hexo server",
+ "localhost": "hexo clean & hexo g & hexo s"
}

终端输入npm run localhost,测试跑通即可。左图为webstorm双击运行,右图为vscode选择npm运行

Hexo博客搭建36

如果两个软件都没安装且现有编译器没有运行功能,新建[BlogRoot]/run.bat,双击运行

hexo clean && hexo g && hexo s

gulp压缩

原文地址:使用gulp压缩博客静态资源 | Akilarの糖果屋

Hexo博客本身由静态文件组成,通过gulp,可以压缩html、css、js文件从而达到快速加载的效果

安装gulp插件

npm install --global gulp-cli #全局安装gulp指令集
npm install gulp --save #安装gulp插件

安装压缩html插件

npm install gulp-htmlclean --save-dev
npm install gulp-html-minifier-terser --save-dev # 用gulp-html-minifier-terser可以压缩HTML中的ES6语法

安装压缩CSS插件

npm install gulp-clean-css --save-dev

安装压缩js插件

npm install gulp-terser --save-dev

安装压缩字体插件(仅支持压缩ttf格式的字体包)

npm install gulp-fontmin --save-dev

为Gulp创建gulpfile.js任务脚本。新建[Blogroot]/gulpfile.js

//用到的各个插件
var gulp = require('gulp');
var cleanCSS = require('gulp-clean-css');
var htmlmin = require('gulp-html-minifier-terser');
var htmlclean = require('gulp-htmlclean');
var fontmin = require('gulp-fontmin');
// gulp-tester
var terser = require('gulp-terser');
// 压缩js
gulp.task('compress', async() =>{
gulp.src(['./public/**/*.js', '!./public/**/*.min.js'])
.pipe(terser())
.pipe(gulp.dest('./public'))
});
//压缩css
gulp.task('minify-css', () => {
return gulp.src(['./public/**/*.css'])
.pipe(cleanCSS({
compatibility: 'ie11'
}))
.pipe(gulp.dest('./public'));
});
//压缩html
gulp.task('minify-html', () => {
return gulp.src('./public/**/*.html')
.pipe(htmlclean())
.pipe(htmlmin({
removeComments: true, //清除html注释
collapseWhitespace: true, //压缩html
collapseBooleanAttributes: true,
//省略布尔属性的值,例如:<input checked="true"/> ==> <input />
removeEmptyAttributes: true,
//删除所有空格作属性值,例如:<input id="" /> ==> <input />
removeScriptTypeAttributes: true,
//删除<script>的type="text/javascript"
removeStyleLinkTypeAttributes: true,
//删除<style>和<link>的 type="text/css"
minifyJS: true, //压缩页面 JS
minifyCSS: true, //压缩页面 CSS
minifyURLs: true //压缩页面URL
}))
.pipe(gulp.dest('./public'))
});
//压缩字体
function minifyFont(text, cb) {
gulp
.src('./public/fonts/*.ttf') //原字体所在目录
.pipe(fontmin({
text: text
}))
.pipe(gulp.dest('./public/fontsdest/')) //压缩后的输出目录
.on('end', cb);
}

gulp.task('mini-font', (cb) => {
var buffers = [];
gulp
.src(['./public/**/*.html']) //HTML文件所在目录请根据自身情况修改
.on('data', function(file) {
buffers.push(file.contents);
})
.on('end', function() {
var text = Buffer.concat(buffers).toString('utf-8');
minifyFont(text, cb);
});
});
// 运行gulp命令时依次执行以下任务
gulp.task('default', gulp.parallel(
'compress', 'minify-css', 'minify-html','mini-font'
))

在每次运行完hexo generate生成静态页面后,运行gulp对其进行压缩

hexo clean
hexo generate
gulp
hexo deploy

图片压缩

图片压缩一方面可以加快加载速度,一方面减少出站流量(买的CDN也是钱哇!)。小张只对后台监控流量高的图片进行了压缩,大概逻辑就是能替换就替换,替换不了就压缩

Hexo博客搭建37

meowtec/Imagine:现在在用的软件,支持win、mac,批量转格式压缩一体,UI简洁,最重要的是压缩后不仅体积小且画质清晰

格式工厂:转格式压缩一体,但多了很多图片以外的功能,所以UI复杂一些不太喜欢

TinyPNG:在线压缩网站,质量高但一次最多20张

Caesium:批量压缩软件,无限制,人物图有些失真

Imgbot:Github插件,提交自动压缩发起pr

搜索

原文地址:

前文使用了本地搜索插件,Algolia是一款更快速的搜索工具,每月只有 10000 次调用额度。两种搜索一秒内出结果但本地搜索需要预先加载文件当刚进网站就点搜索时,Algolia更快

卸载本地搜索插件

npm uninstall hexo-generator-search

修改主题配置文件_config.butterfly.yml,关闭本地搜索

# Local search
local_search:
enable: false
preload: true
CDN:

注册 Algolia并创建一个应用

安装

npm install hexo-algoliasearch --save

修改配置文件 _config.yml,在最下面添加appId、apiKey、adminApiKey、indexName 根据自己的情况填写

plugins:
- hexo-algoliasearch

algolia:
appId: "RNPIZK8E"
apiKey: "8ee7fe3d8cad0c9a545a96e8bc26"
adminApiKey: "117700ad23daaa7f4ffe19a48da8"
chunkSize: 5000
indexName: "Hexo_Blog"
fields:
- content:strip:truncate,0,200
- tags
- permalink
- excerpt:strip
- title
- categories

修改主题配置文件_config.butterfly.yml

# Algolia search
algolia_search:
enable: true
hits:
per_page: 6

修改/themes/butterfly/source/js/search/algolia.js,设置按回车搜索以及提示词

const searchBox = instantsearch.widgets.searchBox({
container: '#algolia-search-input',
showReset: false,
showSubmit: true, // 设为true 可以通过按钮搜索
searchAsYouType: false, // 新增 可以实现回车或点击按钮搜索,不会每次输入都搜索
// placeholder: GLOBAL_CONFIG.algolia.languages.input_placeholder,
placeholder: "输入关键词后,按下回车键即可搜索文章...", //提示词
showLoadingIndicator: true
})

提交搜索hexo clean & hexo g & hexo algolia & hexo d

博客升级

升级前做好备份!!!

对npm升级

npm -v		# 检查npm版本
npm install npm@latest -g # 升级版本
npm cache clean -f # 更新新版本后如果安装其它包失败,清除npm缓存

对hexo及插件升级,在[BlogRoot]下操作

npm install -g npm-check-updates	# 安装检查更新模块

# 方法1 ncu -u更新package.json文件中保存的版本号,然后执行npm install
ncu -u
npm install

# 方法2
ncu # 查看可更新的模块 npm-check-updates命令的缩写
npm install 单个包名

# 方法3 不安装npm-check-updates,直接无脑更新全部
npm install -g npm-upgrade # 安装npm-upgrade包
npm update # 一键更新所有

# 检查更新命令 包名 -v或 包名 --version
hexo -v

对Butterfly升级,在[BlogRoot]/theme/butterfly下操作

git pull	# 合并新版本

根据Butterfly 更新日志,对[BlogRoot]/_config.butterfly.yml增删新版的配置

隐藏文章

原文地址:如何优雅隐藏 Hexo 文章 | CC的部落格

写好但不发布,方法蛮多的,Front-Matter我认为更方便一些

在文章Front-Matter部分配置published参数

---
published: false
---

跳过渲染

原文地址:跳过渲染参考 MuJin’s Blog

有时我们需要放一些自己写好的html文件,但会被hexo渲染到主题中,这就需要跳过渲染

方法一:在文件前加Front matter,设置layout属性

---
layout: false
---

方法二:修改配置文件 _config.yml

# 指定目录跳过hexo渲染
skip_render:
- '文件名/*'

RSS订阅

RSS不知道是什么,其实就是博客站点中一个小WIFI的按钮,打个比方,bili和知乎都支持RSS订阅,可以将RSS添加到订阅软件中,然后在软件中浏览指定的博主,不被大数据所轰炸,博客同理,在软件中浏览其他人的博客,这样就不需要来回去点网站访问了。

文档:hexo-generator-feed

安装插件

npm install hexo-generator-feed

修改配置文件 _config.yml,在最下面添加

#RSS订阅 其它配置参考官网
feed:
type: rss2 # 类型有atom和rss2,如果乱码就换另一个
path: feed.xml # 为路径取个名字
limit: 10 # 订阅前10条

hexo三连后,生成public/feed.xml,通过http://localhost:4000/feed.xml(域名/feed.xml)访问

关于RSS软件,近年下架了不少,推荐安卓 Focus,Apple Store reader

域名解析

域名厂商很多,就不详细写绑定流程了,参考以下三篇文章,想要用二级域名参考第三篇,注意上传一个写有域名地址且文件命名CNAME的文件到Github仓库内,域名才会生效

Hexo个人免费博客(五) 使用自己的域名_

hexo 绑定自己的域名_

如何添加二级域名 Hydrion-Qlz的博客

SEO收录及优化

SEO收录简单来说就是可以让别人通过搜索一些关键字,然后搜到我们的博客内容

原文地址:

以下是我自己总结的,其实直接看B站教学就行,图文并茂没视频效果好

小tips:如果绑定了域名,不要使用xxx.github.io这个地址,绑定站点配置时会失败(301错误),如果使用的免费域名例如github.io百度基本不会收录

安装站点地图

站点地图即 sitemap, 是一个页面,通过插件会帮助我们将站内所有的网址记录在这个页面内,告诉搜索引擎网站上有哪些可供抓取的网页,以便搜索引擎可以更加智能地抓取网站

安装百度和 Google 的站点地图生成插件

npm install hexo-generator-baidu-sitemap --save
npm install hexo-generator-sitemap --save

修改配置文件 _config.yml,在下面添加

# 站点地图
sitemap:
path: sitemap.xml
baidusitemap:
path: baidusitemap.xml

修改配置文件 _config.yml,添加域名地址

# URL
## Set your site url here. For example, if you use GitHub Page, set url as 'https://username.github.io/project'
url: https://xxxx.xxx

hexo clean & hexo g生成public/sitemap.xmlpublic/baidusitemap.xml。通过https://你的域名/sitemap.xmlhttps://你的域名/baidusitemap.xml检查,如果出现代码就说明插件安装成功

robots.txt 是一种存放于网站根目录下的 ASCII 编码的文本文件,它的作用是告诉搜索引擎此网站中哪些内容是可以被爬取的,哪些是禁止爬取的。robots.txt 放在博客目录下的 source 文件夹中,博客生成后在站点目录 /public/ 下,使用规则,我博客没啥东西,小蜘蛛爬就爬去吧,所以我没设置这项,感兴趣可以设置一下

# hexo robots.txt
User-agent: * #引擎名字,*是所有,具体服务商名字看规则说明
Allow: / #允许路径
Disallow: #禁止路径
Sitemap: https://域名/sitemap.xml
Sitemap: https://域名/baidusitemap.xml

百度收录

百度站点

Hexo博客搭建13

选择标签验证更方便一点点,修改主题配置文件_config.butterfly.yml,推送到服务器然后再点击验证

site_verification:
- name: baidu-site-verification
content: xxxxxxx

Hexo博客搭建14

主动推送(已弃用)

主动推送最快最方便,通过插件每次会自动提交,但是百度虽然有插件但是收录效果没谷歌bing快…

安装

npm install hexo-baidu-url-submit --save

修改配置文件 _config.yml,在最下面添加

# 主动推送百度,被百度收录
baidu_url_submit:
count: 10 # 提交最新的10个链接
host: https://zhsher.cn # 百度站长平台中注册的域名
token: # 秘钥,百度站长平台 > 推送接口 > 接口调用地址中token字段
path: baidu_urls.txt # 文本文档的地址, 新链接会保存在此文本文档里,不用改

修改配置文件 _config.yml,新增一个type

# Deployment
## Docs: https://hexo.io/docs/one-command-deployment
deploy:
- type: git
repository: xxxxx
branch: main
- type: baidu_url_submitter #<--加这里,注意缩进

之后每次hexo g会把最新的链接放在public/baidu_urls.txthexo d会自动读取文件内容并提交给百度,返回一段值remain当日剩余可提交,success成功提交,如果有error说明前面配的有问题

Hexo博客搭建15

sitemap

API提交旁边的sitemap即手动推送站点地图,其实主动推送插件就够用了(再旁边的手动提交就是一条一条的提交,sitemap更方便一些)

https://你的域名/sitemap.xml
https://你的域名/baidusitemap.xml

Hexo博客搭建16

谷歌收录

Google Search Console

两种验证方式,第二个方便一些

Hexo博客搭建11

修改主题配置文件_config.butterfly.ymlhexo c & g & d之后点击验证,之后等待收录就可以了

site_verification:
- name: baidu-site-verification
content: xxxxxxx
+- name: google-site-verification
+ content: xxxxxxx

虽然没有百度的主动推送方式但同样也有sitemap,提交这个https://你的域名/sitemap.xml,bing同理

Bing收录

Bing

做完谷歌收录,bing这里直接导入谷歌即可

Hexo博客搭建12

URL持久化

原文地址:

hexo 默认生成的文章地址路径是 网站名称/年/月/日/文章名称,这种链接对搜索爬虫是很不友好的,第一它的 url 结构超过了三层,太深了,abbrlink会优化为一段数字

安装

npm install hexo-abbrlink --save

修改配置文件 _config.yml,二选一,重新hexo c & g & d就看到效果了

# 第一种默认算法与进制
permalink: posts/:abbrlink/
# 第二种加了算法和进制要求 
# permalink: :title/
permalink: archives/:abbrlink.html
abbrlink:
alg: crc32 # 算法:crc16(default) and crc32
rep: hex # 进制:dec(default) and hex

添加nofollow标签

原文地址:Hexo 框架 (六):SEO 优化及站点被搜索引擎收录设置

给非友情链接的出站链接添加「nofollow」标签,nofollow 标签是由谷歌领头创新的一个「反垃圾链接」的标签,并被百度、yahoo 等各大搜索引擎广泛支持,引用 nofollow 标签的目的是:用于指示搜索引擎不要追踪(即抓取)网页上的带有 nofollow 属性的任何出站链接,以减少垃圾链接的分散网站权重

npm install hexo-filter-nofollow --save

修改配置文件 _config.yml,将 nofollow 设置为 true:

nofollow:
enable: true
field: site
exclude: ''

三家主动推送

2023.01.06更新:因为谷歌、Bing一两天就会收录,而百度短则一周长则三四个月(一般是长)所以前面对百度加装了主动推送插件,如果你熟悉对Github的使用(不会也问题不大,作者乐特教程很详细),推荐Hexo-SEO-AutoPush: 每天自动提交url到百度和谷歌必应插件,使用Github Action每日定时推送,省去手动hexo d才推送的操作

安装

npm install hexo-seo-autopush --save

修改配置文件 _config.yml,在最下面添加

# enable: 开启/关闭 推送
# cron: 执行时间周期
# count: 每次提交最新的10篇文章,输入0或者不填写则默认为所有文章(建议是最新的10篇文章)
# date: 更新时间(updated)|创建日期(created)
# https://github.com/Lete114/hexo-seo-autopush.git
hexo_seo_autopush:
cron: 0 4 * * *
baidu:
enable: true
date: created
count: 10
bing:
enable: true
date: created
count: 10
google:
enable: true
date: created
count: 10

生成的 actions 是在github.io仓库下的.github/workflows/HexoSeoAutoPush.yml,点开头的文件或文件夹都会被视为隐藏文件,所以 hexo 不会将隐藏文件部署到 pages,需要新增配置ignore_hidden属性

deploy:
type: git
repo: https://github.com/<username>/<project>
# example, https://github.com/hexojs/hexojs.github.io
branch: gh-pages
+ ignore_hidden: false # 忽略隐藏文件及文件夹(目录)

hexo clean & hexo g后在[BlogRoot]/public生成baidu.txt、google.txt、bing.json则插件安装成功

之后在github.io仓库加入变量,为仓库做定时提交任务,具体参考文档

CDN加速

注:CDN需要中国大陆实名备案,且年费用在10元左右,如果你是无服务器部署,是不可以做备案的,可以尝试其它托管服务

  • VercelNetlify:首推Vercel。俩平台用自己的Github注册导入github.io仓库即可,十分方便
  • Gitee Page服务:国内Gitee的静态服务,但每次都需要点击手动检查部署,如果触发违禁词还需要重新编写文章,十分繁琐

2022.08.08,博客已稳定运行三个多月,感觉CDN加速没什么用,但始终逃不过真香定律。下图为加速后和加速前的ping测试

Hexo博客搭建32

为什么使用 CDN 内容分发网络?

当用户直接访问源站中的静态内容时,可能面临的体验问题

  • 客户离服务器越远,访问速度越慢。

  • 客户数量越多,网络带宽费用越高。

  • 跨境用户访问体验较差。

  • 摘自店长的解释:

    CDN(Content Delivery Network,内容分发网络)的作用很简单,顾名思义,把你的网站内容存在由各个节点构成的网络内,然后按照请求距离远近,让最近的节点去分发服务。

    打个比方,把源站比作商品,CDN比作物流。
    原本你从国内向海外发起海外购(访问源站),然后美国仓库发货(githubpage响应请求),可能要一周多才能到货。
    现在套了全站CDN,你向美国发货,然后国内仓库(国内CDN缓存节点)比较了下,发现它在上海、北京、深圳等等地方都有一模一样的货(缓存内容),所以他看你在浙江,于是直接从离你最近的上海仓库发货(最近节点分发内容),于是,你上午下单,下午就到了。这样子,网站速度就快了。

CDN 如何改善您的网络体验

  • CDN 缓存内容后,用户仅需要访问就近的 CDN 节点即可获取静态内容。
  • 缓解源站带宽压力,网络费用更低。
  • 分布全球的跨境节点提升跨境访问体验。

简单点说,就是用一个服务商去帮你代理你的网站,从而做到全国加速访问的效果。其中有又拍云、百度云、腾讯云

文档经常更新,所以具体参考各个平台最新文档内容:内容分发网络 CDN 业务场景-场景教学-文档中心-腾讯云CDN配置方式(以腾讯云为例) - 忆梦小站

避坑:不建议开启IP访问限频配置,因为hexo静态文件居多,加载网页同时[BlogRoot]/source/js[BlogRoot]/source/css等文件这些都算同一时间内的访问次数的,如果访问频率过低会导致页面加载错误,可以根据控制台报错找一个合适的频率配置

建议开启HTTPS配置(导入ssl证书)、HTTPS服务+强制跳转HTTPS、用量封顶配置,关掉IP限制但为了盗刷流量可以配置用量封顶

Hexo博客搭建34

检查是否CDN加速是否起作用

  • 站长工具测试全国访问速度
  • 查看请求头:网络控制台请求表头中包含x-cache-lookup:Cache Hit (代表成功从cdn上取得资源)
  • 命令行ping 域名:返回源地址而不是自己的服务器ip

站内资源CDN

原文地址:Butterfly CDN链接更改指南,替换jsdelivr提升访问速度 | 张洪Heo

既然不能为自己public文件夹下静态文件加速,那么主题渲染过程中也引入了很多外部资源,默认用的是国外厂商jsdelivr例如:https://cdn.jsdelivr.net/npm/xxx/dist/xxx.min.js,修改这些文件的地址也可以减少网站加载时间

所有外部资源文件的名称在

  • [BlogRoot]/themes/butterfly/scripts/events/cdn.js
  • ``[BlogRoot]/themes/butterfly/plugins.yml`

修改应遵循优先使用字节跳动的cdn。如果字节跳动静态资源公共库没有则使用elemecdn,可以达到加速的效果。如果都没有可以和洪哥一样自己打包npm引用(我偷懒直接白嫖了嘻嘻)

修改主题配置文件_config.butterfly.yml

CDN:
......
option:
+ 在这里按需添加对应链接

jquery

https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.6.0/jquery.min.js

pjax

pjax: https://npm.elemecdn.com/pjax@latest/pjax.min.js

sharejs

sharejs: https://npm.elemecdn.com/butterfly-extsrc@latest/sharejs/dist/js/social-share.min.js
sharejs_css: https://npm.elemecdn.com/butterfly-extsrc@latest/sharejs/dist/css/share.min.css

gitalk

gitalk: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/gitalk/1.7.2/gitalk.min.js
gitalk_css: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/gitalk/1.7.2/gitalk.min.css

valine

https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/valine/1.4.16/Valine.min.js

disqusjs

disqusjs: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/disqusjs/1.3.0/disqus.js
disqusjs_css: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/disqusjs/1.3.0/disqusjs.css

twikoo(这个是定制版)

twikoo: https://jsd.onmicrosoft.cn/npm/js-heo@1.0.3/twikoo/twikoo.all.min.js

twikoo(官方版)

twikoo: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/twikoo/1.4.18/twikoo.all.min.js

waline

https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/waline/1.5.4/Waline.min.js

algolia

algolia_js: https://jsd.onmicrosoft.cn/npm/js-heo@1.0.11/algolia/algolia.js
algolia_search_v4: https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/algoliasearch/4.12.1/algoliasearch-lite.umd.min.js

lazyload

lazyload: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/vanilla-lazyload/17.3.1/lazyload.iife.min.js

instantpage

instantpage: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/instant.page/5.1.0/instantpage.min.js

typed

typed: https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/typed.js/2.0.12/typed.min.js

fancybox

fancybox_css_v4: https://jsd.onmicrosoft.cn/npm/@fancyapps/ui@4.0.31/dist/fancybox.css
fancybox_v4: https://jsd.onmicrosoft.cn/npm/@fancyapps/ui@latest/dist/fancybox.umd.js

medium_zoom

https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/medium-zoom/1.0.6/medium-zoom.min.js

snackbar

snackbar_css: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/node-snackbar/0.1.16/snackbar.min.css
snackbar: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/node-snackbar/0.1.16/snackbar.min.js

fontawesome

fontawesomeV6: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/font-awesome/6.0.0/css/all.min.css

translate

translate: https://jsd.onmicrosoft.cn/npm/hexo-theme-butterfly/source/js/tw_cn.js

aplayer

aplayer_css: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/aplayer/1.10.1/APlayer.min.css
aplayer_js: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/aplayer/1.10.1/APlayer.min.js
meting_js: https://jsd.onmicrosoft.cn/npm/js-heo@1.0.12/metingjs/Meting.min.js

Prism

prismjs_js: https://jsd.onmicrosoft.cn/npm/prismjs@1.1.0/prism.js
prismjs_lineNumber_js: https://jsd.onmicrosoft.cn/npm/prismjs/plugins/line-numbers/prism-line-numbers.min.js
prismjs_autoloader: https://jsd.onmicrosoft.cn/npm/prismjs/plugins/autoloader/prism-autoloader.min.js

justifiedGallery

flickr_justified_gallery_js: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/justifiedGallery/3.8.1/js/jquery.justifiedGallery.min.js
flickr_justified_gallery_css: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/justifiedGallery/3.8.1/css/justifiedGallery.min.css

网站监控

可以监控多个站点或友链访问是否正常,发送错误时以邮件或短信方式通知

  • 哪吒面板:安装在自己服务器,需要额外借助GitHub,部署复杂,优点是不仅可以监控站点还可以监控服务器
  • UptimeRobot:无需安装,免费监控50个站点
  • louislam/uptime-kuma,基于uptimerobot,安装在自己服务器,部署简单

小张采用uptime-kuma

首先确认已安装docker环境:安装 Docker教程

安装uptime-kuma,并在网络控制台放行3001端口,通过服务器ip:3001访问

docker run -d --restart=always -p 3001:3001 -v /www/wwwroot/status/uptime-kuma/data:/app/data --name uptime-kuma louislam/uptime-kuma:1

选做:配置域名参考文档 uptime-kuma Wiki,以nginx为例,/www/server/panel/vhost/nginx下创建status.conf文件,第三行为域名,四五行为证书路径

server {
listen 443 ssl http2;
server_name status.zhsher.cn;
ssl_certificate /path/to/ssl/cert/crt;
ssl_certificate_key /path/to/ssl/key/key;

location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://localhost:3001/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}

但如果想和博客一样在宝塔面板的网站中显示(强迫症,列一起好知道自己有那些站点),可以添加一个空站点,之后修改配置文件或者做一个反代,二者效果相同

Hexo博客搭建33

更新参考:uptime-kuma Wiki

docker pull louislam/uptime-kuma:1
docker stop uptime-kuma
docker rm uptime-kuma

# Default
docker run -d --restart=always -p 3001:3001 -v uptime-kuma:/app/data --name uptime-kuma louislam/uptime-kuma:1

# If you are not using default value
# docker run -d --restart=always -p <YOUR PORT>:3001 -v <YOUR VOLUME>:/app/data --name uptime-kuma louislam/uptime-kuma:1

新增状态页面后,在仪表盘可将网站入口设置为状态页面,之后仪表盘需要通过域名/dashboard进入

我的自定义css

body {

}
.info,h1,.shadow-box,.mb-4 ,.group-title,.mt-5{
font-family: "华文新魏","楷体";
}

Hexo异步加载方案

原文地址:Hexo异步加载方案 | Akilarの糖果屋

Pjax适配

原文地址:我是这么适配pjax的 | Leonus

七、魔改

个人喜欢简约风格,魔改美化应遵循阅读体验、实用功能优先的原则,因而不做繁冗的增添与过于商业性质的修改

魔改由简到难,分为css、js文件引入修改,插件魔改,主题源码魔改。其中css分文件编写只是为了区分功能,实际操作可以合并为一个文件减少网页请求次数提高加载速度,Hexo异步加载方案中有详细说明

插入代码自定义样式(鼠标或footer)及备案信息实现

在正式魔改前,先回顾一下主题文档是如何修改样式的

原文地址:使用Hexo搭建个人博客手摸手教学(16)|插入代码自定义样式及备案信息实现

卷二兔up主的其它css文件:constown/HexoStaticFile: HexoStaticFile

在博客界面右击想要修改的地方,点击检查,以底部为例,查到#footer-wrap,新建[BlogRoot]/source/css/style.css

#footer{
background: transparent;
}
#footer-wrap{
color: #0d0d0d;
}

修改主题配置文件_config.butterfly.yml,引入css文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
- <link rel="stylesheet" href="/css/style.css">

修改主题配置文件_config.butterfly.yml,添加备案信息并修改#footer-a属性

# Footer Settings
# --------------------------------------
footer:
owner:
enable: true
since: 2022
custom_text: <div>满地都是六便士 我想抬头看月亮</div><div><a onclick="window.open('url')" class="footer-a">备没服务器...</a></div>
copyright: true # Copyright of theme and framework

同样在style.css中修改样式

#footer-a{
color: #0d0d0d;
}

twikoo美化

twikoo输入提醒

原文地址:给你的评论添加一个输入提醒吧 | Leonus

新建[BlogRoot]/source/css/twikoo.css

/* 设置文字内容 :nth-child(1)的作用是选择第几个 */
.el-input.el-input--small.el-input-group.el-input-group--prepend:nth-child(1):before {
content: '输入QQ号会自动获取昵称和头像🐧';
}

.el-input.el-input--small.el-input-group.el-input-group--prepend:nth-child(2):before {
content: '收到回复将会发送到您的邮箱📧';
}

.el-input.el-input--small.el-input-group.el-input-group--prepend:nth-child(3):before {
content: '可以通过昵称访问您的网站🔗';
}

/* 当用户点击输入框时显示 */
.el-input.el-input--small.el-input-group.el-input-group--prepend:focus-within::before,
.el-input.el-input--small.el-input-group.el-input-group--prepend:focus-within::after {
display: block;
}

/* 主内容区 */
.el-input.el-input--small.el-input-group.el-input-group--prepend::before {
/* 先隐藏起来 */
display: none;
/* 绝对定位 */
position: absolute;
/* 向上移动60像素 */
top: -60px;
/* 文字强制不换行,防止left:50%导致的文字换行 */
white-space: nowrap;
/* 圆角 */
border-radius: 10px;
/* 距离左边50% */
left: 50%;
/* 然后再向左边挪动自身的一半,即可实现居中 */
transform: translate(-50%);
/* 填充 */
padding: 14px 18px;
background: #444;
color: #fff;
}

/* 小角标 */
.el-input.el-input--small.el-input-group.el-input-group--prepend::after {
display: none;
content: '';
position: absolute;
/* 内容大小(宽高)为0且边框大小不为0的情况下,每一条边(4个边)都是一个三角形,组成一个正方形。
我们先将所有边框透明,再给其中的一条边添加颜色就可以实现小三角图标 */
border: 12px solid transparent;
border-top-color: #444;
left: 50%;
transform: translate(-50%, -48px);
}

修改主题配置文件_config.butterfly.yml,引入css文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/twikoo.css">

twikoo评论美化

原文地址:

新建[BlogRoot]/source/css/twikoo.css

方案一:注释很清晰可以自己微调,我修改了一下回复气泡的位置:.tk-content中新增 margin-left: 30px;

/*twikoo评论气泡*/

/* 自定义twikoo评论输入框高度 */
.tk-input[data-v-619b4c52] .el-textarea__inner {
height: 130px !important;
}
/* 输入评论时自动隐藏输入框背景图片 */
.tk-input[data-v-619b4c52] .el-textarea__inner:focus {
background-image: none !important;
}
/* 调整楼中楼样式 ,整体左移,贴合气泡化效果 */
.tk-replies {
left: -70px;
width: calc(100% + 70px);
}
/* 头像宽度调整 rem单位与全局字体大小挂钩,需配合自己情况调整大小以保证头像显示完整*/
.tk-replies .tk-avatar {
width: 2.5rem !important;
height: 2.5rem !important;
}
.tk-replies .tk-avatar img {
width: 2.5rem !important;
height: 2.5rem !important;
}
/* 回复框左移,避免窄屏时出框 */
.tk-comments-container .tk-submit {
position: relative;
left: -70px;
}
/* 评论块气泡化修改 */
.tk-content {
background: #00a6ff; /*默认模式访客气泡配色*/
padding: 10px;
color: #fff; /*默认模式访客气泡字体配色*/
border-radius: 10px;
font-size: 16px !important;
width: fit-content;
max-width: 100%;
position: relative !important;
overflow: visible !important;
max-height: none !important;
margin-left: 30px;
}
/* 修复图片出框 */
.tk-content img {
max-width: 100% !important;
}
/* 修复过长文本出框 */
.tk-content pre {
white-space: pre-wrap;
word-wrap: break-word;
}
.tk-content a {
color: #eeecaa; /*默认模式超链接配色*/
}
.tk-content::before {
content: '';
width: 0;
height: 0;
position: absolute;
top: 20px;
left: -13px;
border-top: 2px solid transparent;
border-bottom: 20px solid transparent;
border-right: 15px solid #00a6ff; /*默认模式访客气泡小三角配色*/
border-left: 0px solid transparent;
}
.tk-master .tk-content {
background: #ff8080; /*默认模式博主气泡配色*/
color: #fff; /*默认模式博主气泡字体配色*/
width: fit-content;
max-width: 100%;
}
.tk-master .tk-content a {
color: #eeecaa;
}
.tk-master .tk-content::before {
content: '';
width: 0;
height: 0;
position: absolute;
top: 20px;
left: -13px;
border-top: 2px solid transparent;
border-bottom: 20px solid transparent;
border-right: 15px solid #ff8080; /*默认模式博主气泡小三角配色*/
border-left: 0px solid transparent;
}
.tk-row[data-v-d82ce9a0] {
max-width: 100%;
width: fit-content;
}
.tk-avatar {
border-radius: 50%;
margin-top: 10px;
}

/* 夜间模式配色,具体比照上方默认模式class */
[data-theme="dark"] .tk-content {
background: #000;
color: #fff;
}
[data-theme="dark"] .tk-content a {
color: #dfa036;
}
[data-theme="dark"] .tk-content::before {
border-right: 15px solid #000;
}
[data-theme="dark"] .tk-master .tk-content {
background: #000;
color: #fff;
}
[data-theme="dark"] .tk-master .tk-content a {
color: #dfa036;
}
[data-theme="dark"] .tk-master .tk-content::before {
border-top: 2px solid transparent;
border-bottom: 20px solid transparent;
border-right: 15px solid #000;
border-left: 0px solid transparent;
}
/* 自适应内容 */
@media screen and (min-width: 1024px) {
/* 设置宽度上限,避免挤压博主头像 */
.tk-content {
max-width: 75%;
width: fit-content;
}
.tk-master .tk-content {
width: 75%;
}
.tk-master .tk-content::before {
left: 100%;
border-left: 15px solid #ff8080;
border-right: 0px solid transparent;
}
.tk-master .tk-avatar {
position: relative;
left: calc(75% + 70px);
}
.tk-master .tk-row[data-v-d82ce9a0] {
position: relative;
top: 0px;
left: calc(75% - 230px);
}
[data-theme="dark"] .tk-master .tk-content::before {
border-left: 15px solid #000;
border-right: 0px solid transparent;
}
}
/* 设备名称常态隐藏,悬停评论时显示 */
.tk-extras {
opacity: 0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
}
.tk-content:hover + .tk-extras {
-webkit-animation: tk-extras-fadeIn 0.5s linear;
-moz-animation: tk-extras-fadeIn 0.5s linear;
-o-animation: tk-extras-fadeIn 0.5s linear;
-ms-animation: tk-extras-fadeIn 0.5s linear;
animation: tk-extras-fadeIn 0.5s linear;
-webkit-animation-fill-mode: forwards;
-moz-animation-fill-mode: forwards;
-o-animation-fill-mode: forwards;
-ms-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
@-moz-keyframes tk-extras-fadeIn {
from {
opacity: 0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
}
to {
opacity: 1;
-ms-filter: none;
filter: none;
}
}
@-webkit-keyframes tk-extras-fadeIn {
from {
opacity: 0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
}
to {
opacity: 1;
-ms-filter: none;
filter: none;
}
}
@-o-keyframes tk-extras-fadeIn {
from {
opacity: 0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
}
to {
opacity: 1;
-ms-filter: none;
filter: none;
}
}
@keyframes tk-extras-fadeIn {
from {
opacity: 0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
}
to {
opacity: 1;
-ms-filter: none;
filter: none;
}
}

/* gif动图 */
.tk-input textarea {
background-image: url('https://zhsher.cn/Hexo_img/config/Twikooback.gif');/* 图片地址 */
min-height: 120px !important; /* 默认是75px 拉高评论框大小 */
background-size:10em 10em; /* 设置图片长宽 */
/* background-color: #ffffff; */
transition: all 0.25s ease-in-out 0s; /* 动画过渡 */
}

.tk-input textarea:focus {
background-position-y: 130px;
transition: all 0.25s ease-in-out 0s
}

方案二

/* 声名部分变量 */
:root {
--zhangshier-radius: 7px;
--zhangshier-card-border-width: 1px;
}

/* 浅色模式颜色 */
[data-theme=light] {
--zhangshier-border-color: #e3e8f7;
--zhangshier-card-bg: #fff;
--zhangshier-card-border: #e3e8f7;
--style-border-always: 1px solid var(--zhangshier-card-border);
--zhangshier-blue: #425AEF;
}

/* 深色模式颜色 */
[data-theme=dark] {
--zhangshier-border-color: #42444a;
--zhangshier-card-bg: #1d1b26;
--zhangshier-card-border: #42444a;
--style-border-always: 1px solid var(--zhangshier-card-border);
--zhangshier-blue: #0084FF;
}

/* 评论区评论大框 */
.twikoo .tk-comments-container>.tk-comment {
/* 内边距 */
padding: 1rem;
/* 圆角 */
border-radius: var(--zhangshier-radius);
/* 背景颜色 */
background: var(--zhangshier-card-bg);
/* 变动动画时长 */
transition: .3s;
}

/* 浅色模式评论区评论大框 */
[data-theme=light] .twikoo .tk-comments-container>.tk-comment {
/* 阴影 */
box-shadow: var(--card-box-shadow);
}

/* 浅色模式评论区评论大框阴影悬浮加深 */
[data-theme=light] .twikoo .tk-comments-container>.tk-comment:hover {
/* 阴影(浅色模式突出层次感) */
box-shadow: var(--card-hover-box-shadow);
}

/* 黑暗模式评论区评论大框 */
[data-theme=dark] .twikoo .tk-comments-container>.tk-comment {
/* 边框样式 */
border-style: solid;
/* 边框宽度 */
border-width: var(--zhangshier-card-border-width);
/* 边框颜色 */
border-color: var(--zhangshier-card-border);
}

/* 设备信息 */
.twikoo .tk-extra {
/* 圆角 */
border-radius: var(--zhangshier-radius);
/* 背景颜色 */
background: var(--zhangshier-card-bg);
/* 内边距 */
padding: 0.4rem;
/* 底边距 */
margin-bottom: 1rem;
/* 变动动画时长 */
transition: .3s;
}

/* 浅色模式设备信息 */
[data-theme=light] .twikoo .tk-extra {
/* 阴影 */
box-shadow: var(--card-box-shadow);
}

/* 浅色模式设备信息阴影悬浮加深 */
[data-theme=light] .twikoo .tk-extra:hover {
/* 阴影 */
box-shadow: var(--card-hover-box-shadow);
}

/* 黑暗模式设备信息 */
[data-theme=dark] .twikoo .tk-extra {
/* 边框样式 */
border-style: solid;
/* 边框宽度 */
border-width: var(--zhangshier-card-border-width);
/* 边框颜色 */
border-color: var(--zhangshier-card-border);
}

/* 加载更多按钮 */
.twikoo .tk-expand {
/* 圆角 */
border-radius: var(--zhangshier-radius);
}

/* 浅色模式加载更多按钮 */
[data-theme=light] .twikoo .tk-expand {
/* 阴影 */
box-shadow: var(--card-box-shadow);
}

/* 浅色模式加载更多按钮(鼠标悬浮时) */
[data-theme=light] .twikoo .tk-expand:hover {
/* 阴影 */
box-shadow: var(--card-hover-box-shadow);
/* 背景颜色 */
background-color: var(--btn-bg);
}

/* 黑暗模式加载更多按钮(鼠标悬浮时) */
[data-theme=dark] .twikoo .tk-expand:hover {
/* 背景颜色 */
background-color: var(--zhangshier-blue);
}

/* 黑暗模式加载更多按钮 */
[data-theme=dark] .twikoo .tk-expand {
/* 边框样式 */
border-style: solid;
/* 边框宽度 */
border-width: var(--zhangshier-card-border-width);
/* 边框颜色 */
border-color: var(--zhangshier-card-border);
}

/* gif动图 */
.tk-input textarea {
background-image: url('https://zhsher.cn/Hexo_img/config/Twikooback.gif');/* 图片地址 */
min-height: 120px !important; /* 默认是75px 拉高评论框大小 */
background-size:10em 10em; /* 设置图片长宽 */
/* background-color: #ffffff; */
transition: all 0.25s ease-in-out 0s; /* 动画过渡 */
}

.tk-input textarea:focus {
background-position-y: 130px;
transition: all 0.25s ease-in-out 0s
}

方案三

.tk-expand {
width: 100%;
cursor: pointer;
padding: .75em;
text-align: center;
transition: all .5s
}

#twikoo .tk-content p {
margin: 0
}

#twikoo .tk-expand:hover {
color: #fff;
background-color: #3b70fc;
border: 1px solid transparent;
}

.tk-expand {
border: var(--style-border);
box-shadow: 0 8px 16px -4px #2c2d300c;
border-radius: 50px;
letter-spacing: 5px;
background-color: var(--zhsher-card-bg)
}

.tk-replies > .tk-comment {
border-top: var(--style-border-dashed);
border-radius: 12px;
padding: 1rem 0 0;
transition: all .3s ease 0s
}

.tk-replies .tk-content span:first-child:not(.token) {
font-size: .5rem;
color: var(--zhsher-secondtext)
}

#twikoo pre code {
padding: none;
background: 0 0;
color: none;
}

#twikoo code {
padding: 2px 4px;
background: var(--zhsher-secondbg);
color: #f47466
}

.el-input.el-input--small.el-input-group.el-input-group--prepend:nth-child(1):before {
content: '输入QQ号会自动获取昵称和头像';
}

.el-input.el-input--small.el-input-group.el-input-group--prepend:nth-child(2):before {
content: '收到回复将会发送到你的邮箱';
}

.el-input.el-input--small.el-input-group.el-input-group--prepend:nth-child(3):before {
content: '可以通过昵称访问你的网站';
}

.el-input.el-input--small.el-input-group.el-input-group--prepend:focus-within::after, .el-input.el-input--small.el-input-group.el-input-group--prepend:focus-within::before {
display: block
}

.el-input.el-input--small.el-input-group.el-input-group--prepend::before {
display: none;
position: absolute;
top: -60px;
white-space: nowrap;
border-radius: 10px;
left: 50%;
transform: translate(-50%);
padding: 14px 18px;
background: #444;
color: #fff
}

.el-input.el-input--small.el-input-group.el-input-group--prepend::after {
display: none;
content: "";
position: absolute;
border: 12px solid transparent;
border-top-color: #444;
left: 50%;
transform: translate(-50%, -48px)
}

.vwrap {
box-shadow: 2px 2px 5px #bbb;
background: rgba(255, 255, 255, .3);
border-radius: 8px;
padding: 30px;
margin: 30px 0 30px 0
}

.vcard {
box-shadow: 2px 2px 5px #bbb;
background: rgba(255, 255, 255, .3);
border-radius: 8px;
padding: 30px;
margin: 30px 0 0 0
}

#twikoo .tk-extra {
background: var(--zhsher-card-bg);
border: var(--style-border-always);
padding: 4px 8px;
border-radius: 8px;
margin-right: 4px;
color: var(--zhsher-secondtext);
margin-top: 6px;
font-size: .8rem
}

#twikoo .tk-extra-text {
font-size: .5rem
}

#twikoo .tk-replies .tk-content {
font-size: .9rem
}

#twikoo .tk-content {
margin-top: 0
}

.tk-content span a:not([data-fancybox=gallery]) {
font-weight: 500;
border-bottom: solid 2px var(--zhsher-lighttext);
color: var(--zhsher-fontcolor);
padding: 0 .2em;
text-decoration: none
}

.tk-content span a:not([data-fancybox=gallery]):hover {
color: var(--zhsher-white);
background-color: var(--zhsher-theme);
border-radius: 4px
}

.tk-main .tk-content span > a {
border-bottom: none
}

#post-comment .comment-head {
font-size: .8em !important;
margin-bottom: .5rem
}

.el-input.el-input--small.el-input-group.el-input-group--prepend:focus-within::before {
display: block;
animation: commonTipsIn .3s
}

@keyframes commonTipsIn {
0% {
top: -50px;
opacity: 0
}
100% {
top: -60px;
opacity: 1
}
}

#twikoo .tk-input .el-textarea__inner {
min-height: 130px !important;
border-radius: 15px;
display: block;
resize: vertical;
padding: 16px 16px 40px 16px;
line-height: 1.5;
box-sizing: border-box;
width: 100%;
font-size: inherit;
color: #606266;
background-color: var(--zhsher-card-bg);
border: var(--style-border-always);
transition: border-color .2s cubic-bezier(.645, .045, .355, 1)
}

#page .el-textarea__inner {
background: var(--zhsher-card-bg) !important;
box-shadow: var(--zhsher-shadow-border);
color: var(--zhsher-fontcolor) !important
}

#twikoo.twikoo .el-input__inner:focus, #twikoo.twikoo .el-textarea__inner:focus {
border-color: var(--zhsher-main)
}

.tk-comments-container > .tk-comment {
margin-top: 0 !important;
margin-bottom: 1rem !important;
transition: .3s;
border-radius: 12px;
padding: 0;
padding-top: 1rem;
border: none;
border-top: var(--style-border-dashed)
}

#post-comment .comment-tips {
background-color: rgba(103, 194, 58, .13);
border: var(--style-border-always);
border-color: var(--zhsher-green);
color: var(--zhsher-green);
border-radius: 8px;
padding: 8px 12px;
margin-top: .5rem;
display: none
}

#post-comment .comment-tips.show {
display: flex
}

#page .tk-comments-container > .tk-comment {
background: var(--zhsher-card-bg);
padding: 1rem;
padding-bottom: 1rem;
border: var(--style-border);
border-top: var(--style-border);
box-shadow: var(--zhsher-shadow-border)
}

.tk-content {
margin-top: .5rem;
overflow: auto;
max-height: 500px
}

.page .el-input__inner {
background: var(--zhsher-card-bg) !important
}

.tk-comments .tk-row-actions-start {
position: relative;
top: -56px;
left: 17px
}

.tk-comments .tk-main .tk-row-actions-start {
position: relative;
top: -56px;
left: 2px
}

.OwO .OwO-body {
border: var(--style-border-always) !important;
border-radius: 8px !important;
overflow: hidden;
background-color: var(--zhsher-maskbg) !important;
backdrop-filter: saturate(180%) blur(10px);
cursor: auto;
top: 2.1em !important
}

@media screen and (max-width: 768px) {
.OwO .OwO-body {
width: 260px
}

.tk-comments .tk-main .tk-row-actions-start {
left: 30px
}
}

.OwO .OwO-body .OwO-items .OwO-item:hover {
box-shadow: var(--zhsher-shadow-lightblack) !important;
border-radius: 8px
}

#post-comment .tk-avatar.tk-clickable {
margin: 5px
}
/* gif动图 */
.tk-input textarea {
background-image: url('https://zhsher.cn/Hexo_img/config/Twikooback.gif');/* 图片地址 */
min-height: 120px !important; /* 默认是75px 拉高评论框大小 */
background-size:10em 10em; /* 设置图片长宽 */
/* background-color: #ffffff; */
transition: all 0.25s ease-in-out 0s; /* 动画过渡 */
}

.tk-input textarea:focus {
background-position-y: 130px;
transition: all 2s ease-in-out 0s!important;
}

修改主题配置文件_config.butterfly.yml,引入css文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/twikoo.css">

Twikoo回复邮件模板

原文地址:Twikoo评论回复邮件模板:Acrylic Mail 粉 | 张洪Heo

在前端面板修改配置

<div class="page flex-col">
<div class="box_3 flex-col" style="
display: flex;
position: relative;
width: 100%;
height: 206px;
background: #ef859d2e;
top: 0;
left: 0;
justify-content: center;
"><div class="section_1 flex-col" style="
background-image: url(&quot;这里更改为你的网站图标&quot;);
position: absolute;
width: 152px;
height: 152px;
display: flex;
top: 130px;
background-size: cover;
"></div></div>
<div class="box_4 flex-col" style="
margin-top: 92px;
display: flex;
flex-direction: column;
align-items: center;
">
<div class="text-group_5 flex-col justify-between" style="
display: flex;
flex-direction: column;
align-items: center;
margin: 0 20px;
">
<span class="text_1" style="
font-size: 26px;
font-family: PingFang-SC-Bold, PingFang-SC;
font-weight: bold;
color: #000000;
line-height: 37px;
text-align: center;
">嘿!你在&nbsp;${SITE_NAME}&nbsp;博客中收到一条新回复。</span>
<span class="text_2" style="
font-size: 16px;
font-family: PingFang-SC-Bold, PingFang-SC;
font-weight: bold;
color: #00000030;
line-height: 22px;
margin-top: 21px;
text-align: center;
">你之前的评论&nbsp;在&nbsp;${SITE_NAME} 博客中收到来自&nbsp;${NICK}&nbsp;的回复</span>
</div>
<div class="box_2 flex-row" style="
margin: 0 20px;
min-height: 128px;
background: #F7F7F7;
border-radius: 12px;
margin-top: 34px;
display: flex;
flex-direction: column;
align-items: flex-start;
padding: 32px 16px;
width: calc(100% - 40px);
">

<div class="text-wrapper_4 flex-col justify-between" style="
display: flex;
flex-direction: column;
margin-left: 30px;
margin-bottom: 16px;
">
<span class="text_3" style="
height: 22px;
font-size: 16px;
font-family: PingFang-SC-Bold, PingFang-SC;
font-weight: bold;
color: #C5343E;
line-height: 22px;
">${PARENT_NICK}</span>
<span class="text_4" style="
margin-top: 6px;
margin-right: 22px;
font-size: 16px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #000000;
line-height: 22px;
">${PARENT_COMMENT}</span>
</div><hr style="
display: flex;
position: relative;
border: 1px dashed #ef859d2e;
box-sizing: content-box;
height: 0px;
overflow: visible;
width: 100%;
"><div class="text-wrapper_4 flex-col justify-between" style="
display: flex;
flex-direction: column;
margin-left: 30px;
">
<hr>
<span class="text_3" style="
height: 22px;
font-size: 16px;
font-family: PingFang-SC-Bold, PingFang-SC;
font-weight: bold;
color: #C5343E;
line-height: 22px;
">${NICK}</span>
<span class="text_4" style="
margin-top: 6px;
margin-right: 22px;
font-size: 16px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #000000;
line-height: 22px;
">${COMMENT}</span>
</div>

<a class="text-wrapper_2 flex-col" style="
min-width: 106px;
height: 38px;
background: #ef859d38;
border-radius: 32px;
display: flex;
align-items: center;
justify-content: center;
text-decoration: none;
margin: auto;
margin-top: 32px;
" href="${POST_URL}">
<span class="text_5" style="
color: #DB214B;
">查看详情</span>
</a>
</div>
<div class="text-group_6 flex-col justify-between" style="
display: flex;
flex-direction: column;
align-items: center;
margin-top: 34px;
">
<span class="text_6" style="
height: 17px;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #00000045;
line-height: 17px;
">此邮件由评论服务自动发出,直接回复无效。</span>
<a class="text_7" style="
height: 17px;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #DB214B;
line-height: 17px;
margin-top: 6px;
text-decoration: none;
" href="${SITE_URL}">前往博客</a>
</div>
</div>
</div>

底部徽标美化

原文地址:徽标 | Akilarの糖果屋

徽标我使用shields.io在线生成,没有使用插件。Akilar的插件有动画效果,可以试一试!

shields.io格式:https://img.shields.io/badge/左侧文字-右侧文字-色值?style=flat&logo=xxx,色值支持十六进制、rgb、rgba、hsl、hsla,中文及符号需要转义字符对照表

logo设定:logo图标查询,如果没有对应图标可以使用在线图片转BASE64

html写好后,通过在线HTML压缩<body>中的内容压缩(不包括body),之后在主题配置文件_config.butterfly.yml中引入

footer:
- custom_text:
+ custom_text: 压缩的html代码

附我的模板,建议将徽标图片在网页中保存到博客路径中,而不是使用url,因为shields访问速度慢

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div>满地都是六便士 我想抬头看月亮</div>

<!-- <a onclick="window.open('https://beian.miit.gov.cn/#/Integrated/index')"
class="footer-a">晋ICP备2022005322号</a> -->
<p>
<a style="margin-inline:5px" target="_blank" href="https://beian.miit.gov.cn/#/Integrated/index/">
<img src="https://img.shields.io/badge/%E6%99%8BICP%E5%A4%87-2022005322%E5%8F%B7--1-e1d492?style=flat&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAdCAYAAAC9pNwMAAABS2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIi8+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+nhxg7wAACNlJREFUSInF1mmMVeUdx/Hv2e+5+519mJWBYQZkGxZZxLKJqBXGoLS1iXWrmihotFXaJiTWWlsbl6q1aetWd5u0VkKjNG4YEJSlOCibDLMwM8x679z9nnPP1jcVJUxf+7z6J8+LT37/Z4VvaQhfFS8+sBXbctCDGrVTKlBUH4mxAbI9Hfj0IJLsp6paJ5/tmn20N/D0wKDRMq9F/c3M2U1/V0vDfWMFh+tv/Ig1zYPMabDImPJ52OaXO87W580KggCiiOsJOJ6I3wcNFaaeNKxrt72f2fLGu4FpJ/sDQABRzD22fH7/Yze069vGc6mrDLNIJCDik10sxz2by3VdPM87xzkP9jwPTZFRVI1YUJKH+oy7n3tbvv/P2wW/UQxRWe6w4ZJRptYLHDoCuz8v5cP92XbI762O+h6UVWHnUFbPpU0fEb2A60mMJ7MUi9b/b7UgKhiZMaIxm8YLplLMDPz8hl/EH+rs8TNlUpFf32uyZJGLPDwCiTGUyTWodTN49eUCdz2YwXb9NNcObp1X98WDoufynzMVCEKGn27ayPTWBi5ad8P5iQUkJEnFLjqM9Z+hrVX0vfDe6K2dPRWsW2bwyp9EUifSJB84gdxrkR0eRgv1o/3I4fbbprJ6scqamzVO9pffec1S5ZWY2Nfz5qEy/FqOC2Y3s3j53HMSi18VRjFPwSwg+1RfVbl115vvJrsfej7UGIsYPPGgQ7JXoO+Xx5B3dHEomyJ9x1qiQozkr95h5937aFnVyouPlgJK+Ss7Fxz64OTSxSX+LHYxT2IsRW5kbGI4oHcR0jqoqTjV9se3I7/f8rS/ClS23GxSXhph6L5d9Akm7qqZhHWBQGUJ+CWGFzcg7e7m6D3/ZuW1Ea5YKdA3EojuONi813TqNi+YPYOKUhXDtCeGL26/hakLLiEcdsaHRkRAoLRc4fJrmhnekyF0apgZowWSwwkaa+rw3f8WA1GZZsPP5JEChX8dhZTN6iU6kAcs5s+dHd183SJ0VVKL57pfw6YdRQw23aeWTns47DPTALWlRTR7kMLew6hGgYqUhWXYFFUdPZ6lUBahLA8hVcOftckfi7No7VRAAQqsX1dybfvG1qwriM9mM5mJ4e4jO5Cc01dPqixbr8tWGBQUL4vjGigEEShi+xUmZ2RiR/sJ1pbS8NkgZrKAGw0TsgQsQyFaF/nfYTGprAlMFysbA1pI3mhkR6snhGsaymYGvPyFEb9IdbUE2AzFFTwpRqCtBY0wmdER+hZW4j63gcJj38V+/ErSUZXsYBfjIZHIRW0c2Z8BskCAqN+CbBJBFnyyKjR+Ez57nBxLqpfMUeSISElMBFz6x2Q6OxzWrYjyxWVzEewioU3LCS5vQY6nMUrLwNaxXvoQ59IloFSx54PPAZtQLExVZZDxsVE8J4dn6v4JYatgbSjk0owPw7RGH2ADMo88Z7L20ip8f7gC7fAo0q4+0rt7kEQDvaghVZbiPHUHcyeXcfLjT3jmpR7AYsnSScya3UR8bARVMck7Y/cB75/X6rDf3Fg2dw2jKZm5dXGm1LuAzO5DCo9v6aT0ibco5kzOvLOP+NGTFJtDpPYeZKijk/Rn3QxsfZV7txwhX7ABiZUXBsGvIvguQApNQQva9RMmTvZ2dpVUls+tX/UD7GN/Y8Ws05w6rQF+9vyzg1vZjbvMRJhXiRSU8DpTFFe0QE8S6SfPkOkZoktrB2oAhZWrwljxOPmchiSMYOWNoxNuruFU5vWeXdsojiUon345113dBBQBmTYlTimgdB8nfPo4WjaNFgN9OMEkJ02dnadVt5ki54Esqy+bzKJltVhSPbI3iN2zCyMTeXNCuG7Omm2Zok7PR2+R7jvD8ouruHhmCrB5jVZeYxLdrTP4sr4Vtd9g4MA4qc4c+6cu5NPamfw4P59t2WrA4YdXKkASf7SFivo6PDdEPmf1fRM++zp1bH/0r4I1dD1ODtOWaW4IsvPjL7nqXhloQiSPwjjgMYkMASyGEBkjhISCQwkwzve/18AbT+pk8pVY4UacQi9y+gyZ0eRAw4qHa89LXEx1LXMSPfhDJYRb59BtlLKg2WPT2l6qYl1svtGkrLYckyA1S+t5+2ATm37WCui0LSynsckDNH5zTxAchbQtkx08hDHYiW6NgC0enHBzEZ102UDH8QORdEckjEzZrNWkRydzyx17uGnDXqbUnGZ6dRPjSY91q2TqwjFuvTxLo5Zn5Qo/pumRSFcTLQtybEhGE0fQrDhhJ0VvH2lTnnHPhGtsmWan469apERjI2MH3qN7+7MEfH6ql29CbV7PvsMG32k6yU2XDhEKyZw66eJaRdrXR7CzCcqUNC3zwgymPJRCH4KRRLINimpL14A5Y4GDeOqbsPRVcfuN7Xj44pav/hFfrNT2kr2rsqf2Ibp5pEA14ZIImUyW3t5REkkTXRGQ/DGGhtLginhqCWknQDE5hKf5UFSF9Lj020Q2ul5V1AR2hr+8vuP8Vlc2zMPRxoSjnx7XBC14sDoydahSGq7KdO/HFyrBchxCVfX4fDKp4T7SCQejYODZLrYgIqgKFsNIgQqEYob8mW6yiUyb7Z64LVK/+B85xznnJ3AWzqTzuIX46mr5wLs+UUTyIriBCjRNxguHMJIFDLEEvXEOVRWnSJ0+jCd4CJoGjoedM1CLcXQziW3nMV2TSMBeOx7vWZvPt1r+cMPzE8KunaUkFn0vNrvtqXj34c1W6gzxlEQ6naIoBahtnkMwoFMwIVzSRNguMt53Aj2s4nkSlgPoGqLkICsRNF0gl8rYWuP8+11/w/OOJDEhHPKLCIpOXmi+M9AgP+maiesLifF2T1Rn5ZNj5Lo/Qc/GcPMmhdoqlEgIGzCK4PiCmJKK68p4KfF3qYGuF0qCRUkJTzleUbvQyWRTuE5xYthxQbBs7EISAbkzUFG3VfXXbK2YFi3X/eryfKKnqVBItNjJxDzH8erddC4SqWwcN5WyTtlyO1RP/Lh3eHD76MB40swmiDVJyDLYRhpc5+ub6tse/wWKbvSQEAw1awAAAABJRU5ErkJggg==
" title="ICP备案">
</a>
<a style="margin-inline:5px" target="_blank" href="https://hexo.io/">
<img src="https://img.shields.io/badge/Frame-Hexo-blue?style=flat&logo=hexo" title="博客框架为Hexo">
</a>
<a style="margin-inline:5px" target="_blank" href="https://butterfly.js.org/">
<img src="https://img.shields.io/badge/Theme-Butterfly-6513df?style=flat&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAXCAMAAADX9CSSAAABnlBMVEUAAAAYERBJLh1JJBTeu7EjEgo5HRRaHjwxIBsaEQ4dHSEeOUjZ2dk8JBs0Mzza3dodExQcFhIZNVBfNyxXQjBWTklxaWRAX3EkEgZWHEwiEQAZZIgPDxIUOFhAOzYobpQ8orkjXoJHoLjJyclBdYokJCE7PUItKyxFSVE4obJQPStAkp80s8pAJBMcWHUOJUERFBgQAAAfNEoPIzsndpklIi0gIi4SFBkcP2wcVXAcQnEmTWomcZkoT20sZY4uOD8fHR4pVnopVnlDbHM6kqIziJmqqqUnoPg1zP8vyP84vf8/wf8xw/8ltP9L4v8lv/8wz/8nzv4bVpop2f8xy/8osf440P8u5P8mk/QjjPUvfKojp/EchdIyu/Ahbs0YXqIio/8pxP8qxvs5wvgnh94lsP1C0f9A6/87xP4puv8lqP1Czf8znO1Ax/8KDQs7qv8ldKsnxv8ulcI64/ImpNw75P8s9P8tuP0sPkotjc4oKz8nrPMhme4gluomdZ1B3f84sf9Crtgtfa4tYYw4sv9CrdUuZJJB3P8kbNEjb9U867bWAAAAR3RSTlMAxTQTEU0fAidq1OoDG2MYdYfmF8bLTsr9CQ/p1PhE6fL+9gnlq4+KH8p0d9vj/fj3P+H267m99MH5xoz+lONNu9PS5vrxNhiY9jsAAAGGSURBVHhefY/VbuMAEEXHiWs7YIeZysyMi2AOMzOUmXn5r3fXTtT2oXuk0Ujn4d4ZeA3tMEHiLxVJDGthSG18P6h4ZhWDH4zqIXi3u8899FMAWpCG6v/O7+8igCFf93b8vRTo+qBPB1Svf2fvB0IAKDTb91v+7rcoCijq7fZvfdvWSLkDaZ6vN0ZMOtCZRhp1nn8ckIpUPRzX/Hk0hn5Bx47umhzXo5L9usAGmZNxq8U6fsIEWeFW9jMrQjTInl3ZJmxXZ2wwKkx2SR7T5BgmGvt9ab/8FYsyTE5DSB5X+SrxOHtxbj+/YOPxyry+/X+XqxxJJE4/2T+fJhKRskuOAWw2UwpFIqGPE7Z/q5QxyjmKuRsxEDo4tpgtxwehgHg95ZW8Q53drLUCh2ar+TDQqm1m1UqQMBSKdExMj8JoWozRxYKh0+tJ0TTtIwB783cnPe1eULrDqWR1Awd8rZpMhd2mtsdVS+H8KgkA5HI+PK13QAc9sijfhi0gBngCdyo7mU4c/scfy35OuevmbR0AAAAASUVORK5CYII=
" title="主题采用butterfly">
</a>

<a style="margin-inline:5px" target="_blank" href="https://cloud.tencent.com/ ">
<img src="https://img.shields.io/badge/Hosted-腾讯云-0cedbe?style=flat&logo=iCloud"
title="本站采用双线部署,国内线路托管于腾讯云">
</a>

<a style="margin-inline:5px" target="_blank" href="https://github.com/">
<img src="https://img.shields.io/badge/Source-Github-d021d6?style=flat&logo=GitHub"
title="本站采用双线部署,国外线路托管于Github">
</a>
<a style="margin-inline:5px" target="_blank" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
<img src="https://img.shields.io/badge/Copyright-BY--NC--SA%204.0-d42328?style=flat&logo=Claris"
title="本站采用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议进行许可">
</a>
</p>
</body>
</html>

一图流

原文地址:

小张采用店长方案

修改主题配置文件_config.butterfly.ymlbackground配置项,设置全局背景

# Website Background (設置網站背景)
# can set it to color or image (可設置圖片 或者 顔色)
# The formal of image: url(http://xxxxxx.com/xxx.jpg)
background: url(http://xxxxxx.com/xxx.jpg)

新建[BlogRoot]/source/css/bg.css

/* 页脚透明 */
#footer{
background: transparent!important;
}
/* 页脚黑色透明玻璃效果移除 */
#footer::before{
background: transparent!important;
}
/* 头图透明 */
#page-header{
background: transparent!important;
}
/* 头图遮罩层透明 */
#page-header::before{
background: transparent!important;
}
/*top-img黑色透明玻璃效果移除,不建议加,除非你执着于完全一图流或者背景图对比色明显 */
#page-header.post-bg:before {
background-color: transparent!important;
}
/*夜间模式伪类遮罩层透明*/
[data-theme="dark"]
#footer::before{
background: transparent!important;
}
[data-theme="dark"]
#page-header::before{
background: transparent!important;
}

修改主题配置文件_config.butterfly.yml,引入css文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/bg.css">

夜间模式繁星

原文地址:Hexo博客夜间模式繁星(宇宙)效果 | Leonus

新建[BlogRoot]/source/js/universe.js

function dark() {
window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
var n, e, i, h, t = .05,
s = document.getElementById("universe"),
o = !0,
a = "180,184,240",
r = "226,225,142",
d = "226,225,224",
c = [];

function f() {
n = window.innerWidth, e = window.innerHeight, i = .216 * n, s.setAttribute("width", n), s.setAttribute("height", e)
}
function u() {
h.clearRect(0, 0, n, e);
for (var t = c.length, i = 0; i < t; i++) {
var s = c[i];
s.move(), s.fadeIn(), s.fadeOut(), s.draw()
}
}
function y() {
this.reset = function() {
this.giant = m(3), this.comet = !this.giant && !o && m(10), this.x = l(0, n - 10), this.y = l(0, e), this.r = l(1.1, 2.6), this.dx = l(t, 6 * t) + (this.comet + 1 - 1) * t * l(50, 120) + 2 * t, this.dy = -l(t, 6 * t) - (this.comet + 1 - 1) * t * l(50, 120), this.fadingOut = null, this.fadingIn = !0, this.opacity = 0, this.opacityTresh = l(.2, 1 - .4 * (this.comet + 1 - 1)), this.do = l(5e-4, .002) + .001 * (this.comet + 1 - 1)
}, this.fadeIn = function() {
this.fadingIn && (this.fadingIn = !(this.opacity > this.opacityTresh), this.opacity += this.do)
}, this.fadeOut = function() {
this.fadingOut && (this.fadingOut = !(this.opacity < 0), this.opacity -= this.do /2,(this.x>n||this.y<0)&&(this.fadingOut=!1,this.reset()))},this.draw=function(){if(h.beginPath(),this.giant)h.fillStyle="rgba("+a+","+this.opacity+")",h.arc(this.x,this.y,2,0,2*Math.PI,!1);else if(this.comet){h.fillStyle="rgba("+d+","+this.opacity+")",h.arc(this.x,this.y,1.5,0,2*Math.PI,!1);for(var t=0;t<30;t++)h.fillStyle="rgba("+d+","+(this.opacity-this.opacity/20 * t) + ")", h.rect(this.x - this.dx / 4 * t, this.y - this.dy / 4 * t - 2, 2, 2), h.fill()
} else h.fillStyle = "rgba(" + r + "," + this.opacity + ")", h.rect(this.x, this.y, this.r, this.r);
h.closePath(), h.fill()
}, this.move = function() {
this.x += this.dx, this.y += this.dy, !1 === this.fadingOut && this.reset(), (this.x > n - n / 4 || this.y < 0) && (this.fadingOut = !0)
}, setTimeout(function() {
o = !1
}, 50)
}
function m(t) {
return Math.floor(1e3 * Math.random()) + 1 < 10 * t
}
function l(t, i) {
return Math.random() * (i - t) + t
}
f(), window.addEventListener("resize", f, !1), function() {
h = s.getContext("2d");
for (var t = 0; t < i; t++) c[t] = new y, c[t].reset();
u()
}(), function t() {
document.getElementsByTagName('html')[0].getAttribute('data-theme') == 'dark' && u(), window.requestAnimationFrame(t)
}()
};
dark()

新建[BlogRoot]/source/css/universe.css

#universe {
display: block;
position: fixed;
margin: 0;
padding: 0;
border: 0;
outline: 0;
left: 0;
top: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 1;
}

@media screen and (max-width: 768px) {
#universe {
display: none;
}

/* 下面这个是切换手机背景的代码,有需要的可以使用,没需要的删了就行 */
/*#web_bg {*/
/* background-image: url("https://img.vm.laomishuo.com/image/2021/05/2021053107390019.jpeg");*/
/*}*/
}

/* leonus微调 */
[data-theme='light'] #universe{
display: none;
}

修改主题配置文件_config.butterfly.yml,引入css、js文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/universe.css">
bottom:
# - <script src="xxxx"></script>
+ - <canvas id="universe"></canvas> # 创建画布
+ - <script async src="/js/universe.js"></script> # 引入js

友链申请按钮

Leonus控制台爬的

新建[BlogRoot]/source/css/applybutton.js

// 申请友链
function linkCom(type) {
var n = document.querySelector(".el-textarea__inner")
if (type == 'bf') {
n.value = '```yml\n';
n.value += `- name:
link:
avatar:
descr: `;
n.value += '\n```';
n.setSelectionRange(15, 15);
} else {
n.value = '```yml\n';
n.value += `站点名称:
站点地址:
头像链接:
站点描述:`;
n.value += '\n```';
n.setSelectionRange(5, 5);
}
n.focus();
}

新建[BlogRoot]/source/css/applybutton.css

.addBtn button:hover {
background: #da6c7d;
color: white;
}
[data-theme=dark] .addBtn button:hover {
background: #96a7be;
}
.addBtn {
display: flex;
justify-content: center;
flex-wrap: wrap;
}
.addBtn i{
font-size: 1.3rem;
margin-right: 10px;
}
.addBtn button {
transtion: .2s;
display: flex;
margin: 5px auto;
color: var(--global-bg);
padding: 15px;
border-radius: 12px;
background: var(--search-result-title);
align-items: center;
}

修改主题配置文件_config.butterfly.yml,引入css、js文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/applybutton.css">
bottom:
# - <script src="xxxx"></script>
+ - <script async src="/js/applybutton.js"></script>

[BlogRoot]/source/link/index.md底部插入

<div class="addBtn">
<button onclick="linkCom()"><i class="fa-solid fa-circle-plus"></i>快速申请 (默认样式)</button>
<button onclick="linkCom('bf')"><i class="fa-solid fa-circle-plus"></i>快速申请 (Butterfly)</button>
</div>

控制台彩蛋

原文地址:console的高级用法 | 安知鱼

新建[BlogRoot]/source/js/print.js

var now1 = new Date()

function createtime1() {
var grt = new Date('05/01/2022 00:00:00') //此处修改你的建站时间或者网站上线时间
now1.setTime(now1.getTime() + 250)
var days = (now1 - grt) / 1000 / 60 / 60 / 24
var dnum = Math.floor(days)

var ascll = [
`欢迎来到张时贰\`Blog!`,
`洞庭春溜满,平湖锦帆张,称小张。十二为一年亦半天亦...家人、恋人、朋友...安好、知心、快乐...十二画,时间、人、情绪,十二是我最喜欢的数字,故称张时贰!`,
`

██╗ ██╗██╗ ██████╗ ██╗ ███████╗████████╗
██║ ██║██║██╔═══██╗██║ ██╔════╝╚══██╔══╝
██║ ██║██║██║ ██║██║ █████╗ ██║
╚██╗ ██╔╝██║██║ ██║██║ ██╔══╝ ██║
╚████╔╝ ██║╚██████╔╝███████╗███████╗ ██║
╚═══╝ ╚═╝ ╚═════╝ ╚══════╝╚══════╝ ╚═╝

`,
'张时贰`Blog 已上线',
dnum,
'天',
'©2022 By 张时贰',
]

setTimeout(
console.log.bind(
console,
`\n%c${ascll[0]} %c ${ascll[1]} %c ${ascll[2]} %c${ascll[3]}%c ${ascll[4]}%c ${ascll[5]}\n\n%c ${ascll[6]}\n`,
'color:#425aef',
'',
'color:#425aef',
'color:#425aef',
'',
'color:#425aef',
''
)
)
}

createtime1()

function createtime2() {
var ascll2 = [`NCC2-036`, `调用前置摄像头拍照成功,识别为【小笨蛋】.`, `Photo captured: `, ` 🤪 `]

setTimeout(
console.log.bind(
console,
`%c ${ascll2[0]} %c ${ascll2[1]} %c \n${ascll2[2]} %c\n${ascll2[3]}\n`,
'color:white; background-color:#4fd953',
'',
'',
'background:url("https://q1.qlogo.cn/g?b=qq&nk=1310446718&s=5") no-repeat;font-size:450%'
)
)

setTimeout(
console.log.bind(
console,
'%c WELCOME %c 你好,小笨蛋.',
'color:white; background-color:#4f90d9',
''
)
)

setTimeout(
console.warn.bind(
console,
'%c ⚡ Powered by 张时贰 %c 你正在访问 张时贰 的博客.',
'color:white; background-color:#f0ad4e',
''
)
)

setTimeout(
console.log.bind(
console,
'%c W23-12 %c 你已打开控制台.',
'color:white; background-color:#4f90d9',
''
)
)
setTimeout(
console.warn.bind(
console,
'%c S013-782 %c 你现在正处于监控中.',
'color:white; background-color:#d9534f',
''
)
)
}
createtime2()

console.log = function () {}

修改主题配置文件_config.butterfly.yml,引入js文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
bottom:
# - <script src="xxxx"></script>
+ - <script async src="/js/print.js"></script>

动态title

新建[BlogRoot]/source/js/title.js

//标题
var OriginTitile = document.title; // 保存之前页面标题
var titleTime;
document.addEventListener('visibilitychange', function(){
if (document.hidden){
document.title = '404 Not Found';
clearTimeout(titleTime);
}else{
document.title = 'ヾ(≧▽≦*)o上当了吧嘿嘿';
titleTime = setTimeout(function() {
document.title = OriginTitile;
}, 3000); // 3秒后恢复原标题
}
});

修改主题配置文件_config.butterfly.yml,引入js文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
bottom:
# - <script src="xxxx"></script>
+ - <script async src="/js/title.js"></script>

鼠标样式

自己制作ico格式图片或者下载致美化cur格式文件存放在[BlogRoot]/source/css

新建[BlogRoot]/source/css/curtor.css

/* 鼠标样式 */
/* 默认时 */
body {
cursor: url(close.ico),
default;
}

/* 链接、图片 */
a,
img {
cursor: url(open.ico),
default;
}

修改主题配置文件_config.butterfly.yml,引入css文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/cursor.css">

全站变灰

原文地址:Custom Beautify | Akilarの糖果屋

有时候一些哀悼日、纪念日需要变灰时使用

新建[BlogRoot]/source/js/gray.js

方案一:店长方案,通过JS在特定日期变灰

if(PublicSacrificeDay()){
document.getElementsByTagName("html")[0].setAttribute("style","filter:gray !important;filter:grayscale(100%);-webkit-filter:grayscale(100%);-moz-filter:grayscale(100%);-ms-filter:grayscale(100%);-o-filter:grayscale(100%);");
}

function PublicSacrificeDay(){
var PSFarr=new Array("0403","0404","0405","0406","0414","0512","0707","0807","0814","0909","0918","0930","1025","1213");
//202044日 新冠肺炎哀悼日,清明节
//2010414日,青海玉树地震
//2008512日,四川汶川地震
//193777日,七七事变 又称卢沟桥事变
//201087日,甘肃舟曲特大泥石流
//814日,世界慰安妇纪念日
//197699日,毛主席逝世
//1931918日,九一八事变
//烈士纪念日为每年930
//19501025日,抗美援朝纪念日
//19371213日,南京大屠杀
var currentdate = new Date();
var str = "";
var mm = currentdate.getMonth()+1;
if(currentdate.getMonth()>9){
str += mm;
}else{
str += "0" + mm;
}
if(currentdate.getDate()>9){
str += currentdate.getDate();
}else{
str += "0" + currentdate.getDate();
}
if(PSFarr.indexOf(str)>-1){
return 1;
}else{
return 0;
}
}

修改主题配置文件_config.butterfly.yml,引入js文件

inject:
bottom:
+ - <script async src="/css/gray.js"></script>

方案二:在需要时手动加入

新建[BlogRoot]/source/js/gray.css

html {
-webkit-filter: grayscale(100%);
filter: progid:DXImageTransform.Microsoft.BasicImage(graysale=1);
}

修改主题配置文件_config.butterfly.yml,引入css文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/gray.css">

方案三:电脑不在跟前且是服务器部署,修改nginx配置文件(不知道配置文件位置可以借助宝塔,参考网站监控中图文说明)

http {
……
# 上面为其他配置项

# 全站页面变灰,用于哀悼日
sub_filter '</head>' '<style type="text/css">html { -webkit-filter: grayscale(100%); -moz-filter: grayscale(100%); -ms-filter: grayscale(100%); -o-filter: grayscale(100%); filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1); filter: gray;}</style></head>';
sub_filter_types *;
sub_filter_once off;
}

黑幕

原文地址:简单、快速地实现萌娘百科黑幕效果 - Initial_heart’s Blog

新建[BlogRoot]/source/css/dark span.css

/* 萌娘百科 “黑幕” */
/* 以下内容引用自萌娘百科 https://zh.moegirl.org.cn/MediaWiki:Gadget-site-styles.css,感谢! */
/* MoeGirl Start */
/* 参考https://www.initbili.top/2022/dba42bb67415/ */
/* <span class="heimu" title="你知道的太多了">内容</span> */
.heimu,
.heimu rt{
background-color:gray;
}
.heimu,
.heimu a,
a .heimu,
a.new .heimu,
span.heimu a.new,
span.heimu a.external,
span.heimu a.external:visited,
span.heimu a.extiw,
span.heimu a.extiw:visited,
span.heimu a.mw-disambig,
span.heimu a.mw-redirect{
transition:color 0.13s linear;
color:gray;
text-shadow:none;
}

span.heimu:hover,
span.heimu:active{
color:white;
}

span.heimu:hover a,
a:hover span.heimu{
color:lightblue;
}

span.heimu:hover a:visited,
a:visited:hover span.heimu{
color:#C5CAE9;
}

span.heimu:hover a.new,
a.new:hover span.heimu{
color:#FCC;
}

span.heimu a.new:hover:visited,
a.new:hover:visited span.heimu{
color:#EF9A9A;
}

span.heimu:hover a.extiw:visited,
a.extiw:visited:hover span.heimu{
color:#D1C4E9;
}

修改主题配置文件_config.butterfly.yml,引入css文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/dark span.css">

访客统计与信息

首先注册申请51la,拿到统计代码,可参考51la统计体验报告:很全面的惊喜,Butterfly适配51la统计 | 张洪Heo

原文地址:

主题文档:

访问统计侧边栏

新建[BlogRoot]/source/_data/widget.yml

bottom:
- class_name:
id_name:
name: 访问统计
icon: iconfont icon-tongji
order: 1
html: <link rel="stylesheet" href="/css/visitor.css"><div id="visitor"><div class="content"></div></div><script src="/js/visitor.js"></script>

新建[BlogRoot]/source/js/visitor.js,注意修改51la地址

// 侧边栏访问统计
fetch('https://v6-widget.51.la/v6/xxxxxxxxxxxxxx/quote.js').then(res => res.text()).then((data) => {
let title = ['最近活跃访客', '今日访问人数', '今日访问量', '昨日人数', '昨日访问量', '本月访问量', '总访问量']
let num = data.match(/(?<=<\/span><span>).*?(?=<\/span><\/p>)/g)
let s = document.querySelectorAll('#visitor .content')[0]
if (s !== undefined) {
for (let i = 0; i < num.length; i++) {
if (i == 3 || i == 4) continue;
s.innerHTML += '<div><p><span id=name>' + title[i] + '</span><span class="num">' + num[i] + '</span></p></div>'
}
}
});

新建[BlogRoot]/source/css/visitor.css

/* 侧边栏访问统计样式 */
#visitor {
box-sizing: border-box !important;
margin: 0px !important;
font-size: 18px !important;
line-height: 1.7 !important;
color: rgb(51, 51, 51) !important;
background-color: rgb(255, 255, 255) !important;
padding: 16px 0px !important;
border: 1px solid rgb(255, 255, 255) !important;
height: auto !important;
}

#visitor div p {
margin: 0px !important;
text-align: left !important;
}

#visitor div #name {
color: rgb(137, 137, 137) !important;
display: inline-block !important;
}

#visitor div .num {
color: rgb(51, 51, 51) !important;
font-weight: bold !important;
float: right !important;
}

修改主题配置文件_config.butterfly.yml,引入css、js文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/visitor.css">
bottom:
# - <script src="xxxx"></script>
+ - <script src="/js/visitor.js"></script>

访客信息

效果预览:关于 | 心流

只需在md文件中插入

## 博客统计

### 访客统计
<div id="pvisitor">
<div class="content"></div>
</div>

### 访客信息
<div id="ivisitor">
<div class="content"></div>
</div>

<link rel="stylesheet" href="/css/visitor.css">

<script>
fetch('https://v6-widget.51.la/v6/xxxxxxxxxxxxxx/quote.js').then(res => res.text()).then((data) => {
let title = ['最近活跃访客', '今日访问人数', '今日访问量', '昨日人数', '昨日访问量', '本月访问量', '总访问量']
let num = data.match(/(?<=<\/span><span>).*?(?=<\/span><\/p>)/g)
let s = document.querySelectorAll('#pvisitor .content')[0]
for (let i = 0; i < num.length; i++) {
if (i == 3 || i == 4) continue;
s.innerHTML += '<div><span>' + title[i] + '</span><span class="num">' + num[i] + '</span></div>'
}
});
fetch('https://api.vvhan.com/api/visitor.info').then(res => res.json()).then((data) => { //获取访客信息
let c = document.querySelectorAll('#ivisitor .content')[0]
var system = data['system']
var addr = data['location']
var ipaddr = data['ip']
var weather = data['tq']+"&nbsp"+data['high'].replace("最低 ","")+"~"+data['high'].replace("最高 ","")
var tip = data['tip']
system = system==="未知操作系统"?"移动端":system
addr = addr===null?"未知":addr
ipaddr = ipaddr===null?"未知":ipaddr
weather = weather===null?"未知":weather
tip = tip===null?"未知":tip
c.innerHTML = `<div><span>系统</span><span class="num">${system}</span></div>
<div><span>地址</span><span class="num">${addr}</span></div>
<div><span>IP地址</span><span class="num">${ipaddr}</span></div>
<div><span>天气</span><span class="num">${weather}</span></div>
<div><span>温馨提示</span><span class="num">
<div style="width:100% !important"><span style="font-size:1.5rem;font-weight:bold;display:block;">${tip}</span></div>
</span></div>
`
});
</script>

新建[BlogRoot]/source/css/ivisitor.css

/* 关于页面访问统计、访客信息样式 */
#pvisitor,
#ivisitor {
font-size: 18px;
padding: 20px;
border-radius: 12px;
width: 100%;
color: var(--font-color);
background-color: var(--card-bg);
}

div#pvisitor .content,
div#ivisitor .content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}

div#pvisitor a,
div#ivisitor a {
text-decoration: none;
}

#pvisitor .content div,
#ivisitor .content div {
display: inline-block;
}

#pvisitor div span,
#ivisitor div span {
font-size: 14px;
line-height: 1.3;
display: block;
}

#pvisitor div .num,
#ivisitor div .num {
letter-spacing: 1px;
font-weight: bold;
font-size: 1.6rem;
margin-bottom: .8rem;
}

修改主题配置文件_config.butterfly.yml,引入css文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/ivisitor.css">

访客统计&访客信息合并版

我想把访客统计和访客信息合并在一起,对心流的方案进行了更改,主要变更了innerHTML结构及css样式

新建[BlogRoot]/source/_data/widget.yml

bottom:
- class_name:
id_name:
name: 你好呀
icon: fa-solid fa-child
order: 1
html: <link rel="stylesheet" href="/css/visitor.css"><div id="visitor"><div class="content"></div></div><div id="visitor"><div class="content"></div></div><script src="/js/visitor.js"></script>

新建[BlogRoot]/source/css/visitor.css

/* 侧边栏访问统计样式 */
#visitor {
box-sizing: border-box !important;
margin: 0px !important;
font-size: var(--global-font-size);
line-height: 1.7 !important;
color: rgb(51, 51, 51) !important;
height: auto !important;
}

/* 单一行调整间距 */
#visitor div p {
margin: 0px !important;
text-align: left !important;
}

/* 左侧竖列 */
#visitor div #name {
color: rgb(137, 137, 137) !important;
display: inline-block !important;
}

/* 右侧竖列 */
#visitor div .num {
color: rgb(51, 51, 51) !important;
letter-spacing: 1px;
font-weight: bold;
float: right !important;
}

新建[BlogRoot]/source/js/visitor.js,注意修改51la地址

//获取访客信息
fetch('https://api.vvhan.com/api/visitor.info').then(res => res.json()).then((data) => { //获取访客信息
let c = document.querySelectorAll('#visitor .content')[0]
var system = data['system']
var addr = data['location']
var ipaddr = data['ip']
var weather = data['tq'] + "&nbsp" + data['high'].replace("最低 ", "") + "~" + data['high'].replace("最高 ", "")
var tip = data['tip']
var f1 = data['fl']
system = system === "未知操作系统" ? "移动端" : system
addr = addr === null ? "未知" : addr
ipaddr = ipaddr === null ? "未知" : ipaddr
weather = weather === null ? "未知" : weather
tip = tip === null ? "未知" : tip
f1 = f1 === null ? "未知" : f1
c.innerHTML = `<div><p><span id=name>系统</span><span class="num">${system}</span></p></div>
<div><p><span id=name>地址</span><span class="num">${addr}</span></p></div>
<div><p><span id=name>IP地址</span><span class="num">${ipaddr}</span></p></div>
<div><p><span id=name>天气</span><span class="num">${weather}</span></p></div>
<div><p><span id=name>风级</span><span class="num">${f1}</span></p></div>
<div><p><span id=name>温馨提示</span><span class="num">
<div style="width:100% !important"><span style="font-weight:bold;display:block;">${tip}</span></div>
</p></span></div>
`
});

//获取51la统计
fetch('https://v6-widget.51.la/v6/xxxxxxxxxx/quote.js').then(res => res.text()).then((data) => {
let title = ['最近活跃访客', '今日访问人数', '今日访问量', '昨日人数', '昨日访问量', '本月访问量', '总访问量']
let num = data.match(/(?<=<\/span><span>).*?(?=<\/span><\/p>)/g)
let s = document.querySelectorAll('#visitor .content')[1]
if (s !== undefined) {
for (let i = 0; i < num.length; i++) {
if (i == 3 || i == 4) continue;
s.innerHTML += '<div><p><span id=name>' + title[i] + '</span id=name><span class="num">' + num[i] + '</span></p></div>'
}
}
});

顶部卡片

来源:Leonus - 进一寸有进一寸的欢喜控制台扒的

Heo哥、Leonus、安知鱼等朋友圈、即刻短文等顶部都有一张卡片,蛮不错,所以扒了一下

在需要使用的页面顶部插入

<!-- 顶部卡片 -->
<div class="page-top-card" style="background-image: url(https://图片地址);">
<div class="content-item-tips">动态</div>
<span class="content-item-title">空间说说</span>
<div class="content-bottom">
<div class="tips">我的生活、吐槽、闲话...</div>
<a class="banner-button" href="https://www.cn">
<i class="fa-solid fa-image"></i><span>关于我</span>
</a>
</div>
</div>
<style type="text/css">
#page-header.not-home-page {
height: 50px;
}
div#page-site-info {
display: none;
}
.page-top-card {
background-size: cover;
background-position: center;
height: 20rem;
padding: 10px 2.7rem;
border-radius: 20px;
color: #fff;
position: relative
}
span.content-item-title {
font-size: 2.3em;
font-weight: 700;
line-height: 1.2
}
.content-bottom {
display: flex;
justify-content: space-between;
align-items: center;
position: absolute;
width: calc(100% - 5.4rem);
bottom: 1rem
}
a.banner-button {
cursor: pointer;
color: #fff !important;
backdrop-filter: saturate(180%) blur(20px);
background: rgb(120 120 120 / 30%);
padding: 5px 15px;
border-radius: 100px;
text-decoration: none !important
}
a.banner-button i {
margin-right: 5px
}
a.banner-button:hover {
background: var(--btn-bg);
}
[data-theme=dark] .page-top-card {
opacity: .7
}
@media screen and (max-width:900px) {
.page-top-card {
padding: 10px 1rem;
height: 12rem;
margin: 0 5px
}
.content-bottom {
width: calc(100% - 2rem)
}
a.banner-button span {
display: none
}
a.banner-button {
width: 50px;
height: 35px;
display: flex;
align-items: center;
justify-content: center
}
a.banner-button i {
margin: 0
}
}
</style>

文章目录

新建[BlogRoot]/source/css/aside_toc.css

方案一,透明目录(Heo化太多了,自己直接做透明了,最好手动调一下颜色让文字鲜艳些以适配自己的背景)

/* PC端下目录透明 */
@media screen and (min-width: 900px) {
#aside-content .card-widget#card-toc {
background-color: transparent !important;
box-shadow: none !important;
border: none;
}

#aside-content #card-toc .item-headline {
opacity: 0;
}
}

/* 去掉主题原先的杠 */
#aside-content #card-toc .toc-content > * > .toc-item > .toc-child {
border-left: none !important;
}

/* 当前小节前样式及小杠 */
#aside-content #card-toc .toc-content .toc-link.active {
display: flex;
transform: scale(1.2);
background: none;
color: var(--zhsher-lighttext); /* 第一处颜色 */
font-weight: bold;
}

#aside-content #card-toc .toc-content .toc-link.active:before {
content: " " !important;
margin-top: 0.8rem !important;
margin-right: 0.5rem;
width: 0.8rem !important;
height: 0.2rem !important;
border-radius: 0.1rem !important;
background: var(--zhsher-lighttext); /* 第二处颜色 */
}

/* 隐藏滚动条 */
#aside-content #card-toc .toc-content::-webkit-scrollbar-thumb, #aside-content #card-toc .toc-content::-webkit-scrollbar-corner {
background-color: transparent;
}

方案二,heo哥目录(取自heo哥F12)

/* 文章目录 */
#aside-content #card-toc .toc-content .toc-link.active {
line-height: 1.2;
border-radius: 12px;
border-left-color: var(--heo-hovertext);
background-color: var(--heo-card-bg);
color: var(--heo-lighttext);
font-weight: bold;
font-size: 20px;
}

[data-theme=dark].toc .toc-item.active .toc-link .toc-text {
color: var(--heo-white);
}

#aside-content #card-toc .toc-content .toc-item.active .toc-link {
opacity: 1;
border-radius: 8px;
}

#aside-content #card-toc .toc-content .toc-link {
line-height: 1.2;
padding: 8px;
border-left: 0px solid transparent;
border-radius: 12px;
color: var(--heo-secondtext);
cursor: default;
}

#aside-content #card-toc .toc-content .toc-link:not(.active) span {
opacity: 0.6;
cursor: pointer;
filter: blur(1px);
transition: 0.3s;
}

#aside-content #card-toc:hover .toc-content .toc-link:not(.active) span {
filter: blur(0px);
opacity: 1;
}

#aside-content #card-toc .toc-content .toc-link:not(.active) span:hover {
color: var(--heo-lighttext);
}

/* 目录卡片边距 */
#card-toc {
padding: 0.5rem 0.5rem !important;
}

修改主题配置文件_config.butterfly.yml,引入css文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/aside_toc.css">

小张比较喜欢简化风格,所以隐藏了除目录外的其它卡片,toc.style_simple: true

Github 贡献日历

原文地址:hexo-githubcalendar | 小冰博客

安装

npm i hexo-githubcalendar --save

修改配置文件 _config.yml,在最后新增

# Ice Kano Plus_in
# Hexo Github Canlendar
# Author: Ice Kano
# Modify: Lete乐特
githubcalendar:
enable: true
priority: 3
enable_page: /
user: GC-ZF # <- 改为自己的Github用户名
layout:
type: id
name: recent-posts
index: 0
githubcalendar_html: '<div class="recent-post-item" style="width:100%;height:auto;padding:10px;"><div id="github_loading" style="width:10%;height:100%;margin:0 auto;display: block"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50" xml:space="preserve"><path fill="#d0d0d0" d="M25.251,6.461c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615V6.461z" transform="rotate(275.098 25 25)"><animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="0.6s" repeatCount="indefinite"></animateTransform></path></svg></div><div id="github_container"></div></div>'
pc_minheight: 280px
mobile_minheight: 0px
color: "['#ebedf0', '#fdcdec', '#fc9bd9', '#fa6ac5', '#f838b2', '#f5089f', '#c4067e', '#92055e', '#540336', '#48022f', '#30021f']"
api: https://gitcalendar.zfe.space/api
# api: https://python-gitee-calendar-api.vercel.app/api
calendar_js: https://jsd.onmicrosoft.cn/gh/Zfour/hexo-github-calendar@1.21/hexo_githubcalendar.min.js
plus_style: ""

在其它页面中挂载,只需在对应md文件中插入

<div name="我是墙" id="history_calendar">
<!-- id=>type recent-posts=>name -->
<div name="我是画框">
<div name="我是纸">
<!--这里通过js挂载githubcalendar,也就是画画-->
</div>
</div>
</div>

文章双栏布局

原文地址:

安装

npm i hexo-butterfly-article-double-row --save

修改配置文件 _config.yml,在最后新增

butterfly_article_double_row:
enable: true

如果每页文章太少,可以调整index_generator属性

index_generator:
path: ''
per_page: 12
order_by: -date

但是文章最后一页页码按钮会错位,所以不用插件直接用小冰老师的css文件做一个微调

新建[BlogRoot]/source/css/double row.css

#recent-posts {
margin-top: -1rem; /*头部抵消间隔*/
align-content: flex-start;
display: flex;
flex-wrap: wrap; /*规定灵活的项目在必要的时候拆行或拆列。*/
justify-content: space-between; /*。*/
}

#recent-posts > .recent-post-item {
/*max-height:324px;*/ /*文章容器最大高度*/
margin-top: 1rem; /*最小间距*/
display: inline-block;
height: auto; /*高度自动*/
width: 49%; /*文章容器容器宽度*/
}

#recent-posts > .recent-post-item .post_cover {
width: 100%; /*图片封面宽度*/
height: 200px; /*图片封面高度*/
}

#recent-posts > .recent-post-item .post_cover img.post_bg {
width: 100%; /*图片宽度*/
height: 100%; /*图片高度*/
}


#recent-posts > .recent-post-item > .recent-post-info > .content {
display: none; /*隐藏文章详情*/
}

#recent-posts > .recent-post-item {

-webkit-flex-direction: column; /*容器内部纵向排列*/
-ms-flex-direction: column; /*容器内部纵向排列*/
flex-direction: column; /*容器内部纵向排列*/

}

#recent-posts > .recent-post-item .left_radius {
border-radius: 8px 8px 0 0; /*圆角修改*/
}

#recent-posts > .recent-post-item .right_radius {
border-radius: 8px 8px 0 0; /*圆角修改*/
}

.recent-post-item {
height: auto !important; /*容器高度自动*/
}

.recent-post-info {

padding: 0 40px; /*容器内部文字左右间距*/
margin-top: 1em; /*容器内部文字上间距*/
width: 100% !important; /*容器宽度*/
}

#recent-posts > .recent-post-item > .recent-post-info > .article-title {
-webkit-line-clamp: 1; /*控制标题的行数*/
margin-top: 0.3rem; /*控制标题的上间距*/
margin-bottom: 0.3rem; /*控制标题的下间距*/
color: var(--text-highlight-color);
font-size: 1.2em; /*控制标题的字体大小*/
line-height: 1.4; /*控制标题的行高*/

}

#recent-posts > .recent-post-item > .recent-post-info > .article-meta-wrap {
margin-bottom: 1rem; /*控制标题meta信息的底部间距*/
}

@media screen and (max-width: 768px) {
#recent-posts > .recent-post-item {
width: 100%; /*控制手机自适应*/
}
}

/* 小冰老师微调,解决最后一页错误问题 */
nav#pagination {
width: 100%;
}

修改主题配置文件_config.butterfly.yml,引入css文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/double row.css">

时钟(已移除)

原文地址:

安装

npm install hexo-butterfly-clock-anzhiyu --save

修改配置文件 _config.yml,在最后新增

# electric_clock
# see https://anzhiy.cn/posts/fc18.html
electric_clock:
enable: true # 开关
priority: 5 #过滤器优先权
enable_page: all # 应用页面
exclude:
# - /posts/
# - /about/
layout: # 挂载容器类型
type: class
name: sticky_layout
index: 0
loading: https://cdn.cbd.int/hexo-butterfly-clock-anzhiyu@1.1.6/lib/loading.gif #加载动画自定义
clock_css: https://cdn.cbd.int/hexo-butterfly-clock-anzhiyu@1.1.6/lib/clock.min.css
clock_js: https://cdn.cbd.int/hexo-butterfly-clock-anzhiyu@1.1.6/lib/clock.min.js
ip_api: https://widget.qweather.net/simple/static/js/he-simple-common.js?v=2.0
qweather_key: # 和风天气key
gaud_map_key: # 高得地图web服务key
default_rectangle: true # 开启后将一直显示rectangle位置的天气,否则将获取访问者的地理位置与天气
rectangle: 112.6534116,27.96920845 # 获取访问者位置失败时会显示该位置的天气,同时该位置为开启default_rectangle后的位置

hexo-magnet

原文地址:hexo-magnet 插件 1.0 | 小冰博客

功能:

  1. 自定义 tags 或 categories 的排列和展示
  2. 自定义 tags 或 categories 的展示图标,名称
  3. 自定义排列的行数,默认 2 行

安装

npm i hexo-magnet --save

修改配置文件 _config.yml,在最后新增

  • type:categories/tags
  • name:分类原名
  • display_name:替换名称
  • icon:图标
# hexo-magnet
magnet:
enable: true
priority: 8
enable_page: /
type: categories
devide: 2
display:
- name: 小张列传
display_name: 小张列传
icon: 📚
- name: 服务器
display_name: 瞎折腾服务器
icon: 👩‍💻
color_setting:
text_color: black
text_hover_color: white
background_color: "#f2f2f2"
background_hover_color: "#b30070"
layout:
type: id
name: recent-posts
index: 0
temple_html: '<div class="recent-post-item" style="width:100%;height: auto"><div id="catalog_magnet">${temple_html_item}</div></div>'
plus_style: ""

文章轮播置顶

原文地址: hexo-butterfly-swiper | Akilarの糖果屋

安装

npm install hexo-butterfly-swiper --save

修改配置文件 _config.yml,在最下面添加

# hexo-butterfly-swiper
# see https://akilar.top/posts/8e1264d1/
swiper:
enable: true # 开关
priority: 5 #过滤器优先权
enable_page: all # 应用页面
timemode: date #date/updated
layout: # 挂载容器类型
type: id
name: recent-posts
index: 0
default_descr: 再怎么看我也不知道怎么描述它的啦!
swiper_css: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.css #swiper css依赖
swiper_js: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.js #swiper js依赖
custom_css: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiperstyle.css # 适配主题样式补丁
custom_js: https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper_init.js # swiper初始化方法

在文章的front_matter中添加swiper_index配置项

---
swiper_index: 1 #置顶轮播图顺序,非负整数,数字越大越靠前
---

Wowjs

原文地址:Add Blog Animation – Wowjs | Akilarの糖果屋

安装

npm install hexo-butterfly-wowjs --save

修改配置文件 _config.yml,在最下面添加

# 加载动画
wowjs:
enable: true #控制动画开关。true是打开,false是关闭
priority: 10 #过滤器优先级
mobile: false #移动端是否启用,默认移动端禁用
animateitem:
- class: recent-post-item #必填项,需要添加动画的元素的class
style: animate__zoomIn #必填项,需要添加的动画
duration: 1.5s #选填项,动画持续时间,单位可以是ms也可以是s。例如3s,700ms。
delay: 200ms #选填项,动画开始的延迟时间,单位可以是ms也可以是s。例如3s,700ms。
offset: 30 #选填项,开始动画的距离(相对浏览器底部)
iteration: 1 #选填项,动画重复的次数
- class: card-widget
style: animate__zoomIn
animate_css: https://npm.elemecdn.com/hexo-butterfly-wowjs/lib/animate.min.css
wow_js: https://npm.elemecdn.com/hexo-butterfly-wowjs/lib/wow.min.js
wow_init_js: https://npm.elemecdn.com/hexo-butterfly-wowjs/lib/wow_init.js

文章密码

文档地址:hexo-blog-encrypt Github

安装

npm install --save hexo-blog-encrypt

使用时修改文章的front_matterpassword必选,其它选填。也可以将整个分类加密,具体参考文档

---
password: mikemessi
abstract: 有东西被加密了, 请输入密码查看.
message: 您好, 这里需要密码.
wrong_pass_message: 抱歉, 这个密码看着不太对, 请再试试.
wrong_hash_message: 抱歉, 这个文章不能被校验, 不过您还是能看看解密后的内容.
---

视频

通常用<iframe height=500 width=500 src='xxxx' frameborder=0 'allowfullscreen'></iframe>标签插入视频,但本地markdown软件打开文件总是自动播放,所以借助插件会方便一些

文档地址:hexo-tag-dplayer | Github

基于DIYgod/DPlayer修改,hexo-tag-dplayer具体参数可以参考它

安装

npm install --save hexo-tag-dplayer

使用

{% dplayer "url=xxx" "autoplay=false" %}
选项默认值描述选项默认值描述
url必须值视频地址autoplaytrue自动播放,移动端浏览器暂时不支持
pic视频封面loopfalse视频循环播放
screenshotfalse视频截图hotkeytrue开启热键,支持快进、快退、音量控制、播放暂停
mutextrue阻止多个播放器同时播放width,height宽高,例”width=854px” “height=480px”
theme#ad7a86播放器风格色彩设置preloadauto视频文件预载入模式,可选项: none, metadata, auto
langzh-cn‘en’, ‘zh-cn’, ‘zh-tw’logourl,在左上角展示一个 logo
volume0.7播放器音量

footer底部 跳动的心

原文地址:[【源码开放】Hexo+Github 博客butterfly 和 matery 主题 搭建完全教程【整理】 | 超逸の博客](https://yangchaoyi.vip/posts/520520/#页面底部 footer 跳动的心)

编辑 [BlogRoot]/themes/Butterfly/layout/includes/footer.pug

-&copy;${theme.since} - ${nowYear} By ${config.author}
+&copy;${theme.footer.owner.since} - ${nowYear + ' '} <i id="heartbeat" class="fa fas fa-heartbeat"></i> ${config.author}

-&copy;${nowYear} By ${config.author}
+&copy;${nowYear + ' '} <i id="heartbeat" class="fa fas fa-heartbeat"></i> ${config.author}

//最底部添加
+<head><link rel="stylesheet" href="https://jsd.onmicrosoft.cn/gh/HCLonely/images@master/others/heartbeat.min.css"></head>

朋友圈

文档地址:hexo-filter-fcircle

本博客目前采用GitHub+Leancloud+yyyz前端方案部署,朋友圈项目迭代特别快,不再详细记录,根据文档最新教程部署即可

鼠标右击美化

原文地址:

修改PUG

新建 [BlogRoot]/themes/butterfly/layout/includes/rightmenu.pug

#rightMenu
.rightMenu-group.rightMenu-small
a.rightMenu-item(href="javascript:window.history.back();")
i.fa.fa-arrow-left
a.rightMenu-item(href="javascript:window.history.forward();")
i.fa.fa-arrow-right
a.rightMenu-item(href="javascript:window.location.reload();")
i.fa.fa-refresh
a.rightMenu-item(href="javascript:rmf.scrollToTop();")
i.fa.fa-arrow-up
.rightMenu-group.rightMenu-line.hide#menu-text
a.rightMenu-item(href="javascript:rmf.copySelect();")
i.fa.fa-copy
span='复制'
a.rightMenu-item(href="javascript:window.open(\"https://www.baidu.com/s?wd=\"+window.getSelection().toString());window.location.reload();")
i.fa-solid.fa-magnifying-glass
span='百度搜索'
.rightMenu-group.rightMenu-line.hide#menu-too
a.rightMenu-item(href="javascript:window.open(window.getSelection().toString());window.location.reload();")
i.fa.fa-link
span='转到链接'
.rightMenu-group.rightMenu-line.hide#menu-paste
a.rightMenu-item(href='javascript:rmf.paste()')
i.fa.fa-copy
span='粘贴'
.rightMenu-group.rightMenu-line.hide#menu-post
a.rightMenu-item(href="#post-comment")
i.fas.fa-comment
span='空降评论'
a.rightMenu-item(href="javascript:rmf.copyWordsLink()")
i.fa.fa-link
span='复制本文地址'
.rightMenu-group.rightMenu-line.hide#menu-to
a.rightMenu-item(href="javascript:rmf.openWithNewTab()")
i.fa.fa-window-restore
span='新窗口打开'
a.rightMenu-item#menu-too(href="javascript:rmf.open()")
i.fa.fa-link
span='转到链接'
a.rightMenu-item(href="javascript:rmf.copyLink()")
i.fa.fa-copy
span='复制链接'
.rightMenu-group.rightMenu-line.hide#menu-img
a.rightMenu-item(href="./#post-comment")
i.fa.fa-download
span='保存图片'
a.rightMenu-item(href="javascript:rmf.openWithNewTab()")
i.fa.fa-window-restore
span='在新窗口打开'
a.rightMenu-item(href="javascript:rmf.click()")
i.fa.fa-arrows-alt
span='全屏显示'
a.rightMenu-item(href="javascript:rmf.copyLink()")
i.fa.fa-copy
span='复制图片链接'
.rightMenu-group.rightMenu-line
//a.rightMenu-item(href="javascript:toRandomPost()")
// i.fa.fa-paper-plane
// span='随便逛逛'
a.rightMenu-item(href="javascript:rmf.switchDarkMode();")
i.fa.fa-moon
span='昼夜切换'
a.rightMenu-item(href="javascript:rmf.translate();")
i.fas.fa-language
span='繁简转换'
if is_home() == false
a.rightMenu-item(href="javascript:rmf.switchReadMode();")
i.fa.fa-book
span='阅读模式'
a.rightMenu-item(href="javascript:window.location.href=\"/about/\";")
i.fa.fa-info-circle
span='关于小张'

[BlogRoot]/themes/butterfly/layout/includes/layout.pug中引入(注意缩进,去掉+)

    include ./rightside.pug
include ./additional-js.pug
!=partial('includes/third-party/search/index', {}, {cache: true})
+ !=partial('includes/rightmenu',{}, {cache:true})

CSS

新建 [BlogRoot]/themes/butterfly/source/css/rightmenu/rightmenu.css

/* rightMenu */
[data-theme='light'] #rightMenu{
display: none;
position: fixed;
width: 160px;
height: fit-content;
top: 10%;
left: 10%;
background-color: var(--card-bg);
border: 1px solid rgb(210,210,210);;
border-radius: 8px;
z-index: 100;
box-shadow: 3px 3px 5px #88888894;
background-color: var(--zhshier-white-acrylic1);
backdrop-filter: blur(30px);
}
[data-theme='dark'] #rightMenu{
display: none;
position: fixed;
width: 160px;
height: fit-content;
top: 10%;
left: 10%;
background-color: var(--card-bg);
border: 1px solid rgb(210,210,210);;
border-radius: 8px;
z-index: 100;
box-shadow: 3px 3px 5px #88888894;
background-color: var(--zhshier-black-acrylic1);
backdrop-filter: blur(30px);
}
#rightMenu .rightMenu-group{
padding: 7px 6px;
}
#rightMenu .rightMenu-group:not(:nth-last-child(1)){
border-bottom: 1px solid rgb(180,180,180);
}
#rightMenu .rightMenu-group.rightMenu-small{
display: flex;
justify-content: space-between;
}
#rightMenu .rightMenu-group .rightMenu-item{
height: 30px;
line-height: 30px;
border-radius: 8px;
transition: 0.3s;
color: var(--font-color);
}
#rightMenu .rightMenu-group.rightMenu-line .rightMenu-item{
display: flex;
height: 40px;
line-height: 40px;
padding: 0 4px;
}
#rightMenu .rightMenu-group .rightMenu-item:hover{
background-color: var(--text-bg-hover);
box-shadow: 0px 0px 5px var(--zhshier-border);
}
#rightMenu .rightMenu-group .rightMenu-item i{
display: inline-block;
text-align: center;
line-height: 30px;
width: 30px;
height: 30px;
padding: 0 5px;
}
#rightMenu .rightMenu-group .rightMenu-item span{
line-height: 30px;
}
#rightMenu:hover{
border: 1px solid var(--zhshier-blue);
/* box-shadow:0 0 3px var(--zhshier-blue)!important; */
}
#rightMenu .rightMenu-group.rightMenu-line .rightMenu-item *{
height: 40px;
line-height: 40px;
}
.rightMenu-group.hide{
display: none;
}
.rightMenu-item:hover{
color:white!important;
background-color:var(--zhshier-blue)!important;
}
:root{
--zhshier-border:#c9c9c9;
--zhshier-blue:#6cf;
--zhshier-black-acrylic1: #0008;
--zhshier-white-acrylic1:#fffd;
}

修改主题配置文件_config.butterfly.yml,引入css文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/rightmenu/rightmenu.css">

iconfont图标

因为少部分图标使用iconfont,你需要自己添加,下载LYX的iconfont图标包,然后解压把里面的东西扔到 [BlogRoot]/themes/butterfly/source/css/rightmenu/里面即可(图片源自阿里图标,也可以自己直接用主题自带的矢量图标)

修改主题配置文件_config.butterfly.yml,引入css文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/iconfont.css">

JS

新建 [BlogRoot]/themes/butterfly/source/js/rightmenu.js

console.log(
"Codes uses GPL Licence"
)

function insertAtCursor(myField, myValue) {

//IE 浏览器
if (document.selection) {
myField.focus();
sel = document.selection.createRange();
sel.text = myValue;
sel.select();
}

//FireFox、Chrome等
else if (myField.selectionStart || myField.selectionStart == '0') {
var startPos = myField.selectionStart;
var endPos = myField.selectionEnd;

// 保存滚动条
var restoreTop = myField.scrollTop;
myField.value = myField.value.substring(0, startPos) + myValue + myField.value.substring(endPos, myField.value.length);

if (restoreTop > 0) {
myField.scrollTop = restoreTop;
}

myField.focus();
myField.selectionStart = startPos + myValue.length;
myField.selectionEnd = startPos + myValue.length;
} else {
myField.value += myValue;
myField.focus();
}
}
let rmf = {};
rmf.showRightMenu = function (isTrue, x = 0, y = 0) {
let $rightMenu = $('#rightMenu');
$rightMenu.css('top', x + 'px').css('left', y + 'px');

if (isTrue) {
$rightMenu.show();
} else {
$rightMenu.hide();
}
}
rmf.switchDarkMode = function () {
const nowMode = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light'
if (nowMode === 'light') {
activateDarkMode()
saveToLocal.set('theme', 'dark', 2)
GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.day_to_night)
} else {
activateLightMode()
saveToLocal.set('theme', 'light', 2)
GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.night_to_day)
}
// handle some cases
typeof utterancesTheme === 'function' && utterancesTheme()
typeof FB === 'object' && window.loadFBComment()
window.DISQUS && document.getElementById('disqus_thread').children.length && setTimeout(() => window.disqusReset(), 200)
};
rmf.copyWordsLink = function () {
let url = window.location.href
let txa = document.createElement("textarea");
txa.value = url;
document.body.appendChild(txa)
txa.select();
document.execCommand("Copy");
document.body.removeChild(txa);
Swal.fire("复制成功!");
}
rmf.switchReadMode = function () {
const $body = document.body
$body.classList.add('read-mode')
const newEle = document.createElement('button')
newEle.type = 'button'
newEle.className = 'fas fa-sign-out-alt exit-readmode'
$body.appendChild(newEle)

function clickFn() {
$body.classList.remove('read-mode')
newEle.remove()
newEle.removeEventListener('click', clickFn)
}

newEle.addEventListener('click', clickFn)
}

//复制选中文字
rmf.copySelect = function () {
document.execCommand('Copy', false, null);
//这里可以写点东西提示一下 已复制
}

//回到顶部
rmf.scrollToTop = function () {
btf.scrollToDest(0, 500);
}
rmf.translate = function () {
document.getElementById("translateLink").click();
}

// 右键菜单事件
document.onkeydown = function (event) {
event = (event || window.event);
if (event.keyCode == 17) {
console.log("你知道的太多了");
return;
}
}

function popupMenu() {
//window.oncontextmenu=function(){return false;}
window.oncontextmenu = function (event) {
if(event.ctrlKey)return true;
console.log(event.keyCode)
$('.rightMenu-group.hide').hide();
//如果有文字选中,则显示 文字选中相关的菜单项
if (document.getSelection().toString()) {
$('#menu-text').show();
}
if (document.getElementById('post')) {
$('#menu-post').show();
} else {
if (document.getElementById('page')) {
$('#menu-post').show();
}
}
var el = window.document.body;
el = event.target;
var a=/^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\*\+,;=.]+$/
if (a.test(window.getSelection().toString())){
$('#menu-too').show()
}
if (el.tagName == 'A') {
$('#menu-to').show()
rmf.open = function () {
location.href = el.href
}
rmf.openWithNewTab = function () {
window.open(el.href);
}
rmf.copyLink = function () {
let url = el.href
let txa = document.createElement("textarea");
txa.value = url;
document.body.appendChild(txa)
txa.select();
document.execCommand("Copy");
document.body.removeChild(txa);
}
}
if (el.tagName == 'IMG') {
$('#menu-img').show()
rmf.openWithNewTab = function () {
window.open(el.src);
}
rmf.click = function () {
el.click()
}
rmf.copyLink = function () {
let url = el.src
let txa = document.createElement("textarea");
txa.value = url;
document.body.appendChild(txa)
txa.select();
document.execCommand("Copy");
document.body.removeChild(txa);
}
} else if (el.tagName == "TEXTAREA" || el.tagName == "INPUT") {
$('#menu-paste').show();
rmf.paste = function () {
navigator.permissions
.query({
name: 'clipboard-read'
})
.then(result => {
if (result.state == 'granted' || result.state == 'prompt') {
//读取剪贴板
navigator.clipboard.readText().then(text => {
console.log(text)
insertAtCursor(el, text)
})
} else {
alert('请允许读取剪贴板!')
}
})
}
}
let pageX = event.clientX + 10;
let pageY = event.clientY;
let rmWidth = $('#rightMenu').width();
let rmHeight = $('#rightMenu').height();
if (pageX + rmWidth > window.innerWidth) {
pageX -= rmWidth + 10;
}
if (pageY + rmHeight > window.innerHeight) {
pageY -= pageY + rmHeight - window.innerHeight;
}



rmf.showRightMenu(true, pageY, pageX);
return false;
};

window.addEventListener('click', function () {
rmf.showRightMenu(false);
});
}
if (!(navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
popupMenu()
}
const box = document.documentElement

function addLongtabListener(target, callback) {
let timer = 0 // 初始化timer

target.ontouchstart = () => {
timer = 0 // 重置timer
timer = setTimeout(() => {
callback();
timer = 0
}, 380) // 超时器能成功执行,说明是长按
}

target.ontouchmove = () => {
clearTimeout(timer) // 如果来到这里,说明是滑动
timer = 0
}

target.ontouchend = () => { // 到这里如果timer有值,说明此触摸时间不足380ms,是点击
if (timer) {
clearTimeout(timer)
}
}
}

addLongtabListener(box, popupMenu)

因为这个js依赖于jquery,所以还需要引入jquery,修改主题配置文件_config.butterfly.yml,引入js文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
bottom:
# - <script src="xxxx"></script>
+ - <script defer type="text/javascript" src="https://jsd.onmicrosoft.cn/npm/jquery@latest/dist/jquery.min.js"></script>
+ - <script defer type="text/javascript" src="/js/rightmenu.js"></script>

悬浮伸缩侧边栏

原文地址:给网站增加悬浮伸缩侧边栏 | 轻笑Chuckle

修改[BlogRoot]/themes/butterfly/layout/includes/layout.pug,注意修改歌单id

include ./rightside.pug
!=partial('includes/third-party/search/index', {}, {cache: true})
!=partial('includes/dorakika/rightmenu',{}, {cache:true})
include ./additional-js.pug
//- 上面的是本来就有的,对齐上面的缩进,加上下面的内容
// 侧边悬浮栏
.contact-info
.option
i.fas.fa-rocket
.bloktop
.text
.strip
<div class="aside_notice">鉴于评论非即时聊天、问题描述不清晰,可以加我并附上你的问题截图。🐧:1310446718,VX:GC_XiaoZhang(无偿,不要怕社恐小张也紧张!也不需要客气就当好朋友聊天就可以啦!)<br>糖果屋交流群:589330978<br>小N姐姐公益群:641126318</div>
.option
i.fas.fa-cube
.blok
.text
.strip
<div class="post-reward"><div class="reward-button"><i class="fa-solid fa-bolt"></i></div><div class="reward-main"><ul class="reward-all"><li class="reward-item"><a href="/Hexo_img/config/wechat.png" target="_blank"><img class="post-qr-code-img entered loaded" src="/Hexo_img/config/wechat.png" alt="微信"></a><div class="post-qr-code-desc">微信</div></li><li class="reward-item"><a href="/Hexo_img/config/alipay.jpg" target="_blank"><img class="post-qr-code-img entered loaded" src="/Hexo_img/config/alipay.jpg" alt="支付宝"></a><div class="post-qr-code-desc">支付宝</div></li></ul></div></div>
.option
i.fas.fa-music
.blokbottom
.text.aplayertext
.strip
.aplayer.no-destroy(mutex='true', listfolded='true', data-id='7041302176', data-preload="none" , data-server='netease', data-volume='0.25', data-order='random', data-type='playlist', data-fixed='true', data-autoplay='false')

新建[BlogRoot]/source/css/asidefloat.css

.contact-info {
position: fixed;
top: 22%;
z-index: 200;
left: -51px;
transition: 0.4s;
}

.contact-info:hover {
left: 0px;
}

.contact-info .option {
cursor: pointer;
position: relative;
}

.contact-info .option i {
display: block;
width: 50px;
text-align: center;
height: 60px;
line-height: 60px;
background: rgb(255, 255, 255);
color: #b9b9b9;
font-size: 20px;
transition: 0.4s;
border-radius: 0 10px 10px 0;
}

.contact-info .option:hover i {
color: #3498db;
}

.contact-info .text {
border-radius: 15px;
position: absolute;
height: 68px;
width: 200px;
background: rgba(255, 255, 255, .85);
top: 0;
z-index: -1;
left: -136px;
color: rgb(0, 0, 0);
line-height: 60px;
text-align: center;
transition: 0.4s;
}

.contact-info .aplayertext {
transition: none !important;
}

.contact-info .aplayer {
position: absolute !important;
}

.contact-info .aplayer.aplayer-fixed .aplayer-body {
left: -60px;
position: absolute !important;
width: 370px !important;
transition: none !important;
border-radius: 10px !important;
}

.contact-info .aplayer.aplayer-fixed {
left: -300px !important;
}

.contact-info .option:hover .aplayer.aplayer-fixed .aplayer-body, .contact-info .option:hover .aplayer.aplayer-fixed {
left: 0px !important;
}

.contact-info .option:hover .text {
left: 60px;
}

.contact-info .blok {
position: absolute;
height: 60px;
width: 100px;
top: 0;
z-index: -1;
left: 0px;
}

.contact-info .bloktop {
position: absolute;
height: 75px;
width: 100px;
bottom: 0px;
z-index: -1;
left: 0px;
}

.contact-info .blokbottom {
position: absolute;
height: 75px;
width: 100px;
top: 0;
z-index: -1;
left: 0px;
}

.contact-info .option:hover .blok, .contact-info .option:hover .bloktop, .contact-info .option:hover .blokbottom {
left: 0px;
}

.contact-info .option:hover .aplayertext {
left: 60px !important;
width: 370px !important;
background: transparent !important;
}

.contact-info .aplayer.aplayer-fixed .aplayer-miniswitcher {
border-radius: 0 10px 10px 0 !important;
}

.contact-info .aplayer.aplayer-fixed .aplayer-body {
transition: 0.28s !important;
border-radius: 10px !important;
height: 60px;
}

.contact-info .aplayer .aplayer-pic {
height: 60px !important;
}

.contact-info .aplayer .aplayer-info {
height: 60px !important;
}

.aplayer .aplayer-list.aplayer-list-hide {
margin-bottom: 59px !important;
}

.contact-info .aplayer.aplayer-fixed .aplayer-list {
margin-bottom: 62px !important;
max-height: 240px !important;
}

.contact-info .aplayer.aplayer-fixed .aplayer-info {
transition: none !important;
}

.aplayer.aplayer-narrow .aplayer-body, .aplayer.aplayer-narrow .aplayer-pic {
border-radius: 10px 0 0 10px !important;
}

.aplayer.aplayer-fixed {
border-radius: 10px !important;
}

.aplayer .aplayer-pic {
border-radius: 0 0 0 10px !important;
}

.aplayer.aplayer-fixed .aplayer-list {
border-radius: 10px 10px 0 0 !important;
}

[data-theme=dark]
.contact-info .option i {
background: rgb(22, 22, 22);
color: #b9b9b9;
}

[data-theme=dark]
.contact-info .text {
background: rgba(23, 23, 23, 0.85);
color: rgba(255, 255, 255, 0.92);
}

@media screen and (max-width: 1300px) {
.contact-info {
display: none !important;
}
}

.aplayer {
opacity: .93 !important;
}

[data-theme=dark]
.aplayer {
background: rgb(22, 22, 22) !important;
color: rgb(255, 255, 255);
}

[data-theme=dark]
.aplayer.aplayer-fixed .aplayer-body {
background: rgb(22, 22, 22) !important;
color: rgb(255, 255, 255);
}

[data-theme=dark]
.aplayer .aplayer-list ol li:hover {
background: #3b3b3b;
}

[data-theme=dark]
.aplayer .aplayer-list ol li.aplayer-list-light {
background: #686868;
}

[data-theme=dark]
.aplayer .aplayer-info .aplayer-controller .aplayer-time {
color: #d4d4d4;
}

[data-theme=dark]
.aplayer .aplayer-list ol li .aplayer-list-index {
color: #d4d4d4;
}

[data-theme=dark]
.aplayer .aplayer-list ol li .aplayer-list-author {
color: #d4d4d4;
}

[data-theme=dark]
.aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-icon path {
fill: #d4d4d4;
}

.contact-info .text .strip {
border-radius: 5px;
position: absolute;
height: 36px;
width: 5px;
background: rgba(20, 163, 230, 0.8);
top: 12px;
z-index: -1;
right: 4px;
transition: 0.4s;
}

.contact-info .aplayertext .strip {
transition: none !important;
}

.contact-info .option:hover .aplayertext .strip {
background: transparent;
}

[data-theme=dark]
.contact-info .aplayer .aplayer-miniswitcher {
background: rgba(23, 23, 23, 0.85);
}

.contact-info .aplayer .aplayer-miniswitcher .aplayer-icon path {
fill: #3498db;
}

[data-theme=dark]
.contact-info .option:hover i {
color: #3498db;
}

.contact-info .option .text .post-reward .tip-button__text {
margin: 25px !important;
}

.contact-info .option .text .post-reward .reward-main .reward-all {
border-radius: 12px !important;
}

.contact-info .option .text .post-reward .reward-button .reward-main .reward-all {
z-index: 999 !important;
}

[data-theme="dark"]
.contact-info .option .text .post-reward .tip-button {
border: solid 2px rgba(236, 233, 233, 0.8);
background: #043749d0;
}


/* 基于chuckle的微调,可能与你的博客不适配,根据注释微调 */
/* 第一个按钮的滚动通知 */
/* 通知栏大小 文字行高调整 */
.contact-info .option:first-child:hover .text {
height: 100px;
width: 300px;
line-height: 20px;
overflow: hidden;
}
/* 小图标调整 */
.contact-info .option:first-child:hover .text .strip {
top: 33px;
}

.contact-info .option .text .aside_notice{
word-wrap:break-word;
padding:20px;
/*color: transparent; !*偷个懒不做位移直接透明*!*/
display: none;
}

/* 文字滚动动画 */
.contact-info .option:first-child:hover .text .aside_notice{
color: #0A84FF;
display: block;
animation: notice 5s linear 0s infinite normal forwards;
}
/* 鼠标悬停时停止滚动 */
.contact-info .option .text .aside_notice:hover {
animation-play-state: paused!important;
cursor: pointer;
}
/* 文字滚动动画 */
@keyframes notice {
0% {
transform: translateY(90px);
}
100% {
transform: translateY(-100%);
}
}

/* 打赏按钮大小与布局 */
.contact-info .option .text .post-reward .reward-button {
display: inline-flex;
width: 90%;
position: relative;
left: -9.7px;
border-radius: 15px;
}

.contact-info .option .text .post-reward {
margin-top: 0px;
}

/* 二维码横向排列 */
.contact-info .option .text .post-reward .reward-main .reward-all {
display: inline-flex;
}

/* 二维码靠边对齐 */
.contact-info .option .text .post-reward .reward-main {
left: -60px;
line-height: 30px;
}

/* 倒三角位置 */
.contact-info .option .text .post-reward .reward-main .reward-all:after {
left: 110px;
}

/* 充电矢量图动画 */
.contact-info .option .text .post-reward .reward-button i {
background: yellow;
border-radius: 10px;
animation: Breath 1.2s linear 1s infinite;
color: var(--btn-bg) !important;
position: relative;
left: 46px;
}

@keyframes Breath {
0% {
transform: scale(0.8);
}
50% {
transform: scale(1);
}
100% {
transform: scale(0.8);
}
}


/* 打赏按钮hover动画 */
.contact-info .option .text .post-reward:hover .reward-button {
background: linear-gradient(to left, yellow 50%, var(--btn-bg) 50%);
background-size: 200%;
background-position-x: -100%;
transition: .5s ease-out;
}

修改主题配置文件_config.butterfly.yml,引入css文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/twikoo.css">

即刻短文 Memos

原文地址:基于Memos实现说说和清单功能 | Leonus

其它Memos教程:

Memos需要服务器部署,类似无服务器的项目:

说说功能

创建说说页面hexo new page zone,并粘贴以下代码

<style>
/* 页面初始化 */
div#page {
background: none;
border: 0;
padding: 0;
}

[data-theme=dark] #twikoo .tk-content,
#twikoo .tk-content {
padding: 0;
background: transparent;
}

.talk_item,
.tk-expand,
.tk-comments-container>.tk-comment,
.tk-submit:nth-child(1){
background: var(--card-bg);
border: 1px solid #e0e3ed;
box-shadow: 0 5px 10px rgb(189 189 189 / 10%);
transition: all .3s ease-in-out;
border-radius: 12px;
}
.talk_item:hover,
.tk-comments-container>.tk-comment:hover,
.tk-submit:nth-child(1):hover {
border-color: #49b1f5;
}

.tk-submit {
padding: 20px 10px 0;
}

.tk-comments-container>.tk-comment {
padding: 15px;
}

/* 页面初始化结束 */

#talk{
margin-top: 1rem;
}

#talk .loading {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}

#talk .loading img {
width: 200px;
}

.talk_item {
display: flex;
flex-direction: column;
padding: 20px;
margin-bottom: 15px;
}

.avatar {
margin: 0 !important;
width: 60px;
height: 60px;
border-radius: 10px;
}


.talk_bottom,
.talk_meta {
display: flex;
align-items: center;
width: 100%;
line-height: 1.5;
}
.talk_bottom{
justify-content: space-between;
}
.info {
display: flex;
flex-direction: column;
margin-left: 10px;
}
span.talk_nick {
color: #6dbdc3;
font-size: 1.2rem;
}
svg.is-badge.icon {
width: 15px;
margin-left: 5px;
padding-top: 3px;
}
span.talk_date {
opacity: .6;
}

.talk_content {
line-height: 1.5;
margin-top: 10px;
}
.zone_imgbox {
display: flex;
flex-wrap: wrap;
--w: calc(25% - 8px);
gap: 10px;
margin-top: 5px;
}
.zone_imgbox a {
display: block;
border-radius: 12px;
width: var(--w);
aspect-ratio: 1/1;
position: relative;
}

.zone_imgbox img {
width: 100%;
height: 100%;
margin: 0 !important;
object-fit: cover;
}
/* 底部 */

.talk_bottom {
opacity: .9;
}
.talk_bottom .icon {
color: var(--font-color);
float: right;
transition: all .3s;
}

.talk_bottom .icon:hover {
color: #49b1f5;
}

span.talk_tag{
font-size: 14px;
}
.talk_content>a {
margin: 0 3px;
color: #ff7d73 !important;
}
.talk_content>a:hover{
text-decoration: none !important;
color: #ff5143 !important
}

/* 提醒 */

.limit {
transition: all .3s ease-in-out;
color: rgba(76, 73, 72, 0.6);
}

[data-theme=dark] .limit {
color: rgba(255, 255, 255, 0.5);
}

.limit {
display: none;
text-align: center;
margin-top: 20px;
color: var(--font-color);
}
@media screen and (max-width: 900px) {
.zone_imgbox {
--w: calc(33% - 5px);
}
#talk{
margin: 10px 3px 0
}
#post-comment{
margin: 0 3px
}
}

@media screen and (max-width: 768px) {
.zone_imgbox {
gap: 6px;
}
.zone_imgbox {
--w: calc(50% - 3px);
}
span.talk_date {
font-size: 14px;
}
}
</style>

<div id="talk">
<div class='loading'><img src="/img/loading.svg" alt="加载中..."></div>
</div>

<div class="limit">- 只展示最近30条说说 -</div>
<script>
pageTalk();
// 页面说说
function pageTalk() {
fetch('https://你的memos地址/api/v1/memo?creatorId=1&tag=说说&limit=30').then(res => res.json()).then(data => { // 注意修改域名
let items = [],
html = '',
icon = '<svg viewBox="0 0 512 512"xmlns="http://www.w3.org/2000/svg"class="is-badge icon"><path d="m512 268c0 17.9-4.3 34.5-12.9 49.7s-20.1 27.1-34.6 35.4c.4 2.7.6 6.9.6 12.6 0 27.1-9.1 50.1-27.1 69.1-18.1 19.1-39.9 28.6-65.4 28.6-11.4 0-22.3-2.1-32.6-6.3-8 16.4-19.5 29.6-34.6 39.7-15 10.2-31.5 15.2-49.4 15.2-18.3 0-34.9-4.9-49.7-14.9-14.9-9.9-26.3-23.2-34.3-40-10.3 4.2-21.1 6.3-32.6 6.3-25.5 0-47.4-9.5-65.7-28.6-18.3-19-27.4-42.1-27.4-69.1 0-3 .4-7.2 1.1-12.6-14.5-8.4-26-20.2-34.6-35.4-8.5-15.2-12.8-31.8-12.8-49.7 0-19 4.8-36.5 14.3-52.3s22.3-27.5 38.3-35.1c-4.2-11.4-6.3-22.9-6.3-34.3 0-27 9.1-50.1 27.4-69.1s40.2-28.6 65.7-28.6c11.4 0 22.3 2.1 32.6 6.3 8-16.4 19.5-29.6 34.6-39.7 15-10.1 31.5-15.2 49.4-15.2s34.4 5.1 49.4 15.1c15 10.1 26.6 23.3 34.6 39.7 10.3-4.2 21.1-6.3 32.6-6.3 25.5 0 47.3 9.5 65.4 28.6s27.1 42.1 27.1 69.1c0 12.6-1.9 24-5.7 34.3 16 7.6 28.8 19.3 38.3 35.1 9.5 15.9 14.3 33.4 14.3 52.4zm-266.9 77.1 105.7-158.3c2.7-4.2 3.5-8.8 2.6-13.7-1-4.9-3.5-8.8-7.7-11.4-4.2-2.7-8.8-3.6-13.7-2.9-5 .8-9 3.2-12 7.4l-93.1 140-42.9-42.8c-3.8-3.8-8.2-5.6-13.1-5.4-5 .2-9.3 2-13.1 5.4-3.4 3.4-5.1 7.7-5.1 12.9 0 5.1 1.7 9.4 5.1 12.9l58.9 58.9 2.9 2.3c3.4 2.3 6.9 3.4 10.3 3.4 6.7-.1 11.8-2.9 15.2-8.7z"fill="#1da1f2"></path></svg>';
data.data.forEach(item => { items.push(Format(item)) });
if (items.length == 30) document.querySelector('.limit').style.display = 'block';
items.forEach(item => {
html += `<div class="talk_item"><div class="talk_meta"><img class="no-lightbox avatar" src="https://q1.qlogo.cn/g?b=qq&nk=553344777&s=5"><div class="info"><span class="talk_nick">Leonus${icon}</span><span class="talk_date">${item.date}</span></div></div><div class="talk_content">${item.content}</div><div class="talk_bottom"><div><span class="talk_tag"># ${item.tag}</span></div><a href="javascript:;"onclick="goComment('${item.text}')"><span class="icon"><i class="fa-solid fa-message fa-fw"></i></span></a></div></div>` // 注意修改头像链接和名称
})
document.getElementById('talk').innerHTML = html
})
}
// 页面评论
function goComment(e) {
var n = document.querySelector(".el-textarea__inner")
n.value = `> ${e}\n\n`;
n.focus();
btf.snackbarShow("无需删除空行,直接输入评论即可", !1, 2e3);
}
// 页面内容格式化
function Format(item) {
let date = getTime(new Date(item.createdTs * 1000).toString()),
content = item.content,
tag = item.content.match(/\{(.*?)\})/g),
imgls = content.match(/!\[.*\]\(.*?\)/g), // 2023-02-06更新
text = ''
text = content.replace(/#(.*?)\s/g, '').replace(/\!\[(.*?)\]\((.*?)\)/g, '').replace(/\{(.*?)\}/g, '')
content = text.replace(/\[(.*?)\]\((.*?)\)/g, `<a href="$2">@$1</a>`);
if (imgls) {
content += `<div class="zone_imgbox">`
imgls.map(item => { return item.replace(/!\[.*\]\((.*?)\)/, '$1') }).forEach(e => content += `<a href="${e}" data-fancybox="gallery" class="fancybox" data-thumb="${e}"><img src="${e}"></a>` // 2023-02-06更新
)
content += '</div>'
}
return {
content: content,
tag: tag ? tag[0].replace(/\{(.*?)\}/,'$1') : '无标签',
date: date,
text: text.replace(/\[(.*?)\]\((.*?)\)/g, '[链接]' + `${imgls?'[图片]':''}`)
}
}
// 页面时间格式化
function getTime(time) {
let d = new Date(time),
ls = [d.getFullYear(), d.getMonth() + 1, d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds()];
for (let i = 0; i < ls.length; i++) {
ls[i] = ls[i] <= 9 ? '0' + ls[i] : ls[i] + ''
}
if (new Date().getFullYear() == ls[0]) return ls[1] + '月' + ls[2] + '日 ' + ls[3] +':'+ ls[4]
else return ls[0] + '年' + ls[1] + '月' + ls[2] + '日 ' + ls[3] +':'+ ls[4]
}
</script>

使用格式,其中**#说说固定,用于获取Memos内所有的带#说说**标签的内容(如果图片加载失败,配置主题文件lazyload.field:post

#说说 {说说标签} 我是内容 [我是链接](链接地址) ![](图片链接)

首页轮播

修改[BlogRoot]/themes/butterfly/layout/includes/layout.pug

include ./header/index.pug
...上面原本的内容...
if (is_home())
#main_top
#bber-talk.wow.animate__flipInX(onclick=`pjax.loadUrl("/zone/")`)
svg.icon(t='1660960757124', viewBox='0 0 1024 1024', version='1.1', xmlns='http://www.w3.org/2000/svg', p-id='3946', width='200', height='200')
path(d='M526.432 924.064c-20.96 0-44.16-12.576-68.96-37.344L274.752 704H192c-52.928 0-96-43.072-96-96V416c0-52.928 43.072-96 96-96h82.752l182.624-182.624c24.576-24.576 47.744-37.024 68.864-37.024C549.184 100.352 576 116 576 160v704c0 44.352-26.72 60.064-49.568 60.064zM192 384c-17.632 0-32 14.368-32 32v192c0 17.664 14.368 32 32 32h96c8.48 0 16.64 3.36 22.624 9.376l192.064 192.096c3.392 3.36 6.496 6.208 9.312 8.576V174.016a145.824 145.824 0 0 0-9.376 8.608l-192 192C304.64 380.64 296.48 384 288 384h-96zM687.584 730.368a31.898 31.898 0 0 1-18.656-6.016c-14.336-10.304-17.632-30.304-7.328-44.672l12.672-17.344C707.392 617.44 736 578.624 736 512c0-69.024-25.344-102.528-57.44-144.928-5.664-7.456-11.328-15.008-16.928-22.784-10.304-14.336-7.04-34.336 7.328-44.672 14.368-10.368 34.336-7.04 44.672 7.328 5.248 7.328 10.656 14.464 15.968 21.504C764.224 374.208 800 421.504 800 512c0 87.648-39.392 141.12-74.144 188.32l-12.224 16.736c-6.272 8.704-16.064 13.312-26.048 13.312z', p-id='3947')
path(d='M796.448 839.008a31.906 31.906 0 0 1-21.088-7.936c-13.28-11.648-14.624-31.872-2.976-45.152C836.608 712.672 896 628.864 896 512s-59.392-200.704-123.616-273.888c-11.648-13.312-10.304-33.504 2.976-45.184 13.216-11.648 33.44-10.336 45.152 2.944C889.472 274.56 960 373.6 960 512s-70.528 237.472-139.488 316.096c-6.368 7.232-15.2 10.912-24.064 10.912z', p-id='3948')
ul.talk-list 说说加载中。。。
...下面原本的内容...
main#content-inner.layout(class=hideAside)

新建[BlogRoot]/source/css/memos.css

/* maintop */

div#main_top {
z-index: 1;
max-width: 1200px;
margin: 20px auto -15px;
width: 100%;
padding: 0 15px;
}

@media screen and (min-width: 2000px) {
div#main_top {
max-width: 1500px;
}
}

#bber-talk {
border-radius: 12px;
box-shadow: none;
border: 1px solid #e0e3ed;
box-sizing: border-box;
transition: all .3s ease-in-out;
cursor: pointer;
width: 100%;
min-height: 50px;
background: var(--card-bg);
padding: .5rem 1rem;
display: flex;
align-items: center;
overflow: hidden;
font-weight: 700;
}

#bber-talk:hover {
border-color: #49b1f5;
box-shadow: none;
}

#bber-talk,
#bber-talk a {
color: var(--font-color);
}

#bber-talk svg.icon {
width: 1em;
height: 1em;
vertical-align: -.15em;
fill: currentColor;
overflow: hidden;
font-size: 20px;
}

#bber-talk .item i {
margin-left: 5px;
}

#bber-talk>i {
font-size: 1.1rem;
}

#bber-talk .talk-list {
flex: 1;
max-height: 32px;
font-size: 16px;
padding: 0;
margin: 0;
overflow: hidden;
}

#bber-talk .talk-list :hover {
color: #49b1f5 !important;
transition: all .2s ease-in-out;
}

#bber-talk .talk-list li {
list-style: none;
width: 100%;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
margin-left: 10px;
}

@media screen and (min-width: 768px) {
#bber-talk .talk-list {
text-align: center;
margin-right: 20px;
}
}

新建[BlogRoot]/source/js/memos.js

// 存数据
function saveData(name, data) { localStorage.setItem(name, JSON.stringify({ 'time': Date.now(), 'data': data })) };
// 取数据
function loadData(name, time) {
let d = JSON.parse(localStorage.getItem(name));
// 过期或有错误返回 0 否则返回数据
if (d) {
let t = Date.now() - d.time
if (-1 < t && t < (time * 60000)) return d.data;
}
return 0;
};

let talkTimer = null;
function indexTalk() {
if (talkTimer) {
clearInterval(talkTimer)
talkTimer = null;
}
if (!document.getElementById('bber-talk')) return

function toText(ls) {
let text = []
ls.forEach(item => {
text.push(item.content.replace(/#(.*?)\s/g, '').replace(/\{(.*?)\}/g, '').replace(/\!\[(.*?)\]\((.*?)\)/g, '<i class="fa-solid fa-image"></i>').replace(/(?<!!)\[(.*?)\]\((.*?)\)/g, '<i class="fa-solid fa-link"></i>'))
});
return text
}

function talk(ls) {
let html = ''
ls.forEach((item, i) => { html += `<li class="item item-${i + 1}">${item}</li>` });
let box = document.querySelector("#bber-talk .talk-list")
box.innerHTML = html;
talkTimer = setInterval(() => {
box.appendChild(box.children[0]);
}, 3000);
}

let d = loadData('talk', 10);
if (d) talk(d);
else {
fetch('https://你的memos地址/api/v1/memo?creatorId=1&tag=说说&limit=10').then(res => res.json()).then(data => { // 更改地址
data = toText(data.data)
talk(data);
saveData('talk', data);
})
}
}
indexTalk();

// pjax注释掉上面的 indexTalk(); 使用如下方法:
// function whenDOMReady() {
// indexTalk();
// }

// whenDOMReady()
// document.addEventListener("pjax:complete", whenDOMReady)

修改主题配置文件_config.butterfly.yml,引入css、js文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/memos.css">
bottom:
# - <script src="xxxx"></script>
+ - <script async src="/js/memos.js"></script>

清单功能

创建说说页面hexo new page todo,并粘贴以下代码

<style>
/* 页面初始化 */
div#page {
background: none;
border: 0;
padding: 0;
}
[data-theme=dark] #twikoo .tk-content,
#twikoo .tk-content {
padding: 0;
background: transparent;
}

.tk-comments-container>.tk-comment,
.tk-submit:nth-child(1){
background: var(--card-bg);
border: 1px rgba(188, 188, 188, 0.8) solid;
box-shadow: 0 5px 10px rgb(189 189 189 / 10%);
transition: all .3s ease-in-out;
border-radius: 12px;
}

.tk-comments-container>.tk-comment:hover,
.tk-submit:nth-child(1):hover {
border-color: #6dc3fd;
}

.tk-submit {
padding: 20px 10px 0;
}

.tk-comments-container>.tk-comment {
padding: 15px;
}

/* 页面初始化结束 */
div#todolist {
display: flex;
flex-wrap: wrap;
margin-top: 1rem;
}
.list_item {
display: inline-block;
width: calc(50% - .4rem);
background: #ffe3dd;
border-radius: 12px;
padding: 10px 1rem 1.2rem;
border: 2px dashed #f7a796;
--todo-border: 1px solid #f7a796;
margin-right: 1rem;
margin-bottom: 1rem;
}
.list_item h3 {
margin: 0;
border-bottom: var(--todo-border);
}
.list_item ul {
font-size: 17px;
padding: 0 !important;
margin: 0;
}
.list_item li{
margin: 0 !important;
border-bottom: var(--todo-border);
}
.list_item li::marker {
content: none;
}
li.achieve {
opacity: .8;
text-decoration: line-through;
}
@media screen and (max-width: 900px) {
div#todolist {
margin: 1rem 5px 0;
}
}
@media screen and (max-width: 768px) {
.list_item{
width: 100%;
}
}
</style>


<div id="todolist"></div>


<script>
// 瀑布流函数,不用管
function waterfall(t){function e(t,e){var n=window.getComputedStyle(e);return parseFloat(n["margin"+t])||0}function n(t){return t+"px"}function r(t){return parseFloat(t.style.left)}function o(t){return t.clientWidth}function l(t){return function(t){return parseFloat(t.style.top)}(t)+function(t){return t.clientHeight}(t)+e("Bottom",t)}function i(t){return r(t)+o(t)+e("Right",t)}function u(t){t=t.sort((function(t,e){return l(t)===l(e)?r(e)-r(t):l(e)-l(t)}))}function a(e){o(t)!=h&&(e.target.removeEventListener(e.type,arguments.callee),waterfall(t))}"string"==typeof t&&(t=document.querySelector(t));var s=[].map.call(t.children,(function(t){return t.style.position="absolute",t}));t.style.position="relative";var f=[];s.length&&(s[0].style.top="0px",s[0].style.left=n(e("Left",s[0])),f.push(s[0]));for(var p=1;p<s.length;p++){var c=s[p-1],y=s[p];if(!(i(c)+o(y)<=o(t)))break;y.style.top=c.style.top,y.style.left=n(i(c)+e("Left",y)),f.push(y)}for(;p<s.length;p++){u(f);y=s[p];var d=f.pop();y.style.top=n(l(d)+e("Top",y)),y.style.left=n(r(d)),f.push(y)}u(f);var v=f[0];t.style.height=n(l(v));var h=o(t);window.addEventListener?window.addEventListener("resize",a):document.body.onresize=a}

// 清单函数
todolist();
function todolist() {
fetch('https://你的memos地址/api/v1/memo?creatorId=1&tag=清单').then(res => res.json()).then(data => { // 注意替换链接
// 获取并处理数据
data = data.data
let box = document.getElementById('todolist')
data.forEach(item => {
// 处理数据
let content = item.content,
title = content.match(/(?<=#.*\[)(.*?)(?=\])/g);
// 去掉多余内容,替换清单内容
content = content.replace(/#.*\s/g, '').replace(/(-\s\[\s\]\s)(.*)(?=\s*)/g, `<li><i style="margin-right: 5px;" class="fa-regular fa-circle"></i>$2</li>`).replace(/(-\s\[x\]\s)(.*)(?=\s*)/g, `<li class="achieve"><i style="margin-right: 5px;" class="fa-regular fa-circle-check"></i>$2</li>`);
// 渲染数据
let div = document.createElement('div');
div.className = 'list_item';
div.innerHTML = `<h3>${title}</h3><ul>${content}</ul>`;
box.appendChild(div);
});
waterfall('#todolist');
}).catch()
}
</script>

使用

#清单 [计划]
- [ ] 测试Memos
- [x] 测试Memos

Heo同款loading动画

原文地址:安知鱼 - 生活明朗 万物可爱

修改[BlogRoot]/themes/butterfly/layout/includes/loading/fullpage-loading.pug

-#loading-box
- .loading-left-bg
- .loading-right-bg
- .spinner-box
- .configure-border-1
- .configure-core
- .configure-border-2
- .configure-core
- .loading-word= _p('loading')
+#loading-box(onclick='document.getElementById("loading-box").classList.add("loaded")')
+ .loading-bg
+ div.loading-img
+ .loading-image-dot

修改[BlogRoot]/themes/butterfly/layout/includes/loading/index.pug

if theme.preloader.source === 1
include ./fullpage-loading.pug
else if theme.preloader.source === 2
include ./pace.pug
else
include ./fullpage-loading.pug
include ./pace.pug

新建source/css/progress_bar.css,也可以不做这一步下面配置文件pace_css_url这一项就要留空,,这一步是修改 pace 加载的胶囊 💊 样式用的

.pace {
-webkit-pointer-events: none;
pointer-events: none;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
z-index: 2000;
position: fixed;
margin: auto;
top: 10px;
left: 0;
right: 0;
height: 8px;
border-radius: 8px;
width: 4rem;
background: #eaecf2;
border: 1px #e3e8f7;
overflow: hidden;
}

.pace-inactive .pace-progress {
opacity: 0;
transition: 0.3s ease-in;
}

.pace .pace-progress {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
-o-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
max-width: 200px;
position: absolute;
z-index: 2000;
display: block;
top: 0;
right: 100%;
height: 100%;
width: 100%;
background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
animation: gradient 1.5s ease infinite;
background-size: 200%;
}

.pace.pace-inactive {
opacity: 0;
transition: 0.3s;
top: -8px;
}
@keyframes gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}

修改themes/butterfly/source/css/_layout/loading.styl,注意其中颜色代码--anzhiyu-card-bg等需自行替换为自己的色值。

if hexo-config('preloader')
.loading-bg
display: flex;
width: 100%;
height: 100%;
position: fixed;
background: var(--anzhiyu-card-bg);
z-index: 1001;
opacity: 1;
transition: .3s;

#loading-box
.loading-img
width: 100px;
height: 100px;
border-radius: 50%;
margin: auto;
border: 4px solid #f0f0f2;
animation-duration: .3s;
animation-name: loadingAction;
animation-iteration-count: infinite;
animation-direction: alternate;
.loading-image-dot
width: 30px;
height: 30px;
background: #6bdf8f;
position: absolute;
border-radius: 50%;
border: 6px solid #fff;
top: 50%;
left: 50%;
transform: translate(18px, 24px);
&.loaded
.loading-bg
opacity: 0;
z-index: -1000;

@keyframes loadingAction
0% {
opacity: 1;
}

100% {
opacity: .4;
}

在合适的地方加上自定义 css, 其中 backgroundurl 即为 loading 的图片地址

.loading-img {
background: url(https://q1.qlogo.cn/g?b=qq&nk=1310446718&s=5) no-repeat center center;
background-size: cover;
}

修改主题配置文件_config.butterfly.ymlsource: 1为满屏加载无pace胶囊source: 2pace胶囊无满屏动画,source: 3是两者都启用。

# Loading Animation (加载动画)
preloader:
enable: true
# source
# 1. fullpage-loading
# 2. pace (progress bar)
# else all
source: 3
# pace theme (see https://codebyzach.github.io/pace/)
pace_css_url: /css/progress_bar.css

导航栏

原文地址:butterfly导航栏修改方案(自用方案) | 安知鱼

其它教程:关于Butterfly的导航栏的一些教程 | Ariasakaの小窝

新建[BlogRoot]/source/css/nav_menu.css

#nav a:hover {
background: var(--zhsher-theme);
transition: 0.3s;
}

#nav-totop:hover .totopbtn i {
opacity: 1;
}
#nav-totop #percent {
font-size: 12px;
background: var(--zhsher-white);
color: var(--zhsher-theme);
width: 25px;
height: 25px;
border-radius: 35px;
display: flex;
justify-content: center;
align-items: center;
transition: 0.3s;
}
.nav-fixed #nav-totop #percent,
.page #nav-totop #percent {
background: var(--font-color);
color: var(--card-bg);
font-size: 13px;
}

#nav-totop {
width: 35px;
}
#page-header:not(.is-top-bar) #percent {
transition: 0.3s;
}
#page-header:not(.is-top-bar) #nav-totop {
width: 0;
opacity: 0;
transition: width 0.3s, opacity 0.2s;
margin-left: 0 !important;
}
#nav-totop #percent {
font-weight: 700;
}
#nav-totop:hover #percent {
opacity: 0;
transform: scale(1.5);
font-weight: 700;
}
#page-header #nav #nav-right div {
margin-left: 0.5rem;
padding: 0;
}

#nav-totop {
display: flex;
align-items: center;
justify-content: center;
transition: 0.3s;
}
.nav-button {
cursor: pointer;
}
div#menus {
display: flex;
align-items: center;
}
#page-header #nav .nav-button a {
height: 35px;
width: 35px;
display: flex;
align-items: center;
justify-content: center;
}

#nav .site-page {
padding-bottom: 0px;
}
#nav *::after {
background-color: transparent !important;
}

/* 顶栏修改 */
#nav .menus_items .menus_item .menus_item_child li a {
padding: 2px 16px;
}
#nav .menus_items .menus_item .menus_item_child li:hover a {
color: white !important;
}

#nav .menus_items .menus_item .menus_item_child li {
margin: 6px;
border-radius: 5px;
transition: all 0.3s;
display: inline-block;
margin: 0 3px;
}
#nav .menus_items .menus_item .menus_item_child:before {
top: -19px;
}
#site-name,
.shuoshuo {
white-space: nowrap;
overflow: hidden;
}
#site-name {
padding: 0 8px;
position: relative;
display: flex;
align-items: center;
justify-content: center;
transition: 0.3s;
}

#blog-info #site-name i {
opacity: 0;
position: absolute;
}

#blog-info #site-name:hover .title {
opacity: 0;
}

#blog-info #site-name:hover i {
opacity: 1;
transform: scale(1.01);
color: white;
}
/* 圆角隐藏 */
ul.menus_item_child {
border-radius: 5px;
}

/* 一级菜单居中 */
#nav .menus_items {
position: absolute;
width: fit-content;
left: 50%;
transform: translateX(-50%);
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
height: 60px;
}

#nav .menus_items .menus_item:hover .menus_item_child {
display: block;
transform: translateX(-50%);
right: auto;
left: auto !important;
padding: 6px 4px;
box-sizing: content-box;
line-height: 35px;
}
#nav .menus_items .menus_item:hover {
padding: 0 5px 27px 5px !important;
margin-bottom: -14.5px !important;
}

#nav .menus_items .menus_item .menus_item_child {
top: 44px;
}

@media screen and (min-width: 768px) {
.page .menus_item:hover > a.site-page {
color: var(--zhsher-white) !important;
background: var(--zhsher-theme);
transition: 0.3s;
box-shadow: var(--zhsher-shadow-main);
}
}

.nav-fixed #nav {
transform: translateY(58px) !important;
}
#nav {
padding: 0 calc((100% - 1420px) / 2);
backdrop-filter: saturate(180%) blur(20px);
}

#nav a {
border-radius: 8px;
color: var(--font-color);
}
.page #nav a:hover {
color: var(--zhsher-white) !important;
background: var(--zhsher-theme);
transition: 0.3s;
box-shadow: var(--zhsher-shadow-main);
}

#menus > div.menus_items > div > a {
letter-spacing: 0.3rem;
font-weight: 700;
padding: 0em 0.3em 0em 0.5em;
height: 35px;
line-height: 35px;
}
#nav .menus_items .menus_item {
padding: 0 5px;
display: flex;
flex-direction: column;
margin: auto;
align-items: center;
}

#nav div#toggle-menu {
padding: 2px 0 4px 6px;
}

#nav-totop .totopbtn i {
position: absolute;
display: flex;
opacity: 0;
}
#page-name::before {
font-size: 18px;
position: absolute;
width: 100%;
height: 100%;
border-radius: 8px;
color: white !important;
top: 0;
left: 0;
content: "回到顶部";
background-color: var(--zhsher-theme);
transition: all 0.3s;
-webkit-transition: all 0.3s;
-moz-transition: all 0.3s;
-ms-transition: all 0.3s;
-o-transition: all 0.3s;
opacity: 0;
box-shadow: 0 0 3px var(--zhsher-theme);
line-height: 45px; /*如果垂直位置不居中可以微调此值,也可以删了*/
}
#page-name:hover:before {
opacity: 1;
}
#name-container {
transition: all 0.3s;
-webkit-transition: all 0.3s;
-moz-transition: all 0.3s;
-ms-transition: all 0.3s;
-o-transition: all 0.3s;
}
#name-container:hover {
transform: translateX(-50%) scale(1.03);
}
#page-name {
position: relative;
padding: 10px 30px;
}

center#name-container {
position: absolute;
width: 100%;
left: 50%;
transform: translateX(-50%);
font-family: "ZhuZiAYuanJWD";
}
.nav-fixed.nav-visible #name-container {
transition: 0.3s;
transform: translate(-50%, 60px);
}
.nav-fixed.nav-visible #menus .menus_items {
transform: translate(-50%);
transition: 0.3s;
line-height: 60px;
}
.nav-fixed #menus .menus_items {
transform: translate(-50%, -60px);
transition: 0.3s;
}
.nav-fixed #name-container {
top: 15%;
transition: 0.3s;
}
#name-container {
bottom: 60px;
}

.mask-name-container {
max-width: 1200px;
width: 50%;
height: 100%;
position: absolute;
overflow: hidden;
left: 50%;
transform: translateX(-50%);
}

@media screen and (max-width: 992px) {
.mask-name-container {
width: 65%;
}
}

@media screen and (max-width: 768px) {
.mask-name-container {
display: none;
}
}
#sidebar #sidebar-menus .menus_items .site-page:hover {
color: var(--zhsher-white);
border-radius: var(--zhsher-border-radius);
}
#nav .menus_items .menus_item > a > i:last-child {
display: none;
}
#nav #search-button {
font-size: 1.3em;
}

@media screen and (min-width: 900px) {
#nav .back-home-button:hover {
box-shadow: var(--zhsher-shadow-main);
}
}

.back-home-button:hover {
background: var(--zhsher-theme);
color: var(--zhsher-white) !important;
}
.back-home-button {
display: flex;
width: 35px;
height: 35px;
padding: 0 !important;
align-items: center;
justify-content: center;
margin-right: 4px;
transition: 0.3s;
border-radius: 8px;
}

.back-home-button:hover .back-menu-list-groups {
display: flex;
opacity: 1;
transition: 0.3s;
top: 55px;
pointer-events: auto;
left: 0;
}
.back-home-button .back-menu-list-groups {
position: absolute;
top: 65px;
left: 0;
background: var(--zhsher-card-bg);
border-radius: 12px;
border: var(--style-border);
flex-direction: column;
font-size: 12px;
color: var(--zhsher-secondtext);
box-shadow: var(--zhsher-shadow-border);
transition: 0s;
opacity: 0;
pointer-events: none;
}

.back-home-button .back-menu-list-group {
display: flex;
flex-direction: column;
}
.back-home-button .back-menu-list-group .back-menu-list-title {
margin: 8px 0 0 16px;
transition: 0.3s;
}
.back-home-button .back-menu-list {
display: flex;
/* 微调 */
flex-direction: row;
width: 332px;
flex-wrap: wrap;
justify-content: space-between;
}
.back-home-button .back-menu-list::before {
position: absolute;
top: -22px;
left: 0px;
width: 100%;
height: 25px;
content: "";
}

.back-home-button .back-menu-list-group:hover .back-menu-list-title {
color: var(--zhsher-theme);
}
.back-home-button .back-menu-list-groups:hover {
border: var(--style-border-hover);
}
.back-home-button .back-menu-list .back-menu-item {
display: flex;
align-items: center;
margin: 4px 8px;
padding: 4px 8px !important;
transition: 0.3s;
border-radius: 8px;
width: 150px;/* 调整 */
}
.back-home-button .back-menu-list .back-menu-item .back-menu-item-text {
font-size: var(--global-font-size);
margin-left: 0.5rem;
color: var(--zhsher-fontcolor);
white-space: nowrap;
}
#nav #blog-info {
flex-wrap: nowrap;
height: 60px;
display: flex;
align-items: center;
/* z-index: 102; */
transition: 0.3s;
}
.back-home-button .back-menu-list .back-menu-item .back-menu-item-icon {
width: 24px;
height: 24px;
border-radius: 24px;
background: var(--zhsher-secondbg);
}
#page-header #nav .back-home-button {
cursor: pointer;
position: relative;
}

@media screen and (min-width: 1300px) {
#nav a:hover {
transform: scale(1.03);
}
}
.back-home-button .back-menu-list .back-menu-item:hover .back-menu-item-text {
color: var(--zhsher-white);
}
.back-menu-item-icon.loading img {
width: 25px;
}

#page-header #nav #menus .nav-button.long a.totopbtn,
#page-header #nav #menus .nav-button.long,
#page-header #nav #menus .nav-button.long a.totopbtn span {
width: 70px;
}
#page-header #nav #menus .nav-button.long a.totopbtn span {
border-radius: 35px;
display: flex;
justify-content: center;
align-items: center;
transition: 0.3s;
white-space: nowrap;
}

#page-header #nav #menus .nav-button.long a.totopbtn:hover {
border-radius: 35px;
height: 30px;
}

#nav #search-button {
padding-left: 0;
}
#page-header #nav .nav-button {
margin-left: 0.5rem;
padding: 0;
}
#page-header:not(.is-top-bar) #nav-totop a {
display: none;
}
#search-button a.site-page.social-icon.search span {
display: none;
}

/* 微调 */
#nav #blog-info {
overflow: unset;
}

新建[BlogRoot]/source/js/nav_menu.js

// 返回顶部 显示网页阅读进度
window.onscroll = percent; // 执行函数
// 页面百分比
function percent() {
let a = document.documentElement.scrollTop || window.pageYOffset, // 卷去高度
b =
Math.max(
document.body.scrollHeight,
document.documentElement.scrollHeight,
document.body.offsetHeight,
document.documentElement.offsetHeight,
document.body.clientHeight,
document.documentElement.clientHeight
) - document.documentElement.clientHeight, // 整个网页高度 减去 可视高度
result = Math.round((a / b) * 100), // 计算百分比
btn = document.querySelector("#percent"); // 获取图标

result <= 99 || (result = 99), (btn.innerHTML = result);
}

document.getElementById("page-name").innerText = document.title.split(" | 张时贰")[0];

修改主题配置文件_config.butterfly.yml,引入css、js文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/nav_menu.css">
bottom:
# - <script src="xxxx"></script>
+ - <script data-pjax src="/js/nav_menu.js"></script>

为了处理顶栏一闪而过的 bug 修改[BlogRoot]/themes/butterfly/source/js/main.js,注意有引用线上版本的话一定要使用本地版本改完再自行上传线上版本

if (currentTop > 56) {
+ $header.classList.add('is-top-bar')
if (isDown) {

if (currentTop === 0) {
- $header.classList.remove('nav-fixed', 'nav-visible')
+ $header.classList.remove('is-top-bar')
}

修改[BlogRoot]/themes/butterfly/layout/includes/header/index.pug

其中nav-visible可以控制默认显示的是站点标题还是导航栏菜单。

  if top_img !== false
- var imgSource = top_img && top_img.indexOf('/') !== -1 ? `background-image: url('${url_for(top_img)}')` : `background: ${top_img}`
- var bg_img = top_img ? imgSource : ''
- var site_title = page.title || page.tag || page.category || config.title
- - var isHomeClass = is_home() ? 'full_page' : 'not-home-page'
+ - var isHomeClass = is_home() ? 'full_page nav-fixed nav-visible' : 'not-home-page'
- is_post() ? isHomeClass = 'post-bg' : isHomeClass
else
- var isHomeClass = 'not-top-img'

全部替换[BlogRoot]/themes/butterfly/layout/includes/header/nav.pug

nav#nav
span#blog-info
.back-home-button(tabindex='-1')
i.back-home-button-icon.fas.fa-grip-vertical
.back-menu-list-groups
.back-menu-list-group
.back-menu-list-title 网页
.back-menu-list
a.back-menu-item(href='/', title='前往博客主页', target='_blank', one-link-mark='yes')
img.back-menu-item-icon(src='https://q1.qlogo.cn/g?b=qq&nk=1310446718&s=5')
span.back-menu-item-text 博客

a.back-menu-item(href='https://status.zhsher.cn/status/friend', rel='external nofollow', title='前往友链监控', target='_blank', one-link-mark='yes')
img.back-menu-item-icon(src='https://zhsher.cn/Hexo_img/config/nav_uptime.webp')
span.back-menu-item-text 友链监控

a.back-menu-item(href='https://rv.zhsher.cn/Game_box/game/', rel='external nofollow', title='前往游戏盒', target='_blank', one-link-mark='yes')
img.back-menu-item-icon(src='https://zhsher.cn/Hexo_img/config/nav_box.webp')
span.back-menu-item-text 游戏盒
.back-menu-list-group
.back-menu-list-title 项目
.back-menu-list
a.back-menu-item(href='https://github.com/GC-ZF/hexo-hot-article', title='前往阅读统计', target='_blank', rel='noopener nofollow', one-link-mark='yes')
img.back-menu-item-icon(src='https://zhsher.cn/Hexo_img/config/nav_article.webp')
span.back-menu-item-text 占位

a#site-name(href=url_for('/'))
.title #[=config.title]
i.fa-solid.fa-house

div.mask-name-container
center(id="name-container")
a(id="page-name" href="javascript:rmf.scrollToTop()") PAGE_NAME

#menus
if (theme.algolia_search.enable || theme.local_search.enable || theme.docsearch.enable)
div.nav-button#search-button
a.site-page.social-icon.search(href="javascript:void(0);")
i.fas.fa-search.fa-fw
span=' '+_p('search.title')

if theme.darkmode.enable && theme.darkmode.button
div.nav-button#darkmode_navswitch
a.darkmode_switchbutton(type="button" title=_p('rightside.night_mode_title') onclick="rmf.switchDarkMode()")
i.fas.fa-adjust

div.nav-button#nav-totop
a.totopbtn
i.fas.fa-arrow-up
span#percent(onclick="btf.scrollToDest(0,500)") 0


!=partial('includes/header/menu_item', {}, {cache: true})

#toggle-menu
a.site-page
i.fas.fa-bars.fa-fw

社交卡片

来源:安知鱼 - 生活明朗 万物可爱站点扒的

全部替换[BlogRoot]/themes/butterfly/layout/includes/widget/card_author.pug

if theme.aside.card_author.enable
.card-widget.card-info
.author-info-top
.card-info-avatar
a.avatar-img(href='/about')
img(src=url_for(theme.avatar.img) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt="avatar")
.author-status-box
.author-status
g-emoji.g-emoji(alias='palm_tree', fallback-src='https://zhsher.cn/Hexo_img/config/social_card2.webp') 🌴
span On vacation
.author-info__sayhi#author-info__sayhi
h1.author-info__name= config.author
.author-info__description!= theme.aside.card_author.description || config.description
.banner-button-group
a.banner-button(href='/about')
i.fas.fa-circle-arrow-up-right
span.banner-button-text 了解更多

if(theme.social)
.card-info-social-icons.is-center
!=fragment_cache('social', function(){return partial('includes/header/social')})

新建[BlogRoot]/source/css/social_card.css

div#author-info__sayhi {
text-align: left;
background: var(--zhsher-white-op);
color: var(--font-color);
border: var(--style-border);
font-size: 12px;
margin-right: auto;
padding: 5px 8px;
border-radius: 12px;
width: fit-content;
display: inline;
margin-left: -1px
}

.card-widget .author-info-top {
margin: 15px auto 0;
display: flex;
justify-content: center
}

.card-widget .card-info-avatar {
display: inline-block;
position: relative
}

.card-widget.card-info .banner-button-group {
margin: 5px 0;
display: flex
}

#aside-content .card-info .banner-button {
height: 40px;
width: 100%;
border-radius: 20px;
justify-content: center
}

.card-widget.card-info .banner-button-group .banner-button {
padding: 20px 12px;
background: var(--zhsher-theme);
border-radius: 12px;
color: var(--zhsher-white);
display: flex;
align-items: center;
z-index: 1;
transition: all .3s ease 0s;
cursor: pointer
}

.card-widget.card-info .banner-button-group .banner-button .fas.fa-circle-arrow-up-right {
font-size: 1.3rem;
margin-right: 10px
}

.card-widget.card-info .banner-button-group .banner-button:hover {
background: var(--zhsher-main-op-deep);
color: var(--zhsher-white)
}

.card-info-avatar .avatar-img {
width: 100px;
height: 100px;
display: block
}

.card-info-avatar .author-status-box {
position: absolute;
bottom: 0;
left: calc(100% - 28px);
width: 28px;
height: 28px;
border: var(--style-border);
border-radius: 2em;
background-color: var(--zhsher-card-bg);
transition: .3s;
overflow: hidden
}

.card-info-avatar .author-status-box .author-status {
display: flex;
align-items: center;
justify-content: center;
height: 28px;
padding: 0 5px
}

.card-info-avatar .author-status-box:hover {
width: 105px
}

.card-info-avatar .author-status-box:hover .author-status span {
width: 105px;
margin-left: 4px
}

.card-info-avatar .author-status-box .author-status span {
width: 0;
font-size: 12px;
height: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
transition: .3s
}

#aside-content > .card-info {
background: #fff url(https://img02.anheyu.com/adminuploads/1/2022/10/26/6358a07bf21fc.webp) top -24% center no-repeat;
position: relative
}

[data-theme=dark] #aside-content > .card-info {
background: var(--zhsher-card-bg)
}

@media screen and (max-width: 992px) {
#aside-content > .card-info {
background-size: 100% 70%
}
}

.card-widget .author-info__name {
line-height: 1.5em;
margin: 4px 0
}

新建[BlogRoot]/source/js/social_card.js

var zhsher = {
getTimeState: function () {
var element = (new Date).getHours(), time = "";
return 0 <= element && element <= 5 ? time = "晚安😴" : 5 < element && element <= 10 ? time = "早上好👋" : 10 < element && element <= 14 ? time = "中午好👋" : 14 < element && element <= 18 ? time = "下午好👋" : 18 < element && element <= 24 && (time = "晚上好👋"), time
},
sayhi: function () {
var element = document.getElementById("author-info__sayhi");
element && (element.innerHTML = zhsher.getTimeState() + "!我是")
}
}
zhsher.sayhi();

修改主题配置文件_config.butterfly.yml,引入css、js文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/social_card.css">
bottom:
# - <script src="xxxx"></script>
+ - <script data-pjax src="/js/social_card.js"></script>

随便逛逛(未启用仅记录)

原文地址:Hexo的Butterfly魔改:随机网页跳转(无缝版) | 张洪Heo

新建[BlogRoot]/themes/butterfly/scripts/helpers/random.js

hexo.extend.generator.register('random', function (locals) {
const config = hexo.config.random || {}
const posts = []
for (const post of locals.posts.data) {
if (post.random !== false) posts.push(post.path)
}
return {
path: config.path || 'zhheo/random.js',
data: `var posts=${JSON.stringify(posts)};function toRandomPost(){pjax.loadUrl('/'+posts[Math.floor(Math.random() * posts.length)]);};`
}
})

没有开启pjax用下面的代码

hexo.extend.generator.register('random', function (locals) {
const config = hexo.config.random || {}
const posts = []
for (const post of locals.posts.data) {
if (post.random !== false) posts.push(post.path)
}
return {
path: config.path || 'zhheo/random.js',
data: `var posts=${JSON.stringify(posts)};function toRandomPost(){window.open('/'+posts[Math.floor(Math.random() * posts.length)],"_self");};`
}
})

修改主题配置文件_config.butterfly.yml,引入js文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
bottom:
# - <script src="xxxx"></script>
+ - <script src="/zhheo/random.js"></script>

在需要调用的位置执行toRandomPost()函数即可。

比如任意dom添加onclick="toRandomPost()"

例如主题配置文件_config.butterfly.yml导航栏中需要的位置添加,宝藏博主: javascript:travelling() || fas fa-bus

右侧悬浮按钮刷新页面(未启用仅记录)

借鉴控制台:轻笑Chuckle

新建[BlogRoot]/source/js/refresh.js

function refreshCache(){confirm("是否确定刷新缓存")&&location.reload(!0)}

修改主题配置文件_config.butterfly.yml,引入css文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/refresh.css">

修改[BlogRoot]/themes/butterfly/layout/includes/rightside.pug

mixin rightsideItem(array)
each item in array
case item
+ when 'refresh'
+ button#refresh-cache(type='button',title='刷新缓存',onclick='refreshCache()')

- - const hideArray = enable ? hide && hide.split(',') :['readmode','translate','darkmode','hideAside']

+ - const hideArray = enable ? hide && hide.split(',') :['readmode','translate','darkmode','hideAside','refresh']

人潮汹涌轮播组件(未启用仅记录)

插件地址:hexo-butterfly-swiper-anzhiyu-pro - npm

安装

npm install hexo-butterfly-swiper-anzhiyu-pro --save

修改配置文件 _config.yml,在最下面添加

# 人潮汹涌
swiper:
enable: true # 开关
randomenable: true # 人潮汹涌开关
priority: 5 #过滤器优先权
enable_page: / # 应用页面
timemode: date #date/updated
layout: # 挂载容器类型
type: id
name: home_top
index: 1
category:
- name: 前端
path: /categories/前端/
shadow: var(--anzhiyu-shadow-blue)
class: blue
icon: fas fa-dove
- name: 大学
path: /categories/大学/
shadow: var(--anzhiyu-shadow-red)
class: red
icon: fas fa-burn
- name: 生活
path: /categories/生活/
shadow: var(--anzhiyu-shadow-green)
class: green
icon: fas fa-book
default_descr: 再怎么看我也不知道怎么描述它的啦!
swiper_css: https://cdn.cbd.int/hexo-butterfly-swiper-anzhiyu-pro/lib/swiper.min.css #swiper css依赖
swiper_js: https://npm.elemecdn.com/anzhiyu-blog@1.1.6/js/swiper.min.js #swiper js依赖 #swiper js依赖
custom_css: https://cdn.cbd.int/hexo-butterfly-swiper-anzhiyu-pro/lib/swiperstyle.css # 适配主题样式补丁
custom_js: https://cdn.cbd.int/hexo-butterfly-swiper-anzhiyu-pro/lib/swiper_init.js # swiper初始化方法
gsap_js: https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/gsap/3.9.1/gsap.min.js
people_js: https://npm.elemecdn.com/hexo-butterfly-swiper-anzhiyu-pro/lib/people.min.js
categorygroup_css: https://cdn.cbd.int/hexo-butterfly-swiper-anzhiyu-pro/lib/categoryGroup.css

新建[BlogRoot]/source/css/home_top.css

#home_top {
margin: 1rem auto 0;
padding: 0px 15px;
max-width: 1450px;
width: 100%;
}

修改主题配置文件_config.butterfly.yml,引入css文件

inject:
head:
# - <link rel="stylesheet" href="/xxx.css">
+ - <link rel="stylesheet" href="/css/home_top.css">

修改[BlogRoot]/themes/butterfly/layout/includes/header/index.pug,最后一行加

#home_top

使用时在文章的front_matter中添加swiper_indextop_group_index配置项

---
title: 文章标题
date: 创建日期
updated: 更新日期
cover: 文章封面
description: 文章描述
swiper_index: 1 #置顶轮播图顺序,需填非负整数,数字越大越靠前
top_group_index: 1 #右侧磁帖顺序,需填非负整数,数字越大越靠前
---

八、部署至服务器

注意一:如果仅是玩Hexo博客,不需要浪费这个钱购买服务器,使用Github、Vercel等这类托管服务即可

注意贰:此方法已过时,因为仅是服务器部署且比较繁琐,第六小节中的自动化部署无脑简单方便更适合实际生产!

2022.05.31日,没错!我买服务器啦!!!微信里加了各种平台的运营、经销商之类,早上告我腾讯云618在搞促销,我当时在上课没回复,可能以为我没兴趣,中午转了我个红包?!”帮我完成一下考核,随便买个域名”,小张岂能是无功受禄之人?”不用了,我买个服务器给你冲KPI吧!”,废话不多说开始教学,从买服务器开始吧

准备

域名:阿里云域名28元一年

服务器:腾讯云新用户首购45元一年,Ubuntu 轻量型 2核2G 40GB 4M带宽 300G流量 。博客轻量型足够,毕竟学生党嘛

shell工具(仁者见仁智者见智,不分好坏):Aechoterm(首推)=CMD+vim命令=XShell(连接服务器)+Xftp 6(与服务器互传文件)+VScode或Notepad++(编辑服务器里的文件)

先前部署在Github上,不需要备案,但是服务器建在国内就必须做了

  1. 在服务器厂商(阿里云/腾讯云)申请ICP备案(十天左右通过审核,ICP必须备否则域名无法访问)
  2. 给域名申请SSL证书
  3. ICP备案通过后在全国公安机关互联网站安全管理服务平台进行公安备案(公安备案看地方,原则上是强制性的,但有的地方不管,博客备非交互式的www服务,如果安装了评论则备交互式且需要面审)

这部分全是提交申请也没什么好写的,参考:腾讯云完整建站过程阿里云域名SSL证书申请,之后就可以部署服务器了,也可以先部署只是没ICP备案,部署好网站打不开(如果你和我一样在写教程,截图中公网IP不要暴露)

安装宝塔

买下服务器先重置密码

Hexo博客搭建17

打开命令行窗口连接服务器:ssh root@公网IP,输入密码,如果你不是CentOS,宝塔面板官网看一下安装指令

Hexo博客搭建18

yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh ed8484bec

确认安装宝塔,输入y等待执行完即可,返回信息如下。这个窗口不要关,第五行外网地址,第七、八行是账号密码

success
==================================================================
Congratulations! Installed successfully!
==================================================================
外网面板地址: http://服务器ip:8888/5b50213c
内网面板地址: http://服务器ip:8888/5b50213c
username: mpspyztn
password: 14871f82
If you cannot access the panel,
release the following panel port [8888] in the security group
若无法访问面板,请检查防火墙/安全组是否有放行面板[8888]端口
==================================================================
Time consumed: 0 Minute!

在防火墙为宝塔添加端口8888,阿里叫添加安全组

Hexo博客搭建19

接下来访问外网地址http://服务器ip:8888/5b50213c,第一次进来默认安装LNMP,为我们一键安装所需要的环境。顺便在面板设置里改下登录用户名和密码

Hexo博客搭建20

方法一 Github Action

注意:原理及优化已在第六小节自动化部署中总结,方法一已过时

视频教程:自动部署到服务器和github page bilibili。不得不多说,看了一些其它方法,卷二兔是最省事最简单无脑的教学(包括之前的教学)

打开宝塔面板,输入自己的域名(上文域名已做好解析)

Hexo博客搭建21

新建[BlogRoot]/.github/workflows/autodeploy.yml,51~53行为Github用户名和邮箱,68行宝塔根目录

# 当有改动推送到master分支时,启动Action
name: 自动部署

on:
push:
branches:
- main

release:
types:
- published

jobs:
checkout:
runs-on: ubuntu-latest
steps:
- name: 检查分支
uses: actions/checkout@v2
with:
ref: main

- name: 安装 Node
uses: actions/setup-node@v1
with:
node-version: "12.x"

- name: 安装 Hexo
run: |
export TZ='Asia/Shanghai'
npm install hexo-cli -g

- name: 缓存 Hexo
uses: actions/cache@v1
id: cache
with:
path: node_modules
key: ${{runner.OS}}-${{hashFiles('**/package-lock.json')}}

- name: 安装依赖
if: steps.cache.outputs.cache-hit != 'true'
run: |
npm install --save
git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly

- name: 生成静态文件
run: |
hexo clean
hexo generate

- name: 部署到github pages
run: |
git config --global user.name "xxxx"
git config --global user.email "xxxx@gmail.com"
# git clone https://github.com/xxx/xxx.github.io.git .deploy_git
# 此处务必用HTTPS链接。SSH链接可能有权限报错的隐患
# =====注意.deploy_git前面有个空格=====
# 这行指令的目的是clone博客静态文件仓库,防止Hexo推送时覆盖整个静态文件仓库,而是只推送有更改的文件
# 我注释掉了是为了刷新整个仓库,也可以选择不注释掉,但是可能出现没有识别到的情况
hexo deploy

- name: 部署到云服务器
uses: cross-the-world/scp-pipeline@master
with:
host: ${{ secrets.USER_HOST }}
user: ${{ secrets.USER_NAME }}
pass: ${{ secrets.USER_PASS }}
connect_timeout: 10s
local: './.deploy_git/*'
remote: /www/wwwroot/zhsher.cn

在博客备份的仓库,注意是备份,不是渲染好的静态页面github.io仓库,添加Secrets

Hexo博客搭建22

回到博客路径下

git add .
git commit -m "添加Action"
git push

如果这里显示到自动部署,等待执行完毕后为绿色则部署成功

Hexo博客搭建23

方法二

原理:通过在服务器内创建Git仓库,利用Git钩子将文件显示在站点路径下

参考:

命令行或者宝塔面板操作都可以,这里以命令操作为例

环境搭建-服务器端配置

因为服务器也需要搭建环境,和我们的本地是一样的,连接服务器后操作

服务器安装git(ubuntu系统自带git)

yum install git

添加用户

adduser git

设置/etc/sudoers文件权限

chmod 740 /etc/sudoers

编辑/etc/sudoers

vi /etc/sudoers

输入 i 进入 insert 模式 ,找到 root ALL=(ALL) ALL ,在其下方加入一行 git ALL=(ALL) ALL

git ALL=(ALL) ALL	# 按 ESC ,输入 :wq ,保存文件

变更/etc/sudoers文件权限

chmod 400 /etc/sudoers

设置git账户密码

sudo passwd git

切换git账户,创建 ~/.ssh 文件夹和 ~/.ssh/authorized_keys 文件

su git
mkdir ~/.ssh
vim ~/.ssh/authorized_keys

输入 i 进入 insert 模式,将电脑本地的id_rsa.pub公钥复制进去(可以和Github密钥公用一个或者重新建一个),按 ESC ,输入 :wq ,保存文件

配置权限

chmod 600 /home/git/.ssh/authorized_keys
chmod 700 /home/git/.ssh

测试,在本地电脑端连接,输入yes

ssh -i ~\.ssh\私钥文件名 git@服务器ip地址或域名

以上服务器端Git已配置好,相当于在自己的服务器创建了一个Github用户及密码(root权限太高所以用git用户操作),接下来就是新建仓库

切换root账户

sudo su root

创建仓库目录,在var目录下创建repo作为Git仓库目录并添加权限

mkdir /var/repo		# 新建文件夹
chown -R git:git /var/repo # 为git用户设置权限
chmod -R 755 /var/repo # 设置权限

创建 hexo目录作为网站根目录

mkdir /www/wwwroot/hexo			# 新建文件夹
chown -R git:git /www/wwwroot/hexo # 为git用户设置权限
chmod -R 755 /www/wwwroot/hexo # 设置权限

创建git仓库

cd /var/repo
git init --bare hexo.git

因为Linux系统下,Git仓库文件不会显示存在,钩子就是说把hexo.git这个仓库的文件内容显示在/www/wwwroot/hexo目录下

编辑Git钩子

vim /var/repo/hexo.git/hooks/post-receive

i进入编辑模式,添加下面的代码,按esc输入:wq 保存

git --work-tree=/www/wwwroot/hexo --git-dir=/var/repo/hexo.git checkout -f

更改权限

chown -R git:git /var/repo/hexo.git/hooks/post-receive
chmod +x /var/repo/hexo.git/hooks/post-receive

配置宝塔

宝塔面板中网页->添加站点。注意根目录设置!!!

Hexo博客搭建24

在域名服务商添加解析,地址为自己的服务器公网IP

Hexo博客搭建25

配置本地部署

修改配置文件 _config.yml,找到deploy,配置自己的公网ip。为了测试先注释掉Github仓库

deploy:
- type: git
repository:
#github: https://github.com/xxx/xxxx.github.io.git <-注释掉
tecent: git@xxx.xx.xxx.xxx:/var/repo/hexo.git # tecent随便命名
branch: main

hexo clean & hexo g & hexo d三连上去,上传成功在面板文件的/www/wwwroot/hexo查看

设置同时上传服务器与Github,注意格式与之前不同!我的踩坑记录:appear a new branch?how do I do that? · Issue #258appear a new branch?how do I do that · Discussion #4988

deploy:
- type: git
repository:
github: https://github.com/xxx/xxx.github.io.git,main
tecent: root@xxx.xx.xxx.xxx:/var/repo/hexo.git,master

SSL证书添加

在阿里云下载Nginx格式证书

Hexo博客搭建26

宝塔面板为网站添加证书

Hexo博客搭建27

添加备案信息

修改主题配置文件_config.butterfly.yml,将备案信息添加至页脚

# Footer Settings
# --------------------------------------
footer:
owner:
enable: true
since: 2022
custom_text: <div><a onclick="window.open('https://beian.miit.gov.cn/#/Integrated/index')" class="footer-a">晋ICP备2022005322号</a></div>
copyright: true # Copyright of theme and framework

特别鸣谢

一百个Chocolate博客搭建整理以及部分魔改,他的博客里还有好多好多魔改,大家可以去参考参考,他有的都取消了,可能美化的终极就是简化吧哈哈哈(就是因为这个学长所以学的Hexo!)

你真是一个美好的人类,B站系列教程及博客,对萌新简直太友好!

小冰老师系列教程

Akilarの糖果屋系列教程

Heo哥

Leonus

轻笑Chuckle

安知鱼

Ariasaka

心流

完结撒花,以上有任何看不懂的地方,可以直接评论或者滴滴我的QQ