hexo-theme-stellar 1.26.8 → 1.27.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 (150) hide show
  1. package/_config.yml +134 -94
  2. package/_data/icons.yml +8 -1
  3. package/_data/widgets.yml +19 -7
  4. package/languages/en.yml +4 -2
  5. package/languages/zh-CN.yml +3 -1
  6. package/languages/zh-TW.yml +4 -2
  7. package/layout/404.ejs +1 -1
  8. package/layout/_partial/{plugins/comments → comments}/artalk/script.ejs +2 -2
  9. package/layout/_partial/{plugins/comments/utterances → comments/giscus}/layout.ejs +5 -2
  10. package/layout/_partial/{plugins/comments → comments}/giscus/script.ejs +1 -4
  11. package/layout/_partial/{plugins/comments → comments}/layout.ejs +1 -1
  12. package/layout/_partial/{plugins/comments → comments}/twikoo/script.ejs +1 -1
  13. package/layout/_partial/comments/waline/script.ejs +43 -0
  14. package/layout/_partial/head.ejs +0 -1
  15. package/layout/_partial/main/article/article_footer.ejs +1 -1
  16. package/layout/_partial/main/footer.ejs +1 -1
  17. package/layout/_partial/main/navbar/article_banner.ejs +81 -17
  18. package/layout/_partial/main/navbar/ghinfo.ejs +1 -1
  19. package/layout/_partial/main/post_list/post_card.ejs +1 -1
  20. package/layout/_partial/menubtn.ejs +6 -3
  21. package/layout/_partial/scripts/defines.ejs +31 -0
  22. package/layout/_partial/scripts/services.ejs +29 -0
  23. package/layout/_partial/scripts/sidebar.ejs +25 -0
  24. package/layout/_partial/scripts/utils.ejs +158 -0
  25. package/layout/_partial/scripts.ejs +32 -0
  26. package/layout/_partial/sidebar/{index.ejs → index_leftbar.ejs} +22 -20
  27. package/layout/_partial/sidebar/index_rightbar.ejs +84 -0
  28. package/layout/_partial/sidebar/logo.ejs +1 -1
  29. package/layout/_partial/widgets/author.ejs +37 -0
  30. package/layout/_partial/widgets/components/edit.ejs +24 -0
  31. package/layout/_partial/widgets/ghissues.ejs +1 -1
  32. package/layout/_partial/widgets/ghrepo.ejs +2 -2
  33. package/layout/_partial/widgets/ghuser.ejs +2 -2
  34. package/layout/_partial/widgets/markdown.ejs +1 -1
  35. package/layout/_partial/widgets/recent.ejs +1 -5
  36. package/layout/_partial/widgets/related.ejs +1 -1
  37. package/layout/_partial/widgets/timeline.ejs +1 -1
  38. package/layout/_partial/widgets/toc.ejs +32 -85
  39. package/layout/_partial/widgets/tree.ejs +71 -0
  40. package/layout/_plugins/copycode.ejs +13 -0
  41. package/layout/_plugins/fancybox.ejs +32 -0
  42. package/layout/_plugins/heti.ejs +21 -0
  43. package/layout/_plugins/index.ejs +24 -0
  44. package/layout/_plugins/lazyload.ejs +21 -0
  45. package/layout/{_partial/plugins/parser/mathjax/script.ejs → _plugins/mathjax.ejs} +1 -1
  46. package/layout/_plugins/mermaid.ejs +29 -0
  47. package/layout/_plugins/preload.ejs +9 -0
  48. package/layout/_plugins/scrollreveal.ejs +15 -0
  49. package/layout/_plugins/search/local_search.ejs +8 -0
  50. package/layout/_plugins/swiper.ejs +26 -0
  51. package/layout/_plugins/tianli_gpt.ejs +11 -0
  52. package/layout/archive.ejs +9 -2
  53. package/layout/layout.ejs +9 -6
  54. package/layout/page.ejs +2 -10
  55. package/package.json +1 -1
  56. package/scripts/events/lib/doc_tree.js +8 -8
  57. package/scripts/events/lib/topic_tree.js +3 -0
  58. package/scripts/generators/author.js +1 -1
  59. package/scripts/helpers/parse_config.js +6 -5
  60. package/scripts/tags/lib/albums.js +2 -2
  61. package/scripts/tags/lib/button.js +1 -1
  62. package/scripts/tags/lib/emoji.js +1 -1
  63. package/scripts/tags/lib/friends.js +1 -1
  64. package/scripts/tags/lib/icon.js +10 -5
  65. package/scripts/tags/lib/link.js +2 -2
  66. package/scripts/tags/lib/md.js +1 -1
  67. package/scripts/tags/lib/posters.js +2 -2
  68. package/scripts/tags/lib/sites.js +1 -1
  69. package/scripts/tags/lib/timeline.js +2 -2
  70. package/source/css/_common/button.styl +8 -2
  71. package/source/css/_common/device.styl +39 -12
  72. package/source/css/_custom.styl +15 -16
  73. package/source/css/_defines/const.styl +1 -1
  74. package/source/css/_defines/func.styl +14 -4
  75. package/source/css/_defines/theme.styl +38 -27
  76. package/source/css/_layout/layout.styl +62 -27
  77. package/source/css/_layout/list.styl +1 -1
  78. package/source/css/_layout/main.styl +1 -4
  79. package/source/css/_layout/md.styl +16 -2
  80. package/source/css/_layout/pages/archives.styl +4 -0
  81. package/source/css/_layout/partial/article-banner.styl +14 -15
  82. package/source/css/_layout/partial/article-footer.styl +0 -5
  83. package/source/css/_layout/partial/footer.styl +8 -6
  84. package/source/css/_layout/partial/related.styl +4 -0
  85. package/source/css/_layout/sidebar/footer.styl +3 -1
  86. package/source/css/_layout/sidebar/logo.styl +3 -1
  87. package/source/css/_layout/sidebar/nav-area.styl +1 -1
  88. package/source/css/_layout/sidebar/sidebar.styl +23 -16
  89. package/source/css/_layout/tag-plugins/banner.styl +1 -8
  90. package/source/css/_layout/tag-plugins/common.styl +10 -5
  91. package/source/css/_layout/tag-plugins/icon.styl +6 -0
  92. package/source/css/_layout/tag-plugins/image.styl +1 -1
  93. package/source/css/_layout/tag-plugins/quot.styl +1 -1
  94. package/source/css/_layout/tag-plugins/timeline.styl +26 -27
  95. package/source/css/_layout/widgets/ghrepo.styl +1 -1
  96. package/source/css/_layout/widgets/ghuser.styl +9 -5
  97. package/source/css/_layout/widgets/list.styl +4 -2
  98. package/source/css/_layout/widgets/related.styl +0 -1
  99. package/source/css/_layout/widgets/timeline.styl +27 -21
  100. package/source/css/_layout/widgets/toc.styl +182 -0
  101. package/source/css/_layout/widgets/tree.styl +0 -0
  102. package/source/css/_layout/widgets/widgets.styl +26 -7
  103. package/source/css/_plugins/comments/twikoo.styl +6 -6
  104. package/source/css/_plugins/comments/waline.styl +13 -10
  105. package/source/css/_plugins/index.styl +2 -0
  106. package/source/css/_plugins/katex.styl +5 -0
  107. package/source/css/_plugins/mermaid.styl +49 -59
  108. package/source/css/_plugins/tianli_gpt.styl +208 -151
  109. package/source/js/main.js +48 -251
  110. package/source/js/plugins/copycode.js +24 -28
  111. package/source/js/search/local-search.js +32 -0
  112. package/source/js/services/fcircle.js +36 -0
  113. package/source/js/services/friends.js +27 -0
  114. package/source/js/services/ghinfo.js +33 -0
  115. package/source/js/services/mdrender.js +10 -0
  116. package/source/js/services/memos.js +73 -0
  117. package/source/js/services/siteinfo.js +38 -0
  118. package/source/js/services/sites.js +30 -0
  119. package/source/js/services/timeline.js +106 -0
  120. package/source/js/services/weibo.js +60 -0
  121. package/layout/_partial/main/navbar/article_top_area.ejs +0 -35
  122. package/layout/_partial/main/navbar/author_banner.ejs +0 -29
  123. package/layout/_partial/plugins/ai/tianli_gpt.ejs +0 -9
  124. package/layout/_partial/plugins/comments/waline/script.ejs +0 -39
  125. package/layout/_partial/plugins/parser/head.ejs +0 -3
  126. package/layout/_partial/plugins/parser/katex/head.ejs +0 -3
  127. package/layout/_partial/plugins/parser/katex/script.ejs +0 -4
  128. package/layout/_partial/plugins/parser/mermaid/script.ejs +0 -29
  129. package/layout/_partial/plugins/parser/script.ejs +0 -9
  130. package/layout/_partial/scripts/index.ejs +0 -176
  131. package/source/css/_layout/widgets/toc_blog.styl +0 -3
  132. package/source/css/_layout/widgets/toc_common.styl +0 -92
  133. package/source/css/_layout/widgets/toc_wiki.styl +0 -62
  134. package/source/js/plugins/fcircle.js +0 -92
  135. package/source/js/plugins/friends.js +0 -84
  136. package/source/js/plugins/ghinfo.js +0 -85
  137. package/source/js/plugins/linkcard.js +0 -48
  138. package/source/js/plugins/marked.js +0 -50
  139. package/source/js/plugins/memos.js +0 -132
  140. package/source/js/plugins/sites.js +0 -87
  141. package/source/js/plugins/timeline.js +0 -162
  142. package/source/js/plugins/weibo.js +0 -116
  143. /package/layout/_partial/{plugins/comments → comments}/artalk/layout.ejs +0 -0
  144. /package/layout/_partial/{plugins/comments → comments}/beaudar/layout.ejs +0 -0
  145. /package/layout/_partial/{plugins/comments → comments}/beaudar/script.ejs +0 -0
  146. /package/layout/_partial/{plugins/comments → comments}/script.ejs +0 -0
  147. /package/layout/_partial/{plugins/comments → comments}/twikoo/layout.ejs +0 -0
  148. /package/layout/_partial/{plugins/comments/giscus → comments/utterances}/layout.ejs +0 -0
  149. /package/layout/_partial/{plugins/comments → comments}/utterances/script.ejs +0 -0
  150. /package/layout/_partial/{plugins/comments → comments}/waline/layout.ejs +0 -0
@@ -0,0 +1,43 @@
1
+ <script type="module">
2
+ import { init } from '<%- theme.comments.waline.js %>'
3
+
4
+ function load_comment(){
5
+ if(!document.getElementById("waline_container"))return;
6
+
7
+ utils.css('<%- theme.comments.waline.css %>');
8
+ utils.css('<%- theme.comments.waline.meta_css %>');
9
+
10
+ const el = document.getElementById("waline_container");
11
+ var path = el.getAttribute('comment_id');
12
+ if (!path) {
13
+ path = decodeURI(window.location.pathname);
14
+ }
15
+
16
+ const waline = init(Object.assign(<%- JSON.stringify(theme.comments.waline) %>, {
17
+ el: '#waline_container',
18
+ path: path,
19
+ <% if(!!theme.comments.waline.imageUploader?.api){ %>
20
+ imageUploader: function(file) {
21
+ let headers = new Headers();
22
+ headers.set('Accept', 'application/json');
23
+ <% if(!!theme.comments.waline.imageUploader?.token) { %>
24
+ headers.set('<%= theme.comments.waline.imageUploader?.tokenName %>', '<%= theme.comments.waline.imageUploader?.token %>')
25
+ <% } %>
26
+ let formData = new FormData();
27
+ formData.append('<%= theme.comments.waline.imageUploader?.fileName %>', file);
28
+ return fetch('<%= theme.comments.waline.imageUploader?.api %>',{
29
+ method: 'POST',
30
+ body: formData,
31
+ headers: headers
32
+ }).then((resp) => resp.json())
33
+ .then((resp) => resp.<%= theme.comments.waline.imageUploader?.resp %>)
34
+ },
35
+ <% } %>
36
+ }));
37
+
38
+ }
39
+ window.addEventListener('DOMContentLoaded', (event) => {
40
+ load_comment();
41
+ });
42
+
43
+ </script>
@@ -128,6 +128,5 @@ function custom_inject() {
128
128
  <%- css(theme.style.codeblock.highlightjs_theme) %>
129
129
  <% } %>
130
130
 
131
- <%- partial('plugins/parser/head') %>
132
131
  <%- custom_inject() %>
133
132
  </head>
@@ -64,7 +64,7 @@ function layoutDiv() {
64
64
  }
65
65
  }
66
66
  if (author) {
67
- license = license.replace('${author.name}', author.name).replace('${author.url}', author.url)
67
+ license = license.replace('{author.name}', author.name).replace('{author.url}', author.url)
68
68
  }
69
69
  el += `
70
70
  <section id="license">
@@ -1,5 +1,5 @@
1
1
  <%
2
- const content = theme.footer.content?.replace('${author.name}', (config.author || 'Anonymity'))?.replace('${theme.name}', stellar_info('name'))?.replace('${theme.version}', stellar_info('version'))?.replace('${theme.tree}', stellar_info('tree'))
2
+ const content = theme.footer.content?.replace('{author.name}', (config.author || 'Anonymity'))?.replace('{theme.name}', stellar_info('name'))?.replace('{theme.version}', stellar_info('version'))?.replace('{theme.tree}', stellar_info('tree'))
3
3
  function layoutDiv() {
4
4
  var el = ''
5
5
  el += `<footer class="page-footer${scrollreveal(' ')} footnote">`
@@ -1,30 +1,94 @@
1
1
  <%
2
2
 
3
- var banner_url
3
+ var banner = {}
4
+
4
5
  if (page.banner) {
5
- banner_url = page.banner
6
+ banner.url = page.banner
6
7
  } else if (theme.topic.tree[page.topic]?.banner != null) {
7
- banner_url = theme.topic.tree[page.topic]?.banner
8
+ banner.url = theme.topic.tree[page.topic]?.banner
8
9
  } else if (theme.wiki.tree[page.wiki]?.banner != null) {
9
- banner_url = theme.wiki.tree[page.wiki]?.banner
10
+ banner.url = theme.wiki.tree[page.wiki]?.banner
11
+ }
12
+ banner = Object.assign(banner, page.banner_info)
13
+ // 标题
14
+ if (banner.title == null) {
15
+ banner.title = page.h1 != null ? page.h1 : page.title
16
+ }
17
+ // 副标题
18
+ if (banner.subtitle == null) {
19
+ banner.subtitle = page.subtitle
20
+ }
21
+
22
+ function layoutBreadcrumb() {
23
+ if (page.breadcrumb === false) {
24
+ return `<div class="top"></div>`
25
+ }
26
+ var el = ''
27
+ // 1.main
28
+ el += `<div class="top bread-nav footnote">`
29
+ // 2.left
30
+ el += `<div class="left">`
31
+ // 3.left.top: 面包屑导航
32
+ el += `<div class="flex-row" id="breadcrumb">`
33
+ // 首页
34
+ el += `<a class="cap breadcrumb" href="${url_for(config.root)}">${__("btn.home")}</a>`
35
+ if (theme.wiki.tree[page.wiki]) {
36
+ el += partial('breadcrumb/wiki')
37
+ } else if (page.layout == 'post') {
38
+ el += partial('breadcrumb/blog')
39
+ } else {
40
+ el += partial('breadcrumb/page')
41
+ }
42
+ // end 3.left.top
43
+ el += `</div>`
44
+ // 3.left.bottom
45
+ el += partial('dateinfo')
46
+ // end 2.left
47
+ el += `</div>`
48
+ // end 1.main
49
+ el += `</div>`
50
+ return el
10
51
  }
11
52
 
12
53
  function layoutTitle() {
13
- const title = page.h1 != null ? page.h1 : page.title
14
- if (title && title.length > 0) {
15
- return `<h1 class="text title"><span>${title}</span></h1>`
54
+ if (banner.title?.length > 0) {
55
+ return `<h1 class="text title"><span>${banner.title}</span></h1>`
56
+ } else {
57
+ return ''
58
+ }
59
+ }
60
+
61
+ function layoutSubtitle() {
62
+ if (banner.subtitle?.length > 0) {
63
+ return `<div class="text subtitle">${banner.subtitle}</div>`
64
+ } else {
65
+ return ''
66
+ }
67
+ }
68
+
69
+ function layoutIcon() {
70
+ if (banner.avatar?.length > 0 || banner.icon?.length > 0) {
71
+ return `<img class="avatar" src="${banner.avatar || banner.icon}">`
16
72
  } else {
17
73
  return ''
18
74
  }
19
75
  }
20
76
 
21
77
  function layoutBottom() {
22
- const article_title = layoutTitle()
23
- if (article_title.length > 0) {
78
+ const el_icon = layoutIcon()
79
+ const el_title = layoutTitle()
80
+ const el_subtitle = layoutSubtitle()
81
+ var cls = ''
82
+ if (el_title.length > 0 && el_subtitle.length == 0) {
83
+ cls += ' only-title'
84
+ }
85
+ if (el_title.length > 0) {
24
86
  return `
25
- <div class="bottom">
87
+ <div class="bottom${cls}">
88
+ ${el_icon}
26
89
  <div class="text-area">
27
- ${article_title}
90
+ ${el_title}
91
+ ${el_subtitle}
28
92
  </div>
29
93
  </div>
30
94
  `
@@ -34,18 +98,18 @@ function layoutBottom() {
34
98
  }
35
99
 
36
100
  function layoutDiv() {
37
- const top = partial('article_top_area')
38
101
  const bottom = layoutBottom()
39
- if (top.trim().length == 0 && bottom.length == 0) {
102
+ if (page.breadcrumb === false && bottom.length == 0) {
40
103
  return ``
41
104
  }
105
+ const top = layoutBreadcrumb()
42
106
  var style = ``
43
107
  var el = ``
44
108
  el += `<div class="article banner top">`
45
- if (banner_url?.length > 0) {
46
- el += `<img class="bg" src="${banner_url}">`
47
- if (page.poster?.color) {
48
- style += ' style="--text-banner:' + page.poster?.color + '"'
109
+ if (banner.url?.length > 0) {
110
+ el += `<img class="bg" src="${banner.url}">`
111
+ if (banner.color) {
112
+ style += ' style="--text-banner:' + banner.color + '"'
49
113
  }
50
114
  }
51
115
  el += `
@@ -5,7 +5,7 @@ function layoutDiv() {
5
5
  return ''
6
6
  }
7
7
  return `
8
- <div class="right ghrepo stellar-ghinfo-api" api="${theme.api_host.ghapi}/repos/${repo}">
8
+ <div class="right ghrepo ds-ghinfo" api="${theme.api_host.ghapi}/repos/${repo}">
9
9
  <a class="repo-link bold" href="https://github.com/${repo}">
10
10
  ${icon('github:repo')}
11
11
  <span type="text">${repo}</span>
@@ -51,7 +51,7 @@ function div_default() {
51
51
 
52
52
  // 摘要
53
53
  el += '<div class="excerpt';
54
- if (theme.plugins.heti && theme.plugins.heti.enable) {
54
+ if (theme.plugins.heti?.enable) {
55
55
  el += ' heti';
56
56
  }
57
57
  el += '">';
@@ -1,5 +1,8 @@
1
- <div class='float-panel mobile-only blur' style='display:none'>
2
- <button type='button' class='sidebar-toggle mobile' onclick='sidebar.toggle()'>
3
- <%- icon('default:sidebar') %>
1
+ <div class='float-panel blur'>
2
+ <button type='button' style='display:none' class='laptop-only rightbar-toggle mobile' onclick='sidebar.rightbar()'>
3
+ <%- icon('default:rightbar') %>
4
+ </button>
5
+ <button type='button' style='display:none' class='mobile-only leftbar-toggle mobile' onclick='sidebar.leftbar()'>
6
+ <%- icon('default:leftbar') %>
4
7
  </button>
5
8
  </div>
@@ -0,0 +1,31 @@
1
+ <script type="text/javascript">
2
+ const ctx = {
3
+ date_suffix: {
4
+ just: `<%- __('meta.date_suffix.just') %>`,
5
+ min: `<%- __('meta.date_suffix.min') %>`,
6
+ hour: `<%- __('meta.date_suffix.hour') %>`,
7
+ day: `<%- __('meta.date_suffix.day') %>`,
8
+ },
9
+ root : `<%- config.root %>`,
10
+ };
11
+
12
+ // required plugins (only load if needs)
13
+ if (`<%- theme.search.service %>`) {
14
+ ctx.search = {};
15
+ ctx.search.service = `<%- theme.search.service %>`;
16
+ if (ctx.search.service == 'local_search') {
17
+ let service_obj = Object.assign({}, `<%- JSON.stringify(theme.search.local_search) %>`);
18
+ ctx.search[ctx.search.service] = service_obj;
19
+ }
20
+ }
21
+ const def = {
22
+ avatar: `<%- theme.default.avatar %>`,
23
+ cover: `<%- theme.default.cover %>`,
24
+ };
25
+ const deps = {
26
+ jquery: `<%- url_for(theme.dependencies.jquery) %>`,
27
+ marked: `<%- url_for(theme.dependencies.marked) %>`
28
+ }
29
+
30
+
31
+ </script>
@@ -0,0 +1,29 @@
1
+ <script defer>
2
+ window.addEventListener('DOMContentLoaded', (event) => {
3
+ ctx.services = Object.assign({}, JSON.parse(`<%- JSON.stringify(theme.data_services) %>`));
4
+ for (let id of Object.keys(ctx.services)) {
5
+ const js = ctx.services[id].js;
6
+ if (id == 'siteinfo') {
7
+ ctx.cardlinks = document.querySelectorAll('a.link-card[cardlink]');
8
+ if (ctx.cardlinks?.length > 0) {
9
+ utils.js(js, { defer: true }).then(function () {
10
+ setCardLink(ctx.cardlinks);
11
+ });
12
+ }
13
+ } else {
14
+ const els = document.getElementsByClassName(`ds-${id}`);
15
+ if (els?.length > 0) {
16
+ utils.jq(() => {
17
+ if (id == 'timeline' || 'memos' || 'marked') {
18
+ utils.js(deps.marked).then(function () {
19
+ utils.js(js, { defer: true });
20
+ });
21
+ } else {
22
+ utils.js(js, { defer: true });
23
+ }
24
+ });
25
+ }
26
+ }
27
+ }
28
+ });
29
+ </script>
@@ -0,0 +1,25 @@
1
+ <script>
2
+ const sidebar = {
3
+ leftbar: () => {
4
+ if (l_body) {
5
+ l_body.toggleAttribute('leftbar');
6
+ l_body.removeAttribute('rightbar');
7
+ }
8
+ },
9
+ rightbar: () => {
10
+ if (l_body) {
11
+ l_body.toggleAttribute('rightbar');
12
+ l_body.removeAttribute('leftbar');
13
+ }
14
+ },
15
+ dismiss: () => {
16
+ if (l_body) {
17
+ l_body.removeAttribute('leftbar');
18
+ l_body.removeAttribute('rightbar');
19
+ }
20
+ },
21
+ toggleTOC: () => {
22
+ document.querySelector('#data-toc').classList.toggle('collapse');
23
+ }
24
+ }
25
+ </script>
@@ -0,0 +1,158 @@
1
+ <script type="text/javascript">
2
+ const utils = {
3
+ // 懒加载 css https://github.com/filamentgroup/loadCSS
4
+ css: (href, before, media, attributes) => {
5
+ var doc = window.document;
6
+ var ss = doc.createElement("link");
7
+ var ref;
8
+ if (before) {
9
+ ref = before;
10
+ } else {
11
+ var refs = (doc.body || doc.getElementsByTagName("head")[0]).childNodes;
12
+ ref = refs[refs.length - 1];
13
+ }
14
+ var sheets = doc.styleSheets;
15
+ if (attributes) {
16
+ for (var attributeName in attributes) {
17
+ if (attributes.hasOwnProperty(attributeName)) {
18
+ ss.setAttribute(attributeName, attributes[attributeName]);
19
+ }
20
+ }
21
+ }
22
+ ss.rel = "stylesheet";
23
+ ss.href = href;
24
+ ss.media = "only x";
25
+ function ready(cb) {
26
+ if (doc.body) {
27
+ return cb();
28
+ }
29
+ setTimeout(function () {
30
+ ready(cb);
31
+ });
32
+ }
33
+ ready(function () {
34
+ ref.parentNode.insertBefore(ss, before ? ref : ref.nextSibling);
35
+ });
36
+ var onloadcssdefined = function (cb) {
37
+ var resolvedHref = ss.href;
38
+ var i = sheets.length;
39
+ while (i--) {
40
+ if (sheets[i].href === resolvedHref) {
41
+ return cb();
42
+ }
43
+ }
44
+ setTimeout(function () {
45
+ onloadcssdefined(cb);
46
+ });
47
+ };
48
+ function loadCB() {
49
+ if (ss.addEventListener) {
50
+ ss.removeEventListener("load", loadCB);
51
+ }
52
+ ss.media = media || "all";
53
+ }
54
+ if (ss.addEventListener) {
55
+ ss.addEventListener("load", loadCB);
56
+ }
57
+ ss.onloadcssdefined = onloadcssdefined;
58
+ onloadcssdefined(loadCB);
59
+ return ss;
60
+ },
61
+
62
+ js: (src, opt) => new Promise((resolve, reject) => {
63
+ var script = document.createElement('script');
64
+ if (src.startsWith('/')){
65
+ src = ctx.root + src.substring(1);
66
+ }
67
+ script.src = src;
68
+ if (opt) {
69
+ for (let key of Object.keys(opt)) {
70
+ script[key] = opt[key]
71
+ }
72
+ } else {
73
+ // 默认异步,如果需要同步,第二个参数传入 {} 即可
74
+ script.async = true
75
+ }
76
+ script.onerror = reject
77
+ script.onload = script.onreadystatechange = function() {
78
+ const loadState = this.readyState
79
+ if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
80
+ script.onload = script.onreadystatechange = null
81
+ resolve()
82
+ }
83
+ document.head.appendChild(script)
84
+ }),
85
+
86
+ jq: (fn) => {
87
+ if (typeof jQuery === 'undefined') {
88
+ utils.js(deps.jquery).then(fn)
89
+ } else {
90
+ fn()
91
+ }
92
+ },
93
+
94
+ onLoading: (el) => {
95
+ if (el) {
96
+ $(el).append('<div class="loading-wrap"><svg xmlns="http://www.w3.org/2000/svg" width="2em" height="2em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="2"><path stroke-dasharray="60" stroke-dashoffset="60" stroke-opacity=".3" d="M12 3C16.9706 3 21 7.02944 21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3Z"><animate fill="freeze" attributeName="stroke-dashoffset" dur="1.3s" values="60;0"/></path><path stroke-dasharray="15" stroke-dashoffset="15" d="M12 3C16.9706 3 21 7.02944 21 12"><animate fill="freeze" attributeName="stroke-dashoffset" dur="0.3s" values="15;0"/><animateTransform attributeName="transform" dur="1.5s" repeatCount="indefinite" type="rotate" values="0 12 12;360 12 12"/></path></g></svg></div>');
97
+ }
98
+ },
99
+ onLoadSuccess: (el) => {
100
+ if (el) {
101
+ $(el).find('.loading-wrap').remove();
102
+ }
103
+ },
104
+ onLoadFailure: (el) => {
105
+ if (el) {
106
+ $(el).find('.loading-wrap svg').remove();
107
+ $(el).find('.loading-wrap').append('<svg xmlns="http://www.w3.org/2000/svg" width="2em" height="2em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path stroke-dasharray="60" stroke-dashoffset="60" d="M12 3L21 20H3L12 3Z"><animate fill="freeze" attributeName="stroke-dashoffset" dur="0.5s" values="60;0"/></path><path stroke-dasharray="6" stroke-dashoffset="6" d="M12 10V14"><animate fill="freeze" attributeName="stroke-dashoffset" begin="0.6s" dur="0.2s" values="6;0"/></path></g><circle cx="12" cy="17" r="1" fill="currentColor" fill-opacity="0"><animate fill="freeze" attributeName="fill-opacity" begin="0.8s" dur="0.4s" values="0;1"/></circle></svg>');
108
+ $(el).find('.loading-wrap').addClass('error');
109
+ }
110
+ },
111
+ request: (el, url, callback, onFailure) => {
112
+ let retryTimes = 3;
113
+ utils.onLoading(el);
114
+ function req() {
115
+ return new Promise((resolve, reject) => {
116
+ let status = 0; // 0 等待 1 完成 2 超时
117
+ let timer = setTimeout(() => {
118
+ if (status === 0) {
119
+ status = 2;
120
+ timer = null;
121
+ reject('请求超时');
122
+ if (retryTimes == 0) {
123
+ onFailure();
124
+ }
125
+ }
126
+ }, 5000);
127
+ fetch(url).then(function(response) {
128
+ if (status !== 2) {
129
+ clearTimeout(timer);
130
+ resolve(response);
131
+ timer = null;
132
+ status = 1;
133
+ }
134
+ if (response.ok) {
135
+ return response.json();
136
+ }
137
+ throw new Error('Network response was not ok.');
138
+ }).then(function(data) {
139
+ retryTimes = 0;
140
+ utils.onLoadSuccess(el);
141
+ callback(data);
142
+ }).catch(function(error) {
143
+ if (retryTimes > 0) {
144
+ retryTimes -= 1;
145
+ setTimeout(() => {
146
+ req();
147
+ }, 5000);
148
+ } else {
149
+ utils.onLoadFailure(el);
150
+ onFailure();
151
+ }
152
+ });
153
+ });
154
+ }
155
+ req();
156
+ },
157
+ };
158
+ </script>
@@ -0,0 +1,32 @@
1
+ <%
2
+
3
+ function custom_inject() {
4
+ var el = '';
5
+ for (let item of (config.inject?.script || [])) {
6
+ el += item;
7
+ }
8
+ for (let item of (theme.inject?.script || [])) {
9
+ el += item;
10
+ }
11
+ for (let item of (page.inject?.script || [])) {
12
+ el += item;
13
+ }
14
+ return el;
15
+ }
16
+
17
+ %>
18
+ <%- partial('scripts/defines') %>
19
+ <%- partial('scripts/utils') %>
20
+ <%- partial('scripts/sidebar') %>
21
+
22
+ <!-- required -->
23
+ <script src="<%- `${theme.stellar.main_js}?v=${stellar_info('version')}` %>" async></script>
24
+
25
+ <!-- optional -->
26
+ <%- partial('comments/script') %>
27
+
28
+ <%- partial('scripts/services') %>
29
+ <%- partial('../_plugins/index') %>
30
+
31
+ <!-- inject -->
32
+ <%- custom_inject() %>
@@ -3,50 +3,52 @@
3
3
  const wiki = theme.wiki.tree[page.wiki]
4
4
  const topic = theme.topic.tree[page.topic]
5
5
 
6
- if (page.sidebar == null) {
6
+ if (page.leftbar == null) {
7
7
  const { site_tree } = theme
8
8
  var sidebar
9
9
  if (is_home()) {
10
- sidebar = site_tree.home.sidebar
10
+ sidebar = site_tree.home.leftbar
11
11
  } else if (is_category() || is_tag() || is_archive() || ['categories', 'tags', 'archives'].includes(page.layout)) {
12
- sidebar = site_tree.index_blog.sidebar
12
+ sidebar = site_tree.index_blog.leftbar
13
13
  } else if (page.layout === 'index_topic') {
14
14
  // 专栏列表页等同于博客列表页
15
- sidebar = site_tree.index_blog.sidebar
15
+ sidebar = site_tree.index_blog.leftbar
16
16
  } else if (page.topic?.length > 0) {
17
17
  // 专栏文章内页等同于普通文章内页
18
- sidebar = site_tree.post.sidebar
18
+ sidebar = site_tree.post.leftbar
19
19
  } else if (page.layout === 'index_wiki') {
20
- sidebar = site_tree.index_wiki.sidebar
20
+ sidebar = site_tree.index_wiki.leftbar
21
21
  } else if (page.wiki?.length > 0) {
22
- sidebar = site_tree.wiki.sidebar
22
+ sidebar = site_tree.wiki.leftbar
23
23
  } else if (page.layout === '404') {
24
- sidebar = site_tree.error_page.sidebar
24
+ sidebar = site_tree.error_page.leftbar
25
25
  } else if (page.layout === 'page') {
26
- sidebar = site_tree.page.sidebar
26
+ sidebar = site_tree.page.leftbar
27
27
  } else if (page.layout === 'post') {
28
- sidebar = site_tree.post.sidebar
28
+ sidebar = site_tree.post.leftbar
29
29
  } else if (page.layout == null) {
30
- sidebar = site_tree.page.sidebar
30
+ sidebar = site_tree.page.leftbar
31
31
  } else {
32
32
  sidebar = []
33
33
  }
34
34
 
35
- if (topic?.sidebar) {
36
- sidebar = topic.sidebar
35
+ if (topic?.leftbar) {
36
+ sidebar = topic.leftbar
37
37
  }
38
- if (wiki?.sidebar) {
39
- sidebar = wiki.sidebar
38
+ if (wiki?.leftbar) {
39
+ sidebar = wiki.leftbar
40
40
  }
41
41
 
42
- page.sidebar = sidebar
42
+ page.leftbar = sidebar
43
43
  }
44
44
 
45
45
 
46
46
  // parse array string
47
- if (typeof page.sidebar == 'string') {
48
- page.sidebar = page.sidebar.replace(/ /g, '').split(',');
47
+ if (typeof page.leftbar == 'string') {
48
+ page.leftbar = page.leftbar.replace(/ /g, '').split(',');
49
49
  }
50
+
51
+
50
52
  function layoutTitle(main, url, sub) {
51
53
  var el = '';
52
54
  el += '<a class="title" href="' + url_for(url || "/") + '">';
@@ -66,8 +68,8 @@ function layoutTitle(main, url, sub) {
66
68
  function layoutWidgets() {
67
69
  var el = '';
68
70
  el += '<div class="widgets">';
69
- if (page.sidebar) {
70
- page.sidebar.forEach((w, i) => {
71
+ if (page.leftbar) {
72
+ page.leftbar.forEach((w, i) => {
71
73
  let name = ''
72
74
  let widget = {}
73
75
  if (typeof w == 'string') {
@@ -0,0 +1,84 @@
1
+ <%
2
+
3
+ const wiki = theme.wiki.tree[page.wiki]
4
+ const topic = theme.topic.tree[page.topic]
5
+
6
+ if (page.rightbar == null) {
7
+ const { site_tree } = theme
8
+ var sidebar
9
+ if (is_home()) {
10
+ sidebar = site_tree.home.rightbar
11
+ } else if (is_category() || is_tag() || is_archive() || ['categories', 'tags', 'archives'].includes(page.layout)) {
12
+ sidebar = site_tree.index_blog.rightbar
13
+ } else if (page.layout === 'index_topic') {
14
+ // 专栏列表页等同于博客列表页
15
+ sidebar = site_tree.index_blog.rightbar
16
+ } else if (page.topic?.length > 0) {
17
+ // 专栏文章内页等同于普通文章内页
18
+ sidebar = site_tree.post.rightbar
19
+ } else if (page.layout === 'index_wiki') {
20
+ sidebar = site_tree.index_wiki.rightbar
21
+ } else if (page.wiki?.length > 0) {
22
+ sidebar = site_tree.wiki.rightbar
23
+ } else if (page.layout === '404') {
24
+ sidebar = site_tree.error_page.rightbar
25
+ } else if (page.layout === 'page') {
26
+ sidebar = site_tree.page.rightbar
27
+ } else if (page.layout === 'post') {
28
+ sidebar = site_tree.post.rightbar
29
+ } else if (page.layout == null) {
30
+ sidebar = site_tree.page.rightbar
31
+ } else {
32
+ sidebar = []
33
+ }
34
+
35
+ if (topic?.rightbar) {
36
+ sidebar = topic.rightbar
37
+ }
38
+ if (wiki?.rightbar) {
39
+ sidebar = wiki.rightbar
40
+ }
41
+
42
+ page.rightbar = sidebar
43
+ }
44
+
45
+
46
+ // parse array string
47
+ if (typeof page.rightbar == 'string') {
48
+ page.rightbar = page.rightbar.replace(/ /g, '').split(',');
49
+ }
50
+
51
+ function layoutWidgets() {
52
+ if (page.rightbar == null || page.rightbar.length == 0) {
53
+ return ''
54
+ }
55
+ var el = ''
56
+ if (page.rightbar) {
57
+ page.rightbar.forEach((w, i) => {
58
+ let name = ''
59
+ let widget = {}
60
+ if (typeof w == 'string') {
61
+ name = w
62
+ } else if (typeof w == 'object' && w.override) {
63
+ name = w.override
64
+ }
65
+ if (name in theme.widgets) {
66
+ Object.assign(widget, theme.widgets[name])
67
+ }
68
+ if (typeof w == 'object' && (w.override || w.layout)) {
69
+ Object.assign(widget, w)
70
+ }
71
+ if (widget && widget.layout) {
72
+ el += partial('../widgets/' + widget.layout, {item: widget})
73
+ }
74
+ });
75
+ }
76
+ if (el.trim().length > 0) {
77
+ return `<div class="widgets">${el}</div>`
78
+ } else {
79
+ return ''
80
+ }
81
+ }
82
+
83
+ %>
84
+ <%- layoutWidgets() %>