Repository: pcardune/handlebars-loader

Issue:
Doesn't work with inline partials
If I try to require the following handlebars template using this loader, I get an error:

```
{{#*inline "toAttributes"}}
    {{#each this}}
        {{@key}}="{{this}}"
    {{/each}}
{{/inline}}

{{> toAttributes}}
```

The relevant stack from the error:

```
ERROR in ./public/pantry/page/index.hbs
Module build failed: Error: Partial 'toAttributes' not found
    at tryExtension (/Users/lzilioli/Projects/member-profile/node_modules/handlebars-loader/index.js:236:34)
    at /Users/lzilioli/Projects/member-profile/node_modules/handlebars-loader/index.js:246:11
    at next (/Users/lzilioli/Projects/member-profile/node_modules/handlebars-loader/index.js:189:20)
    at /Users/lzilioli/Projects/member-profile/node_modules/handlebars-loader/index.js:205:20
```


Hints from issue comments:
@lzilioli: I suspect this has to do with the fact that the handlebars.JavascriptCompiler is invoking nameLookup for these inline partials, but haven't had a chance to debug further. @pcardune do you have any input here?
@mAAdhaTTah: I got this working by providing empty default content:

```
{{#> toAttributes}}
{{/toAttributes}}
```
@mAAdhaTTah: I stand corrected. The above trick only works when the inline partial is defined in a separate file from where it's referenced.
@rafde: I had to remove creating the error instance [here](https://github.com/pcardune/handlebars-loader/blob/master/index.js#L241-L242).
It shouldn't error out if it can't find the partial, it should when running the code. I'd submit a PR but there is stuff in the contrib I don't feel like doing so I'll do it later when I get more time.
@michaeldzjap: I'm running into the same problem here. Would be nice if this could be fixed.
@EstherAF: +1, I would like to use inline partials in the same file too.
@minkyu-yi: As a workaround, use the `transform-loader` + `hbsfy`.

``` js
        loaders: [
            {
                test: /\.hbs$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'transform?hbsfy'
            },
            //.....
        ]
```
@skrolikowski: Here's another workaround, add your inline partial name (e.g. toAttributes ) to the the _ignorePartials_ query:

```
loaders: [
    {
        test: /\.html$/,
        loader: 'handlebars-loader',
        query: {
            ignorePartials: [ 'toAttributes' ],
        }
    },
    //...
]
```
@sualko: @pcardune can you look into this?

@skrolikowski your workaround works quite fine. Thanks.@pcardune: @sualko I don't have time to debug this right now, but if someone wants to submit a PR with a fix, I'd be more than happy to review/merge/release it.@the-stas: @lzilioli and @pcardune this one should be closed because issue already resolve in https://github.com/pcardune/handlebars-loader/commit/a8a9773824710d8e774a7388a10602bd10430bad ! in Jan 21, 2018 .@inkas: @the-stas This still seems to be failing with webpack 4.44.2 and handlebars-loader 1.7.1 Would really love to be able to use inline partials.@the-stas: @inkas works fine for webpack 4.41.5 and handlebars-loader 1.7.1 , even works with webpack 5.9.0 and handlebars-loader 1.7.1 @inkas: @the-stas 

My webpack handlebars-loader config looks like this
```
{
    test: /\.(hbs|handlebars)$/,
    loader: 'handlebars-loader',
    options: {
        partialDirs: [
            path.resolve(__dirname, 'src/templates/partials')
        ],
        helperDirs: [
            path.resolve(__dirname, 'src/assets/js/handlebars/helpers'),
            path.resolve(__dirname, 'src/templates/block-helpers')
        ],
    },
}
```
src/templates/partials/wrapper.hbs
```
<h2>{{> MyInlinePartial }}</h2>
```

src/templates/views/employees/index.hbs
```
{{#>wrapper}}
    {{#*inline "MyInlinePartial" }}
        Some text
    {{/inline}}
{{/wrapper}}
```

Error
```
ERROR in ./src/templates/partials/wrapper.hbs
Module build failed (from ./node_modules/handlebars-loader/index.js):
Error: Partial './MyInlinePartial' not found
    at tryExtension (C:\xampp\htdocs\project\node_modules\handlebars-loader\index.js:291:27)
    at C:\xampp\htdocs\project\node_modules\handlebars-loader\index.js:299:11
    at next (C:\xampp\htdocs\project\node_modules\handlebars-loader\index.js:241:20)
    at C:\xampp\htdocs\project\node_modules\handlebars-loader\index.js:257:20
    at C:\xampp\htdocs\project\node_modules\enhanced-resolve\lib\Resolver.js:213:14
    at C:\xampp\htdocs\project\node_modules\enhanced-resolve\lib\Resolver.js:285:5
    at eval (eval at create (C:\xampp\htdocs\project\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:15:1)
    at C:\xampp\htdocs\project\node_modules\enhanced-resolve\lib\UnsafeCachePlugin.js:44:7
    at C:\xampp\htdocs\project\node_modules\enhanced-resolve\lib\Resolver.js:285:5
    at eval (eval at create (C:\xampp\htdocs\project\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:15:1)
 @ ./src/templates/views/employees/index.hbs 16:41-78
 @ ./node_modules/html-webpack-plugin/lib/loader.js!./src/templates/views/employees/index.js
```

Am I doing something wrong?@the-stas: @inkas inline partial can be used only within the file where it define. In your case it can be used inly on `src/templates/views/employees/index.hbs` and probably it's definition can not be placed inside extend hbs syntax (but I'm not sure, haven't did that and do not check).@inkas: It seems to be working if I invoke the inline partial as a partial block.

src/templates/partials/wrapper.hbs
```
<h2>
  {{#> MyInlinePartial }}
    {{!-- MyInlinePartial content will be printed here --}}
  {{/MyInlinePartial}}
</h2>
```@AmadeusK525: Thanks @inkas, this is what got it working for me. It's a shame this wasn't properly fixed.

Solution patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 33e6fae..8a80c29 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 cdb0556..afbd084 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;



Test patch:
diff --git a/test/test.js b/test/test.js
index faba1e3..600bfcf 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 0000000..f5049d1
--- /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 0000000..3469294
--- /dev/null
+++ b/test/with-partial-block.handlebars
@@ -0,0 +1,3 @@
+{{#> non-existent}}
+  <div>Failover</div>
+{{/non-existent}}
\ No newline at end of file