hexo插件

本地搜索

1
npm install --save hexo-generator-search

hexo

_config.yml

1
2
3
4
5
search:
path: search.json
field: all
content: true
limit: 1000

发布

prot不通

1
2
3
4
❯ mousepad ~/.ssh/config
Host github.com
Hostname ssh.github.com
Port 443
1
2
3
4
❯  ssh -T git@github.com
Warning: Permanently added 'github.com' (ED25519) to the list of known hosts.
Hi chengshea! You've successfully authenticated, but GitHub does not provide shell access.
❯ hexo d

搜索 DNS Resource Records

ip 配置到 hosts

主题spfk

_config.yml

1
search_box: true

左侧left-col.ejs

/hexo/themes/spfk/layout/_partial/left-col.ejs

1
2
3
4
5
<div id="id_search"   onclick = "document.getElementById('local_search').style.display='block'">
<span class="search-icon">
<i class="fa fa-search"> </i>
</span> 搜索
</div>

弹出层layout.ejs

/hexo/themes/spfk/layout/layout.ejs

1
2
3
4
5
6
<div id="local_search" class="search-popup" >
<div class="search-header">
<i class="fa fa-search"> </i> <input id="local-search-input" class="search-input" placeholder="搜索..." spellcheck="false" type="search"/>
</div>
<div id="local-search-result"></div>
</div>

/hexo/themes/spfk/layout/_partial/after-footer.ejs

引入search.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
<%- js('js/jquery-1.9.1.min') %>
<%- js('js/search') %>

<% if (theme.search_box) { %>
<script type="text/javascript">
var inputArea = document.querySelector("#local-search-input");
inputArea.onclick = function(){ getSearchFile(); this.onclick = null }
inputArea.onkeydown = function(){ if(event.keyCode == 13) return false }
var getSearchFile = function(){
searchFunc("<%= config.root %>" + "search.json", 'local-search-input', 'local-search-result');
}
$(document).on('click', function(e) {
var si= $(e.target).closest('#id_search').length;
var d= $(e.target).closest('#local_search').length;
if(si==1){
document.body.style.overflow='hidden';
}
if( si==0 && d==0){
document.body.style.overflow=''
$('#local_search').hide();
}

});

</script>
<% } %>
search.js

/hexo/themes/spfk/source/js/search.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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
var searchFunc = function (path, search_id, content_id) {
// 0x00. environment initialization
'use strict';
var $input = document.getElementById(search_id);
var $resultContent = document.getElementById(content_id);
$resultContent.innerHTML = "<ul><span class='local-search-empty'>首次搜索,正在载入索引文件,请稍后……<span></ul>";
$.ajax({
// 0x01. load xml file
url: path,
dataType: "json",
success: function (datas) {
$resultContent.innerHTML = "";
$input.addEventListener('input', function () {
// 0x03. parse query to keywords list
var str = '<ul class=\"search-result-list\">';
var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
$resultContent.innerHTML = "";
if (this.value.trim().length <= 0) {
return;
}
// 0x04. perform local searching
datas.forEach(function (data) {
var isMatch = true;
var content_index = [];
if (!data.title || data.title.trim() === '') {
data.title = "Untitled";
}
var orig_data_title = data.title.trim();
var data_title = orig_data_title.toLowerCase();
if (!data.content || data.content.trim() === '') {
console.log(data.content)//空文章
data.content = "no content";
}
var orig_data_content = data.content.trim().replace(/<[^>]+>/g, "");
var data_content = orig_data_content.toLowerCase();
var data_url = data.url;

var index_title = -1;
var index_content = -1;
var first_occur = -1;
// only match artiles with not empty contents
if (data_content !== '') {
keywords.forEach(function (keyword, i) {
index_title = data_title.indexOf(keyword);
index_content = data_content.indexOf(keyword);

if (index_title < 0 && index_content < 0) {
isMatch = false;
} else {
if (index_content < 0) {
index_content = 0;
}
if (i == 0) {
first_occur = index_content;
}
// content_index.push({index_content:index_content, keyword_len:keyword_len});
}
});
} else {
isMatch = false;
}
// 0x05. show search results
if (isMatch) {
str += "<li><a href='" + data_url + "' class='search-result-title' target='_blank'>" + orig_data_title + "</a>";
var content = orig_data_content;
if (first_occur >= 0) {
// cut out 100 characters
var start = first_occur - 20;
var end = first_occur + 10;

if (start < 0) {
start = 0;
}

if (start == 0) {
end = 100;
}

if (end > content.length) {
end = content.length;
}

var match_content = content.substr(start, end);

// highlight all keywords
keywords.forEach(function (keyword) {
var regS = new RegExp(keyword, "gi");
match_content = match_content.replace(regS, "<em class=\"search-keyword\">" + keyword + "</em>");
});

str += "<p class=\"search-result\">" + match_content + "...</p>"
}
str += "</li>";
}
});
str += "</ul>";
if (str.indexOf('<li>') === -1) {
return $resultContent.innerHTML = "<ul><span class='local-search-empty'>没有找到内容,请尝试更换检索词。<span></ul>";
}
$resultContent.innerHTML = str;
});
}
});
}
css

/hexo/themes/spfk/source/css/search.css

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

.search-popup {
display: none;
background: #32503d;
border-radius: 5px;
height: 80%;
left: calc(50% - 350px);
position: fixed;
top: 10%;
width: 700px;
z-index: 1500;
}

.search-popup .search-header {
background: #eee;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
display: flex;
padding: 5px;
}
.search-popup input.search-input {
background: transparent;
border: 0;
outline: 0;
width: 100%;
}


.search-popup ul.search-result-list {
margin: 0 5px;
padding: 0;
width: 100%;

}

ul.search-result-list li::marker {
content: '😩';
}


.search-popup p.search-result {
border-bottom: 2px dashed #7de485d4;
padding: 5px 0;
line-height: 21px;
}
.search-popup a.search-result-title {
font-weight: bold;
}
.search-popup .search-keyword {
border-bottom: 1px dashed #ff2a2a;
color: #ff2a2a;
font-weight: bold;
}
.search-popup #local-search-result{
display: flex;
height: calc(100% - 55px);
overflow: auto;
padding: 5px 25px;
}
.search-popup #no-result {
color: #ccc;
margin: auto;
}

live2d

helper

1
npm install --save hexo-helper-live2d

_config.yml

1
2
3
4
5
6
7
8
9
10
11
live2d:
enable: true
scriptFrom: local
model:
use: live2d-widget-model-hibiki #模型选择
display:
position: right #模型位置
width: 150 #模型宽度
height: 300 #模型高度
mobile:
show: false #是否在手机端显示

js 推荐

放在合适位置 footer.ejs

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
<script src="https://eqcn.ajz.miesnfu.com/wp-content/plugins/wp-3d-pony/live2dw/lib/L2Dwidget.min.js"></script>
<script>
L2Dwidget.init({
"model": {
       //jsonpath控制显示那个小萝莉模型
jsonPath: "https://unpkg.com/live2d-widget-model-haruto@1.0.5/assets/haruto.model.json",
"scale": 1
},
"display": {
"position": "right", //看板娘的表现位置
"width": 150, //小萝莉的宽度
"height": 300, //小萝莉的高度
"hOffset": 0,
"vOffset": -20
},
"mobile": {
"show": true,
"scale": 0.5
},
"react": {
"opacityDefault": 0.7,
"opacityOnHover": 0.2
}
});
</script>

hexo-blog-encrypt

加密doc https://github.com/D0n9X1n/hexo-blog-encrypt/blob/master/ReadMe.zh.md#%E4%BF%AE%E6%94%B9%E5%8A%A0%E5%AF%86%E6%A8%A1%E6%9D%BF

1
npm install --save hexo-blog-encrypt

单篇

1
2
3
4
5
6
7
---
title: Hello World
tags:
- 加密
date: 1022-02-30 21:12:21
password: 123 #添加该行配置密码访问
---

标签维度_config.yml

1
2
3
4
5
6
7
8
9
# 安全插件 hexo-blog-encrypt 配置
encrypt:
abstract: 有东西被加密了, 请输入密码查看.
message: 您好, 私密文章需要密码访问.
tags:
- {name: private-cs, password: cs@qazqwe;}
- {name: tagName, password: 密码@B}
wrong_pass_message: 抱歉, 这个密码看着不太对, 请再试试.
wrong_hash_message: 抱歉, 私密文章不能被校验, 不过您还是能看看解密后的内容.

文章底部版权声明

themes/spfk/layout/_partial/post/nav.ejs

1
<a href="<%- config.root %>" title="访问 <%= theme.author %> 的个人博客"><%= theme.author%></a>

hexo-generator-index

置顶逻辑

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
  const posts = locals.posts.sort(config.index_generator.order_by);
//添加置顶逻辑,文章添加top标记
posts.data = posts.data.sort(function(a, b) {
if(a.top && b.top) { // 两篇文章都有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的排在前面
return -1;
}
else if(!a.top && b.top) {
return 1;
}
else return b.date - a.date; //都没有top标签,最新的文章在前面
});
//注释原有逻辑
// sort(posts.data, (a, b) => (b.sticky || 0) - (a.sticky || 0));

title: xxx
permalink: xx/xx/
tags:
- xx
categories:
- xx
date: xxx
top: 8

置顶标志

spfk article.ejs

1
2
3
4
5
6
7
<% if (post.top){%>
<div class="article-pop-out tagcloud">
<a class="">
<p font-weight="bold" >置顶</p>
</a>
</div>
<% } %>

_config.yml

theme.excerpt_link

❯ zgrep “excerpt_link” *
article.ejs: <a <% if (!theme.excerpt_link){ %>class=”hidden”<% } %> href=”<%- url_for(post.path) %>#more”><%= theme.excerpt_link %> >>

搜索到 themes/spfk/layout/_partial/article.ejs

点击打赏
文章目录
  1. 1. 本地搜索
    1. 1.1. hexo
    2. 1.2. 发布
    3. 1.3. 主题spfk
      1. 1.3.1. _config.yml
      2. 1.3.2. 左侧left-col.ejs
      3. 1.3.3. 弹出层layout.ejs
      4. 1.3.4. 触发搜索 after-footer.ejs
        1. 1.3.4.1. 引入search.js
        2. 1.3.4.2. search.js
        3. 1.3.4.3. css
  2. 2. live2d
    1. 2.1. helper
    2. 2.2. js 推荐
  3. 3. hexo-blog-encrypt
    1. 3.0.1. 文章底部版权声明
  • 4. hexo-generator-index
    1. 4.1. 置顶逻辑
    2. 4.2. 置顶标志
  • 载入天数...载入时分秒... ,