diff --git a/README.md b/README.md index 8ad7a36..bb8f5b3 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ marked: autolink: true sanitizeUrl: false headerIds: true + prependRoot: false ``` - **gfm** - Enables [GitHub flavored markdown](https://help.github.com/articles/github-flavored-markdown) @@ -42,6 +43,13 @@ marked: - **autolink** - Enable autolink for URLs. E.g. `https://hexo.io` will become `https://hexo.io`. - **sanitizeUrl** - Remove URLs that start with `javascript:`, `vbscript:` and `data:`. - **headerIds** - Insert header id, e.g. `

text

`. Useful for inserting anchor link to each paragraph with a heading. +- **headerIds** - Insert header id, e.g. `

text

`. Useful for inserting anchor link to each paragraph with a heading. +- **prependRoot** - Prepend root value to (internal) image path. + * Example `_config.yml`: + ``` yml + root: /blog/ + ``` + * `![text](/path/to/image.jpg)` becomes `text` ## Extras diff --git a/index.js b/index.js index aa1605c..6c75006 100644 --- a/index.js +++ b/index.js @@ -13,7 +13,9 @@ hexo.config.marked = Object.assign({ modifyAnchors: '', autolink: true, sanitizeUrl: false, - headerIds: true + headerIds: true, + // TODO: enable prependRoot by default in v3 + prependRoot: false }, hexo.config.marked); hexo.extend.renderer.register('md', 'html', renderer, true); diff --git a/lib/renderer.js b/lib/renderer.js index 61f9fb3..c67103c 100644 --- a/lib/renderer.js +++ b/lib/renderer.js @@ -2,8 +2,9 @@ const marked = require('marked'); const stripIndent = require('strip-indent'); -const { stripHTML, highlight, slugize } = require('hexo-util'); +const { stripHTML, highlight, slugize, encodeURL, url_for } = require('hexo-util'); const MarkedRenderer = marked.Renderer; +const { parse } = require('url'); function Renderer() { MarkedRenderer.apply(this); @@ -82,6 +83,16 @@ Renderer.prototype.paragraph = text => { return `

${text}

\n`; }; +// Prepend root to image path +Renderer.prototype.image = function(href, title, text) { + if (!parse(href).hostname && !this.options.config.relative_link + && this.options.prependRoot) { + href = url_for.call(this.options, href); + } + + return `${text}`; +}; + marked.setOptions({ langPrefix: '', highlight(code, lang) { @@ -94,7 +105,14 @@ marked.setOptions({ }); module.exports = function(data, options) { + const url_forCfg = Object.assign({}, { + config: { + root: this.config.root, + relative_link: this.config.relative_link + } + }); + return marked(data.text, Object.assign({ renderer: new Renderer() - }, this.config.marked, options)); + }, this.config.marked, options, url_forCfg)); }; diff --git a/package.json b/package.json index 5f1f25b..2c9bba4 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,8 @@ ], "license": "MIT", "dependencies": { - "hexo-util": "^1.0.1", + "hexo": "^3.9.0", + "hexo-util": "^1.3.0", "marked": "^0.7.0", "strip-indent": "^3.0.0" }, diff --git a/test/index.js b/test/index.js index 169b9b9..a3b99ad 100644 --- a/test/index.js +++ b/test/index.js @@ -191,4 +191,75 @@ describe('Marked renderer', () => { ].join('\n')); }); }); + + describe('prependRoot option tests', () => { + const body = [ + '![](/bar/baz.jpg)', + '![foo](/aaa/bbb.jpg)' + ].join('\n'); + + const renderer = require('../lib/renderer'); + + const ctx = { + config: { + marked: { + prependRoot: false + }, + root: '/blog/', + relative_link: false + } + }; + + it('should not modify image path with default option', () => { + const r = renderer.bind(ctx); + const result = r({text: body}); + + result.should.eql([ + '

', + 'foo

\n' + ].join('\n')); + }); + + it('should not modify image path when enable relative_link', () => { + ctx.config.relative_link = true; + const r = renderer.bind(ctx); + const result = r({text: body}); + + result.should.eql([ + '

', + 'foo

\n' + ].join('\n')); + + ctx.config.relative_link = false; + }); + + it('should prepend image path with root', () => { + ctx.config.marked.prependRoot = true; + const r = renderer.bind(ctx); + const result = r({text: body}); + + result.should.eql([ + '

', + 'foo

\n' + ].join('\n')); + ctx.config.marked.prependRoot = false; + }); + }); + + it('should encode image url', () => { + const body = [ + '![](/foo/bár.jpg)', + '![](http://fóo.com/bar.jpg)' + ].join('\n'); + + const renderer = require('../lib/renderer'); + const r = renderer.bind(ctx); + + const result = r({text: body}); + + result.should.eql([ + '

', + '

\n' + ].join('\n')); + }); });