hexo-theme-stellar 1.18.5 → 1.20.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 (68) hide show
  1. package/_config.yml +93 -17
  2. package/layout/_partial/cover/wiki_cover.ejs +1 -1
  3. package/layout/_partial/head.ejs +15 -2
  4. package/layout/_partial/main/article/ai_abstract.ejs +8 -0
  5. package/layout/_partial/main/article/article_footer.ejs +87 -50
  6. package/layout/_partial/main/article/read_next.ejs +17 -12
  7. package/layout/_partial/main/navbar/breadcrumb.ejs +53 -15
  8. package/layout/_partial/main/navbar/list_post.ejs +6 -4
  9. package/layout/_partial/main/navbar/list_wiki.ejs +4 -3
  10. package/layout/_partial/main/post_list/paginator.ejs +1 -1
  11. package/layout/_partial/plugins/comments/beaudar/script.ejs +1 -1
  12. package/layout/_partial/plugins/comments/giscus/script.ejs +1 -1
  13. package/layout/_partial/plugins/comments/layout.ejs +2 -2
  14. package/layout/_partial/plugins/comments/utterances/script.ejs +1 -1
  15. package/layout/_partial/plugins/comments/waline/script.ejs +17 -0
  16. package/layout/_partial/scripts/index.ejs +7 -0
  17. package/layout/_partial/sidebar/header.ejs +1 -1
  18. package/layout/_partial/sidebar/index.ejs +3 -3
  19. package/layout/_partial/widgets/ghissues.ejs +1 -1
  20. package/layout/_partial/widgets/ghrepo.ejs +1 -1
  21. package/layout/_partial/widgets/recent.ejs +3 -3
  22. package/layout/_partial/widgets/related.ejs +9 -8
  23. package/layout/_partial/widgets/toc.ejs +15 -10
  24. package/layout/index.ejs +7 -4
  25. package/layout/mermaid.ejs +32 -0
  26. package/layout/page.ejs +3 -0
  27. package/layout/post.ejs +6 -0
  28. package/layout/wiki.ejs +6 -0
  29. package/package.json +1 -1
  30. package/scripts/events/lib/doc_tree.js +123 -92
  31. package/scripts/filters/index.js +13 -0
  32. package/scripts/tags/index.js +2 -2
  33. package/scripts/tags/inline-labels.js +2 -2
  34. package/scripts/tags/lib/ablock.js +1 -1
  35. package/scripts/tags/lib/checkbox.js +1 -1
  36. package/scripts/tags/lib/folders.js +1 -1
  37. package/scripts/tags/lib/folding.js +2 -2
  38. package/scripts/tags/lib/hashtag.js +36 -0
  39. package/scripts/tags/lib/image.js +5 -1
  40. package/scripts/tags/lib/mark.js +1 -1
  41. package/scripts/tags/lib/note.js +1 -1
  42. package/scripts/tags/lib/okr.js +140 -0
  43. package/scripts/tags/lib/sites.js +1 -1
  44. package/scripts/tags/lib/toc.js +1 -1
  45. package/source/css/_common/button.styl +1 -0
  46. package/source/css/_common/highlight.styl +2 -0
  47. package/source/css/_custom.styl +2 -2
  48. package/source/css/_defines/theme.styl +0 -1
  49. package/source/css/_layout/md.styl +10 -2
  50. package/source/css/_layout/partial/ai_abstract.styl +155 -0
  51. package/source/css/_layout/partial/bread-nav.styl +32 -0
  52. package/source/css/_layout/partial/paginator.styl +7 -3
  53. package/source/css/_layout/tag-plugins/common.styl +30 -39
  54. package/source/css/_layout/tag-plugins/folding.styl +1 -1
  55. package/source/css/_layout/tag-plugins/hashtag.styl +17 -0
  56. package/source/css/_layout/tag-plugins/link.styl +1 -7
  57. package/source/css/_layout/tag-plugins/mark.styl +2 -5
  58. package/source/css/_layout/tag-plugins/note.styl +1 -1
  59. package/source/css/_layout/tag-plugins/okr.styl +106 -0
  60. package/source/css/_plugins/copycode.styl +27 -0
  61. package/source/css/_plugins/index.styl +4 -0
  62. package/source/css/_plugins/mermaid.styl +125 -0
  63. package/source/js/main.js +8 -3
  64. package/source/js/plugins/copycode.js +49 -0
  65. package/source/js/plugins/linkcard.js +1 -1
  66. package/source/js/plugins/sites.js +1 -1
  67. package/scripts/tags/lib/tag.js +0 -35
  68. package/source/css/_layout/tag-plugins/tag.styl +0 -13
@@ -12,8 +12,8 @@ if (theme.comments.service && theme.comments.service.length > 0) {
12
12
  }
13
13
  }
14
14
  // 合并项目评论
15
- if (loadComment && page.layout == 'wiki' && page.wiki) {
16
- let proj = theme.wiki.projects[page.wiki];
15
+ let proj = theme.wiki.tree[page.wiki];
16
+ if (loadComment && page.layout == 'wiki' && page.wiki && (proj != null)) {
17
17
  if (proj.comment_title != undefined && page.comment_title == undefined) {
18
18
  if (['utterances', 'beaudar', 'giscus'].includes(theme.comments.service)) {
19
19
  page.comment_title = proj.comment_title;
@@ -6,7 +6,7 @@
6
6
  try {
7
7
  el.innerHTML = '';
8
8
  } catch (error) {
9
- console.log(error);
9
+ console.error(error);
10
10
  }
11
11
  var script = document.createElement('script');
12
12
  script.src = 'https://utteranc.es/client.js';
@@ -11,6 +11,23 @@
11
11
  Waline.init(Object.assign(<%- JSON.stringify(theme.comments.waline) %>, {
12
12
  el: '#waline_container',
13
13
  path: path,
14
+ <% if(!!theme.comments.waline.imageUploader?.api){ %>
15
+ imageUploader: function(file) {
16
+ let headers = new Headers();
17
+ headers.set('Accept', 'application/json');
18
+ <% if(!!theme.comments.waline.imageUploader?.token) { %>
19
+ headers.set('<%= theme.comments.waline.imageUploader?.tokenName %>', '<%= theme.comments.waline.imageUploader?.token %>')
20
+ <% } %>
21
+ let formData = new FormData();
22
+ formData.append('<%= theme.comments.waline.imageUploader?.fileName %>', file);
23
+ return fetch('<%= theme.comments.waline.imageUploader?.api %>',{
24
+ method: 'POST',
25
+ body: formData,
26
+ headers: headers
27
+ }).then((resp) => resp.json())
28
+ .then((resp) => resp.<%= theme.comments.waline.imageUploader?.resp %>)
29
+ },
30
+ <% } %>
14
31
  }));
15
32
  });
16
33
  }
@@ -62,6 +62,9 @@
62
62
  // 从 butterfly 和 volantis 获得灵感
63
63
  loadScript: (src, opt) => new Promise((resolve, reject) => {
64
64
  var script = document.createElement('script');
65
+ if (src.startsWith('/')){
66
+ src = stellar.config.root + src.substring(1);
67
+ }
65
68
  script.src = src;
66
69
  if (opt) {
67
70
  for (let key of Object.keys(opt)) {
@@ -100,6 +103,7 @@
100
103
  day: '<%- __('meta.date_suffix.day') %>',
101
104
  month: '<%- __('meta.date_suffix.month') %>',
102
105
  },
106
+ root : '<%- config.root %>',
103
107
  };
104
108
 
105
109
  // required plugins (only load if needs)
@@ -139,6 +143,9 @@
139
143
  if ('<%- theme.plugins.heti.enable %>' == 'true') {
140
144
  stellar.plugins.heti = Object.assign(<%- JSON.stringify(theme.plugins.heti) %>);
141
145
  }
146
+ if ('<%- theme.plugins.copycode.enable %>' == 'true') {
147
+ stellar.plugins.copycode = Object.assign(<%- JSON.stringify(theme.plugins.copycode) %>);
148
+ }
142
149
  </script>
143
150
 
144
151
  <!-- required -->
@@ -1,7 +1,7 @@
1
1
  <%
2
2
  var proj;
3
3
  if (page.layout === 'wiki' && page.wiki) {
4
- proj = theme.wiki.projects[page.wiki];
4
+ proj = theme.wiki.tree[page.wiki];
5
5
  }
6
6
  function layoutTitle(main, url, sub) {
7
7
  var el = '';
@@ -1,15 +1,15 @@
1
1
  <%
2
2
  var proj;
3
3
  if (page.layout === 'wiki' && page.wiki) {
4
- proj = theme.wiki.projects[page.wiki];
4
+ proj = theme.wiki.tree[page.wiki];
5
5
  }
6
6
  // 默认组件
7
7
  if (page.sidebar == undefined) {
8
8
  if (page.layout == 'post' && page.content) {
9
9
  page.sidebar = theme.sidebar.widgets.post;
10
10
  } else if (page.layout == 'wiki' && page.content && page.wiki) {
11
- let proj = theme.wiki.projects[page.wiki];
12
- if (proj.sidebar) {
11
+ let proj = theme.wiki.tree[page.wiki];
12
+ if (proj?.sidebar) {
13
13
  page.sidebar = proj.sidebar;
14
14
  } else {
15
15
  page.sidebar = theme.sidebar.widgets.wiki;
@@ -6,7 +6,7 @@ function layoutDiv() {
6
6
  if (page.repo) {
7
7
  repo = page.repo
8
8
  } else if (page.layout === 'wiki' && page.wiki) {
9
- let proj = theme.wiki.projects[page.wiki];
9
+ let proj = theme.wiki.tree[page.wiki];
10
10
  if (proj && proj.repo) {
11
11
  repo = proj.repo;
12
12
  if (proj.branch != undefined) {
@@ -6,7 +6,7 @@ function layoutDiv() {
6
6
  if (page.repo) {
7
7
  repo = page.repo
8
8
  } else if (page.layout === 'wiki' && page.wiki) {
9
- let proj = theme.wiki.projects[page.wiki];
9
+ let proj = theme.wiki.tree[page.wiki];
10
10
  if (proj && proj.repo) {
11
11
  repo = proj.repo;
12
12
  if (proj.branch != undefined) {
@@ -15,8 +15,8 @@ function layoutDiv() {
15
15
  if (page.menu_id == 'wiki') {
16
16
  arr = theme.wiki.all_pages.filter( p => {
17
17
  if (p.wiki) {
18
- let proj = theme.wiki.projects[p.wiki];
19
- return proj.index != false;
18
+ let proj = theme.wiki.tree[p.wiki];
19
+ return proj?.index != false;
20
20
  }
21
21
  return false
22
22
  })
@@ -32,7 +32,7 @@ function layoutDiv() {
32
32
  el += '<a class="item title" href="' + url_for(post.link || post.path) + '">';
33
33
  el += '<span class="title">'
34
34
  if (post.layout == 'wiki') {
35
- let proj = theme.wiki.projects[post.wiki];
35
+ let proj = theme.wiki.tree[post.wiki];
36
36
  let name = proj?.name || post?.wiki;
37
37
  if (name) {
38
38
  el += '<strong>' + name + '</strong>' + '<span class="dot"></span>';
@@ -4,11 +4,12 @@ function layoutDiv() {
4
4
  return '';
5
5
  }
6
6
  var related = [];
7
- let proj = theme.wiki.projects[page.wiki];
8
- if (proj.related && proj.related.length > 0) {
9
- proj.related.forEach((pid, i) => {
10
- let p = theme.wiki.projects[pid];
11
- if (p && p.title !== proj.title && p.index !== false) {
7
+ const { shelf, tree } = theme.wiki;
8
+ let proj = tree[page.wiki];
9
+ if (proj?.related?.length > 0) {
10
+ proj.related.filter(pid => shelf.includes(pid)).forEach((pid, i) => {
11
+ let p = tree[pid];
12
+ if (p && p.title !== proj?.title && p.homepage) {
12
13
  related.push(p);
13
14
  }
14
15
  });
@@ -24,15 +25,15 @@ function layoutDiv() {
24
25
  el += '<span class="name">' + __('meta.more', title) + '</span>';
25
26
  el += '</div>';
26
27
  el += '<div class="widget-body related-posts">';
27
- related.forEach((p, i) => {
28
+ for (let p of related) {
28
29
  // 同一个分组中的其它项目
29
- el += '<a class="item wiki" href="' + url_for(p.homepage.path) + '">';
30
+ el += '<a class="item wiki" href="' + url_for(p.homepage?.path) + '">';
30
31
  el += '<span class="title">' + p.title + '</span>';
31
32
  if (p.description && p.description.length > 0) {
32
33
  el += '<span class="excerpt">' + p.description + '</span>';
33
34
  }
34
35
  el += '</a>';
35
- });
36
+ }
36
37
  el += '</div>';
37
38
  el += '</widget>';
38
39
  }
@@ -1,5 +1,5 @@
1
1
  <%
2
- let proj = theme.wiki.projects[page.wiki];
2
+ let proj = theme.wiki.tree[page.wiki];
3
3
 
4
4
  function layoutToc() {
5
5
  if (toc(page.content).length > 0) {
@@ -22,7 +22,10 @@ function layoutTocHeader(title) {
22
22
 
23
23
  function layoutDocTree(pages) {
24
24
  var el = '';
25
- pages.forEach((p, i) => {
25
+ for (let p of pages) {
26
+ if (p.title == null || p.title.length == 0) {
27
+ continue;
28
+ }
26
29
  let isActive = '';
27
30
  if (p.path === page.path) {
28
31
  isActive += ' active';
@@ -34,14 +37,14 @@ function layoutDocTree(pages) {
34
37
  href += '#start'
35
38
  }
36
39
  el += '<a class="doc-tree-link' + isActive + '" href="' + href + '">';
37
- el += '<span class="toc-text">' + (p.title || p.seo_title) + '</span>';
40
+ el += '<span class="toc-text">' + p.title + '</span>';
38
41
  el += '</a>';
39
42
  }
40
43
  if (p.path === page.path) {
41
44
  el += layoutToc();
42
45
  }
43
46
  el += '</div>';
44
- });
47
+ }
45
48
  return el;
46
49
  }
47
50
 
@@ -74,17 +77,19 @@ function layoutDiv(fallback) {
74
77
  el += '</div>';
75
78
  } else if (proj) {
76
79
  // wiki 布局
77
- if (proj.sections && proj.sections.length > 0) {
80
+ if (proj.sections && proj.sections.length > 0 && proj.pages.length > 1) { // 多 pages
78
81
  proj.sections.forEach((sec, i) => {
79
- // section
80
- el += layoutTocHeader(sec.title);
82
+ if (sec.title?.length > 0) {
83
+ el += layoutTocHeader(sec.title);
84
+ }
81
85
  el += '<div class="widget-body fs14">';
82
86
  el += layoutDocTree(sec.pages);
83
87
  el += '</div>';
84
88
  });
85
- } else {
86
- // section
87
- el += layoutTocHeader(page.toc_title);
89
+ } else { // 单 page
90
+ if (proj.pages.length == 1) {
91
+ el += layoutTocHeader(page.toc_title);
92
+ }
88
93
  el += '<div class="widget-body fs14">';
89
94
  el += layoutDocTree(proj.pages);
90
95
  el += '</div>';
package/layout/index.ejs CHANGED
@@ -51,10 +51,13 @@ function layout_posts(partial) {
51
51
  function layout_wikis(partial) {
52
52
  var el = '';
53
53
  var wikis = [];
54
- const projects = theme.wiki.projects;
55
- for (let proj_name of Object.keys(projects)) {
56
- let proj = projects[proj_name];
57
- if (proj.index === false || proj.pages == undefined || proj.pages.length === 0) {
54
+ const { shelf, tree } = theme.wiki;
55
+ for (let pid of shelf) {
56
+ let proj = tree[pid];
57
+ if (proj == null) {
58
+ continue;
59
+ }
60
+ if (proj.pages == undefined || proj.pages.length === 0) {
58
61
  continue;
59
62
  }
60
63
  if (page.filter === false) {
@@ -0,0 +1,32 @@
1
+ <% if (theme.plugins.mermaid.enable) { %>
2
+ <script type="text/javascript" src="<%- theme.plugins.mermaid.js %>"></script>
3
+
4
+ <script>
5
+ var mermaid_config = {
6
+ startOnLoad: true,
7
+ theme:
8
+ "<%- theme.style.darkmode %>" == "auto" &&
9
+ window.matchMedia("(prefers-color-scheme: dark)").matches
10
+ ? "dark"
11
+ : "<%- theme.plugins.mermaid.theme %>",
12
+ logLevel: 3,
13
+ themeVariables: {
14
+ darkMode: true
15
+ },
16
+ flowchart: {
17
+ useMaxWidth: false,
18
+ htmlLabels: true,
19
+ curve: "linear"
20
+ },
21
+ gantt: {
22
+ axisFormat: "%Y/%m/%d"
23
+ },
24
+ sequence: {
25
+ actorMargin: 50
26
+ }
27
+ }
28
+ if (window.mermaid) {
29
+ mermaid.initialize(mermaid_config);
30
+ }
31
+ </script>
32
+ <% } %>
package/layout/page.ejs CHANGED
@@ -12,6 +12,9 @@ function layoutDiv() {
12
12
  if (page.post_list) {
13
13
  el += partial('_partial/main/navbar/list_post');
14
14
  }
15
+ if (page.mermaid == true) {
16
+ el += partial('mermaid');
17
+ }
15
18
  if (page.h1 || page.title || (page.content && page.content.length > 0)) {
16
19
  el += partial('_partial/main/navbar/breadcrumb');
17
20
  }
package/layout/post.ejs CHANGED
@@ -22,10 +22,16 @@ if (theme.plugins.heti && theme.plugins.heti.enable) {
22
22
  <% if (page.mathjax == true){ %>
23
23
  <%- partial('mathjax') %>
24
24
  <% } %>
25
+ <% if (page.mermaid == true){ %>
26
+ <%- partial('mermaid') %>
27
+ <% } %>
25
28
  <%- partial('_partial/main/navbar/breadcrumb') %>
26
29
  <article class='md-text content<%- heti %> <%- post.layout %><%- post.indent ? ' indent' : '' %><%- scrollreveal() %>'>
27
30
  <%- layoutTitle() %>
28
31
  <%- post.content %>
32
+ <% if (theme.plugins.tianli_gpt.enable && ['all', 'post'].includes(theme.plugins.tianli_gpt.field)) { %>
33
+ <%- partial('_partial/main/article/ai_abstract') %>
34
+ <% } %>
29
35
  <%- partial('_partial/main/article/article_footer') %>
30
36
  </article>
31
37
  <%- partial('_partial/main/article/read_next') %>
package/layout/wiki.ejs CHANGED
@@ -29,10 +29,16 @@ function layoutTitle() {
29
29
  page.header = 'auto';
30
30
  }
31
31
  %>
32
+ <% if (page.mermaid == true){ %>
33
+ <%- partial('mermaid') %>
34
+ <% } %>
32
35
  <%- partial('_partial/main/navbar/breadcrumb') %>
33
36
  <article class='md-text content <%- page.layout %><%- page.indent ? ' indent' : '' %><%- scrollreveal() %>'>
34
37
  <%- layoutTitle() %>
35
38
  <%- page.content %>
39
+ <% if (theme.plugins.tianli_gpt.enable && ['all', 'wiki'].includes(theme.plugins.tianli_gpt.field)) { %>
40
+ <%- partial('_partial/main/article/ai_abstract') %>
41
+ <% } %>
36
42
  <%- partial('_partial/main/article/article_footer') %>
37
43
  </article>
38
44
  <%- partial('_partial/main/article/read_next') %>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hexo-theme-stellar",
3
- "version": "1.18.5",
3
+ "version": "1.20.0",
4
4
  "description": "Elegant and powerful theme for Hexo.",
5
5
  "main": "package.json",
6
6
  "scripts": {
@@ -7,157 +7,188 @@
7
7
  class WikiPage {
8
8
  constructor(page) {
9
9
  this.id = page._id
10
+ this.wiki = page.wiki
10
11
  this.title = page.title
12
+ this.seo_title = page.seo_title
11
13
  this.path = page.path
14
+ this.path_key = page.path.replace('.html', '')
12
15
  this.layout = page.layout
13
- this.seo_title = page.seo_title
14
- this.wiki = page.wiki
15
- this.order = page.order || 0
16
16
  this.updated = page.updated
17
17
  }
18
18
  }
19
19
 
20
- function createWikiObject(ctx) {
21
- const wiki = { projects:{} }
22
- const { projects } = ctx.locals.get('data')
23
- if (projects) {
24
- Object.assign(wiki.projects, projects)
20
+ function getWikiObject(ctx) {
21
+ var wiki = { tree:{} }
22
+ const data = ctx.locals.get('data')
23
+ var list = []
24
+ for (let key of Object.keys(data)) {
25
+ if (key.includes('wiki/') && key.length > 5) {
26
+ let newKey = key.replace('wiki/', '')
27
+ let obj = data[key]
28
+ if ((typeof obj.tags == 'string') && obj.tags.constructor == String) {
29
+ obj.tags = [obj.tags]
30
+ }
31
+ if ((typeof obj.toc == 'object') && obj.toc.constructor == Array) {
32
+ obj.toc = { '': obj.toc }
33
+ }
34
+ obj.id = newKey
35
+ if (obj.sort == null) {
36
+ obj.sort = 0
37
+ }
38
+ if (obj.path?.startsWith('/')) {
39
+ obj.path = obj.path.substring(1)
40
+ }
41
+ if (obj.path?.endsWith('/') == false) {
42
+ obj.path = obj.path + '/'
43
+ }
44
+ list.push(obj)
45
+ }
46
+ }
47
+ list = list.sort((p1, p2) => p2.sort - p1.sort)
48
+ for (let item of list) {
49
+ wiki.tree[item.id] = item
25
50
  }
26
51
  return wiki
27
52
  }
28
53
 
29
54
  module.exports = ctx => {
30
55
  // wiki 配置
31
- var wiki = createWikiObject(ctx)
56
+ var wiki = getWikiObject(ctx)
32
57
  const pages = ctx.locals.get('pages')
33
58
  // wiki 所有页面
34
- const wiki_pages = pages.filter(p => (p.layout === 'wiki') && (p.wiki != undefined) && (p.wiki.length > 0)).map(p => new WikiPage(p))
59
+ const wiki_pages = pages.filter(p => (p.layout === 'wiki')).map(p => new WikiPage(p))
60
+ const wiki_list = Object.keys(wiki.tree)
35
61
 
36
62
  // 数据整合:项目标签
37
63
  var all_tag_name = []
38
- for (let id of Object.keys(wiki.projects)) {
39
- let proj = wiki.projects[id]
40
- let tags = proj.tags
64
+ for (let id of wiki_list) {
65
+ let item = wiki.tree[id]
66
+ let tags = item.tags
41
67
  if (tags) {
42
- if ((typeof tags == 'string') && tags.constructor == String) {
43
- if (all_tag_name.includes(tags) === false) {
44
- all_tag_name.push(tags)
68
+ tags.forEach((tag, i) => {
69
+ if (all_tag_name.includes(tag) === false) {
70
+ all_tag_name.push(tag)
45
71
  }
46
- // 类型转换
47
- tags = [tags]
48
- } else if ((typeof tags == 'object') && tags.constructor == Array) {
49
- tags.forEach((tag, i) => {
50
- if (all_tag_name.includes(tag) === false) {
51
- all_tag_name.push(tag)
52
- }
53
- })
54
- }
55
- wiki.projects[id].tags = tags
72
+ })
73
+ wiki.tree[id].tags = tags
56
74
  }
57
75
  }
58
- // 补充未分组的项目
59
- const projs = Object.keys(wiki.projects)
60
- wiki_pages.forEach((p, i) => {
61
- if (projs.includes(p.wiki) == false) {
62
- if (wiki.projects[p.wiki] == undefined) {
63
- wiki.projects[p.wiki] = {}
64
- wiki.projects[p.wiki].pages = []
65
- }
66
- var proj = wiki.projects[p.wiki]
67
- if (proj.description == undefined) {
68
- proj.description = p.description
69
- }
70
- wiki.projects[p.wiki].pages.push(p)
71
- }
72
- })
76
+
73
77
  // 补充项目名称和首页
74
- for (let id of Object.keys(wiki.projects)) {
75
- let proj = wiki.projects[id]
76
- proj.id = id
77
- if (proj.title == undefined || proj.title.length === 0) {
78
- proj.title = id
78
+ for (let id of wiki_list) {
79
+ let item = wiki.tree[id]
80
+ item.id = id
81
+ if (item.title == undefined || item.title.length === 0) {
82
+ item.title = id
79
83
  }
80
- if (proj.name == undefined || proj.name.length == 0) {
81
- proj.name = id
84
+ if (item.name == undefined || item.name.length == 0) {
85
+ item.name = id
82
86
  }
83
87
  }
84
- // 补充 order
85
- wiki_pages.forEach((p, i) => {
86
- if (p.order == undefined) {
87
- p.order = 0
88
- }
89
- })
90
-
88
+
91
89
  // 数据整合:每个项目的子页面
92
- for (let id of Object.keys(wiki.projects)) {
93
- let proj = wiki.projects[id]
94
- let proj_pages = wiki_pages.filter(p => p.wiki === id).sort((p1, p2) => p1.order < p2.order ? -1 : 1)
95
- if (!proj_pages || proj_pages.length == 0) {
90
+ for (let i = 0; i < wiki_list.length; i++) {
91
+ let id = wiki_list[i];
92
+ let item = wiki.tree[id]
93
+ let sub_pages = wiki_pages.filter(p => p.wiki === id)
94
+ if (!sub_pages || sub_pages.length == 0) {
95
+ wiki_list.splice(i, 1)
96
+ delete wiki.tree[id]
96
97
  continue
97
98
  }
98
- proj.homepage = proj_pages[0]
99
- proj.homepage.is_homepage = true
100
- // 内页按 section 分组
101
- var section_configs = []
102
- if (proj.sections) {
103
- for (let t of Object.keys(proj.sections)) {
104
- let range = proj.sections[t]
105
- if (range.length > 1) {
106
- section_configs.push({
107
- title: t,
108
- from: range[0],
109
- to: range[1]
110
- })
99
+
100
+ // 首页
101
+ // 未特别指定首页时,获取TOC第一页作为首页
102
+ if (item.homepage == null && item.toc != null) {
103
+ for (let id of Object.keys(item.toc)) {
104
+ const sec = item.toc[id]
105
+ for (let key of sec) {
106
+ let hs = sub_pages.filter(p => p.path_key == item.path + key)
107
+ if (hs.length > 0) {
108
+ item.homepage = hs[0]
109
+ break
110
+ }
111
+ }
112
+ if (item.homepage != null) {
113
+ break
111
114
  }
112
115
  }
113
116
  }
117
+ if (item.homepage == null) {
118
+ item.homepage = sub_pages[0]
119
+ }
120
+ item.homepage.is_homepage = true
121
+ // 内页分组
114
122
  var sections = []
115
- section_configs.forEach((sec, i) => {
116
- const sec_pages = proj_pages.filter( p => p.order >= sec.from && p.order <= sec.to )
117
- if (sec_pages && sec_pages.length > 0) {
123
+ var others = sub_pages
124
+ if (item.toc) {
125
+ // 根据配置设置顺序
126
+ for (let title of Object.keys(item.toc)) {
127
+ var sec = { title: title, pages: []}
128
+ for (let key of item.toc[title]) {
129
+ sec.pages = sec.pages.concat(sub_pages.filter(p => p.path_key == item.path + key))
130
+ others = others.filter(p => p.path_key != item.path + key)
131
+ }
132
+ sections.push(sec)
133
+ }
134
+ if (others.length > 0 && others.filter(p => p.title?.length > 0).length > 0) {
118
135
  sections.push({
119
- title: sec.title,
120
- pages: sec_pages
136
+ title: '...',
137
+ pages: others.sort((p1, p2) => p1.path - p2.path)
121
138
  })
122
139
  }
123
- })
124
- proj.sections = sections
125
- proj.pages = proj_pages
140
+ } else {
141
+ // 自动设置顺序
142
+ sections.push({
143
+ pages: sub_pages.sort((p1, p2) => p1.path - p2.path)
144
+ })
145
+ }
146
+
147
+ // page number
148
+ var page_number = 0
149
+ for (let sec of sections) {
150
+ for (let page of sec.pages) {
151
+ page.page_number = page_number++
152
+ }
153
+ }
154
+ item.sections = sections
155
+ item.pages = sub_pages
126
156
  }
127
-
157
+
128
158
  // 全站所有的项目标签
129
159
  var all_tags = {}
130
160
  all_tag_name.forEach((tag_name, i) => {
131
- var projs = []
132
- for (let id of Object.keys(wiki.projects)) {
133
- let proj = wiki.projects[id]
134
- if (proj.tags && proj.tags.includes(tag_name) === true && projs.includes(tag_name) === false) {
135
- projs.push(proj.id)
161
+ var subs = []
162
+ for (let id of wiki_list) {
163
+ let item = wiki.tree[id]
164
+ if (item.tags && item.tags.includes(tag_name) === true && subs.includes(tag_name) === false) {
165
+ subs.push(item.id)
136
166
  }
137
167
  }
138
168
  all_tags[tag_name] = {
139
169
  name: tag_name,
140
170
  path: (ctx.config.wiki_dir || 'wiki') + '/tags/' + tag_name + '/index.html',
141
- items: projs
171
+ items: subs
142
172
  }
143
173
  })
144
174
 
145
175
  // 关联相似项目
146
- for (let id of Object.keys(wiki.projects)) {
147
- let proj = wiki.projects[id]
148
- if (proj.tags) {
176
+ for (let id of wiki_list) {
177
+ let item = wiki.tree[id]
178
+ if (item.tags) {
149
179
  var related = []
150
- proj.tags.forEach((tag_name, i) => {
180
+ item.tags.forEach((tag_name, i) => {
151
181
  let tagObj = all_tags[tag_name]
152
182
  related = related.concat(tagObj.items)
153
183
  related = [...new Set(related)]
154
184
  })
155
- proj.related = related
185
+ item.related = related
156
186
  }
157
187
  }
158
188
 
159
189
  wiki.all_tags = all_tags
160
190
  wiki.all_pages = wiki_pages
191
+ wiki.shelf = ctx.locals.get('data').wiki
161
192
  ctx.theme.config.wiki = wiki
162
193
 
163
194
  }
@@ -2,3 +2,16 @@
2
2
 
3
3
  hexo.extend.filter.register('after_render:html', require('./lib/img_lazyload').processSite);
4
4
  hexo.extend.filter.register('after_render:html', require('./lib/img_onerror').processSite);
5
+
6
+ function change_image(data) {
7
+ if (this.theme.config.tag_plugins.image.parse_markdown) {
8
+ data.content = data.content.replace(
9
+ /!\[(.*?)\]\((.*?)\s*(?:"(.*?)")?\)/g,
10
+ '{% image $2 $3 %}'
11
+ );
12
+ }
13
+ return data;
14
+ }
15
+
16
+
17
+ hexo.extend.filter.register('before_post_render', change_image, 9);
@@ -32,6 +32,6 @@ hexo.extend.tag.register('navbar', require('./lib/navbar')(hexo))
32
32
  hexo.extend.tag.register('note', require('./lib/note')(hexo))
33
33
  hexo.extend.tag.register('poetry', require('./lib/poetry')(hexo), true)
34
34
  hexo.extend.tag.register('quot', require('./lib/quot')(hexo))
35
- hexo.extend.tag.register('tag', require('./lib/tag')(hexo))
36
-
35
+ hexo.extend.tag.register('hashtag', require('./lib/hashtag')(hexo))
36
+ hexo.extend.tag.register('okr', require('./lib/okr')(hexo), {ends: true})
37
37
  // others