hexo-theme-shokax 0.4.0-alpha.2 → 0.4.0-alpha.4

Sign up to get free protection for your applications and to get access to all the features.
package/_config.yml CHANGED
@@ -21,8 +21,6 @@ pwa:
21
21
 
22
22
  # 实验性特性
23
23
  experiments:
24
- gradient: false # 使用CSS渐变作为文章封面
25
- fixedCover: "" # 主页面cover(为空则使用bing随机图片)
26
24
  debug: false # 使用debug模式启动
27
25
  disableThemeComment: false # 禁用主题评论系统(一般用于关闭评论或让插件接管评论系统)
28
26
  usingRelative: false # _image.yml 使用相对路径
@@ -30,6 +28,11 @@ experiments:
30
28
  # 具体见https://docs.kaitaku.xyz/guide/theme.html#%E9%95%BF%E6%96%87%E7%AB%A0%E4%BC%98%E5%8C%96
31
29
  mobileWidth: 820px # 移动版和桌面版导航栏最短切换长度
32
30
 
31
+ homeConfig:
32
+ gradient: false # 使用CSS渐变作为文章封面
33
+ # fixedCover 性能比默认的更好,且开启时将启用LCP优化和预加载 TODO
34
+ fixedCover: "" # 主页面cover(为空则使用bing随机图片)
35
+
33
36
  # ShokaX 模块化分包引入设置
34
37
  # 请关闭所有不使用的模块以优化主题 js 体积和性能
35
38
  modules:
@@ -41,11 +44,17 @@ modules:
41
44
  quiz: true # 启用文章内问题扩展支持
42
45
  fancybox: true # 启用 fancybox 支持(不建议禁用)
43
46
 
47
+ styles:
48
+ postprocess: true # 启用后处理器
49
+ modules:
50
+ mermaid: false
51
+
44
52
  # 优化性能区
45
53
  performance:
46
54
  # 使用preconnect预加载的网址(不建议超过三个)
47
55
  preConnect:
48
56
  - "https://lf9-cdn-tos.bytecdntp.com"
57
+ - "https://at.alicdn.com"
49
58
  # 使用dns-prefetch预解析的网址
50
59
  dnsPrefetch:
51
60
 
@@ -1,41 +1,6 @@
1
1
  mixin CommentRender()
2
2
  != shokax_inject('comment')
3
- - var tk = theme?.twikoo?.enable,wl = theme?.waline?.enable
4
- if page.comment !== false && !theme.experiments.disableThemeComment
5
- if tk
6
- div(class="wrap" id="comments")
7
- script(type="text/javascript" data-pjax).
8
- setTimeout(function () {
9
- twikoo.init({
10
- envId: '#{ theme.twikoo.envId }',
11
- el: '#comments',
12
- region: '#{theme.twikoo.region}'
13
- })
14
- }, 1000)
15
- else if wl
16
- div(class="wrap" id="comments")
17
- - var locale = JSON.stringify(theme.waline.locale)
18
- - var emoji = JSON.stringify(theme.waline.emoji)
19
- - var meta = JSON.stringify(theme.waline.meta)
20
- - var requiredMeta = JSON.stringify(theme.waline.requiredMeta)
21
- script(type="module" data-pjax).
22
- import { init } from 'https://npm.webcache.cn/@waline/client@v2/dist/waline.mjs';
23
-
24
- setTimeout(function () {
25
- init({
26
- el: '#comments',
27
- serverURL: '#{theme.waline.serverURL.replace(/\/+$/, '')}',
28
- lang: '#{theme.waline.lang}',
29
- locale: !{locale},
30
- emoji: !{emoji},
31
- meta: !{meta},
32
- requiredMeta: !{requiredMeta},
33
- wordLimit: #{theme.waline.wordLimit},
34
- pageSize: #{theme.waline.pageSize},
35
- pageview: #{theme.waline.pageview},
36
- path: window.location.pathname,
37
- dark: 'html[data-theme="dark"]'
38
- });
39
- }, 1000)
3
+ if page.comment !== false
4
+ div(class="wrap" id="comments")
40
5
 
41
6
 
@@ -1,6 +1,6 @@
1
1
  include postmeta.pug
2
2
 
3
- mixin SMRender(item)
3
+ mixin SMRender(item, lazy)
4
4
  - var link1 = item.link || item.path
5
5
  - var gradient = theme?.experiments?.gradient
6
6
  if item.link
@@ -11,7 +11,10 @@ mixin SMRender(item)
11
11
  div(class="cover" style=`background: linear-gradient(to bottom right, ${random_color()}, ${random_color()});`)
12
12
  else
13
13
  div(class="cover")
14
- != _url(link1, '<img loading="lazy" data-src="'+ _cover(item) +'" alt="article cover">', {itemprop: 'url', title: postText})
14
+ if lazy
15
+ != _url(link1, '<img loading="lazy" decoding="async" data-src="'+ _cover(item) +'" alt="article cover">', {itemprop: 'url', title: postText})
16
+ else
17
+ != _url(link1, '<img loading="eager" decoding="async" src="'+ _cover(item) +'" alt="article cover">', {itemprop: 'url', title: postText})
15
18
  div(class="info")
16
19
  +PMRender(item)
17
20
  h3
@@ -34,7 +34,7 @@ div(class="status")
34
34
  if beianN && RC
35
35
  br
36
36
  a(target="_blank" href=`https://beian.mps.gov.cn/#/query/webSearch?code=${RC}`)
37
- img(src=theme.statics + theme.assets + '/' + theme.footer.icp.icon style="max-width: 2em;display:inline;" width="20" height="20")
37
+ img(loading="lazy" decoding="async" data-src=theme.statics + theme.assets + '/' + theme.footer.icp.icon style="max-width: 2em;display:inline;" width="20" height="20")
38
38
  != beianN
39
39
  != shokax_inject('status')
40
40
 
@@ -42,18 +42,11 @@ each dnsLink in dnslinks
42
42
  if fontConfig
43
43
  != _vendor_font()
44
44
  != _css('app.css')
45
-
46
- if theme.polyfill.enable
47
- script(src=`https://polyfill.io/v3/polyfill.min.js?features=${theme.polyfill.features}` defer)
48
-
49
- != vendor_js()
50
- != _js('siteInit.js')
45
+ != preloadjs()
51
46
 
52
47
  include pwa.pug
53
- if tk
54
- script(src=theme.twikoo.link )
55
- else if wl
56
- link(rel="stylesheet" href="https://npm.webcache.cn/@waline/client@v2/dist/waline.css" media="none" onload="this.media='all'")
48
+ if wl
49
+ link(rel="stylesheet" href="https://npm.webcache.cn/@waline/client@3.0.0-alpha.11/dist/waline.css" media="none" onload="this.media='all'")
57
50
 
58
51
  - var qw = theme?.qweather?.enable
59
52
  if qw
@@ -10,7 +10,7 @@ nav(id="nav")
10
10
  a(href=config.root rel="start")
11
11
  != alternate || title
12
12
  ul(class="right" id="rightNav")
13
- li(class="item theme" @click="changeThemeByBtn")
13
+ li(class="item theme")
14
14
  i(class="ic i-sun")
15
15
  li(class="item search")
16
16
  i(class="ic i-search")
@@ -35,18 +35,18 @@ html(lang=page.language?page.language:config.language, style=theme.grayMode ? 'f
35
35
 
36
36
  != partial('_partials/header.pug', {}, {cache: true})
37
37
  div(id="imgs" class="pjax")
38
- if theme.experiments.gradient || theme.experiments.fixedCover
38
+ if theme.homeConfig.gradient || theme.homeConfig.fixedCover
39
39
  //- cover不可用时用Bing随机图片代替
40
- - var coverImage = theme.experiments.fixedCover || "https://7ed.net/bing/api"
41
- img(src=coverImage)
40
+ - var coverImage = theme.homeConfig.fixedCover || "https://7ed.net/bing/api"
41
+ img(src=coverImage loading="eager" decoding="async" fetchpriority="high")
42
42
  else
43
43
  - var covers = _cover_index(page, 6)
44
44
  if covers.length === 6
45
45
  ul
46
46
  each image in covers
47
- li(class="item" data-background-image=image)
47
+ li(class="item" style=`background-image: url("${image}");`)
48
48
  else
49
- img(src=covers)
49
+ img(src=covers loading="eager" decoding="async" fetchpriority="high")
50
50
  div(id="waves")
51
51
  svg(class="waves" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto")
52
52
  defs
@@ -82,6 +82,7 @@ html(lang=page.language?page.language:config.language, style=theme.grayMode ? 'f
82
82
 
83
83
  script(data-config type="text/javascript").
84
84
  var LOCAL = {
85
+ ispost: !{is_post()},
85
86
  path: `#{_permapath(page.path)}`,
86
87
  favicon: {
87
88
  show: `#{__('favicon.show')}`,
@@ -118,10 +119,12 @@ html(lang=page.language?page.language:config.language, style=theme.grayMode ? 'f
118
119
  != partial('_partials/third-party/baidu-analytics.pug', {}, {cache: true})
119
120
  != partial('_partials/third-party/clarity.pug', {}, {cache: true})
120
121
  != partial('_partials/third-party/google-analytics.pug', {}, {cache: true})
121
- if theme.twikoo.enable
122
- != _new_comments('twikoo')
123
- else if theme.waline.enable
124
- != _new_comments('waline')
122
+
123
+ != vendor_js()
124
+ if theme.polyfill.enable
125
+ script(src=`https://polyfill.io/v3/polyfill.min.js?features=${theme.polyfill.features}` defer)
126
+
127
+ != _js('siteInit.js')
125
128
 
126
129
  != shokax_inject('bodyEnd')
127
130
 
@@ -12,13 +12,5 @@ div(class="meta")
12
12
  != __('post.edited')
13
13
  time(title=__('post.modified') + __('symbol.colon') + full_date(post.updated) itemprop="dateModified" datetime=moment(post.updated).format())
14
14
  != date(post.updated)
15
- if theme.waline.pageview && !theme.waline.enable && !theme.twikoo.enable
16
- script(type = "module" data-pjax).
17
- import { pageviewCount } from 'https://unpkg.com/@waline/client@2/dist/pageview.mjs';
18
-
19
- pageviewCount({
20
- serverURL: '#{theme.waline.serverURL}',
21
- path: window.location.pathname,
22
- });
23
15
 
24
16
  != shokax_inject('postMeta')
@@ -11,7 +11,7 @@ article(itemscope itemtype="http://schema.org/Article" class="post block" lang=t
11
11
  if post.photos && post.photos.length
12
12
  div(class="gallery" itemscope itemtype="http://schema.org/ImageGallery")
13
13
  each photo in post.photos
14
- img(loading="lazy" data-src=_image_url(photo, post.path) itemprop="contentUrl")
14
+ img(loading="lazy" decoding="async" data-src=_image_url(photo, post.path) itemprop="contentUrl")
15
15
  if theme.summary.enable && page.layout === 'post'
16
16
  div(class='tabs' id='summary')
17
17
  div(class="show-btn")
@@ -1,6 +1,6 @@
1
1
  div(class="author" itemprop="author" itemscope itemtype="http://schema.org/Person")
2
- img(loading="lazy" class="image" itemprop="image" alt=author
3
- data-src=url_for(theme.statics + theme.assets + '/'+ theme.sidebar.avatar))
2
+ img(loading="eager" decoding="async" class="image" itemprop="image" alt=author
3
+ src=url_for(theme.statics + theme.assets + '/'+ theme.sidebar.avatar))
4
4
  p(class="name" itemprop="name")
5
5
  != author
6
6
  div(class="description" itemprop="description")
package/layout/index.pug CHANGED
@@ -12,7 +12,7 @@ block content
12
12
  - var sticky = page.sticky.toArray()
13
13
  div(class="segments sticky")
14
14
  each post in sticky
15
- +SMRender(post)
15
+ +SMRender(post, false)
16
16
  if page.catlist.length > 0
17
17
  h2(class="divider")
18
18
  != __('index.category')
@@ -27,7 +27,7 @@ block content
27
27
  != __('index.posts')
28
28
  div(class="segments posts")
29
29
  each post in posts
30
- +SMRender(post)
30
+ +SMRender(post, true)
31
31
  include _partials/pagination.pug
32
32
 
33
33
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hexo-theme-shokax",
3
- "version": "0.4.0-alpha.2",
3
+ "version": "0.4.0-alpha.4",
4
4
  "description": "a hexo theme based on shoka",
5
5
  "main": "index.js",
6
6
  "repository": "https://github.com/theme-shoka-x/hexo-theme-shokaX",
@@ -43,6 +43,7 @@
43
43
  "quicklink": "^2.3.0",
44
44
  "theme-shokax-anime": "^0.0.6",
45
45
  "theme-shokax-pjax": "^0.0.3",
46
+ "twikoo": "^1.6.31",
46
47
  "unlazy": "^0.10.4"
47
48
  },
48
49
  "engines": {
@@ -47,7 +47,22 @@ hexo.extend.generator.register('script', function (locals) {
47
47
  audio: undefined,
48
48
  fireworks: (theme.fireworks && theme.fireworks.enable && theme.fireworks.options)
49
49
  ? theme.fireworks.options
50
- : undefined
50
+ : undefined,
51
+ waline: {
52
+ serverURL: theme.waline.serverURL,
53
+ lang: theme.waline.lang,
54
+ locale: theme.waline.locale,
55
+ emoji: theme.waline.emoji,
56
+ meta: theme.waline.meta,
57
+ requiredMeta: theme.waline.requiredMeta,
58
+ wordLimit: theme.waline.wordLimit,
59
+ pageSize: theme.waline.pageSize,
60
+ pageview: theme.waline.pageview
61
+ },
62
+ twikoo: {
63
+ envId: theme.twikoo.envId,
64
+ region: theme.twikoo.region
65
+ }
51
66
  };
52
67
  if (config?.algolia) {
53
68
  siteConfig.search = {
@@ -98,7 +113,10 @@ hexo.extend.generator.register('script', function (locals) {
98
113
  __shokax_tabs__: theme.modules.tabs ? 'true' : 'false',
99
114
  __shokax_quiz__: theme.modules.quiz ? 'true' : 'false',
100
115
  __shokax_fancybox__: theme.modules.fancybox ? 'true' : 'false',
101
- shokax_CONFIG: JSON.stringify(siteConfig)
116
+ __shokax_waline__: theme.waline.enable ? 'true' : 'false',
117
+ __shokax_twikoo__: theme.twikoo.enable ? 'true' : 'false',
118
+ shokax_CONFIG: JSON.stringify(siteConfig),
119
+ shokax_siteURL: "'" + config.url + "'"
102
120
  },
103
121
  alias: {
104
122
  'algoliasearch/lite': 'algoliasearch/dist/algoliasearch-lite.esm.browser.js'
@@ -133,8 +151,6 @@ hexo.extend.generator.register('script', function (locals) {
133
151
  }
134
152
  });
135
153
  }
136
- node_fs_1.default.unlinkSync(`./shokaxTemp/${file}`);
137
154
  });
138
- node_fs_1.default.rmSync('./shokaxTemp', { force: true, recursive: true });
139
155
  return res;
140
156
  });
@@ -7,78 +7,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  const package_json_1 = __importDefault(require("../../package.json"));
8
8
  const hexo_util_1 = require("hexo-util");
9
9
  const utils_1 = require("../utils");
10
+ // TODO 弃用函数
10
11
  hexo.extend.helper.register('_new_comments', function (mode) {
11
- const root = this.config.url.replace(/^(https?:\/\/)?[^\/]*/, '');
12
- if (mode === 'twikoo') {
13
- return `<script data-pjax type="module">
14
- let comments = []
15
- twikoo.getRecentComments({
16
- envId: "${hexo.theme.config?.twikoo?.envId}",
17
- pageSize: 10
18
- }).then(function (res) {
19
- res.forEach(function (item) {
20
- let cText = item.commentText
21
- if (item.commentText.length > 50) {
22
- cText = item.commentText.substring(0,50)+'...'
23
- }
24
- const siteLink = item.url + "#" + item.id
25
- comments.push({
26
- href: siteLink,
27
- nick: item.nick,
28
- time: item.relativeTime,
29
- text: cText
30
- })
31
- });
32
- Vue.createApp({
33
- data() {
34
- return {
35
- coms: comments,
36
- root: '${root}'
37
- }
38
- }
39
- }).mount('#new-comment')
40
- }).catch(function (err) {
41
- console.error(err)
42
- })
43
- </script>`;
44
- }
45
- else if (mode === 'waline') {
46
- return `
47
- <script type="module" data-pjax>
48
- let items = []
49
- import { RecentComments } from 'https://npm.webcache.cn/@waline/client@v2/dist/waline.mjs'
50
- RecentComments({
51
- serverURL: '${hexo.theme.config.waline.serverURL.replace(/\/+$/, '')}',
52
- count: 10,
53
- }).then(({ comments }) => {
54
- comments.forEach(function (item) {
55
- let cText = (item.orig.length > 50) ? item.orig.substring(0,50)+'...' : item.orig
56
- item.url = item.url.startsWith('/') ? item.url : '/' + item.url;
57
- const siteLink = item.url + "#" + item.objectId
58
- items.push({
59
- href: siteLink,
60
- nick: item.nick,
61
- time: item.insertedAt.split('T').shift(),
62
- text: cText
63
- })
64
- })
65
- Vue.createApp({
66
- data() {
67
- return {
68
- coms: items,
69
- root: '${root}'
70
- }
71
- }
72
- }).mount('#new-comment')
73
- }).catch(function (err) {
74
- console.error(err)
75
- })
76
- </script>
77
- `;
78
- }
79
- else {
80
- console.log(`${mode} is not supported recent comment`);
81
- }
12
+ return '';
82
13
  });
83
14
  hexo.extend.helper.register('_safedump', (source) => {
84
15
  return JSON.stringify(source);
@@ -122,17 +53,17 @@ hexo.extend.helper.register('_css', function (...urls) {
122
53
  return urls.map(url => (0, hexo_util_1.htmlTag)('link', {
123
54
  rel: 'stylesheet',
124
55
  href: hexo_util_1.url_for.call(this, `${statics}${css}/${url}?v=${package_json_1.default.version}`)
125
- })).join('');
56
+ }), '').join('');
126
57
  });
127
58
  hexo.extend.helper.register('_js', function (...urls) {
128
59
  const { statics, js } = hexo.theme.config;
129
- return urls.map(url => (0, hexo_util_1.htmlTag)('script', { src: hexo_util_1.url_for.call(this, `${statics}${js}/${url}?v=${package_json_1.default.version}`), type: 'module', fetchpriority: 'high' }, '')).join('');
60
+ return urls.map(url => (0, hexo_util_1.htmlTag)('script', { src: hexo_util_1.url_for.call(this, `${statics}${js}/${url}?v=${package_json_1.default.version}`), type: 'module', fetchpriority: 'high', defer: true }, '')).join('');
130
61
  });
131
62
  hexo.extend.helper.register('vendor_js', function () {
132
63
  const vendors = hexo.theme.config.vendors;
133
64
  let res = '';
134
65
  for (const jsSync in vendors.js) {
135
- res += (0, hexo_util_1.htmlTag)('script', { src: (0, utils_1.getVendorLink)(hexo, vendors.js[jsSync]) }, '');
66
+ res += (0, hexo_util_1.htmlTag)('script', { src: (0, utils_1.getVendorLink)(hexo, vendors.js[jsSync]), async: true }, '');
136
67
  }
137
68
  // for (const jsAsync in vendors.async_js) {
138
69
  // res += htmlTag('script', { src: getVendorLink(hexo, vendors.async_js[jsAsync]), async: true }, '')
@@ -1,7 +1,11 @@
1
1
  'use strict';
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  // @ts-ignore
4
7
  const hexo_util_1 = require("hexo-util");
8
+ const node_fs_1 = __importDefault(require("node:fs"));
5
9
  const randomServer = parseInt(String(Math.random() * 4), 10) + 1;
6
10
  const randomBG = function (count = 1, image_server = null, image_list = []) {
7
11
  let i;
@@ -48,6 +52,16 @@ const randomBG = function (count = 1, image_server = null, image_list = []) {
48
52
  }
49
53
  return parseImage(image_list[Math.floor(Math.random() * image_list.length)], 'mw690');
50
54
  };
55
+ hexo.extend.helper.register('preloadjs', function () {
56
+ const { statics, js } = hexo.theme.config;
57
+ let res = '';
58
+ node_fs_1.default.readdirSync('./shokaxTemp').forEach((file) => {
59
+ if (file.endsWith('.js')) {
60
+ res += (0, hexo_util_1.htmlTag)('link', { rel: 'modulepreload', href: hexo_util_1.url_for.call(this, `${statics}${js}/${file}`) }, '');
61
+ }
62
+ });
63
+ return res;
64
+ });
51
65
  // 注册hexo主题中的URL帮助方法
52
66
  hexo.extend.helper.register('_url', function (path, text, options = {}) {
53
67
  // 如果未提供URL路径,则返回
@@ -96,7 +110,7 @@ hexo.extend.helper.register('_cover_index', function (item) {
96
110
  return this._image_url(item.photos[0], item.path);
97
111
  }
98
112
  else {
99
- return randomBG(1, image_server, index_images.length === 0 ? image_list : index_images);
113
+ return randomBG(6, image_server, index_images.length === 0 ? image_list : index_images);
100
114
  }
101
115
  });
102
116
  // 注册hexo主题的永久链接帮助方法
@@ -37,6 +37,7 @@ const fs = __importStar(require("node:fs"));
37
37
  hexo.on('generateBefore', () => {
38
38
  // 加载`theme_injects`过滤器
39
39
  (0, injects_1.default)(hexo);
40
+ fs.rmSync('./shokaxTemp', { force: true, recursive: true });
40
41
  if (fs.existsSync('request.lock')) {
41
42
  fs.unlinkSync('request.lock');
42
43
  }
@@ -149,12 +149,12 @@ input, textarea {
149
149
  @font-face {
150
150
  font-family: 'ic';
151
151
  font-display: swap;
152
- src: url('//at.alicdn.com/t/c/font_' + $iconfont + '.eot');
153
- src: url('//at.alicdn.com/t/c/font_' + $iconfont + '.eot?#iefix') format('embedded-opentype'),
154
- url('//at.alicdn.com/t/c/font_' + $iconfont + '.woff2') format('woff2'),
155
- url('//at.alicdn.com/t/c/font_' + $iconfont + '.woff') format('woff'),
156
- url('//at.alicdn.com/t/c/font_' + $iconfont + '.ttf') format('truetype'),
157
- url('//at.alicdn.com/t/c/font_' + $iconfont + '.svg#ic') format('svg');
152
+ src: url('https://at.alicdn.com/t/c/font_' + $iconfont + '.eot');
153
+ src: url('https://at.alicdn.com/t/c/font_' + $iconfont + '.eot?#iefix') format('embedded-opentype'),
154
+ url('https://at.alicdn.com/t/c/font_' + $iconfont + '.woff2') format('woff2'),
155
+ url('https://at.alicdn.com/t/c/font_' + $iconfont + '.woff') format('woff'),
156
+ url('https://at.alicdn.com/t/c/font_' + $iconfont + '.ttf') format('truetype'),
157
+ url('https://at.alicdn.com/t/c/font_' + $iconfont + '.svg#ic') format('svg');
158
158
  }
159
159
 
160
160
  @font-face {
@@ -1,5 +1,7 @@
1
1
  import { CONFIG } from '../globals/globalVars'
2
- import { init, pageviewCount } from '@waline/client'
2
+ import { init, pageviewCount, RecentComments } from '@waline/client'
3
+
4
+ import { createApp } from 'vue'
3
5
 
4
6
  // await import('@waline/client/style')
5
7
  // fixme 处理样式引入问题
@@ -29,5 +31,30 @@ export const walinePageview = function () {
29
31
  }
30
32
 
31
33
  export const walineRecentComments = async function () {
32
-
34
+ const root = shokax_siteURL.replace(/^(https?:\/\/)?[^/]*/, '')
35
+ let items = []
36
+ const { comments } = await RecentComments({
37
+ serverURL: CONFIG.waline.serverURL.replace(/\/+$/, ''),
38
+ count: 10
39
+ })
40
+ comments.forEach(function (item) {
41
+ let cText = (item.orig.length > 50) ? item.orig.substring(0, 50) + '...' : item.orig
42
+ item.url = item.url.startsWith('/') ? item.url : '/' + item.url
43
+ const siteLink = item.url + '#' + item.objectId
44
+ items.push({
45
+ href: siteLink,
46
+ nick: item.nick,
47
+ // @ts-ignore
48
+ time: item.insertedAt.split('T').shift(),
49
+ text: cText
50
+ })
51
+ })
52
+ createApp({
53
+ data () {
54
+ return {
55
+ coms: items,
56
+ root
57
+ }
58
+ }
59
+ }).mount('#new-comment')
33
60
  }
@@ -0,0 +1,41 @@
1
+ import twikoo from 'twikoo'
2
+ import { CONFIG } from '../globals/globalVars'
3
+ import { createApp } from 'vue'
4
+
5
+ export const twikooComment = function () {
6
+ twikoo.init({
7
+ envId: CONFIG.twikoo.envId,
8
+ el: '#comments',
9
+ region: CONFIG.twikoo.region
10
+ })
11
+ }
12
+
13
+ export const twikooRecentComments = async function () {
14
+ let comments = []
15
+ const root = shokax_siteURL.replace(/^(https?:\/\/)?[^/]*/, '')
16
+ const res = await twikoo.getRecentComments({
17
+ envId: CONFIG.twikoo.envId,
18
+ pageSize: 10
19
+ })
20
+ res.forEach(function (item) {
21
+ let cText = item.commentText
22
+ if (item.commentText.length > 50) {
23
+ cText = item.commentText.substring(0, 50) + '...'
24
+ }
25
+ const siteLink = item.url + '#' + item.id
26
+ comments.push({
27
+ href: siteLink,
28
+ nick: item.nick,
29
+ time: item.relativeTime,
30
+ text: cText
31
+ })
32
+ })
33
+ createApp({
34
+ data () {
35
+ return {
36
+ coms: comments,
37
+ root
38
+ }
39
+ }
40
+ }).mount('#new-comment')
41
+ }
@@ -22,7 +22,7 @@ import {
22
22
  } from './globalVars'
23
23
  import { changeMetaTheme } from './themeColor'
24
24
  import { Loader } from './thirdparty'
25
- import {getHeight, setWidth} from '../library/proto'
25
+ import { getHeight, setWidth } from '../library/proto'
26
26
 
27
27
  export const resizeHandle = () => {
28
28
  // 获取 siteNav 的高度
@@ -119,5 +119,5 @@ export const visibilityListener = () => {
119
119
  }, 2000))
120
120
  break
121
121
  }
122
- })
122
+ }, { passive: true })
123
123
  }
@@ -30,6 +30,7 @@ declare interface EventTarget {
30
30
  type walineMeta = 'nick'|'mail'|'link'
31
31
 
32
32
  declare const LOCAL: {
33
+ ispost: boolean;
33
34
  path: string;
34
35
  ignores: Array<(uri:string)=>boolean>;
35
36
  audio: string[];
@@ -105,6 +106,10 @@ interface configType {
105
106
  pageSize: number
106
107
  pageview: boolean
107
108
  }
109
+ twikoo: {
110
+ envId: string
111
+ region: string
112
+ }
108
113
  walinePageView: boolean
109
114
  quicklink: {
110
115
  ignores: any
@@ -123,4 +128,6 @@ declare const __shokax_tabs__: boolean
123
128
  declare const __shokax_quiz__: boolean
124
129
  declare const __shokax_fancybox__: boolean
125
130
  declare const __shokax_waline__:boolean
131
+ declare const __shokax_twikoo__:boolean
126
132
  declare const shokax_CONFIG:configType
133
+ declare const shokax_siteURL:string
@@ -37,9 +37,9 @@ export const createChild = function (parent: HTMLElement, tag: string, obj: obje
37
37
  export const wrapObject = function (parent: HTMLElement, obj: any): void {
38
38
  const box = document.createElement('div')
39
39
  Object.assign(box, obj)
40
- parent.insertBefore(box, obj)
41
- parent.removeChild(obj)
42
- box.appendChild(obj)
40
+ parent.parentNode.insertBefore(box, parent)
41
+ parent.parentNode.removeChild(parent)
42
+ box.appendChild(parent)
43
43
  }
44
44
 
45
45
  export const getHeight = function (el: HTMLElement): number {
@@ -5,18 +5,8 @@ import { searchBox, configure, stats, hits, pagination } from 'instantsearch.js/
5
5
  import type { HitHighlightResult } from 'instantsearch.js/es/types/results'
6
6
  import instantsearch from 'instantsearch.js'
7
7
  import algoliasearch from 'algoliasearch/lite'
8
- import {createChild} from "../library/proto";
9
8
 
10
9
  export function algoliaSearch (pjax) {
11
- if (CONFIG.search === null) { return }
12
-
13
- if (!siteSearch) {
14
- setSiteSearch(createChild(BODY, 'div', {
15
- id: 'search',
16
- innerHTML: '<div class="inner"><div class="header"><span class="icon"><i class="ic i-search"></i></span><div class="search-input-container"></div><span class="close-btn"><i class="ic i-times-circle"></i></span></div><div class="results"><div class="inner"><div id="search-stats"></div><div id="search-hits"></div><div id="search-pagination"></div></div></div></div>'
17
- }))
18
- }
19
-
20
10
  const search = instantsearch({
21
11
  indexName: CONFIG.search.indexName,
22
12
  searchClient: algoliasearch(CONFIG.search.appID, CONFIG.search.apiKey),
@@ -104,16 +94,6 @@ export function algoliaSearch (pjax) {
104
94
 
105
95
  search.start()
106
96
 
107
- // Handle and trigger popup window
108
- $dom.each('.search', (element) => {
109
- element.addEventListener('click', () => {
110
- document.body.style.overflow = 'hidden'
111
- transition(siteSearch, 'shrinkIn', () => {
112
- $dom('.search-input').focus()
113
- }) // transition.shrinkIn
114
- })
115
- })
116
-
117
97
  // Monitor main search box
118
98
  const onPopupClose = () => {
119
99
  document.body.style.overflow = ''
@@ -76,6 +76,7 @@ export default function domInit () {
76
76
  root: null,
77
77
  threshold: 0.2
78
78
  }).observe(document.getElementById('waves'))
79
+
79
80
  // sakura在视口外时停止动画
80
81
  new IntersectionObserver(([entry]) => {
81
82
  if (entry.isIntersecting) {
@@ -40,6 +40,25 @@ export const siteRefresh = (reload) => {
40
40
  vendorJs('copy_tex')
41
41
  vendorCss('mermaid')
42
42
 
43
+ // 懒加载背景图
44
+ console.log('lazyBg')
45
+ const lazyBg = new IntersectionObserver(function (entries, observer) {
46
+ entries.forEach(entry => {
47
+ if (entry.isIntersecting) {
48
+ const el = entry.target as HTMLElement
49
+ el.style.backgroundImage = `url("${el.getAttribute('data-background-image')}")`
50
+ el.removeAttribute('data-background-image')
51
+ observer.unobserve(el)
52
+ }
53
+ })
54
+ }, {
55
+ root: null,
56
+ threshold: 0.2
57
+ })
58
+ document.querySelectorAll('[data-background-image]').forEach(el => {
59
+ lazyBg.observe(el)
60
+ })
61
+
43
62
  if (reload !== 1) {
44
63
  $dom.each('script[data-pjax]', pjaxScript)
45
64
  }
@@ -53,9 +72,47 @@ export const siteRefresh = (reload) => {
53
72
  sideBarTab()
54
73
  sidebarTOC()
55
74
 
56
- import('../page/post').then(({ postBeauty }) => {
57
- postBeauty()
58
- })
75
+ if (LOCAL.ispost) {
76
+ import('../page/post').then(({ postBeauty }) => {
77
+ postBeauty()
78
+ })
79
+
80
+ const comment = new IntersectionObserver((entries) => {
81
+ entries.forEach((entry) => {
82
+ if (entry.isIntersecting) {
83
+ if (__shokax_waline__) {
84
+ import('../components/comments').then(({ walinePageview, walineComment }) => {
85
+ walinePageview()
86
+ walineComment()
87
+ })
88
+ }
89
+ if (__shokax_twikoo__) {
90
+ import('../components/tcomments').then(({ twikooComment }) => {
91
+ twikooComment()
92
+ })
93
+ }
94
+ comment.disconnect()
95
+ }
96
+ })
97
+ }, {
98
+ root: null,
99
+ threshold: 0.2
100
+ })
101
+
102
+ comment.observe($dom('#copyright'))
103
+ }
104
+
105
+ if (__shokax_waline__) {
106
+ import('../components/comments').then(async ({ walinePageview, walineRecentComments }) => {
107
+ await walineRecentComments()
108
+ })
109
+ }
110
+
111
+ if (__shokax_twikoo__) {
112
+ import('../components/tcomments').then(async ({ twikooRecentComments }) => {
113
+ await twikooRecentComments()
114
+ })
115
+ }
59
116
 
60
117
  if (__shokax_tabs__) {
61
118
  tabFormat()
@@ -1,13 +1,16 @@
1
1
  import domInit from './domInit'
2
2
  import { pjaxReload, siteRefresh } from './refresh'
3
3
  import { cloudflareInit } from '../library/scriptPjax'
4
- import { CONFIG, pjax, setPjax } from '../globals/globalVars'
4
+ import { BODY, CONFIG, pjax, setPjax, setSiteSearch, siteSearch } from '../globals/globalVars'
5
5
  import { autoDarkmode, themeColorListener } from '../globals/themeColor'
6
6
  import { resizeHandle, scrollHandle, visibilityListener } from '../globals/handles'
7
7
  import { pagePosition } from '../globals/tools'
8
8
  import Pjax from 'theme-shokax-pjax'
9
9
  import { initVue } from '../library/vue'
10
10
  import { lazyLoad } from 'unlazy'
11
+ import { $dom } from '../library/dom'
12
+ import { createChild } from '../library/proto'
13
+ import { transition } from '../library/anime'
11
14
 
12
15
  const siteInit = () => {
13
16
  initVue()
@@ -36,10 +39,32 @@ const siteInit = () => {
36
39
  visibilityListener()
37
40
  }
38
41
  themeColorListener()
42
+
39
43
  if (__shokax_search__) {
40
- import('../page/search').then(({ algoliaSearch }) => {
41
- algoliaSearch(pjax)
42
- })
44
+ $dom('li.item.search > i').addEventListener('click', () => {
45
+ if (CONFIG.search === null) { return }
46
+
47
+ if (!siteSearch) {
48
+ setSiteSearch(createChild(BODY, 'div', {
49
+ id: 'search',
50
+ innerHTML: '<div class="inner"><div class="header"><span class="icon"><i class="ic i-search"></i></span><div class="search-input-container"></div><span class="close-btn"><i class="ic i-times-circle"></i></span></div><div class="results"><div class="inner"><div id="search-stats"></div><div id="search-hits"></div><div id="search-pagination"></div></div></div></div>'
51
+ }))
52
+ }
53
+
54
+ import('../page/search').then(({ algoliaSearch }) => {
55
+ algoliaSearch(pjax)
56
+ })
57
+
58
+ // Handle and trigger popup window
59
+ $dom.each('.search', (element) => {
60
+ element.addEventListener('click', () => {
61
+ document.body.style.overflow = 'hidden'
62
+ transition(siteSearch, 'shrinkIn', () => {
63
+ $dom('.search-input').focus()
64
+ }) // transition.shrinkIn
65
+ })
66
+ })
67
+ }, { once: true, capture: true })
43
68
  }
44
69
 
45
70
  if (__shokax_fireworks__) {
@@ -49,13 +74,21 @@ const siteInit = () => {
49
74
  }
50
75
  lazyLoad()
51
76
 
52
- window.addEventListener('scroll', scrollHandle)
77
+ window.addEventListener('scroll', scrollHandle, {
78
+ passive: true
79
+ })
53
80
 
54
- window.addEventListener('resize', resizeHandle)
81
+ window.addEventListener('resize', resizeHandle, {
82
+ passive: true
83
+ })
55
84
 
56
- window.addEventListener('pjax:send', pjaxReload)
85
+ window.addEventListener('pjax:send', pjaxReload, {
86
+ passive: true
87
+ })
57
88
 
58
- window.addEventListener('pjax:success', siteRefresh) // 默认会传入一个event参数
89
+ window.addEventListener('pjax:success', siteRefresh, {
90
+ passive: true
91
+ }) // 默认会传入一个event参数
59
92
 
60
93
  window.addEventListener('beforeunload', () => {
61
94
  pagePosition()
@@ -1,3 +0,0 @@
1
- @import "_variables.styl";
2
-
3
- @import "_mixins.styl";