Icarus调教指北 - 我对主题的修改

本博客主题基于 imaegoo/hexo-theme-icarus 二次修改,本文章的内容理论上支持4.x以后的官方分支以及 imaegoo 的分支,如果遇到问题请自行调整

基于原始分支的修改

添加预加载

themes/icarus/layout/common/scripts.jsx中的 </Fragment> 前添加

1
<script src={cdn('instant.page', '5.1.1', 'instantpage.min.js')} type="module"></script>

目录固定

themes/icarus/source/js/main.js 中的 if ($toc.length > 0) 后添加

1
$toc.addClass('column-right is-sticky');   // 如果目录在左侧则改为 column-left

为了防止目录固定之后无法点击到较下方的项目,需要允许目录滚动

themes/icarus/include/style/widget.styl 添加

1
2
3
#toc  //目录可滚动
max-height: calc(100vh - 22px)
overflow-y: scroll

右侧边栏吸底

此处参考 imaegoo 的左侧边栏吸底,可添加在 themes/icarus/source/js/main.js 末尾;如果右侧边栏有后加载内容(如友链、最近评论)则应加在完成该操作之后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//右侧边栏吸底(无文章目录时生效)
var columnRight = $('.column-right')[0];

function fixRightColumnTop() {
// if SBP return
if ($(window).width() < 769) {
columnRight.style.top = null;
} else {
if (columnRight) {
columnRight.style.top = $(window).height() - columnRight.scrollHeight - 10 + 'px';
} else {
setTimeout(function () {
columnRight = $('.column-right')[0];
fixRightColumnTop();
}, 500);
}
}
}
if (!($('#toc').length > 0)) { // 无目录
fixRightColumnTop();
$(window).resize(fixRightColumnTop);
}

H标签美化

添加在 themes/icarus/source/css/default.styl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.content > h1 
padding: 0px 13px;
border-left: 8px solid #ed515191
.content > h2
padding:0px 12px;
border-left: 7px solid #BF51ED91
.content > h3
padding:0px 11px;
border-left: 6px solid #6495ed91
.content > h4
padding:0px 10px;
border-left: 5px solid #e2aa2b91
.content > h5
padding:0 19px;
border-left: 4px solid #64c1c191

图片懒加载

安装并配置 hexo-image-lazyload插件

1
$ npm install hexo-lazyload-image --save
1
2
3
4
5
6
lazyload:
enable: true
onlypost: false # optional
loadingImg: # optional eg ./images/loading.gif
isSPA: false # optional
preloadRatio: 3 # optional, default is 1

themes/icarus/source/js/main.js 添加代码以修复 lightGallery 兼容

1
2
3
4
// 懒加载修复
$(document).find('img[data-original]').each(function () {
$(this).parent().attr("href", $(this).attr("data-original"));
});

添加置顶文章标签

安装 hexo-generator-index-pin-top 然后为你需要置顶的文章添加 top 字段作为置顶权重

1
npm install hexo-generator-index-pin-top --save

themes/icarus/layout/common/article.jsx<div class="level-left"> 下方添加

1
{index && page.top ? <span class="level-item stick-top"> 置顶 </span> : null}

CSS 添加在 themes/icarus/source/css/default.styl

1
2
3
4
5
6
7
8
9
10
11
/* 置顶标签 */
.stick-top {
background-color: rgba(64, 158, 255, 0.13);
border: 1px solid rgba(64, 158, 255, 0.5);
border-radius: 2px;
color: #409eff;
display: inline-block;
padding: 0 0.5em;
font-size: 0.75em;
background-color: #f2f6fc;
}

如果你需要黑夜模式的 CSS ,请添加在themes/icarus/source/css/night.styl

1
2
3
4
5
6
7
8
9
10
/* 黑夜模式置顶标签 */
.stick-top {
border: none;
border-radius: 2px;
color: dark-font-color;
display: inline-block;
padding: 0 0.5em;
font-size: 0.75em;
background-color: dark-primary-color-hover;
}

添加 Qexo 友链侧边栏

themes/icarus/include/schema/common/widgets.jsonitems.oneOf 添加

1
2
3
{
"$ref": "/widget/qexo_friends.json"
}

themes/icarus/include/schema/widget/qexo_friends.json

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "/widget/qexo_friends.json",
"description": "Qexo friends links widget configurations",
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "qexo_friends"
}
},
"required": ["type"]
}

themes/icarus/layout/widget/qexo_friends.jsx 注意此处修改 https://yoursite.com 为你的 Qexo 部署地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const { URL } = require('url');
const { Component } = require('inferno');
const { cacheComponent } = require('hexo-component-inferno/lib/util/cache');

class QexoLinks extends Component {
render() {
const js = `loadSideBarFriends('qexo-sidebar-friends', 'https://yoursite.com');`;
return (
<div class="card widget">
<div class="card-content">
<div class="menu">
<h3 class="menu-label">友情链接</h3>
<ul class="menu-list qexo-sidebar-friends"></ul>
</div>
<script dangerouslySetInnerHTML={{ __html: js }}></script>
<a class="link-more button is-light is-small size-small" href="/links/">查看更多</a>
</div>
</div>
);
}
}


module.exports = QexoLinks;

themes/icarus/source/js/sidebar-friends.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
function loadSideBarFriends(id, url) {
var uri = url + "/pub/friends/";
var loadStyle = '<div class="qexo_loading"><div class="qexo_part"><div style="display: flex; justify-content: center"><div class="qexo_loader"><div class="qexo_inner one"></div><div class="qexo_inner two"></div><div class="qexo_inner three"></div></div></div></div><p style="text-align: center; display: block">友链加载中...</p></div>';
for(let i=0;i<document.getElementsByClassName(id).length;i++){
document.getElementsByClassName(id)[i].innerHTML = loadStyle;
}
document.getElementsByClassName(id)[1]
var ajax;
try {
// Firefox, Opera 8.0+, Safari
ajax = new XMLHttpRequest();
} catch (e) {
// Internet Explorer
try {
ajax = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
ajax = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
alert("糟糕,你的浏览器不能上传文件!");
return false;
}
}
}
ajax.open("get", uri, true);
ajax.setRequestHeader("Content-Type", "text/plain");
ajax.onreadystatechange = function () {
if (ajax.readyState == 4) {
if (ajax.status == 200) {
var res = JSON.parse(ajax.response);
if (res["status"]) {
var friends = res["data"];
for(let i=0;i<document.getElementsByClassName(id).length;i++){
document.getElementsByClassName(id)[i].innerHTML = '<ul class="menu-list">';
}
for (let i = 0; i < friends.length; i++) {
for(let j=0;j<document.getElementsByClassName(id).length;j++){
document.getElementsByClassName(id)[j].innerHTML += '<li><a class="level is-mobile is-mobile" href="'+friends[i]["url"]+'" target="_blank" rel="noopener"><span class="level-left"><span class="level-item">'+friends[i]["name"]+'</span></span><span class="level-right"><span class="level-item tag">'+friends[i]["url"].split('/')[2]+'</span></span></a></li>';
}
}
} else {
console.log(res["data"]["msg"]);
}
} else {
console.log("友链获取失败! 网络错误");
}
}
};
ajax.send(null);
}

themes/icarus/layout/common/head.jsx</head> 前添加

1
<script src="/js/sidebar-friends.js"></script>

添加 Qexo 友链申请页面

创建一个页面,其中填写

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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
{% raw %}
<article class="message is-info">
<div class="message-header">
申请友链
</div>
<div class="message-body">
<div class="form-ask-friend">
<div class="field">
<label class="label">名称</label>
<div class="control has-icons-left">
<input class="input" type="text" placeholder="您的站点名" id="friend-name" required>
<span class="icon is-small is-left">
<i class="fas fa-signature"></i>
</span>
</div>
</div>
<div class="field">
<label class="label">链接</label>
<div class="control has-icons-left">
<input class="input" type="url" placeholder="您网站首页的链接" id="friend-link" required>
<span class="icon is-small is-left">
<i class="fas fa-link"></i>
</span>
</div>
<p class="help ">请确保站点可访问!</p>
</div>
<div class="field">
<label class="label">图标</label>
<div class="control has-icons-left">
<input class="input" type="url" placeholder="您的网站图标(尽量为正圆形)" id="friend-icon" required>
<span class="icon is-small is-left">
<i class="fas fa-image"></i>
</span>
</div>
</div>
<div class="field">
<label class="label">描述</label>
<div class="control has-icons-left">
<input class="input" type="text" placeholder="请用一句话介绍您的站点" id="friend-des" required>
<span class="icon is-small is-left">
<i class="fas fa-info"></i>
</span>
</div>
</div>
<div class="field">
<div class="control">
<label class="checkbox">
<input type="checkbox" id="friend-check"/> 我提交的不是无意义信息
</label>
</div>
</div>
<div class="field is-grouped">
<div class="control">
<button class="button is-info" type="submit" onclick="askFriend(event)">申请友链</button>
</div>
</div>
</div>
</div>
</article>
<script src="https://recaptcha.net/recaptcha/api.js?render=你的reCpatchaV3密钥"></script>
<script>
function TestUrl(url) {
var Expression=/http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/;
var objExp=new RegExp(Expression);
if(objExp.test(url) != true){
return false;
}
return true;
}
function askFriend (event) {
let check = $("#friend-check").is(":checked");
let name = $("#friend-name").val();
let url = $("#friend-link").val();
let image = $("#friend-icon").val();
let des = $("#friend-des").val();
if(!check){
alert("请勾选\"我提交的不是无意义信息\"");
return;
}
if(!(name&&url&&image&&des)){
alert("信息填写不完整! ");
return;
}
if (!(TestUrl(url))){
alert("URL格式错误! 需要包含HTTP协议头! ");
return;
}
if (!(TestUrl(image))){
alert("图片URL格式错误! 需要包含HTTP协议头! ");
return;
}
event.target.classList.add('is-loading');
grecaptcha.ready(function() {
grecaptcha.execute('你的reCpatchaV3密钥', {action: 'submit'}).then(function(token) {
$.ajax({
type: 'get',
cache: false,
url: url,
dataType: "jsonp",
async: false,
processData: false,
//timeout:10000,
complete: function (data) {
if(data.status==200){
$.ajax({
type: 'POST',
dataType: "json",
data: {
"name": name,
"url": url,
"image": image,
"description": des,
"verify": token,
},
url: 'https://你的Qexo部署站点/pub/ask_friend/',
success: function (data) {
alert(data.msg);
}
});}
else{
alert("URL无法连通!");
}
event.target.classList.remove('is-loading');
}
});
});
});
}
</script>
{% endraw %}

会自动验证站点可连通性并提交到 Qexo 后台。注意需要依照提示配置好 reCaptcha V3 和你的 Qexo 站点链接

接入 Qexo 页面访问统计

themes/icarus/source/js/statistic.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
function loadStatistic(e) {
var t = e + "/pub/statistic/";

function qexoInner(a,b) {if (document.getElementById(a)) document.getElementById(a).innerHTML = b;}

function qexoFailed() {
var j = ["qexo-site-uv","qexo-site-pv","qexo-page-pv"]
for (var i = 0; i < j.length; i++) qexoInner(j[i],"请求失败");
}

fetch(t, {
referrerPolicy: "no-referrer-when-downgrade"
}).then(function (res) {
if (res.ok) {
res.json().then(function (e) {
if (e.status) {
qexoInner("qexo-site-uv", e.site_uv);
qexoInner("qexo-site-pv", e.site_pv);
qexoInner("qexo-page-pv", e.page_pv);
} else {
console.log(e.error);
qexoFailed()
}
})
} else {
qexoFailed()
}
}, function (ex) {
console.log('站点统计失败! 网络错误')
qexoFailed()
});
}

themes/icarus/layout/common/footer.jsx 你需要的位置添加

1
2
<span id="busuanzi_container_site_uv" style="display: inline;"><span id="qexo-site-uv"> Loading </span>个访客</span>
<div dangerouslySetInnerHTML={{ __html: '<script src="/js/statistic.js"></script><script>loadStatistic("https://my.oplog.cn")</script>'}} />

themes/icarus/layout/common/article.jsx{/* Visitor counter */} 下方三行改为

1
{!index ? <span id={url_for(page.link || page.path)} class="level-item leancloud_visitors" data-flag-title={page.title} dangerouslySetInnerHTML={{__html: '<i class="far fa-eye"></i>' + _p('plugin.visit_count', '  <span id="qexo-page-pv"><i class="fa fa-spinner fa-spin"></i></span>')}}></span> : null}

添加 Qexo 说说侧边栏

themes/icarus/include/schema/common/widgets.jsonitems.oneOf 添加

1
2
3
{
"$ref": "/widget/qexo_talks.json"
}

themes/icarus/include/schema/widget/qexo_talks.json

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "/widget/qexo_talks.json",
"description": "Qexo talks widget configurations",
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "qexo_talks"
}
},
"required": ["type"]
}

themes/icarus/layout/widget/qexo_talks.jsx 注意此处修改 https://yoursite.com 为你的 Qexo 部署地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const { URL } = require('url');
const { Component } = require('inferno');
const { cacheComponent } = require('hexo-component-inferno/lib/util/cache');

class QexoTalks extends Component {
render() {
const js = `loadSideBarTalks('qexo-sidebar-talks', 'https://yoursite.com', 5);`;
return (
<div class="card widget">
<div class="card-content">
<div class="menu">
<h3 class="menu-label">最近说说</h3>
<ul class="menu-list qexo-sidebar-talks"></ul>
</div>
<script dangerouslySetInnerHTML={{ __html: js }}></script>
<a class="link-more button is-light is-small size-small" href="/talks/">查看更多</a>
</div>
</div>
);
}
}


module.exports = QexoTalks;

themes/icarus/source/js/sidebar-friends.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
function loadSideBarTalks(id, url, limit) { //id=class name
var uri = url + "/pub/talks/?page=1&limit=" + limit;
var loadStyle = '<div class="qexo_loading"><div class="qexo_part"><div style="display: flex; justify-content: center"><div class="qexo_loader"><div class="qexo_inner one"></div><div class="qexo_inner two"></div><div class="qexo_inner three"></div></div></div></div><p style="text-align: center; display: block">说说加载中...</p></div>';
for (let i = 0; i < document.getElementsByClassName(id).length; i++) {
document.getElementsByClassName(id)[i].innerHTML = loadStyle;
}
document.getElementsByClassName(id)[1]
var ajax;
try {
// Firefox, Opera 8.0+, Safari
ajax = new XMLHttpRequest();
} catch (e) {
// Internet Explorer
try {
ajax = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
ajax = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
alert("糟糕,你的浏览器不能上传文件!");
return false;
}
}
}
ajax.open("get", uri, true);
ajax.setRequestHeader("Content-Type", "text/plain");
ajax.onreadystatechange = function () {
if (ajax.readyState == 4) {
if (ajax.status == 200) {
var res = JSON.parse(ajax.response);
if (res["status"]) {
var talks = res["data"];
for (let i = 0; i < document.getElementsByClassName(id).length; i++) {
document.getElementsByClassName(id)[i].innerHTML = '';
}
for (let i = 0; i < talks.length; i++) {
var item = talks[i];
var date = new Date(item.time * 1000);
for (let j = 0; j < document.getElementsByClassName(id).length; j++) {
document.getElementsByClassName(id)[j].innerHTML +=
'<article class="media"><div class="media-content">' +
'<p class="title"><a href="#' + item.id + '">' + changeContent(item.content) + '</a></p>' +
'<p class="date">' + item.tags.join() + ' / ' + date.getFullYear() + "-" +
(date.getMonth() < 9 ? 0 : "") + (date.getMonth() + 1) + "-" + date.getDate() + '</p>' +
'</div></article>';
}
}
} else {
console.log(res["data"]["msg"]);
}
} else {
console.log("友链获取失败! 网络错误");
}
}
};
ajax.send(null);
}

// 从 butterfly 主题借鉴
// https://github.com/jerryc127/hexo-theme-butterfly/blob/dev/layout/includes/third-party/newest-comments/twikoo-comment.pug
function changeContent(content) {
if (content === '') return content;
content = content.replace(/<[^>]+>/g, ''); // remove html tag
if (content.length > 150) {
content = content.substring(0, 150) + '...';
}
return content;
}

基于 Imaegoo 分支的修改

跟随系统切换黑夜模式

themes/icarus/source/js/imaegoo/night.js 中将 isNight && applyNight(isNight); 注释并在后方添加,请注意本方案较温和,仅在首次访问或访问时进行了模式更改时生效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var ifSysIsNight = window.matchMedia('(prefers-color-scheme: dark)');
if (isNight === null){
isNight = ifSysIsNight.matches ? true : false;
applyNight(isNight);
localStorage.setItem('night', isNight);
}
else{
isNight && applyNight(isNight);
}
ifSysIsNight.onchange = function (evt) {
isNight = evt.matches ? true : false;
applyNight(isNight);
localStorage.setItem('night', isNight);
}

最后

本篇文章修改较为仓促,可能存在疏漏,可以在评论区指出

Icarus调教指北 - 我对主题的修改

http://www.oplog.cn/archives/8962.html

作者

啊不都

发布于

2022-12-28

更新于

2024-03-08

许可协议

CC BY 4.0

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×