refactor(script): remove unused hexo helpers

This commit is contained in:
ppoffice 2019-12-23 17:35:21 -05:00
parent 8e88905c48
commit 4234234c6c
11 changed files with 102 additions and 741 deletions

View File

@ -1,40 +0,0 @@
/**
* Helper functions for controlling layout.
*
* @example
* <%- get_widgets(position) %>
* <%- has_column() %>
* <%- column_count() %>
*/
module.exports = function (hexo) {
hexo.extend.helper.register('has_widget', function (type) {
const hasWidgets = hexo.extend.helper.get('has_config').bind(this)('widgets');
if (!hasWidgets) {
return false;
}
const widgets = hexo.extend.helper.get('get_config').bind(this)('widgets');
return widgets.some(widget => widget.hasOwnProperty('type') && widget.type === type);
});
hexo.extend.helper.register('get_widgets', function (position) {
const hasWidgets = hexo.extend.helper.get('has_config').bind(this)('widgets');
if (!hasWidgets) {
return [];
}
const widgets = hexo.extend.helper.get('get_config').bind(this)('widgets');
return widgets.filter(widget => widget.hasOwnProperty('position') && widget.position === position);
});
hexo.extend.helper.register('has_column', function (position) {
const getWidgets = hexo.extend.helper.get('get_widgets').bind(this);
return getWidgets(position).length > 0;
});
hexo.extend.helper.register('column_count', function () {
let columns = 1;
const hasColumn = hexo.extend.helper.get('has_column').bind(this);
columns += hasColumn('left') ? 1 : 0;
columns += hasColumn('right') ? 1 : 0;
return columns;
});
}

View File

@ -1,194 +0,0 @@
/**
* Helper functions that override Hexo built-in helpers.
*
* @example
* <%- _list_archives() %>
* <%- _list_categories() %>
* <%- _list_tags() %>
* <%- _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 { LRUMap } = require('../utils/lru');
const __archives = [];
const __categories = [];
const __tags = [];
const __fragmentCache = new LRUMap(20);
module.exports = function (hexo) {
hexo.extend.helper.register('_list_archives', function () {
if (__archives.length) {
return __archives;
}
const $ = cheerio.load(this.list_archives(), { decodeEntities: false });
$('.archive-list-item').each(function () {
__archives.push({
url: $(this).find('.archive-list-link').attr('href'),
name: $(this).find('.archive-list-link').text(),
count: $(this).find('.archive-list-count').text()
});
});
return __archives;
});
hexo.extend.helper.register('_list_categories', function () {
if (__categories.length) {
return __categories;
}
const $ = cheerio.load(this.list_categories({ depth: 2 }), { decodeEntities: false });
function traverse(root) {
const categories = [];
root.find('> .category-list-item').each(function () {
const category = {
url: $(this).find('> .category-list-link').attr('href'),
name: $(this).find('> .category-list-link').text(),
count: $(this).find('> .category-list-count').text()
};
if ($(this).find('> .category-list-child').length) {
category['children'] = traverse($(this).find('> .category-list-child'));
}
categories.push(category);
});
return categories;
}
__categories.push(...traverse($('.category-list')));
return __categories;
});
hexo.extend.helper.register('_list_tags', function () {
if (__tags.length) {
return __tags;
}
const $ = cheerio.load(this.list_tags(), { decodeEntities: false });
$('.tag-list-item').each(function () {
__tags.push({
url: $(this).find('.tag-list-link').attr('href'),
name: $(this).find('.tag-list-link').text(),
count: $(this).find('.tag-list-count').text()
});
});
return __tags;
});
/**
* Export a tree of headings of an article
* {
* "1": {
* "id": "How-to-enable-table-of-content-for-a-post",
* "index": "1"
* },
* "2": {
* "1": {
* "1": {
* "id": "Third-level-title",
* "index": "2.1.1"
* },
* "id": "Second-level-title",
* "index": "2.1"
* },
* "2": {
* "id": "Another-second-level-title",
* "index": "2.2"
* },
* "id": "First-level-title",
* "index": "2"
* }
* }
*/
hexo.extend.helper.register('_toc', (content) => {
const $ = cheerio.load(content, { decodeEntities: false });
const toc = {};
const levels = [0, 0, 0];
// Get top 3 headings that are present in the content
const tags = [1, 2, 3, 4, 5, 6].map(i => 'h' + i).filter(h => $(h).length > 0).slice(0, 3);
if (tags.length === 0) {
return toc;
}
$(tags.join(',')).each(function () {
const level = tags.indexOf(this.name);
const id = $(this).attr('id');
const text = $(this).text();
for (let i = 0; i < levels.length; i++) {
if (i > level) {
levels[i] = 0;
} else if (i < level) {
if (levels[i] === 0) {
// if headings start with a lower level heading, set the former heading index to 1
// e.g. h3, h2, h1, h2, h3 => 1.1.1, 1.2, 2, 2.1, 2.1.1
levels[i] = 1;
}
} else {
levels[i] += 1;
}
}
let node = toc;
for (let i of levels.slice(0, level + 1)) {
if (!node.hasOwnProperty(i)) {
node[i] = {};
}
node = node[i];
}
node.id = id;
node.text = text;
node.index = levels.slice(0, level + 1).join('.');
});
return toc;
});
hexo.extend.helper.register('_js', function (url, defer = false, async = false) {
const urlFor = hexo.extend.helper.get('url_for').bind(this);
if (!url.endsWith('.js') && !url.includes('?')) {
url += '.js';
}
return `<script src="${urlFor(url)}"${async ? ' async' : ''}${defer ? ' defer' : ''}></script>`;
});
hexo.extend.helper.register('_css', function (url) {
const urlFor = hexo.extend.helper.get('url_for').bind(this);
if (!url.endsWith('.css') && !url.includes('?')) {
url += '.css';
}
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('-');
if (!__fragmentCache.has(cacheId)) {
__fragmentCache.set(cacheId, partial(name, _locals, { cache: false, only: options.only || false }));
}
return __fragmentCache.get(cacheId);
});
}

View File

@ -2,50 +2,10 @@
* Helper functions for page/post.
*
* @example
* <%- is_categories(page) %>
* <%- is_tags(page) %>
* <%- page_title(page) %>
* <%- has_thumbnail(post) %>
* <%- get_thumbnail(post) %>
* <%- get_og_image(post) %>
*/
module.exports = function (hexo) {
hexo.extend.helper.register('is_categories', function (page = null) {
return (page === null ? this.page : page).__categories;
});
hexo.extend.helper.register('is_tags', function (page = null) {
return (page === null ? this.page : page).__tags;
});
/**
* Generate html head title based on page type
*/
hexo.extend.helper.register('page_title', function (page = null) {
page = page === null ? this.page : page;
let title = page.title;
if (this.is_archive()) {
title = this._p('common.archive', Infinity);
if (this.is_month()) {
title += ': ' + page.year + '/' + page.month;
} else if (this.is_year()) {
title += ': ' + page.year;
}
} else if (this.is_category()) {
title = this._p('common.category', 1) + ': ' + page.category;
} else if (this.is_tag()) {
title = this._p('common.tag', 1) + ': ' + page.tag;
} else if (this.is_categories()) {
title = this._p('common.category', Infinity);
} else if (this.is_tags()) {
title = this._p('common.tag', Infinity);
}
const siteTitle = hexo.extend.helper.get('get_config').bind(this)('title', '', true);
return [title, siteTitle].filter(str => typeof (str) !== 'undefined' && str.trim() !== '').join(' - ');
});
hexo.extend.helper.register('has_thumbnail', function (post) {
const getConfig = hexo.extend.helper.get('get_config').bind(this);
const allowThumbnail = getConfig('article.thumbnail', true);
@ -59,29 +19,4 @@ module.exports = function (hexo) {
const hasThumbnail = hexo.extend.helper.get('has_thumbnail').bind(this)(post);
return this.url_for(hasThumbnail ? post.thumbnail : 'images/thumbnail.svg');
});
hexo.extend.helper.register('has_og_image', function (post) {
return post.hasOwnProperty('og_image');
});
hexo.extend.helper.register('get_og_image', function (post) {
const getConfig = hexo.extend.helper.get('get_config').bind(this);
const hasConfig = hexo.extend.helper.get('has_config').bind(this);
const hasOGImage = hexo.extend.helper.get('has_og_image').bind(this)(post);
const hasThumbnail = hexo.extend.helper.get('has_thumbnail').bind(this)(post);
const getThumbnail = hexo.extend.helper.get('get_thumbnail').bind(this);
let og_image
if (hasOGImage)
og_image = post.og_image
else if (hasThumbnail)
og_image = getThumbnail(post);
else
og_image = getConfig('article.og_image', '/images/og_image.png');
return this.url_for(og_image);
});
}

View File

@ -1,106 +0,0 @@
/**
* Helper functions related the site properties.
*
* @example
* <%- is_same_link(url_a, url_b) %>
* <%- get_domain(url) %>
* <%- post_count() %>
* <%- category_count() %>
* <%- tag_count() %>
* <%- duration() %>
* <%- word_count(content) %>
* <%- md5(data) %>
* <%- meta() %>
* <%- hexo_version() %>
*/
const URL = require('url').URL;
const moment = require('moment');
const crypto = require('crypto');
module.exports = function (hexo) {
hexo.extend.helper.register('is_same_link', function (a, b) {
function santize(url) {
let paths = url.replace(/(^\w+:|^)\/\//, '').split('#')[0].split('/').filter(p => p.trim() !== '');
if (paths.length > 0 && paths[paths.length - 1].trim() === 'index.html') {
paths = paths.slice(0, paths.length - 1)
}
return paths.join('/');
}
return santize(this.url_for(a)) == santize(this.url_for(b));
});
hexo.extend.helper.register('get_domain', function (link) {
const url = new URL(link);
return url.hostname;
});
hexo.extend.helper.register('post_count', function () {
return this.site.posts.length;
});
hexo.extend.helper.register('category_count', function () {
return this.site.categories.filter(category => category.length).length;
});
hexo.extend.helper.register('tag_count', function () {
return this.site.tags.filter(tag => tag.length).length;
});
/**
* Export moment.duration
*/
hexo.extend.helper.register('duration', function () {
return moment.duration.apply(moment, arguments);
});
/**
* Get the word count of a paragraph.
*/
hexo.extend.helper.register('word_count', function (content) {
content = content.replace(/<\/?[a-z][^>]*>/gi, '');
content = content.trim();
return content ? (content.match(/[\u00ff-\uffff]|[a-zA-Z]+/g) || []).length : 0;
});
hexo.extend.helper.register('md5', function (data) {
return crypto.createHash('md5').update(data).digest("hex");
});
hexo.extend.helper.register('meta', function () {
function trim(str) {
return str.trim().replace(/^"(.*)"$/, '$1').replace(/^'(.*)'$/, '$1');
}
function split(str, sep) {
const result = [];
let matched = null;
while (matched = sep.exec(str)) {
result.push(matched[0]);
}
return result;
}
const getConfig = hexo.extend.helper.get('get_config').bind(this);
const metas = getConfig('meta', []);
const metaDOMArray = metas.map(function (meta) {
const entities = split(meta, /(?:[^\\;]+|\\.)+/g);
const entityArray = entities.map(function (entity) {
const keyValue = split(entity, /(?:[^\\=]+|\\.)+/g);
if (keyValue.length < 2) {
return null;
}
const key = trim(keyValue[0]);
const value = trim(keyValue[1]);
return key + '="' + value + '"';
}).filter(function (entity) {
return entity;
});
return '<meta ' + entityArray.join(' ') + ' />';
});
return metaDOMArray.join('\n');
});
hexo.extend.helper.register('hexo_version', function (data) {
return hexo.version;
});
}

View File

@ -1,305 +0,0 @@
/**
* A doubly linked list-based Least Recently Used (LRU) cache. Will keep most
* recently used items while discarding least recently used items when its limit
* is reached.
*
* Licensed under MIT. Copyright (c) 2010 Rasmus Andersson <http://hunch.se/>
* See README.md for details.
*
* Illustration of the design:
*
* entry entry entry entry
* ______ ______ ______ ______
* | head |.newer => | |.newer => | |.newer => | tail |
* | A | | B | | C | | D |
* |______| <= older.|______| <= older.|______| <= older.|______|
*
* removed <-- <-- <-- <-- <-- <-- <-- <-- <-- <-- <-- added
*/
(function (g, f) {
const e = typeof exports == 'object' ? exports : typeof g == 'object' ? g : {};
f(e);
if (typeof define == 'function' && define.amd) { define('lru', e); }
})(this, function (exports) {
const NEWER = Symbol('newer');
const OLDER = Symbol('older');
function LRUMap(limit, entries) {
if (typeof limit !== 'number') {
// called as (entries)
entries = limit;
limit = 0;
}
this.size = 0;
this.limit = limit;
this.oldest = this.newest = undefined;
this._keymap = new Map();
if (entries) {
this.assign(entries);
if (limit < 1) {
this.limit = this.size;
}
}
}
exports.LRUMap = LRUMap;
function Entry(key, value) {
this.key = key;
this.value = value;
this[NEWER] = undefined;
this[OLDER] = undefined;
}
LRUMap.prototype._markEntryAsUsed = function (entry) {
if (entry === this.newest) {
// Already the most recenlty used entry, so no need to update the list
return;
}
// HEAD--------------TAIL
// <.older .newer>
// <--- add direction --
// A B C <D> E
if (entry[NEWER]) {
if (entry === this.oldest) {
this.oldest = entry[NEWER];
}
entry[NEWER][OLDER] = entry[OLDER]; // C <-- E.
}
if (entry[OLDER]) {
entry[OLDER][NEWER] = entry[NEWER]; // C. --> E
}
entry[NEWER] = undefined; // D --x
entry[OLDER] = this.newest; // D. --> E
if (this.newest) {
this.newest[NEWER] = entry; // E. <-- D
}
this.newest = entry;
};
LRUMap.prototype.assign = function (entries) {
let entry, limit = this.limit || Number.MAX_VALUE;
this._keymap.clear();
let it = entries[Symbol.iterator]();
for (let itv = it.next(); !itv.done; itv = it.next()) {
let e = new Entry(itv.value[0], itv.value[1]);
this._keymap.set(e.key, e);
if (!entry) {
this.oldest = e;
} else {
entry[NEWER] = e;
e[OLDER] = entry;
}
entry = e;
if (limit-- == 0) {
throw new Error('overflow');
}
}
this.newest = entry;
this.size = this._keymap.size;
};
LRUMap.prototype.get = function (key) {
// First, find our cache entry
var entry = this._keymap.get(key);
if (!entry) return; // Not cached. Sorry.
// As <key> was found in the cache, register it as being requested recently
this._markEntryAsUsed(entry);
return entry.value;
};
LRUMap.prototype.set = function (key, value) {
var entry = this._keymap.get(key);
if (entry) {
// update existing
entry.value = value;
this._markEntryAsUsed(entry);
return this;
}
// new entry
this._keymap.set(key, (entry = new Entry(key, value)));
if (this.newest) {
// link previous tail to the new tail (entry)
this.newest[NEWER] = entry;
entry[OLDER] = this.newest;
} else {
// we're first in -- yay
this.oldest = entry;
}
// add new entry to the end of the linked list -- it's now the freshest entry.
this.newest = entry;
++this.size;
if (this.size > this.limit) {
// we hit the limit -- remove the head
this.shift();
}
return this;
};
LRUMap.prototype.shift = function () {
// todo: handle special case when limit == 1
var entry = this.oldest;
if (entry) {
if (this.oldest[NEWER]) {
// advance the list
this.oldest = this.oldest[NEWER];
this.oldest[OLDER] = undefined;
} else {
// the cache is exhausted
this.oldest = undefined;
this.newest = undefined;
}
// Remove last strong reference to <entry> and remove links from the purged
// entry being returned:
entry[NEWER] = entry[OLDER] = undefined;
this._keymap.delete(entry.key);
--this.size;
return [entry.key, entry.value];
}
};
// ----------------------------------------------------------------------------
// Following code is optional and can be removed without breaking the core
// functionality.
LRUMap.prototype.find = function (key) {
let e = this._keymap.get(key);
return e ? e.value : undefined;
};
LRUMap.prototype.has = function (key) {
return this._keymap.has(key);
};
LRUMap.prototype['delete'] = function (key) {
var entry = this._keymap.get(key);
if (!entry) return;
this._keymap.delete(entry.key);
if (entry[NEWER] && entry[OLDER]) {
// relink the older entry with the newer entry
entry[OLDER][NEWER] = entry[NEWER];
entry[NEWER][OLDER] = entry[OLDER];
} else if (entry[NEWER]) {
// remove the link to us
entry[NEWER][OLDER] = undefined;
// link the newer entry to head
this.oldest = entry[NEWER];
} else if (entry[OLDER]) {
// remove the link to us
entry[OLDER][NEWER] = undefined;
// link the newer entry to head
this.newest = entry[OLDER];
} else {// if(entry[OLDER] === undefined && entry.newer === undefined) {
this.oldest = this.newest = undefined;
}
this.size--;
return entry.value;
};
LRUMap.prototype.clear = function () {
// Not clearing links should be safe, as we don't expose live links to user
this.oldest = this.newest = undefined;
this.size = 0;
this._keymap.clear();
};
function EntryIterator(oldestEntry) { this.entry = oldestEntry; }
EntryIterator.prototype[Symbol.iterator] = function () { return this; }
EntryIterator.prototype.next = function () {
let ent = this.entry;
if (ent) {
this.entry = ent[NEWER];
return { done: false, value: [ent.key, ent.value] };
} else {
return { done: true, value: undefined };
}
};
function KeyIterator(oldestEntry) { this.entry = oldestEntry; }
KeyIterator.prototype[Symbol.iterator] = function () { return this; }
KeyIterator.prototype.next = function () {
let ent = this.entry;
if (ent) {
this.entry = ent[NEWER];
return { done: false, value: ent.key };
} else {
return { done: true, value: undefined };
}
};
function ValueIterator(oldestEntry) { this.entry = oldestEntry; }
ValueIterator.prototype[Symbol.iterator] = function () { return this; }
ValueIterator.prototype.next = function () {
let ent = this.entry;
if (ent) {
this.entry = ent[NEWER];
return { done: false, value: ent.value };
} else {
return { done: true, value: undefined };
}
};
LRUMap.prototype.keys = function () {
return new KeyIterator(this.oldest);
};
LRUMap.prototype.values = function () {
return new ValueIterator(this.oldest);
};
LRUMap.prototype.entries = function () {
return this;
};
LRUMap.prototype[Symbol.iterator] = function () {
return new EntryIterator(this.oldest);
};
LRUMap.prototype.forEach = function (fun, thisObj) {
if (typeof thisObj !== 'object') {
thisObj = this;
}
let entry = this.oldest;
while (entry) {
fun.call(thisObj, entry.value, entry.key, this);
entry = entry[NEWER];
}
};
/** Returns a JSON (array) representation */
LRUMap.prototype.toJSON = function () {
var s = new Array(this.size), i = 0, entry = this.oldest;
while (entry) {
s[i++] = { key: entry.key, value: entry.value };
entry = entry[NEWER];
}
return s;
};
/** Returns a String representation */
LRUMap.prototype.toString = function () {
var s = '', entry = this.oldest;
while (entry) {
s += String(entry.key) + ':' + entry.value;
entry = entry[NEWER];
if (entry) {
s += ' < ';
}
}
return s;
};
});

View File

@ -17,10 +17,10 @@ module.exports = class extends Component {
function renderArticleList(posts, year, month = null) {
const time = moment([page.year, page.month ? page.month - 1 : null].filter(i => i !== null));
return <div class="card widget">
<div class="card-content">
<h3 class="tag is-link">{month === null ? year : time.locale(language).format('MMMM YYYY')}</h3>
<div class="timeline">
return <div className="card widget">
<div className="card-content">
<h3 className="tag is-link">{month === null ? year : time.locale(language).format('MMMM YYYY')}</h3>
<div className="timeline">
{posts.map(post => {
const categories = [];
post.categories.forEach((category, i) => {
@ -29,21 +29,21 @@ module.exports = class extends Component {
categories.push('/');
}
});
return <article class="media">
{has_thumbnail(post) ? <a href={url_for((post.link || post.path))} class="media-left">
<p class="image is-64x64">
<img class="thumbnail" src={get_thumbnail(post)} alt={post.title || get_thumbnail(post)} />
return <article className="media">
{has_thumbnail(post) ? <a href={url_for((post.link || post.path))} className="media-left">
<p className="image is-64x64">
<img className="thumbnail" src={get_thumbnail(post)} alt={post.title || get_thumbnail(post)} />
</p>
</a> : null}
<div class="media-content">
<div class="content">
<time class="has-text-grey is-size-7 is-block is-uppercase"
<div className="media-content">
<div className="content">
<time className="has-text-grey is-size-7 is-block is-uppercase"
datetime={date_xml(post.date)}>{date(post.date)}</time>
<a class="title has-link-black-ter is-size-6 has-text-weight-normal"
<a className="title has-link-black-ter is-size-6 has-text-weight-normal"
href={url_for((post.link || post.path))} >{post.title}</a>
<div class="level article-meta is-mobile">
<div class="level-left">
{categories.length ? <div class="level-item is-size-7 is-uppercase">
<div className="level article-meta is-mobile">
<div className="level-left">
{categories.length ? <div className="level-item is-size-7 is-uppercase">
{categories}
</div> : null}
</div>

View File

@ -11,15 +11,15 @@ module.exports = class extends Component {
const { url_for, _p } = helper;
return <Fragment>
<div class="card">
<div class="card-content">
<nav class="breadcrumb" aria-label="breadcrumbs">
<div className="card">
<div className="card-content">
<nav className="breadcrumb" aria-label="breadcrumbs">
<ul>
<li><a href={url_for('/categories')}>{_p('common.category', Infinity)}</a></li>
{page.parents.map(category => {
return <li><a href={url_for(category.path)}>{category.name}</a></li>
})}
<li class="is-active"><a href="#" aria-current="page">{page.category}</a></li>
<li className="is-active"><a href="#" aria-current="page">{page.category}</a></li>
</ul>
</nav>
</div>

View File

@ -5,6 +5,78 @@ const MetaTags = require('../misc/meta');
const OpenGraph = require('../misc/open_graph');
const Plugins = require('./plugins');
function isArchivePage(page) {
return !!page.archive;
}
function isCategoriesPage(page) {
return !!page.__categories;
}
function isTagsPage(page) {
return !!page.__tags;
}
function isMonthPage(page, year, month) {
if (!isArchivePage(page)) {
return false;
}
if (year) {
if (month) {
return page.year === year && page.month === month;
}
return page.month === year;
}
return page.year && page.month;
}
function isYearPage(page, year) {
if (!isArchivePage(page)) {
return false;
}
if (year) {
return page.year === year;
}
return !!page.year;
}
function isCategoryPage(page, category) {
if (category) {
return page.category === category;
}
return !!page.category;
}
function isTagPage(page, tag) {
if (tag) {
return page.tag === tag;
}
return !!page.tag;
}
function getPageTitle(page, siteTitle, _p) {
let title = page.title;
if (isArchivePage(page)) {
title = _p('common.archive', Infinity);
if (isMonthPage()) {
title += ': ' + page.year + '/' + page.month;
} else if (isYearPage(page)) {
title += ': ' + page.year;
}
} else if (isCategoryPage()) {
title = _p('common.category', 1) + ': ' + page.category;
} else if (isTagPage()) {
title = _p('common.tag', 1) + ': ' + page.tag;
} else if (isCategoriesPage(page)) {
title = _p('common.category', Infinity);
} else if (isTagsPage(page)) {
title = _p('common.tag', Infinity);
}
return [title, siteTitle].filter(str => typeof (str) !== 'undefined' && str.trim() !== '').join(' - ');
}
module.exports = class extends Component {
render() {
const { env, site, config, helper, page } = this.props;
@ -55,6 +127,8 @@ module.exports = class extends Component {
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<MetaTags meta={meta} />
<title>{getPageTitle(page, config.title, _p)}</title>
{open_graph ? <OpenGraph
type={is_post() ? 'article' : 'website'}
title={page.title || config.title}

View File

@ -22,12 +22,12 @@ module.exports = class extends Component {
<head>
<Head env={env} site={site} config={config} helper={helper} page={page} />
</head>
<body class={`is-${columnCount}-column`}>
<body className={`is-${columnCount}-column`}>
<Navbar config={config} helper={helper} page={page} />
<section class="section">
<div class="container">
<div class="columns">
<div class={{
<section className="section">
<div className="container">
<div className="columns">
<div className={{
column: true,
'has-order-2': true,
'column-main': true,

View File

@ -11,12 +11,12 @@ module.exports = class extends Component {
const { url_for, _p } = helper;
return <Fragment>
<div class="card">
<div class="card-content">
<nav class="breadcrumb" aria-label="breadcrumbs">
<div className="card">
<div className="card-content">
<nav className="breadcrumb" aria-label="breadcrumbs">
<ul>
<li><a href={url_for('/tags')}>{_p('common.tag', Infinity)}</a></li>
<li class="is-active"><a href="#" aria-current="page">{page.tag}</a></li>
<li className="is-active"><a href="#" aria-current="page">{page.tag}</a></li>
</ul>
</nav>
</div>

View File

@ -7,10 +7,7 @@ require('../includes/generators/tags')(hexo);
require('../includes/generators/insight')(hexo);
require('../includes/helpers/cdn')(hexo);
require('../includes/helpers/config')(hexo);
require('../includes/helpers/layout')(hexo);
require('../includes/helpers/override')(hexo);
require('../includes/helpers/page')(hexo);
require('../includes/helpers/site')(hexo);
// Fix large blog rendering OOM
const hooks = [