From 8edb00591ff9f33c3ec2e37e3c87e5e3f2987c4b Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Tue, 10 Sep 2019 09:40:40 +0100 Subject: [PATCH 01/43] fix(helpers, tag plugins): encode url by default --- lib/plugins/helper/url_for.js | 4 ++-- lib/plugins/tag/asset_img.js | 4 ++-- lib/plugins/tag/asset_link.js | 2 +- lib/plugins/tag/asset_path.js | 6 ++++-- lib/plugins/tag/post_link.js | 2 +- lib/plugins/tag/post_path.js | 6 +++++- 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/plugins/helper/url_for.js b/lib/plugins/helper/url_for.js index ed1ec087fc..c7bb94f466 100644 --- a/lib/plugins/helper/url_for.js +++ b/lib/plugins/helper/url_for.js @@ -27,9 +27,9 @@ function urlForHelper(path = '/', options) { } // Prepend root path - path = root + path; + path = encodeURL((root + path).replace(/\/{2,}/g, '/')); - return path.replace(/\/{2,}/g, '/'); + return path; } module.exports = urlForHelper; diff --git a/lib/plugins/tag/asset_img.js b/lib/plugins/tag/asset_img.js index 752d0deb05..0d3bfbd35f 100644 --- a/lib/plugins/tag/asset_img.js +++ b/lib/plugins/tag/asset_img.js @@ -1,7 +1,7 @@ 'use strict'; -const url = require('url'); const img = require('./img'); +const { encodeURL } = require('hexo-util'); /** * Asset image tag @@ -19,7 +19,7 @@ module.exports = ctx => { for (let i = 0; i < len; i++) { const asset = PostAsset.findOne({post: this._id, slug: args[i]}); if (asset) { - args[i] = url.resolve('/', asset.path); + args[i] = encodeURL('/' + asset.path); return img(ctx)(args); } } diff --git a/lib/plugins/tag/asset_link.js b/lib/plugins/tag/asset_link.js index fc631fa35d..d12000b505 100644 --- a/lib/plugins/tag/asset_link.js +++ b/lib/plugins/tag/asset_link.js @@ -1,7 +1,7 @@ 'use strict'; const url = require('url'); -const { escapeHTML } = require('hexo-util'); +const { encodeURL, escapeHTML } = require('hexo-util'); /** * Asset link tag diff --git a/lib/plugins/tag/asset_path.js b/lib/plugins/tag/asset_path.js index 81babf2297..432d925e2b 100644 --- a/lib/plugins/tag/asset_path.js +++ b/lib/plugins/tag/asset_path.js @@ -1,6 +1,6 @@ 'use strict'; -const url = require('url'); +const { encodeURL } = require('hexo-util'); /** * Asset path tag @@ -18,6 +18,8 @@ module.exports = ctx => { const asset = PostAsset.findOne({post: this._id, slug}); if (!asset) return; - return url.resolve(ctx.config.root, asset.path); + const path = encodeURL(ctx.config.root + asset.path); + + return path; }; }; diff --git a/lib/plugins/tag/post_link.js b/lib/plugins/tag/post_link.js index 5ba86e62b3..b7cfe8a54f 100644 --- a/lib/plugins/tag/post_link.js +++ b/lib/plugins/tag/post_link.js @@ -1,6 +1,6 @@ 'use strict'; -const { escapeHTML } = require('hexo-util'); +const { encodeURL, escapeHTML } = require('hexo-util'); /** * Post link tag diff --git a/lib/plugins/tag/post_path.js b/lib/plugins/tag/post_path.js index defe0b265f..55bdd7d808 100644 --- a/lib/plugins/tag/post_path.js +++ b/lib/plugins/tag/post_path.js @@ -1,5 +1,7 @@ 'use strict'; +const { encodeURL } = require('hexo-util'); + /** * Post path tag * @@ -16,6 +18,8 @@ module.exports = ctx => { const post = Post.findOne({slug}); if (!post) return; - return ctx.config.root + post.path; + const link = encodeURL(ctx.config.root + post.path); + + return link; }; }; From dcde0ae7fb9b60782f970016eaab8a38119bd757 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Tue, 10 Sep 2019 10:18:03 +0100 Subject: [PATCH 02/43] test(helpers, tag plugins): encode url by default --- test/scripts/helpers/url_for.js | 8 ++++++++ test/scripts/tags/asset_img.js | 9 +++++++++ test/scripts/tags/asset_link.js | 9 +++++++++ test/scripts/tags/asset_path.js | 9 +++++++++ test/scripts/tags/post_link.js | 9 +++++++++ test/scripts/tags/post_path.js | 11 +++++++++-- 6 files changed, 53 insertions(+), 2 deletions(-) diff --git a/test/scripts/helpers/url_for.js b/test/scripts/helpers/url_for.js index 0195805d9f..de705220e7 100644 --- a/test/scripts/helpers/url_for.js +++ b/test/scripts/helpers/url_for.js @@ -8,6 +8,14 @@ describe('url_for', () => { const urlFor = require('../../../lib/plugins/helper/url_for').bind(ctx); + it('should encode path', () => { + ctx.config.root = '/'; + urlFor('fôo.html').should.eql('/f%C3%B4o.html'); + + ctx.config.root = '/fôo/'; + urlFor('bár.html').should.eql('/f%C3%B4o/b%C3%A1r.html'); + }); + it('internal url (relative off)', () => { ctx.config.root = '/'; urlFor('index.html').should.eql('/index.html'); diff --git a/test/scripts/tags/asset_img.js b/test/scripts/tags/asset_img.js index 1399654176..0adc7e60cb 100644 --- a/test/scripts/tags/asset_img.js +++ b/test/scripts/tags/asset_img.js @@ -28,6 +28,11 @@ describe('asset_img', () => { slug: 'bar', post: post._id }), + PostAsset.insert({ + _id: 'bár', + slug: 'bár', + post: post._id + }), PostAsset.insert({ _id: 'spaced asset', slug: 'spaced asset', @@ -40,6 +45,10 @@ describe('asset_img', () => { assetImg('bar').should.eql(''); }); + it('should encode path', () => { + assetImg('bár').should.eql(''); + }); + it('default', () => { assetImg('bar title').should.eql(''); }); diff --git a/test/scripts/tags/asset_link.js b/test/scripts/tags/asset_link.js index 4531bcd9b4..8a1140bc17 100644 --- a/test/scripts/tags/asset_link.js +++ b/test/scripts/tags/asset_link.js @@ -28,6 +28,11 @@ describe('asset_link', () => { slug: 'bar', post: post._id }), + PostAsset.insert({ + _id: 'bár', + slug: 'bár', + post: post._id + }), PostAsset.insert({ _id: 'spaced asset', slug: 'spaced asset', @@ -40,6 +45,10 @@ describe('asset_link', () => { assetLink('bar').should.eql('bar'); }); + it('should encode path', () => { + assetLink('bár').should.eql('bár'); + }); + it('title', () => { assetLink('bar Hello world').should.eql('Hello world'); }); diff --git a/test/scripts/tags/asset_path.js b/test/scripts/tags/asset_path.js index 60c50086fe..20d1d4a065 100644 --- a/test/scripts/tags/asset_path.js +++ b/test/scripts/tags/asset_path.js @@ -28,6 +28,11 @@ describe('asset_path', () => { slug: 'bar', post: post._id }), + PostAsset.insert({ + _id: 'bár', + slug: 'bár', + post: post._id + }), PostAsset.insert({ _id: 'spaced asset', slug: 'spaced asset', @@ -40,6 +45,10 @@ describe('asset_path', () => { assetPath('bar').should.eql('/foo/bar'); }); + it('should encode path', () => { + assetPath('bár').should.eql('/foo/b%C3%A1r'); + }); + it('with space', () => { // {% asset_path "spaced asset" %} assetPathTag.call(post, ['spaced asset']) diff --git a/test/scripts/tags/post_link.js b/test/scripts/tags/post_link.js index b2b6f6dd42..831538befe 100644 --- a/test/scripts/tags/post_link.js +++ b/test/scripts/tags/post_link.js @@ -17,12 +17,21 @@ describe('post_link', () => { source: 'title-with-tag', slug: 'title-with-tag', title: '"Hello" !' + }, + { + source: 'fôo', + slug: 'fôo', + title: 'Hello world' }]))); it('default', () => { postLink(['foo']).should.eql('Hello world'); }); + it('should encode path', () => { + postLink(['fôo']).should.eql('Hello world'); + }); + it('title', () => { postLink(['foo', 'test']).should.eql('test'); }); diff --git a/test/scripts/tags/post_path.js b/test/scripts/tags/post_path.js index 260a2ec818..2b73c1edc8 100644 --- a/test/scripts/tags/post_path.js +++ b/test/scripts/tags/post_path.js @@ -8,15 +8,22 @@ describe('post_path', () => { hexo.config.permalink = ':title/'; - before(() => hexo.init().then(() => Post.insert({ + before(() => hexo.init().then(() => Post.insert([{ source: 'foo', slug: 'foo' - }))); + }, { + source: 'fôo', + slug: 'fôo' + }]))); it('default', () => { postPath(['foo']).should.eql('/foo/'); }); + it('should encode path', () => { + postPath(['fôo']).should.eql('/f%C3%B4o/'); + }); + it('no slug', () => { should.not.exist(postPath([])); }); From d1da5801b8f3a90aed086aeb24b86fbce7909fac Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Sun, 15 Sep 2019 00:58:23 +0100 Subject: [PATCH 03/43] refactor: use url_for from hexo-util --- lib/plugins/helper/url_for.js | 36 ++++------------------------------- 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/lib/plugins/helper/url_for.js b/lib/plugins/helper/url_for.js index c7bb94f466..a31379a29b 100644 --- a/lib/plugins/helper/url_for.js +++ b/lib/plugins/helper/url_for.js @@ -1,35 +1,7 @@ 'use strict'; -const url = require('url'); -const relative_url = require('./relative_url'); +const { url_for } = require('hexo-util'); -function urlForHelper(path = '/', options) { - if (path[0] === '#' || path.startsWith('//')) { - return path; - } - - const { config } = this; - const { root } = config; - const data = url.parse(path); - - options = Object.assign({ - relative: config.relative_link - }, options); - - // Exit if this is an external path - if (data.protocol) { - return path; - } - - // Resolve relative url - if (options.relative) { - return relative_url(this.path, path); - } - - // Prepend root path - path = encodeURL((root + path).replace(/\/{2,}/g, '/')); - - return path; -} - -module.exports = urlForHelper; +module.exports = function(path, options) { + return url_for.call(this, path, options); +}; From 4624058da7d0a1db825d89fea22dd3bcb257aa30 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Sun, 15 Sep 2019 01:03:46 +0100 Subject: [PATCH 04/43] refactor: use relative_url from hexo-util --- lib/plugins/helper/relative_url.js | 31 ++++-------------------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/lib/plugins/helper/relative_url.js b/lib/plugins/helper/relative_url.js index 7a82d94c77..045a9be9f3 100644 --- a/lib/plugins/helper/relative_url.js +++ b/lib/plugins/helper/relative_url.js @@ -1,29 +1,6 @@ 'use strict'; -function relativeUrlHelper(from = '', to = '') { - const fromParts = from.split('/'); - const toParts = to.split('/'); - const length = Math.min(fromParts.length, toParts.length); - let i = 0; - - for (; i < length; i++) { - if (fromParts[i] !== toParts[i]) break; - } - - let out = toParts.slice(i); - - for (let j = fromParts.length - i - 1; j > 0; j--) { - out.unshift('..'); - } - - const outLength = out.length; - - // If the last 2 elements of `out` is empty strings, replace them with `index.html`. - if (outLength > 1 && !out[outLength - 1] && !out[outLength - 2]) { - out = out.slice(0, outLength - 2).concat('index.html'); - } - - return out.join('/').replace(/\/{2,}/g, '/'); -} - -module.exports = relativeUrlHelper; +module.exports = function(from, to) { + const relative_url = require('hexo-util').relative_url.bind(this); + return relative_url(from, to); +}; From 249a4332cbbb8b937d8be2aebb764ce6a7b2c0b8 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Sun, 15 Sep 2019 01:05:01 +0100 Subject: [PATCH 05/43] style: remove unnecessary argument initialize --- lib/plugins/helper/url_for.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/plugins/helper/url_for.js b/lib/plugins/helper/url_for.js index a31379a29b..fc4a2eebd6 100644 --- a/lib/plugins/helper/url_for.js +++ b/lib/plugins/helper/url_for.js @@ -1,7 +1,6 @@ 'use strict'; -const { url_for } = require('hexo-util'); - module.exports = function(path, options) { - return url_for.call(this, path, options); + const url_for = require('hexo-util').url_for.bind(this); + return url_for(path, options); }; From 1e61096cd4b569e8eb4c44badad05cff2a5665ef Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Sun, 15 Sep 2019 01:06:35 +0100 Subject: [PATCH 06/43] test(relative_url): should encode path --- test/scripts/helpers/relative_url.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/scripts/helpers/relative_url.js b/test/scripts/helpers/relative_url.js index 8f511747b4..60930788bc 100644 --- a/test/scripts/helpers/relative_url.js +++ b/test/scripts/helpers/relative_url.js @@ -27,4 +27,8 @@ describe('relative_url', () => { relativeURL('foo/', '/').should.eql('../index.html'); relativeURL('foo/index.html', '/').should.eql('../index.html'); }); + + it('should encode path', () => { + relativeURL('foo/', 'css/fôo.css').should.eql('../css/f%C3%B4o.css'); + }); }); From ec83d43b6641fe36371e969755f24f94fc31a839 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Sun, 15 Sep 2019 15:48:59 +0100 Subject: [PATCH 07/43] refactor: utilize url_for() helper to prepend config.root --- lib/plugins/tag/asset_link.js | 1 + lib/plugins/tag/asset_path.js | 3 ++- lib/plugins/tag/post_link.js | 1 + lib/plugins/tag/post_path.js | 3 ++- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/plugins/tag/asset_link.js b/lib/plugins/tag/asset_link.js index d12000b505..3dea9f94dc 100644 --- a/lib/plugins/tag/asset_link.js +++ b/lib/plugins/tag/asset_link.js @@ -11,6 +11,7 @@ const { encodeURL, escapeHTML } = require('hexo-util'); */ module.exports = ctx => { const PostAsset = ctx.model('PostAsset'); + const url_for = require('../../plugins/helper/url_for').bind(ctx); return function assetLinkTag(args) { const slug = args.shift(); diff --git a/lib/plugins/tag/asset_path.js b/lib/plugins/tag/asset_path.js index 432d925e2b..27ecb10f36 100644 --- a/lib/plugins/tag/asset_path.js +++ b/lib/plugins/tag/asset_path.js @@ -10,6 +10,7 @@ const { encodeURL } = require('hexo-util'); */ module.exports = ctx => { const PostAsset = ctx.model('PostAsset'); + const url_for = require('../../plugins/helper/url_for').bind(ctx); return function assetPathTag(args) { const slug = args.shift(); @@ -18,7 +19,7 @@ module.exports = ctx => { const asset = PostAsset.findOne({post: this._id, slug}); if (!asset) return; - const path = encodeURL(ctx.config.root + asset.path); + const path = encodeURL(url_for(asset.path)); return path; }; diff --git a/lib/plugins/tag/post_link.js b/lib/plugins/tag/post_link.js index b7cfe8a54f..de495d1442 100644 --- a/lib/plugins/tag/post_link.js +++ b/lib/plugins/tag/post_link.js @@ -10,6 +10,7 @@ const { encodeURL, escapeHTML } = require('hexo-util'); */ module.exports = ctx => { const Post = ctx.model('Post'); + const url_for = require('../../plugins/helper/url_for').bind(ctx); return function postLinkTag(args) { const slug = args.shift(); diff --git a/lib/plugins/tag/post_path.js b/lib/plugins/tag/post_path.js index 55bdd7d808..e4c8672a79 100644 --- a/lib/plugins/tag/post_path.js +++ b/lib/plugins/tag/post_path.js @@ -10,6 +10,7 @@ const { encodeURL } = require('hexo-util'); */ module.exports = ctx => { const Post = ctx.model('Post'); + const url_for = require('../../plugins/helper/url_for').bind(ctx); return function postPathTag(args) { const slug = args.shift(); @@ -18,7 +19,7 @@ module.exports = ctx => { const post = Post.findOne({slug}); if (!post) return; - const link = encodeURL(ctx.config.root + post.path); + const link = encodeURL(url_for(post.path)); return link; }; From f24a66caea04315495086d2882932ab65328404c Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Sun, 15 Sep 2019 17:07:21 +0100 Subject: [PATCH 08/43] refactor: replace Function.bind() with Function.call() --- lib/plugins/helper/relative_url.js | 5 +++-- lib/plugins/helper/url_for.js | 5 +++-- lib/plugins/tag/asset_link.js | 2 +- lib/plugins/tag/asset_path.js | 4 ++-- lib/plugins/tag/post_link.js | 4 +++- lib/plugins/tag/post_path.js | 4 ++-- 6 files changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/plugins/helper/relative_url.js b/lib/plugins/helper/relative_url.js index 045a9be9f3..e7b6a40fd2 100644 --- a/lib/plugins/helper/relative_url.js +++ b/lib/plugins/helper/relative_url.js @@ -1,6 +1,7 @@ 'use strict'; +const { relative_url } = require('hexo-util'); + module.exports = function(from, to) { - const relative_url = require('hexo-util').relative_url.bind(this); - return relative_url(from, to); + return relative_url.call(this, from, to); }; diff --git a/lib/plugins/helper/url_for.js b/lib/plugins/helper/url_for.js index fc4a2eebd6..822a02df90 100644 --- a/lib/plugins/helper/url_for.js +++ b/lib/plugins/helper/url_for.js @@ -1,6 +1,7 @@ 'use strict'; +const url_for = require('hexo-util'); + module.exports = function(path, options) { - const url_for = require('hexo-util').url_for.bind(this); - return url_for(path, options); + return url_for.call(this, path, options); }; diff --git a/lib/plugins/tag/asset_link.js b/lib/plugins/tag/asset_link.js index 3dea9f94dc..50b8ff8eea 100644 --- a/lib/plugins/tag/asset_link.js +++ b/lib/plugins/tag/asset_link.js @@ -11,7 +11,6 @@ const { encodeURL, escapeHTML } = require('hexo-util'); */ module.exports = ctx => { const PostAsset = ctx.model('PostAsset'); - const url_for = require('../../plugins/helper/url_for').bind(ctx); return function assetLinkTag(args) { const slug = args.shift(); @@ -30,6 +29,7 @@ module.exports = ctx => { let title = args.length ? args.join(' ') : asset.slug; const attrTitle = escapeHTML(title); if (escape === 'true') title = attrTitle; + const link = encodeURL(url_for.call(ctx, asset.path)); return `${title}`; }; diff --git a/lib/plugins/tag/asset_path.js b/lib/plugins/tag/asset_path.js index 27ecb10f36..33f16eeed4 100644 --- a/lib/plugins/tag/asset_path.js +++ b/lib/plugins/tag/asset_path.js @@ -1,6 +1,7 @@ 'use strict'; const { encodeURL } = require('hexo-util'); +const url_for = require('../../plugins/helper/url_for'); /** * Asset path tag @@ -10,7 +11,6 @@ const { encodeURL } = require('hexo-util'); */ module.exports = ctx => { const PostAsset = ctx.model('PostAsset'); - const url_for = require('../../plugins/helper/url_for').bind(ctx); return function assetPathTag(args) { const slug = args.shift(); @@ -19,7 +19,7 @@ module.exports = ctx => { const asset = PostAsset.findOne({post: this._id, slug}); if (!asset) return; - const path = encodeURL(url_for(asset.path)); + const path = encodeURL(url_for.call(ctx, asset.path)); return path; }; diff --git a/lib/plugins/tag/post_link.js b/lib/plugins/tag/post_link.js index de495d1442..16541ef907 100644 --- a/lib/plugins/tag/post_link.js +++ b/lib/plugins/tag/post_link.js @@ -10,7 +10,6 @@ const { encodeURL, escapeHTML } = require('hexo-util'); */ module.exports = ctx => { const Post = ctx.model('Post'); - const url_for = require('../../plugins/helper/url_for').bind(ctx); return function postLinkTag(args) { const slug = args.shift(); @@ -29,6 +28,9 @@ module.exports = ctx => { let title = args.length ? args.join(' ') : post.title; const attrTitle = escapeHTML(title); if (escape === 'true') title = attrTitle; + const title = args.length ? args.join(' ') : post.title; + + const link = encodeURL(url_for.call(ctx, post.path)); return `${title}`; }; diff --git a/lib/plugins/tag/post_path.js b/lib/plugins/tag/post_path.js index e4c8672a79..078495bc3a 100644 --- a/lib/plugins/tag/post_path.js +++ b/lib/plugins/tag/post_path.js @@ -1,6 +1,7 @@ 'use strict'; const { encodeURL } = require('hexo-util'); +const url_for = require('../../plugins/helper/url_for'); /** * Post path tag @@ -10,7 +11,6 @@ const { encodeURL } = require('hexo-util'); */ module.exports = ctx => { const Post = ctx.model('Post'); - const url_for = require('../../plugins/helper/url_for').bind(ctx); return function postPathTag(args) { const slug = args.shift(); @@ -19,7 +19,7 @@ module.exports = ctx => { const post = Post.findOne({slug}); if (!post) return; - const link = encodeURL(url_for(post.path)); + const link = encodeURL(url_for.call(this, post.path)); return link; }; From d7cd1f1ce5a74598e631930bd3cdfb5e40af27f9 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Sun, 15 Sep 2019 17:10:51 +0100 Subject: [PATCH 09/43] refactor: url_for path --- lib/plugins/tag/asset_path.js | 2 +- lib/plugins/tag/post_path.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/plugins/tag/asset_path.js b/lib/plugins/tag/asset_path.js index 33f16eeed4..0d6604488f 100644 --- a/lib/plugins/tag/asset_path.js +++ b/lib/plugins/tag/asset_path.js @@ -1,7 +1,7 @@ 'use strict'; const { encodeURL } = require('hexo-util'); -const url_for = require('../../plugins/helper/url_for'); +const url_for = require('../helper/url_for'); /** * Asset path tag diff --git a/lib/plugins/tag/post_path.js b/lib/plugins/tag/post_path.js index 078495bc3a..a7589493e8 100644 --- a/lib/plugins/tag/post_path.js +++ b/lib/plugins/tag/post_path.js @@ -1,7 +1,7 @@ 'use strict'; const { encodeURL } = require('hexo-util'); -const url_for = require('../../plugins/helper/url_for'); +const url_for = require('../helper/url_for'); /** * Post path tag From 8f985eb15538274467561d05de29b28e89252a94 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Sun, 15 Sep 2019 17:20:08 +0100 Subject: [PATCH 10/43] fix: function binding and module destructure --- lib/plugins/helper/url_for.js | 2 +- lib/plugins/tag/asset_link.js | 1 + lib/plugins/tag/asset_path.js | 4 ++-- lib/plugins/tag/post_link.js | 3 ++- lib/plugins/tag/post_path.js | 4 ++-- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/plugins/helper/url_for.js b/lib/plugins/helper/url_for.js index 822a02df90..a31379a29b 100644 --- a/lib/plugins/helper/url_for.js +++ b/lib/plugins/helper/url_for.js @@ -1,6 +1,6 @@ 'use strict'; -const url_for = require('hexo-util'); +const { url_for } = require('hexo-util'); module.exports = function(path, options) { return url_for.call(this, path, options); diff --git a/lib/plugins/tag/asset_link.js b/lib/plugins/tag/asset_link.js index 50b8ff8eea..bb2334d218 100644 --- a/lib/plugins/tag/asset_link.js +++ b/lib/plugins/tag/asset_link.js @@ -11,6 +11,7 @@ const { encodeURL, escapeHTML } = require('hexo-util'); */ module.exports = ctx => { const PostAsset = ctx.model('PostAsset'); + const url_for = require('../helper/url_for').bind(ctx); return function assetLinkTag(args) { const slug = args.shift(); diff --git a/lib/plugins/tag/asset_path.js b/lib/plugins/tag/asset_path.js index 0d6604488f..0192ba3ce1 100644 --- a/lib/plugins/tag/asset_path.js +++ b/lib/plugins/tag/asset_path.js @@ -1,7 +1,6 @@ 'use strict'; const { encodeURL } = require('hexo-util'); -const url_for = require('../helper/url_for'); /** * Asset path tag @@ -11,6 +10,7 @@ const url_for = require('../helper/url_for'); */ module.exports = ctx => { const PostAsset = ctx.model('PostAsset'); + const url_for = require('../helper/url_for').bind(ctx); return function assetPathTag(args) { const slug = args.shift(); @@ -19,7 +19,7 @@ module.exports = ctx => { const asset = PostAsset.findOne({post: this._id, slug}); if (!asset) return; - const path = encodeURL(url_for.call(ctx, asset.path)); + const path = encodeURL(url_for(asset.path)); return path; }; diff --git a/lib/plugins/tag/post_link.js b/lib/plugins/tag/post_link.js index 16541ef907..cc23837231 100644 --- a/lib/plugins/tag/post_link.js +++ b/lib/plugins/tag/post_link.js @@ -10,6 +10,7 @@ const { encodeURL, escapeHTML } = require('hexo-util'); */ module.exports = ctx => { const Post = ctx.model('Post'); + const url_for = require('../helper/url_for').bind(ctx); return function postLinkTag(args) { const slug = args.shift(); @@ -30,7 +31,7 @@ module.exports = ctx => { if (escape === 'true') title = attrTitle; const title = args.length ? args.join(' ') : post.title; - const link = encodeURL(url_for.call(ctx, post.path)); + const link = encodeURL(url_for(post.path)); return `${title}`; }; diff --git a/lib/plugins/tag/post_path.js b/lib/plugins/tag/post_path.js index a7589493e8..591651c4c7 100644 --- a/lib/plugins/tag/post_path.js +++ b/lib/plugins/tag/post_path.js @@ -1,7 +1,6 @@ 'use strict'; const { encodeURL } = require('hexo-util'); -const url_for = require('../helper/url_for'); /** * Post path tag @@ -11,6 +10,7 @@ const url_for = require('../helper/url_for'); */ module.exports = ctx => { const Post = ctx.model('Post'); + const url_for = require('../helper/url_for').bind(ctx); return function postPathTag(args) { const slug = args.shift(); @@ -19,7 +19,7 @@ module.exports = ctx => { const post = Post.findOne({slug}); if (!post) return; - const link = encodeURL(url_for.call(this, post.path)); + const link = encodeURL(url_for(post.path)); return link; }; From 55760f8695352eaafce79914580b9feab502c938 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Sun, 15 Sep 2019 18:41:34 +0100 Subject: [PATCH 11/43] refactor(relative_url): 'this' binding is not required --- lib/plugins/helper/relative_url.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/plugins/helper/relative_url.js b/lib/plugins/helper/relative_url.js index e7b6a40fd2..db1fba37fc 100644 --- a/lib/plugins/helper/relative_url.js +++ b/lib/plugins/helper/relative_url.js @@ -3,5 +3,5 @@ const { relative_url } = require('hexo-util'); module.exports = function(from, to) { - return relative_url.call(this, from, to); + return relative_url(from, to); }; From ff38e12bd547a351a1a284b8d4545b70abaecb04 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Sun, 15 Sep 2019 20:30:31 +0100 Subject: [PATCH 12/43] fix: url_for() already encode path --- lib/plugins/tag/asset_path.js | 4 +--- lib/plugins/tag/post_link.js | 2 +- lib/plugins/tag/post_path.js | 4 +--- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/plugins/tag/asset_path.js b/lib/plugins/tag/asset_path.js index 0192ba3ce1..ddd59d52db 100644 --- a/lib/plugins/tag/asset_path.js +++ b/lib/plugins/tag/asset_path.js @@ -1,7 +1,5 @@ 'use strict'; -const { encodeURL } = require('hexo-util'); - /** * Asset path tag * @@ -19,7 +17,7 @@ module.exports = ctx => { const asset = PostAsset.findOne({post: this._id, slug}); if (!asset) return; - const path = encodeURL(url_for(asset.path)); + const path = url_for(asset.path); return path; }; diff --git a/lib/plugins/tag/post_link.js b/lib/plugins/tag/post_link.js index cc23837231..4ed02e2cea 100644 --- a/lib/plugins/tag/post_link.js +++ b/lib/plugins/tag/post_link.js @@ -31,7 +31,7 @@ module.exports = ctx => { if (escape === 'true') title = attrTitle; const title = args.length ? args.join(' ') : post.title; - const link = encodeURL(url_for(post.path)); + const link = url_for(post.path); return `${title}`; }; diff --git a/lib/plugins/tag/post_path.js b/lib/plugins/tag/post_path.js index 591651c4c7..1a440c9507 100644 --- a/lib/plugins/tag/post_path.js +++ b/lib/plugins/tag/post_path.js @@ -1,7 +1,5 @@ 'use strict'; -const { encodeURL } = require('hexo-util'); - /** * Post path tag * @@ -19,7 +17,7 @@ module.exports = ctx => { const post = Post.findOne({slug}); if (!post) return; - const link = encodeURL(url_for(post.path)); + const link = url_for(post.path); return link; }; From 6aeab6f2f67fd8849e8c75d9d5d45cf6ffc6eb53 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Fri, 20 Sep 2019 05:18:34 +0100 Subject: [PATCH 13/43] refactor: initialize url_for() outside of exports --- lib/plugins/tag/asset_link.js | 1 - lib/plugins/tag/asset_path.js | 5 +++-- lib/plugins/tag/post_link.js | 3 +-- lib/plugins/tag/post_path.js | 5 +++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/plugins/tag/asset_link.js b/lib/plugins/tag/asset_link.js index bb2334d218..50b8ff8eea 100644 --- a/lib/plugins/tag/asset_link.js +++ b/lib/plugins/tag/asset_link.js @@ -11,7 +11,6 @@ const { encodeURL, escapeHTML } = require('hexo-util'); */ module.exports = ctx => { const PostAsset = ctx.model('PostAsset'); - const url_for = require('../helper/url_for').bind(ctx); return function assetLinkTag(args) { const slug = args.shift(); diff --git a/lib/plugins/tag/asset_path.js b/lib/plugins/tag/asset_path.js index ddd59d52db..346cf7ba97 100644 --- a/lib/plugins/tag/asset_path.js +++ b/lib/plugins/tag/asset_path.js @@ -1,5 +1,7 @@ 'use strict'; +const url_for = require('../helper/url_for'); + /** * Asset path tag * @@ -8,7 +10,6 @@ */ module.exports = ctx => { const PostAsset = ctx.model('PostAsset'); - const url_for = require('../helper/url_for').bind(ctx); return function assetPathTag(args) { const slug = args.shift(); @@ -17,7 +18,7 @@ module.exports = ctx => { const asset = PostAsset.findOne({post: this._id, slug}); if (!asset) return; - const path = url_for(asset.path); + const path = url_for.call(ctx, asset.path); return path; }; diff --git a/lib/plugins/tag/post_link.js b/lib/plugins/tag/post_link.js index 4ed02e2cea..3f8091074e 100644 --- a/lib/plugins/tag/post_link.js +++ b/lib/plugins/tag/post_link.js @@ -10,7 +10,6 @@ const { encodeURL, escapeHTML } = require('hexo-util'); */ module.exports = ctx => { const Post = ctx.model('Post'); - const url_for = require('../helper/url_for').bind(ctx); return function postLinkTag(args) { const slug = args.shift(); @@ -31,7 +30,7 @@ module.exports = ctx => { if (escape === 'true') title = attrTitle; const title = args.length ? args.join(' ') : post.title; - const link = url_for(post.path); + const link = url_for.call(ctx, post.path); return `${title}`; }; diff --git a/lib/plugins/tag/post_path.js b/lib/plugins/tag/post_path.js index 1a440c9507..76ea907f34 100644 --- a/lib/plugins/tag/post_path.js +++ b/lib/plugins/tag/post_path.js @@ -1,5 +1,7 @@ 'use strict'; +const url_for = require('../helper/url_for'); + /** * Post path tag * @@ -8,7 +10,6 @@ */ module.exports = ctx => { const Post = ctx.model('Post'); - const url_for = require('../helper/url_for').bind(ctx); return function postPathTag(args) { const slug = args.shift(); @@ -17,7 +18,7 @@ module.exports = ctx => { const post = Post.findOne({slug}); if (!post) return; - const link = url_for(post.path); + const link = url_for.call(ctx, post.path); return link; }; From 382b0deef4ea6906a58c7828a70d4b3bebb5b2da Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Fri, 20 Sep 2019 08:26:29 +0100 Subject: [PATCH 14/43] fix: use url.resolve() as a workaround for Windows compatibility --- lib/plugins/tag/asset_img.js | 3 ++- lib/plugins/tag/asset_link.js | 7 ++++--- lib/plugins/tag/asset_path.js | 5 +++-- lib/plugins/tag/post_link.js | 6 +++--- lib/plugins/tag/post_path.js | 5 +++-- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/lib/plugins/tag/asset_img.js b/lib/plugins/tag/asset_img.js index 0d3bfbd35f..df1b67bd34 100644 --- a/lib/plugins/tag/asset_img.js +++ b/lib/plugins/tag/asset_img.js @@ -1,5 +1,6 @@ 'use strict'; +const { resolve } = require('url'); const img = require('./img'); const { encodeURL } = require('hexo-util'); @@ -19,7 +20,7 @@ module.exports = ctx => { for (let i = 0; i < len; i++) { const asset = PostAsset.findOne({post: this._id, slug: args[i]}); if (asset) { - args[i] = encodeURL('/' + asset.path); + args[i] = encodeURL(resolve('/', asset.path)); return img(ctx)(args); } } diff --git a/lib/plugins/tag/asset_link.js b/lib/plugins/tag/asset_link.js index 50b8ff8eea..c51dc3e005 100644 --- a/lib/plugins/tag/asset_link.js +++ b/lib/plugins/tag/asset_link.js @@ -1,7 +1,7 @@ 'use strict'; -const url = require('url'); const { encodeURL, escapeHTML } = require('hexo-util'); +const { resolve } = require('url'); /** * Asset link tag @@ -29,8 +29,9 @@ module.exports = ctx => { let title = args.length ? args.join(' ') : asset.slug; const attrTitle = escapeHTML(title); if (escape === 'true') title = attrTitle; - const link = encodeURL(url_for.call(ctx, asset.path)); - return `${title}`; + const link = encodeURL(resolve(ctx.config.root, asset.path)); + + return `${title}`; }; }; diff --git a/lib/plugins/tag/asset_path.js b/lib/plugins/tag/asset_path.js index 346cf7ba97..88be887673 100644 --- a/lib/plugins/tag/asset_path.js +++ b/lib/plugins/tag/asset_path.js @@ -1,6 +1,7 @@ 'use strict'; -const url_for = require('../helper/url_for'); +const { resolve } = require('url'); +const { encodeURL } = require('hexo-util'); /** * Asset path tag @@ -18,7 +19,7 @@ module.exports = ctx => { const asset = PostAsset.findOne({post: this._id, slug}); if (!asset) return; - const path = url_for.call(ctx, asset.path); + const path = encodeURL(resolve(ctx.config.root, asset.path)); return path; }; diff --git a/lib/plugins/tag/post_link.js b/lib/plugins/tag/post_link.js index 3f8091074e..30cfef2c5f 100644 --- a/lib/plugins/tag/post_link.js +++ b/lib/plugins/tag/post_link.js @@ -1,6 +1,7 @@ 'use strict'; const { encodeURL, escapeHTML } = require('hexo-util'); +const { resolve } = require('url'); /** * Post link tag @@ -28,10 +29,9 @@ module.exports = ctx => { let title = args.length ? args.join(' ') : post.title; const attrTitle = escapeHTML(title); if (escape === 'true') title = attrTitle; - const title = args.length ? args.join(' ') : post.title; - const link = url_for.call(ctx, post.path); + const link = encodeURL(resolve(ctx.config.root, post.path)); - return `${title}`; + return `${title}`; }; }; diff --git a/lib/plugins/tag/post_path.js b/lib/plugins/tag/post_path.js index 76ea907f34..e156c9deaa 100644 --- a/lib/plugins/tag/post_path.js +++ b/lib/plugins/tag/post_path.js @@ -1,6 +1,7 @@ 'use strict'; -const url_for = require('../helper/url_for'); +const { resolve } = require('url'); +const { encodeURL } = require('hexo-util'); /** * Post path tag @@ -18,7 +19,7 @@ module.exports = ctx => { const post = Post.findOne({slug}); if (!post) return; - const link = url_for.call(ctx, post.path); + const link = encodeURL(resolve(ctx.config.root, post.path)); return link; }; From bf30aeb904367293494649713162ba380fe55faf Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Mon, 26 Aug 2019 15:52:50 +0930 Subject: [PATCH 15/43] fix: external_link should use after_render * also move meta_generator to after_render/ folder --- lib/plugins/filter/after_post_render/index.js | 1 - .../{after_post_render => after_render}/external_link.js | 8 +++++--- lib/plugins/filter/after_render/index.js | 8 ++++++++ lib/plugins/filter/{ => after_render}/meta_generator.js | 0 lib/plugins/filter/index.js | 2 +- test/scripts/filters/external_link.js | 9 ++++----- test/scripts/filters/meta_generator.js | 2 +- 7 files changed, 19 insertions(+), 11 deletions(-) rename lib/plugins/filter/{after_post_render => after_render}/external_link.js (78%) create mode 100644 lib/plugins/filter/after_render/index.js rename lib/plugins/filter/{ => after_render}/meta_generator.js (100%) diff --git a/lib/plugins/filter/after_post_render/index.js b/lib/plugins/filter/after_post_render/index.js index fbc7a7822c..0c1451d3ff 100644 --- a/lib/plugins/filter/after_post_render/index.js +++ b/lib/plugins/filter/after_post_render/index.js @@ -3,6 +3,5 @@ module.exports = ctx => { const { filter } = ctx.extend; - filter.register('after_post_render', require('./external_link')); filter.register('after_post_render', require('./excerpt')); }; diff --git a/lib/plugins/filter/after_post_render/external_link.js b/lib/plugins/filter/after_render/external_link.js similarity index 78% rename from lib/plugins/filter/after_post_render/external_link.js rename to lib/plugins/filter/after_render/external_link.js index 229f3a3f41..c10844ed69 100644 --- a/lib/plugins/filter/after_post_render/external_link.js +++ b/lib/plugins/filter/after_render/external_link.js @@ -8,13 +8,13 @@ function externalLinkFilter(data) { const siteHost = url.parse(config.url).hostname || config.url; - data.content = data.content.replace(//gi, (str, hrefStr, href) => { + data = data.replace(//gi, (str, hrefStr, href) => { if (/target=/gi.test(str)) return str; - const data = url.parse(href); + const parsedUrl = url.parse(href); // Exit if the link doesn't have protocol, which means it's a internal link // Exit if the url has same host with config.url - if (!data.protocol || data.hostname === siteHost) return str; + if (!parsedUrl.protocol || parsedUrl.hostname === siteHost) return str; if (/rel=/gi.test(str)) { str = str.replace(/rel="(.*?)"/gi, (relStr, rel) => { @@ -27,6 +27,8 @@ function externalLinkFilter(data) { return str.replace(hrefStr, `${hrefStr} target="_blank" rel="noopener"`); }); + return data; + } module.exports = externalLinkFilter; diff --git a/lib/plugins/filter/after_render/index.js b/lib/plugins/filter/after_render/index.js new file mode 100644 index 0000000000..819e0490ce --- /dev/null +++ b/lib/plugins/filter/after_render/index.js @@ -0,0 +1,8 @@ +'use strict'; + +module.exports = ctx => { + const { filter } = ctx.extend; + + filter.register('after_render:html', require('./external_link')); + filter.register('after_render:html', require('./meta_generator')); +}; diff --git a/lib/plugins/filter/meta_generator.js b/lib/plugins/filter/after_render/meta_generator.js similarity index 100% rename from lib/plugins/filter/meta_generator.js rename to lib/plugins/filter/after_render/meta_generator.js diff --git a/lib/plugins/filter/index.js b/lib/plugins/filter/index.js index 4b3d47575b..f349b99b29 100644 --- a/lib/plugins/filter/index.js +++ b/lib/plugins/filter/index.js @@ -3,6 +3,7 @@ module.exports = ctx => { const { filter } = ctx.extend; + require('./after_render')(ctx); require('./after_post_render')(ctx); require('./before_post_render')(ctx); require('./before_exit')(ctx); @@ -11,5 +12,4 @@ module.exports = ctx => { filter.register('new_post_path', require('./new_post_path')); filter.register('post_permalink', require('./post_permalink')); - filter.register('after_render:html', require('./meta_generator')); }; diff --git a/test/scripts/filters/external_link.js b/test/scripts/filters/external_link.js index 1e095d6a82..76de3cfc80 100644 --- a/test/scripts/filters/external_link.js +++ b/test/scripts/filters/external_link.js @@ -3,7 +3,8 @@ describe('External link', () => { const Hexo = require('../../../lib/hexo'); const hexo = new Hexo(); - const externalLink = require('../../../lib/plugins/filter/after_post_render/external_link').bind(hexo); + const externalLink = require('../../../lib/plugins/filter/after_render/external_link').bind(hexo); + console.log(typeof externalLink); hexo.config.external_link = true; hexo.config.url = 'https://example.com'; @@ -46,11 +47,9 @@ describe('External link', () => { 'Example Domain' ].join('\n'); - const data = {content}; - - externalLink(data); + const result = externalLink(content); - data.content.should.eql([ + result.should.eql([ '# External link test', '1. External link', 'Hexo', diff --git a/test/scripts/filters/meta_generator.js b/test/scripts/filters/meta_generator.js index 03814a4e63..62d85d33d5 100644 --- a/test/scripts/filters/meta_generator.js +++ b/test/scripts/filters/meta_generator.js @@ -3,7 +3,7 @@ describe('Meta Generator', () => { const Hexo = require('../../../lib/hexo'); const hexo = new Hexo(); - const metaGenerator = require('../../../lib/plugins/filter/meta_generator').bind(hexo); + const metaGenerator = require('../../../lib/plugins/filter/after_render/meta_generator').bind(hexo); const cheerio = require('cheerio'); it('default', () => { From c60486465c743f5610799e5b96790fe8cf27044a Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Tue, 24 Sep 2019 13:45:36 +0100 Subject: [PATCH 16/43] test: remove console.log --- test/scripts/filters/external_link.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/scripts/filters/external_link.js b/test/scripts/filters/external_link.js index 76de3cfc80..5b8255f92a 100644 --- a/test/scripts/filters/external_link.js +++ b/test/scripts/filters/external_link.js @@ -4,7 +4,6 @@ describe('External link', () => { const Hexo = require('../../../lib/hexo'); const hexo = new Hexo(); const externalLink = require('../../../lib/plugins/filter/after_render/external_link').bind(hexo); - console.log(typeof externalLink); hexo.config.external_link = true; hexo.config.url = 'https://example.com'; From 412002504407cb80707cda8b1872c4671999f07e Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Tue, 24 Sep 2019 14:33:23 +0100 Subject: [PATCH 17/43] feat(external_link): add enable, site, exclude options --- lib/hexo/default_config.js | 6 +- .../filter/after_post_render/external_link.js | 51 +++++++ lib/plugins/filter/after_post_render/index.js | 1 + .../filter/after_render/external_link.js | 35 +++-- test/scripts/filters/external_link.js | 124 +++++++++++++++++- 5 files changed, 199 insertions(+), 18 deletions(-) create mode 100644 lib/plugins/filter/after_post_render/external_link.js diff --git a/lib/hexo/default_config.js b/lib/hexo/default_config.js index 87da724e70..b4887efd9c 100644 --- a/lib/hexo/default_config.js +++ b/lib/hexo/default_config.js @@ -29,7 +29,11 @@ module.exports = { new_post_name: ':title.md', default_layout: 'post', titlecase: false, - external_link: true, + external_link: { + enable: true, + field: 'site', + exclude: '' + }, filename_case: 0, render_drafts: false, post_asset_folder: false, diff --git a/lib/plugins/filter/after_post_render/external_link.js b/lib/plugins/filter/after_post_render/external_link.js new file mode 100644 index 0000000000..ba6a6e523c --- /dev/null +++ b/lib/plugins/filter/after_post_render/external_link.js @@ -0,0 +1,51 @@ +'use strict'; + +const { parse } = require('url'); + +/** + * Check whether the link is external + * @param {String} url The url to check + * @param {Object} config The site config + * @returns {Boolean} True if the link doesn't have protocol or link has same host with config.url + */ +const isExternal = (url, config) => { + const exclude = config.external_link.exclude; + const data = parse(url); + const host = data.hostname; + const sitehost = parse(config.url).hostname || config.url; + + if (!data.protocol || !sitehost) return false; + + if (exclude && exclude.length) { + for (const i of exclude) { + if (host === i) return false; + } + } + + if (host !== sitehost) return true; + + return false; +}; + +function externalLinkFilter(data) { + const { config } = this; + if (typeof config.external_link === 'undefined') return; + if (config.external_link === false || config.external_link.enable === false || + config.external_link.field !== 'post') return; + + data.content = data.content.replace(//gi, (str, hrefStr, href) => { + if (/target=/gi.test(str) || !isExternal(href, config)) return str; + + if (/rel=/gi.test(str)) { + str = str.replace(/rel="(.*?)"/gi, (relStr, rel) => { + if (!rel.includes('noopenner')) relStr = relStr.replace(rel, `${rel} noopener`); + return relStr; + }); + return str.replace(hrefStr, `${hrefStr} target="_blank"`); + } + + return str.replace(hrefStr, `${hrefStr} target="_blank" rel="noopener"`); + }); +} + +module.exports = externalLinkFilter; diff --git a/lib/plugins/filter/after_post_render/index.js b/lib/plugins/filter/after_post_render/index.js index 0c1451d3ff..fbc7a7822c 100644 --- a/lib/plugins/filter/after_post_render/index.js +++ b/lib/plugins/filter/after_post_render/index.js @@ -3,5 +3,6 @@ module.exports = ctx => { const { filter } = ctx.extend; + filter.register('after_post_render', require('./external_link')); filter.register('after_post_render', require('./excerpt')); }; diff --git a/lib/plugins/filter/after_render/external_link.js b/lib/plugins/filter/after_render/external_link.js index c10844ed69..c96d1ab328 100644 --- a/lib/plugins/filter/after_render/external_link.js +++ b/lib/plugins/filter/after_render/external_link.js @@ -1,20 +1,34 @@ 'use strict'; -const url = require('url'); +const { parse } = require('url'); + +const isExternal = (url, config) => { + const exclude = config.external_link.exclude; + const data = parse(url); + const host = data.hostname; + const sitehost = parse(config.url).hostname || config.url; + + if (!data.protocol || !sitehost) return false; + + if (exclude && exclude.length) { + for (const i of exclude) { + if (host === i) return false; + } + } + + if (host !== sitehost) return true; + + return false; +}; function externalLinkFilter(data) { const { config } = this; - if (!config.external_link) return; - - const siteHost = url.parse(config.url).hostname || config.url; + if (typeof config.external_link === 'undefined') return; + if (config.external_link === false || config.external_link.enable === false || + config.external_link.field !== 'site') return; data = data.replace(//gi, (str, hrefStr, href) => { - if (/target=/gi.test(str)) return str; - - const parsedUrl = url.parse(href); - // Exit if the link doesn't have protocol, which means it's a internal link - // Exit if the url has same host with config.url - if (!parsedUrl.protocol || parsedUrl.hostname === siteHost) return str; + if (/target=/gi.test(str) || !isExternal(href, config)) return str; if (/rel=/gi.test(str)) { str = str.replace(/rel="(.*?)"/gi, (relStr, rel) => { @@ -28,7 +42,6 @@ function externalLinkFilter(data) { }); return data; - } module.exports = externalLinkFilter; diff --git a/test/scripts/filters/external_link.js b/test/scripts/filters/external_link.js index 5b8255f92a..6b288bd55c 100644 --- a/test/scripts/filters/external_link.js +++ b/test/scripts/filters/external_link.js @@ -1,12 +1,110 @@ 'use strict'; + describe('External link', () => { const Hexo = require('../../../lib/hexo'); const hexo = new Hexo(); const externalLink = require('../../../lib/plugins/filter/after_render/external_link').bind(hexo); - hexo.config.external_link = true; - hexo.config.url = 'https://example.com'; + hexo.config = { + url: 'https://example.com', + external_link: { + enable: true, + field: 'site', + exclude: '' + } + }; + + it('disabled', () => { + const content = 'foo' + + 'Hexo' + + 'bar'; + + hexo.config.external_link.enable = false; + + const result = typeof externalLink(content); + result.should.eql('undefined'); + hexo.config.external_link.enable = true; + }); + + it('field is post', () => { + const content = 'foo' + + 'Hexo' + + 'bar'; + + hexo.config.external_link.field = 'post'; + + const result = typeof externalLink(content); + result.should.eql('undefined'); + hexo.config.external_link.field = 'site'; + }); + + it('enabled', () => { + const content = [ + '# External link test', + '1. External link', + 'Hexo', + '2. External link with "rel" Attribute', + 'Hexo', + 'Hexo', + 'Hexo', + 'Hexo', + 'Hexo', + 'Hexo', + '3. External link with Other Attributes', + 'Hexo', + 'Hexo', + '4. Internal link', + 'Link', + '5. Ignore links have "target" attribute', + 'Hexo', + '6. Ignore links don\'t have "href" attribute', + 'Anchor', + '7. Ignore links whose hostname is same as config', + 'Example Domain' + ].join('\n'); + + const result = externalLink(content); + + result.should.eql([ + '# External link test', + '1. External link', + 'Hexo', + '2. External link with "rel" Attribute', + 'Hexo', + 'Hexo', + 'Hexo', + 'Hexo', + 'Hexo', + 'Hexo', + '3. External link with Other Attributes', + 'Hexo', + 'Hexo', + '4. Internal link', + 'Link', + '5. Ignore links have "target" attribute', + 'Hexo', + '6. Ignore links don\'t have "href" attribute', + 'Anchor', + '7. Ignore links whose hostname is same as config', + 'Example Domain' + ].join('\n')); + }); +}); + +describe('External link - post', () => { + const Hexo = require('../../../lib/hexo'); + const hexo = new Hexo(); + const externalLink = require('../../../lib/plugins/filter/after_post_render/external_link').bind(hexo); + + hexo.config = { + url: 'https://example.com', + external_link: { + enable: true, + field: 'post', + exclude: '' + } + }; it('disabled', () => { const content = 'foo' @@ -14,11 +112,24 @@ describe('External link', () => { + 'bar'; const data = {content}; - hexo.config.external_link = false; + hexo.config.external_link.enable = false; externalLink(data); data.content.should.eql(content); - hexo.config.external_link = true; + hexo.config.external_link.enable = true; + }); + + it('field is site', () => { + const content = 'foo' + + 'Hexo' + + 'bar'; + + const data = {content}; + hexo.config.external_link.field = 'site'; + + externalLink(data); + data.content.should.eql(content); + hexo.config.external_link.field = 'post'; }); it('enabled', () => { @@ -46,9 +157,10 @@ describe('External link', () => { 'Example Domain' ].join('\n'); - const result = externalLink(content); + const data = {content}; + externalLink(data); - result.should.eql([ + data.content.should.eql([ '# External link test', '1. External link', 'Hexo', From ac0fad5b0dd3e0b72417f9d7384f08f610a939b8 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Tue, 24 Sep 2019 14:36:38 +0100 Subject: [PATCH 18/43] docs(external_link): move jsdoc to after_render --- lib/plugins/filter/after_post_render/external_link.js | 6 ------ lib/plugins/filter/after_render/external_link.js | 6 ++++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/plugins/filter/after_post_render/external_link.js b/lib/plugins/filter/after_post_render/external_link.js index ba6a6e523c..8824e63989 100644 --- a/lib/plugins/filter/after_post_render/external_link.js +++ b/lib/plugins/filter/after_post_render/external_link.js @@ -2,12 +2,6 @@ const { parse } = require('url'); -/** - * Check whether the link is external - * @param {String} url The url to check - * @param {Object} config The site config - * @returns {Boolean} True if the link doesn't have protocol or link has same host with config.url - */ const isExternal = (url, config) => { const exclude = config.external_link.exclude; const data = parse(url); diff --git a/lib/plugins/filter/after_render/external_link.js b/lib/plugins/filter/after_render/external_link.js index c96d1ab328..717d8a5326 100644 --- a/lib/plugins/filter/after_render/external_link.js +++ b/lib/plugins/filter/after_render/external_link.js @@ -2,6 +2,12 @@ const { parse } = require('url'); +/** + * Check whether the link is external + * @param {String} url The url to check + * @param {Object} config The site config + * @returns {Boolean} True if the link doesn't have protocol or link has same host with config.url + */ const isExternal = (url, config) => { const exclude = config.external_link.exclude; const data = parse(url); From a26a2e557f478d2806036d1516026295297e1a13 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Tue, 24 Sep 2019 15:01:57 +0100 Subject: [PATCH 19/43] fix(external_link): support exclude in String type --- .../filter/after_post_render/external_link.js | 3 +- .../filter/after_render/external_link.js | 3 +- test/scripts/filters/external_link.js | 118 ++++++++++++++++++ 3 files changed, 122 insertions(+), 2 deletions(-) diff --git a/lib/plugins/filter/after_post_render/external_link.js b/lib/plugins/filter/after_post_render/external_link.js index 8824e63989..ebea6b6586 100644 --- a/lib/plugins/filter/after_post_render/external_link.js +++ b/lib/plugins/filter/after_post_render/external_link.js @@ -3,7 +3,8 @@ const { parse } = require('url'); const isExternal = (url, config) => { - const exclude = config.external_link.exclude; + const exclude = Array.isArray(config.external_link.exclude) ? config.external_link.exclude : + [config.external_link.exclude]; const data = parse(url); const host = data.hostname; const sitehost = parse(config.url).hostname || config.url; diff --git a/lib/plugins/filter/after_render/external_link.js b/lib/plugins/filter/after_render/external_link.js index 717d8a5326..4989358c3d 100644 --- a/lib/plugins/filter/after_render/external_link.js +++ b/lib/plugins/filter/after_render/external_link.js @@ -9,7 +9,8 @@ const { parse } = require('url'); * @returns {Boolean} True if the link doesn't have protocol or link has same host with config.url */ const isExternal = (url, config) => { - const exclude = config.external_link.exclude; + const exclude = Array.isArray(config.external_link.exclude) ? config.external_link.exclude : + [config.external_link.exclude]; const data = parse(url); const host = data.hostname; const sitehost = parse(config.url).hostname || config.url; diff --git a/test/scripts/filters/external_link.js b/test/scripts/filters/external_link.js index 6b288bd55c..12a380944d 100644 --- a/test/scripts/filters/external_link.js +++ b/test/scripts/filters/external_link.js @@ -90,6 +90,63 @@ describe('External link', () => { 'Example Domain' ].join('\n')); }); + + it('backward compatibility', () => { + const content = 'foo' + + 'Hexo' + + 'bar'; + + hexo.config.external_link = false; + + const result = typeof externalLink(content); + result.should.eql('undefined'); + + hexo.config.external_link = { + enable: true, + field: 'site', + exclude: '' + }; + }); + + it('exclude - string', () => { + const content = [ + 'Hexo', + 'Hexo', + 'Hexo' + ].join('\n'); + + hexo.config.external_link.exclude = 'foo.com'; + + const result = externalLink(content); + + result.should.eql([ + 'Hexo', + 'Hexo', + 'Hexo' + ].join('\n')); + + hexo.config.external_link.exclude = ''; + }); + + it('exclude - array', () => { + const content = [ + 'Hexo', + 'Hexo', + 'Hexo' + ].join('\n'); + + hexo.config.external_link.exclude = ['foo.com', 'bar.com']; + + const result = externalLink(content); + + result.should.eql([ + 'Hexo', + 'Hexo', + 'Hexo' + ].join('\n')); + }); + + hexo.config.external_link.exclude = ''; }); describe('External link - post', () => { @@ -184,4 +241,65 @@ describe('External link - post', () => { 'Example Domain' ].join('\n')); }); + + + it('backward compatibility', () => { + const content = 'foo' + + 'Hexo' + + 'bar'; + + const data = {content}; + hexo.config.external_link = false; + + externalLink(data); + data.content.should.eql(content); + + hexo.config.external_link = { + enable: true, + field: 'post', + exclude: '' + }; + }); + + it('exclude - string', () => { + const content = [ + 'Hexo', + 'Hexo', + 'Hexo' + ].join('\n'); + + hexo.config.external_link.exclude = 'foo.com'; + + const data = {content}; + externalLink(data); + + data.content.should.eql([ + 'Hexo', + 'Hexo', + 'Hexo' + ].join('\n')); + + hexo.config.external_link.exclude = ''; + }); + + it('exclude - array', () => { + const content = [ + 'Hexo', + 'Hexo', + 'Hexo' + ].join('\n'); + + hexo.config.external_link.exclude = ['foo.com', 'bar.com']; + + const data = {content}; + externalLink(data); + + data.content.should.eql([ + 'Hexo', + 'Hexo', + 'Hexo' + ].join('\n')); + }); + + hexo.config.external_link.exclude = ''; }); From a198b0d415ba2743a3228d7c30a6703b48b76e82 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Tue, 24 Sep 2019 15:06:06 +0100 Subject: [PATCH 20/43] style: remove newline --- test/scripts/filters/external_link.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/scripts/filters/external_link.js b/test/scripts/filters/external_link.js index 12a380944d..f2ee12049e 100644 --- a/test/scripts/filters/external_link.js +++ b/test/scripts/filters/external_link.js @@ -1,6 +1,5 @@ 'use strict'; - describe('External link', () => { const Hexo = require('../../../lib/hexo'); const hexo = new Hexo(); From 471b3523cec0a49ce2aef015c31548b81685f699 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Tue, 24 Sep 2019 15:59:25 +0100 Subject: [PATCH 21/43] fix(external_link): enable and use site by default --- lib/plugins/filter/after_post_render/external_link.js | 9 ++++++++- lib/plugins/filter/after_render/external_link.js | 9 ++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/plugins/filter/after_post_render/external_link.js b/lib/plugins/filter/after_post_render/external_link.js index ebea6b6586..004b5f0a37 100644 --- a/lib/plugins/filter/after_post_render/external_link.js +++ b/lib/plugins/filter/after_post_render/external_link.js @@ -24,7 +24,14 @@ const isExternal = (url, config) => { function externalLinkFilter(data) { const { config } = this; - if (typeof config.external_link === 'undefined') return; + + if (typeof config.external_link === 'undefined' || typeof config.external_link === 'object') { + config.external_link = Object.assign({ + enable: true, + field: 'site', + exclude: '' + }, config.external_link); + } if (config.external_link === false || config.external_link.enable === false || config.external_link.field !== 'post') return; diff --git a/lib/plugins/filter/after_render/external_link.js b/lib/plugins/filter/after_render/external_link.js index 4989358c3d..7669fbb0a3 100644 --- a/lib/plugins/filter/after_render/external_link.js +++ b/lib/plugins/filter/after_render/external_link.js @@ -30,7 +30,14 @@ const isExternal = (url, config) => { function externalLinkFilter(data) { const { config } = this; - if (typeof config.external_link === 'undefined') return; + + if (typeof config.external_link === 'undefined' || typeof config.external_link === 'object') { + config.external_link = Object.assign({ + enable: true, + field: 'site', + exclude: '' + }, config.external_link); + } if (config.external_link === false || config.external_link.enable === false || config.external_link.field !== 'site') return; From 60a000db2d54895f2808ee5ac98209548b14dd01 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Tue, 24 Sep 2019 21:33:33 +0100 Subject: [PATCH 22/43] fix(external_link): support 'external_link: true' --- .../filter/after_post_render/external_link.js | 3 ++- .../filter/after_render/external_link.js | 3 ++- test/scripts/filters/external_link.js | 17 ++++++++++++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/plugins/filter/after_post_render/external_link.js b/lib/plugins/filter/after_post_render/external_link.js index 004b5f0a37..a056a5a525 100644 --- a/lib/plugins/filter/after_post_render/external_link.js +++ b/lib/plugins/filter/after_post_render/external_link.js @@ -25,7 +25,8 @@ const isExternal = (url, config) => { function externalLinkFilter(data) { const { config } = this; - if (typeof config.external_link === 'undefined' || typeof config.external_link === 'object') { + if (typeof config.external_link === 'undefined' || typeof config.external_link === 'object' || + config.external_link === true) { config.external_link = Object.assign({ enable: true, field: 'site', diff --git a/lib/plugins/filter/after_render/external_link.js b/lib/plugins/filter/after_render/external_link.js index 7669fbb0a3..fd3d7b4ea8 100644 --- a/lib/plugins/filter/after_render/external_link.js +++ b/lib/plugins/filter/after_render/external_link.js @@ -31,7 +31,8 @@ const isExternal = (url, config) => { function externalLinkFilter(data) { const { config } = this; - if (typeof config.external_link === 'undefined' || typeof config.external_link === 'object') { + if (typeof config.external_link === 'undefined' || typeof config.external_link === 'object' || + config.external_link === true) { config.external_link = Object.assign({ enable: true, field: 'site', diff --git a/test/scripts/filters/external_link.js b/test/scripts/filters/external_link.js index f2ee12049e..db80bdbfa2 100644 --- a/test/scripts/filters/external_link.js +++ b/test/scripts/filters/external_link.js @@ -90,7 +90,7 @@ describe('External link', () => { ].join('\n')); }); - it('backward compatibility', () => { + it('old option - false', () => { const content = 'foo' + 'Hexo' + 'bar'; @@ -107,6 +107,21 @@ describe('External link', () => { }; }); + it('old option - true', () => { + const content = 'Hexo'; + + hexo.config.external_link = true; + + const result = externalLink(content); + result.should.eql('Hexo'); + + hexo.config.external_link = { + enable: true, + field: 'site', + exclude: '' + }; + }); + it('exclude - string', () => { const content = [ 'Hexo', From 26b010ab25dba745ab5e2fa2d1a4fdbccb569c02 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Tue, 24 Sep 2019 21:35:41 +0100 Subject: [PATCH 23/43] text(external_link): reset config --- test/scripts/filters/external_link.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/scripts/filters/external_link.js b/test/scripts/filters/external_link.js index db80bdbfa2..b0d7d64c40 100644 --- a/test/scripts/filters/external_link.js +++ b/test/scripts/filters/external_link.js @@ -158,9 +158,9 @@ describe('External link', () => { 'Hexo', 'Hexo' ].join('\n')); - }); - hexo.config.external_link.exclude = ''; + hexo.config.external_link.exclude = ''; + }); }); describe('External link - post', () => { @@ -313,7 +313,7 @@ describe('External link - post', () => { 'Hexo', 'Hexo' ].join('\n')); - }); - hexo.config.external_link.exclude = ''; + hexo.config.external_link.exclude = ''; + }); }); From cdac4d90fdefbda5caf521076688c1177e87eb67 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sat, 28 Sep 2019 12:38:46 +0900 Subject: [PATCH 24/43] chore(deps): update hexo-log requirement from ^0.2.0 to ^1.0.0 (#3730) Updates the requirements on [hexo-log](https://github.com/hexojs/hexo-log) to permit the latest version. - [Release notes](https://github.com/hexojs/hexo-log/releases) - [Commits](https://github.com/hexojs/hexo-log/commits) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d2be457a63..6aa0484191 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "hexo-front-matter": "^1.0.0", "hexo-fs": "^2.0.0", "hexo-i18n": "^1.0.0", - "hexo-log": "^0.2.0", + "hexo-log": "^1.0.0", "hexo-util": "^1.3.1", "js-yaml": "^3.12.0", "lodash": "^4.17.11", From 6cda2021e384b4ddd4cf1e6fd3cc8b878094c5dc Mon Sep 17 00:00:00 2001 From: YoshinoriN Date: Sun, 29 Sep 2019 19:45:49 +0900 Subject: [PATCH 25/43] chore(github): delete old ISSUE_TEMPLATE (#3737) * Already migrate to new ISSUE_TEMPLATE (#3600) --- .github/ISSUE_TEMPLATE.md | 39 --------------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 177297dfbb..0000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,39 +0,0 @@ - - -## Environment Info - -Node version(`node -v`: **Should be at least nodejs 6.9. If not, please update before posting an issue!**): - -Your site `_config.yml` (Optional): - -Your theme `_config.yml` (Optional): - -Hexo and Plugin version(`npm ls --depth 0`): - -Your package.json `package.json`: - -## For BUG - - - - - - - -## For question - - - -## For feature request - - From 58a48827b5b644b8949ae68b45119ddc8d48a577 Mon Sep 17 00:00:00 2001 From: YoshinoriN Date: Mon, 30 Sep 2019 20:15:58 +0900 Subject: [PATCH 26/43] fix(mtime): Use UnixTime at all of the modified fields (#3739) --- lib/models/cache.js | 6 +++--- test/scripts/box/box.js | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/models/cache.js b/lib/models/cache.js index 1e3c9cd39d..bd431dfcc4 100644 --- a/lib/models/cache.js +++ b/lib/models/cache.js @@ -7,7 +7,7 @@ module.exports = ctx => { const Cache = new Schema({ _id: {type: String, required: true}, hash: {type: String, default: ''}, - modified: {type: Number, default: Date.now} + modified: {type: Number, default: Date.now() } // UnixTime }); Cache.static('compareFile', function(id, hashFn, statFn) { @@ -19,7 +19,7 @@ module.exports = ctx => { return Promise.all([hashFn(id), statFn(id)]).spread((hash, stats) => this.insert({ _id: id, hash, - modified: stats.mtime + modified: stats.mtime.getTime() })).thenReturn({ type: 'create' }); @@ -29,7 +29,7 @@ module.exports = ctx => { // Get file stats return statFn(id).then(stats => { - mtime = stats.mtime; + mtime = stats.mtime.getTime(); // Skip the file if the modified time is unchanged if (cache.modified === mtime) { diff --git a/test/scripts/box/box.js b/test/scripts/box/box.js index 025c05bce3..d022915d7d 100644 --- a/test/scripts/box/box.js +++ b/test/scripts/box/box.js @@ -158,8 +158,7 @@ describe('Box', () => { box.addProcessor(processor); return fs.writeFile(path, 'a').then(() => fs.stat(path)).then(stats => box.Cache.insert({ - _id: cacheId, - modified: stats.mtime + _id: cacheId })).then(() => box.process()).then(() => { const file = processor.args[0][0]; file.type.should.eql('update'); From bc7740f5637d109bbd64d65314e2959bc491a7ed Mon Sep 17 00:00:00 2001 From: YoshinoriN Date: Tue, 1 Oct 2019 23:09:44 +0900 Subject: [PATCH 27/43] chore(deps): update warehouse requirement from ^2.2.0 to ^3.0.0 (#3736) --- lib/models/types/moment.js | 9 ++++----- package.json | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/models/types/moment.js b/lib/models/types/moment.js index 9012663984..3996f6a6e0 100644 --- a/lib/models/types/moment.js +++ b/lib/models/types/moment.js @@ -2,14 +2,13 @@ const moment = require('moment-timezone'); const { SchemaType } = require('warehouse'); -const util = require('util'); -function SchemaTypeMoment(name, options) { - Reflect.apply(SchemaType, this, [name, options]); +class SchemaTypeMoment extends SchemaType { + constructor(name, options = {}) { + super(name, options); + } } -util.inherits(SchemaTypeMoment, SchemaType); - function toMoment(value) { // FIXME: Something is wrong when using a moment instance. I try to get the // original date object and create a new moment object again. diff --git a/package.json b/package.json index 6aa0484191..c293dce88f 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "text-table": "^0.2.0", "tildify": "^2.0.0", "titlecase": "^1.1.2", - "warehouse": "^2.2.0" + "warehouse": "^3.0.0" }, "devDependencies": { "@easyops/git-exec-and-restage": "^1.0.4", From a8bb7b83057fe02dbf7e38747f67470f26679180 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Tue, 1 Oct 2019 23:40:30 +0930 Subject: [PATCH 28/43] test: remove empty test (#3742) --- test/scripts/console/render.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/scripts/console/render.js b/test/scripts/console/render.js index 5243703740..a336319d7f 100644 --- a/test/scripts/console/render.js +++ b/test/scripts/console/render.js @@ -76,8 +76,6 @@ describe('render', () => { }); }); - it('output'); - it('engine', () => { const src = pathFn.join(hexo.base_dir, 'test'); const dest = pathFn.join(hexo.base_dir, 'result.json'); From 5bb063d378d62f1b4c5118fb53f799246cc48094 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Wed, 2 Oct 2019 11:16:54 +0100 Subject: [PATCH 29/43] style: prefer-arrow-callback --- .eslintrc.json | 3 ++- lib/extend/tag.js | 2 +- lib/plugins/tag/code.js | 2 +- test/scripts/console/list_categories.js | 2 +- test/scripts/console/list_page.js | 2 +- test/scripts/console/list_post.js | 2 +- test/scripts/console/list_tags.js | 2 +- 7 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 57bd13b4a0..9fb853fe59 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -12,6 +12,7 @@ { "after": true } - ] + ], + "prefer-arrow-callback": "error" } } diff --git a/lib/extend/tag.js b/lib/extend/tag.js index df66add124..ba8efef76e 100644 --- a/lib/extend/tag.js +++ b/lib/extend/tag.js @@ -69,7 +69,7 @@ function getContext(lines, errLine, location, type) { Array.prototype.push.apply(message, // get LINES_OF_CONTEXT lines surrounding `errLine` getContextLineNums(1, lines.length, errLine, LINES_OF_CONTEXT) - .map(function(lnNum) { + .map(lnNum => { const line = ' ' + lnNum + ' | ' + lines[lnNum - 1]; if (lnNum === errLine) { return colorize.bold(line); diff --git a/lib/plugins/tag/code.js b/lib/plugins/tag/code.js index e7cfd8a614..69700a1c60 100644 --- a/lib/plugins/tag/code.js +++ b/lib/plugins/tag/code.js @@ -52,7 +52,7 @@ function getHighlightOptions(config, arg) { let mark = []; if (rMark.test(arg)) { arg = arg.replace(rMark, (match, _mark) => { - mark = _mark.split(',').reduce(function getMarkedLines(prev, cur) { + mark = _mark.split(',').reduce((prev, cur) => { if (/-/.test(cur)) { let a = Number(cur.substr(0, cur.indexOf('-'))); let b = Number(cur.substr(cur.indexOf('-') + 1)); diff --git a/test/scripts/console/list_categories.js b/test/scripts/console/list_categories.js index 822bc312a1..1519533356 100644 --- a/test/scripts/console/list_categories.js +++ b/test/scripts/console/list_categories.js @@ -13,7 +13,7 @@ describe('Console list', () => { before(() => { const log = console.log; - sinon.stub(console, 'log').callsFake(function(...args) { + sinon.stub(console, 'log').callsFake((...args) => { return log.apply(log, args); }); }); diff --git a/test/scripts/console/list_page.js b/test/scripts/console/list_page.js index d4f2afd1c5..96cd89a26d 100644 --- a/test/scripts/console/list_page.js +++ b/test/scripts/console/list_page.js @@ -12,7 +12,7 @@ describe('Console list', () => { hexo.config.permalink = ':title/'; before(() => { const log = console.log; - sinon.stub(console, 'log').callsFake(function(...args) { + sinon.stub(console, 'log').callsFake((...args) => { return log.apply(log, args); }); }); diff --git a/test/scripts/console/list_post.js b/test/scripts/console/list_post.js index 96f424fdfb..6509e3751e 100644 --- a/test/scripts/console/list_post.js +++ b/test/scripts/console/list_post.js @@ -12,7 +12,7 @@ describe('Console list', () => { before(() => { const log = console.log; - sinon.stub(console, 'log').callsFake(function(...args) { + sinon.stub(console, 'log').callsFake((...args) => { return log.apply(log, args); }); }); diff --git a/test/scripts/console/list_tags.js b/test/scripts/console/list_tags.js index 50b38419f1..0b9d9247df 100644 --- a/test/scripts/console/list_tags.js +++ b/test/scripts/console/list_tags.js @@ -14,7 +14,7 @@ describe('Console list', () => { hexo.config.permalink = ':title/'; before(() => { const log = console.log; - sinon.stub(console, 'log').callsFake(function(...args) { + sinon.stub(console, 'log').callsFake((...args) => { return log.apply(log, args); }); }); From 33af2400f1452b9573714048c0ad01d5e91f838d Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Wed, 2 Oct 2019 11:18:59 +0100 Subject: [PATCH 30/43] style: revert config --- .eslintrc.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 9fb853fe59..57bd13b4a0 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -12,7 +12,6 @@ { "after": true } - ], - "prefer-arrow-callback": "error" + ] } } From a17a7e8e8e2ffc06eff2f0cb1634152fca8b2962 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 2 Oct 2019 19:44:34 +0200 Subject: [PATCH 31/43] chore(deps): bump hexo-cli from 2.0.0 to 3.0.0 (#3743) Bumps [hexo-cli](https://github.com/hexojs/hexo-cli) from 2.0.0 to 3.0.0. - [Release notes](https://github.com/hexojs/hexo-cli/releases) - [Commits](https://github.com/hexojs/hexo-cli/commits) Signed-off-by: dependabot-preview[bot] --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c293dce88f..962c8e04fb 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "bluebird": "^3.5.2", "chalk": "^2.4.1", "cheerio": "0.22.0", - "hexo-cli": "^2.0.0", + "hexo-cli": "^3.0.0", "hexo-front-matter": "^1.0.0", "hexo-fs": "^2.0.0", "hexo-i18n": "^1.0.0", From 71d10fd648b6d51c9039689b4acb9ed147fe38e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=B4=8D=C9=AA=E1=B4=8D=C9=AA?= <1119186082@qq.com> Date: Fri, 4 Oct 2019 22:30:22 +0800 Subject: [PATCH 32/43] refactor: ignore categories / tags with zero posts (#3624) --- lib/hexo/index.js | 10 ++++++++-- lib/plugins/helper/tagcloud.js | 3 --- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/hexo/index.js b/lib/hexo/index.js index 4060dc4228..065b7619d3 100644 --- a/lib/hexo/index.js +++ b/lib/hexo/index.js @@ -136,9 +136,15 @@ Hexo.prototype._bindLocals = function() { return db.model('Page').find(query); }); - locals.set('categories', () => db.model('Category')); + locals.set('categories', () => { + // Ignore categories with zero posts + return db.model('Category').filter(category => category.length); + }); - locals.set('tags', () => db.model('Tag')); + locals.set('tags', () => { + // Ignore tags with zero posts + return db.model('Tag').filter(tag => tag.length); + }); locals.set('data', () => { const obj = {}; diff --git a/lib/plugins/helper/tagcloud.js b/lib/plugins/helper/tagcloud.js index 9fd5bda421..d4ad0e3c75 100644 --- a/lib/plugins/helper/tagcloud.js +++ b/lib/plugins/helper/tagcloud.js @@ -36,9 +36,6 @@ function tagcloudHelper(tags, options) { tags = tags.sort(orderby, order); } - // Ignore tags with zero posts - tags = tags.filter(tag => tag.length); - // Limit the number of tags if (options.amount) { tags = tags.limit(options.amount); From e1167b7fc82e5ac799af3802d0ecf2a5fb349fa5 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Sun, 6 Oct 2019 18:04:31 +1030 Subject: [PATCH 33/43] style: no-var & prefer-const (#3745) * style: no-var & prefer-const * refactor: Array.from() - https://stackoverflow.com/a/38213213 * style: object spacing * refactor: while() push --- lib/extend/tag.js | 11 ++++------- test/scripts/hexo/multi_config_path.js | 6 +++--- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/lib/extend/tag.js b/lib/extend/tag.js index ba8efef76e..8dfe0a782c 100644 --- a/lib/extend/tag.js +++ b/lib/extend/tag.js @@ -47,13 +47,10 @@ const placeholder = '\uFFFC'; const rPlaceholder = /(?:<|<)!--\uFFFC(\d+)--(?:>|>)/g; function getContextLineNums(min, max, center, amplitude) { - var result = []; - var lbound = Math.max(min, center - amplitude); - var hbound = Math.min(max, center + amplitude); - for (var i = lbound; i <= hbound; i++) { - result.push(i); - } - + const result = []; + let lbound = Math.max(min, center - amplitude); + const hbound = Math.min(max, center + amplitude); + while (lbound <= hbound) result.push(lbound++); return result; } diff --git a/test/scripts/hexo/multi_config_path.js b/test/scripts/hexo/multi_config_path.js index 3247c5a3c9..3e105348d4 100644 --- a/test/scripts/hexo/multi_config_path.js +++ b/test/scripts/hexo/multi_config_path.js @@ -167,7 +167,7 @@ describe('config flag handling', () => { }); it('1 not found file warning absolute', () => { - let notFile = '/tmp/not_a_file.json'; + const notFile = '/tmp/not_a_file.json'; mcp(base, notFile).should.eql(pathFn.join(base, '_config.yml')); hexo.log.reader[0].type.should.eql('warning'); @@ -256,8 +256,8 @@ describe('config flag handling', () => { }); it('write multiconfig to specified path', () => { - let outputPath = osFn.tmpdir(); - let combinedPath = pathFn.join(outputPath, '_multiconfig.yml'); + const outputPath = osFn.tmpdir(); + const combinedPath = pathFn.join(outputPath, '_multiconfig.yml'); mcp(base, 'test1.yml', outputPath).should.not.eql(combinedPath); mcp(base, 'test1.yml,test2.yml', outputPath).should.eql(combinedPath); From 79ef191dfcc9313399249bbce7563efa9a377a68 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Fri, 23 Aug 2019 07:45:20 +0930 Subject: [PATCH 34/43] fix(open_graph): support IDN url --- lib/plugins/helper/open_graph.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/plugins/helper/open_graph.js b/lib/plugins/helper/open_graph.js index 0af4ef2c8b..a31cde5df3 100644 --- a/lib/plugins/helper/open_graph.js +++ b/lib/plugins/helper/open_graph.js @@ -90,6 +90,11 @@ function openGraphHelper(options = {}) { url = url.replace(/index\.html$/, ''); } + url = urlFn.format({ + protocol: urlFn.parse(url).protocol, + hostname: urlFn.parse(url).hostname, + pathname: encodeURI(urlFn.parse(url).pathname) + }); result += og('og:url', url, false); result += og('og:site_name', siteName); From 5043bac5f91b6efa317ee005f0745df13b3607e9 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Fri, 23 Aug 2019 08:17:51 +0930 Subject: [PATCH 35/43] test(open_graph): IDN handling --- test/scripts/helpers/open_graph.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/scripts/helpers/open_graph.js b/test/scripts/helpers/open_graph.js index 648046512e..d9c484a712 100644 --- a/test/scripts/helpers/open_graph.js +++ b/test/scripts/helpers/open_graph.js @@ -129,6 +129,19 @@ describe('open_graph', () => { hexo.config.pretty_urls.trailing_index = true; }); + it('url - IDN', () => { + const ctx = { + page: {}, + config: hexo.config, + is_post: isPost, + url: 'https://foô.com/bár' + }; + + const result = openGraph.call(ctx); + + result.should.contain(meta({property: 'og:url', content: 'https://xn--fo-9ja.com/b%C3%A1r'})); + }); + it('images - content', () => { const result = openGraph.call({ page: { From c6190ca0b2602ee464b255461c8fd8b217ab779f Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Fri, 23 Aug 2019 09:07:43 +0930 Subject: [PATCH 36/43] fix(open_graph): do not format empty url --- lib/plugins/helper/open_graph.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/plugins/helper/open_graph.js b/lib/plugins/helper/open_graph.js index a31cde5df3..a97436dae0 100644 --- a/lib/plugins/helper/open_graph.js +++ b/lib/plugins/helper/open_graph.js @@ -90,11 +90,13 @@ function openGraphHelper(options = {}) { url = url.replace(/index\.html$/, ''); } - url = urlFn.format({ - protocol: urlFn.parse(url).protocol, - hostname: urlFn.parse(url).hostname, - pathname: encodeURI(urlFn.parse(url).pathname) - }); + if (url) { + url = urlFn.format({ + protocol: urlFn.parse(url).protocol, + hostname: urlFn.parse(url).hostname, + pathname: encodeURI(urlFn.parse(url).pathname) + }); + } result += og('og:url', url, false); result += og('og:site_name', siteName); From d5fb012e841f3a0a1d77c156263e3221967e9697 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Wed, 25 Sep 2019 02:25:09 +0100 Subject: [PATCH 37/43] refactor: utilize encodeURL of hexo-util --- lib/plugins/helper/open_graph.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/plugins/helper/open_graph.js b/lib/plugins/helper/open_graph.js index a97436dae0..c3100a9ee6 100644 --- a/lib/plugins/helper/open_graph.js +++ b/lib/plugins/helper/open_graph.js @@ -2,7 +2,7 @@ const urlFn = require('url'); const moment = require('moment'); -const { escapeHTML, htmlTag, stripHTML } = require('hexo-util'); +const { encodeURL, escapeHTML, htmlTag, stripHTML } = require('hexo-util'); function meta(name, content, escape) { if (escape !== false && typeof content === 'string') { @@ -90,13 +90,7 @@ function openGraphHelper(options = {}) { url = url.replace(/index\.html$/, ''); } - if (url) { - url = urlFn.format({ - protocol: urlFn.parse(url).protocol, - hostname: urlFn.parse(url).hostname, - pathname: encodeURI(urlFn.parse(url).pathname) - }); - } + if (url) url = encodeURL(url); result += og('og:url', url, false); result += og('og:site_name', siteName); From 8bd3439421e2b50799d13e1ba3f804d599c94962 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Wed, 25 Sep 2019 03:25:59 +0100 Subject: [PATCH 38/43] fix(open_graph): htmlTag escapes html by default - https://github.com/hexojs/hexo-util/releases/tag/1.3.0 --- lib/plugins/helper/open_graph.js | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/lib/plugins/helper/open_graph.js b/lib/plugins/helper/open_graph.js index c3100a9ee6..54e134dd17 100644 --- a/lib/plugins/helper/open_graph.js +++ b/lib/plugins/helper/open_graph.js @@ -2,24 +2,16 @@ const urlFn = require('url'); const moment = require('moment'); -const { encodeURL, escapeHTML, htmlTag, stripHTML } = require('hexo-util'); - -function meta(name, content, escape) { - if (escape !== false && typeof content === 'string') { - content = escapeHTML(content); - } +const { encodeURL, htmlTag, stripHTML } = require('hexo-util'); +function meta(name, content) { return `${htmlTag('meta', { name, content })}\n`; } -function og(name, content, escape) { - if (escape !== false && typeof content === 'string') { - content = escapeHTML(content); - } - +function og(name, content) { return `${htmlTag('meta', { property: name, content @@ -70,7 +62,7 @@ function openGraphHelper(options = {}) { let result = ''; if (description) { - result += meta('description', description, false); + result += meta('description', description); } if (keywords) { @@ -91,15 +83,15 @@ function openGraphHelper(options = {}) { } if (url) url = encodeURL(url); - result += og('og:url', url, false); + result += og('og:url', url); result += og('og:site_name', siteName); if (description) { - result += og('og:description', description, false); + result += og('og:description', description); } if (language) { - result += og('og:locale', language, false); + result += og('og:locale', language); } images = images.map(path => { @@ -113,7 +105,7 @@ function openGraphHelper(options = {}) { }); images.forEach(path => { - result += og('og:image', path, false); + result += og('og:image', path); }); if (updated) { @@ -125,7 +117,7 @@ function openGraphHelper(options = {}) { result += meta('twitter:card', twitterCard); if (images.length) { - result += meta('twitter:image', images[0], false); + result += meta('twitter:image', images[0]); } if (options.twitter_id) { @@ -136,7 +128,7 @@ function openGraphHelper(options = {}) { } if (options.twitter_site) { - result += meta('twitter:site', options.twitter_site, false); + result += meta('twitter:site', options.twitter_site); } if (options.google_plus) { From e6ed3f829b8df43a187fcc31ba3d626b114976c4 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Wed, 25 Sep 2019 06:45:20 +0100 Subject: [PATCH 39/43] test(open_graph): avoid double-escaping --- test/scripts/helpers/open_graph.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/scripts/helpers/open_graph.js b/test/scripts/helpers/open_graph.js index d9c484a712..cffc4a63b4 100644 --- a/test/scripts/helpers/open_graph.js +++ b/test/scripts/helpers/open_graph.js @@ -10,6 +10,7 @@ describe('open_graph', () => { const isPost = require('../../../lib/plugins/helper/is').post; const tag = require('hexo-util').htmlTag; const Post = hexo.model('Post'); + const cheerio = require('cheerio'); function meta(options) { return tag('meta', options); @@ -591,7 +592,8 @@ describe('open_graph', () => { const result = openGraph.call(ctx); const keywords = 'optimize,web&<>"'/,site'; - result.should.contain(meta({name: 'keywords', content: keywords})); + const $ = cheerio.load(result, { decodeEntities: false }); + $('meta[name="keywords"]').attr('content').should.eql(keywords); }); it('og:locale - options.language', () => { From 62e6e5c259d6d85c705a1fe7f1e13b139bdd64d6 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Wed, 25 Sep 2019 07:13:50 +0100 Subject: [PATCH 40/43] fix(open_graph): url might be null --- lib/plugins/helper/open_graph.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/plugins/helper/open_graph.js b/lib/plugins/helper/open_graph.js index 54e134dd17..8fd03f8394 100644 --- a/lib/plugins/helper/open_graph.js +++ b/lib/plugins/helper/open_graph.js @@ -78,11 +78,12 @@ function openGraphHelper(options = {}) { result += og('og:type', type); result += og('og:title', title); - if (config.pretty_urls.trailing_index === false) { - url = url.replace(/index\.html$/, ''); + if (url) { + if (config.pretty_urls.trailing_index === false) { + url = url.replace(/index\.html$/, ''); + } + url = encodeURL(url); } - - if (url) url = encodeURL(url); result += og('og:url', url); result += og('og:site_name', siteName); From 02041eb705836d0c3c776a0abfb0fa4a5f9bc600 Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Mon, 7 Oct 2019 13:12:54 +0100 Subject: [PATCH 41/43] chore(deps): update hexo-util from ^1.3.1 to ^1.4.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 962c8e04fb..298392a387 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "hexo-fs": "^2.0.0", "hexo-i18n": "^1.0.0", "hexo-log": "^1.0.0", - "hexo-util": "^1.3.1", + "hexo-util": "^1.4.0", "js-yaml": "^3.12.0", "lodash": "^4.17.11", "micromatch": "^4.0.2", From 09ccc9f3f2ee48f09c4e9ac378c5efcc455f65be Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Mon, 7 Oct 2019 13:15:05 +0100 Subject: [PATCH 42/43] refactor: cheerio is no longer necessary - https://github.com/hexojs/hexo-util/pull/104 - Revert 19902892c6a3fa64ae716a1e1ef0c85ea9fe7865 --- test/scripts/helpers/open_graph.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/scripts/helpers/open_graph.js b/test/scripts/helpers/open_graph.js index cffc4a63b4..d9c484a712 100644 --- a/test/scripts/helpers/open_graph.js +++ b/test/scripts/helpers/open_graph.js @@ -10,7 +10,6 @@ describe('open_graph', () => { const isPost = require('../../../lib/plugins/helper/is').post; const tag = require('hexo-util').htmlTag; const Post = hexo.model('Post'); - const cheerio = require('cheerio'); function meta(options) { return tag('meta', options); @@ -592,8 +591,7 @@ describe('open_graph', () => { const result = openGraph.call(ctx); const keywords = 'optimize,web&<>"'/,site'; - const $ = cheerio.load(result, { decodeEntities: false }); - $('meta[name="keywords"]').attr('content').should.eql(keywords); + result.should.contain(meta({name: 'keywords', content: keywords})); }); it('og:locale - options.language', () => { From 6f7fe0c36b71f4240e3ffe6cd235f2b07644d25a Mon Sep 17 00:00:00 2001 From: curbengh <43627182+curbengh@users.noreply.github.com> Date: Mon, 7 Oct 2019 13:18:45 +0100 Subject: [PATCH 43/43] test(asset_img): attribute shouldn't be similar to value, unless it's boolean - https://github.com/hexojs/hexo-util/commit/622167f3cf98f08436b0fb0bc1a7bc7ec00904f4 --- test/scripts/tags/asset_img.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/scripts/tags/asset_img.js b/test/scripts/tags/asset_img.js index 0adc7e60cb..d8f0709c09 100644 --- a/test/scripts/tags/asset_img.js +++ b/test/scripts/tags/asset_img.js @@ -50,7 +50,7 @@ describe('asset_img', () => { }); it('default', () => { - assetImg('bar title').should.eql(''); + assetImg('bar "a title"').should.eql(''); }); it('with space', () => { @@ -60,13 +60,13 @@ describe('asset_img', () => { }); it('with alt and title', () => { - assetImgTag.call(post, ['bar', '"title"', '"alt"']) - .should.eql('alt'); + assetImgTag.call(post, ['bar', '"a title"', '"an alt"']) + .should.eql('an alt'); }); it('with width height alt and title', () => { - assetImgTag.call(post, ['bar', '100', '200', '"title"', '"alt"']) - .should.eql('alt'); + assetImgTag.call(post, ['bar', '100', '200', '"a title"', '"an alt"']) + .should.eql('an alt'); }); it('no slug', () => {