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.
Files changed (2) hide show
  1. package/index.js +56 -22
  2. 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').bind(hexoInstance);
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.toObject();
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
- <title>${t.title} - ${hexoInstance.config.title}</title>
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
- if (force && await fs.exists(dest)) await fs.unlink(dest);
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
- hexo.extend.generator.register('html-sitemap', function() { return createHtmlSitemap(this); });
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) { return createHtmlSitemap(this, args.f || args.force); });
119
+ options: [{ name: '-f, --force', desc: 'Overwrite existing sitemap.html' }]
120
+ }, async function(args) {
121
+ return createHtmlSitemap(this, args.f || args.force);
122
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hexo-sitemap-html",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"