From 761e9e6882c02dbe070bb014b5d92f721296288d Mon Sep 17 00:00:00 2001 From: xaoxuu Date: Wed, 6 Dec 2023 13:20:04 +0800 Subject: [PATCH] [opt] wiki reconstruction --- layout/_partial/cover/wiki_cover.ejs | 2 +- layout/_partial/head.ejs | 4 +- layout/_partial/main/article/read_next.ejs | 2 +- layout/_partial/main/navbar/breadcrumb.ejs | 12 +- layout/_partial/plugins/comments/layout.ejs | 4 +- layout/_partial/sidebar/header.ejs | 2 +- layout/_partial/sidebar/index.ejs | 6 +- layout/_partial/widgets/ghissues.ejs | 2 +- layout/_partial/widgets/ghrepo.ejs | 2 +- layout/_partial/widgets/recent.ejs | 6 +- layout/_partial/widgets/related.ejs | 8 +- layout/_partial/widgets/toc.ejs | 8 +- layout/index.ejs | 9 +- scripts/events/lib/doc_tree.js | 197 ++++++++++---------- scripts/tags/lib/toc.js | 2 +- 15 files changed, 139 insertions(+), 127 deletions(-) diff --git a/layout/_partial/cover/wiki_cover.ejs b/layout/_partial/cover/wiki_cover.ejs index 2be64b3..404b75c 100644 --- a/layout/_partial/cover/wiki_cover.ejs +++ b/layout/_partial/cover/wiki_cover.ejs @@ -1,7 +1,7 @@ <% function layoutWikiCover() { var el = ''; - let proj = theme.wiki.projects[page.wiki]; + let proj = theme.wiki.tree[page.wiki]; if (proj == undefined) { return el; } diff --git a/layout/_partial/head.ejs b/layout/_partial/head.ejs index f14ea73..3f63872 100755 --- a/layout/_partial/head.ejs +++ b/layout/_partial/head.ejs @@ -4,7 +4,7 @@ function generate_title() { return page.seo_title; } if (page.wiki) { - let proj = theme.wiki.projects[page.wiki]; + let proj = theme.wiki.tree[page.wiki]; let wiki = (proj && proj.name) || page.wiki; if (page.title) { return wiki + __('symbol.colon') + page.title + ' - ' + config.title; @@ -27,7 +27,7 @@ function generate_description() { return ''; } if (page.layout == 'wiki' && page.wiki) { - let proj = theme.wiki.projects[page.wiki]; + let proj = theme.wiki.tree[page.wiki]; if (proj && proj.description) { return ''; } diff --git a/layout/_partial/main/article/read_next.ejs b/layout/_partial/main/article/read_next.ejs index 43d36c7..ee91a31 100644 --- a/layout/_partial/main/article/read_next.ejs +++ b/layout/_partial/main/article/read_next.ejs @@ -10,7 +10,7 @@ function layoutDiv() { title_prev = __('meta.newer'); title_next = __('meta.older'); } else if (page.layout === 'wiki' && page.wiki && page.wiki.length > 0) { - let proj = theme.wiki.projects[page.wiki]; + let proj = theme.wiki.tree[page.wiki]; if (proj) { const current = page.order || 0; proj.pages.forEach((p, i) => { diff --git a/layout/_partial/main/navbar/breadcrumb.ejs b/layout/_partial/main/navbar/breadcrumb.ejs index 9bc2014..2899a21 100644 --- a/layout/_partial/main/navbar/breadcrumb.ejs +++ b/layout/_partial/main/navbar/breadcrumb.ejs @@ -58,11 +58,13 @@ function layoutDiv() { el += '' + __("btn.wiki") + ''; } // 项目名 - let proj = theme.wiki.projects[page.wiki]; - let url_proj = url_for(proj.homepage.path); - if (nodes.includes(url_proj) === false) { - el += ''; - el += '' + (proj.name || proj.title) + ''; + let proj = theme.wiki.tree[page.wiki]; + if (proj != null) { + let url_proj = url_for(proj.homepage.path); + if (nodes.includes(url_proj) === false) { + el += ''; + el += '' + (proj.name || proj.title) + ''; + } } el += ''; // 更新日期 diff --git a/layout/_partial/plugins/comments/layout.ejs b/layout/_partial/plugins/comments/layout.ejs index f7dd825..5405784 100644 --- a/layout/_partial/plugins/comments/layout.ejs +++ b/layout/_partial/plugins/comments/layout.ejs @@ -12,8 +12,8 @@ if (theme.comments.service && theme.comments.service.length > 0) { } } // 合并项目评论 -if (loadComment && page.layout == 'wiki' && page.wiki) { - let proj = theme.wiki.projects[page.wiki]; +let proj = theme.wiki.tree[page.wiki]; +if (loadComment && page.layout == 'wiki' && page.wiki && (proj != null)) { if (proj.comment_title != undefined && page.comment_title == undefined) { if (['utterances', 'beaudar', 'giscus'].includes(theme.comments.service)) { page.comment_title = proj.comment_title; diff --git a/layout/_partial/sidebar/header.ejs b/layout/_partial/sidebar/header.ejs index 92c7ffa..e661704 100644 --- a/layout/_partial/sidebar/header.ejs +++ b/layout/_partial/sidebar/header.ejs @@ -1,7 +1,7 @@ <% var proj; if (page.layout === 'wiki' && page.wiki) { - proj = theme.wiki.projects[page.wiki]; + proj = theme.wiki.tree[page.wiki]; } function layoutTitle(main, url, sub) { var el = ''; diff --git a/layout/_partial/sidebar/index.ejs b/layout/_partial/sidebar/index.ejs index 1c81660..1d4d75e 100755 --- a/layout/_partial/sidebar/index.ejs +++ b/layout/_partial/sidebar/index.ejs @@ -1,15 +1,15 @@ <% var proj; if (page.layout === 'wiki' && page.wiki) { - proj = theme.wiki.projects[page.wiki]; + proj = theme.wiki.tree[page.wiki]; } // 默认组件 if (page.sidebar == undefined) { if (page.layout == 'post' && page.content) { page.sidebar = theme.sidebar.widgets.post; } else if (page.layout == 'wiki' && page.content && page.wiki) { - let proj = theme.wiki.projects[page.wiki]; - if (proj.sidebar) { + let proj = theme.wiki.tree[page.wiki]; + if (proj?.sidebar) { page.sidebar = proj.sidebar; } else { page.sidebar = theme.sidebar.widgets.wiki; diff --git a/layout/_partial/widgets/ghissues.ejs b/layout/_partial/widgets/ghissues.ejs index c229e57..e01a2fd 100644 --- a/layout/_partial/widgets/ghissues.ejs +++ b/layout/_partial/widgets/ghissues.ejs @@ -6,7 +6,7 @@ function layoutDiv() { if (page.repo) { repo = page.repo } else if (page.layout === 'wiki' && page.wiki) { - let proj = theme.wiki.projects[page.wiki]; + let proj = theme.wiki.tree[page.wiki]; if (proj && proj.repo) { repo = proj.repo; if (proj.branch != undefined) { diff --git a/layout/_partial/widgets/ghrepo.ejs b/layout/_partial/widgets/ghrepo.ejs index 57e83a6..aefcb08 100644 --- a/layout/_partial/widgets/ghrepo.ejs +++ b/layout/_partial/widgets/ghrepo.ejs @@ -6,7 +6,7 @@ function layoutDiv() { if (page.repo) { repo = page.repo } else if (page.layout === 'wiki' && page.wiki) { - let proj = theme.wiki.projects[page.wiki]; + let proj = theme.wiki.tree[page.wiki]; if (proj && proj.repo) { repo = proj.repo; if (proj.branch != undefined) { diff --git a/layout/_partial/widgets/recent.ejs b/layout/_partial/widgets/recent.ejs index ab9ec0d..e5ed8d8 100644 --- a/layout/_partial/widgets/recent.ejs +++ b/layout/_partial/widgets/recent.ejs @@ -15,8 +15,8 @@ function layoutDiv() { if (page.menu_id == 'wiki') { arr = theme.wiki.all_pages.filter( p => { if (p.wiki) { - let proj = theme.wiki.projects[p.wiki]; - return proj.index != false; + let proj = theme.wiki.tree[p.wiki]; + return proj?.index != false; } return false }) @@ -32,7 +32,7 @@ function layoutDiv() { el += ''; el += '' if (post.layout == 'wiki') { - let proj = theme.wiki.projects[post.wiki]; + let proj = theme.wiki.tree[post.wiki]; let name = proj?.name || post?.wiki; if (name) { el += '' + name + '' + ''; diff --git a/layout/_partial/widgets/related.ejs b/layout/_partial/widgets/related.ejs index 46e93c6..8dd6a39 100644 --- a/layout/_partial/widgets/related.ejs +++ b/layout/_partial/widgets/related.ejs @@ -4,11 +4,11 @@ function layoutDiv() { return ''; } var related = []; - let proj = theme.wiki.projects[page.wiki]; - if (proj.related && proj.related.length > 0) { + let proj = theme.wiki.tree[page.wiki]; + if (proj?.related?.length > 0) { proj.related.forEach((pid, i) => { - let p = theme.wiki.projects[pid]; - if (p && p.title !== proj.title && p.index !== false) { + let p = theme.wiki.tree[pid]; + if (p && p.title !== proj?.title && p.index !== false) { related.push(p); } }); diff --git a/layout/_partial/widgets/toc.ejs b/layout/_partial/widgets/toc.ejs index 2555976..1fb4e0b 100644 --- a/layout/_partial/widgets/toc.ejs +++ b/layout/_partial/widgets/toc.ejs @@ -1,5 +1,5 @@ <% -let proj = theme.wiki.projects[page.wiki]; +let proj = theme.wiki.tree[page.wiki]; function layoutToc() { if (toc(page.content).length > 0) { @@ -74,10 +74,12 @@ function layoutDiv(fallback) { el += ''; } else if (proj) { // wiki 布局 - if (proj.sections && proj.sections.length > 0) { + if (proj.sections && proj.sections.length > 1) { proj.sections.forEach((sec, i) => { // 多 section - el += layoutTocHeader(sec.title); + if (sec.title?.length > 0) { + el += layoutTocHeader(sec.title); + } el += '
'; el += layoutDocTree(sec.pages); el += '
'; diff --git a/layout/index.ejs b/layout/index.ejs index 522f3a9..17c72fc 100755 --- a/layout/index.ejs +++ b/layout/index.ejs @@ -51,9 +51,12 @@ function layout_posts(partial) { function layout_wikis(partial) { var el = ''; var wikis = []; - const projects = theme.wiki.projects; - for (let proj_name of Object.keys(projects)) { - let proj = projects[proj_name]; + const wiki_tree = theme.wiki.tree; + for (let proj_name of Object.keys(wiki_tree)) { + let proj = wiki_tree[proj_name]; + if (proj == null) { + continue; + } if (proj.index === false || proj.pages == undefined || proj.pages.length === 0) { continue; } diff --git a/scripts/events/lib/doc_tree.js b/scripts/events/lib/doc_tree.js index 1e293c9..eb5c7d1 100644 --- a/scripts/events/lib/doc_tree.js +++ b/scripts/events/lib/doc_tree.js @@ -7,152 +7,157 @@ class WikiPage { constructor(page) { this.id = page._id - this.title = page.title - this.path = page.path - this.layout = page.layout - this.seo_title = page.seo_title this.wiki = page.wiki - this.order = page.order || 0 + this.title = page.title + this.seo_title = page.seo_title + this.path = page.path + this.path_key = page.path.replace('.html', '') + this.layout = page.layout this.updated = page.updated } } -function createWikiObject(ctx) { - const wiki = { projects:{} } - const { projects } = ctx.locals.get('data') - if (projects) { - Object.assign(wiki.projects, projects) +function getWikiObject(ctx) { + var wiki = { tree:{} } + const data = ctx.locals.get('data') + var list = [] + for (let key of Object.keys(data)) { + if (key.includes('wiki/') && key.length > 5) { + let newKey = key.replace('wiki/', '') + let obj = data[key] + if ((typeof obj.tags == 'string') && obj.tags.constructor == String) { + obj.tags = [obj.tags] + } + if ((typeof obj.toc == 'object') && obj.toc.constructor == Array) { + obj.toc = { '': obj.toc } + } + obj.id = newKey + if (obj.sort == null) { + obj.sort = 0 + } + list.push(obj) + } + } + list = list.sort((p1, p2) => p1.sort - p2.sort) + for (let item of list) { + wiki.tree[item.id] = item } return wiki } module.exports = ctx => { // wiki 配置 - var wiki = createWikiObject(ctx) + var wiki = getWikiObject(ctx) const pages = ctx.locals.get('pages') // wiki 所有页面 - const wiki_pages = pages.filter(p => (p.layout === 'wiki') && (p.wiki != undefined) && (p.wiki.length > 0)).map(p => new WikiPage(p)) + const wiki_pages = pages.filter(p => (p.layout === 'wiki')).map(p => new WikiPage(p)) + const wiki_list = Object.keys(wiki.tree) // 数据整合:项目标签 var all_tag_name = [] - for (let id of Object.keys(wiki.projects)) { - let proj = wiki.projects[id] - let tags = proj.tags + for (let id of wiki_list) { + let item = wiki.tree[id] + let tags = item.tags if (tags) { - if ((typeof tags == 'string') && tags.constructor == String) { - if (all_tag_name.includes(tags) === false) { - all_tag_name.push(tags) + tags.forEach((tag, i) => { + if (all_tag_name.includes(tag) === false) { + all_tag_name.push(tag) } - // 类型转换 - tags = [tags] - } else if ((typeof tags == 'object') && tags.constructor == Array) { - tags.forEach((tag, i) => { - if (all_tag_name.includes(tag) === false) { - all_tag_name.push(tag) - } - }) - } - wiki.projects[id].tags = tags + }) + wiki.tree[id].tags = tags } } - // 补充未分组的项目 - const projs = Object.keys(wiki.projects) - wiki_pages.forEach((p, i) => { - if (projs.includes(p.wiki) == false) { - if (wiki.projects[p.wiki] == undefined) { - wiki.projects[p.wiki] = {} - wiki.projects[p.wiki].pages = [] - } - var proj = wiki.projects[p.wiki] - if (proj.description == undefined) { - proj.description = p.description - } - wiki.projects[p.wiki].pages.push(p) - } - }) - // 补充项目名称和首页 - for (let id of Object.keys(wiki.projects)) { - let proj = wiki.projects[id] - proj.id = id - if (proj.title == undefined || proj.title.length === 0) { - proj.title = id - } - if (proj.name == undefined || proj.name.length == 0) { - proj.name = id - } - } - // 补充 order - wiki_pages.forEach((p, i) => { - if (p.order == undefined) { - p.order = 0 - } - }) + // 补充项目名称和首页 + for (let id of wiki_list) { + let item = wiki.tree[id] + item.id = id + if (item.title == undefined || item.title.length === 0) { + item.title = id + } + if (item.name == undefined || item.name.length == 0) { + item.name = id + } + } + // 数据整合:每个项目的子页面 - for (let id of Object.keys(wiki.projects)) { - let proj = wiki.projects[id] - let proj_pages = wiki_pages.filter(p => p.wiki === id).sort((p1, p2) => p1.order < p2.order ? -1 : 1) - if (!proj_pages || proj_pages.length == 0) { + for (let id of wiki_list) { + let item = wiki.tree[id] + let sub_pages = wiki_pages.filter(p => p.wiki === id) + if (!sub_pages || sub_pages.length == 0) { continue } - proj.homepage = proj_pages[0] - proj.homepage.is_homepage = true - // 内页按 section 分组 - var section_configs = [] - if (proj.sections) { - for (let t of Object.keys(proj.sections)) { - let range = proj.sections[t] - if (range.length > 1) { - section_configs.push({ - title: t, - from: range[0], - to: range[1] - }) + + // 首页 + // 未特别指定首页时,获取TOC第一页作为首页 + if (item.homepage == null && item.toc != null) { + for (let id of Object.keys(item.toc)) { + const path_key = item.toc[id] + let hs = sub_pages.filter(p => (p.path_key.endsWith(path_key))) + if (hs.length > 0) { + item.homepage = hs[0] + break } } } + if (item.homepage == null) { + item.homepage = sub_pages[0] + } + item.homepage.is_homepage = true + // 内页分组 var sections = [] - section_configs.forEach((sec, i) => { - const sec_pages = proj_pages.filter( p => p.order >= sec.from && p.order <= sec.to ) - if (sec_pages && sec_pages.length > 0) { + var others = sub_pages + if (item.toc) { + for (let title of Object.keys(item.toc)) { + let key_list = item.toc[title] + var arr = [] + for (let key of key_list) { + arr = arr.concat(sub_pages.filter(p => p.path_key.endsWith(key))) + others = others.filter(p => p.path_key.endsWith(key) == false) + } sections.push({ - title: sec.title, - pages: sec_pages + title: title, + pages: arr }) } - }) - proj.sections = sections - proj.pages = proj_pages + } + if (others.length > 0) { + sections.push({ + pages: others + }) + } + item.sections = sections + item.pages = sub_pages } // 全站所有的项目标签 var all_tags = {} all_tag_name.forEach((tag_name, i) => { - var projs = [] - for (let id of Object.keys(wiki.projects)) { - let proj = wiki.projects[id] - if (proj.tags && proj.tags.includes(tag_name) === true && projs.includes(tag_name) === false) { - projs.push(proj.id) + var subs = [] + for (let id of wiki_list) { + let item = wiki.tree[id] + if (item.tags && item.tags.includes(tag_name) === true && subs.includes(tag_name) === false) { + subs.push(item.id) } } all_tags[tag_name] = { name: tag_name, path: (ctx.config.wiki_dir || 'wiki') + '/tags/' + tag_name + '/index.html', - items: projs + items: subs } }) // 关联相似项目 - for (let id of Object.keys(wiki.projects)) { - let proj = wiki.projects[id] - if (proj.tags) { + for (let id of wiki_list) { + let item = wiki.tree[id] + if (item.tags) { var related = [] - proj.tags.forEach((tag_name, i) => { + item.tags.forEach((tag_name, i) => { let tagObj = all_tags[tag_name] related = related.concat(tagObj.items) related = [...new Set(related)] }) - proj.related = related + item.related = related } } diff --git a/scripts/tags/lib/toc.js b/scripts/tags/lib/toc.js index d2780bd..8a267b4 100644 --- a/scripts/tags/lib/toc.js +++ b/scripts/tags/lib/toc.js @@ -43,7 +43,7 @@ module.exports = ctx => function(args) { el += '' if (args.wiki) { - const proj = ctx.theme.config.wiki.projects[args.wiki] + const proj = ctx.theme.config.wiki.tree[args.wiki] if (proj == undefined) { return '' }