Search code examples
nunjucksmetalsmith

Using nunjucks includes with Metalsmith-in-place causing rendering error


I'am using Metalsmith with Nunjucks to create a static website.

I have no issue creating a blog-like website, meaning creating a layout in which I could wrap some markdown content, using the metalsmith-layout plugin.

But I would like to create some views that :

  • use a layout (with front-matter or with an extends method)
  • use some hand-made components / partials / macros

For instance, an index.njk :

{% extends "layouts/base.njk" %}

{% block content %}

Hello World!

{% include components/test1.njk %}

{% include components/test2.njk %}

{% include components/test3.njk %}

{% endblock %}

I tried to use the metalsmisth-in-place plugin with :

.use(inplace({
    engineOptions: {
        path: __dirname + '/src/templating'
    }
})

but I have a an error : The Transform "nunjucks" does not support rendering synchronously

It seems that inplace() cannot render the include properly...

Any idea ?


Solution

  • Ok, I had some great answer and explanation on the metalsmith slack.

    First, the folder structure should be something like:

    layouts/
        base.njk
    components/
        test.njk
    partials/
        head.njk
    src/
        index.njk
    

    The reason is that the src folder should only gather the main content, all the nunjucks files are only adding to this content.

    Then, with this configuration, a simple .use(inplace()) is enough. A directory option could be added if the directory is different from ./layouts.

    With this set up, this index.njk works fine:

    {% extends "./layouts/base.njk" %}
    
    {% block content %}
    
    Hello World!
    {% include './components/test.njk' %}
    
    {% endblock %}
    

    With a base.njk layout being:

    <!doctype html>
    <html class="" lang="">
    
      {% include '../partials/head.njk' %}
    
      <body>
    
        {% block content %}{% endblock %}
    
      </body>
    
    </html>
    

    Be careful however, as I have been told:

    • the files from the src folder are transformed in the metalsmith files object and thus are read from there, meaning in the memory and not directly from the disk. It means that nunjucks cannot resolve relative path inside of this folder, that's why the include in the index.njk has an absolute path: './components/test.njk'
    • the files outside the src folder are not transformed in the metalsmith files object and thus are read directly from the disk. In this case, nunjucks can resolve relative path, that's why the include has such a path '../partials/head.njk'

    Hope I explain it and understood it well^^

    Thanks a lot to "ismay" for taking some times to help me on the Metalsmith slack.