hexo-theme-shokax 0.1.8 → 0.2.0-rc1
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +3 -10
- package/_config.yml +1 -3
- package/layout/_partials/post/footer.pug +10 -0
- package/layout/_partials/sidebar/menu.pug +15 -16
- package/package.json +7 -5
- package/scripts/filters/post.js +3 -7
- package/scripts/generaters/config.js +0 -1
- package/scripts/generaters/images.js +0 -1
- package/scripts/generaters/index.js +2 -3
- package/scripts/helpers/engine.js +31 -22
- package/source/js/_app/global.js +2 -2
- package/source/js/_app/player.js +3 -3
package/README.md
CHANGED
@@ -7,7 +7,6 @@
|
|
7
7
|
语言(language): 简体中文 | [English](./README_en.md) \
|
8
8
|
此项目是shoka的一个二次开发版(算精神续作),致力于提高性能和优化魔改体验 \
|
9
9
|
诞生原因是目前shoka已经两年没有更新了,积压了大量BUG和功能请求。\
|
10
|
-
`0.0.2-alpha2`开始,`lantern`和`qweather`已迁移为插件
|
11
10
|
|
12
11
|
shokaX的社区资源导航和插件仓库为[awesome-shokaX](https://github.com/zkz098/awesome-shokaX)
|
13
12
|
|
@@ -39,7 +38,7 @@ npm i shokax-cli --location=global
|
|
39
38
|
# hexo init 初始化环境
|
40
39
|
SXC install shokaX
|
41
40
|
```
|
42
|
-
[点此](https://docs.kaitaku.xyz/guide/#%E9%85%8D%E7%BD%AE%E4%B8%BB%E9%A2%98)以进行下一步配置
|
41
|
+
[点此](https://docs.kaitaku.xyz/guide/#%E9%85%8D%E7%BD%AE%E4%B8%BB%E9%A2%98)以进行下一步配置
|
43
42
|
|
44
43
|
github仓库建议通过右边的 releases 下载,步骤为:
|
45
44
|
- 点击 Releases 的 Latest 版本
|
@@ -71,14 +70,8 @@ GPL许可证主要目的是限制修改后的分发行为,避免未经许可
|
|
71
70
|
| Hexo | Hexo contributors | 为本项目提供了良好的基础 |
|
72
71
|
| hexo-theme-shoka | amehime | 本项目的父主题 |
|
73
72
|
|
74
|
-
##
|
75
|
-
shokaX
|
76
|
-
|
77
|
-
| 名称 | 站点 |
|
78
|
-
|:----------------------------------------|:---------------------------|
|
79
|
-
| Lavender | https://www.lavenderdh.cn/ |
|
80
|
-
| AdminZhang | https://www.a9-9.top/ |
|
81
|
-
| [D-Sketon](https://github.com/D-Sketon) | https://d-sketon.top/ |
|
73
|
+
## 开发者们
|
74
|
+
[![](https://contributors-img.web.app/image?repo=zkz098/hexo-theme-shokaX)](https://github.com/zkz098/hexo-theme-shokaX/graphs/contributors)
|
82
75
|
|
83
76
|
## 特别鸣谢
|
84
77
|
[<img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.png" width="25%">](https://jb.gg/OpenSourceSupport)
|
package/_config.yml
CHANGED
@@ -21,6 +21,7 @@ pwa:
|
|
21
21
|
|
22
22
|
# 实验性特性
|
23
23
|
experiments:
|
24
|
+
noIE: true # TODO 阻止IE浏览器访问(ShokaX不支持IE的任何版本)
|
24
25
|
noPlayer: false # 禁用音乐播放器
|
25
26
|
gradient: false # 使用CSS渐变作为文章封面
|
26
27
|
fixedCover: "" # 主页面cover(为空则使用bing随机图片)
|
@@ -404,6 +405,3 @@ vendors:
|
|
404
405
|
copy_tex: npm/katex@0.12.0/dist/contrib/copy-tex.min.js # ok
|
405
406
|
chart: npm/frappe-charts@1.5.0/dist/frappe-charts.min.iife.min.js # ok
|
406
407
|
|
407
|
-
qweather:
|
408
|
-
enable: false
|
409
|
-
key: "114514"
|
@@ -11,4 +11,14 @@ div(class="meta")
|
|
11
11
|
!= __('post.edited')
|
12
12
|
time(title=__('post.modified') + __('symbol.colon') + full_date(post.updated) itemprop="dateModified" datetime=moment(post.updated).format())
|
13
13
|
!= date(post.updated)
|
14
|
+
if theme.waline.pageview && !theme.waline.enable
|
15
|
+
script(type = "module" data-pjax).
|
16
|
+
import { pageviewCount } from 'https://unpkg.com/@waline/client/dist/pageview.mjs';
|
17
|
+
|
18
|
+
const path = document.getElementById("twikoo_visitors").getAttribute("data-path");
|
19
|
+
pageviewCount({
|
20
|
+
serverURL: '#{theme.waline.serverURL}',
|
21
|
+
path: path,
|
22
|
+
});
|
23
|
+
|
14
24
|
!= shokax_inject('postMeta')
|
@@ -1,5 +1,5 @@
|
|
1
|
-
mixin item(name, path, parent,
|
2
|
-
- var trimn = (str)=>{
|
1
|
+
mixin item(name, path, parent, sublist)
|
2
|
+
- var trimn = (str)=>{return str!=null?str.trim():"";}
|
3
3
|
- var path = path.split('||')
|
4
4
|
- var itemURL = path[0].trim()
|
5
5
|
- if (!itemURL.startsWith('http')){ itemURL = itemURL.replace('//', '/') }
|
@@ -12,19 +12,18 @@ mixin item(name, path, parent, dropdown, sublist)
|
|
12
12
|
!= menuIcon + menuText
|
13
13
|
else
|
14
14
|
!= _url(itemURL, menuIcon + menuText, {rel: 'section'})
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
!= _url(itemURL, menuIcon + menuText, {rel: 'section'})
|
15
|
+
ul(class="submenu")
|
16
|
+
each subvalue, subname in sublist
|
17
|
+
- var path = subvalue.split('||')
|
18
|
+
- var itemURL = path[0].trim()
|
19
|
+
- if (itemURL==='/') itemURL='javascript:void(0)'
|
20
|
+
- var menuText = __('menu.' + subname).replace('menu.', '')
|
21
|
+
if subname == 'default'
|
22
|
+
- var menuText = __('menu.' + name).replace('menu.', '')
|
23
|
+
else
|
24
|
+
- var menuIcon = '<i class="ic i-' + trimn(path[1]) + '"></i>'
|
25
|
+
li(class="item")
|
26
|
+
!= _url(itemURL, menuIcon + menuText, {rel: 'section'})
|
28
27
|
else
|
29
28
|
li(class="item")
|
30
29
|
!= _url(itemURL, menuIcon + menuText, {rel: 'section'})
|
@@ -33,6 +32,6 @@ each value, name in theme.menu
|
|
33
32
|
if value == '[object Object]'
|
34
33
|
each subvalue, subname in value
|
35
34
|
if subname == 'default'
|
36
|
-
+item(name, subvalue, true,
|
35
|
+
+item(name, subvalue, true, value)
|
37
36
|
else
|
38
37
|
+item(name, value)
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "hexo-theme-shokax",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.2.0-rc1",
|
4
4
|
"description": "a hexo theme based on shoka",
|
5
5
|
"main": "index.js",
|
6
6
|
"repository": "https://github.com/zkz098/hexo-theme-shokaX",
|
@@ -19,10 +19,10 @@
|
|
19
19
|
"@types/jquery": "^3.5.16",
|
20
20
|
"@types/js-yaml": "^4.0.5",
|
21
21
|
"@types/lozad": "^1.16.1",
|
22
|
-
"@types/node": "^18.
|
22
|
+
"@types/node": "^18.14.1",
|
23
23
|
"@types/shelljs": "^0.8.11",
|
24
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
25
|
-
"@typescript-eslint/parser": "^5.
|
24
|
+
"@typescript-eslint/eslint-plugin": "^5.53.0",
|
25
|
+
"@typescript-eslint/parser": "^5.53.0",
|
26
26
|
"@vuepress/client": "2.0.0-beta.60",
|
27
27
|
"eslint": "^8.34.0",
|
28
28
|
"eslint-config-standard": "^17.0.0",
|
@@ -30,10 +30,12 @@
|
|
30
30
|
"eslint-plugin-n": "^15.6.1",
|
31
31
|
"eslint-plugin-promise": "^6.1.1",
|
32
32
|
"eslint-plugin-vue": "^9.9.0",
|
33
|
+
"hexo-fs": "^4.1.1",
|
34
|
+
"hexo-util": "^3.0.1",
|
33
35
|
"typescript": "^4.9.5",
|
34
36
|
"vue": "^3.2.47",
|
35
37
|
"vuepress": "2.0.0-beta.60",
|
36
|
-
"vuepress-plugin-sitemap2": "2.0.0-beta.
|
38
|
+
"vuepress-plugin-sitemap2": "2.0.0-beta.181"
|
37
39
|
},
|
38
40
|
"dependencies": {
|
39
41
|
"js-yaml": "^4.1.0"
|
package/scripts/filters/post.js
CHANGED
@@ -1,21 +1,17 @@
|
|
1
|
+
/* global hexo */
|
1
2
|
'use strict'
|
2
3
|
|
3
4
|
hexo.extend.filter.register('after_post_render', data => {
|
4
5
|
const { config } = hexo
|
5
|
-
const theme = hexo.theme.config
|
6
6
|
|
7
7
|
data.content = data.content.replace(/(<img[^>]*) src=/img, '$1 data-src=')
|
8
8
|
|
9
|
-
const
|
10
|
-
// eslint-disable-next-line n/no-deprecated-api
|
11
|
-
const siteHost = url.parse(config.url).hostname || config.url
|
9
|
+
const siteHost = new URL(config.url).hostname || config.url
|
12
10
|
data.content = data.content.replace(/<a[^>]* href="([^"]+)"[^>]*>([^<]*)<\/a>/img, (match, href, html) => {
|
13
|
-
// Exit if the href attribute doesn't exists.
|
14
11
|
if (!href) return match
|
15
12
|
|
16
13
|
// Exit if the url has same host with `config.url`, which means it's an internal link.
|
17
|
-
|
18
|
-
const link = url.parse(href)
|
14
|
+
const link = new URL(href, config.url)
|
19
15
|
if (!link.protocol || link.hostname === siteHost) return match
|
20
16
|
|
21
17
|
return `<span class="exturl" data-url="${Buffer.from(href).toString('base64')}">${html}</span>`
|
@@ -14,7 +14,6 @@ hexo.extend.generator.register('index', function (locals) {
|
|
14
14
|
const catlist = []
|
15
15
|
let pages
|
16
16
|
const config = hexo.config
|
17
|
-
const theme = hexo.theme.config
|
18
17
|
const sticky = locals.posts.find({ sticky: true }).sort(config.index_generator.order_by)
|
19
18
|
const posts = locals.posts.find({ sticky: { $exists: false } }).sort(config.index_generator.order_by)
|
20
19
|
const paginationDir = config.pagination_dir || 'page'
|
@@ -69,9 +68,9 @@ hexo.extend.generator.register('index', function (locals) {
|
|
69
68
|
cat.subs = child.sort({ name: 1 }).limit(6).toArray()
|
70
69
|
pl = Math.max(0, pl - child.length)
|
71
70
|
if (pl > 0) {
|
72
|
-
//
|
71
|
+
// TODO 需要测试
|
73
72
|
cat.subs.push.apply(cat.subs, cat.posts.sort({ title: 1 }).filter(function (item, i) {
|
74
|
-
|
73
|
+
return item.categories.last()._id === cat._id
|
75
74
|
}).limit(pl).toArray())
|
76
75
|
}
|
77
76
|
} else {
|
@@ -3,10 +3,8 @@
|
|
3
3
|
'use strict'
|
4
4
|
|
5
5
|
const { htmlTag, url_for } = require('hexo-util')
|
6
|
-
const url = require('url')
|
7
|
-
const crypto = require('crypto')
|
8
6
|
|
9
|
-
const randomServer = parseInt(Math.random() * 4, 10) + 1
|
7
|
+
const randomServer = parseInt(String(Math.random() * 4), 10) + 1
|
10
8
|
|
11
9
|
const randomBG = function (count = 1, image_server = null, image_list = []) {
|
12
10
|
let i
|
@@ -53,24 +51,27 @@ const randomBG = function (count = 1, image_server = null, image_list = []) {
|
|
53
51
|
return parseImage(image_list[Math.floor(Math.random() * image_list.length)], 'mw690')
|
54
52
|
}
|
55
53
|
|
54
|
+
// 注册hexo主题中的URL帮助方法
|
56
55
|
hexo.extend.helper.register('_url', function (path, text, options = {}) {
|
56
|
+
// 如果未提供URL路径,则返回
|
57
57
|
if (!path) { return }
|
58
58
|
|
59
|
+
// 获取hexo配置和URL路径信息
|
59
60
|
const { config } = this
|
60
|
-
|
61
|
-
const
|
62
|
-
// eslint-disable-next-line n/no-deprecated-api
|
63
|
-
const siteHost = url.parse(config.url).hostname || config.url
|
61
|
+
const data = new URL(path, hexo.config.url)
|
62
|
+
const siteHost = new URL(config.url).hostname || config.url
|
64
63
|
|
64
|
+
// 获取主题配置
|
65
65
|
const theme = hexo.theme.config
|
66
66
|
let exturl = ''
|
67
67
|
let tag = 'a'
|
68
68
|
let attrs = { href: url_for.call(this, path) }
|
69
69
|
|
70
|
-
//
|
70
|
+
// 如果启用了 `exturl`,则只为外部链接设置spanned链接。
|
71
71
|
if (theme.exturl && data.protocol && data.hostname !== siteHost) {
|
72
72
|
tag = 'span'
|
73
73
|
exturl = 'exturl'
|
74
|
+
// 编码URL字符串,并将其存储在数据属性中。
|
74
75
|
const encoded = Buffer.from(path).toString('base64')
|
75
76
|
attrs = {
|
76
77
|
class: exturl,
|
@@ -80,8 +81,8 @@ hexo.extend.helper.register('_url', function (path, text, options = {}) {
|
|
80
81
|
|
81
82
|
for (const key in options) {
|
82
83
|
/**
|
83
|
-
*
|
84
|
-
*
|
84
|
+
* 如果选项包含 `class` 属性,则将其添加到 `exturl` 类中(如果启用了 `exturl` 选项)。
|
85
|
+
* 否则,将其添加到属性集中。
|
85
86
|
*/
|
86
87
|
if (exturl !== '' && key === 'class') {
|
87
88
|
attrs[key] += ' ' + options[key]
|
@@ -94,20 +95,21 @@ hexo.extend.helper.register('_url', function (path, text, options = {}) {
|
|
94
95
|
attrs.class = attrs.class.join(' ')
|
95
96
|
}
|
96
97
|
|
97
|
-
//
|
98
|
+
// 如果是外部链接,则重写属性
|
98
99
|
if (data.protocol && data.hostname !== siteHost) {
|
99
100
|
attrs.external = null
|
100
101
|
|
101
102
|
if (!theme.exturl) {
|
102
|
-
//
|
103
|
+
// 仅需要为简单链接重写/添加属性。
|
103
104
|
attrs.rel = 'noopener'
|
104
105
|
attrs.target = '_blank'
|
105
106
|
} else {
|
106
|
-
//
|
107
|
+
// 在主菜单中移除 `exturl` 的 rel 属性。
|
107
108
|
attrs.rel = null
|
108
109
|
}
|
109
110
|
}
|
110
111
|
|
112
|
+
// 返回HTML标记字符串
|
111
113
|
return htmlTag(tag, attrs, decodeURI(text), false)
|
112
114
|
})
|
113
115
|
|
@@ -123,7 +125,7 @@ hexo.extend.helper.register('_image_url', function (img, path = '') {
|
|
123
125
|
})
|
124
126
|
|
125
127
|
hexo.extend.helper.register('_cover', function (item, num) {
|
126
|
-
const {
|
128
|
+
const { image_server, image_list } = hexo.theme.config
|
127
129
|
|
128
130
|
if (item.cover) {
|
129
131
|
return this._image_url(item.cover, item.path)
|
@@ -134,20 +136,17 @@ hexo.extend.helper.register('_cover', function (item, num) {
|
|
134
136
|
}
|
135
137
|
})
|
136
138
|
|
137
|
-
//
|
138
|
-
hexo.extend.helper.register('_md5', function (path) {
|
139
|
-
const str = url_for.call(this, path)
|
140
|
-
str.replace('index.html', '')
|
141
|
-
return crypto.createHash('md5').update(str).digest('hex')
|
142
|
-
})
|
143
|
-
|
139
|
+
// 注册hexo主题的永久链接帮助方法
|
144
140
|
hexo.extend.helper.register('_permapath', function (str) {
|
145
|
-
//
|
141
|
+
// 获取hexo的永久链接配置
|
146
142
|
const { permalink } = hexo.config
|
143
|
+
// 将输入字符串中的'index.html'替换为空字符串
|
147
144
|
let url = str.replace(/index\.html$/, '')
|
145
|
+
// 如果永久链接不以'.html'结尾,将输入字符串中的'.html'替换为空字符串
|
148
146
|
if (!permalink.endsWith('.html')) {
|
149
147
|
url = url.replace(/\.html$/, '')
|
150
148
|
}
|
149
|
+
// 返回处理后的URL字符串
|
151
150
|
return url
|
152
151
|
})
|
153
152
|
|
@@ -158,21 +157,31 @@ hexo.extend.helper.register('canonical', function () {
|
|
158
157
|
/**
|
159
158
|
* Get page path given a certain language tag
|
160
159
|
*/
|
160
|
+
// 注册hexo主题的国际化路径帮助方法
|
161
161
|
hexo.extend.helper.register('i18n_path', function (language) {
|
162
|
+
// 获取当前页面的path和lang
|
162
163
|
const { path, lang } = this.page
|
164
|
+
// 如果path以lang开头,则截取掉lang部分,作为基础路径
|
163
165
|
const base = path.startsWith(lang) ? path.slice(lang.length + 1) : path
|
166
|
+
// 通过调用url_for方法,生成国际化路径
|
164
167
|
return url_for.call(this, `${this.languages.indexOf(language) === 0 ? '' : '/' + language}/${base}`)
|
165
168
|
})
|
166
169
|
|
167
170
|
/**
|
168
171
|
* Get the language name
|
169
172
|
*/
|
173
|
+
// 注册hexo主题的语言名称帮助方法
|
170
174
|
hexo.extend.helper.register('language_name', function (language) {
|
175
|
+
// 从主题配置中获取指定语言的名称
|
171
176
|
const name = hexo.theme.i18n.__(language)('name')
|
177
|
+
// 如果名称为默认值'name',则返回语言代码,否则返回语言名称
|
172
178
|
return name === 'name' ? language : name
|
173
179
|
})
|
174
180
|
|
175
181
|
hexo.extend.helper.register('random_color', function () {
|
182
|
+
/**
|
183
|
+
@type {number[]}
|
184
|
+
*/
|
176
185
|
const arr = []
|
177
186
|
for (let i = 0; i < 3; i++) {
|
178
187
|
arr.push(Math.floor(Math.random() * 128 + 128))
|
package/source/js/_app/global.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
const statics = CONFIG.statics.indexOf('//') > 0 ? CONFIG.statics : CONFIG.root;
|
2
|
-
const scrollAction = { x:
|
2
|
+
const scrollAction = { x: 0, y: 0 };
|
3
3
|
let diffY = 0;
|
4
4
|
let originTitle, titleTime;
|
5
5
|
const BODY = document.getElementsByTagName('body')[0];
|
@@ -53,7 +53,7 @@ const lazyload = lozad('img, [data-background-image]', {
|
|
53
53
|
}
|
54
54
|
});
|
55
55
|
const Loader = {
|
56
|
-
timer:
|
56
|
+
timer: undefined,
|
57
57
|
lock: false,
|
58
58
|
show: function () {
|
59
59
|
clearTimeout(this.timer);
|
package/source/js/_app/player.js
CHANGED
@@ -231,7 +231,7 @@ const mediaPlayer = function (t, config) {
|
|
231
231
|
const el = playlist.el;
|
232
232
|
playlist.data.map(function (item, index) {
|
233
233
|
if (item.el) {
|
234
|
-
return;
|
234
|
+
return null;
|
235
235
|
}
|
236
236
|
const id = 'list-' + t.player._id + '-' + item.group;
|
237
237
|
let tab = $dom('#' + id);
|
@@ -320,7 +320,7 @@ const mediaPlayer = function (t, config) {
|
|
320
320
|
}, 300);
|
321
321
|
}
|
322
322
|
};
|
323
|
-
|
323
|
+
const option = {
|
324
324
|
type: 'audio',
|
325
325
|
mode: 'random',
|
326
326
|
btns: ['play-pause', 'music'],
|
@@ -345,7 +345,7 @@ const mediaPlayer = function (t, config) {
|
|
345
345
|
}
|
346
346
|
}
|
347
347
|
};
|
348
|
-
|
348
|
+
const utils = {
|
349
349
|
random: function (len) {
|
350
350
|
return Math.floor((Math.random() * len));
|
351
351
|
},
|