hexo-theme-stellar 1.33.1 → 1.34.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 (81) hide show
  1. package/CLAUDE.md +217 -0
  2. package/README.md +2 -0
  3. package/_config.yml +28 -14
  4. package/docs/audits/2026-08-08-stellar-analysis.md +267 -0
  5. package/docs/release-process.md +59 -0
  6. package/layout/_partial/comments/artalk/script.ejs +56 -41
  7. package/layout/_partial/comments/beaudar/script.ejs +35 -20
  8. package/layout/_partial/comments/giscus/script.ejs +34 -19
  9. package/layout/_partial/comments/twikoo/script.ejs +29 -14
  10. package/layout/_partial/comments/utterances/script.ejs +35 -20
  11. package/layout/_partial/comments/waline/script.ejs +40 -28
  12. package/layout/_partial/cover/wiki_cover.ejs +1 -1
  13. package/layout/_partial/head.ejs +53 -4
  14. package/layout/_partial/scripts/defines.ejs +21 -3
  15. package/layout/_partial/scripts/lazyload.ejs +2 -2
  16. package/layout/_partial/scripts/services.ejs +101 -41
  17. package/layout/_partial/scripts/utils.ejs +144 -5
  18. package/layout/_partial/sidebar/index_leftbar.ejs +3 -0
  19. package/layout/_partial/sidebar/search.ejs +3 -0
  20. package/layout/_partial/widgets/ghuser.ejs +18 -4
  21. package/layout/_partial/widgets/linklist.ejs +1 -1
  22. package/layout/_partial/widgets/timeline.ejs +36 -33
  23. package/layout/_plugins/copycode.ejs +9 -5
  24. package/layout/_plugins/mermaid.ejs +28 -24
  25. package/layout/_plugins/pjax.ejs +8 -0
  26. package/layout/_plugins/scrollreveal.ejs +14 -13
  27. package/layout/_plugins/swiper.ejs +2 -2
  28. package/layout/index.ejs +4 -2
  29. package/layout/index_topic.ejs +4 -2
  30. package/layout/index_wiki.ejs +6 -4
  31. package/layout/layout.ejs +3 -2
  32. package/package.json +2 -1
  33. package/scripts/commands/new-note.js +49 -0
  34. package/scripts/filters/lib/img_onerror.js +0 -2
  35. package/scripts/helpers/json_ld.js +11 -8
  36. package/scripts/helpers/pretty_url.js +5 -0
  37. package/scripts/tags/lib/chat.js +16 -9
  38. package/scripts/tags/lib/frame.js +2 -1
  39. package/scripts/tags/lib/image.js +6 -5
  40. package/scripts/tags/lib/link.js +6 -4
  41. package/scripts/tags/lib/timeline.js +101 -79
  42. package/source/css/_common/canonical.styl +11 -6
  43. package/source/css/_common/highlight.styl +4 -1
  44. package/source/css/_common/html.styl +4 -0
  45. package/source/css/_common/loading.styl +5 -1
  46. package/source/css/_components/md.styl +1 -0
  47. package/source/css/_components/pages/article-story.styl +2 -0
  48. package/source/css/_components/partial/article-footer.styl +1 -0
  49. package/source/css/_components/partial/navbar.styl +2 -0
  50. package/source/css/_components/sidebar/menu.styl +1 -0
  51. package/source/css/_components/sidebar/search.styl +4 -0
  52. package/source/css/_components/sidebar/sidebar.styl +12 -5
  53. package/source/css/_components/tag-plugins/chat.styl +6 -8
  54. package/source/css/_components/tag-plugins/folding.styl +1 -0
  55. package/source/css/_components/tag-plugins/gallery.styl +2 -0
  56. package/source/css/_components/tag-plugins/grid.styl +1 -0
  57. package/source/css/_components/tag-plugins/image.styl +3 -0
  58. package/source/css/_components/tag-plugins/link.styl +1 -0
  59. package/source/css/_components/tag-plugins/navbar.styl +15 -13
  60. package/source/css/_components/tag-plugins/note.styl +1 -0
  61. package/source/css/_components/tag-plugins/okr.styl +1 -0
  62. package/source/css/_components/tag-plugins/sites.styl +2 -0
  63. package/source/css/_components/tag-plugins/timeline.styl +9 -0
  64. package/source/css/_components/tag-plugins/vote.styl +2 -0
  65. package/source/css/_components/widgets/components.styl +1 -0
  66. package/source/css/_components/widgets/ghuser.styl +19 -3
  67. package/source/css/_components/widgets/list.styl +1 -0
  68. package/source/css/_components/widgets/toc.styl +3 -0
  69. package/source/css/_components/widgets/widgets.styl +4 -0
  70. package/source/css/_custom.styl +2 -1
  71. package/source/css/_defines/func.styl +8 -0
  72. package/source/css/_plugins/comments/artalk.styl +6 -2
  73. package/source/css/_plugins/comments/twikoo.styl +2 -0
  74. package/source/css/_plugins/index.styl +2 -0
  75. package/source/css/_plugins/pjax.styl +61 -0
  76. package/source/js/main.js +80 -26
  77. package/source/js/plugins/copycode.js +34 -27
  78. package/source/js/plugins/pjax.js +646 -0
  79. package/source/js/search/local-search.js +5 -2
  80. package/source/js/services/memos.js +42 -4
  81. package/source/js/services/rss.js +200 -0
@@ -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 || [])) {
@@ -127,18 +167,27 @@ function generate_canonical() {
127
167
  <meta name="theme-color" content="#f9fafb">
128
168
  <title><%- generate_title() %></title>
129
169
 
130
- <% if (theme.open_graph && theme.open_graph.enable) { %>
131
- <%- open_graph(og_args()) %>
132
- <% } %>
170
+ <%- render_open_graph() %>
133
171
  <%- generate_description() %>
134
172
 
135
173
  <%- generate_keywords() %>
136
174
 
137
175
  <!-- feed -->
138
176
  <% if (config.feed && config.feed.path) { %>
139
- <%- feed_tag(config.feed.path, {title: config.title}) %>
177
+ <%
178
+ var paths = Array.isArray(config.feed.path)
179
+ ? config.feed.path
180
+ : [config.feed.path];
181
+ %>
182
+
183
+ <% paths.forEach(function (path) { %>
184
+ <% if (path) { %>
185
+ <%- feed_tag(path, { title: config.title }) %>
186
+ <% } %>
187
+ <% }) %>
140
188
  <% } %>
141
189
 
190
+ <link rel="preload" href="<%- url_for(`${theme.stellar.main_css}?v=${stellar_info('version')}`) %>" as="style">
142
191
  <link rel="stylesheet" href="<%- url_for(`${theme.stellar.main_css}?v=${stellar_info('version')}`) %>">
143
192
 
144
193
 
@@ -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>
@@ -30,7 +30,7 @@
30
30
  container = document.querySelector(container);
31
31
  }
32
32
  if (!container) return;
33
-
33
+
34
34
  const images = container.querySelectorAll('img');
35
35
  images.forEach((img) => {
36
36
  if (img.classList.contains('lazy')) return;
@@ -63,5 +63,5 @@
63
63
  window.lazyLoadInstance.update();
64
64
  }
65
65
  }
66
-
66
+
67
67
  </script>