hexo-theme-stellar 1.31.0 → 1.32.1

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 (67) hide show
  1. package/_config.yml +15 -13
  2. package/_data/icons.yml +3 -3
  3. package/layout/_partial/comments/artalk/script.ejs +1 -2
  4. package/layout/_partial/comments/layout.ejs +1 -1
  5. package/layout/_partial/head.ejs +15 -3
  6. package/layout/_partial/scripts/theme.ejs +3 -3
  7. package/layout/_partial/sidebar/index_leftbar.ejs +9 -9
  8. package/layout/index.ejs +3 -1
  9. package/layout/layout.ejs +3 -2
  10. package/package.json +4 -2
  11. package/scripts/events/index.js +39 -2
  12. package/scripts/events/lib/fix_image_tags.js +44 -0
  13. package/scripts/events/lib/get_image_ratios.js +110 -0
  14. package/scripts/events/lib/version-check.js +2 -0
  15. package/scripts/helpers/json_ld.js +5 -1
  16. package/scripts/tags/index.js +1 -1
  17. package/scripts/tags/lib/{quote.js → blockquote.js} +5 -5
  18. package/scripts/tags/lib/image.js +16 -6
  19. package/scripts/tags/lib/navbar.js +2 -2
  20. package/scripts/tags/lib/timeline.js +1 -1
  21. package/scripts/tags/lib/video.js +2 -2
  22. package/source/css/_common/base.styl +16 -6
  23. package/source/css/_common/canonical.styl +1 -1
  24. package/source/css/_common/highlight.styl +5 -2
  25. package/source/css/_components/layout.styl +11 -10
  26. package/source/css/_components/list.styl +3 -0
  27. package/source/css/_components/main.styl +1 -1
  28. package/source/css/_components/md.styl +4 -2
  29. package/source/css/_components/pages/archives.styl +2 -2
  30. package/source/css/_components/pages/article-story.styl +40 -32
  31. package/source/css/_components/pages/article-tech.styl +1 -1
  32. package/source/css/_components/pages/notebook.styl +1 -1
  33. package/source/css/_components/partial/article-banner.styl +4 -1
  34. package/source/css/_components/partial/footer.styl +1 -1
  35. package/source/css/_components/partial/navbar.styl +2 -1
  36. package/source/css/_components/sidebar/nav-area.styl +1 -1
  37. package/source/css/_components/sidebar/search.styl +44 -21
  38. package/source/css/_components/sidebar/sidebar.styl +9 -5
  39. package/source/css/_components/tag-plugins/banner.styl +1 -1
  40. package/source/css/_components/tag-plugins/button.styl +3 -4
  41. package/source/css/_components/tag-plugins/copy.styl +12 -8
  42. package/source/css/_components/tag-plugins/friends.styl +1 -1
  43. package/source/css/_components/tag-plugins/gallery.styl +6 -0
  44. package/source/css/_components/tag-plugins/image.styl +10 -0
  45. package/source/css/_components/tag-plugins/navbar.styl +18 -8
  46. package/source/css/_components/tag-plugins/note.styl +0 -3
  47. package/source/css/_components/tag-plugins/override.styl +0 -5
  48. package/source/css/_components/tag-plugins/quot.styl +2 -2
  49. package/source/css/_components/tag-plugins/quote.styl +1 -1
  50. package/source/css/_components/tag-plugins/tabs.styl +4 -3
  51. package/source/css/_components/tag-plugins/timeline.styl +2 -2
  52. package/source/css/_components/tag-plugins/toc.styl +1 -1
  53. package/source/css/_components/widgets/list.styl +1 -1
  54. package/source/css/_components/widgets/markdown.styl +0 -7
  55. package/source/css/_components/widgets/toc.styl +7 -5
  56. package/source/css/_components/widgets/widgets.styl +0 -5
  57. package/source/css/_custom.styl +5 -7
  58. package/source/css/_defines/const.styl +1 -1
  59. package/source/css/_defines/func.styl +9 -5
  60. package/source/css/_defines/theme.styl +4 -15
  61. package/source/css/_plugins/comments/artalk.styl +114 -2
  62. package/source/css/_plugins/comments/twikoo.styl +3 -3
  63. package/source/css/_plugins/index.styl +5 -5
  64. package/source/css/_plugins/lazyload.styl +49 -2
  65. package/source/js/search/local-search.js +163 -151
  66. package/source/js/services/artalk_latest_comment.js +1 -1
  67. package/layout/_partial/widgets/search.ejs +0 -0
@@ -1,170 +1,182 @@
1
- // A local search script with the help of
2
- // [hexo-generator-search](https://github.com/PaicHyperionDev/hexo-generator-search)
3
- // Copyright (C) 2015
4
- // Joseph Pan <http://github.com/wzpan>
5
- // Shuhao Mao <http://github.com/maoshuhao>
6
- // This library is free software; you can redistribute it and/or modify
7
- // it under the terms of the GNU Lesser General Public License as
8
- // published by the Free Software Foundation; either version 2.1 of the
9
- // License, or (at your option) any later version.
10
- //
11
- // This library is distributed in the hope that it will be useful, but
12
- // WITHOUT ANY WARRANTY; without even the implied warranty of
13
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
- // Lesser General Public License for more details.
15
- //
16
- // You should have received a copy of the GNU Lesser General Public
17
- // License along with this library; if not, write to the Free Software
18
- // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
- // 02110-1301 USA
20
- //
21
- // Modified by:
22
- // Pieter Robberechts <http://github.com/probberechts>
23
-
24
- /*exported searchFunc*/
1
+ var searchCache = null;
2
+ var searchCacheKey = 'search_cache_v1';
3
+
25
4
  var searchFunc = function(path, filter, wrapperId, searchId, contentId) {
26
5
 
27
6
  function getAllCombinations(keywords) {
28
- var i, j, result = [];
29
-
30
- for (i = 0; i < keywords.length; i++) {
31
- for (j = i + 1; j < keywords.length + 1; j++) {
32
- result.push(keywords.slice(i, j).join(" "));
33
- }
7
+ const result = [];
8
+ const maxLen = 3; // 组合最大长度
9
+ for (let i = 0; i < keywords.length; i++) {
10
+ for (let j = i + 1; j <= Math.min(i + maxLen, keywords.length); j++) {
11
+ result.push(keywords.slice(i, j).join(" "));
12
+ }
34
13
  }
35
14
  return result;
36
15
  }
37
16
 
38
- $.ajax({
39
- url: path,
40
- dataType: "json",
41
- success: function(jsonResponse) {
42
- var datas = jsonResponse;
43
- var $input = document.getElementById(searchId);
44
- if (!$input) { return; }
45
- var $resultContent = document.getElementById(contentId);
46
- var $wrapper = document.getElementById(wrapperId);
47
-
48
- $input.addEventListener("input", function(){
49
- var resultList = [];
50
- var keywords = getAllCombinations(this.value.trim().toLowerCase().split(" "))
51
- .sort(function(a,b) { return b.split(" ").length - a.split(" ").length; });
52
- $resultContent.innerHTML = "";
53
- if (this.value.trim().length <= 0) {
54
- $wrapper.setAttribute('searching', 'false');
55
- return;
56
- }
57
- $wrapper.setAttribute('searching', 'true');
58
- // perform local searching
59
- datas.forEach(function(data) {
60
- if (!data.content?.trim().length) { return }
61
- var matches = 0;
62
- if (filter && !data.path.includes(filter)) { return }
63
- var dataTitle = data.title?.trim() || 'Untitled';
64
- var dataTitleLowerCase = dataTitle.toLowerCase();
65
- var dataContent = data.content;
66
- var dataContentLowerCase = dataContent.toLowerCase();
67
- var dataUrl = data.path.startsWith('//') ? data.path.slice(1) : data.path; // 避免文章设置永久链接导致点击打开失败
68
- var indexTitle = -1;
69
- var indexContent = -1;
70
- var firstOccur = -1;
71
- // only match artiles with not empty contents
72
- if (dataContent !== "") {
73
- keywords.forEach(function(keyword) {
74
- indexTitle = dataTitleLowerCase.indexOf(keyword);
75
- indexContent = dataContentLowerCase.indexOf(keyword);
76
-
77
- if( indexTitle >= 0 || indexContent >= 0 ){
78
- matches += 1;
79
- if (indexContent < 0) {
80
- indexContent = 0;
81
- }
82
- if (firstOccur < 0) {
83
- firstOccur = indexContent;
84
- }
85
- }
86
- });
87
- }
88
- // show search results
89
- if (matches > 0) {
90
- var searchResult = {};
91
- searchResult.rank = matches;
92
- searchResult.str = "<li><a href='"+ dataUrl +"'><span class='search-result-title'>"+ dataTitle +"</span>";
93
- if (firstOccur >= 0) {
94
- // cut out 100 characters
95
- var start = firstOccur - 20;
96
- var end = firstOccur + 80;
97
-
98
- if(start < 0){
99
- start = 0;
100
- }
101
-
102
- if(start == 0){
103
- end = 100;
104
- }
105
-
106
- if(end > dataContent.length){
107
- end = dataContent.length;
108
- }
109
-
110
- var matchContent = dataContent.substring(start, end);
111
-
112
- // highlight all keywords
113
- var regS = new RegExp(keywords.join("|"), "gi");
114
- matchContent = matchContent.replace(regS, function(keyword) {
115
- return "<span class=\"search-keyword\">"+keyword+"</span>";
116
- });
117
-
118
- searchResult.str += "<p class=\"search-result-content\">" + matchContent +"...</p>";
119
- }
120
- searchResult.str += "</a></li>";
121
- resultList.push(searchResult);
17
+ function escapeRegExp(string) {
18
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
19
+ }
20
+
21
+ function initSearch(datas) {
22
+ var $input = document.getElementById(searchId);
23
+ if (!$input) { return; }
24
+ if ($input._searchInitialized) return; // 防止重复绑定
25
+ $input._searchInitialized = true;
26
+
27
+ var $resultContent = document.getElementById(contentId);
28
+ var $wrapper = document.getElementById(wrapperId);
29
+
30
+ $input.addEventListener("input", function() {
31
+ var resultList = [];
32
+ var keywords = getAllCombinations(this.value.trim().toLowerCase().split(" "))
33
+ .sort(function(a,b) { return b.split(" ").length - a.split(" ").length; });
34
+ $resultContent.innerHTML = "";
35
+ if (this.value.trim().length <= 0) {
36
+ $wrapper.setAttribute('searching', 'false');
37
+ return;
38
+ }
39
+ $wrapper.setAttribute('searching', 'true');
40
+
41
+ datas.forEach(function(data) {
42
+ if (!data.content?.trim().length) return;
43
+ if (filter && !data.path.includes(filter)) return;
44
+
45
+ var matches = 0;
46
+ var dataTitle = data.title?.trim() || 'Untitled';
47
+ var dataTitleLowerCase = dataTitle.toLowerCase();
48
+ var dataContent = data.content;
49
+ var dataContentLowerCase = dataContent.toLowerCase();
50
+ var dataUrl = data.path.startsWith('//') ? data.path.slice(1) : data.path;
51
+
52
+ var indexTitle = -1;
53
+ var indexContent = -1;
54
+ var firstOccur = -1;
55
+
56
+ keywords.forEach(function(keyword) {
57
+ indexTitle = dataTitleLowerCase.indexOf(keyword);
58
+ indexContent = dataContentLowerCase.indexOf(keyword);
59
+ if (indexTitle >= 0 || indexContent >= 0) {
60
+ matches += 1;
61
+ if (indexContent < 0) indexContent = 0;
62
+ if (firstOccur < 0) firstOccur = indexContent;
122
63
  }
123
64
  });
124
- if (resultList.length) {
125
- resultList.sort(function(a, b) {
126
- return b.rank - a.rank;
127
- });
128
- var result ="<ul class=\"search-result-list\">";
129
- for (var i = 0; i < resultList.length; i++) {
130
- result += resultList[i].str;
65
+
66
+ if (matches > 0) {
67
+ const li = document.createElement('li');
68
+ const a = document.createElement('a');
69
+ a.href = dataUrl;
70
+
71
+ const titleSpan = document.createElement('span');
72
+ titleSpan.className = 'search-result-title';
73
+ titleSpan.textContent = dataTitle;
74
+ a.appendChild(titleSpan);
75
+
76
+ if (firstOccur >= 0) {
77
+ var start = Math.max(0, firstOccur - 20);
78
+ var end = Math.min(dataContent.length, firstOccur + 80);
79
+ if (start === 0) end = 100;
80
+ var matchContent = dataContent.substring(start, end);
81
+
82
+ var regS = new RegExp(keywords.map(escapeRegExp).join("|"), "gi");
83
+ matchContent = matchContent.replace(regS, function(keyword) {
84
+ return "<span class=\"search-keyword\">" + keyword + "</span>";
85
+ });
86
+
87
+ const para = document.createElement('p');
88
+ para.className = 'search-result-content';
89
+ para.innerHTML = matchContent + '...';
90
+ a.appendChild(para);
131
91
  }
132
- result += "</ul>";
133
- $resultContent.innerHTML = result;
92
+
93
+ li.appendChild(a);
94
+ resultList.push({ rank: matches, element: li });
134
95
  }
135
96
  });
136
- }
137
- });
97
+
98
+ if (resultList.length) {
99
+ resultList.sort(function(a, b) {
100
+ return b.rank - a.rank;
101
+ });
102
+
103
+ const ul = document.createElement('ul');
104
+ ul.className = 'search-result-list';
105
+ resultList.forEach(function(item) {
106
+ ul.appendChild(item.element);
107
+ });
108
+
109
+ $resultContent.innerHTML = '';
110
+ $resultContent.appendChild(ul);
111
+ }
112
+ });
113
+ }
114
+
115
+ if (!searchCache) {
116
+ // 数据还没准备好,延迟初始化
117
+ const timer = setInterval(() => {
118
+ if (searchCache) {
119
+ clearInterval(timer);
120
+ initSearch(searchCache);
121
+ }
122
+ }, 100);
123
+ } else {
124
+ initSearch(searchCache);
125
+ }
138
126
  };
139
127
 
140
128
  utils.jq(() => {
141
- var $inputArea = $("input#search-input");
142
- if ($inputArea.length == 0) {
143
- return;
129
+ (function preloadSearchData() {
130
+ var path = ctx.search.path;
131
+ if (path.startsWith('/')) {
132
+ path = path.substring(1);
144
133
  }
145
- var $resultArea = document.querySelector("div#search-result");
146
- $inputArea.focus(function() {
147
- var path = ctx.search.path;
148
- if (path.startsWith('/')) {
149
- path = path.substring(1);
150
- }
151
- path = ctx.root + path;
152
- const filter = $inputArea.attr('data-filter') || '';
153
- searchFunc(path, filter, 'search-wrapper', 'search-input', 'search-result');
154
- });
155
- $inputArea.keydown(function(e) {
156
- if (e.which == 13) {
157
- e.preventDefault();
134
+ path = ctx.root + path;
135
+
136
+ try {
137
+ var cached = localStorage.getItem(searchCacheKey);
138
+ if (cached) {
139
+ searchCache = JSON.parse(cached);
158
140
  }
159
- });
160
- var observer = new MutationObserver(function(mutationsList, observer) {
161
- if (mutationsList.length == 1) {
162
- if (mutationsList[0].addedNodes.length) {
163
- $('.search-wrapper').removeClass('noresult');
164
- } else if (mutationsList[0].removedNodes.length) {
165
- $('.search-wrapper').addClass('noresult');
141
+ } catch (e) {
142
+ console.warn('搜索缓存解析失败', e);
143
+ }
144
+
145
+ fetch(path)
146
+ .then(res => res.json())
147
+ .then(json => {
148
+ searchCache = json;
149
+ try {
150
+ localStorage.setItem(searchCacheKey, JSON.stringify(json));
151
+ } catch (e) {
152
+ console.warn('搜索缓存写入失败', e);
166
153
  }
167
- }
168
- });
169
- observer.observe($resultArea, { childList: true });
154
+ });
155
+ })();
156
+
157
+ var $inputArea = $("input#search-input");
158
+ if ($inputArea.length == 0) return;
159
+ var $resultArea = document.querySelector("div#search-result");
160
+
161
+ $inputArea.focus(function() {
162
+ var path = ctx.search.path;
163
+ if (path.startsWith('/')) {
164
+ path = path.substring(1);
165
+ }
166
+ path = ctx.root + path;
167
+ const filter = $inputArea.attr('data-filter') || '';
168
+ searchFunc(path, filter, 'search-wrapper', 'search-input', 'search-result');
169
+ });
170
+
171
+ $inputArea.keydown(function(e) {
172
+ if (e.which == 13) {
173
+ e.preventDefault();
174
+ }
175
+ });
176
+
177
+ const observer = new MutationObserver(function(mutationsList) {
178
+ const hasResults = $resultArea.querySelector(".search-result-list li");
179
+ $('.search-wrapper').toggleClass('noresult', !hasResults);
170
180
  });
181
+ observer.observe($resultArea, { childList: true, subtree: true });
182
+ });
@@ -10,7 +10,7 @@ utils.jq(() => {
10
10
  continue;
11
11
  }
12
12
  utils.request(el, api, async resp => {
13
- const data = await resp.json();
13
+ var data = await resp.json();
14
14
  data = data.data || [];
15
15
  data.forEach((item, i) => {
16
16
  var cell = '<div class="timenode" index="' + i + '">';
File without changes