hexo-theme-stellar 1.33.1 → 1.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.md +2 -0
  2. package/_config.yml +19 -14
  3. package/layout/_partial/comments/artalk/script.ejs +56 -41
  4. package/layout/_partial/comments/beaudar/script.ejs +35 -20
  5. package/layout/_partial/comments/giscus/script.ejs +34 -19
  6. package/layout/_partial/comments/twikoo/script.ejs +29 -14
  7. package/layout/_partial/comments/utterances/script.ejs +35 -20
  8. package/layout/_partial/comments/waline/script.ejs +40 -28
  9. package/layout/_partial/cover/wiki_cover.ejs +1 -1
  10. package/layout/_partial/head.ejs +53 -7
  11. package/layout/_partial/scripts/defines.ejs +21 -3
  12. package/layout/_partial/scripts/lazyload.ejs +2 -2
  13. package/layout/_partial/scripts/services.ejs +101 -41
  14. package/layout/_partial/scripts/utils.ejs +100 -4
  15. package/layout/_partial/sidebar/index_leftbar.ejs +3 -0
  16. package/layout/_partial/sidebar/search.ejs +3 -0
  17. package/layout/_partial/widgets/ghuser.ejs +18 -4
  18. package/layout/_partial/widgets/linklist.ejs +1 -1
  19. package/layout/_partial/widgets/timeline.ejs +36 -33
  20. package/layout/_plugins/copycode.ejs +9 -5
  21. package/layout/_plugins/mermaid.ejs +28 -24
  22. package/layout/_plugins/scrollreveal.ejs +14 -13
  23. package/layout/_plugins/swiper.ejs +2 -2
  24. package/layout/index.ejs +4 -2
  25. package/layout/index_topic.ejs +4 -2
  26. package/layout/index_wiki.ejs +6 -4
  27. package/layout/layout.ejs +2 -2
  28. package/package.json +5 -2
  29. package/scripts/commands/new-note.js +49 -0
  30. package/scripts/events/index.js +2 -1
  31. package/scripts/events/lib/doc_tree.js +7 -4
  32. package/scripts/events/lib/merge_posts.js +3 -1
  33. package/scripts/events/lib/notebooks.js +5 -3
  34. package/scripts/events/lib/path_normalize.js +22 -0
  35. package/scripts/filters/lib/img_onerror.js +0 -2
  36. package/scripts/generators/search.js +3 -1
  37. package/scripts/helpers/json_ld.js +14 -10
  38. package/scripts/helpers/pretty_url.js +12 -8
  39. package/scripts/lib/path_utils.js +24 -0
  40. package/scripts/tags/lib/chat.js +16 -9
  41. package/scripts/tags/lib/frame.js +2 -1
  42. package/scripts/tags/lib/image.js +6 -5
  43. package/scripts/tags/lib/link.js +6 -4
  44. package/scripts/tags/lib/timeline.js +101 -79
  45. package/source/css/_common/canonical.styl +11 -6
  46. package/source/css/_common/highlight.styl +4 -1
  47. package/source/css/_common/html.styl +4 -0
  48. package/source/css/_common/loading.styl +5 -1
  49. package/source/css/_components/md.styl +1 -0
  50. package/source/css/_components/pages/article-story.styl +2 -0
  51. package/source/css/_components/partial/article-footer.styl +1 -0
  52. package/source/css/_components/partial/navbar.styl +2 -0
  53. package/source/css/_components/sidebar/menu.styl +1 -0
  54. package/source/css/_components/sidebar/search.styl +4 -0
  55. package/source/css/_components/sidebar/sidebar.styl +12 -5
  56. package/source/css/_components/tag-plugins/chat.styl +6 -8
  57. package/source/css/_components/tag-plugins/folding.styl +1 -0
  58. package/source/css/_components/tag-plugins/gallery.styl +2 -0
  59. package/source/css/_components/tag-plugins/grid.styl +1 -0
  60. package/source/css/_components/tag-plugins/image.styl +3 -0
  61. package/source/css/_components/tag-plugins/link.styl +1 -0
  62. package/source/css/_components/tag-plugins/navbar.styl +15 -13
  63. package/source/css/_components/tag-plugins/note.styl +1 -0
  64. package/source/css/_components/tag-plugins/okr.styl +1 -0
  65. package/source/css/_components/tag-plugins/sites.styl +2 -0
  66. package/source/css/_components/tag-plugins/timeline.styl +9 -0
  67. package/source/css/_components/tag-plugins/vote.styl +2 -0
  68. package/source/css/_components/widgets/components.styl +1 -0
  69. package/source/css/_components/widgets/ghuser.styl +19 -3
  70. package/source/css/_components/widgets/list.styl +1 -0
  71. package/source/css/_components/widgets/toc.styl +3 -0
  72. package/source/css/_components/widgets/widgets.styl +4 -0
  73. package/source/css/_custom.styl +2 -1
  74. package/source/css/_defines/func.styl +8 -0
  75. package/source/css/_plugins/comments/artalk.styl +6 -2
  76. package/source/css/_plugins/comments/twikoo.styl +2 -0
  77. package/source/css/_plugins/index.styl +0 -1
  78. package/source/js/main.js +76 -26
  79. package/source/js/plugins/copycode.js +34 -27
  80. package/source/js/search/local-search.js +5 -2
  81. package/source/js/services/memos.js +42 -4
  82. package/source/js/services/rss.js +200 -0
package/README.md CHANGED
@@ -50,6 +50,8 @@ npm i hexo-theme-stellar
50
50
 
51
51
  See docs: https://xaoxuu.com/wiki/stellar/
52
52
 
53
+ > AI docs: https://deepwiki.com/xaoxuu/hexo-theme-stellar/
54
+
53
55
  ## Examples
54
56
 
55
57
  https://xaoxuu.com/wiki/stellar/examples/
package/_config.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  ######## Stellar info ########
2
2
  stellar:
3
- version: '1.33.1'
3
+ version: '1.35.0'
4
4
  homepage: 'https://xaoxuu.com/wiki/stellar/'
5
5
  repo: 'https://github.com/xaoxuu/hexo-theme-stellar'
6
6
  main_css: /css/main.css
@@ -9,13 +9,16 @@ stellar:
9
9
 
10
10
  ######## head tags ########
11
11
  preconnect:
12
- # - https://gcore.jsdelivr.net
13
- # - https://gcore.jsdelivr.net
14
- # - https://unpkg.com
12
+ - https://gcore.jsdelivr.net
13
+ - https://unpkg.com
14
+ - https://cdn.jsdelivr.net
15
+ - https://cdnjs.cloudflare.com
15
16
 
16
17
  # 一旦设置源站地址,非源站地址将不会被SEO收录,并且访问时弹出提示
17
18
  # 如果访问地址不在备用站主机列表,则警告信息为非法克隆
18
19
  canonical:
20
+ closeEnable: true # 是否显示关闭提示按钮
21
+ closeText: 关闭提示 # 关闭提示按钮的文字描述
19
22
  originalHost: # 主站点域名主机,例如 xaoxuu.com
20
23
  officialHosts: # 官方主机列表,每行一个,例如 xaoxuu.vercel.app
21
24
  - localhost
@@ -311,8 +314,8 @@ comments:
311
314
  # Artalk
312
315
  # https://artalk.js.org/
313
316
  artalk:
314
- css: https://unpkg.com/artalk@2.9/dist/Artalk.css
315
- js: https://unpkg.com/artalk@2.9/dist/Artalk.js
317
+ css: https://unpkg.com/artalk@2.9/dist/artalk.css
318
+ js: https://unpkg.com/artalk@2.9/dist/artalk.js
316
319
  server: # 后端服务地址
317
320
  site: '' # 站点名称
318
321
  darkMode: auto # 其它模式都有问题,慎用,否则后果自负
@@ -451,7 +454,7 @@ tag_plugins:
451
454
 
452
455
  # 基础依赖
453
456
  dependencies:
454
- jquery: https://gcore.jsdelivr.net/npm/jquery@3.7/dist/jquery.min.js
457
+ jquery: https://gcore.jsdelivr.net/npm/jquery@3.7/dist/jquery.slim.min.js
455
458
  marked: https://gcore.jsdelivr.net/npm/marked@13.0/lib/marked.umd.min.js
456
459
  lazyload:
457
460
  js: https://gcore.jsdelivr.net/npm/vanilla-lazyload@19.1/dist/lazyload.min.js
@@ -516,7 +519,8 @@ data_services:
516
519
  '_posts/': # https://github.com/xaoxuu/xaoxuu.com/blob/main/source/_posts/
517
520
  'wiki/stellar/': https://github.com/xaoxuu/hexo-theme-stellar-docs/blob/main/
518
521
  js: /js/services/contributors.js
519
-
522
+ rss:
523
+ js: /js/services/rss.js
520
524
 
521
525
  # 扩展插件接入方法:(插件名下面用 #plugin# 代替)
522
526
  # 1. 在这里增加 #plugin# 配置,至少应含有 enable 字段,默认为空(不启用)
@@ -537,7 +541,6 @@ plugins:
537
541
  # available for {% image xxx %}
538
542
  fancybox:
539
543
  enable: true
540
- loader: /js/plugins/fancybox-loader.js
541
544
  js: https://gcore.jsdelivr.net/npm/@fancyapps/ui@5.0/dist/fancybox/fancybox.umd.js
542
545
  css: https://gcore.jsdelivr.net/npm/@fancyapps/ui@5.0/dist/fancybox/fancybox.css
543
546
  # 让 md 语法图片支持放大可以这样写: .md-text img:not([class]), .md-text .image img
@@ -557,8 +560,8 @@ plugins:
557
560
  enable: #true # 慎用,有些时候打开页面空白
558
561
  js: https://gcore.jsdelivr.net/npm/scrollreveal@4.0/dist/scrollreveal.min.js
559
562
  distance: 8px
560
- duration: 500 # ms
561
- interval: 50 # ms
563
+ duration: 1000 # ms
564
+ interval: 100 # ms
562
565
  scale: 1 # 0.1~1
563
566
 
564
567
  # AI 摘要
@@ -588,8 +591,8 @@ plugins:
588
591
  katex:
589
592
  enable: #true # hexo-renderer-markdown-it-plus 默认开启 katex,此选项仅用于引入样式
590
593
  inject: |
591
- <link rel="stylesheet" href="https://gcore.jsdelivr.net/npm/katex@0.16/dist/katex.min.css" integrity="sha384-vKruj+a13U8yHIkAyGgK1J3ArTLzrFGBbBc0tDp4ad/EyewESeXE/Iv67Aj8gKZ0" crossorigin="anonymous">
592
-
594
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.23/dist/katex.min.css" integrity="sha384-//SZkxyB7axjCAopkAL1E1rve+ZSPKapD89Lo/lLhcsXR+zOYl5z6zJZEFXil+q0" crossorigin="anonymous">
595
+
593
596
  # MathJax
594
597
  # 需在Markdown文件开头加入mathjax: true
595
598
  # 推荐使用Pandoc: npm uninstall hexo-renderer-marked --save & npm install hexo-renderer-pandoc --save
@@ -672,7 +675,9 @@ style:
672
675
  start: 'linear-gradient(to right, hsl(215, 95%, 64%), hsl(195, 95%, 60%), hsl(165, 95%, 56%), hsl(165, 95%, 56%), hsl(195 95% 60%), hsl(215, 95%, 64%))'
673
676
  leftbar:
674
677
  # 可以设置:纯色/渐变色/图片作为背景
675
- background-color: var(--card) # var(--block)
678
+ # 设置为纯色时,可以分别设置浅色和深色模式背景色
679
+ background-color-light: var(--card) # var(--block) #'rgb(#C3C3C3)'
680
+ background-color-dark: var(--card) # var(--block) #'rgb(#3C3C3C)'
676
681
  background-image: url(https://gcore.jsdelivr.net/gh/cdn-x/placeholder@1.0.13/image/sidebar-bg1@small.jpg)
677
682
  blur-px: 100px
678
683
  blur-bg: var(--bg-a60)
@@ -1,42 +1,57 @@
1
- <script type="module">
2
- const el = document.getElementById('artalk_container');
3
- util.viewportLazyload(el, load_artalk, <%= theme.comments.lazyload ?? false %>);
4
-
5
- function load_artalk() {
6
- if (!el) return;
7
- utils.css('<%- theme.comments.artalk.css %>');
8
- utils.js('<%- theme.comments.artalk.js %>', {defer: true}).then(function () {
9
- // 监听 Artalk 事件
10
- // FIXME: Artalk开启了懒加载会导致评论输入预览框里的图也变成data-src,导致看不到图
11
- // Artalk.use((ctx) => {
12
- // ctx.on('list-loaded', () => window.lazyLoadInstance?.update())
13
- // })
14
- const path = el.getAttribute('comment_id') ?? decodeURI(window.location.pathname);
15
- const artalk = Artalk.init({
16
- el: '#artalk_container',
17
- pageKey: path,
18
- pageTitle: '<%= page.title %>',
19
- server: '<%= theme.comments.artalk.server %>',
20
- site: '<%= theme.comments.artalk.site %>',
21
- darkMode: '<%= theme.comments.artalk.darkMode %>',
22
- <% if (theme.comments.artalk.imageUploader?.api) { %>
23
- imgUploader: function(file) {
24
- let headers = new Headers();
25
- headers.set('Accept', 'application/json');
26
- <% if (theme.comments.artalk.imageUploader?.token) { %>
27
- headers.set('Authorization', '<%- theme.comments.artalk.imageUploader?.token %>')
28
- <% } %>
29
- let formData = new FormData();
30
- formData.append('file', file);
31
- return fetch('<%- theme.comments.artalk.imageUploader?.api %>',{
32
- method: 'POST',
33
- body: formData,
34
- headers: headers
35
- }).then((resp) => resp.json())
36
- .then((resp) => resp.<%- theme.comments.artalk.imageUploader?.resp %>)
37
- },
38
- <% } %>
39
- });
40
- });
41
- }
1
+ <script>
2
+ (function() {
3
+ const lazyload = <%= theme.comments.lazyload ?? false %>;
4
+
5
+ function initArtalk() {
6
+ const el = document.getElementById('artalk_container');
7
+ if (!el) return;
8
+
9
+ function load_artalk() {
10
+ utils.css('<%- theme.comments.artalk.css %>');
11
+ utils.js('<%- theme.comments.artalk.js %>', {defer: true}).then(function () {
12
+ // 监听 Artalk 事件
13
+ // FIXME: Artalk开启了懒加载会导致评论输入预览框里的图也变成data-src,导致看不到图
14
+ // Artalk.use((ctx) => {
15
+ // ctx.on('list-loaded', () => window.lazyLoadInstance?.update())
16
+ // })
17
+ const path = el.getAttribute('comment_id') ?? decodeURI(window.location.pathname);
18
+ const artalk = Artalk.init({
19
+ el: '#artalk_container',
20
+ pageKey: path,
21
+ pageTitle: '<%= page.title %>',
22
+ server: '<%= theme.comments.artalk.server %>',
23
+ site: '<%= theme.comments.artalk.site %>',
24
+ darkMode: '<%= theme.comments.artalk.darkMode %>',
25
+ <% if (theme.comments.artalk.imageUploader?.api) { %>
26
+ imgUploader: function(file) {
27
+ let headers = new Headers();
28
+ headers.set('Accept', 'application/json');
29
+ <% if (theme.comments.artalk.imageUploader?.token) { %>
30
+ headers.set('Authorization', '<%- theme.comments.artalk.imageUploader?.token %>')
31
+ <% } %>
32
+ let formData = new FormData();
33
+ formData.append('file', file);
34
+ return fetch('<%- theme.comments.artalk.imageUploader?.api %>',{
35
+ method: 'POST',
36
+ body: formData,
37
+ headers: headers
38
+ }).then((resp) => resp.json())
39
+ .then((resp) => resp.<%- theme.comments.artalk.imageUploader?.resp %>)
40
+ },
41
+ <% } %>
42
+ });
43
+ });
44
+ }
45
+
46
+ util.viewportLazyload(el, load_artalk, lazyload);
47
+ }
48
+
49
+ // Store in global stellar namespace for PJAX reinitialization
50
+ window.stellar = window.stellar || {};
51
+ window.stellar.initComments = window.stellar.initComments || {};
52
+ window.stellar.initComments.artalk = initArtalk;
53
+
54
+ // Initialize on page load
55
+ initArtalk();
56
+ })();
42
57
  </script>
@@ -1,23 +1,38 @@
1
- <script type="module">
2
- const el = document.querySelector('#comments #beaudar');
3
- util.viewportLazyload(el, load_beaudar, <%= theme.comments.lazyload ?? false %>);
4
-
5
- function load_beaudar() {
6
- if (!el) return;
7
- try {
8
- el.innerHTML = '';
9
- } catch (error) {
10
- console.error(error);
11
- }
12
- const script = document.createElement('script');
13
- script.src = 'https://beaudar.lipk.org/client.js';
14
- script.async = true;
15
- for (const key of Object.keys(el.attributes)) {
16
- const attr = el.attributes[key];
17
- if (['class', 'id'].includes(attr.name) === false) {
18
- script.setAttribute(attr.name, attr.value);
1
+ <script>
2
+ (function() {
3
+ const lazyload = <%= theme.comments.lazyload ?? false %>;
4
+
5
+ function initBeaudar() {
6
+ const el = document.querySelector('#comments #beaudar');
7
+ if (!el) return;
8
+
9
+ function load_beaudar() {
10
+ try {
11
+ el.innerHTML = '';
12
+ } catch (error) {
13
+ console.error(error);
14
+ }
15
+ const script = document.createElement('script');
16
+ script.src = 'https://beaudar.lipk.org/client.js';
17
+ script.async = true;
18
+ for (const key of Object.keys(el.attributes)) {
19
+ const attr = el.attributes[key];
20
+ if (['class', 'id'].includes(attr.name) === false) {
21
+ script.setAttribute(attr.name, attr.value);
22
+ }
23
+ }
24
+ el.appendChild(script);
19
25
  }
26
+
27
+ util.viewportLazyload(el, load_beaudar, lazyload);
20
28
  }
21
- el.appendChild(script);
22
- }
29
+
30
+ // Store in global stellar namespace for PJAX reinitialization
31
+ window.stellar = window.stellar || {};
32
+ window.stellar.initComments = window.stellar.initComments || {};
33
+ window.stellar.initComments.beaudar = initBeaudar;
34
+
35
+ // Initialize on page load
36
+ initBeaudar();
37
+ })();
23
38
  </script>
@@ -1,22 +1,37 @@
1
- <script type="module">
2
- const el = document.querySelector('#comments #giscus');
3
- util.viewportLazyload(el, load_discus, <%= theme.comments.lazyload ?? false %>);
4
-
5
- function load_discus() {
6
- if (!el) return;
7
- try {
8
- el.innerHTML = '';
9
- } catch (error) {
10
- console.error(error);
11
- }
12
- const script = document.createElement('script');
13
- script.async = true;
14
- for (const key of Object.keys(el.attributes)) {
15
- const attr = el.attributes[key];
16
- if (['class', 'id'].includes(attr.name) === false) {
17
- script.setAttribute(attr.name, attr.value);
1
+ <script>
2
+ (function() {
3
+ const lazyload = <%= theme.comments.lazyload ?? false %>;
4
+
5
+ function initGiscus() {
6
+ const el = document.querySelector('#comments #giscus');
7
+ if (!el) return;
8
+
9
+ function load_giscus() {
10
+ try {
11
+ el.innerHTML = '';
12
+ } catch (error) {
13
+ console.error(error);
14
+ }
15
+ const script = document.createElement('script');
16
+ script.async = true;
17
+ for (const key of Object.keys(el.attributes)) {
18
+ const attr = el.attributes[key];
19
+ if (['class', 'id'].includes(attr.name) === false) {
20
+ script.setAttribute(attr.name, attr.value);
21
+ }
18
22
  }
23
+ el.appendChild(script);
19
24
  }
20
- el.appendChild(script);
21
- }
25
+
26
+ util.viewportLazyload(el, load_giscus, lazyload);
27
+ }
28
+
29
+ // Store in global stellar namespace for PJAX reinitialization
30
+ window.stellar = window.stellar || {};
31
+ window.stellar.initComments = window.stellar.initComments || {};
32
+ window.stellar.initComments.giscus = initGiscus;
33
+
34
+ // Initialize on page load
35
+ initGiscus();
36
+ })();
22
37
  </script>
@@ -1,15 +1,30 @@
1
- <script type="module">
2
- const el = document.getElementById('twikoo_container');
3
- util.viewportLazyload(el, load_twikoo, <%= theme.comments.lazyload ?? false %>);
4
-
5
- function load_twikoo() {
6
- if (!el) return;
7
- utils.js('<%- theme.comments.twikoo.js %>', {defer: true}).then(function () {
8
- const path = el.getAttribute('comment_id') ?? decodeURI(window.location.pathname);
9
- twikoo.init(Object.assign(<%- JSON.stringify(theme.comments.twikoo) %>, {
10
- el: '#twikoo_container',
11
- path: path,
12
- }));
13
- });
14
- }
1
+ <script>
2
+ (function() {
3
+ const lazyload = <%= theme.comments.lazyload ?? false %>;
4
+
5
+ function initTwikoo() {
6
+ const el = document.getElementById('twikoo_container');
7
+ if (!el) return;
8
+
9
+ function load_twikoo() {
10
+ utils.js('<%- theme.comments.twikoo.js %>', {defer: true}).then(function () {
11
+ const path = el.getAttribute('comment_id') ?? decodeURI(window.location.pathname);
12
+ twikoo.init(Object.assign(<%- JSON.stringify(theme.comments.twikoo) %>, {
13
+ el: '#twikoo_container',
14
+ path: path,
15
+ }));
16
+ });
17
+ }
18
+
19
+ util.viewportLazyload(el, load_twikoo, lazyload);
20
+ }
21
+
22
+ // Store in global stellar namespace for PJAX reinitialization
23
+ window.stellar = window.stellar || {};
24
+ window.stellar.initComments = window.stellar.initComments || {};
25
+ window.stellar.initComments.twikoo = initTwikoo;
26
+
27
+ // Initialize on page load
28
+ initTwikoo();
29
+ })();
15
30
  </script>
@@ -1,23 +1,38 @@
1
- <script type="module">
2
- const el = document.querySelector("#comments #utterances");
3
- util.viewportLazyload(el, load_utterances, <%= theme.comments.lazyload ?? false %>);
4
-
5
- function load_utterances() {
6
- if (!el) return;
7
- try {
8
- el.innerHTML = '';
9
- } catch (error) {
10
- console.error(error);
11
- }
12
- const script = document.createElement('script');
13
- script.src = 'https://utteranc.es/client.js';
14
- script.async = true;
15
- for (const key of Object.keys(el.attributes)) {
16
- const attr = el.attributes[key];
17
- if (['class', 'id'].includes(attr.name) === false) {
18
- script.setAttribute(attr.name, attr.value);
1
+ <script>
2
+ (function() {
3
+ const lazyload = <%= theme.comments.lazyload ?? false %>;
4
+
5
+ function initUtterances() {
6
+ const el = document.querySelector("#comments #utterances");
7
+ if (!el) return;
8
+
9
+ function load_utterances() {
10
+ try {
11
+ el.innerHTML = '';
12
+ } catch (error) {
13
+ console.error(error);
14
+ }
15
+ const script = document.createElement('script');
16
+ script.src = 'https://utteranc.es/client.js';
17
+ script.async = true;
18
+ for (const key of Object.keys(el.attributes)) {
19
+ const attr = el.attributes[key];
20
+ if (['class', 'id'].includes(attr.name) === false) {
21
+ script.setAttribute(attr.name, attr.value);
22
+ }
23
+ }
24
+ el.appendChild(script);
19
25
  }
26
+
27
+ util.viewportLazyload(el, load_utterances, lazyload);
20
28
  }
21
- el.appendChild(script);
22
- }
29
+
30
+ // Store in global stellar namespace for PJAX reinitialization
31
+ window.stellar = window.stellar || {};
32
+ window.stellar.initComments = window.stellar.initComments || {};
33
+ window.stellar.initComments.utterances = initUtterances;
34
+
35
+ // Initialize on page load
36
+ initUtterances();
37
+ })();
23
38
  </script>
@@ -1,36 +1,48 @@
1
1
  <script type="module">
2
2
  import { init } from '<%- theme.comments.waline.js %>';
3
3
 
4
- const el = document.getElementById('waline_container');
5
- util.viewportLazyload(el, load_waline, <%= theme.comments.lazyload ?? false %>);
6
-
7
- function load_waline(){
4
+ const lazyload = <%= theme.comments.lazyload ?? false %>;
5
+
6
+ function initWaline() {
7
+ const el = document.getElementById('waline_container');
8
8
  if (!el) return;
9
9
 
10
- utils.css('<%- theme.comments.waline.css %>');
11
- utils.css('<%- theme.comments.waline.meta_css %>');
10
+ function load_waline() {
11
+ utils.css('<%- theme.comments.waline.css %>');
12
+ utils.css('<%- theme.comments.waline.meta_css %>');
12
13
 
13
- const path = el.getAttribute('comment_id') ?? decodeURI(window.location.pathname);
14
- const waline = init(Object.assign(<%- JSON.stringify(theme.comments.waline) %>, {
15
- el: '#waline_container',
16
- path: path,
17
- <% if(!!theme.comments.waline.imageUploader?.api){ %>
18
- imageUploader: function(file) {
19
- const headers = new Headers();
20
- headers.set('Accept', 'application/json');
21
- <% if(!!theme.comments.waline.imageUploader?.token) { %>
22
- headers.set('<%= theme.comments.waline.imageUploader?.tokenName %>', '<%= theme.comments.waline.imageUploader?.token %>')
23
- <% } %>
24
- const formData = new FormData();
25
- formData.append('<%= theme.comments.waline.imageUploader?.fileName %>', file);
26
- return fetch('<%= theme.comments.waline.imageUploader?.api %>',{
27
- method: 'POST',
28
- body: formData,
29
- headers: headers
30
- }).then((resp) => resp.json())
31
- .then((resp) => resp.<%= theme.comments.waline.imageUploader?.resp %>)
32
- },
33
- <% } %>
34
- }));
14
+ const path = el.getAttribute('comment_id') ?? decodeURI(window.location.pathname);
15
+ const waline = init(Object.assign(<%- JSON.stringify(theme.comments.waline) %>, {
16
+ el: '#waline_container',
17
+ path: path,
18
+ <% if(!!theme.comments.waline.imageUploader?.api){ %>
19
+ imageUploader: function(file) {
20
+ const headers = new Headers();
21
+ headers.set('Accept', 'application/json');
22
+ <% if(!!theme.comments.waline.imageUploader?.token) { %>
23
+ headers.set('<%= theme.comments.waline.imageUploader?.tokenName %>', '<%= theme.comments.waline.imageUploader?.token %>')
24
+ <% } %>
25
+ const formData = new FormData();
26
+ formData.append('<%= theme.comments.waline.imageUploader?.fileName %>', file);
27
+ return fetch('<%= theme.comments.waline.imageUploader?.api %>',{
28
+ method: 'POST',
29
+ body: formData,
30
+ headers: headers
31
+ }).then((resp) => resp.json())
32
+ .then((resp) => resp.<%= theme.comments.waline.imageUploader?.resp %>)
33
+ },
34
+ <% } %>
35
+ }));
36
+ }
37
+
38
+ util.viewportLazyload(el, load_waline, lazyload);
35
39
  }
40
+
41
+ // Store in global stellar namespace for PJAX reinitialization
42
+ window.stellar = window.stellar || {};
43
+ window.stellar.initComments = window.stellar.initComments || {};
44
+ window.stellar.initComments.waline = initWaline;
45
+
46
+ // Initialize on page load
47
+ initWaline();
36
48
  </script>
@@ -6,7 +6,7 @@ function layoutWikiCover() {
6
6
  return el;
7
7
  }
8
8
  if (proj.homepage.path !== page.path) {
9
- return;
9
+ return el;
10
10
  }
11
11
  if (proj.coverpage == undefined || proj.coverpage === false || proj.coverpage === '[]') {
12
12
  return el;
@@ -70,6 +70,46 @@ function og_args() {
70
70
  return Object.assign(args, page.open_graph);
71
71
  }
72
72
 
73
+ function escape_meta_content(content) {
74
+ return String(content || '')
75
+ .replace(/&/g, '&amp;')
76
+ .replace(/"/g, '&quot;')
77
+ .replace(/</g, '&lt;')
78
+ .replace(/>/g, '&gt;');
79
+ }
80
+
81
+ function generate_og_title() {
82
+ return escape_meta_content(strip_html(page.title || config.title));
83
+ }
84
+
85
+ function generate_og_site_name() {
86
+ if (page.layout === 'post' && page.title) {
87
+ return generate_og_title();
88
+ }
89
+ return escape_meta_content(strip_html(config.title));
90
+ }
91
+
92
+ function render_open_graph() {
93
+ if (!(theme.open_graph && theme.open_graph.enable)) {
94
+ return '';
95
+ }
96
+ let meta = open_graph(og_args());
97
+ meta = meta.replace(/<meta property="og:title" content="[^"]*">/, `<meta property="og:title" content="${generate_og_title()}">`);
98
+ if (meta.match(/<meta property="og:site_name" content="[^"]*">/)) {
99
+ meta = meta.replace(/<meta property="og:site_name" content="[^"]*">/, `<meta property="og:site_name" content="${generate_og_site_name()}">`);
100
+ } else {
101
+ meta += `<meta property="og:site_name" content="${generate_og_site_name()}">`;
102
+ }
103
+ if (page.title) {
104
+ if (meta.match(/<meta name="twitter:title" content="[^"]*">/)) {
105
+ meta = meta.replace(/<meta name="twitter:title" content="[^"]*">/, `<meta name="twitter:title" content="${generate_og_title()}">`);
106
+ } else {
107
+ meta += `<meta name="twitter:title" content="${generate_og_title()}">`;
108
+ }
109
+ }
110
+ return meta;
111
+ }
112
+
73
113
  function preconnect() {
74
114
  var el = '';
75
115
  for (let href of (theme.preconnect || [])) {
@@ -99,9 +139,6 @@ function generate_canonical() {
99
139
  if (path.startsWith('/404') || path.startsWith('404')) {
100
140
  return '';
101
141
  }
102
- if (path.endsWith('.html') && path.length > 5) {
103
- path = path.split('.html')[0];
104
- }
105
142
  return `<link rel="canonical" href="https://${originalHost}${path}">`;
106
143
  }
107
144
  return '';
@@ -127,18 +164,27 @@ function generate_canonical() {
127
164
  <meta name="theme-color" content="#f9fafb">
128
165
  <title><%- generate_title() %></title>
129
166
 
130
- <% if (theme.open_graph && theme.open_graph.enable) { %>
131
- <%- open_graph(og_args()) %>
132
- <% } %>
167
+ <%- render_open_graph() %>
133
168
  <%- generate_description() %>
134
169
 
135
170
  <%- generate_keywords() %>
136
171
 
137
172
  <!-- feed -->
138
173
  <% if (config.feed && config.feed.path) { %>
139
- <%- feed_tag(config.feed.path, {title: config.title}) %>
174
+ <%
175
+ var paths = Array.isArray(config.feed.path)
176
+ ? config.feed.path
177
+ : [config.feed.path];
178
+ %>
179
+
180
+ <% paths.forEach(function (path) { %>
181
+ <% if (path) { %>
182
+ <%- feed_tag(path, { title: config.title }) %>
183
+ <% } %>
184
+ <% }) %>
140
185
  <% } %>
141
186
 
187
+ <link rel="preload" href="<%- url_for(`${theme.stellar.main_css}?v=${stellar_info('version')}`) %>" as="style">
142
188
  <link rel="stylesheet" href="<%- url_for(`${theme.stellar.main_css}?v=${stellar_info('version')}`) %>">
143
189
 
144
190
 
@@ -4,10 +4,30 @@
4
4
  const canonicalWithEncoded = Object.assign({}, canonical, {
5
5
  encoded: encoded
6
6
  });
7
+ const permalink = page.permalink || canonical.originalHost;
8
+ const checklink = theme.data_services.video.js
7
9
  %>
8
10
 
9
11
  <script type="text/javascript">
10
12
  window.canonical = <%- JSON.stringify(canonicalWithEncoded) %>;
13
+ window.canonical["param"] = <%- JSON.stringify({permalink, checklink}) %>;
14
+ // Fix: Ensure page is at the correct top position on data load
15
+ if (history.scrollRestoration) {
16
+ history.scrollRestoration = 'auto';
17
+ }
18
+ (function() {
19
+ const scrollHandler = () => {
20
+ const wikiCover = document.querySelector('#l_cover .l_cover.wiki');
21
+ const startEl = document.getElementById('start');
22
+ if (wikiCover && startEl) {
23
+ window.scrollTo(0, startEl.offsetTop);
24
+ } else {
25
+ window.scrollTo(0, 0);
26
+ }
27
+ };
28
+ if (document.readyState !== 'loading') scrollHandler();
29
+ else document.addEventListener('DOMContentLoaded', scrollHandler);
30
+ })();
11
31
  const ctx = {
12
32
  date_suffix: {
13
33
  just: `<%- __('meta.date_suffix.just') %>`,
@@ -38,8 +58,6 @@
38
58
  const deps = {
39
59
  jquery: `<%- url_for(theme.dependencies.jquery) %>`,
40
60
  marked: `<%- url_for(theme.dependencies.marked) %>`,
41
- lazyload: `<%- url_for(theme.dependencies.lazyload) %>`
61
+ lazyload: `<%- url_for(theme.dependencies.lazyload.js) %>`
42
62
  }
43
-
44
-
45
63
  </script>