diff --git a/lib/extend/tag.js b/lib/extend/tag.js index 3ad227dc0b..1b167565c1 100644 --- a/lib/extend/tag.js +++ b/lib/extend/tag.js @@ -1,7 +1,7 @@ 'use strict'; const { stripIndent } = require('hexo-util'); -const { cyan } = require('chalk'); +const { cyan, magenta, red } = require('chalk'); const { Environment } = require('nunjucks'); const Promise = require('bluebird'); const placeholder = '\uFFFC'; @@ -129,7 +129,7 @@ const LINES_OF_CONTEXT = 5; const getContext = (lines, errLine, location, type) => { const message = [ - location + ' ' + type, + location + ' ' + red(type), cyan(' ===== Context Dump ====='), cyan(' === (line number probably different from source) ===') ]; @@ -158,14 +158,17 @@ const getContext = (lines, errLine, location, type) => { * @param {string} str string input for Nunjucks * @return {Error} New error object with embedded context */ -const formatNunjucksError = (err, input) => { +const formatNunjucksError = (err, input, source = '') => { const match = err.message.match(/Line (\d+), Column \d+/); if (!match) return err; const errLine = parseInt(match[1], 10); if (isNaN(errLine)) return err; // trim useless info from Nunjucks Error - const splited = err.message.replace('(unknown path)', '').split('\n'); + const splited = err.message.replace('(unknown path)', () => { + if (source) return magenta(source); + return ''; + }).split('\n'); const e = new Error(); e.name = 'Nunjucks Error'; @@ -222,12 +225,15 @@ class Tag { if (env.hasExtension(name)) env.removeExtension(name); } - render(str, options, callback) { + render(str, options = {}, callback) { if (!callback && typeof options === 'function') { callback = options; options = {}; } + // Get path of post from source + const source = options.source ? options.source : ''; + const cache = []; const escapeContent = str => ``; @@ -235,7 +241,7 @@ class Tag { str = str.replace(/
[\s\S]*?<\/code><\/pre>/gm, escapeContent); return Promise.fromCallback(cb => { this.env.renderString(str, options, cb); }) - .catch(err => Promise.reject(formatNunjucksError(err, str))) + .catch(err => Promise.reject(formatNunjucksError(err, str, source))) .then(result => result.replace(rPlaceholder, (_, index) => cache[index])) .asCallback(callback); } diff --git a/test/scripts/extend/tag_errors.js b/test/scripts/extend/tag_errors.js index 5f408e4548..1b616f2cfc 100644 --- a/test/scripts/extend/tag_errors.js +++ b/test/scripts/extend/tag_errors.js @@ -102,4 +102,26 @@ describe('Tag Errors', () => { assertNunjucksError(err, 2, 'expected variable end'); } }); + + it('source file path', async () => { + const source = '_posts/hello-world.md'; + const tag = new Tag(); + + tag.register('test', + (args, content) => {}, + { ends: true }); + + const body = [ + '{% test %}', + ' {{docker ps -aq | map docker inspect -f "{{.Name}} {{.Mounts}}"}}', + '{% endtest %}' + ].join('\n'); + + try { + // Add { source } as option + await tag.render(body, { source }); + } catch (err) { + err.message.should.contains(source); + } + }); });