Hexo搭建笔记

Hexo搭建笔记

Todo List

  1. 实现在配置文件中修改配色文件
  2. 主页博客文章预览美化,打算显示每篇文章的目录
  3. 有时‘更多’变成‘Read more’ 语言文件不一致
  4. 手机版 markdown流程图大小适配,style=“overflow: auto;”?
  5. 用** live2d-widget替代hexo-helper-live2d**
  6. 每篇文章的“上一篇”,“下一篇”和主页的顺序匹配,而不是按默认的创建日期
  7. 文章页面同时显示创建日期和更新日期
  8. canvas-nest.js
  9. 主题 hexo-theme-icarus
  10. markdown表格内的图片不解析 举例 怀疑是hexo-image-asset hexo-image-link没解析的问题
  11. hexo-indexnow
  12. instant.page
  13. 借鉴 removeif.github.io,hexo-theme-amazing:代码块折叠>folded,暗黑模式,页面时间轴记录

文档

Hexo 一篇文章多个 categories

Hexo 一篇文章多个 categories
下面的分类会将该分章放到 Java/Servlet这个分类下。

1
2
3
categories:
- Java
- Servlet
1
categories: [Java, Servlet]

如果我们的要求是将文章同时分到多个不同的分类中呢,我们应该这样:

1
2
3
categories:
-[Java]
-[Servlet]

这样,就可以将上面的文章分类到 Java 和 Servlet 这两个不同的目录中了。
扩展一下,如果我们将其分类到 Java/Servlet 和 Programming 两个不同的目录下,我们应该如下写:

1
2
3
categories:
-[Java, Servlet]
-[Programming]

定制Claudia主题

排序-置顶

themes\hexo-theme-Claudia\layout\widget\widget-post-list.pug

1
each post in page.posts.sort('date', -1).toArray()

改为

1
each post in page.posts.sort({date:-1,top:-1}).toArray()

node_modules\warehouse\lib\query.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* Sorts documents.
*
* Example:
*
* ``` js
* query.sort('date', -1);
* query.sort({date: -1, title: 1});
* query.sort('-date title');
* ```
*
* If the `order` equals to `-1`, `desc` or `descending`, the data will be
* returned in reversed order.
*
* @param {String|Object} orderby
* @param {String|Number} [order]
* @return {Query}
*/
sort(orderby, order) {
const sort = parseArgs(orderby, order);
const fn = this._schema._execSort(sort);

return new this.constructor(this.data.slice().sort(fn));
}

改为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
sort(orderby, order) {
const sort = parseArgs(orderby, order);
const fn = this._schema._execSort(sort);
var tmp = new this.constructor(this.data.slice().sort(fn));
if (sort.top == -1 && sort.date == -1) {
tmp = new this.constructor(this.data.slice().sort((a, b) => {
if (a.top && b.top) { // 两篇文章top都有定义
if (a.top == b.top) return b.date - a.date; // 若top值一样则按照文章日期降序排
else return b.top - a.top; // 否则按照top值降序排
} else if (a.top && !b.top) { // 以下是只有一篇文章top有定义,那么将有top的排在前面(这里用异或操作居然不行233
return -1;
} else if (!a.top && b.top) {
return 1;
} else return b.date - a.date; // 都没定义按照文章日期降序排
}));
}
return tmp;
}

接下来只要在文章加入 top值就行,若写 top: 则按date排序

1
2
3
4
5
6
7
8
---
title: Hexo学习笔记
password: ''
date: 2021-02-04 10:25:10
tags: Hexo
categories: 学习笔记
top: 100
---

知识点:
TypeScript
-compareFn
-sort
-console.log(new Error().stack.split("\n"));打印堆栈

分页导致top值失效

注意!!! 这里方案描述有问题,最新方法移步本文章 “文章按更新内容排序”一节!

当文件数超过10条导致出现分页时,我发现之前设置的top不起作用,经过1小时的艰苦奋斗,发现

1
2
3
4
5
6
7
8
9
# Home page setting
# path: Root path for your blogs index page. (default = '')
# per_page: Posts displayed per page. (0 = disable pagination)
# order_by: Posts order. (Order by date descending by default)
index_generator:
path: ''
per_page: 10
order_by: -date

改为

1
2
3
4
5
6
7
8
9
# Home page setting
# path: Root path for your blogs index page. (default = '')
# per_page: Posts displayed per page. (0 = disable pagination)
# order_by: Posts order. (Order by date descending by default)
index_generator:
path: ''
per_page: 10
order_by: -top -date

即可解决问题

Post侧边目录显示序列号

themes\hexo-theme-Claudia\layout\post.pug

1
2
block content
- var tocContent = toc(page.content, {list_number: false})

改为

1
2
block content
- var tocContent = toc(page.content, {list_number: true})

主页侧边栏随页面滚动

修改模版文件

themes\hexo-theme-Claudia\layout\index.pug

1
2
3
4
5
6
7
8
9
10
block sidebar
include widget/widget-profile
if theme.widgets.includes('recent_posts')
include widget/widget-recent
if theme.widgets.includes('category') && site.categories.length > 0
include widget/widget-categories
if theme.widgets.includes('archive')
include widget/widget-archives
if theme.widgets.includes('tag') && site.tags.length > 0
include widget/widget-tag

改为

1
2
3
4
5
6
7
8
9
10
11
block sidebar
div.sidebarFixed
include widget/widget-profile
if theme.widgets.includes('recent_posts')
include widget/widget-recent
if theme.widgets.includes('category') && site.categories.length > 0
include widget/widget-categories
if theme.widgets.includes('archive')
include widget/widget-archives
if theme.widgets.includes('tag') && site.tags.length > 0
include widget/widget-tag

或者

1
2
3
4
5
6
7
8
9
10
11
12
13
block content
include widget/widget-post-list
block sidebar
include widget/widget-profile
if theme.widgets.includes('recent_posts')
include widget/widget-recent
div.sidebarFixed
if theme.widgets.includes('category') && site.categories.length > 0
include widget/widget-categories
if theme.widgets.includes('archive')
include widget/widget-archives
if theme.widgets.includes('tag') && site.tags.length > 0
include widget/widget-tag

后者滚动时会不显示个人介绍栏,而显示category archive tag,更有利于浏览。

修改CSS文件

向阮一峰学习CSS 定位详解
在themes\hexo-theme-Claudia\source\style\widget-post-list.scss添加

1
2
3
4
5
6
.post-container {
.sidebarFixed{
position: sticky;
top: 50px;
}
}

侧边栏进一步定制

建议搭配第二种模版文件修改方法
为了让侧边栏不过于长,影响浏览体验

  • 侧边栏长度大于屏幕的高度时,侧边栏下面未被显示的部分只有拉到页面底部才会被显示
    themes\hexo-theme-Claudia_config.yml
1
2
3
4
5
widgets: //显示顺序为recent_posts category archive tag
- tag
- archive
- category
- recent_posts

改为

1
2
3
4
widgets: //显示顺序为category archive tag
- tag
- archive
- category

修改侧边栏显示顺序

修改上述模版文件的4个if的位置即可

图片点击放大

  1. hexo实现图片单击放大

  2. Hexo 折腾:利用 Fancybox 添加图片放大预览查看功能

  3. 【翻译】fancyBox3 中文文档

  4. 【翻译】fancyBox3 中文文档

    themes\hexo-theme-Claudia\layout\widget\base.pug

    1
    2
    3
    4
    5
    link(rel="icon" href= url_for(theme.favicon))
    link(rel="stylesheet" href= url_for('/style/common/bulma.css'))
    link(rel="stylesheet" href= url_for('/style/base.css'))
    link(rel="stylesheet" href= url_for('/style/common/helper.css'))
    script(src= url_for("/js/common.js"))

    改为

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    link(rel="icon" href= url_for(theme.favicon))
    link(rel="stylesheet" href= url_for('/style/common/bulma.css'))
    link(rel="stylesheet" href= url_for('/style/base.css'))
    link(rel="stylesheet" href= url_for('/style/common/helper.css'))
    script(src= url_for("/js/common.js"))
    if (theme.fancybox)
    link(rel="stylesheet" href= url_for('/js/fancybox/jquery.fancybox.min.css'))
    script(src= url_for("/js/fancybox/jquery-3.5.1.min.js"))
    script(src= url_for("/js/fancybox/jquery.fancybox.min.js"))
    script(src= url_for("/js/wrapImage.js"))

    增加的jQuery和Fancybox需下载放入themes\hexo-theme-Claudia\source\js\fancybox中

    wrapImage.js内容为

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    $(document).ready(function() {
    wrapImageWithFancyBox();
    });

    /**
    * Wrap images with fancybox support.
    */
    function wrapImageWithFancyBox() {
    $('img').not('.js-img-fadeIn').each(function() {
    var $image = $(this);
    var imageCaption = $image.attr('alt');
    var $imageWrapLink = $image.parent('a');
    if ($imageWrapLink.length < 1) {
    //没找到a标签就新增一个a标签包裹
    var src = this.getAttribute('src');
    var idx = src.lastIndexOf('?');
    if (idx != -1) {
    src = src.substring(0, idx);
    }
    $imageWrapLink = $image.wrap('<a href="' + src + '"></a>').parent('a');
    }

    $imageWrapLink.attr('data-fancybox', 'images');
    if (imageCaption) {
    $imageWrapLink.attr('data-caption', imageCaption);
    }

    });

    $().fancybox({ //参数见https://github.com/fancyapps/fancybox/blob/master/docs/index.html
    selector: '[data-fancybox="images"]',
    closeExisting: false,
    buttons: [
    "zoom",
    //"share",
    //"slideShow",
    //"fullScreen",
    //"download",
    "thumbs",
    "close"
    ],
    keyboard: false,
    helpers: {
    overlay: {
    locked: false
    }
    },
    hash: true,
    // 相册循环浏览
    loop: false,
    // 图片周围的margin,如果视口(viewport)宽度小于800px则忽略
    margin: [44, 0],
    //是否禁用右键
    protect: true,
    //鼠标滚轮
    wheel: false,
    //是否在屏幕边缘显示箭头
    arrows: true,
    //顶部信息栏
    infobar: false,
    // Open/close animation type
    // Possible values:
    // false - disable
    // "zoom" - zoom images from/to thumbnail
    // "fade"
    // "zoom-in-out"
    //
    animationEffect: "zoom",
    // Duration in ms for open/close animation
    animationDuration: 500,
    // Should allow caption to overlap the content
    preventCaptionOverlap: false,
    //底部不显示图片名
    caption: function(instance, item) {
    var caption = ''
    },
    /* 在标题右边增加当前图片的序号和图片总数:
    caption: function(instance, item) {
    var caption = $(this).data('caption') || '';

    return (caption.length ? caption + '<br />' : '') + 'Image <span data-fancybox-index></span> of <span data-fancybox-count></span>';
    }*/
    });
    }

fancybox导致页面自动滚动

[how to prevent scrolling of page behind fancybox-2](https://stackoverflow.com/questions/15631124/how-to-prevent-scrolling-of-page-behind-fancybox-2)

fancybox causes page to to jump to the top

各种方法试下来,只有如下方法有效

在themes\hexo-theme-Claudia\source\style\base.scss添加

1
2
3
.fancybox-active{
height: 100% !important;
}

更改Highlight高亮

下载

样式预览

替换highlight-theme-light.csshighlight.pack.js

进一步修改

将下载的压缩包放入themes\hexo-theme-Claudia\source\js\highlight\中

themes\hexo-theme-Claudia\layout\post.pug

1
2
3
4
5
6
7
8
extends widget/base
block append head
link(rel='stylesheet', href= url_for('/style/post.css'))
link(rel='stylesheet', href= url_for('/style/themes/highlight-theme-light.css'))
script(src= url_for("/js/highlight.pack.js"))
meta(name="description", content=truncate( strip_html(page.content), {length: 360, omission: '..'} ))
if theme.comment_valine && theme.comment_valine.enable
script(src="//unpkg.com/valine/dist/Valine.min.js")

修改为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
extends widget/base
block append head
link(rel='stylesheet', href= url_for('/style/post.css'))
if theme.appearance == 'dark'
//暗黑模式
link(rel='stylesheet', href= url_for('js/highlight/styles/atom-one-dark-reasonable.min.css'))
else
//auto&light
//link(rel='stylesheet', href= url_for('js/highlight/styles/atom-one-light.min.css'))
//link(rel='stylesheet', href= url_for('js/highlight/styles/lioshi.min.css'))
link(rel='stylesheet', href= url_for('js/highlight/styles/github.min.css'))
script(src= url_for("/js/highlight/highlight.min.js"))
meta(name="description", content=truncate( strip_html(page.content), {length: 360, omission: '..'} ))
if theme.comment_valine && theme.comment_valine.enable
script(src="//unpkg.com/valine/dist/Valine.min.js")

以后把修改配色文件的功能放进config.yml

文章按更新时间排序

资料

修改文章 显示的日期:创建日期改为修改日期

themes\hexo-theme-Claudia\layout\widget\widget-post-list.pug

1
2
if post.date
time.has-text-grey(datetime=post.date.toJSON())= date(post.date, date_format)

改为

1
2
3
4
//if post.date
time.has-text-grey(datetime=post.date.toJSON())= date(post.date, date_format)
if post.updated
time.has-text-grey(datetime=post.updated.toJSON())= date(post.updated, date_format)

注意到node_modules\hexo-generator-index\lib\generator.js里面的timsort

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
'use strict';

const pagination = require('hexo-pagination');
const { sort } = require('timsort');

module.exports = function(locals) {
const config = this.config;
const posts = locals.posts.sort(config.index_generator.order_by);

sort(posts.data, (a, b) => (b.sticky || 0) - (a.sticky || 0));

const paginationDir = config.pagination_dir || 'page';
const path = config.index_generator.path || '';

return pagination(path, posts, {
perPage: config.index_generator.per_page,
layout: ['index', 'archive'],
format: paginationDir + '/%d/',
data: {
__index: true
}
});
};
1
2
3
4
5
6
7
8
# Home page setting
# path: Root path for your blogs index page. (default = '')
# per_page: Posts displayed per page. (0 = disable pagination)
# order_by: Posts order. (Order by date descending by default)
index_generator:
path: ''
per_page: 10
order_by: -top -updated -date

注意到order_by并不是是按设定先后排序,即order_by: -updated -top 排序顺序为先按更新时间递减排序,后按top值递减排序,

而是只支持一个排序条件,因此需要修改源码

故改为

1
2
3
4
index_generator:
path: ''
per_page: 10
order_by: -top

再修改node_modules\hexo-generator-index\lib\generator.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
'use strict';

const pagination = require('hexo-pagination');
const { sort } = require('timsort');

module.exports = function(locals) {
const config = this.config;
const posts = locals.posts.sort(config.index_generator.order_by);

//sort(posts.data, (a, b) => (b.sticky || 0) - (a.sticky || 0));
sort(posts.data, (a, b) => {
//先按top降序
var res = (b.top || 0) - (a.top || 0);
if (res == 0) {
//再按更新日期降序
res = (b.updated || 0) - (a.updated || 0);
if (res == 0) {
//最后按创建日期降序
res = (b.dated || 0) - (a.dated || 0);
return res;
} else {
return res;
}
} else {
return res;
}
});

const paginationDir = config.pagination_dir || 'page';
const path = config.index_generator.path || '';

return pagination(path, posts, {
perPage: config.index_generator.per_page,
layout: ['index', 'archive'],
format: paginationDir + '/%d/',
data: {
__index: true
}
});
};

再删除theme自带的排序themes\hexo-theme-Claudia\layout\widget\widget-post-list.pug

1
2
3
4
5
6
7
8
if page.posts.length > 0
//each post in page.posts.sort({updated:-1}).toArray()
p= post.title+' updated'+date(post.updated, date_format)+" date:"+date(post.date, date_format)+" top:"+post.top
each post in page.posts.sort({date:-1,top:-1}).toArray()
- var postURL = url_for(post.path)
- var imgURL = getPostCoverImg(post)
- var isExcerpt = post.excerpt && post.excerpt.length > 0
- var postContent = isExcerpt ? post.excerpt : post.content

改为

1
2
3
4
5
6
7
8
9
if page.posts.length > 0
//each post in page.posts.sort({updated:-1}).toArray()
p= post.title+' updated'+date(post.updated, date_format)+" date:"+date(post.date, date_format)+" top:"+post.top
//each post in page.posts.sort({date:-1,top:-1}).toArray()
each post in page.posts.toArray()
- var postURL = url_for(post.path)
- var imgURL = getPostCoverImg(post)
- var isExcerpt = post.excerpt && post.excerpt.length > 0
- var postContent = isExcerpt ? post.excerpt : post.content

原理

live2d

live2d看板娘不显示的解决办法

live2d看板娘不显示的解决办法

用chrome的console看了一下问题是Live2D widgets: Failed to create WebGL context.
检查到是没有开启WebGL这个选项, 所以如果你使用了live2d但是却不显示 那么可能就是你的浏览器没有开启或者不支持WebGL
chrome用户可以通过chrome://gpu来查看是否开启
如果没有的话, 可以按照以下步骤开启:

  1. 打开chrome://settings,在’高级-系统’里面打开’使用硬件加速模式(如果可用)’
  2. 打开chrome://flags 把’Override software rendering list’和’WebGL Draft Extensions’选为’Enabled’
  3. 重启浏览器

之后重新加载使用了live2d的网站,等待几秒就能看见可爱的看板娘了

定制css样式

themes\hexo-theme-Claudia\layout\widget\base.pug新增

1
2
3
4
5
6
7
8
9
10
11
12
link(rel="icon" href= url_for(theme.favicon))
link(rel="stylesheet" href= url_for('/style/common/bulma.css'))
link(rel="stylesheet" href= url_for('/style/base.css'))
link(rel="stylesheet" href= url_for('/style/common/helper.css'))
script(src= url_for("/js/common.js"))
if (theme.fancybox)
link(rel="stylesheet" href= url_for('/js/fancybox/jquery.fancybox.min.css'))
script(src= url_for("/js/fancybox/jquery-3.5.1.min.js"))
script(src= url_for("/js/fancybox/jquery.fancybox.min.js"))
script(src= url_for("/js/wrapImage.js"))
block head
script(src= url_for("/js/modifyLive2dCss.js"))

创建themes\hexo-theme-Claudia\source\js\modifyLive2dCss.js

由于live2d插件后生成的样式会覆盖,所以加上!important强制应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
$(document).ready(function() {
modifyCss();
});
/* 原始css
.live2d-widget-dialog-container {
width: 300px;
height: 120px;
position: absolute;
bottom: 65%;
right: 0px;
transform-origin: right;
padding: 12px;
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
}
.live2d-widget-dialog {
width: 100%;
height: 100%;
color: #917159;
font-size: 16px;
padding: 12px;
border: 2px solid rgb(236, 203, 180);
background: rgb(252, 248, 244);
box-sizing: border-box;
border-radius: 10px;
transform: rotate(-2deg);
opacity: 0;
transition: 200ms opacity;
box-shadow: rgba(0, 0, 0, 0.12) 0px 1px 6px, rgba(0, 0, 0, 0.12) 0px 1px 4px;
animation: live2d-widget-dialog-tingle 4s ease-in-out 0s infinite alternate;
}
@keyframes live2d-widget-dialog-tingle {
0% { transform: translate(-1px, 1.5px) rotate(-2deg); }
100% { transform: translate(1px, -1.5px) rotate(2deg); }
}

*/
function modifyCss() {
/* $(".live2d-widget-dialog-container").css({
"width": "320px",
"height": "120px",
"right": "-20px"
});
$(".live2d-widget-dialog").css({
"font-size": "20px"
}); */
//var cssText = ".live2d-widget-dialog-container{width:320px!important;height:120px!important;right:-20px!important}.live2d-widget-dialog{font-size:20px!important}";
var cssText = `
.live2d-widget-container{
left:2%!important;
bottom: -15%!important;
}
.live2d-widget-dialog-container {
width: 320px!important;
height: 130px!important;
right: -20px!important;
top: 7%!important;
}
.live2d-widget-dialog {
font-size: 20px!important;
}
`;
insertStyle(cssText);
if (!IsPC()) {
insertStyle(".live2d-widget-dialog-container {visibility: hidden;}");
}

}

function insertStyle(cssText) {
var head = document.getElementsByTagName("head")[0];
var style = document.createElement("style");
var rules = document.createTextNode(cssText);
style.type = "text/css";
if (style.styleSheet) {
style.styleSheet.cssText = rules.nodeValue;
} else {
style.appendChild(rules);
}
head.appendChild(style);
}
//判断是否是pc端 true为pc端 false为移动端
function IsPC() {
var userAgentInfo = navigator.userAgent;
var Agents = new Array("Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod");
var flag = true;
for (var v = 0; v < Agents.length; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
flag = false;
break;
}
}
return flag;
}

编辑技巧

反向TAB(编辑时与tab键相反功能的建)

Shift+Tab

空格

&ensp

正则表达式在行首添加指定内容

^ 表示行头
$ 表示行尾

流程图

例子

语言选择为flow

1
2
3
4
5
6
7
st=>start: Start
op=>operation: Your Operation
cond=>condition: Yes or No?
e=>end
st->op->cond
cond(yes)->e
cond(no)->op

效果

定义元素的语法

1
tag=>type: content:>url
  • tag就是元素名字,

  • type是这个元素的类型,有6中类型,分别为:

    • start # 开始
    • end # 结束
    • operation # 操作
    • subroutine # 子程序
    • condition # 条件
    • inputoutput # 输入或产出
  • content就是在框框中要写的内容,注意type后的冒号与文本之间一定要有个空格。

  • url是一个连接,与框框中的文本相绑定

连接元素的语法

用**->**来连接两个元素,需要注意的是condition类型,因为他有yes和no两个分支,所以要写成

1
2
c2(yes)->io->e 
c2(no)->op2->e

流程图方向

待更新

表情

Typora中的emoji表情

People
😄 :smile: 😆 :laughing: 😫 :tired_face:
😊 :blush: 😃 :smiley: ☺️ :relaxed:
😏 :smirk: 😍 :heart_eyes: 😘 :kissing_heart:
😚 :kissing_closed_eyes: 😳 :flushed: 😌 :relieved:
😆 :satisfied: 😁 :grin: 😉 :wink:
😜 :stuck_out_tongue_winking_eye: 😝 :stuck_out_tongue_closed_eyes: 😀 :grinning:
😗 :kissing: 😙 :kissing_smiling_eyes: 😛 :stuck_out_tongue:
😴 :sleeping: 😟 :worried: 😦 :frowning:
😧 :anguished: 😮 :open_mouth: 😬 :grimacing:
😕 :confused: 😯 :hushed: 😑 :expressionless:
😒 :unamused: 😅 :sweat_smile: 😓 :sweat:
😥 :disappointed_relieved: 😩 :weary: 😔 :pensive:
😞 :disappointed: 😖 :confounded: 😨 :fearful:
😰 :cold_sweat: 😣 :persevere: 😢 :cry:
😭 :sob: 😂 :joy: 😲 :astonished:
😱 :scream:
😠 :angry: 😡 :rage: 😤 :triumph:
😪 :sleepy: 😋 :yum: 😷 :mask:
😎 :sunglasses: 😵 :dizzy_face: 👿 :imp:
😈 :smiling_imp: 😐 :neutral_face: 😶 :no_mouth:
😇 :innocent: 👽 :alien: 💛 :yellow_heart:
💙 :blue_heart: 💜 :purple_heart: ❤️ :heart:
💚 :green_heart: 💔 :broken_heart: 💓 :heartbeat:
💗 :heartpulse: 💕 :two_hearts: 💞 :revolving_hearts:
💘 :cupid: 💖 :sparkling_heart: :sparkles:
⭐️ :star: 🌟 :star2: 💫 :dizzy:
💥 :boom: 💥 :collision: 💢 :anger:
❗️ :exclamation: :question: :grey_exclamation:
:grey_question: 💤 :zzz: 💨 :dash:
💦 :sweat_drops: 🎶 :notes: 🎵 :musical_note:
🔥 :fire: 💩 :hankey: 💩 :poop:
💩 :shit: 👍 :+1: 👍 :thumbsup:
👎 :-1: 👎 :thumbsdown: 👌 :ok_hand:
👊 :punch: 👊 :facepunch: :fist:
✌️ :v: 👋 :wave: :hand:
:raised_hand: 👐 :open_hands: ☝️ :point_up:
👇 :point_down: 👈 :point_left: 👉 :point_right:
🙌 :raised_hands: 🙏 :pray: 👆 :point_up_2:
👏 :clap: 💪 :muscle: 🤘 :metal:
🖕 :fu: 🚶 :walking: 🏃 :runner:
🏃 :running: 👫 :couple: 👪 :family:
👬 :two_men_holding_hands: 👭 :two_women_holding_hands: 💃 :dancer:
👯 :dancers: 🙆 :ok_woman: 🙅 :no_good:
💁 :information_desk_person: 🙋 :raising_hand: 👰 :bride_with_veil:
🙎 :person_with_pouting_face: 🙍 :person_frowning: 🙇 :bow:
💏 :couplekiss: 💑 :couple_with_heart: 💆 :massage:
💇 :haircut: 💅 :nail_care: 👦 :boy:
👧 :girl: 👩 :woman: 👨 :man:
👶 :baby: 👵 :older_woman: 👴 :older_man:
👱 :person_with_blond_hair: 👲 :man_with_gua_pi_mao: 👳 :man_with_turban:
👷 :construction_worker: 👮 :cop: 👼 :angel:
👸 :princess: 😺 :smiley_cat: 😸 :smile_cat:
😻 :heart_eyes_cat: 😽 :kissing_cat: 😼 :smirk_cat:
🙀 :scream_cat: 😿 :crying_cat_face: 😹 :joy_cat:
😾 :pouting_cat: 👹 :japanese_ogre: 👺 :japanese_goblin:
🙈 :see_no_evil: 🙉 :hear_no_evil: 🙊 :speak_no_evil:
💂 :guardsman: 💀 :skull: 🐾 :feet:
👄 :lips: 💋 :kiss: 💧 :droplet:
👂 :ear: 👀 :eyes: 👃 :nose:
👅 :tongue: 💌 :love_letter: 👤 :bust_in_silhouette:
👥 :busts_in_silhouette: 💬 :speech_balloon: 💭 :thought_balloon:
Nature
☀️ :sunny: ☔️ :umbrella: ☁️ :cloud:
❄️ :snowflake: ⛄️ :snowman: ⚡️ :zap:
🌀 :cyclone: 🌁 :foggy: 🌊 :ocean:
🐱 :cat: 🐶 :dog: 🐭 :mouse:
🐹 :hamster: 🐰 :rabbit: 🐺 :wolf:
🐸 :frog: 🐯 :tiger: 🐨 :koala:
🐻 :bear: 🐷 :pig: 🐽 :pig_nose:
🐮 :cow: 🐗 :boar: 🐵 :monkey_face:
🐒 :monkey: 🐴 :horse: 🐎 :racehorse:
🐫 :camel: 🐑 :sheep: 🐘 :elephant:
🐼 :panda_face: 🐍 :snake: 🐦 :bird:
🐤 :baby_chick: 🐥 :hatched_chick: 🐣 :hatching_chick:
🐔 :chicken: 🐧 :penguin: 🐢 :turtle:
🐛 :bug: 🐝 :honeybee: 🐜 :ant:
🐞 :beetle: 🐌 :snail: 🐙 :octopus:
🐠 :tropical_fish: 🐟 :fish: 🐳 :whale:
🐋 :whale2: 🐬 :dolphin: 🐄 :cow2:
🐏 :ram: 🐀 :rat: 🐃 :water_buffalo:
🐅 :tiger2: 🐇 :rabbit2: 🐉 :dragon:
🐐 :goat: 🐓 :rooster: 🐕 :dog2:
🐖 :pig2: 🐁 :mouse2: 🐂 :ox:
🐲 :dragon_face: 🐡 :blowfish: 🐊 :crocodile:
🐪 :dromedary_camel: 🐆 :leopard: 🐈 :cat2:
🐩 :poodle: 🐾 :paw_prints: 💐 :bouquet:
🌸 :cherry_blossom: 🌷 :tulip: 🍀 :four_leaf_clover:
🌹 :rose: 🌻 :sunflower: 🌺 :hibiscus:
🍁 :maple_leaf: 🍃 :leaves: 🍂 :fallen_leaf:
🌿 :herb: 🍄 :mushroom: 🌵 :cactus:
🌴 :palm_tree: 🌲 :evergreen_tree: 🌳 :deciduous_tree:
🌰 :chestnut: 🌱 :seedling: 🌼 :blossom:
🌾 :ear_of_rice: 🐚 :shell: 🌐 :globe_with_meridians:
🌞 :sun_with_face: 🌝 :full_moon_with_face: 🌚 :new_moon_with_face:
🌑 :new_moon: 🌒 :waxing_crescent_moon: 🌓 :first_quarter_moon:
🌔 :waxing_gibbous_moon: 🌕 :full_moon: 🌖 :waning_gibbous_moon:
🌗 :last_quarter_moon: 🌘 :waning_crescent_moon: 🌜 :last_quarter_moon_with_face:
🌛 :first_quarter_moon_with_face: 🌔 :moon: 🌍 :earth_africa:
🌎 :earth_americas: 🌏 :earth_asia: 🌋 :volcano:
🌌 :milky_way: ⛅️ :partly_sunny:
Object
🎍 :bamboo: 💝 :gift_heart: 🎎 :dolls:
🎒 :school_satchel: 🎓 :mortar_board: 🎏 :flags:
🎆 :fireworks: 🎇 :sparkler: 🎐 :wind_chime:
🎑 :rice_scene: 🎃 :jack_o_lantern: 👻 :ghost:
🎅 :santa: 🎄 :christmas_tree: 🎁 :gift:
🔔 :bell: 🔕 :no_bell: 🎋 :tanabata_tree:
🎉 :tada: 🎊 :confetti_ball: 🎈 :balloon:
🔮 :crystal_ball: 💿 :cd: 📀 :dvd:
💾 :floppy_disk: 📷 :camera: 📹 :video_camera:
🎥 :movie_camera: 💻 :computer: 📺 :tv:
📱 :iphone: ☎️ :phone: ☎️ :telephone:
📞 :telephone_receiver: 📟 :pager: 📠 :fax:
💽 :minidisc: 📼 :vhs: 🔉 :sound:
🔈 :speaker: 🔇 :mute: 📢 :loudspeaker:
📣 :mega: ⌛️ :hourglass: :hourglass_flowing_sand:
:alarm_clock: ⌚️ :watch: 📻 :radio:
📡 :satellite: :loop: 🔍 :mag:
🔎 :mag_right: 🔓 :unlock: 🔒 :lock:
🔏 :lock_with_ink_pen: 🔐 :closed_lock_with_key: 🔑 :key:
💡 :bulb: 🔦 :flashlight: 🔆 :high_brightness:
🔅 :low_brightness: 🔌 :electric_plug: 🔋 :battery:
📲 :calling: ✉️ :email: 📫 :mailbox:
📮 :postbox: 🛀 :bath: 🛁 :bathtub:
🚿 :shower: 🚽 :toilet: 🔧 :wrench:
🔩 :nut_and_bolt: 🔨 :hammer: 💺 :seat:
💰 :moneybag: 💴 :yen: 💵 :dollar:
💷 :pound: 💶 :euro: 💳 :credit_card:
💸 :money_with_wings: 📧 :e-mail: 📥 :inbox_tray:
📤 :outbox_tray: ✉️ :envelope: 📨 :incoming_envelope:
📯 :postal_horn: 📪 :mailbox_closed: 📬 :mailbox_with_mail:
📭 :mailbox_with_no_mail: 🚪 :door: 🚬 :smoking:
💣 :bomb: 🔫 :gun: 🔪 :hocho:
💊 :pill: 💉 :syringe: 📄 :page_facing_up:
📃 :page_with_curl: 📑 :bookmark_tabs: 📊 :bar_chart:
📈 :chart_with_upwards_trend: 📉 :chart_with_downwards_trend: 📜 :scroll:
📋 :clipboard: 📆 :calendar: 📅 :date:
📇 :card_index: 📁 :file_folder: 📂 :open_file_folder:
✂️ :scissors: 📌 :pushpin: 📎 :paperclip:
✒️ :black_nib: ✏️ :pencil2: 📏 :straight_ruler:
📐 :triangular_ruler: 📕 :closed_book: 📗 :green_book:
📘 :blue_book: 📙 :orange_book: 📓 :notebook:
📔 :notebook_with_decorative_cover: 📒 :ledger: 📚 :books:
🔖 :bookmark: 📛 :name_badge: 🔬 :microscope:
🔭 :telescope: 📰 :newspaper: 🏈 :football:
🏀 :basketball: ⚽️ :soccer: ⚾️ :baseball:
🎾 :tennis: 🎱 :8ball: 🏉 :rugby_football:
🎳 :bowling: ⛳️ :golf: 🚵 :mountain_bicyclist:
🚴 :bicyclist: 🏇 :horse_racing: 🏂 :snowboarder:
🏊 :swimmer: 🏄 :surfer: 🎿 :ski:
♠️ :spades: ♥️ :hearts: ♣️ :clubs:
♦️ :diamonds: 💎 :gem: 💍 :ring:
🏆 :trophy: 🎼 :musical_score: 🎹 :musical_keyboard:
🎻 :violin: 👾 :space_invader: 🎮 :video_game:
🃏 :black_joker: 🎴 :flower_playing_cards: 🎲 :game_die:
🎯 :dart: 🀄️ :mahjong: 🎬 :clapper:
📝 :memo: 📝 :pencil: 📖 :book:
🎨 :art: 🎤 :microphone: 🎧 :headphones:
🎺 :trumpet: 🎷 :saxophone: 🎸 :guitar:
👞 :shoe: 👡 :sandal: 👠 :high_heel:
💄 :lipstick: 👢 :boot: 👕 :shirt:
👕 :tshirt: 👔 :necktie: 👚 :womans_clothes:
👗 :dress: 🎽 :running_shirt_with_sash: 👖 :jeans:
👘 :kimono: 👙 :bikini: 🎀 :ribbon:
🎩 :tophat: 👑 :crown: 👒 :womans_hat:
👞 :mans_shoe: 🌂 :closed_umbrella: 💼 :briefcase:
👜 :handbag: 👝 :pouch: 👛 :purse:
👓 :eyeglasses: 🎣 :fishing_pole_and_fish: ☕️ :coffee:
🍵 :tea: 🍶 :sake: 🍼 :baby_bottle:
🍺 :beer: 🍻 :beers: 🍸 :cocktail:
🍹 :tropical_drink: 🍷 :wine_glass: 🍴 :fork_and_knife:
🍕 :pizza: 🍔 :hamburger: 🍟 :fries:
🍗 :poultry_leg: 🍖 :meat_on_bone: 🍝 :spaghetti:
🍛 :curry: 🍤 :fried_shrimp: 🍱 :bento:
🍣 :sushi: 🍥 :fish_cake: 🍙 :rice_ball:
🍘 :rice_cracker: 🍚 :rice: 🍜 :ramen:
🍲 :stew: 🍢 :oden: 🍡 :dango:
🥚 :egg: 🍞 :bread: 🍩 :doughnut:
🍮 :custard: 🍦 :icecream: 🍨 :ice_cream:
🍧 :shaved_ice: 🎂 :birthday: 🍰 :cake:
🍪 :cookie: 🍫 :chocolate_bar: 🍬 :candy:
🍭 :lollipop: 🍯 :honey_pot: 🍎 :apple:
🍏 :green_apple: 🍊 :tangerine: 🍋 :lemon:
🍒 :cherries: 🍇 :grapes: 🍉 :watermelon:
🍓 :strawberry: 🍑 :peach: 🍈 :melon:
🍌 :banana: 🍐 :pear: 🍍 :pineapple:
🍠 :sweet_potato: 🍆 :eggplant: 🍅 :tomato:
🌽 :corn:
Places
🏠 :house: 🏡 :house_with_garden: 🏫 :school:
🏢 :office: 🏣 :post_office: 🏥 :hospital:
🏦 :bank: 🏪 :convenience_store: 🏩 :love_hotel:
🏨 :hotel: 💒 :wedding: ⛪️ :church:
🏬 :department_store: 🏤 :european_post_office: 🌇 :city_sunrise:
🌆 :city_sunset: 🏯 :japanese_castle: 🏰 :european_castle:
⛺️ :tent: 🏭 :factory: 🗼 :tokyo_tower:
🗾 :japan: 🗻 :mount_fuji: 🌄 :sunrise_over_mountains:
🌅 :sunrise: 🌠 :stars: 🗽 :statue_of_liberty:
🌉 :bridge_at_night: 🎠 :carousel_horse: 🌈 :rainbow:
🎡 :ferris_wheel: ⛲️ :fountain: 🎢 :roller_coaster:
🚢 :ship: 🚤 :speedboat: ⛵️ :boat:
⛵️ :sailboat: 🚣 :rowboat: ⚓️ :anchor:
🚀 :rocket: ✈️ :airplane: 🚁 :helicopter:
🚂 :steam_locomotive: 🚊 :tram: 🚞 :mountain_railway:
🚲 :bike: 🚡 :aerial_tramway: 🚟 :suspension_railway:
🚠 :mountain_cableway: 🚜 :tractor: 🚙 :blue_car:
🚘 :oncoming_automobile: 🚗 :car: 🚗 :red_car:
🚕 :taxi: 🚖 :oncoming_taxi: 🚛 :articulated_lorry:
🚌 :bus: 🚍 :oncoming_bus: 🚨 :rotating_light:
🚓 :police_car: 🚔 :oncoming_police_car: 🚒 :fire_engine:
🚑 :ambulance: 🚐 :minibus: 🚚 :truck:
🚋 :train: 🚉 :station: 🚆 :train2:
🚅 :bullettrain_front: 🚄 :bullettrain_side: 🚈 :light_rail:
🚝 :monorail: 🚃 :railway_car: 🚎 :trolleybus:
🎫 :ticket: ⛽️ :fuelpump: 🚦 :vertical_traffic_light:
🚥 :traffic_light: ⚠️ :warning: 🚧 :construction:
🔰 :beginner: 🏧 :atm: 🎰 :slot_machine:
🚏 :busstop: 💈 :barber: ♨️ :hotsprings:
🏁 :checkered_flag: 🎌 :crossed_flags: 🏮 :izakaya_lantern:
🗿 :moyai: 🎪 :circus_tent: 🎭 :performing_arts:
📍 :round_pushpin: 🚩 :triangular_flag_on_post: 🇯🇵 :jp:
🇰🇷 :kr: 🇨🇳 :cn: 🇺🇸 :us:
🇫🇷 :fr: 🇪🇸 :es: 🇮🇹 :it:
🇷🇺 :ru: 🇬🇧 :gb: 🇬🇧 :uk:
🇩🇪 :de:
Symbols
1️⃣ :one: 2️⃣ :two: 3️⃣ :three:
4️⃣ :four: 5️⃣ :five: 6️⃣ :six:
7️⃣ :seven: 8️⃣ :eight: 9️⃣ :nine:
🔟 :keycap_ten: 🔢 :1234: 0️⃣ :zero:
#️⃣ :hash: 🔣 :symbols: ◀️ :arrow_backward:
⬇️ :arrow_down: ▶️ :arrow_forward: ⬅️ :arrow_left:
🔠 :capital_abcd: 🔡 :abcd: 🔤 :abc:
↙️ :arrow_lower_left: ↘️ :arrow_lower_right: ➡️ :arrow_right:
⬆️ :arrow_up: ↖️ :arrow_upper_left: ↗️ :arrow_upper_right:
:arrow_double_down: :arrow_double_up: 🔽 :arrow_down_small:
⤵️ :arrow_heading_down: ⤴️ :arrow_heading_up: ↩️:leftwards_arrow_with_hook:
↪️ :arrow_right_hook: ↔️ :left_right_arrow: ↕️ :arrow_up_down:
🔼 :arrow_up_small: 🔃 :arrows_clockwise: 🔄 :arrows_counterclockwise:
:rewind: :fast_forward: ℹ️ :information_source:
🆗 :ok: 🔀 :twisted_rightwards_arrows: 🔁 :repeat:
🔂 :repeat_one: 🆕 :new: 🔝 :top:
🆙 :up: 🆒 :cool: 🆓 :free:
🆖 :ng: 🎦 :cinema: 🈁 :koko:
📶 :signal_strength: 🈹 :u5272: 🈴 :u5408:
🈺 :u55b6: 🈯️ :u6307: 🈷️ :u6708:
🈶 :u6709: 🈵 :u6e80: 🈚️ :u7121:
🈸 :u7533: 🈳 :u7a7a: 🈲 :u7981:
🈂️ :sa: 🚻 :restroom: 🚹 :mens:
🚺 :womens: 🚼 :baby_symbol: 🚭 :no_smoking:
🅿️ :parking: ♿️ :wheelchair: 🚇 :metro:
🛄 :baggage_claim: 🉑 :accept: 🚾 :wc:
🚰 :potable_water: 🚮 :put_litter_in_its_place: ㊙️ :secret:
㊗️ :congratulations: Ⓜ️ :m: 🛂 :passport_control:
🛅 :left_luggage: 🛃 :customs: 🉐 :ideograph_advantage:
🆑 :cl: 🆘 :sos: 🆔 :id:
🚫 :no_entry_sign: 🔞 :underage: 📵 :no_mobile_phones:
🚯 :do_not_litter: 🚱 :non-potable_water: 🚳 :no_bicycles:
🚷 :no_pedestrians: 🚸 :children_crossing: ⛔️ :no_entry:
✳️ :eight_spoked_asterisk: ✴️ :eight_pointed_black_star: 💟 :heart_decoration:
🆚 :vs: 📳 :vibration_mode: 📴 :mobile_phone_off:
💹 :chart: 💱 :currency_exchange: ♈️ :aries:
♉️ :taurus: ♊️ :gemini: ♋️ :cancer:
♌️ :leo: ♍️ :virgo: ♎️ :libra:
♏️ :scorpius: ♐️ :sagittarius: ♑️ :capricorn:
♒️ :aquarius: ♓️ :pisces: :ophiuchus:
🔯 :six_pointed_star: :negative_squared_cross_mark: 🅰️ :a:
🅱️ :b: 🆎 :ab: 🅾️ :o2:
💠:diamond_shape_with_a_dot_inside: ♻️ :recycle: 🔚 :end:
🔛 :on: 🔜 :soon: 🕐 :clock1:
🕜 :clock130: 🕙 :clock10: 🕥 :clock1030:
🕚 :clock11: 🕦 :clock1130: 🕛 :clock12:
🕧 :clock1230: 🕑 :clock2: 🕝 :clock230:
🕒 :clock3: 🕞 :clock330: 🕓 :clock4:
🕟 :clock430: 🕔 :clock5: 🕠 :clock530:
🕕 :clock6: 🕡 :clock630: 🕖 :clock7:
🕢 :clock730: 🕗 :clock8: 🕣 :clock830:
🕘 :clock9: 🕤 :clock930: 💲 :heavy_dollar_sign:
©️ :copyright: ®️ :registered: ™️ :tm:
:x: ❗️ :heavy_exclamation_mark: ‼️ :bangbang:
⁉️ :interrobang: ⭕️ :o: ✖️ :heavy_multiplication_x:
:heavy_plus_sign: :heavy_minus_sign: :heavy_division_sign:
💮 :white_flower: 💯 :100: ✔️ :heavy_check_mark:
☑️ :ballot_box_with_check: 🔘 :radio_button: 🔗 :link:
:curly_loop: 〰️ :wavy_dash: 〽️ :part_alternation_mark:
🔱 :trident: :black_square: :black_square: :white_square: :white_square:
:white_check_mark: 🔲 :black_square_button: 🔳 :white_square_button:
⚫️ :black_circle: ⚪️ :white_circle: 🔴 :red_circle:
🔵 :large_blue_circle: 🔷 :large_blue_diamond: 🔶 :large_orange_diamond:
🔹 :small_blue_diamond: 🔸 :small_orange_diamond: 🔺 :small_red_triangle:
🔻 :small_red_triangle_down:

图片正确插入姿势

  1. 如何进入指定文件目录_hexo博客如何插入图片

  2. hexo-image-link
    npm install hexo-image-link --save

修改渲染器

资料

hexo markdown渲染器

安装新的渲染器

1
2
3
npm uni hexo-renderer-marked --save
npm i @upupming/hexo-renderer-markdown-it-plus --save #以下二选一
npm i hexo-renderer-markdown-it-plus --save

修改 _config.yml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Markdown config
markdown_it_plus:
render:
html: true
xhtmlOut: false
breaks: true
linkify: true
typographer: true
quotes: '“”‘’'
plugins:
anchors:
level: 2
collisionSuffix: 'v'
permalink: true
permalinkClass: header-anchor
permalinkSide: 'left'
permalinkSymbol:

问题

  1. 中文需用\text{}包裹

    1
    2
    3
    4
    5
    6
    LaTeX-incompatible input and strict mode is set to 'warn': Unicode text character "文" used in math mode [unicodeTextInMathMode]
    LaTeX-incompatible input and strict mode is set to 'warn': Unicode text character "件" used in math mode [unicodeTextInMathMode]
    LaTeX-incompatible input and strict mode is set to 'warn': Unicode text character "名" used in math mode [unicodeTextInMathMode]
    No character metrics for '文' in style 'Main-Regular'
    No character metrics for '件' in style 'Main-Regular'
    No character metrics for '名' in style 'Main-Regular'

    我猜测应该是开启了 hexo-renderer-markdown-it-plus 作为渲染器并且用 katex 进行公式解析

    假如是这种情况的话在 $...$ 中用 \text{} 对中文包裹应该可以解决这个问题,比如 $\text{测试}$

    另外这样的警告应该不会对渲染造成任何的影响,一定程度上可以忽视

    如果有其他问题可以继续反馈

    https://github.com/theme-kaze/hexo-theme-kaze/issues/24

    一个是 vscode 等支持正则搜索的工具搜索博客文章,输入 \$.*[\u4e00-\u9fa5]+.*\$ 然后尝试定位,但是由于公式语法首尾是一样的所以定位不一定准。另外这个报错是对每个字符都会报错,所以可以尝试把相关的中文连起来搜索定位。

    另一种是关闭严格模式,但是 hexo-renderer-markdown-it-plus 并没有提供配置注入的能力,并且原本依赖的 markdown-it-katex 好像就不行,所以可能得自己 fork 然后发 npm 改,感觉有点麻烦。相关代码在 https://github.com/CHENXCHEN/hexo-renderer-markdown-it-plus/blob/f2dd1b25738992efc391ba9da398a9c6a7efb105/lib/renderer.js#L83

    katex 也有类似的 issue,KaTeX/KaTeX#1871

  2. Template render error: expected variable end

    latex公式居中_结合MathType和MathJax在Hexo博客中插入数学公式

    后来我发现当有多个花括号,如 `}}`或`{{`,在一起时,就会报Template render error错误。最后在这篇博客中找到了解决办法。即,在公式的前后分别加上`和`:

    1
    {% raw%} $$LaTex数学公式$$ {% endraw %}
  3. Katex支持

    Katex plugin is enabled by default. However, this renderer alone does not work out of the box for mathematical formulas to display correctly on your website. Therefore, you do not need to do anything if you do not want to use Katex. Otherwise, if you want to use katex, you must add this css style to your website: https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0/katex.min.css

    在主题themes\hexo-theme-Claudia\layout\widget\base.pug增加

    1
    link(rel="stylesheet" href= url_for('https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0/katex.min.css'))

    latex公式居中_结合MathType和MathJax在Hexo博客中插入数学公式

hexo博客自定义页面跳过渲染

hexo博客自定义页面跳过渲染

Hexo插件汇总

插件 功能 文档链接
hexo-generator-index-pin-top 文章置顶 https://github.com/netcan/hexo-generator-index-pin-top
hexo-wordcount 文章字数统计和阅读时长统计 https://github.com/willin/hexo-wordcount
hexo-abbrlink 生成URL短链接 https://github.com/rozbo/hexo-abbrlink
hexo-lazyload-image 图片懒加载 https://github.com/Troy-Yang/hexo-lazyload-image
hexo-generator-baidu-sitemap 生成baidusitemap.xml https://github.com/coneycode/hexo-generator-baidu-sitemap
hexo-generator-sitemap 生成sitemap.xml https://github.com/hexojs/hexo-generator-sitemap
hexo-generator-feed 生成RSS文件 https://github.com/hexojs/hexo-generator-feed
hexo-external-link 外链跳转 https://github.com/hvnobug/hexo-external-link
hexo-autonofollow 自动对外部链接增加nofollow属性 https://github.com/liuzc/hexo-autonofollow
hexo-filter-nofollow 为外链添加rel=“noopener external nofollow noreferrer” https://github.com/hexojs/hexo-filter-nofollow
hexo-prism-plugin 代码高亮 https://github.com/ele828/hexo-prism-plugin
hexo-neat 博客压缩 https://github.com/rozbo/hexo-neat
hexo-allminifier 博客压缩 https://developer.aliyun.com/mirror/npm/package/hexo-all-minifier
hexo-tag-aplayer aplayer音乐播放器 https://github.com/MoePlayer/hexo-tag-aplayer
hexo-tag-dplayer dplayer视频播放器 https://github.com/MoePlayer/hexo-tag-dplayer
hexo-douban 添加豆瓣读书,电影,游戏页面 https://github.com/mythsman/hexo-douban
hexo-generator-searchdb 本地搜索,生成search.xml https://github.com/theme-next/hexo-generator-searchdb
hexo-algoliasearch 搜索系统 https://github.com/LouisBarranqueiro/hexo-algoliasearch
hexo-algolia 搜索系统 https://github.com/oncletom/hexo-algolia
hexo-generator-search 本地搜索系统 https://github.com/wzpan/hexo-generator-search
hexo-baidu-url-submit 百度站长主动推送 https://github.com/huiwang/hexo-baidu-url-submit
hexo-offline 开启PWA https://github.com/JLHwung/hexo-offline
hexo-pwa 开启PWA https://github.com/lavas-project/hexo-pwa
hexo-helper-live2d 看板娘 https://github.com/EYHN/hexo-helper-live2d
hexo-addlink 文末添加当前文章链接和版权声明 https://github.com/acwong00/hexo-addlink
hexo-blog-encrypt 博客文章加密 https://github.com/MikeCoder/hexo-blog-encrypt
hexo-simple-mindmap 博客添加脑图 https://github.com/HunterXuan/hexo-simple-mindmap
hexo-pdf 博客展示pdf https://github.com/superalsrk/hexo-pdf
hexo-tag-echarts 博客添加图表 https://github.com/zhoulvjun/hexo-tag-echarts
hexo-steam-games 添加Steam游戏界面 https://github.com/HCLonely/hexo-steam-games
hexo-bilibili-bangumi 添加bilibili番剧页面 https://github.com/HCLonely/hexo-bilibili-bangumi
hexo-generator-random 生成随机文章页面 https://github.com/Drew233/hexo-generator-random
hexo-web-push-notification web推送插件 https://github.com/glazec/hexo-web-push-notification

HEXO无法上传

hexo d无法上传,显示如下

1
2
3
4
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

原因:开了代理

解决方式:命令行增加代理设置

1
2
3
4
#cmd
set http_proxy=http://127.0.0.1:7890 & set https_proxy=http://127.0.0.1:7890
#powershell
$Env:http_proxy="http://127.0.0.1:7890";$Env:https_proxy="http://127.0.0.1:7890"

图片懒加载

  1. hexo-lazyload-image
  2. hexo-lazyload

加密文章图片不显示

问题定位:opacity: 0; 怀疑和懒加载图片插件冲突

1
2
3
4
5
6
7
8
9
.post-page .post-content img {
display: block;
margin: 0 auto;
max-height: 500px;
border-radius: 6px;
box-shadow: 0 0 15px rgb(0 0 0 / 5%);
opacity: 0;
will-change: opacity;
}

软连接同步更新文章

1
mklink /J D:\Code\Git\hexo\source D:\Code\Git\shjdgwj.github.io\source

定制icarus主题

资料

  1. https://github.com/shjdgwj/hexo-theme-icarus
  2. https://ppoffice.github.io/hexo-theme-icarus/
  3. 个人博客优化记录
  4. hexo-theme-icarus 3 食用经验分享
  5. icarus主题自定义
  6. https://bulma.zcopy.site/documentation/overview/
  7. https://bulma.io/documentation/overview/
  8. 自定义Hexo标签插件

文章目录自动开启

toc的判断在themes\hexo-theme-icarus\layout\common\navbar.jsx

1
const showToc = (config.toc === true || page.toc) && hasTocWidget && ['page', 'post'].includes(page.layout);

themes\hexo-theme-icarus\_config.post.yml添加全局生效

1
2
# toc
toc: true

设置展开内容

在hexo中,插入*<!-- more -->*即可实现文章摘要设置,对于没有设置摘要的文章,设定一个默认字符数。

themes\hexo-theme-icarus\layout\common\article.jsx

1
2
3
4
render() {
//.......
return //.......
}

return前添加以下代码

1
2
3
if(config.excerpt.enable == true && page.excerpt.length === 0){
page.excerpt = page.content.replace(/<\/?.+?>/g,"").replace(/ /g,"").substring(0,config.excerpt.words_count);
}

_config.yml添加

1
2
3
4
theme_config:
excerpt: #<!-- more -->
enable: true
words_count: 300

主题语言配置错误

重命名themes\hexo-theme-icarus\languages\zh-CN.ymlzh-cn.yml,再复制一份命名为zh_cn.yml。当然,可以直接命名为zh解决下划线问题

修改_config.yml语言设置language: zh_CNlanguage: zh_cn

造成错误原因如下:

themes\hexo-theme-icarus\layout\common\article.jsx

1
const language = toMomentLocale(page.lang || page.language || config.language || 'en');

node_modules\hexo\lib\plugins\helper\date.js

1
2
3
4
5
6
7
8
9
10
11
12
function toMomentLocale(lang) {
if (lang === undefined) {
return undefined;
}

// moment.locale('') equals moment.locale('en')
// moment.locale(null) equals moment.locale('en')
if (!lang || lang === 'en' || lang === 'default') {
return 'en';
}
return lang.toLowerCase().replace('_', '-');//这里转换成小写了,因此找不到对应的语言配置文件,以及修改了下划线
}

封面 & 缩略图默认设置为文章第一张图

原始需要设置文章的coverthumbnail属性,当不设置这两个属性时显示为文章的第一张图片,现做以下修改:

themes\hexo-theme-icarus\layout\common\article.jsx

1
2
3
4
5
6
render() {
const cover = page.cover ? url_for(page.cover) : null;
//.......
return //.......
}

修改为

1
var cover = page.cover ? url_for(page.cover) : null;

return前添加

1
2
3
4
5
6
7
if(!cover){
const firstImgElRegx = /<img[^>]+src="?([^"\s]+)".*?>/;
const coverImgElement = page.content.match(firstImgElRegx);
if (coverImgElement) {
cover = coverImgElement[1];
}
}

themes\hexo-theme-icarus\layout\archive.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
{posts.map(post => {
const categories = post.categories.map(category => ({
url: url_for(category.path),
name: category.name
}));
return <ArticleMedia
url={url_for(post.link || post.path)}
title={post.title}
date={date(post.date)}
dateXml={date_xml(post.date)}
categories={categories}
thumbnail={post.thumbnail ? url_for(post.thumbnail) : null} />;
})}

修改为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{posts.map(post => {
const categories = post.categories.map(category => ({
url: url_for(category.path),
name: category.name
}));
var thumbnail=post.thumbnail ? url_for(post.thumbnail) : null;
if(!thumbnail){
const firstImgElRegx = /<img[^>]+src="?([^"\s]+)".*?>/;
const thumbnailImgElement = post.content.match(firstImgElRegx);
if (thumbnailImgElement) {
thumbnail = thumbnailImgElement[1];
}
}
return <ArticleMedia
url={url_for(post.link || post.path)}
title={post.title}
date={date(post.date)}
dateXml={date_xml(post.date)}
categories={categories}
thumbnail={thumbnail} />;
})}

魔改hexo-component-inferno

参考hexo-theme-icarus 3 食用经验分享

对于已经移除代码的 widgets,直接从 hexo-component-inferno / src / view 把需要修改的 JSX 复制到主题目录下的 layout/widget,再进行魔改即可。

复制node_modules\hexo-component-inferno\lib\view\widget\recent_posts.jsthemes\hexo-theme-icarus\include\schema\widget\目录

好像不太行,直接修改node_modules\hexo-component-inferno\lib\view\widget\recent_posts.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var posts = site.posts.sort('date', -1).limit(limit).map(function (post) {
return {
url: url_for(post.link || post.path),
title: post.title,
date: date(post.date),
dateXml: date_xml(post.date),
thumbnail: post.thumbnail ? url_for(post.thumbnail) : null,
categories: post.categories.map(function (category) {
return {
name: category.name,
url: url_for(category.path)
};
})
};
});

修改为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var posts = site.posts.sort('date', -1).limit(limit).map(function (post) {
var thumbnail=post.thumbnail ? url_for(post.thumbnail) : null;
if(!thumbnail){
const firstImgElRegx = /<img[^>]+src="?([^"\s]+)".*?>/;
const thumbnailImgElement = post.content.match(firstImgElRegx);
if (thumbnailImgElement) {
thumbnail = thumbnailImgElement[1];
}
}
return {
url: url_for(post.link || post.path),
title: post.title,
date: date(post.date),
dateXml: date_xml(post.date),
thumbnail: thumbnail,
categories: post.categories.map(function (category) {
return {
name: category.name,
url: url_for(category.path)
};
})
};
});

错误代码themes\hexo-theme-icarus\layout\common\navbar.jsx

直接把键名name作为输出

1
2
3
4
5
6
{Object.keys(menu).length ? <div class="navbar-start">
{Object.keys(menu).map(name => {
const item = menu[name];
return <a class={classname({ 'navbar-item': true, 'is-active': item.active })} href={item.url}>{name}</a>;
})}
</div> : null}

本来想用用于生成对应翻译文本helper._p()函数实现多语言支持,但是发现

1
2
3
4
5
6
7
8
9
const menu = {};
if (navbar && navbar.menu) {
const pageUrl = typeof page.path !== 'undefined' ? url_for(page.path) : '';
Object.keys(navbar.menu).forEach(name => {
const url = url_for(navbar.menu[name]);
const active = isSameLink(url, pageUrl);
menu[name] = { url, active };
});
}

menu直接来源于配置文件themes\hexo-theme-icarus\_config.yml

1
2
3
4
5
6
7
navbar:
menu:
Home: /
Archives: /archives
Categories: /categories
Tags: /tags
About: /about

因此其实只要修改为如以下即可,顺序就是最终显示顺序

1
2
3
4
5
6
7
navbar:
menu:
主页: /
分类: /categories
标签: /tags
归档: /archives
关于: /about

文章按更新时间排序

修改node_modules\hexo-component-inferno\lib\view\widget\recent_posts.js,显示修改时间而非创建时间

1
2
3
4
5
6
7
8
9
10
//var posts = site.posts.sort('date', -1).limit(limit).map(function (post) {
var posts = site.posts.sort('updated', -1).limit(limit).map(function (post) {
var thumbnail=post.thumbnail ? url_for(post.thumbnail) : null;
if(!thumbnail){
const firstImgElRegx = /<img[^>]+src="?([^"\s]+)".*?>/;
const thumbnailImgElement = post.content.match(firstImgElRegx);
if (thumbnailImgElement) {
thumbnail = thumbnailImgElement[1];
}
}
1
2
3
4
5
6
7
8
9
return (0, _inferno.createComponentVNode)(2, ArticleMedia, {
"thumbnail": post.thumbnail,
"url": post.url,
"title": post.title,
//"date": post.date,
"date": post.updated,
"dateXml": post.dateXml,
"categories": post.categories
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
return {
url: url_for(post.link || post.path),
title: post.title,
date: date(post.date),
updated: date(post.updated),//添加此行
dateXml: date_xml(post.date),
thumbnail: thumbnail,
categories: post.categories.map(function (category) {
return {
name: category.name,
url: url_for(category.path)
};
})
};

修改node_modules\hexo-generator-index\lib\generator.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
'use strict';

const pagination = require('hexo-pagination');

module.exports = function(locals) {
const config = this.config;
const posts = locals.posts.sort(config.index_generator.order_by);

//posts.data.sort((a, b) => (b.sticky || 0) - (a.sticky || 0));
posts.data.sort((a, b) => {
//先按top降序
var res = (b.top || 0) - (a.top || 0);
if (res == 0) {
//再按更新日期降序
res = (b.updated || 0) - (a.updated || 0);
if (res == 0) {
//最后按创建日期降序
res = (b.dated || 0) - (a.dated || 0);
return res;
} else {
return res;
}
} else {
return res;
}
});

posts.data[0].prev = null;
posts.data[0].next = posts.data[1];
posts.data[posts.data.length-1].prev = posts.data[posts.data.length-2];
posts.data[posts.data.length - 1].next = null;
for (var i = 1; i < posts.data.length-1; i++){
posts.data[i].prev = posts.data[i-1];
posts.data[i].next = posts.data[i+1];
}

const paginationDir = config.pagination_dir || 'page';
const path = config.index_generator.path || '';

return pagination(path, posts, {
perPage: config.index_generator.per_page,
layout: ['index', 'archive'],
format: paginationDir + '/%d/',
data: {
__index: true
}
});
};

加宽正文布局

themes\hexo-theme-icarus\include\style\base.styl

1
2
3
4
5
$gap ?= 64px
$tablet ?= 769px
$desktop ?= 1088px
$widescreen ?= 1280px
$fullhd ?= 1472px

Waline

使用最新版

node_modules\hexo-component-inferno\lib\view\comment\waline.js

1
2
jsUrl: helper.cdn('@waline/client', 'v2', 'dist/waline.js'),
cssUrl: helper.cdn('@waline/client', 'v2', 'dist/waline.css')

HTTPS

遇到This request has been blocked; the content must be served over HTTPS.

<head>下添加

<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"/>

themes\hexo-theme-icarus\layout\common\head.jsx

1
2
3
4
5
return <head>
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"/>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
...

添加备案号

themes\hexo-theme-icarus\layout\common\footer.jsx

1
2
3
4
5
6
7
8
9
<div class="level-mid" style="text-align:center;">
<p class="is-size-7">
<a href="https://beian.miit.gov.cn/" style="color:#606266" target="_blank">沪ICPxxxxxxxx号-1</a>
</p>
<p class="is-size-7">
<img no-lazy src="/img/备案图标.png"></img>
<a href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=沪公网安备xxxxxxxxx号" style="color:#606266" target="_blank">沪公网安备xxxxxxxxx号</a>
</p>
</div>

修改CDN

themes\hexo-theme-icarus\_config.yml

1
2
3
cdn: '[cdnjs]https://cdn.staticfile.org/${package}/${version}/${filename}'
fontcdn: ustc
concdn: 'https://cdn.staticfile.org/font-awesome/6.2.1/css/all.min.css'

themes\hexo-theme-icarus\layout\common\head.jsx这个font加载太慢了,直接注释掉

1
2
3
4
const fontCssUrl = {
// default: fontcdn('Ubuntu:wght@400;600&family=Source+Code+Pro', 'css2'),
cyberpunk: fontcdn('Oxanium:wght@300;400;600&family=Roboto+Mono', 'css2')
};

部署至阿里云OSS

参考资料

  1. Hexo 一键部署到阿里云 OSS 并设置浏览器缓存
  2. 前端静态资源缓存最优解以及max-age的陷阱
  3. 设计一个完美的HTTP缓存策略
  4. 阿里云 OSS+CDN 挂载静态网站(访问加速) http方式访问

代码

1
npm i hexo-deployer-ali-oss-extend --save

_config.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
deploy:
- type: ali-oss
region: "<您的oss 区域代码>"
accessKeyId: "<您的oss accessKeyId>"
accessKeySecret: "<您的oss accessKeySecret>"
bucket: "<您的bucket name>"
cacheControl:
images: "<图片文件HTTP响应头Cache-Control>,留空为no-cache"
css: "<CSS文件HTTP响应头Cache-Control>,留空为no-cache"
js: "<JS文件HTTP响应头Cache-Control>,留空为no-cache"
html: "<HTML文件HTTP响应头Cache-Control>,留空为no-cache"
other: "<其它文件HTTP响应头Cache-Control>,留空为no-cache"

阿里云函数计算部署Waline

阿里云函数+OSS+SQLite

都用阿里云函数了,推荐使用SQLite存储

  1. 根据阿里云函数计算部署创建云函数和OSS
  2. 根据配置OSS文件系统挂载OSS到云函数
  3. 上传waline.sqlite到OSS对应目录
  4. 参考SQLite配置环境变量
  5. 控制台npm install安装node包后部署

日志服务记录的时间和函数计算的时间不一致,可能是因为两者使用的时间格式和时区不一致。

函数计算默认以UTC时间运行,也就是0时区,即北京时间减去8个小时。例如北京时间每天12:00,转化为UTC时间就是每天04:00。您可以通过设置环境变量进行时区修改,例如,设置变量TZ的值为Asia/Shanghai后,函数计算的时区被修改为东8区,即北京时间。具体操作,请参见环境变量

LeanCloud

参考https://waline.js.org/guide/deploy/aliyun-fc.html

注意,由于oss_bucket不能重名,如果出现相关报错Please provide existed ossBucket under your account when code size is greater than 50M.

国际版(如果使用LeanCloud作为数据库)需要使用非大陆地域region,选择cn-hongkong

地区(region)目前支持:cn-beijing, cn-hangzhou, cn-shanghai, cn-qingdao, cn-zhangjiakou, cn-huhehaote, cn-shenzhen, cn-chengdu, cn-hongkong, ap-southeast-1, ap-southeast-2, ap-southeast-3, ap-southeast-5, ap-northeast-1, eu-central-1, eu-west-1, us-west-1, us-east-1, ap-south-1

修改s.ymlossBucket为一个没人用过的名字

部署完成后,请访问 <serverURL>/ui/register 进行注册。首个注册的人会被设定成管理员。AKISMET_KEY=false关闭垃圾检测,服务器在国外,比较慢。

busuanzi统计不显示的根本原因及解决办法

https://blog.csdn.net/weixin_44834205/article/details/126593378

live2d 插件导致问题:https://github.com/xiazeyu/live2d-widget.js/pull/61

网上搜到的很多解决办法是把 id="busuanzi_container_*" 删掉,这样当然就不会被隐藏了,只不过这个隐藏本意是在出错时不把错误或者无意义的内容显示给访客,保留这一行为还是挺好的

HTML Heading Tag 修改

对网站进行SEO优化,要求一个页面只有一个<h1></h1>,但文章撰写时,使用了多个一级标题,因此编写插件hexo-hxtag-fixer,把Markdown源文件的标题下降一级,例如#=>##。由于文章较多,手动修改麻烦,也不符合日常写作习惯,于是编写插件,在渲染前替换Markdown源文件的文本。

核心功能

1
2
hexo.extend.filter.register('before_post_render', filter);
hexo.extend.filter.register('after_render:html', filter);

使用过程发现,源文件渲染是有缓存的,调试时应采用hexo clean;hexo s

核心代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/* global hexo */ //https://github.com/uiolee/hexo-absolute
'use strict';

hexo.config.hxtag = Object.assign({
enable: true
}, hexo.config.hxtag);

const hxtag = hexo.config.hxtag;

const filter = require('./lib/filter');

if (hxtag.enable) {
//hexo.extend.filter.register('before_post_render', filter,1);
hexo.extend.filter.register('after_render:html', function (content, data) {
if (data.path == 'index.html') {
return content;
}
//<(h[1-6])([^>]*)>([\s\S]+?)<\/\1>
for (var i = 5; i >= 1; i--) {
var tag = "h" + (i+1);
var re = new RegExp("<(h"+String(i)+")([^>]*)>([\\s\\S]+?)</\\1>","g");
content = content.replace(re, "<"+tag+"$2>$3</"+tag+">");
}
var re = new RegExp("<(h2)([^>]*)>([\\s\\S]+?)</\\1>");
content = content.replace(re, "<h1$2>$3</h1>");
return content;
},1);
}

hexo-simple-mindmap插件导致网站加载缓慢

不同设备登录时,有时候会网站一直加载不出来,定位问题如下

发现来源于hexo-simple-mindmap插件。

该问题不一定复现,原因是dns缓存,需要浏览器清楚本地缓存及dns缓存才可复现,dns清除方式为chrome://net-internals/#dns

1
2
3
4
5
6
7
8
{% pullquote mindmap mindmap-md %}
- [在 Hexo 中使用思维导图](https://hunterx.xyz/use-mindmap-in-hexo.html)
- 前言
- 操作指南
- 准备需要的文件
- 为主题添加 CSS/JS 文件
- 使用方法
{% endpullquote %}

解决方式为替换node_modules\hexo-simple-mindmap\index.js中js的cdn源。

或者修改为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// kityminder-core.js
htmlTags = htmlTags + util.htmlTag('script', {
type: 'text/javascript',
src: 'https://unpkg.com/kityminder-core@1.4.50/dist/kityminder.core.min.js',
async: true
}, '')

// mindmap.js
htmlTags = htmlTags + util.htmlTag('script', {
defer: 'true',
type: 'text/javascript',
src: 'https://unpkg.com/hexo-simple-mindmap@' + version + '/dist/mindmap.min.js',
async: true
}, '')

// mindmap.css
htmlTags = htmlTags + util.htmlTag('link', {
rel: 'stylesheet',
type: 'text/css',
href: 'https://unpkg.com/hexo-simple-mindmap@' + version + '/dist/mindmap.min.css',
onload: "this.media='all'"
})

参考:css性能优化 hexo-util

不过我最后还是把资源放到了服务器上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// kity.js
htmlTags = htmlTags + util.htmlTag('script', {
type: 'text/javascript',
src: 'https://www.shjdgwj.cn/asset/js/kity.min.js',
async: true
}, '')

// kityminder-core.js
htmlTags = htmlTags + util.htmlTag('script', {
type: 'text/javascript',
src: 'https://www.shjdgwj.cn/asset/js/kityminder.core.min.js',
async: true
}, '')

// mindmap.js
htmlTags = htmlTags + util.htmlTag('script', {
defer: 'true',
type: 'text/javascript',
src: 'https://www.shjdgwj.cn/asset/js/mindmap.min.js',
async: true
}, '')

// mindmap.css
htmlTags = htmlTags + util.htmlTag('link', {
rel: 'stylesheet',
type: 'text/css',
href: 'https://www.shjdgwj.cn/asset/js/mindmap.min.css',
onload: "this.media='all'"
})
作者

GWJ

发布于

2021-02-04

更新于

2023-03-17

许可协议

评论