前言

这里是搭建博客时遇到的一些问题,因为怕以后忘记了会多走弯路,就记在这里了。

看了众多大佬的魔改博客,自觉像我这样没有前端基础的人,只能是小打小闹一般图一乐,不好好学习是永远不可能达到那样的高度的……

魔改记录存档

记录魔改过程,便于后续恢复与更新

为博文添加统计 ECharts 图表

感谢:Hexo 博客文章统计图 | Eurkon

注意,可能是由于新版本 Butterfly(5.0 以上)更改了设置按钮加载的逻辑, chart.js 无法给官方的黑暗模式切换按键添加 listener 了。

操作方法

其他步骤与参考博文基本一致。在添加 charts.js 时需要注意路径位置。

[Blogroot]\themes\butterfly\scripts\helpers\ 或者是[Blogroot]\node_modules\hexo-theme-butterfly\scripts\helpers\(具体与安装方式有关)目录下新建 charts.js 文件,然后添加以下内容:

const cheerio = require('cheerio')
const moment = require('moment')

hexo.extend.filter.register('after_render:html', function (locals) {
const $ = cheerio.load(locals)
const post = $('#posts-chart')
const tag = $('#tags-chart')
const category = $('#categories-chart')
const htmlEncode = false

if (post.length > 0 || tag.length > 0 || category.length > 0) {
if (post.length > 0 && $('#postsChart').length === 0) {
if (post.attr('data-encode') === 'true') htmlEncode = true
post.after(postsChart(post.attr('data-start')))
}
if (tag.length > 0 && $('#tagsChart').length === 0) {
if (tag.attr('data-encode') === 'true') htmlEncode = true
tag.after(tagsChart(tag.attr('data-length')))
}
if (category.length > 0 && $('#categoriesChart').length === 0) {
if (category.attr('data-encode') === 'true') htmlEncode = true
category.after(categoriesChart(category.attr('data-parent')))
}

if (htmlEncode) {
return $.root().html().replace(/&#/g, '&#')
} else {
return $.root().html()
}
} else {
return locals
}
}, 15)

function postsChart (startMonth) {
const startDate = moment(startMonth || '2020-01')
const endDate = moment()

const monthMap = new Map()
const dayTime = 3600 * 24 * 1000
for (let time = startDate; time <= endDate; time += dayTime) {
const month = moment(time).format('YYYY-MM')
if (!monthMap.has(month)) {
monthMap.set(month, 0)
}
}
hexo.locals.get('posts').forEach(function (post) {
const month = post.date.format('YYYY-MM')
if (monthMap.has(month)) {
monthMap.set(month, monthMap.get(month) + 1)
}
})
const monthArr = JSON.stringify([...monthMap.keys()])
const monthValueArr = JSON.stringify([...monthMap.values()])

return `
<script id="postsChart">
var color = document.documentElement.getAttribute('data-theme') === 'light' ? '#4c4948' : 'rgba(255,255,255,0.7)'
var postsChart = echarts.init(document.getElementById('posts-chart'), 'light');
var postsOption = {
title: {
text: '文章发布统计图',
x: 'center',
textStyle: {
color: color
}
},
tooltip: {
trigger: 'axis'
},
xAxis: {
name: '日期',
type: 'category',
boundaryGap: false,
nameTextStyle: {
color: color
},
axisTick: {
show: false
},
axisLabel: {
show: true,
color: color
},
axisLine: {
show: true,
lineStyle: {
color: color
}
},
data: ${monthArr}
},
yAxis: {
name: '文章篇数',
type: 'value',
nameTextStyle: {
color: color
},
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
show: true,
color: color
},
axisLine: {
show: true,
lineStyle: {
color: color
}
}
},
series: [{
name: '文章篇数',
type: 'line',
smooth: true,
lineStyle: {
width: 0
},
showSymbol: false,
itemStyle: {
opacity: 1,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 165)'
},
{
offset: 1,
color: 'rgba(1, 191, 236)'
}])
},
areaStyle: {
opacity: 1,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 165)'
}, {
offset: 1,
color: 'rgba(1, 191, 236)'
}])
},
data: ${monthValueArr},
markLine: {
data: [{
name: '平均值',
type: 'average',
label: {
color: color
}
}]
}
}]
};
postsChart.setOption(postsOption);
window.addEventListener('resize', () => {
postsChart.resize();
});
postsChart.on('click', 'series', (event) => {
if (event.componentType === 'series') window.location.href = '/archives/' + event.name.replace('-', '/');
});
</script>`
}

function tagsChart (len) {
const tagArr = []
hexo.locals.get('tags').map(function (tag) {
tagArr.push({ name: tag.name, value: tag.length, path: tag.path })
})
tagArr.sort((a, b) => { return b.value - a.value })

const dataLength = Math.min(tagArr.length, len) || tagArr.length
const tagNameArr = []
for (let i = 0; i < dataLength; i++) {
tagNameArr.push(tagArr[i].name)
}
const tagNameArrJson = JSON.stringify(tagNameArr)
const tagArrJson = JSON.stringify(tagArr)

return `
<script id="tagsChart">
var color = document.documentElement.getAttribute('data-theme') === 'light' ? '#4c4948' : 'rgba(255,255,255,0.7)'
var tagsChart = echarts.init(document.getElementById('tags-chart'), 'light');
var tagsOption = {
title: {
text: 'Top ${dataLength} 标签统计图',
x: 'center',
textStyle: {
color: color
}
},
tooltip: {},
xAxis: {
name: '标签',
type: 'category',
nameTextStyle: {
color: color
},
axisTick: {
show: false
},
axisLabel: {
show: true,
color: color,
interval: 0
},
axisLine: {
show: true,
lineStyle: {
color: color
}
},
data: ${tagNameArrJson}
},
yAxis: {
name: '文章篇数',
type: 'value',
splitLine: {
show: false
},
nameTextStyle: {
color: color
},
axisTick: {
show: false
},
axisLabel: {
show: true,
color: color
},
axisLine: {
show: true,
lineStyle: {
color: color
}
}
},
series: [{
name: '文章篇数',
type: 'bar',
data: ${tagArrJson},
itemStyle: {
borderRadius: [5, 5, 0, 0],
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 165)'
},
{
offset: 1,
color: 'rgba(1, 191, 236)'
}])
},
emphasis: {
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 195)'
},
{
offset: 1,
color: 'rgba(1, 211, 255)'
}])
}
},
markLine: {
data: [{
name: '平均值',
type: 'average',
label: {
color: color
}
}]
}
}]
};
tagsChart.setOption(tagsOption);
window.addEventListener('resize', () => {
tagsChart.resize();
});
tagsChart.on('click', 'series', (event) => {
if(event.data.path) window.location.href = '/' + event.data.path;
});
</script>`
}

function categoriesChart (dataParent) {
const categoryArr = []
let categoryParentFlag = false
hexo.locals.get('categories').map(function (category) {
if (category.parent) categoryParentFlag = true
categoryArr.push({
name: category.name,
value: category.length,
path: category.path,
id: category._id,
parentId: category.parent || '0'
})
})
categoryParentFlag = categoryParentFlag && dataParent === 'true'
categoryArr.sort((a, b) => { return b.value - a.value })
function translateListToTree (data, parent) {
let tree = []
let temp
data.forEach((item, index) => {
if (data[index].parentId == parent) {
let obj = data[index];
temp = translateListToTree(data, data[index].id);
if (temp.length > 0) {
obj.children = temp
}
if (tree.indexOf())
tree.push(obj)
}
})
return tree
}
const categoryNameJson = JSON.stringify(categoryArr.map(function (category) { return category.name }))
const categoryArrJson = JSON.stringify(categoryArr)
const categoryArrParentJson = JSON.stringify(translateListToTree(categoryArr, '0'))

return `
<script id="categoriesChart">
var color = document.documentElement.getAttribute('data-theme') === 'light' ? '#4c4948' : 'rgba(255,255,255,0.7)'
var categoriesChart = echarts.init(document.getElementById('categories-chart'), 'light');
var categoryParentFlag = ${categoryParentFlag}
var categoriesOption = {
title: {
text: '文章分类统计图',
x: 'center',
textStyle: {
color: color
}
},
legend: {
top: 'bottom',
data: ${categoryNameJson},
textStyle: {
color: color
}
},
tooltip: {
trigger: 'item'
},
series: []
};
categoriesOption.series.push(
categoryParentFlag ?
{
nodeClick :false,
name: '文章篇数',
type: 'sunburst',
radius: ['15%', '90%'],
center: ['50%', '55%'],
sort: 'desc',
data: ${categoryArrParentJson},
itemStyle: {
borderColor: '#fff',
borderWidth: 2,
emphasis: {
focus: 'ancestor',
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(255, 255, 255, 0.5)'
}
}
}
:
{
name: '文章篇数',
type: 'pie',
radius: [30, 80],
roseType: 'area',
label: {
color: color,
formatter: '{b} : {c} ({d}%)'
},
data: ${categoryArrJson},
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(255, 255, 255, 0.5)'
}
}
}
)
categoriesChart.setOption(categoriesOption);
window.addEventListener('resize', () => {
categoriesChart.resize();
});
categoriesChart.on('click', 'series', (event) => {
if(event.data.path) window.location.href = '/' + event.data.path;
});
</script>`
}

在添加黑夜模式适配时,需要注入相应的代码到底部

function switchPostChart () {
// 这里为了统一颜色选取的是“明暗模式”下的两种字体颜色,也可以自己定义
let color = document.documentElement.getAttribute('data-theme') === 'light' ? '#4C4948' : 'rgba(255,255,255,0.7)'
if (document.getElementById('posts-chart') && postsOption) {
try {
let postsOptionNew = postsOption
postsOptionNew.title.textStyle.color = color
postsOptionNew.xAxis.nameTextStyle.color = color
postsOptionNew.yAxis.nameTextStyle.color = color
postsOptionNew.xAxis.axisLabel.color = color
postsOptionNew.yAxis.axisLabel.color = color
postsOptionNew.xAxis.axisLine.lineStyle.color = color
postsOptionNew.yAxis.axisLine.lineStyle.color = color
postsOptionNew.series[0].markLine.data[0].label.color = color
postsChart.setOption(postsOptionNew)
} catch (error) {
console.log(error)
}
}
if (document.getElementById('tags-chart') && tagsOption) {
try {
let tagsOptionNew = tagsOption
tagsOptionNew.title.textStyle.color = color
tagsOptionNew.xAxis.nameTextStyle.color = color
tagsOptionNew.yAxis.nameTextStyle.color = color
tagsOptionNew.xAxis.axisLabel.color = color
tagsOptionNew.yAxis.axisLabel.color = color
tagsOptionNew.xAxis.axisLine.lineStyle.color = color
tagsOptionNew.yAxis.axisLine.lineStyle.color = color
tagsOptionNew.series[0].markLine.data[0].label.color = color
tagsChart.setOption(tagsOptionNew)
} catch (error) {
console.log(error)
}
}
if (document.getElementById('categories-chart') && categoriesOption) {
try {
let categoriesOptionNew = categoriesOption
categoriesOptionNew.title.textStyle.color = color
categoriesOptionNew.legend.textStyle.color = color
if (!categoryParentFlag) { categoriesOptionNew.series[0].label.color = color }
categoriesChart.setOption(categoriesOptionNew)
} catch (error) {
console.log(error)
}
}
}
document.getElementById("darkmode").addEventListener("click", function () { setTimeout(switchPostChart, 100) })

添加右键菜单

感谢:

自定义右键菜单 | DoraKika

Butterfly魔改:自定义右键菜单 | 张洪Heo (zhheo.com)

右键菜单 2024.1.8 更新

由于 9e0dce6 中对 saveToLocal 工具函数的改动,使用 5.0 以上版本的 Butterfly 时,无法直接调用 saveToLocal 函数,rightmenu.jsindex。js 中的相应函数需改为 btf.saveToLocal

同理 activateDarkMode() 需要改成 btf.activateDarkMode

此外,可能是由于 Butterfly 更改了设置按钮加载的逻辑, chart.js 无法给官方的黑暗模式切换按键添加 listener 了。

右键菜单 2023.1.12 更新

把右下角按钮移植入右键菜单,基本上是把 JS 函数拷贝到了 .pug 文件中

rightmenu.pug 修改如下:

#rightMenu
.rightMenu-group.rightMenu-small
a.rightMenu-item(href="javascript:window.history.back();")
i.fa-solid.fa-arrow-left
a.rightMenu-item(href="javascript:window.history.forward();")
i.fa-solid.fa-arrow-right
a.rightMenu-item(href="javascript:window.location.reload();")
i.fa-solid.fa-arrow-rotate-right
a.rightMenu-item(href="javascript:rmf.scrollToTop();")
i.fa-solid.fa-arrow-up
a.rightMenu-item(href="#post-comment")#menu-comment
i.fa-solid.fa-comments
.rightMenu-group.rightMenu-line.hide#menu-text
a.rightMenu-item(href="javascript:rmf.copySelect();")
i.fa-solid.fa-copy
span='复制'
.rightMenu-group.rightMenu-line
a.rightMenu-item(href="javascript:rmf.switchDarkMode();")
i.fa-solid.fa-moon
span='昼夜切换'
a.rightMenu-item(href="javascript:rmf.switchReadMode();")
i.fa-solid.fa-book-open
span='阅读模式'
a.rightMenu-item(href="javascript:rmf.switchAsideMode();")#menu-hide-aside
i.fa-solid.fa-arrows-alt-h
span='单双栏切换'
.rightMenu-group.rightMenu-line
a.rightMenu-item(href="javascript:rmf.switchSakanaStatus();")#menu-sakana
i.fa-solid.fa-toggle-on
span='石蒜模拟器'

对阅读模式做了修改,阅读模式中将不开启右键菜单(否则再开启阅读模式,将会导致出现多个退出按钮)。

rightmenu.js 脚本修改如下:

--- "rightmenu copy.js"	2025-01-08 20:28:01.451974218 +0800
+++ rightmenu.js 2023-01-12 15:30:40.000000000 +0800
@@ -9,6 +9,7 @@
$rightMenu.hide();
}
}
+//黑夜模式
rmf.switchDarkMode = function(){
const nowMode = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light'
if (nowMode === 'light') {
@@ -27,6 +28,7 @@
typeof FB === 'object' && window.loadFBComment()
window.DISQUS && document.getElementById('disqus_thread').children.length && setTimeout(() => window.disqusReset(), 200)
};
+//阅读模式
rmf.switchReadMode = function(){
const $body = document.body
$body.classList.add('read-mode')
@@ -42,8 +44,41 @@
}

newEle.addEventListener('click', clickFn)
+ rmf.closeSakanaStatus()
+}
+//单双栏切换
+rmf.switchAsideMode = function(){
+ const $htmlDom = document.documentElement.classList
+ $htmlDom.contains('hide-aside')
+ ? saveToLocal.set('aside-status', 'show', 2)
+ : saveToLocal.set('aside-status', 'hide', 2)
+ $htmlDom.toggle('hide-aside')
+}
+//Sakana开关
+rmf.switchSakanaStatus = function(){
+ if(!saveToLocal.get('sakana-status'))
+ saveToLocal.set('sakana-status', 'show', 2)
+ let sakanaStatus = saveToLocal.get('sakana-status')
+
+ if(sakanaStatus=='show'){
+ $('#sakana').fadeOut();
+ saveToLocal.set('sakana-status', 'hide', 2)
+ $('#menu-sakana').children("i").addClass('fa-toggle-off')
+ $('#menu-sakana').children("i").removeClass('fa-toggle-on')
+ }
+ else{
+ $('#sakana').fadeIn();
+ saveToLocal.set('sakana-status', 'show', 2)
+ $('#menu-sakana').children("i").addClass('fa-toggle-on')
+ $('#menu-sakana').children("i").removeClass('fa-toggle-ff')
+ }
+}
+rmf.closeSakanaStatus = function(){
+ $('#sakana').fadeOut();
+ saveToLocal.set('sakana-status', 'hide', 2)
+ $('#menu-sakana').children("i").addClass('fa-toggle-off')
+ $('#menu-sakana').children("i").removeClass('fa-toggle-on')
}
-
//复制选中文字
rmf.copySelect = function(){
document.execCommand('Copy',false,null);
@@ -57,29 +92,59 @@

// 右键菜单事件
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))){
+
+ var ctrlDown = false;
+ document.addEventListener('keydown',function(event){if(event.key=="Control")ctrlDown=true;});
+ document.addEventListener('keyup',function(event){if(event.key=="Control")ctrlDown=false;});
+
window.oncontextmenu = function(event){
- $('.rightMenu-group.hide').hide();
- //如果有文字选中,则显示 文字选中相关的菜单项
- if(document.getSelection().toString()){
- $('#menu-text').show();
- }
+ if(!ctrlDown&& !document.body.classList.contains("read-mode"))
+ {
+ $('.rightMenu-group.hide').hide();
+ //如果有文字选中,则显示文字选中相关的菜单项
+ if(document.getSelection().toString()){
+ $('#menu-text').show();
+ }
+ //评论存在,则显示直达评论菜单项
+ if(document.getElementById("post-comment")){
+ $('#menu-comment').show();
+ }
+ else{
+ $('#menu-comment').hide();
+ }
+ //更改石蒜模拟器状态
+ let sakanaStatus = saveToLocal.get('sakana-status')
+ if(sakanaStatus=='show'){
+ $('#menu-sakana').children("i").removeClass('fa-toggle-off')
+ $('#menu-sakana').children("i").addClass('fa-toggle-on')
+ }
+ else{
+ $('#menu-sakana').children("i").removeClass('fa-toggle-on')
+ $('#menu-sakana').children("i").addClass('fa-toggle-off')
+ }
+ 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);

- 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;
+ return false;
}
- if(pageY + rmHeight > window.innerHeight){
- pageY -= pageY + rmHeight - window.innerHeight;
+ else
+ {
+ ctrlDown = false;
+ rmf.showRightMenu(false);
+ return true;
}
-
-
-
- rmf.showRightMenu(true, pageY, pageX);
- return false;
};

+
window.addEventListener('click',function(){rmf.showRightMenu(false);});
}

单多栏切换则由于窗口大小改变布局会发生改变,因而通过媒体查询的方式做到菜单项与布局匹配( copy 的右边栏的样式,改了下就可以匹配了)。

rightmenu.css 添加如下内容:

@media screen and (max-width: 900px) {
#rightMenu #menu-hide-aside{
display: none;
}
}

为适配石蒜模拟器(因为有时候想关掉它,不希望切换页面或者刷新的时候又跑出来),就在右键菜单写了开关

修改了 hexo-sakana 插件。主要是插件过滤器的 JS 部分加了是否开启的判断,以及淡入淡出的动画。可以说这个右键菜单是我改得最深入的一次了,对于我这个没啥基础的人来说,真的见识大涨哈哈哈。

hexo-sakanaindex.js 中修改

@@ -84,6 +84,20 @@
console.log("[hexo-sakana] " + msg);
}

+ function myFadeIn(elemt, speed) { //淡入 0 ~ 1
+ if(elemt.style.opacity == 0 && elemt.style.opacity != "") {
+ var speed = speed || 16.6; //默认速度为16.6ms
+ var num = 0; //累加器
+ var timer = setInterval(function() {
+ num++;
+ elemt.style.opacity = num / 20;
+ if(num >= 20) {
+ clearInterval(timer);
+ }
+ }, speed);
+ }
+ }
+
function initSakanaWidget(config) {
if (
!config.enable_mobile &&
@@ -123,6 +137,14 @@
threshold: config.threshold,
rotate: config.rotate,
}).mount("#sakana");
+ let sakanaStatus = saveToLocal.get('sakana-status')
+ if(sakanaStatus =='hide'){
+ document.getElementById('sakana').style.display="none";
+ }
+ else{
+ document.getElementById('sakana').style.opacity=0;
+ myFadeIn(document.getElementById('sakana'),60)
+ }
}
`;
const contentToInject = `
右键菜单(旧)

添加...butterfly/layout/includes/myCustom/rightmenu.pug

代码如下

#rightMenu
.rightMenu-group.rightMenu-small
a.rightMenu-item(href="javascript:window.history.back();")
i.fa-solid.fa-arrow-left
a.rightMenu-item(href="javascript:window.history.forward();")
i.fa-solid.fa-arrow-right
a.rightMenu-item(href="javascript:window.location.reload();")
i.fa-solid.fa-arrow-rotate-right
a.rightMenu-item(href="javascript:rmf.scrollToTop();")
i.fa-solid.fa-arrow-up
.rightMenu-group.rightMenu-line.hide#menu-text
a.rightMenu-item(href="javascript:rmf.copySelect();")
i.fa-solid.fa-copy
span='复制'
.rightMenu-group.rightMenu-line
a.rightMenu-item(href="javascript:rmf.switchDarkMode();")
i.fa-solid.fa-moon
span='昼夜切换'
a.rightMenu-item(href="javascript:rmf.switchReadMode();")
i.fa-solid.fa-book-open
span='阅读模式'

然后在 ...butterfly/layout/includes/layout.pug 中引入

doctype html
html(lang=config.language data-theme=theme.display_mode class=htmlClassHideAside)
head
include ./head.pug
body
...

else
include ./404.pug

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

然后将 rightmenu.css 样式表 inject 到头部,rightmenu.js 脚本 inject 到底部,内容如下:

/* rightMenu */
#rightMenu{
display: none;
position: fixed;
width: 160px;
height: fit-content;
top: 10%;
left: 10%;
background-color: var(--card-bg);
border: 1px solid var(--font-color);
border-radius: 8px;
z-index: 100;
}
#rightMenu .rightMenu-group{
padding: 7px 6px;
}
#rightMenu .rightMenu-group:not(:nth-last-child(1)){
border-bottom: 1px solid var(--font-color);
}
#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);
}
#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 .rightMenu-group.rightMenu-line .rightMenu-item *{
height: 40px;
line-height: 40px;
}
.rightMenu-group.hide{
display: none;
}
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.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);
}

// 右键菜单事件
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))){
window.oncontextmenu = function(event){
$('.rightMenu-group.hide').hide();
//如果有文字选中,则显示 文字选中相关的菜单项
if(document.getSelection().toString()){
$('#menu-text').show();
}

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);});
}

由于右键菜单的切换夜间模式无法与统计图交互,因而需要对前述的 JS 文件进行如下修改:

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)
+ setTimeout(switchPostChart, 100)
} else {
activateLightMode()
saveToLocal.set('theme', 'light', 2)
GLOBAL_CONFIG.Snackbar !== undefined && btf.snackbarShow(GLOBAL_CONFIG.Snackbar.night_to_day)
+ setTimeout(switchPostChart, 100)
}
// handle some cases
typeof utterancesTheme === 'function' && utterancesTheme()
typeof FB === 'object' && window.loadFBComment()
window.DISQUS && document.getElementById('disqus_thread').children.length && setTimeout(() => window.disqusReset(), 200)
};

主题优化

样式表修改

字体修改

引入字体后,结合样式表选择器可以设置某一部分的字体。

详见:基于Hexo的博客网站 | MateMaster


/* --- 字体修改 --- */
@font-face{
font-family: 'ZCOOL KuaiLe';
src: url('https://cdn.zerolacqua.top/fonts/zcool-happy.ttf');
}

body {
font-family: ZCOOL KuaiLe;
}

#article-container {
font-family: Noto Serif Simplified Chinese
}


透明度修改及黑夜模式适配

依旧是样式表选择器。之前我把主页的头图和背景图设成了同一幅图,但是刷新之后会有一段时间的错位,看起来很不舒服。用大佬的方法完美地解决了问题。并且,利用样式表选择器可以设置黑夜模式下的透明度和色调。

详见:Custom Beautify | Akilarの糖果屋


/* --- 透明度修改 --- */
/* 头图透明 */
#page-header {
background: transparent !important;
}

/* 页脚透明 */
[data-theme="light"] #footer {
background: rgba(20, 20, 20, 0.35) !important;
}
[data-theme="dark"] #footer {
background: transparent!important;
}

/* 页脚黑色透明玻璃效果移除 */
#footer::before {
background: transparent !important;
}


/* -- 白天模式 -- */
/* 首页文章卡片 */
[data-theme="light"] #recent-posts>.recent-post-item {
background: rgba(255, 255, 255, 0.85);
}

/* 首页侧栏卡片 */
[data-theme="light"] .card-widget {
background: rgba(255, 255, 255, 0.85) !important;
}

/* 文章页面正文背景 */
[data-theme="light"] div#post {
background: rgba(255, 255, 255, 0.85);
}

/* 分页页面 */
[data-theme="light"] div#page {
background: rgba(255, 255, 255, 0.85);
}

/* 归档页面 */
[data-theme="light"] div#archive {
background: rgba(255, 255, 255, 0.85);
}

/* 标签页面 */
[data-theme="light"] div#tag {
background: rgba(255, 255, 255, 0.85);
}

/* 分类页面 */
[data-theme="light"] div#category {
background: rgba(255, 255, 255, 0.85);
}

/* -- 夜间模式 -- */
/* 首页文章卡片 */
[data-theme="dark"] #recent-posts>.recent-post-item {
background: rgba(30, 30, 30, 0.5);
}

/* 首页侧栏卡片 */
[data-theme="dark"] .card-widget {
background: rgba(30, 30, 30, 0.5) !important;
}

/* 文章页面正文背景 */
[data-theme="dark"] div#post {
background: rgba(30, 30, 30, 0.5);
}

/* 分页页面 */
[data-theme="dark"] div#page {
background: rgba(30, 30, 30, 0.5);
}

/* 归档页面 */
[data-theme="dark"] div#archive {
background: rgba(30, 30, 30, 0.5);
}

/* 标签页面 */
[data-theme="dark"] div#tag {
background: rgba(30, 30, 30, 0.5);
}

/* 标签页面夜晚模式下反差不够,故加上白色描边 */
[data-theme="dark"] .tag-cloud-list.is-center a {
text-shadow: 0 0 2px rgb(193, 193, 193), 0 0 2px rgb(193, 193, 193);
}

/* 标签卡片也是一样的操作 */
[data-theme="dark"] .card-tag-cloud a {
text-shadow: 0 0 2px rgb(193, 193, 193), 0 0 2px rgb(193, 193, 193);
}

/* 分类页面 */
[data-theme="dark"] div#category {
background: rgba(30, 30, 30, 0.5);
}

/* 资源页面(网站卡片) */
[data-theme="dark"] .site-card-group .info {
text-shadow: 0 0 2px rgb(193, 193, 193), 0 0 2px rgb(193, 193, 193);
}


/*夜间模式伪类遮罩层透明*/
[data-theme="dark"] #footer::before {
background: transparent !important;
}

[data-theme="dark"] #page-header::before {
background: transparent !important;
}
/* --- 隐藏右下角按钮 --- */
/* 我也不知道为啥没找到 Butterfly 隐藏右下角按钮的配置,所以只好自己隐藏了 */
#rightside{
display: none;
}


/* --- 设置 sakana 组件 --- */
#sakana{
z-index: 20;
}
.sakana-widget-ctrl{
display: none;
}

鼠标指针修改

通过样式表选择器进行修改。

详见:Custom Beautify | Akilarの糖果屋

/* --- 鼠标指针修改 --- */
/* 全局默认鼠标指针 */
body,
html {
cursor: url(https://cdn.zerolacqua.top/cursor/arrow.cur), auto !important;
}
/* sandbox:默认鼠标指针 */
div#sandbox {
cursor: auto;
}

/* 石蒜模拟器:鼠标指针 */
div.sakana-widget-img{
cursor: url(https://cdn.zerolacqua.top/cursor/move.cur), auto;
}

/* 选中文字 */
::selection{
cursor: url(https://cdn.zerolacqua.top/cursor/textselete.cur), auto;
}

/* 选择链接标签时的鼠标指针 */
a:hover {
cursor: url(https://cdn.zerolacqua.top/cursor/link.cur), auto;
}

/* 网页卡片:选择链接标签时的鼠标指针 */
a.link-card:hover {
cursor: url(https://cdn.zerolacqua.top/cursor/link.cur), auto;
}

/* 选中输入框时的鼠标指针 */
input:hover{
cursor: url(https://cdn.zerolacqua.top/cursor/input.cur), auto !important;
}

/* 悬停按钮时的鼠标指针 */
button:hover {
cursor: url(https://cdn.zerolacqua.top/cursor/btn.cur), auto !important;
}
/* 悬停图片时的鼠标指针 */
img:hover {
cursor: url(https://cdn.zerolacqua.top/cursor/btn.cur), auto !important;
}
/* Waline:悬停 Waline 打开图片时的鼠标指针 */
label.wl-action:hover {
cursor: url(https://cdn.zerolacqua.top/cursor/btn.cur), auto !important;
}
/* Waline:切换评论排序方式 */
ul.wl-sort li{
cursor: url(https://cdn.zerolacqua.top/cursor/btn.cur), auto;
}
/* Waline: 投票计数 */
.wl-reaction-votes{
cursor: url(https://cdn.zerolacqua.top/cursor/btn.cur), auto;
}
/* Waline:悬停 Waline 文本框时的鼠标指针 */
textarea:hover{
cursor: url(https://cdn.zerolacqua.top/cursor/input.cur), auto;
}
/* Waline:悬停 markdown 打开图片时的鼠标指针 */
a.wl-action:hover {
cursor: url(https://cdn.zerolacqua.top/cursor/link.cur), auto !important;
}
/* Waline:普通标签 */
div.wl-header-item label{
cursor: url(https://cdn.zerolacqua.top/cursor/input.cur), auto;
}

/* 网页卡片 */
a.link-card:hover {
cursor: url(https://cdn.zerolacqua.top/cursor/btn.cur), auto !important;
}

/* 悬停折叠框时的鼠标指针 */
summary:hover {
cursor: url(https://cdn.zerolacqua.top/cursor/btn.cur), auto !important;
}

/* 悬停列表标签时的鼠标指针 */
i:hover {
cursor: url(https://cdn.zerolacqua.top/cursor/link.cur), auto;
}

/* 悬停页脚链接标签(例如页脚徽标)时的鼠标指针 */
#footer-wrap a:hover {
cursor: url(https://cdn.zerolacqua.top/cursor/hf.cur), auto;
}
/* 悬停菜单栏时的鼠标指针 */
#nav .site-page:hover {
cursor: url(https://cdn.zerolacqua.top/cursor/hf.cur), auto;
}

github 日历

Github UI 更新频繁,本插件维护又基本处于停滞状态,因此本站不再使用。

详见:教程:hexo-githubcalendar 插件 1.0 | 小冰博客 (zfe.space)

解决 2023.12.18 的 This Serverless Function has crashed 问题

2023.7.20 api 出现问题

This Serverless Function has crashed.
Your connection is working correctly.
Vercel is working correctly.
500: INTERNAL_SERVER_ERROR

rr210 已继续跟进: github正则匹配规则更改问题,可以参考进行修改,测试有效。

解决 2023.7.20 的 This Serverless Function has crashed 问题

2023.7.20 api 出现问题

This Serverless Function has crashed.
Your connection is working correctly.
Vercel is working correctly.
500: INTERNAL_SERVER_ERROR

zkeq 已继续跟进: Github 页面改版,更新 regex 规则,可以参考进行修改,测试有效。

解决 2023.1.7 的 This Serverless Function has crashed 问题

2023.1.7 api 出现问题,改用自建的 API 也同样报错:

This Serverless Function has crashed.
Your connection is working correctly.
Vercel is working correctly.
500: INTERNAL_SERVER_ERROR

目前其他博主也遇到了这个情况 500: INTERNAL_SERVER_ERROR,可以看到 zkeq 已经针对该问题提了 PR: Github 页面改版,更新 regex 规则,可以参考进行修改,测试有效。

解决 2022.9.4 Vercel 的公共域名被墙的问题

2022.9.4 Vercel 的公共域名被墙了,解决方案有以下两种:

具体参见 Zfour/python_github_calendar_api,关于自建 API 的步骤中,他的配图用错了,创建项目的时候,别再用 friends_link_list_api 啦!

github 卡片 ghcard

本插件是 hexo-butterfly-tag-plugins-plus 中的内容。 可以参见:Tag Plugins Plus | Akilarの糖果屋

如果自己部署了 ghcard API 但是卡片显示 Maximum retries exceeded. Please add an env variable called PAT_1 with your github token in vercel ,那可能是你的 token 没设好,或者过期了,重新生成一个就好。

解决 2022.9.4 Vercel 的公共域名被墙的问题

但因为 2022.9.4 Vercel 的公共域名被墙了,所以需要使用 Vercel 的自定义域名绑定。自己部署在 Vercel 上的方法如下 anuraghazra/github-readme-stats ,然后再绑定自定义域名

注意,在部署时,可能会报错:The value for maxDuration must be between 1 second and 10 seconds, in order to increase this limit upgrade your plan 。解决方法见 fix: decrease vercel ‘maxDuration’ to fix free plan deployment

绑定完成后,需要修改 hexo-butterfly-tag-plugins-plus 中相关文件:

// [path]\hexo-butterfly-tag-plugins-plus\lib\scripts 其他的 api 类似,使用全部替换即可
- url += 'https://github-readme-stats.vercel.app/api/?username=' + path
+ url += 'https://yourdomain/api/?username=' + path;

也可以使用我部署已经好的(不会真的有人会用我的吧??)

https://github-readme-stats.zerolacqua.top/api

Magnet

本站未实装。

详见:教程:hexo-magnet 插件 1.0 | 小冰博客 (zfe.space)

底部栏添加跳动的鱼背景

本站未实装。

详见:jQuery 插件 养鱼 | Ln’s Blog (weilining.github.io)

Akilar 的标签插件 Tag Plugins Plus

本博客的样式使用情况请见:博客样式测试。详细测试例请见:Tag Plugins Plus | Akilarの糖果屋

Waline 评论

这个评论系统有后端的诶真的好棒,看的第一眼就爱上了。不过同样由于 2022.9.4 Vercel 的公共域名被墙了 需要绑定自定义域名。要测试评论可以到这里试试

Butterfly4.6.0」 注意,若在 _config.butterfly.yml 中开启 newest_comments 时,需要注意 serverURL 的最后不要加上 /,否则在调用 API 获取最新评论时,会出现 CORS 问题(在新版本 5.2.2 中似乎已经修复)。

当评论变多后,Vercel 部署的后端似乎响应变慢了,可以在 Vercel 的 Project Settings -> Function Max Duration 中调整最大持续时间,免费版可以调整到 60s(当然 20s 目前来说就够了)。

友链朋友圈

配置效果见朋友圈,需要注意的是,由于 Vercel 受到影响,所以需要使用 Vercel 时,依然要绑定自定义域名。当然也可以使用其他部署方式。文档参见:https://fcircle-doc.yyyzyyyz.cn/

相关功能

关于标签插件

想要将 , 作为参数输入,需要进行转义,使用 &sbquo; 代替 ,

隐藏博客

使用插件 hexo-hide-posts

使用方法

安装插件

npm install hexo-hide-posts --save

在博客的Front-matter中加入如下参数

hidden: false 

可实现对文章的隐藏(虽然还是可以用网址访问就是了)

参考网站:「推荐」本站用到的 hexo 插件 | 若风 (loafing.cn)

文字遮盖效果

使用插件 hexo-hide-posts

使用方法

安装插件

npm install hexo-spoiler --save

站点根目录配置

spoiler:
style: blur # 或者box
color: black # 仅当 style 为 box 时起效
p: false # 没懂啥意思,不管它

使用:

{% spoiler 默认配置效果 %}

效果:

默认配置效果

参考网站:「推荐」本站用到的 hexo 插件 | 若风 (loafing.cn)

跳转站内文章

通过标签插件 {% post_link %}

使用方法
  • 可以使用以下方式

    {% post_link 欢迎光临小店 %}

    其效果是这样的

    欢迎光临小店

  • 可以通过第二个参数修改文字内容

    {% post_link 欢迎光临小店 偷看可是不礼貌的哦 %}

    其效果是这样的

    偷看可是不礼貌的哦

跳转文章锚点

通过<a></a>

使用方法
  • 方法一

    <a href="{% post_path '近景摄影测量编程与实习' %}#影像获取">这是一个跳转</a>

    此方法效果如下

    这是一个跳转

  • 方法二

    [这是一个跳转]({% post_path '近景摄影测量编程与实习' %}#课间实习 )

    此方法目前还无法实现,还没找到问题所在。

    注意:

    1. 如果文章中有图片,可能会出现锚点位置不准确问题,原因是图片加载成功之后会把内容高度撑开。
    2. 如果如果有空格,需要把空格换成连字符 -

    可以参考以下文章

    hexo 链接到站内文章指定锚点 | 极简前端 (jijian.link)

插入视频

使用 html 插入视频

使用方法

嵌入视频

{% raw %}
<div style="position: relative; width: 100%; height: 0; padding-bottom: 75%;"><iframe src="//player.bilibili.com/player.html?aid=460816113&bvid=BV1j5411g7m5&cid=345672460&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true" style="position: absolute; width: 100%; height: 100%; Left: 0; top: 0;" ></iframe></div>
{% endraw %}
<div style="position: relative; padding: 30% 45%;">
<iframe style="position: absolute; width: 100%; height: 100%; left: 0; top: 0;" src="https://player.bilibili.com/player.html?aid=460816113&bvid=BV1j5411g7m5&cid=345672460&page=1" frameborder="no" scrolling="no"></iframe>
</div>

可以参考:

图库

通过标签插件 {% gallery %}

使用方法
{% gallery %}
![](https://cdn.zerolacqua.top/images/blogs/可爱的水伊布/Vaporeon1.png)
{% endgallery %}

效果见可爱的水伊布

ECharts

使用插件 hexo-tag-echarts。由于访问和加载问题本站未实装,如需使用请在使用方法的 diff 中将 cdn 改为有效的地址。

使用方法

安装插件

npm install hexo-tag-echarts --save

更新 node_modules\hexo-tag-echarts3\template.html中第二行的

- <script src="https://cdn.bootcss.com/echarts/3.8.0/echarts.common.min.js"></script>
+ <script src="https://cdn.jsdelivr.net/npm/echarts@5.3.0/dist/echarts.min.js"></script>
// 或者改为 <script src="https://npm.elemecdn.com/echarts@4.9.0/dist/echarts.min.js"></script>
{% echarts 400 '85%' %}
{
tooltip : {
trigger: 'axis',
axisPointer : { // 坐标轴指示器,坐标轴触发有效
type : 'shadow' // 默认为直线,可选为:'line' | 'shadow'
}
},
legend: {
data:['利润', '支出', '收入']
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis : [
{
type : 'value'
}
],
yAxis : [
{
type : 'category',
axisTick : {show: false},
data : ['周一','周二','周三','周四','周五','周六','周日']
}
],
series : [
{
name:'利润',
type:'bar',
itemStyle : {
normal: {
label: {show: true, position: 'inside'}
}
},
data:[200, 170, 240, 244, 200, 220, 210]
},
{
name:'收入',
type:'bar',
stack: '总量',
itemStyle: {
normal: {
label : {show: true}
}
},
data:[320, 302, 341, 374, 390, 450, 420]
},
{
name:'支出',
type:'bar',
stack: '总量',
itemStyle: {normal: {
label : {show: true, position: 'left'}
}},
data:[-120, -132, -101, -134, -190, -230, -210]
}
]
};
{% endecharts %}

参考:

mini-sandbox 前端代码可视化

mini-sandbox 官方文档

内容很大部分参考了使用MiniSandbox前端代码可视化 | 轻笑Chuckle,本站未实装。

使用方法

通过 CDN 单页引入 MiniSandbox

<script src="https://unpkg.com/mini-sandbox@0.3.11"></script>

创建一个 sandbox.js 文件用于文章中的引入

new MiniSandbox({
el: '#sandbox',//要和 markdown 文件中 div 元素的 id 一致
files: {//各 tab 页面
//index.html=>html
//index.css=>css
//index.js=>js
'index.html': {
title: 'HTML',//tab 上显示的名字
defaultValue: `<h1>JavaScript</h1>
<p id="demo">
JavaScript 能改变 HTML 元素的样式。
</p>
<button>点击这里</button>
`,//HTML的内容/代码
cssLibs: ['index.css'],//html引入的css
jsLibs: ['index.js'],//html引入的js
},
'index.css': {
title: 'CSS',
defaultValue: `h1{
background: red;
}
`
},
'index.js': {
title: 'JS',
//JS的内容/代码
defaultValue: `const btn = document.querySelector('button')
btn.addEventListener('click', () => {
document.getElementById("demo").style.color
="#ff0000";
})
`
}
},
//用来设置一些 Sandbox 的默认配置
defaultConfig: {
height: '300px',//Sandbox 的高度, 默认为 '300px'
autoRun: true,//每次修改后是否自动运行, 默认等于 true
autoRunInterval: 1000,//每次自动运行的时间间隔, 单位为毫秒, 默认等于 300
editorRange: '50%',//编辑区域默认占比, 默认情况下编辑区域占 50%
draggable: true,//是否可以左右拖动布局, 默认为 true
direction: 'row',//控制上下/左右布局, 默认为 'row'。'row' | 'row-reverse' | 'column' | 'column-reverse'
}
})

在需要使用的地方插入 div 元素

<div id="sandbox"></div>

并在文章末尾引入

<script src="[your_directory]/sandbox.js"></script>

针对 MiniSandbox 的夜间模式,可以参考轻笑Chuckle的 CSS 配置

.mini-sandbox{
box-shadow: none!important;
border-radius: 7px;
}
[data-theme=dark]
.mini-sandbox{
background-color: #151515!important;
}
[data-theme=dark]
.cm-activeLine{
background-color: #252525!important;
}
[data-theme=dark]
.mini-sandbox .sandbox-head{
background: #202020!important;
}
[data-theme=dark]
.mini-sandbox .cm-gutters{
background: #202020!important;
}
.mini-sandbox .sandbox-head .sandbox-tab .sandbox-tab-active{
box-shadow: none!important;
}
[data-theme=dark]
.mini-sandbox .sandbox-head .sandbox-tab .sandbox-tab-active{
background: #363636!important;
}
[data-theme=dark]
.cm-activeLineGutter{
background: #363636!important;
}
[data-theme=dark]
.sandbox-body .sandbox-gutter{
background: #363636!important;
}
[data-theme=dark]
.mini-sandbox .sandbox-gutter{
border-left: 1px solid #404040!important;
border-right: 1px solid #404040!important;
}
[data-theme=dark]
.mini-sandbox .sandbox-head .sandbox-tab .sandbox-tab-active::after{
background: none!important;
}
[data-theme=dark]
.mini-sandbox .sandbox-head .sandbox-tab .sandbox-tab-active::before{
background: none!important;
}
[data-theme=dark]
.mini-sandbox .sandbox-render{
background: #E1E1E1!important;
}
[data-theme=dark]
.mini-sandbox .ͼd{
color: #c3e88d!important;
}
[data-theme=dark]
.mini-sandbox .ͼc{
color: #c3e88d!important;
}
[data-theme=dark]
.mini-sandboxb{
color: #1E90FF!important;
}
[data-theme=dark]
.mini-sandbox .ͼf{
color: #1E90FF!important;
}
[data-theme=dark]
.mini-sandbox .ͼh{
color: #ff5370!important;
}
[data-theme=dark]
.mini-sandboxa{
color: #FF00FF!important;
}
[data-theme=dark]
.mini-sandboxi{
color:#5F9EA0!important;
}
[data-theme=dark]
.mini-sandbox .ͼl{
color:#969896!important;
}
.mini-sandbox{
margin-bottom: 10px;
}

Markdown 与数学公式

多层嵌套的代码块

注意 ` 的个数

  • 行内代码块

    `

    `` ` ``
  • 代码块

    ```c++
    #include <iostream>
    using namespace std;

    int main()
    {
    cout << "Hello, World!";
    return 0;
    }
    ```
    ````markdown
    ```c++
    #include <iostream>
    using namespace std;

    int main()
    {
    cout << "Hello, World!";
    return 0;
    }
    ```
    ````

数学公式渲染错误

由于 Mathjax 数学公式渲染效果很迷,经常无法复现问题,有时重新部署一下全部都变了,所以 Mathjax 的内容参考价值不大!

果然还是 Katex 用起来更舒服啊,换了 Katex 之后这些问题就不存在了。解决不了问题,就把产生问题的解决掉。

一些解决方法

当然,换了 Katex 还是会有它的问题,就比如加粗

一二**加粗**三四
一二**.加粗**三四
一二**加.粗**三四
一二**加粗.**三四

看看效果吧

一二加粗三四
一二**.加粗三四
一二
加.粗三四
一二
加粗.**三四

  • 所以最好还是不要在内部有字符的时候用加粗斜体
  • 更合适的方法是使用<b></b><i></i>

可以参见这几篇文章进行修改:

但是修改后公式中还是会出现\\被转义成\的问题:

CCW(c,a,b)=
\begin{vmatrix}
a_x&a_y&1\\
b_x&b_y&1\\
c_x&c_y&1\\
\end{vmatrix}=
\begin{vmatrix}
a_x-c_x&a_y-c_y\\
b_x-c_x&b_y-c_y\\
\end{vmatrix}

其效果为:CCW(c,a,b)=axay1bxby1cxcy1=axcxaycybxcxbycyCCW(c,a,b)=\begin{vmatrix}a_x&a_y&1\\b_x&b_y&1\\c_x&c_y&1\\\end{vmatrix}=\begin{vmatrix}a_x-c_x&a_y-c_y\\b_x-c_x&b_y-c_y\\\end{vmatrix}

妥协办法也有,但是太蠢,将就用吧

CCW(c,a,b)=
\begin{vmatrix}
a_x&a_y&1\\\\
b_x&b_y&1\\\\
c_x&c_y&1\\\\
\end{vmatrix}=
\begin{vmatrix}
a_x-c_x&a_y-c_y\\\\
b_x-c_x&b_y-c_y\\\\
\end{vmatrix}

其效果为:CCW(c,a,b)=axay1bxby1cxcy1=axcxaycybxcxbycyCCW(c,a,b)=\begin{vmatrix}a_x&a_y&1\\\\b_x&b_y&1\\\\c_x&c_y&1\\\\\end{vmatrix}=\begin{vmatrix}a_x-c_x&a_y-c_y\\\\b_x-c_x&b_y-c_y\\\\\end{vmatrix}

此外,公式块中 {y}_{t}_会被渲染成斜体

$$

\hat {y}_{t}=\cfrac{1}{2l+1}(y_{t-l}+y_{t-(l-1)}+\cdots+y_{t-1}+y_{t}+y_{t+1}+\cdots+y_{t+l})

$$

其效果为:

y^t=12l+1(ytl+yt(l1)++yt1+yt+yt+1++yt+l)\begin{equation}\hat {y}_{t}=\cfrac{1}{2l+1}(y_{t-l}+y_{t-(l-1)}+\cdots+y_{t-1}+y_{t}+y_{t+1}+\cdots+y_{t+l})\end{equation}

需要改成{y}_ {t}

$$

\hat {y}_ {t}=\cfrac{1}{2l+1}(y_{t-l}+y_{t-(l-1)}+\cdots+y_{t-1}+y_{t}+y_{t+1}+\cdots+y_{t+l})

$$

其效果为

y^t=12l+1(ytl+yt(l1)++yt1+yt+yt+1++yt+l)\hat {y}_ {t}=\cfrac{1}{2l+1}(y_{t-l}+y_{t-(l-1)}+\cdots+y_{t-1}+y_{t}+y_{t+1}+\cdots+y_{t+l})

目前测试发现和{y}_{}有相关,若是\hat y_{t}则不会出现问题。且只会在本地测试时出问题

公式块自动编号

利用 \begin{equation} 进行公式编号

使用方法

可以用以下方式对公式进行自动编号

$$
\begin{equation}
1+1=2
\end{equation}
$$

这是没用的:

1+1=21+1=2

这是用了的:

1+1=2\begin{equation}1+1=2\end{equation}

网站管理

网站验证与提交

使用 hexo-generator-sitemap 插件

使用方法
npm install hexo-generator-sitemap --save

并在 _config.yml 文件中添加:

# hexo-generator-sitemap
sitemap:
path:
- sitemap.xml
- sitemap.txt
template:
template_txt:
rel: false
tags: true
categories: true

各参数可参考该插件的说明。

在各搜索引擎上验证网站,按照各搜索引擎的流程进行验证即可。之后便可以提交网站地图了,需要注意的是,在 Google Search Console 上提交网站地图是,可能会出现无法获取的情况,排除网站地图的问题后,说明可能遇到了 Bug ,状态显示是有误的。参见:Sitemap could not be read in new GSC - Google Search Central Community

网站 RSS 生成

使用 hexo-generator-feed插件

使用方法
npm install hexo-generator-feed --save

并在 _config.yml 文件中添加:

# hexo-generator-feed
feed:
enable: true
type: atom
path: atom.xml
limit: 20
hub:
content:
content_limit: 140
content_limit_delim: ' '
order_by: -date
icon: icon.png
autodiscovery: true
template:

各参数可参考该插件的说明。

之后就可以愉快地订阅啦~

其他参考网站

参考网站