hexo-sitemap-html 1.0.5 → 1.0.6
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.
- package/index.js +56 -22
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -9,7 +9,7 @@ const DEFAULT_CONFIG = {
|
|
|
9
9
|
path: 'sitemap.html',
|
|
10
10
|
enable: { categories: true, posts: true, pages: true },
|
|
11
11
|
exclude: [],
|
|
12
|
-
layout: 'minimal',
|
|
12
|
+
layout: 'minimal',
|
|
13
13
|
nofollow: false
|
|
14
14
|
};
|
|
15
15
|
|
|
@@ -17,72 +17,106 @@ async function createHtmlSitemap(hexo, force = false) {
|
|
|
17
17
|
const hexoInstance = hexo || this;
|
|
18
18
|
if (!hexoInstance) return;
|
|
19
19
|
|
|
20
|
+
|
|
21
|
+
const currentCmd = hexoInstance.env?.cmd;
|
|
22
|
+
if (currentCmd === 'server' && !force) {
|
|
23
|
+
hexoInstance.log.info(`[hexo-sitemap-html] Skip generating in server environment (use hexo generate/sitemap-html to generate)`);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
20
27
|
await hexoInstance.load();
|
|
21
|
-
const urlFor = hexoInstance.extend.helper.get('url_for')
|
|
28
|
+
const urlFor = hexoInstance.extend.helper.get('url_for')?.bind(hexoInstance) || (p => p);
|
|
22
29
|
const config = _.merge({}, DEFAULT_CONFIG, (hexoInstance.config.html_sitemap || {}));
|
|
23
30
|
|
|
24
31
|
// 获取 i18n 和 CSS
|
|
25
32
|
const lang = hexoInstance.config.language || 'en';
|
|
26
33
|
const { t, css } = getTemplate(config.layout, lang);
|
|
27
34
|
|
|
28
|
-
const locals = hexoInstance.locals
|
|
35
|
+
const locals = hexoInstance.locals?.toObject() || {};
|
|
29
36
|
const nofollow = config.nofollow ? 'rel="nofollow"' : '';
|
|
30
37
|
|
|
31
|
-
|
|
32
|
-
const posts = config.enable.posts ? locals.posts.toArray().sort((a,b)=>b.date-a.date) : [];
|
|
33
|
-
const cats = config.enable.categories ? locals.categories.toArray() : [];
|
|
34
|
-
const pages = config.enable.pages ? locals.pages.toArray().filter(p => !config.exclude.some(ex => (p.title||'').includes(ex))) : [];
|
|
38
|
+
|
|
39
|
+
const posts = config.enable.posts && locals.posts ? locals.posts.toArray().sort((a,b)=>b.date-a.date) : [];
|
|
40
|
+
const cats = config.enable.categories && locals.categories ? locals.categories.toArray() : [];
|
|
41
|
+
const pages = config.enable.pages && locals.pages ? locals.pages.toArray().filter(p => !config.exclude.some(ex => (p.title||'').includes(ex))) : [];
|
|
35
42
|
|
|
36
43
|
const html = `
|
|
37
44
|
<!DOCTYPE html>
|
|
38
45
|
<html lang="${lang}">
|
|
39
46
|
<head>
|
|
40
47
|
<meta charset="UTF-8">
|
|
41
|
-
<
|
|
48
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
49
|
+
<title>${t.title} - ${hexoInstance.config.title || 'Hexo Blog'}</title>
|
|
42
50
|
${css}
|
|
43
51
|
</head>
|
|
44
52
|
<body>
|
|
45
53
|
<div class="container">
|
|
46
54
|
|
|
47
|
-
<nav style="display:flex;">
|
|
48
|
-
<a class="${config.layout === 'minimal' ? '' : 'card item-link'}" href="/">${t.home}</a>
|
|
49
|
-
<a class="${config.layout === 'minimal' ? '' : 'card item-link'}" href="javascript:history.back()">${t.back}</a>
|
|
55
|
+
<nav style="display:flex; gap: 1rem; margin-bottom: 2rem;">
|
|
56
|
+
<a class="${config.layout === 'minimal' ? '' : 'card item-link'}" href="/">${t.home || 'Home'}</a>
|
|
57
|
+
<a class="${config.layout === 'minimal' ? '' : 'card item-link'}" href="javascript:history.back()">${t.back || 'Back'}</a>
|
|
50
58
|
</nav>
|
|
51
59
|
|
|
52
|
-
<h1>${t.title}</h1>
|
|
60
|
+
<h1>${t.title || 'Site Sitemap'}</h1>
|
|
53
61
|
|
|
54
|
-
${posts.length ? `<section class="section"><h2>${t.posts}</h2><div class="${config.layout === 'flat' ? 'grid' : 'list'}">
|
|
62
|
+
${posts.length ? `<section class="section"><h2>${t.posts || 'Posts'}</h2><div class="${config.layout === 'flat' ? 'grid' : 'list'}">
|
|
55
63
|
${posts.map(p => `
|
|
56
64
|
<div class="item">
|
|
57
65
|
<a href="${urlFor(p.path)}" class="${config.layout === 'minimal' ? '' : 'card item-link'}" ${nofollow}>
|
|
58
66
|
<span class="card-title">${p.title || 'Untitled'}</span>
|
|
59
67
|
</a>
|
|
60
68
|
${config.layout === 'minimal' ? `<div class="dot"></div>` : ''}
|
|
61
|
-
<span class="meta card-meta">${p.date.format('YYYY-MM-DD')}</span>
|
|
69
|
+
<span class="meta card-meta">${p.date ? p.date.format('YYYY-MM-DD') : 'No Date'}</span>
|
|
62
70
|
</div>`).join('')}
|
|
63
71
|
</div></section>` : ''}
|
|
64
72
|
|
|
65
|
-
${cats.length ? `<section class="section"><h2>${t.categories}</h2><div class="${config.layout === 'flat' ? 'grid' : 'list'}">
|
|
73
|
+
${cats.length ? `<section class="section"><h2>${t.categories || 'Categories'}</h2><div class="${config.layout === 'flat' ? 'grid' : 'list'}">
|
|
66
74
|
${cats.map(c => `
|
|
67
75
|
<div class="item">
|
|
68
76
|
<a href="${urlFor(c.path)}" class="${config.layout === 'minimal' ? '' : 'card item-link'}" ${nofollow}>
|
|
69
|
-
<span class="card-title">${c.name}</span>
|
|
77
|
+
<span class="card-title">${c.name || 'Uncategorized'}</span>
|
|
70
78
|
</a>
|
|
71
79
|
${config.layout === 'minimal' ? `<div class="dot"></div>` : ''}
|
|
72
|
-
<span class="meta card-meta">${c.posts.length} ${t.items}</span>
|
|
80
|
+
<span class="meta card-meta">${c.posts ? c.posts.length : 0} ${t.items || 'Items'}</span>
|
|
81
|
+
</div>`).join('')}
|
|
82
|
+
</div></section>` : ''}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
${pages.length ? `<section class="section"><h2>${t.pages || 'Pages'}</h2><div class="${config.layout === 'flat' ? 'grid' : 'list'}">
|
|
86
|
+
${pages.map(p => `
|
|
87
|
+
<div class="item">
|
|
88
|
+
<a href="${urlFor(p.path)}" class="${config.layout === 'minimal' ? '' : 'card item-link'}" ${nofollow}>
|
|
89
|
+
<span class="card-title">${p.title || 'Untitled Page'}</span>
|
|
90
|
+
</a>
|
|
91
|
+
${config.layout === 'minimal' ? `<div class="dot"></div>` : ''}
|
|
92
|
+
<span class="meta card-meta">${p.date ? p.date.format('YYYY-MM-DD') : 'No Date'}</span>
|
|
73
93
|
</div>`).join('')}
|
|
74
94
|
</div></section>` : ''}
|
|
75
95
|
</div>
|
|
76
96
|
</body>
|
|
77
97
|
</html>`;
|
|
78
98
|
|
|
79
|
-
const dest = path.join(hexoInstance.public_dir, config.path);
|
|
80
|
-
|
|
99
|
+
const dest = path.join(hexoInstance.public_dir || './public', config.path);
|
|
100
|
+
|
|
101
|
+
// 优化:增加文件存在性判断,避免强制删除不存在的文件
|
|
102
|
+
if (force && await fs.exists(dest)) {
|
|
103
|
+
await fs.unlink(dest);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 写入文件
|
|
81
107
|
await fs.writeFile(dest, html);
|
|
82
108
|
hexoInstance.log.info(`[hexo-sitemap-html] Generated: ${config.path} with ${config.layout} style`);
|
|
83
109
|
}
|
|
84
110
|
|
|
85
|
-
|
|
111
|
+
|
|
112
|
+
// 注册生成器钩子
|
|
113
|
+
hexo.extend.generator.register('html-sitemap', function() {
|
|
114
|
+
return createHtmlSitemap(this);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// 注册独立控制台命令
|
|
86
118
|
hexo.extend.console.register('sitemap-html', 'Generate HTML sitemap', {
|
|
87
|
-
options: [{ name: '-f, --force', desc: 'Overwrite' }]
|
|
88
|
-
}, function(args) {
|
|
119
|
+
options: [{ name: '-f, --force', desc: 'Overwrite existing sitemap.html' }]
|
|
120
|
+
}, async function(args) {
|
|
121
|
+
return createHtmlSitemap(this, args.f || args.force);
|
|
122
|
+
});
|