feat(layout): performance boost via fragment cache

This commit is contained in:
ppoffice 2019-08-16 01:03:19 -04:00
parent 7326878b41
commit 958138f214
75 changed files with 333 additions and 108 deletions

View File

@ -5,11 +5,14 @@
* <%- _list_archives() %>
* <%- _list_categories() %>
* <%- _list_tags() %>
* <%- _toc() %>
* <%- _js() %>
* <%- _css() %>
* <%- _toc(content) %>
* <%- _js(url, defer, async) %>
* <%- _css(url) %>
* <%- _partial(url) %>
*/
const cheerio = require('cheerio');
const { existsSync } = require('fs');
const { relative, dirname, join, extname } = require('path');
const __archives = [];
const __categories = [];
@ -151,4 +154,35 @@ module.exports = function (hexo) {
}
return `<link rel="stylesheet" href="${urlFor(url)}">`;
});
hexo.extend.helper.register('_partial', function (name, locals, options = {}) {
const { md5, partial, view_dir, page } = this;
const currentView = this.filename.substring(view_dir.length);
let _locals = Object.assign({}, locals, { layout: false });
let { path } = hexo.theme.getView(join(dirname(currentView), name)) || hexo.theme.getView(name);
path = join(view_dir, path.substring(0, path.length - extname(path).length) + '.locals.js');
if (!existsSync(path)) {
// fallback to default partial
return partial(name, locals, options);
}
_locals = require(path)(this, _locals);
if (_locals === null) {
// partial should be empty
return '';
}
if (_locals === false) {
// do not cache this fragment
return partial(name, locals, options);
}
const language = page.lang || page.language;
const fragment = relative(view_dir, path.substring(0, path.length - '.locals.js'.length));
const cacheId = [fragment, language, md5(JSON.stringify(_locals))].join('-');
return partial(name, _locals, { cache: cacheId, only: options.only || false });
});
}

View File

@ -52,5 +52,5 @@ if (!page.year) {
<%- buildArchive(page.posts, page.year, page.month) %>
<% } %>
<% if (page.total > 1) { %>
<%- partial('common/paginator') %>
<%- _partial('common/paginator') %>
<% } %>

View File

@ -11,4 +11,4 @@
</nav>
</div>
</div>
<%- partial('index', { page }) %>
<%- _partial('index', { page }) %>

View File

@ -3,7 +3,7 @@
You forgot to set the <code>appid</code> or <code>conf</code> for Changyan. Please set it in <code>_config.yml</code>.
</div>
<% } else { %>
<div id="SOHUCS" sid="<%= post.path %>"></div>
<div id="SOHUCS" sid="<%= path %>"></div>
<script charset="utf-8" type="text/javascript" src="https://changyan.sohu.com/upload/changyan.js" ></script>
<script type="text/javascript">
window.changyan.api.config({

View File

@ -0,0 +1,4 @@
module.exports = (ctx, locals) => {
const { page } = ctx;
return Object.assign(locals, { path: page.path });
}

View File

@ -1,8 +1,8 @@
<% if (has_config('comment.shortname')) { %>
<script>
var disqus_config = function () {
this.page.url = '<%= page.permalink %>';
this.page.identifier = '<%= page.disqusId || page.path %>';
this.page.url = '<%= permalink %>';
this.page.identifier = '<%= disqusId || path %>';
};
(function() {
var d = document, s = d.createElement('script');

View File

@ -0,0 +1,4 @@
module.exports = (ctx, locals) => {
const { permalink, disqusId, path } = ctx.page;
return Object.assign(locals, { permalink, disqusId, path });
}

View File

@ -5,4 +5,4 @@
js.src = "//connect.facebook.net/<%= get_config('language', 'en').split('-').join('_') %>/sdk.js#xfbml=1&version=v2.8";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
<div class="fb-comments" data-width="100%" data-href="<%= page.permalink %>" data-num-posts="5"></div>
<div class="fb-comments" data-width="100%" data-href="<%= permalink %>" data-num-posts="5"></div>

View File

@ -0,0 +1,4 @@
module.exports = (ctx, locals) => {
const { permalink } = ctx.page;
return Object.assign(locals, { permalink });
}

View File

@ -12,7 +12,7 @@
var gitalk = new Gitalk({
clientID: '<%= get_config('comment.client_id') %>',
clientSecret: '<%= get_config('comment.client_secret') %>',
id: '<%= md5(page.path) %>',
id: '<%= md5(path) %>',
repo: '<%= get_config('comment.repo') %>',
owner: '<%= get_config('comment.owner') %>',
admin: <%- JSON.stringify(get_config('comment.admin'))%>,

View File

@ -0,0 +1,4 @@
module.exports = (ctx, locals) => {
const { path } = ctx.page;
return Object.assign(locals, { path });
}

View File

@ -10,7 +10,7 @@
<script src="https://imsun.github.io/gitment/dist/gitment.browser.js"></script>
<script>
var gitment = new Gitment({
id: '<%= md5(page.path) %>',
id: '<%= md5(path) %>',
owner: '<%= get_config('comment.owner') %>',
repo: '<%= get_config('comment.repo') %>',
oauth: {

View File

@ -0,0 +1,4 @@
module.exports = (ctx, locals) => {
const { path } = ctx.page;
return Object.assign(locals, { path });
}

View File

@ -0,0 +1,3 @@
module.exports = (ctx, locals) => {
return locals;
}

View File

@ -0,0 +1,3 @@
module.exports = (ctx, locals) => {
return locals;
}

View File

@ -0,0 +1,3 @@
module.exports = (ctx, locals) => {
return locals;
}

View File

@ -1,3 +1,4 @@
<% post = post(); %>
<div class="card">
<% if (has_thumbnail(post)) { %>
<div class="card-image">
@ -71,7 +72,7 @@
</div>
<% } %>
<% if (!index && has_config('share.type')) { %>
<%- partial('share/' + get_config('share.type')) %>
<%- _partial('share/' + get_config('share.type')) %>
<% } %>
</div>
</div>
@ -85,7 +86,7 @@
<% for (let service of services) {
const type = get_config_from_obj(service, 'type');
if (type !== null) { %>
<%- partial('donate/' + type, { type, service }) %>
<%- _partial('donate/' + type, { type, service }) %>
<% }
} %>
</div>
@ -120,7 +121,7 @@
<div class="card">
<div class="card-content">
<h3 class="title is-5 has-text-weight-normal"><%= __('article.comments') %></h3>
<%- partial('comment/' + get_config('comment.type')) %>
<%- _partial('comment/' + get_config('comment.type')) %>
</div>
</div>
<% } %>

View File

@ -0,0 +1,8 @@
module.exports = (ctx, locals) => {
const { index, post } = locals;
return Object.assign(locals, {
index,
post: () => post,
post_id: post._id
});
}

View File

@ -3,17 +3,17 @@
<div class="level">
<div class="level-start has-text-centered-mobile">
<a class="footer-logo is-block has-mb-6" href="<%- url_for('/') %>">
<% if (has_config('logo.text') && get_config('logo.text')) { %>
<%= get_config('logo.text') %>
<% if (logo && logo.text) { %>
<%= logo.text %>
<% } else { %>
<img src="<%- url_for(get_config('logo')) %>" alt="<%= get_config('title') %>" height="28">
<img src="<%- url_for(logo) %>" alt="<%= title %>" height="28">
<% } %>
</a>
<p class="is-size-7">
&copy; <%= date(new Date(), 'YYYY') %> <%= get_config('author') || get_config('title') %>&nbsp;
&copy; <%= date(new Date(), 'YYYY') %> <%= author || title %>&nbsp;
Powered by <a href="https://hexo.io/" target="_blank">Hexo</a> & <a
href="https://github.com/ppoffice/hexo-theme-icarus" target="_blank">Icarus</a>
<% if (has_config('plugins.busuanzi') ? get_config('plugins.busuanzi') : false) { %>
<% if (busuanzi) { %>
<br>
<span id="busuanzi_container_site_uv">
<%- _p('plugin.visitor', '<span id="busuanzi_value_site_uv">0</span>') %>
@ -22,9 +22,8 @@
</p>
</div>
<div class="level-end">
<% if (has_config('footer.links')) { %>
<% if (Object.keys(links).length) { %>
<div class="field has-addons is-flex-center-mobile has-mt-5-mobile is-flex-wrap is-flex-middle">
<% let links = get_config('footer.links'); %>
<% for (let name in links) {
let link = links[name]; %>
<p class="control">

View File

@ -0,0 +1,10 @@
module.exports = (ctx, locals) => {
const { get_config } = ctx;
return Object.assign(locals, {
title: get_config('title'),
author: get_config('author'),
logo: get_config('logo'),
busuanzi: get_config('plugins.busuanzi', false),
links: get_config('footer.links', [])
});
}

View File

@ -36,7 +36,7 @@
<% if (has_config('plugins')) { %>
<% for (let plugin in get_config('plugins')) { %>
<%- partial('plugin/' + plugin, { head: true, plugin: get_config('plugins')[plugin] }) %>
<%- _partial('plugin/' + plugin, { head: true, plugin: get_config('plugins')[plugin] }) %>
<% } %>
<% } %>

View File

@ -2,25 +2,24 @@
<div class="container">
<div class="navbar-brand is-flex-center">
<a class="navbar-item navbar-logo" href="<%- url_for('/') %>">
<% if (has_config('logo.text') && get_config('logo.text')) { %>
<%= get_config('logo.text') %>
<% if (logo && logo.text) { %>
<%= logo.text %>
<% } else { %>
<img src="<%- url_for(get_config('logo')) %>" alt="<%= get_config('title') %>" height="28">
<img src="<%- url_for(logo) %>" alt="<%= title %>" height="28">
<% } %>
</a>
</div>
<div class="navbar-menu">
<% if (has_config('navbar.menu')) { %>
<% if (Object.keys(menus).length) { %>
<div class="navbar-start">
<% for (let i in get_config('navbar.menu')) { let menu = get_config('navbar.menu')[i]; %>
<a class="navbar-item<% if (typeof(page.path) !== 'undefined' && is_same_link(menu, page.path)) { %> is-active<% } %>"
<% for (let i in menus) { let menu = menus[i]; %>
<a class="navbar-item<% if (actives[i]) { %> is-active<% } %>"
href="<%- url_for(menu) %>"><%= i %></a>
<% } %>
</div>
<% } %>
<div class="navbar-end">
<% if (has_config('navbar.links')) { %>
<% let links = get_config('navbar.links'); %>
<% if (Object.keys(links).length) { %>
<% for (let name in links) {
let link = links[name]; %>
<a class="navbar-item" target="_blank" title="<%= name %>" href="<%= url_for(typeof(link) === 'string' ? link : link.url) %>">
@ -32,12 +31,12 @@
</a>
<% } %>
<% } %>
<% if (get_config('toc') === true && has_widget('toc') && (page.layout === 'page' || page.layout === 'post')) { %>
<% if (hasToc) { %>
<a class="navbar-item is-hidden-tablet catalogue" title="<%= _p('widget.catalogue', Infinity) %>" href="javascript:;">
<i class="fas fa-list-ul"></i>
</a>
<% } %>
<% if (has_config('search.type')) { %>
<% if (search) { %>
<a class="navbar-item search" title="<%= __('search.search') %>" href="javascript:;">
<i class="fas fa-search"></i>
</a>

View File

@ -0,0 +1,18 @@
module.exports = (ctx, locals) => {
const { get_config, has_config, has_widget, is_same_link, page } = ctx;
const menus = get_config('navbar.menu', {});
const actives = {};
Object.keys(menus).forEach(i => {
actives[i] = typeof page.path !== 'undefined' && is_same_link(menus[i], page.path)
});
const hasToc = get_config('toc') === true && has_widget('toc') && (page.layout === 'page' || page.layout === 'post');
return Object.assign(locals, {
hasToc,
menus,
actives,
title: get_config('title'),
logo: get_config('logo'),
links: get_config('navbar.links', []),
search: has_config('search.type')
});
}

View File

@ -19,7 +19,7 @@ var IcarusThemeSettings = {
<% if (has_config('plugins')) { %>
<% for (let plugin in get_config('plugins')) { %>
<%- partial('plugin/' + plugin, { head: false, plugin: get_config('plugins')[plugin] }) %>
<%- _partial('plugin/' + plugin, { head: false, plugin: get_config('plugins')[plugin] }) %>
<% } %>
<% } %>

View File

@ -22,12 +22,12 @@
} %>
<div class="column <%= side_column_class() %> <%= visibility_class() %> <%= order_class() %> column-<%= position %> <%= sticky_class(position) %>">
<% get_widgets(position).forEach(widget => {%>
<%- partial('widget/' + widget.type, { widget, post: page }) %>
<%- _partial('widget/' + widget.type, { widget }) %>
<% }) %>
<% if (position === 'left') { %>
<div class="column-right-shadow is-hidden-widescreen <%= sticky_class('right') %>">
<% get_widgets('right').forEach(widget => {%>
<%- partial('widget/' + widget.type, { widget, post: page }) %>
<%- _partial('widget/' + widget.type, { widget }) %>
<% }) %>
</div>
<% } %>

View File

@ -0,0 +1,3 @@
module.exports = (ctx, locals) => {
return locals;
}

View File

@ -0,0 +1,3 @@
module.exports = (ctx, locals) => {
return locals;
}

View File

@ -0,0 +1,3 @@
module.exports = (ctx, locals) => {
return locals;
}

View File

@ -0,0 +1,3 @@
module.exports = (ctx, locals) => {
return locals;
}

View File

@ -1,6 +1,6 @@
<% page.posts.each(function(post){ %>
<%- partial('common/article', { post, index: true }) %>
<%- _partial('common/article', { post, index: true }) %>
<% }); %>
<% if (page.total > 1) { %>
<%- partial('common/paginator') %>
<%- _partial('common/paginator') %>
<% } %>

View File

@ -1,10 +1,10 @@
<!DOCTYPE html>
<html <%- has_config('language') ? ' lang="' + get_config('language').substring(0, 2) + '"' : '' %>>
<head>
<%- partial('common/head') %>
<%- _partial('common/head') %>
</head>
<body class="is-<%= column_count() %>-column">
<%- partial('common/navbar', { page }) %>
<%- _partial('common/navbar') %>
<% function main_column_class() {
switch (column_count()) {
case 1:
@ -20,16 +20,16 @@
<div class="container">
<div class="columns">
<div class="column <%= main_column_class() %> has-order-2 column-main"><%- body %></div>
<%- partial('common/widget', { position: 'left' }) %>
<%- partial('common/widget', { position: 'right' }) %>
<%- _partial('common/widget', { position: 'left' }) %>
<%- _partial('common/widget', { position: 'right' }) %>
</div>
</div>
</section>
<%- partial('common/footer') %>
<%- partial('common/scripts') %>
<%- _partial('common/footer') %>
<%- _partial('common/scripts') %>
<% if (has_config('search.type')) { %>
<%- partial('search/' + get_config('search.type')) %>
<%- _partial('search/' + get_config('search.type')) %>
<% } %>
</body>
</html>

View File

@ -1 +1 @@
<%- partial('common/article', {post: page, index: false}) %>
<%- _partial('common/article', {post: page, index: false}) %>

View File

@ -1,7 +1,5 @@
<% if (plugin !== false) { %>
<% if (head) { %>
<style>body>.footer,body>.navbar,body>.section{opacity:0}</style>
<% } else { %>
<%- _js('js/animation') %>
<% } %>
<% if (head) { %>
<style>body>.footer,body>.navbar,body>.section{opacity:0}</style>
<% } else { %>
<%- _js('js/animation') %>
<% } %>

View File

@ -0,0 +1,7 @@
module.exports = (ctx, locals) => {
const { plugin } = locals;
if (!plugin) {
return null;
}
return locals;
}

View File

@ -1,4 +1,3 @@
<% if (plugin !== false) { %>
<% if (head) { %>
<%- _css('css/back-to-top') %>
<% } else { %>
@ -6,5 +5,4 @@
<i class="fas fa-chevron-up"></i>
</a>
<%- _js('js/back-to-top', true) %>
<% } %>
<% } %>

View File

@ -0,0 +1,7 @@
module.exports = (ctx, locals) => {
const { plugin } = locals;
if (!plugin) {
return null;
}
return locals;
}

View File

@ -1,4 +1,3 @@
<% if (head && get_config_from_obj(plugin, 'tracking_id')) { %>
<script>
var _hmt = _hmt || [];
(function() {
@ -7,5 +6,4 @@ var _hmt = _hmt || [];
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
<% } %>
</script>

View File

@ -0,0 +1,7 @@
module.exports = (ctx, locals) => {
const { head, plugin } = locals;
if (!head || !plugin.tracking_id) {
return null;
}
return locals;
}

View File

@ -1,5 +1 @@
<% if (plugin !== false) { %>
<% if (head) { %>
<script async="" src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<% } %>
<% } %>
<script async="" src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

View File

@ -0,0 +1,7 @@
module.exports = (ctx, locals) => {
const { head, plugin } = locals;
if (!head || !plugin) {
return null;
}
return locals;
}

View File

@ -1,10 +1,8 @@
<% if (plugin !== false) { %>
<% if (head) { %>
<%- _css(cdn('lightgallery', '1.6.8', 'dist/css/lightgallery.min.css')) %>
<%- _css(cdn('justifiedGallery', '3.7.0', 'dist/css/justifiedGallery.min.css')) %>
<% } else { %>
<%- _js(cdn('lightgallery', '1.6.8', 'dist/js/lightgallery.min.js'), true) %>
<%- _js(cdn('justifiedGallery', '3.7.0', 'dist/js/jquery.justifiedGallery.min.js'), true) %>
<%- _js('js/gallery', true) %>
<% } %>
<% if (head) { %>
<%- _css(cdn('lightgallery', '1.6.8', 'dist/css/lightgallery.min.css')) %>
<%- _css(cdn('justifiedGallery', '3.7.0', 'dist/css/justifiedGallery.min.css')) %>
<% } else { %>
<%- _js(cdn('lightgallery', '1.6.8', 'dist/js/lightgallery.min.js'), true) %>
<%- _js(cdn('justifiedGallery', '3.7.0', 'dist/js/jquery.justifiedGallery.min.js'), true) %>
<%- _js('js/gallery', true) %>
<% } %>

View File

@ -0,0 +1,6 @@
module.exports = (ctx, locals) => {
if (!locals.plugin) {
return null;
}
return locals;
}

View File

@ -1,4 +1,3 @@
<% if (head && get_config_from_obj(plugin, 'tracking_id')) { %>
<script async src="https://www.googletagmanager.com/gtag/js?id=<%= get_config_from_obj(plugin, 'tracking_id') %>"></script>
<script>
window.dataLayer = window.dataLayer || [];
@ -7,4 +6,3 @@
gtag('config', '<%= get_config_from_obj(plugin, 'tracking_id') %>');
</script>
<% } %>

View File

@ -0,0 +1,7 @@
module.exports = (ctx, locals) => {
const { head, plugin } = locals;
if (!head || !plugin.tracking_id) {
return null;
}
return locals;
}

View File

@ -1,4 +1,3 @@
<% if (head && get_config_from_obj(plugin, 'site_id')) { %>
<script>
(function(h,o,t,j,a,r){
h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
@ -8,5 +7,4 @@
r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
a.appendChild(r);
})(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');
</script>
<% } %>
</script>

View File

@ -0,0 +1,7 @@
module.exports = (ctx, locals) => {
const { head, plugin } = locals;
if (!head || !plugin.site_id) {
return null;
}
return locals;
}

View File

@ -1,4 +1,3 @@
<% if (!head && plugin !== false) { %>
<%- _js(cdn('mathjax', '2.7.5', 'unpacked/MathJax.js?config=TeX-MML-AM_CHTML'), true) %>
<script>
document.addEventListener('DOMContentLoaded', function () {
@ -20,5 +19,4 @@ document.addEventListener('DOMContentLoaded', function () {
}
});
});
</script>
<% } %>
</script>

View File

@ -0,0 +1,7 @@
module.exports = (ctx, locals) => {
const { head, plugin } = locals;
if (head || !plugin) {
return null;
}
return locals;
}

View File

@ -1,4 +1,3 @@
<% if (plugin !== false) { %>
<% if (head) { %>
<%- _css(cdn('outdatedbrowser', '1.1.5', 'outdatedbrowser/outdatedbrowser.min.css')) %>
<% } else { %>
@ -18,5 +17,4 @@
});
});
</script>
<% } %>
<% } %>

View File

@ -0,0 +1,6 @@
module.exports = (ctx, locals) => {
if (!locals.plugin) {
return null;
}
return locals;
}

View File

@ -1,4 +1,2 @@
<% if (head && plugin !== false) { %>
<%- _css('css/progressbar') %>
<%- _js(cdn('pace-js', '1.0.2', 'pace.min.js')) %>
<% } %>
<%- _js(cdn('pace-js', '1.0.2', 'pace.min.js')) %>

View File

@ -0,0 +1,7 @@
module.exports = (ctx, locals) => {
const { head, plugin } = locals;
if (!head || !plugin) {
return null;
}
return locals;
}

View File

@ -1 +1 @@
<%- partial('common/article', {post: page, index: false}) %>
<%- _partial('common/article', {post: page, index: false}) %>

View File

@ -0,0 +1,3 @@
module.exports = (ctx, locals) => {
return locals;
}

View File

@ -0,0 +1,3 @@
module.exports = (ctx, locals) => {
return locals;
}

View File

@ -0,0 +1,3 @@
module.exports = (ctx, locals) => {
return locals;
}

View File

@ -0,0 +1,3 @@
module.exports = (ctx, locals) => {
return locals;
}

View File

@ -0,0 +1,3 @@
module.exports = (ctx, locals) => {
return locals;
}

View File

@ -0,0 +1,3 @@
module.exports = (ctx, locals) => {
return locals;
}

View File

@ -0,0 +1,9 @@
module.exports = (ctx, locals) => {
const { get_config } = ctx;
return Object.assign(locals, {
// just for diff detection
_providers: {
_cdn: get_config('providers.cdn')
}
});
}

View File

@ -0,0 +1,3 @@
module.exports = (ctx, locals) => {
return locals;
}

View File

@ -8,4 +8,4 @@
</nav>
</div>
</div>
<%- partial('index', { page }) %>
<%- _partial('index', { page }) %>

View File

@ -0,0 +1,3 @@
module.exports = (ctx, locals) => {
return locals;
}

View File

@ -1 +1 @@
<%- partial('categories') %>
<%- _partial('categories') %>

View File

@ -0,0 +1,3 @@
module.exports = (ctx, locals) => {
return locals;
}

View File

@ -1,5 +1,3 @@
<% const links = get_config_from_obj(widget, 'links'); %>
<% if (links !== null) { %>
<div class="card widget">
<div class="card-content">
<div class="menu">
@ -23,4 +21,3 @@
</div>
</div>
</div>
<% } %>

View File

@ -0,0 +1,8 @@
module.exports = (ctx, locals) => {
const { get_config_from_obj } = ctx;
const links = get_config_from_obj(locals.widget, 'links');
if (Object.keys(links).length == 0) {
return null;
}
return Object.assign(locals, { links });
}

View File

@ -0,0 +1,3 @@
module.exports = (ctx, locals) => {
return locals;
}

View File

@ -1,15 +1,14 @@
<% if (site.posts.length) { %>
<div class="card widget">
<div class="card-content">
<h3 class="menu-label">
<%= __('widget.recents') %>
</h3>
<% site.posts.sort('date', -1).limit(5).each(post => { %>
<% posts.forEach(post => { %>
<article class="media">
<% if (!has_config('article.thumbnail') || get_config('article.thumbnail') !== false) { %>
<a href="<%- url_for((post.link?post.link:post.path)) %>" class="media-left">
<% if (thumbnail) { %>
<a href="<%- url_for(post.link ? post.link : post.path) %>" class="media-left">
<p class="image is-64x64">
<img class="thumbnail" src="<%= get_thumbnail(post) %>" alt="<%= post.title %>">
<img class="thumbnail" src="<%= post.thumbnail %>" alt="<%= post.title %>">
</p>
</a>
<% } %>
@ -18,7 +17,7 @@
<div><time class="has-text-grey is-size-7 is-uppercase" datetime="<%= date_xml(post.date) %>"><%= date(post.date) %></time></div>
<a href="<%- url_for((post.link?post.link:post.path)) %>" class="title has-link-black-ter is-size-6 has-text-weight-normal"><%= post.title %></a>
<p class="is-size-7 is-uppercase">
<%- list_categories(post.categories, {
<%- list_categories(post.categories(), {
show_count: false,
class: 'has-link-grey ',
depth:2,
@ -30,5 +29,4 @@
</article>
<% }) %>
</div>
</div>
<% } %>
</div>

View File

@ -0,0 +1,18 @@
module.exports = (ctx, locals) => {
const { has_config, get_config, get_thumbnail } = ctx;
const { posts } = ctx.site;
if (!posts.length) {
return null;
}
const thumbnail = !has_config('article.thumbnail') || get_config('article.thumbnail') !== false;
const _posts = posts.sort('date', -1).limit(5).map(post => ({
link: post.link,
path: post.path,
title: post.title,
date: post.date,
thumbnail: thumbnail ? get_thumbnail(post) : null,
// fix circular JSON serialization issue
categories: () => post.categories
}));
return Object.assign(locals, { thumbnail, posts: _posts });
}

View File

@ -1 +1 @@
<%- partial('tags') %>
<%- _partial('tags') %>

View File

@ -1,4 +1,3 @@
<% if (site.tags.length) { %>
<div class="card widget">
<div class="card-content">
<h3 class="menu-label">
@ -6,5 +5,4 @@
</h3>
<%- tagcloud() %>
</div>
</div>
<% } %>
</div>

View File

@ -0,0 +1,6 @@
module.exports = (ctx, locals) => {
if (!ctx.site.tags.length) {
return null;
}
return locals;
}

View File

@ -1,5 +1,4 @@
<% if (get_config('toc') === true && (post.layout === 'page' || post.layout === 'post')) {
function buildToc(toc) {
<% function buildToc(toc) {
let result = '';
if (toc.hasOwnProperty('id') && toc.hasOwnProperty('index') && toc.hasOwnProperty('text')) {
result += `<li>
@ -24,16 +23,14 @@ function buildToc(toc) {
result += '</li>';
}
return result;
}
%>
} %>
<div class="card widget" id="toc">
<div class="card-content">
<div class="menu">
<h3 class="menu-label">
<%= _p('widget.catalogue', Infinity) %>
</h3>
<%- buildToc(_toc(post.content)) %>
<%- buildToc(_toc(content)) %>
</div>
</div>
</div>
<% } %>
</div>

View File

@ -0,0 +1,8 @@
module.exports = (ctx, locals) => {
const { layout, content } = ctx.page;
const { get_config } = ctx;
if (get_config('toc') !== true || (layout !== 'page' && layout !== 'post')) {
return null;
}
return Object.assign(locals, { content });
}