wiki系统重构,支持数据文件

This commit is contained in:
xaoxuu 2021-07-04 20:21:31 +08:00
parent cf4554e474
commit 4a0d65ad71
14 changed files with 352 additions and 214 deletions

View File

@ -13,22 +13,23 @@ function layoutWikiCover() {
var el = '';
el += '<div class="l_cover' + scrollreveal() + '">';
el += '<article class="cover-wrap md">';
if (page.logo && page.logo.src && cover.includes('logo')) {
let proj = theme.wiki.projects[page.wiki];
if (proj.logo && proj.logo.src && cover.includes('logo')) {
el += '<div class="preview">';
if (page.logo.large) {
el += '<img src="' + page.logo.src + '" height="' + page.logo.large + '">';
if (proj.logo.large) {
el += '<img src="' + proj.logo.src + '" height="' + proj.logo.large + '">';
} else {
el += '<img src="' + page.logo.src + '">';
el += '<img src="' + proj.logo.src + '">';
}
el += '</div>';
}
if (page.title && cover.includes('title')) {
if ((proj.title || page.title) && cover.includes('title')) {
el += '<div class="cover-title">';
el += '<span>' + (page.wiki || page.title) + '</span>';
el += '<span>' + (proj.title || page.title) + '</span>';
el += '</div>';
}
if (page.description && cover.includes('description')) {
el += '<div class="description">' + page.description + '</div>';
if ((proj.description || page.description) && cover.includes('description')) {
el += '<div class="description">' + (proj.description || page.description) + '</div>';
}
el += '<div class="start-wrap">';
el += '<a class="button theme start" href="#start">' + __('btn.getting_started') + '</a>';

View File

@ -1,66 +1,87 @@
<% if (page.breadcrumb != false) { %>
<div class='bread-nav fs12'>
<% if (page.layout == 'post') { %>
<%
var firstCat = '';
function layoutDiv() {
var el = '';
if (page.breadcrumb === false) {
return el;
}
el += '<div class="bread-nav fs12">';
if (page.layout === "post") {
var firstCat = "";
if (page.categories && page.categories.length > 0) {
firstCat = page.categories.data[0].name;
}
%>
<div id='breadcrumb'<%- category_color(firstCat) %>>
<a class='cap breadcrumb' href='/'><%- __('btn.home') %></a>
<span class="sep"></span>
<a class='cap breadcrumb' href='/'><%- __('btn.blog') %></a>
<% if (page.layout == 'post' && page.categories && page.categories.length > 0) { %>
<span class="sep"></span>
<%- list_categories(page.categories, {
class: 'cap breadcrumb',
el += '<div id="breadcrumb"' + category_color(firstCat) + '>';
el += '<a class="cap breadcrumb" href="/">' + __("btn.home") + '</a>';
el += '<span class="sep"></span>';
el += '<a class="cap breadcrumb" href="/">' + __("btn.blog") + '</a>';
if (page.layout == "post" && page.categories && page.categories.length > 0) {
el += '<span class="sep"></span>';
el += list_categories(page.categories, {
class: "cap breadcrumb",
show_count: false,
separator: ' <span class="sep"></span> ',
style: 'none'
}) %>
<% } %>
</div>
<div id='post-meta'>
<%- __('meta.created') %>&nbsp;<time datetime='<%- date_xml(page.date) %>'><%- date(page.date, config.date_format) %></time>
</div>
<% } else if (page.layout == 'wiki') { %>
<%
var catPage = '';
site.pages.filter(function (p) {
return p.layout == 'index' && p.title && p.wiki && p.wiki.includes(page.wiki)
}).limit(1).each(function(p) {
catPage = p;
style: "none"
});
}
el += '</div>';
// 发布日期
el += '<div id="post-meta">';
el += __("meta.created") + '&nbsp;<time datetime="' + date_xml(page.date) + '">' + date(page.date, config.date_format) + '</time>';
el += '</div>';
} else if (page.layout === "wiki" && page.wiki && page.wiki.length > 0) {
var cat_name = '';
let proj = theme.wiki.projects[page.wiki];
if (proj.group && proj.group.length > 0) {
let group = theme.wiki.groups[proj.group];
if (group) {
cat_name = group.title;
}
}
el += '<div id="breadcrumb"' + category_color(cat_name) + '>';
var nodes = [];
// home
el += '<a class="cap breadcrumb" id="home" href="/">' + __("btn.home") + '</a>';
nodes.push('/');
// menu_id
el += '<span class="sep"></span>';
if (page.menu_id && theme.sidebar.menu[page.menu_id] && md_link(theme.sidebar.menu[page.menu_id])) {
let url = url_for(md_link(theme.sidebar.menu[page.menu_id]));
nodes.push(url);
el += '<a class="cap breadcrumb" id="menu" href="' + url + '">' + __(md_text(theme.sidebar.menu[page.menu_id])) + '</a>';
} else {
let url = url_for(config.wiki_dir || "/wiki/");
nodes.push(url);
el += '<a class="cap breadcrumb" id="menu" href="' + url + '">' + __("btn.wiki") + '</a>';
}
// group
if (proj.group && proj.group.length > 0) {
let group = theme.wiki.groups[proj.group];
let url = url_for(group.path);
if (group !== undefined && nodes.includes(url) === false) {
el += '<span class="sep"></span>';
el += '<a class="cap breadcrumb" id="group" href="' + url + '">' + group.title + '</a>';
}
}
// 项目名
let url_proj = url_for(proj.path);
if (nodes.includes(url_proj) === false) {
el += '<span class="sep"></span>';
el += '<a class="cap breadcrumb" id="proj" href="' + url_proj + '">' + proj.title + '</a>';
}
el += '</div>';
// 更新日期
el += '<div id="post-meta">';
el += __("meta.updated") + '&nbsp;<time datetime="' + date_xml(page.updated) + '">' + date(page.updated, config.date_format) + '</time>';
el += '</div>';
} else {
el += '<div id="breadcrumb">';
el += '<a class="cap breadcrumb" href="/">' + __("btn.home") + '</a>';
el += '<span class="sep"></span>';
el += '<a class="cap breadcrumb" href="' + url_for(page.path) + '">' + (page.title || page.seo_title) + '</a>';
el += '</div>';
}
el += '</div>';
return el;
}
%>
<div id='breadcrumb'<%- category_color(catPage.title) %>>
<a class='cap breadcrumb' href='/'><%- __('btn.home') %></a>
<span class="sep"></span>
<% if (page.menu_id && theme.sidebar.menu[page.menu_id] && md_link(theme.sidebar.menu[page.menu_id])) { %>
<a class='cap breadcrumb' href='<%- url_for(md_link(theme.sidebar.menu[page.menu_id])) %>'><%- __(md_text(theme.sidebar.menu[page.menu_id])) %></a>
<% } else { %>
<a class='cap breadcrumb' href='<%- url_for(config.wiki_dir || "/wiki/") %>'><%- __('btn.wiki') %></a>
<% } %>
<% if (catPage && catPage.title && catPage.path) { %>
<span class="sep"></span>
<a class='cap breadcrumb' href='<%- url_for(catPage.path) %>'><%- catPage.title %></a>
<% } %>
<% site.pages.filter(function (p) { %>
<% return p.layout == 'wiki' && p.wiki == page.wiki && p.description %>
<% }).limit(1).each(function(p) { %>
<span class="sep"></span>
<a class='cap breadcrumb' href='<%- url_for(p.path) %>'><%- page.wiki %></a>
<% }); %>
</div>
<div id='post-meta'>
<%- __('meta.updated') %>&nbsp;<time datetime='<%- date_xml(page.updated) %>'><%- date(page.updated, config.date_format) %></time>
</div>
<% } else { %>
<div id='breadcrumb'>
<a class='cap breadcrumb' href='/'><%- __('btn.home') %></a>
<span class="sep"></span>
<a class='cap breadcrumb' href='<%- url_for(page.path) %>'><%- page.title || page.seo_title %></a>
</div>
<% } %>
</div>
<% } %>
<%- layoutDiv() %>

View File

@ -1,28 +1,34 @@
<div class='nav-wrap mobile-hidden'>
<nav class='sub wiki cap'>
<% if (page.layout == 'index' && page.title && page.wiki) { %>
<a href='<%- url_for(config.wiki_dir || "/wiki/") %>'><%- __('btn.all_wiki') %></a>
<% } else { %>
<a class='active' href='<%- url_for(config.wiki_dir || "/wiki/") %>'><%- __('btn.all_wiki') %></a>
<% } %>
<%
var groups = [];
var paths = [];
site.pages.filter(function (p) {
return p.layout == 'index' && p.title && p.wiki;
}).sort('order').each(function(p) {
if (groups.includes(p.wiki) == false) {
groups.push(p.title);
paths.push(p.path);
function layoutDiv() {
var el = '';
el += '<div class="nav-wrap mobile-hidden">';
el += '<nav class="sub wiki cap">';
// 所有项目
el += '<a';
if (page.filter === false) {
el += ' class="active"';
}
el += ' href="' + url_for(config.wiki_dir || "/wiki/") + '">' + __("btn.all_wiki") + '</a>';
el += '</a>';
// 项目分类
for (let group_name of Object.keys(theme.wiki.groups)) {
let group = theme.wiki.groups[group_name];
let projects = group.projects.filter(function(proj){
return proj.index !== false;
})
if (projects && projects.length > 0) {
el += '<a';
if (group.title && group.title.length > 0 && page.group === group.title) {
el += ' class="active"';
}
el += ' href="' + url_for(group.path) + '">' + group.title + '</a>';
el += '</a>';
}
}
el += '</nav>';
el += '</div>';
return el;
}
});
%>
<% groups.forEach((group, i) => { %>
<% if (page.title == group) { %>
<a class='active' href='<%- url_for(paths[i]) %>'><%- group %></a>
<% } else { %>
<a class='' href='<%- url_for(paths[i]) %>'><%- group %></a>
<% } %>
<% }); %>
</nav>
</div>
<%- layoutDiv() %>

View File

@ -1,29 +1,23 @@
<%
function layoutDiv() {
var el = '';
if (post.logo && post.logo.src) {
if (proj.logo && proj.logo.src) {
el += '<div class="preview">';
el += '<img src="' + post.logo.src + '" alt="logo"';
if (post.logo.small) {
el += ' height="' + post.logo.small + '"';
el += '<img src="' + proj.logo.src + '" alt="logo"';
if (proj.logo.small) {
el += ' height="' + proj.logo.small + '"';
}
el += '/>';
el += '</div>';
}
el += '<div class="excerpt">';
var cat = '';
site.pages.filter(function (p) {
return p.layout == 'index' && p.title && p.wiki && p.wiki.includes(post.wiki)
}).limit(1).each(function(p) {
cat = p.title;
});
if (cat) {
el += '<div class="cap breadcrumb"' + category_color(cat) + '>';
el += '<span>' + cat + '</span>';
if (proj.group) {
el += '<div class="cap breadcrumb"' + category_color(proj.group) + '>';
el += '<span>' + proj.group + '</span>';
el += '</div>';
}
el += '<h2 class="post-title">' + (post.wiki || post.title || post.seo_title) + '</h2>';
el += '<p>' + post.description + '</p>';
el += '<h2 class="post-title">' + (proj.wiki || proj.title || proj.seo_title) + '</h2>';
el += '<p>' + proj.description + '</p>';
el += '</div>';
return el;
}

View File

@ -1,4 +1,23 @@
<%
function layoutMenu() {
var el = '';
el += '<nav class="menu dis-select">'
for (let id of Object.keys(theme.sidebar.menu)) {
let item = theme.sidebar.menu[id];
if (item == undefined || item.length == 0) {
continue;
}
el += '<a class="nav-item';
if (id == page.menu_id) {
el += ' active';
}
el += '" href="' + url_for(md_link(item)) + '">';
el += __(md_text(item));
el += '</a>';
}
el += '</nav>';
return el;
}
function layoutMainMenu() {
var el = '';
el += partial('logo');
@ -31,10 +50,13 @@ function layoutDiv() {
el += ' mobile-only';
}
el += '">';
if (page.layout === 'wiki') {
el += layoutWikiMenu();
el += partial('logo');
if (page.layout === 'wiki' && page.wiki) {
if (page.menu_id !== 'wiki') {
el += layoutMenu();
}
} else {
el += layoutMainMenu();
el += layoutMenu();
}
el += '</header>';
return el;

View File

@ -1,16 +1,12 @@
<%
var wiki;
if (page.layout === 'wiki') {
site.pages.filter(function (p) {
return p.layout == 'wiki' && p.wiki == page.wiki && p.description
}).limit(1).each(function(p) {
wiki = p;
});
var proj;
if (page.layout === 'wiki' && page.wiki) {
proj = theme.wiki.projects[page.wiki];
}
function layoutDiv() {
var el = '';
if (page.layout === 'wiki') {
if (page.layout === 'wiki' && proj.index !== false) {
el += '<div class="logo-wrap wiki">';
// all products
el += '<a style="filter: grayscale(100%)" class="wiki-home cap" href="' + url_for(config.wiki_dir) + '">';
@ -18,16 +14,18 @@ function layoutDiv() {
el += __('btn.all_wiki');
el += '</a>';
// this product
if (wiki === undefined) {
if (proj === undefined) {
// 如果没有项目名则使用menu中显示的名字
if (page.menu_id && theme.sidebar.menu[page.menu_id] && md_link(theme.sidebar.menu[page.menu_id])) {
wiki = new Object();
wiki.path = md_link(theme.sidebar.menu[page.menu_id]);
wiki.wiki = __(md_text(theme.sidebar.menu[page.menu_id]));
proj = {
path: md_link(theme.sidebar.menu[page.menu_id]),
wiki: __(md_text(theme.sidebar.menu[page.menu_id]))
};
}
}
if (wiki !== undefined) {
el += '<a class="title" href="' + url_for(wiki.path) + '">';
el += wiki.wiki;
if (proj !== undefined) {
el += '<a class="title" href="' + url_for(proj.path) + '">';
el += proj.title || proj.wiki;
el += '</a>';
}
} else {

View File

@ -3,38 +3,36 @@ function layoutDiv() {
if (page.layout !== "wiki") {
return '';
}
var current_group;
site.pages.filter(function (p) {
return p.layout == "index" && p.title && p.wiki && p.wiki.includes(page.wiki)
}).limit(1).each(function(p) {
current_group = p;
});
if (current_group === undefined || current_group.wiki.length < 1) {
return '';
}
var el = '';
let proj = theme.wiki.projects[page.wiki];
if (proj.group && proj.group.length > 0) {
let group = theme.wiki.groups[proj.group];
let projects = group.projects.filter(function(proj){
return proj.index !== false;
})
if (projects && projects.length > 1) {
var el = '';
el += '<div class="widget-wrap" id="related">';
el += '<div class="widget-header cap dis-select">';
el += '<span class="name">更多' + current_group.title + '</span>';
el += '<span class="name">更多' + group.title + '</span>';
el += '</div>';
el += '<div class="widget-body fs14">';
current_group.wiki.forEach((wiki, i) => {
site.pages.filter(function (p) {
return p.wiki == wiki && p.wiki != page.wiki && p.description
}).each(function(post) {
if (post.wiki || post.title) {
projects.forEach((p, i) => {
if (p.title !== proj.title) {
// 同一个分组中的其它项目
el += '<div class="line"></div>'
el += '<a class="reveal wiki" href="' + url_for(post.link || post.path) + '">';
el += post.wiki || post.title;
el += '<a class="reveal wiki" href="' + url_for(p.path) + '">';
el += p.title;
el += '<div class="excerpt">';
el += post.description;
el += p.description;
el += '</div>';
el += '</a>';
}
});
});
el += '</div>';
el += '</div>';
}
}
return el;
}
%>

View File

@ -1,6 +1,6 @@
<%
if (page.menu_id == undefined) {
if (page.layout == 'index' && page.title && page.wiki) {
if (page.menu_id === undefined) {
if (page.layout === 'index' && page.wiki) {
page.menu_id = 'wiki';
} else {
page.menu_id = 'post';
@ -10,12 +10,9 @@ if (page.title && page.wiki) {
page.robots = 'noindex,follow';
}
function layout_post_card(type, post, content) {
function layout_post_card(layout, post, content) {
var el = '';
if (post.post == undefined) {
post.post = 'article';
}
el += '<a class="post-card ' + type + ' ' + post.post + scrollreveal() + '" href="' + url_for(post.link || post.path) + '">';
el += '<a class="post-card ' + layout + ' ' + scrollreveal() + '" href="' + url_for(post.link || post.path) + '">';
el += '<article class="excerpt md">';
el += content;
el += '</article></a>';
@ -37,7 +34,7 @@ function layout_posts(partial) {
}
// unpinned posts
page.posts.each(function(post){
if (post.pin == undefined) {
if (post.pin === undefined) {
el += layout_post_card('post', post, partial(post));
}
})
@ -53,51 +50,41 @@ function layout_posts(partial) {
function layout_wikis(partial) {
var el = '';
var wikis = [];
if (page.title && page.wiki) {
// filtered wikis
page.wiki.forEach((wiki, i) => {
site.pages.filter(function (p) {
return p.layout == 'wiki' && p.wiki == wiki && p.description;
}).limit(1).each(function(post) {
wikis.push(post);
});
});
el += '<div class="post-list wiki filter">';
wikis.forEach(function(wiki) {
el += layout_post_card('wiki', wiki, partial(wiki));
});
el += '</div>';
} else {
const projects = theme.wiki.projects;
for (let proj_name of Object.keys(projects)) {
let proj = projects[proj_name];
if (proj.index === false || proj.pages === undefined || proj.pages.length === 0) {
continue;
}
if (page.filter === false) {
// all wikis
wikis = site.pages.filter(function (p) {
if (p.layout == 'wiki' && p.wiki && p.description) {
if (p.order == undefined) {
p.order = 0;
}
return true;
} else {
return false;
}
}).sort('order');
proj.pages.sort('order').limit(1).forEach((p0, i) => {
el += '<div class="post-list wiki">';
wikis.forEach(function(wiki) {
el += layout_post_card('wiki', wiki, partial(wiki));
});
el += layout_post_card('wiki', p0, partial(proj));
el += '</div>';
});
} else if (page.group === proj.group) {
// filtered wikis
proj.pages.sort('order').limit(1).forEach((p0, i) => {
el += '<div class="post-list wiki filter">';
el += layout_post_card('wiki', p0, partial(proj));
el += '</div>';
});
}
}
return el;
}
%>
<% if (page.menu_id == 'post') { %>
<% if (page.menu_id === 'post') { %>
<%- partial('_partial/main/navbar/list_post') %>
<%- layout_posts(function(post){
return partial('_partial/main/post_list/post_card', {post: post})
}) %>
<%- partial('_partial/main/post_list/paginator') %>
<% } else if (page.menu_id == 'wiki') { %>
<% } else if (page.menu_id === 'wiki') { %>
<%- partial('_partial/main/navbar/list_wiki') %>
<%- layout_wikis(function(post){
return partial('_partial/main/post_list/wiki_card', {post: post})
<%- layout_wikis(function(proj){
return partial('_partial/main/post_list/wiki_card', {proj: proj})
}) %>
<% } %>

View File

@ -1,13 +1,17 @@
<%
if (page.menu_id == undefined) {
if (page.menu_id === undefined) {
page.menu_id = 'wiki';
}
if (page.layout == undefined) {
if (page.layout === undefined) {
page.layout = 'index';
}
if (page.title == undefined) {
if (page.title === undefined) {
if (page.group) {
page.title = page.group;
} else {
page.title = __('btn.wiki');
}
}
function layoutTitle() {
const title = page.h1 || page.title;
if (title && title.length > 0) {
@ -17,11 +21,11 @@ function layoutTitle() {
}
}
%>
<% if (page.layout == 'index') { %>
<% if (page.layout === 'index') { %>
<%- partial('index') %>
<% } else { %>
<%
if (page.header == undefined) {
if (page.header === undefined) {
page.header = false;
}
%>

View File

@ -5,6 +5,7 @@
hexo.on('generateBefore', () => {
// Merge config.
require('./lib/config')(hexo);
require('./lib/doc_tree')(hexo);
require('./lib/utils')(hexo);
});

View File

@ -0,0 +1,88 @@
/**
* doc_tree.js v1 | https://github.com/xaoxuu/hexo-theme-stellar/
*/
'use strict';
module.exports = hexo => {
const data = hexo.locals.get('data');
if (data.projects) {
if (hexo.theme.config.wiki === undefined) {
hexo.theme.config.wiki = {};
}
if (hexo.theme.config.wiki.projects === undefined) {
hexo.theme.config.wiki.projects = {};
}
for (let id of Object.keys(data.projects)) {
hexo.theme.config.wiki.projects[id] = data.projects[id];
}
}
// wiki 配置
const { wiki } = hexo.theme.config;
// wiki 所有页面
const wiki_pages = hexo.locals.get('pages').filter(function (p) {
return (p.layout === 'wiki') && (p.wiki !== undefined) && (p.wiki.length > 0);
});
// 数据整合:项目组
var cats = [];
for (let proj_name of Object.keys(wiki.projects)) {
let proj = wiki.projects[proj_name];
if (proj.group !== undefined) {
if (cats.includes(proj.group) === false) {
cats.push(proj.group);
}
}
}
// 补充未分组的项目
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 proj_name of Object.keys(wiki.projects)) {
let proj = wiki.projects[proj_name];
if (proj.title === undefined || proj.title.length === 0) {
proj.title = proj_name;
}
}
// 数据整合:每个项目的子页面
for (let proj_name of Object.keys(wiki.projects)) {
let proj = wiki.projects[proj_name];
proj.pages = wiki_pages.filter(function (p) {
return p.wiki === proj_name;
}).sort('order');
proj.pages.limit(1).forEach((p, i) => {
proj.path = p.path;
});
}
var groups = {};
cats.forEach((group_name, i) => {
var projs = [];
for (let proj_name of Object.keys(wiki.projects)) {
let proj = wiki.projects[proj_name];
if (proj.group === group_name && projs.includes(group_name) === false) {
projs.push(proj);
}
}
groups[group_name] = {
title: group_name,
path: (hexo.config.wiki_dir || 'wiki') + '/categories/' + group_name + '/index.html',
projects: projs
};
});
wiki.groups = groups;
wiki.all_pages = wiki_pages;
};

View File

@ -10,11 +10,27 @@ hexo.extend.generator.register('wiki', function (locals) {
}
});
if (hasWiki) {
return {
var ret = [];
ret.push({
path: (hexo.config.wiki_dir || 'wiki') + '/index.html',
data: locals.posts,
data: {'filter': false},
layout: ['wiki']
});
if (hexo.theme.config.wiki && hexo.theme.config.wiki.groups) {
for (let group_name of Object.keys(hexo.theme.config.wiki.groups)) {
let group = hexo.theme.config.wiki.groups[group_name];
ret.push({
path: group.path,
data: {
'filter': true,
'title': group.title,
'group': group.title
},
layout: ['wiki']
});
}
}
return ret;
} else {
return {};
}

View File

@ -108,7 +108,7 @@ nav.menu
&.active, &:hover
color: var(--text-p1)
background: var(--card)
box-shadow: 0 0 4px 0px rgba(0, 0, 0, 0.1)
box-shadow: 0 0 2px 0px rgba(0, 0, 0, 0.04), 0 0 8px 0px rgba(0, 0, 0, 0.04)
.l_left .menu a.nav-item
flex-grow: 1

View File

@ -22,6 +22,8 @@
right: .5rem
&.active
color: var(--text-p1)
&:only-child
background: var(--card)
&:hover
background: var(--block-hover)
&:after