From 4234234c6cb8e3f57852377366f395c6040cab53 Mon Sep 17 00:00:00 2001 From: ppoffice Date: Mon, 23 Dec 2019 17:35:21 -0500 Subject: [PATCH] refactor(script): remove unused hexo helpers --- includes/helpers/layout.js | 40 ----- includes/helpers/override.js | 194 ---------------------- includes/helpers/page.js | 65 -------- includes/helpers/site.js | 106 ------------ includes/utils/lru.js | 305 ----------------------------------- layout/archive.jsx | 30 ++-- layout/category.jsx | 8 +- layout/common/head.jsx | 74 +++++++++ layout/layout.jsx | 10 +- layout/tag.jsx | 8 +- scripts/index.js | 3 - 11 files changed, 102 insertions(+), 741 deletions(-) delete mode 100644 includes/helpers/layout.js delete mode 100644 includes/helpers/override.js delete mode 100644 includes/helpers/site.js delete mode 100644 includes/utils/lru.js diff --git a/includes/helpers/layout.js b/includes/helpers/layout.js deleted file mode 100644 index 7fd6c07..0000000 --- a/includes/helpers/layout.js +++ /dev/null @@ -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; - }); -} \ No newline at end of file diff --git a/includes/helpers/override.js b/includes/helpers/override.js deleted file mode 100644 index 29988c0..0000000 --- a/includes/helpers/override.js +++ /dev/null @@ -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 ``; - }); - - 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 ``; - }); - - 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); - }); -} \ No newline at end of file diff --git a/includes/helpers/page.js b/includes/helpers/page.js index 3e38b79..8dd7445 100644 --- a/includes/helpers/page.js +++ b/includes/helpers/page.js @@ -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); - }); } diff --git a/includes/helpers/site.js b/includes/helpers/site.js deleted file mode 100644 index c29c187..0000000 --- a/includes/helpers/site.js +++ /dev/null @@ -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 ''; - }); - return metaDOMArray.join('\n'); - }); - - hexo.extend.helper.register('hexo_version', function (data) { - return hexo.version; - }); -} \ No newline at end of file diff --git a/includes/utils/lru.js b/includes/utils/lru.js deleted file mode 100644 index 014d4c8..0000000 --- a/includes/utils/lru.js +++ /dev/null @@ -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 - * 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 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 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 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; - }; - -}); diff --git a/layout/archive.jsx b/layout/archive.jsx index ddca928..c4bce4a 100644 --- a/layout/archive.jsx +++ b/layout/archive.jsx @@ -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
-
- -
+ return
+
+

{month === null ? year : time.locale(language).format('MMMM YYYY')}

+
{posts.map(post => { const categories = []; post.categories.forEach((category, i) => { @@ -29,21 +29,21 @@ module.exports = class extends Component { categories.push('/'); } }); - return
- {has_thumbnail(post) ? -

- {post.title + return

+ {has_thumbnail(post) ? +

+ {post.title

: null} -
-
-