diff --git a/CHANGELOG.md b/CHANGELOG.md index 33e6fae47..8a80c2907 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,8 @@ ## [Unreleased] -### Added -- Your feature here! +### Fixed +- Fixed resolving of inline partials and partial blocks with failover content (#106, #135) ## [1.6.0] - 2017-09-01 ## diff --git a/index.js b/index.js index cdb05560f..afbd08489 100644 --- a/index.js +++ b/index.js @@ -136,6 +136,26 @@ module.exports = function(source) { hb.JavaScriptCompiler = MyJavaScriptCompiler; + // Define custom visitor for further template AST parsing + var Visitor = handlebars.Visitor; + function InternalBlocksVisitor() { + this.partialBlocks = []; + this.inlineBlocks = []; + } + + InternalBlocksVisitor.prototype = new Visitor(); + InternalBlocksVisitor.prototype.PartialBlockStatement = function(partial) { + this.partialBlocks.push(partial.name.original); + Visitor.prototype.PartialBlockStatement.call(this, partial); + }; + InternalBlocksVisitor.prototype.DecoratorBlock = function(partial) { + if (partial.path.original === 'inline') { + this.inlineBlocks.push(partial.params[0].value); + } + + Visitor.prototype.DecoratorBlock.call(this, partial); + }; + // This is an async loader var loaderAsyncCallback = this.async(); @@ -167,16 +187,23 @@ module.exports = function(source) { // Precompile template var template = ''; + // AST holder for current template + var ast = null; + + // Compile options + var opts = assign({ + knownHelpersOnly: !firstCompile, + // TODO: Remove these in next major release + preventIndent: !!query.preventIndent, + compat: !!query.compat + }, precompileOptions, { + knownHelpers: knownHelpers, + }); + try { if (source) { - template = hb.precompile(source, assign({ - knownHelpersOnly: !firstCompile, - // TODO: Remove these in next major release - preventIndent: !!query.preventIndent, - compat: !!query.compat - }, precompileOptions, { - knownHelpers: knownHelpers, - })); + ast = hb.parse(source, opts); + template = hb.precompile(ast, opts); } } catch (err) { return loaderAsyncCallback(err); @@ -286,7 +313,19 @@ module.exports = function(source) { } else { partialResolver(request, function(err, resolved){ if(err) { - return partialCallback(err); + var visitor = new InternalBlocksVisitor(); + + visitor.accept(ast); + + if ( + visitor.inlineBlocks.indexOf(request) !== -1 || + visitor.partialBlocks.indexOf(request) !== -1 + ) { + return partialCallback(); + } else { + return partialCallback(err); + } + } foundPartials[partial] = resolved; needRecompile = true; diff --git a/test/test.js b/test/test.js index faba1e36e..600bfcf07 100644 --- a/test/test.js +++ b/test/test.js @@ -542,4 +542,18 @@ describe('handlebars-loader', function () { }); }); + it('should use failover content of the partial block if it refers to non-existent partial', function (done) { + testTemplate(loader, './with-partial-block.handlebars', {}, function (err, output, require) { + assert.ok(output, 'generated output'); + done(); + }); + }); + + it('should recognize and render inline partials', function (done) { + testTemplate(loader, './with-inline-partial.handlebars', {}, function (err, output, require) { + assert.ok(output, 'generated output'); + done(); + }); + }); + }); diff --git a/test/with-inline-partial.handlebars b/test/with-inline-partial.handlebars new file mode 100644 index 000000000..f5049d153 --- /dev/null +++ b/test/with-inline-partial.handlebars @@ -0,0 +1,5 @@ +{{#*inline "printFoo"}} + Foo +{{/inline}} + +{{> printFoo}} \ No newline at end of file diff --git a/test/with-partial-block.handlebars b/test/with-partial-block.handlebars new file mode 100644 index 000000000..346929497 --- /dev/null +++ b/test/with-partial-block.handlebars @@ -0,0 +1,3 @@ +{{#> non-existent}} +
Failover
+{{/non-existent}} \ No newline at end of file