From acae1cbe1b72ba42af851e8966424edcc9285372 Mon Sep 17 00:00:00 2001 From: MDLeom <43627182+curbengh@users.noreply.github.com> Date: Thu, 13 Aug 2020 12:43:49 +0000 Subject: [PATCH] feat: postAsset to prepend post's relative path --- README.md | 5 +++ lib/renderer.js | 15 ++++++-- test/index.js | 94 +++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 102 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 7b824b7..4166637 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ marked: headerIds: true lazyload: false prependRoot: false + postAsset: false external_link: enable: false exclude: [] @@ -55,6 +56,10 @@ marked: root: /blog/ ``` * `![text](/path/to/image.jpg)` becomes `` +- **postAsset** - Resolve post asset's image path to relative path and prepend root valuewhen [`post_asset_folder`](https://hexo.io/docs/asset-folders) is enabled. + * "image.jpg" is located at "/2020/01/02/foo/image.jpg", which is a post asset of "/2020/01/02/foo/". + * `![](image.jpg)` becomes `` + * Requires `prependRoot:` to be enabled. - **external_link** * **enable** - Open external links in a new tab. * **exclude** - Exclude hostname. Specify subdomain when applicable, including `www`. diff --git a/lib/renderer.js b/lib/renderer.js index 0ca933d..605b526 100644 --- a/lib/renderer.js +++ b/lib/renderer.js @@ -4,6 +4,7 @@ const marked = require('marked'); const { encodeURL, slugize, stripHTML, url_for, isExternalLink } = require('hexo-util'); const MarkedRenderer = marked.Renderer; const { parse } = require('url'); +const { join, relative } = require('path').posix; const anchorId = (str, transformOption) => { return slugize(str.trim(), {transform: transformOption}); @@ -87,6 +88,7 @@ class Renderer extends MarkedRenderer { if (!parse(href).hostname && !options.config.relative_link && options.prependRoot) { + if (options.path) href = join(options.path, href); href = url_for.call(options, href); } @@ -109,15 +111,24 @@ module.exports = function(data, options) { config: { url: this.config.url, root: this.config.root, - relative_link: this.config.relative_link + relative_link: this.config.relative_link, + post_asset_folder: this.config.post_asset_folder } }); + let path = ''; + if (this.config.post_asset_folder && this.config.marked.prependRoot && this.config.marked.postAsset) { + const Post = this.model('Post'); + const source = relative(this.source_dir, data.path); + const post = Post.findOne({ source }); + path = post ? post.path : ''; + } + // exec filter to extend renderer. const renderer = new Renderer(); this.execFilterSync('marked:renderer', renderer, {context: this}); return marked(data.text, Object.assign({ renderer - }, this.config.marked, options, siteCfg)); + }, this.config.marked, options, siteCfg, { path })); }; diff --git a/test/index.js b/test/index.js index b81e7a9..9bf3260 100644 --- a/test/index.js +++ b/test/index.js @@ -1,15 +1,23 @@ 'use strict'; require('chai').should(); -const { encodeURL, escapeHTML } = require('hexo-util'); +const { encodeURL, escapeHTML, url_for } = require('hexo-util'); const Hexo = require('hexo'); +const { join } = require('path').posix; describe('Marked renderer', () => { const hexo = new Hexo(__dirname, {silent: true}); - const ctx = Object.assign(hexo, { - config: { - marked: {} - } + const defaultCfg = JSON.parse(JSON.stringify(Object.assign(hexo.config, { + marked: {} + }))); + + before(async () => { + hexo.config.permalink = ':title'; + await hexo.init(); + }); + + beforeEach(() => { + hexo.config = JSON.parse(JSON.stringify(defaultCfg)); }); const r = require('../lib/renderer').bind(hexo); @@ -88,7 +96,7 @@ describe('Marked renderer', () => { it('should render headings without headerIds when disabled', () => { const body = '## hexo-server'; - ctx.config.marked.headerIds = false; + hexo.config.marked.headerIds = false; const result = r({text: body}); @@ -545,7 +553,7 @@ describe('Marked renderer', () => { `![](${urlB})` ].join('\n'); - const r = require('../lib/renderer').bind(ctx); + const r = require('../lib/renderer').bind(hexo); const result = r({text: body}); @@ -562,7 +570,7 @@ describe('Marked renderer', () => { '![a"b](http://bar.com/b.jpg "c>d")' ].join('\n'); - const r = require('../lib/renderer').bind(ctx); + const r = require('../lib/renderer').bind(hexo); const result = r({text: body}); @@ -579,9 +587,9 @@ describe('Marked renderer', () => { '![foo](/aaa/bbb.jpg)' ].join('\n'); - ctx.config.marked.lazyload = true; + hexo.config.marked.lazyload = true; - const r = require('../lib/renderer').bind(ctx); + const r = require('../lib/renderer').bind(hexo); const result = r({ text: body }); @@ -591,6 +599,72 @@ describe('Marked renderer', () => { ].join('\n')); }); + it('postAsset', async () => { + hexo.config.post_asset_folder = true; + hexo.config.marked = { + prependRoot: true, + postAsset: true + }; + const content = '![](foo.svg)'; + const path = join(__dirname, '_posts', 'foo.md'); + const post = { + title: 'foo', + slug: 'foo', + content + }; + await hexo.post.create(post); + + const result = r({ text: content, path }); + + console.log(result); + }); + + describe('postAsset', () => { + const Post = hexo.model('Post'); + + it('should prepend post path', async () => { + hexo.config.post_asset_folder = true; + hexo.config.marked = { + prependRoot: true, + postAsset: true + }; + + const asset = 'bar.svg'; + const content = `![](${asset})`; + const post = { + source: '_posts/foo.md', + slug: 'foo' + }; + const data = await Post.insert(post); + + const result = r({ text: content, path: data.full_source }); + result.should.eql(`
\n`); + + await Post.removeById(data._id); + }); + + it('should handle slash prefix', async () => { + hexo.config.post_asset_folder = true; + hexo.config.marked = { + prependRoot: true, + postAsset: true + }; + + const asset = '/bar.svg'; + const content = `![](${asset})`; + const post = { + source: '_posts/foo.md', + slug: 'foo' + }; + const data = await Post.insert(post); + + const result = r({ text: content, path: data.full_source }); + result.should.eql(`\n`); + + await Post.removeById(data._id); + }); + }); + describe('exec filter to extend', () => { it('should execute filter registered to marked:renderer', () => { const hexo = new Hexo(__dirname, {silent: true});