hexo-theme-linen 1.0.1 → 1.0.2

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.
@@ -50,7 +50,7 @@ const archivesList = Object.entries(site.posts.filter(post=>!post?.hide?.archive
50
50
 
51
51
 
52
52
 
53
- <% if(categoriesList.length) { %>
53
+ <% if(seriesList.length) { %>
54
54
  <br>
55
55
  <aside>
56
56
  <h2 id="series"><%=__('common.series')%></h2>
package/layout/layout.ejs CHANGED
@@ -14,7 +14,7 @@ const version = theme.version;
14
14
  <meta charset="UTF-8" />
15
15
  <meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
16
16
  <title><%=getPageTitle()%></title>
17
- <link rel="icon" type="image/x-icon" href="/favicon.svg" />
17
+ <link rel="icon" type="image/x-icon" href="<%=theme?.icon ?? '/favicon.svg'%>" />
18
18
  <meta name="referrer" content="no-referrer-when-downgrade" />
19
19
  <% if (page.hide && page.hide.seo) { %>
20
20
  <meta name="robots" content="noindex, nofollow">
@@ -29,7 +29,7 @@ const version = theme.version;
29
29
  <% theme.stylesheets.forEach(url => { %>
30
30
  <link rel="stylesheet" href="<%=url%>?v=<%=version%>" />
31
31
  <% }); %> <% } %>
32
- <% if (theme?.lazyload?.enable) { %>
32
+ <% if (theme?.lazyload?.enable ?? true) { %>
33
33
  <link rel="stylesheet" href="/css/lazyload.css?v=<%=version%>" />
34
34
  <% } %>
35
35
  <% if (theme?.heads) { %>
@@ -45,7 +45,6 @@ const version = theme.version;
45
45
  </head>
46
46
 
47
47
  <body>
48
- <div id=" "></div>
49
48
  <div id="page-top"></div>
50
49
  <%-partial('partials/header', {
51
50
  hasTocs: page?.toc ?? !!tocs?.length
@@ -99,7 +98,7 @@ const version = theme.version;
99
98
 
100
99
  <%-partial('partials/footer')%>
101
100
  <div id="mask"></div>
102
- <a id="back-to-top" href="# " title="back to top"></a>
101
+ <a id="back-to-top" href="#page-top" title="back to top"></a>
103
102
  <noscript id="noscript-styles"></noscript>
104
103
  <% if(is_post()) { %>
105
104
  <script src="/js/toc.js?v=<%=version%>" defer></script>
@@ -110,7 +109,7 @@ const version = theme.version;
110
109
  <script src="<%=url%>?v=<%=version%>"></script>
111
110
  <% }); %>
112
111
  <% } %>
113
- <% if (theme?.lazyload?.enable) { %>
112
+ <% if (theme?.lazyload?.enable ?? true) { %>
114
113
  <script src="/js/lazyload.js?v=<%=version%>"></script>
115
114
  <% } %>
116
115
  <% if (page.hdrAssetsPrefix) { %>
@@ -3,7 +3,7 @@ const { hasTranslatation, targetLanguagePath, targetLanguage } = getTranslationP
3
3
 
4
4
  const logoConfig = theme?.logo || {};
5
5
  const { src: logoSrc, text: logoText, width: logoWidth, height: logoHeight } = logoConfig;
6
- const rssPath = config?.feed?.path || theme?.feed?.path;
6
+ const rssPath = theme?.feed === false ? '' : theme?.feed?.path ?? '/feed.xml';
7
7
  %>
8
8
 
9
9
  <% if (is_post()) { %>
@@ -8,7 +8,9 @@ const series = Array.from(new Set(site.posts.filter(item=>item.series).sort('dat
8
8
  <div class="name"><%=config?.author || ''%></div>
9
9
  </div>
10
10
  </div>
11
- <div class="info-row description"><%=theme?.info?.site_desc || ''%></div>
11
+ <% if (theme?.info?.site_desc) { %>
12
+ <div class="info-row description"><%=theme?.info?.site_desc%></div>
13
+ <% } %>
12
14
  <div class="info-row site-statisc">
13
15
  <a href="/archives/#posts" target="_self"><%=site.posts?.filter(post=>!post?.hide?.archive).length%> <%=__('common.posts')%></a>
14
16
  <span class="divider">/</span>
package/layout/post.ejs CHANGED
@@ -232,7 +232,7 @@ const nextPost = series[currentIndex + 1] || null;
232
232
  </script>
233
233
  <% } %>
234
234
 
235
- <% if ([config?.theme_config?.photoswipe, page.photoswipe ?? true, /<img/.test(page?.content)].every(enable=>enable)) {
235
+ <% if ([config?.theme_config?.photoswipe ?? true, page.photoswipe ?? true, /<img/.test(page?.content)].every(enable=>enable)) {
236
236
  const version = theme.version;
237
237
  const hdrAssetsPrefix = page?.hdrAssetsPrefix || '';
238
238
  %>
package/layout/series.ejs CHANGED
@@ -43,7 +43,7 @@
43
43
  </div>
44
44
  <% } else { %>
45
45
  <h1><%=__('common.series') + ': ' + page.series %></h1>
46
- <% if (page.seriesInfo.description) { %>
46
+ <% if (page?.seriesInfo?.description) { %>
47
47
  <div class="series-description"><%=page.seriesInfo.description||''%> <i class="post-count-icon"></i><%=__('common.total')%> <%=page?.seriesPosts?.length%> <%=__('common.seriesPostCount')%></div>
48
48
  <% } %>
49
49
  <% } %>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hexo-theme-linen",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "A clean Hexo theme",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -0,0 +1,39 @@
1
+ function processCodeBlock(content) {
2
+ return content.replace(
3
+ /<\/figure>/g,
4
+ '<div class="copy-btn"></div></figure>',
5
+ );
6
+ }
7
+
8
+ function process(content) {
9
+ if (!content) return "";
10
+ const h2Regex = /(<h2[^>]*>.*?<\/h2>)/g;
11
+ let match,
12
+ count = 0,
13
+ lastIndex = 0;
14
+ let updatedContent = content;
15
+
16
+ while ((match = h2Regex.exec(content)) !== null) {
17
+ count++;
18
+ if (count === 3) {
19
+ lastIndex = match.index + match[0].length;
20
+ updatedContent =
21
+ content.slice(0, lastIndex) +
22
+ '<div id="gitalk-initiator"></div>' +
23
+ content.slice(lastIndex);
24
+ return updatedContent;
25
+ }
26
+ }
27
+
28
+ return updatedContent + '<div id="gitalk-initiator"></div>';
29
+ }
30
+
31
+ hexo.extend.filter.register(
32
+ "after_post_render",
33
+ function (data) {
34
+ data.content = processCodeBlock(data.content);
35
+ data.content = process.call(this, data.content);
36
+ return data;
37
+ },
38
+ 2,
39
+ );
@@ -20,7 +20,11 @@ function process(data) {
20
20
  }
21
21
  }
22
22
 
23
- module.exports.processPost = function (data) {
24
- data.content = process.call(this, data);
25
- return data;
26
- };
23
+ hexo.extend.filter.register(
24
+ "before_post_render",
25
+ function (data) {
26
+ data.content = process.call(this, data);
27
+ return data;
28
+ },
29
+ 2,
30
+ );
package/scripts/index.js CHANGED
@@ -1,16 +1,8 @@
1
1
  "use strict";
2
2
 
3
3
  module.exports = hexo => {
4
- hexo.extend.filter.register(
5
- "before_post_render",
6
- require("./lib/comments").processPost,
7
- 2
8
- );
9
- hexo.extend.filter.register(
10
- "after_post_render",
11
- require("./lib/custom").processPost,
12
- 2
13
- );
4
+ require("./custom")(hexo);
5
+ require("./hoverTexts")(hexo);
14
6
  require("./helpers/tools")(hexo);
15
7
  require("./font-version")(hexo);
16
8
  require("./appendRawMarkdownContent")(hexo);
@@ -18,4 +10,5 @@ require("./addCopyButtonToCodeBlocks")(hexo);
18
10
  require('./folded-code-block')(hexo);
19
11
  require('./series-generator')(hexo);
20
12
  require("./lazyload/index")(hexo);
13
+ require("./rss")(hexo);
21
14
  }
@@ -114,16 +114,6 @@
114
114
  }
115
115
  var lazyloadItems = document.querySelectorAll(".lazyload-wrap");
116
116
  var loadingQueue = [];
117
- var appendStyles = function appendStyles(element, styles) {
118
- var currentStyle = element.getAttribute("style");
119
- var newStyles = "";
120
- if (currentStyle) {
121
- var hasSemicolon = currentStyle.endsWith(";");
122
- newStyles = currentStyle + hasSemicolon ? "" : ";";
123
- }
124
- newStyles += styles;
125
- element.setAttribute("style", newStyles);
126
- };
127
117
  var createResourceElement = function createResourceElement(contentStr) {
128
118
  var nElement = document.createElement("div");
129
119
  nElement.innerHTML = contentStr;
@@ -1,13 +1,13 @@
1
- if (!hexo?.config?.theme_config?.lazyload?.enable) {
2
- return;
3
- }
4
- hexo.extend.filter.register(
5
- "after_post_render",
6
- require("./process").processPost,
7
- );
8
- hexo.extend.filter.register(
9
- "after_render:html",
10
- require("./process").processCovers,
11
- 3,
12
- );
13
- hexo.extend.filter.register("after_render:html", require("./inject")(hexo));
1
+ if (hexo?.config?.theme_config?.lazyload?.enable === false) {
2
+ return;
3
+ }
4
+ hexo.extend.filter.register(
5
+ "after_post_render",
6
+ require("./process").processPost,
7
+ );
8
+ hexo.extend.filter.register(
9
+ "after_render:html",
10
+ require("./process").processCovers,
11
+ 3,
12
+ );
13
+ hexo.extend.filter.register("after_render:html", require("./inject")(hexo));
@@ -133,7 +133,8 @@ module.exports = function (hexo) {
133
133
 
134
134
  let settingsContent = `<script>var $lazyload = {
135
135
  intersectionRatio: ${intersectionRatio},
136
- preloadCount: ${preloadCount}, keepPlaceholder: ${
136
+ preloadCount: ${preloadCount},
137
+ keepPlaceholder: ${
137
138
  page?.lazyload?.keepPlaceholder ?? false
138
139
  }}</script>`;
139
140
 
@@ -276,7 +276,7 @@ function lazyProcess(htmlContent) {
276
276
  ...(themeConfig?.lazyload || {}),
277
277
  };
278
278
 
279
- const enableGallery = themeConfig?.photoswipe === true;
279
+ const enableGallery = themeConfig?.photoswipe ?? true;
280
280
  const imgs = readAllImgs(
281
281
  path.join(this.base_dir, "assets-db/imgs")
282
282
  );
@@ -448,7 +448,7 @@ module.exports.processCovers = function (str, data) {
448
448
  try {
449
449
  const imgs = readAllImgs(path.join(this.base_dir, "assets-db/imgs"));
450
450
  const imgData = imgs.find((item) => isUrlEqual(item.url, data.page.cover || "" || ""));
451
- if (!data?.page?.coverPlaceholder || imgData?.placeholder) {
451
+ if (data?.page?.coverPlaceholder || imgData?.placeholder) {
452
452
  str = str.replace(
453
453
  '<div class="post-cover-img-wrap">',
454
454
  `<div class="post-cover-img-wrap" style="background-image: url(${
package/scripts/rss.js ADDED
@@ -0,0 +1,89 @@
1
+ const { url_for } = require("hexo-util");
2
+
3
+ if (hexo?.config?.theme_config?.feed === false) {
4
+ return;
5
+ }
6
+
7
+ function escape(value) {
8
+ if (value == null) return "";
9
+ const str = String(value);
10
+
11
+ const re = /[&<>"'`]/g;
12
+
13
+ const map = {
14
+ "&": "&amp;",
15
+ "<": "&lt;",
16
+ ">": "&gt;",
17
+ '"': "&quot;",
18
+ "'": "&#39;",
19
+ "`": "&#96;",
20
+ };
21
+
22
+ return str.replace(re, (ch) => map[ch]);
23
+ }
24
+
25
+ hexo.extend.generator.register("rss", function (locals) {
26
+ const themeConfig = hexo.theme.config;
27
+ const posts = locals.posts.sort("-date").limit(themeConfig?.feed?.limit ?? 10);
28
+ const config = hexo.config;
29
+ const language = config.language || "";
30
+
31
+ const feed = `<?xml version="1.0" encoding="UTF-8" ?>
32
+ <?xml-stylesheet type="text/xsl" href="/css/rss-${language.startsWith("zh") ? "zh" : "en"}.xsl"?>
33
+ <rss version="2.0">
34
+ <channel>
35
+ <title>${escape(config.title)}</title>
36
+ <link>${config.url}</link>
37
+ <description>${escape(config.description || "")}</description>
38
+ <lastBuildDate>${new Date().toUTCString()}</lastBuildDate>
39
+ <image>
40
+ <url>${/http/.test(themeConfig?.feed?.icon) ? themeConfig?.feed?.icon : `${config.url}${themeConfig?.feed?.icon}`}</url>
41
+ <title>${escape(config.title)}</title>
42
+ <link>${config.url}</link>
43
+ </image>
44
+ ${posts
45
+ .map((post) => {
46
+ let postContent = post._content
47
+ .replace(
48
+ /:::image-grid(?:\s+([\w-]+))?([\s\S]*?):::/g,
49
+ (match, grid, content) => {
50
+ const gridClass = grid ? ` ${grid}` : "";
51
+ return `<span class="image-grid${gridClass}">${hexo.render
52
+ .renderSync({
53
+ text: content,
54
+ engine: "markdown",
55
+ })
56
+ .replace(/<p>/g, '<span class="grid-item">')
57
+ .replace(/<\/p>/g, "</span>")}</span>`;
58
+ },
59
+ )
60
+ .replace(/\s*data-placeholderimg="[^"]*"/g, "");
61
+ const rawHtml = hexo.render
62
+ .renderSync({
63
+ text: postContent,
64
+ engine: "markdown",
65
+ })
66
+ .replace(
67
+ /<img\b(?![^>]*\bloading=)([^>]*)>/gi,
68
+ '<img loading="lazy"$1>',
69
+ )
70
+ .replace(/<iframe[\s\S]*?<\/iframe>/gi, "");
71
+
72
+ return `
73
+ <item>
74
+ <title>${escape(`${post.title}${post?.subTitle ? `(${post.subTitle})` : ""}`)}</title>
75
+ <link>${config.url + url_for.bind(hexo)(post.path)}</link>
76
+ <guid>${config.url + url_for.bind(hexo)(post.path)}</guid>
77
+ <pubDate>${hexo.extend.helper.store.getPostDate(post, language)}</pubDate>
78
+ <description><![CDATA[${rawHtml}]]></description>
79
+ </item>`;
80
+ })
81
+ .join("")}
82
+ </channel>
83
+ </rss>`;
84
+
85
+ return {
86
+ path: themeConfig?.feed?.path ?? '/feed.xml',
87
+ data: feed,
88
+ };
89
+ });
@@ -1256,21 +1256,6 @@ body {
1256
1256
  &:nth-child(2) {
1257
1257
  margin-top: $postItemGap;
1258
1258
  }
1259
- .logo {
1260
- width: 36px;
1261
- height: 36px;
1262
- display: inline-block;
1263
- margin: 0;
1264
- vertical-align: middle;
1265
- border-radius: 1px;
1266
- }
1267
- .site-name {
1268
- margin-left: 10px;
1269
- display: inline-block;
1270
- line-height: 36px;
1271
- color: $darkText;
1272
- font-size: 18px;
1273
- }
1274
1259
  .author {
1275
1260
  display: flex;
1276
1261
  align-items: center;
@@ -1310,53 +1295,8 @@ body {
1310
1295
  color: #d8d8d8;
1311
1296
  }
1312
1297
  }
1313
- &.about {
1298
+ &:last-child {
1314
1299
  margin-bottom: 10px;
1315
- color: $green;
1316
- font-size: 14px;
1317
- a {
1318
- &:hover {
1319
- text-decoration: underline;
1320
- }
1321
- }
1322
- .about-this-site {
1323
- display: inline-block;
1324
- position: relative;
1325
- bottom: 1px;
1326
- white-space: nowrap;
1327
- color: inherit;
1328
- margin-right: 12px;
1329
- i.about-icon {
1330
- width: 18px;
1331
- height: 18px;
1332
- background-image: url("/img/icons/about.svg");
1333
- background-size: cover;
1334
- display: inline-block;
1335
- vertical-align: middle;
1336
- margin-bottom: 2px;
1337
- opacity: 0.7;
1338
- margin-right: 2px;
1339
- }
1340
- }
1341
- .whats-new {
1342
- margin-right: 0;
1343
- display: inline-block;
1344
- position: relative;
1345
- bottom: 1px;
1346
- white-space: nowrap;
1347
- i.new-icon {
1348
- width: 18px;
1349
- height: 18px;
1350
- background-image: url("/img/icons/new.svg");
1351
- background-size: cover;
1352
- display: inline-block;
1353
- vertical-align: middle;
1354
- margin-bottom: 2px;
1355
- margin-right: 2px;
1356
- }
1357
- font-size: 14px;
1358
- color: $linkColor;
1359
- }
1360
1300
  }
1361
1301
  }
1362
1302
  }
@@ -114,16 +114,6 @@
114
114
  }
115
115
  var lazyloadItems = document.querySelectorAll(".lazyload-wrap");
116
116
  var loadingQueue = [];
117
- var appendStyles = function appendStyles(element, styles) {
118
- var currentStyle = element.getAttribute("style");
119
- var newStyles = "";
120
- if (currentStyle) {
121
- var hasSemicolon = currentStyle.endsWith(";");
122
- newStyles = currentStyle + hasSemicolon ? "" : ";";
123
- }
124
- newStyles += styles;
125
- element.setAttribute("style", newStyles);
126
- };
127
117
  var createResourceElement = function createResourceElement(contentStr) {
128
118
  var nElement = document.createElement("div");
129
119
  nElement.innerHTML = contentStr;
@@ -198,7 +198,6 @@ function initAnchorHighlighter({
198
198
  });
199
199
  }
200
200
 
201
- // 使用示例
202
201
  initAnchorHighlighter({
203
202
  duration: 4000,
204
203
  });
@@ -1,30 +0,0 @@
1
- function processCodeBlock(content) {
2
- return content.replace(/<\/figure>/g, '<div class="copy-btn"></div></figure>');
3
- };
4
-
5
- function process(content) {
6
- if (!content) return '';
7
- // 正则匹配所有 <h2>...</h2>,非贪心匹配
8
- const h2Regex = /(<h2[^>]*>.*?<\/h2>)/g;
9
- let match, count = 0, lastIndex = 0;
10
- let updatedContent = content;
11
-
12
- // 找到第三个 <h2>
13
- while ((match = h2Regex.exec(content)) !== null) {
14
- count++;
15
- if (count === 3) {
16
- lastIndex = match.index + match[0].length; // 计算插入点
17
- updatedContent = content.slice(0, lastIndex) + '<div id="gitalk-initiator"></div>' + content.slice(lastIndex);
18
- return updatedContent;
19
- }
20
- }
21
-
22
- // 如果没有找到第三个 <h2>,则在最后添加
23
- return updatedContent + '<div id="gitalk-initiator"></div>';
24
- }
25
-
26
- module.exports.processPost = function (data) {
27
- data.content = processCodeBlock(data.content);
28
- data.content = process.call(this, data.content);
29
- return data;
30
- };
@@ -1 +0,0 @@
1
- <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2000 1500'><rect fill='#ffffff' width='2000' height='1500'/><defs><rect stroke='#ffffff' stroke-width='.5' width='1' height='1' id='s'/><pattern id='a' width='3' height='3' patternUnits='userSpaceOnUse' patternTransform='scale(50) translate(-980 -735)'><use fill='#fcfcfc' href='#s' y='2'/><use fill='#fcfcfc' href='#s' x='1' y='2'/><use fill='#fafafa' href='#s' x='2' y='2'/><use fill='#fafafa' href='#s'/><use fill='#f7f7f7' href='#s' x='2'/><use fill='#f7f7f7' href='#s' x='1' y='1'/></pattern><pattern id='b' width='7' height='11' patternUnits='userSpaceOnUse' patternTransform='scale(50) translate(-980 -735)'><g fill='#f5f5f5'><use href='#s'/><use href='#s' y='5' /><use href='#s' x='1' y='10'/><use href='#s' x='2' y='1'/><use href='#s' x='2' y='4'/><use href='#s' x='3' y='8'/><use href='#s' x='4' y='3'/><use href='#s' x='4' y='7'/><use href='#s' x='5' y='2'/><use href='#s' x='5' y='6'/><use href='#s' x='6' y='9'/></g></pattern><pattern id='h' width='5' height='13' patternUnits='userSpaceOnUse' patternTransform='scale(50) translate(-980 -735)'><g fill='#f5f5f5'><use href='#s' y='5'/><use href='#s' y='8'/><use href='#s' x='1' y='1'/><use href='#s' x='1' y='9'/><use href='#s' x='1' y='12'/><use href='#s' x='2'/><use href='#s' x='2' y='4'/><use href='#s' x='3' y='2'/><use href='#s' x='3' y='6'/><use href='#s' x='3' y='11'/><use href='#s' x='4' y='3'/><use href='#s' x='4' y='7'/><use href='#s' x='4' y='10'/></g></pattern><pattern id='c' width='17' height='13' patternUnits='userSpaceOnUse' patternTransform='scale(50) translate(-980 -735)'><g fill='#f2f2f2'><use href='#s' y='11'/><use href='#s' x='2' y='9'/><use href='#s' x='5' y='12'/><use href='#s' x='9' y='4'/><use href='#s' x='12' y='1'/><use href='#s' x='16' y='6'/></g></pattern><pattern id='d' width='19' height='17' patternUnits='userSpaceOnUse' patternTransform='scale(50) translate(-980 -735)'><g fill='#ffffff'><use href='#s' y='9'/><use href='#s' x='16' y='5'/><use href='#s' x='14' y='2'/><use href='#s' x='11' y='11'/><use href='#s' x='6' y='14'/></g><g fill='#efefef'><use href='#s' x='3' y='13'/><use href='#s' x='9' y='7'/><use href='#s' x='13' y='10'/><use href='#s' x='15' y='4'/><use href='#s' x='18' y='1'/></g></pattern><pattern id='e' width='47' height='53' patternUnits='userSpaceOnUse' patternTransform='scale(50) translate(-980 -735)'><g fill='#F60'><use href='#s' x='2' y='5'/><use href='#s' x='16' y='38'/><use href='#s' x='46' y='42'/><use href='#s' x='29' y='20'/></g></pattern><pattern id='f' width='59' height='71' patternUnits='userSpaceOnUse' patternTransform='scale(50) translate(-980 -735)'><g fill='#F60'><use href='#s' x='33' y='13'/><use href='#s' x='27' y='54'/><use href='#s' x='55' y='55'/></g></pattern><pattern id='g' width='139' height='97' patternUnits='userSpaceOnUse' patternTransform='scale(50) translate(-980 -735)'><g fill='#F60'><use href='#s' x='11' y='8'/><use href='#s' x='51' y='13'/><use href='#s' x='17' y='73'/><use href='#s' x='99' y='57'/></g></pattern></defs><rect fill='url(#a)' width='100%' height='100%'/><rect fill='url(#b)' width='100%' height='100%'/><rect fill='url(#h)' width='100%' height='100%'/><rect fill='url(#c)' width='100%' height='100%'/><rect fill='url(#d)' width='100%' height='100%'/><rect fill='url(#e)' width='100%' height='100%'/><rect fill='url(#f)' width='100%' height='100%'/><rect fill='url(#g)' width='100%' height='100%'/></svg>