11ty / eleventy

A simpler site generator. Transforms a directory of templates (of varying types) into HTML.
https://www.11ty.dev/
MIT License
17.1k stars 494 forks source link

Render plugin: Global, Navigation, and frontmatter data interpolation #3090

Closed wcDogg closed 11 months ago

wcDogg commented 11 months ago

Operating system

Windows 11

Eleventy

2.0.1

Describe the bug

Hello :) I'm setting up my first project and LOVE Eleventy! Any help is much appreciated.

My templates are Nunjucks HTML. I find that:

Reproduction steps

  1. Clone: repo
  2. npm install
  3. npm run server
  4. View index.html

Expected behavior

{# test.njx  #}
<P>{{title}} | {{site.name}}</P>

{# Included in base.njk like this #}
{% renderFile "./src/_includes/test.njk" %}

{# Should render this  #}
<p>Page Title | Site Name</p>

{# Actually renders this with no errors or messages #}
<p> | </p>

Reproduction URL

https://github.com/wcDogg/eleventy-data-test

Screenshots

No response

pdehaan commented 11 months ago

I believe you're seeing https://www.11ty.dev/docs/plugins/render/#pass-in-data-1

"Both the eleventy and page variables are available inside of these templates by default. If you want to pass in additional data, you can do [by passing your data as the second argument to renderFile]."

Which gets tricky if you're trying to merge front matter data and global files and cascading data. I bet we can do it using eleventyComputed property, although it might not be super pretty. Let me see if I can create a simple test case.

pdehaan commented 11 months ago
---
# src/index.njk
title: Beep boop I'm some front matter.
---

<div>
{% renderFile "./src/_includes/test.njk", fullData %}
</div>

And my template data file, ./src/index.11tydata.js, with my eleventyComputed data looks like this:

// ./src/index.11tydata.js
module.exports = {
  eleventyComputed: {
    fullData: (data) => data,
  }
};

The ./src/_data/site.json file:

{
  "name": "11ty-3090"
}

Finally, my output file ./www/index.html, looks like this:

<div>
<p>Beep boop I'm some front matter. | 11ty-3090</p>
</div>

So takes all computed data from the data cascade and passes it along to the partial to be rendered. It isn't a great solution, if you know you only need a small fraction of the data, you're better off only passing the data you need vs potentially several hundred KB of unneeded global data file data; but it all depends on the site complexity and how much tweaking you want to do.

module.exports = {
  eleventyComputed: {
    // fullData: (data) => data,
    renderArgs({ title, site }) {
      return {
        title,
        site,
      };
    }
  },
};

And then change the renderFile call to use the optimized renderArgs computed data:

{% renderFile "./src/_includes/test.njk", renderArgs %}
wcDogg commented 11 months ago

@pdehaan - Thanks for the fast reply :)

My functional problem is, I can't put things like my site head tag or navigation in their own partial for reuse in multiple layouts.

If nothing else, the fact that globals aren't working tells me there's a problem.

wcDogg commented 11 months ago

Okay. I feel dumb. I wish Eleventy documentation did a better job of explaining include vs renderFile. That's 2 days gone :P

pdehaan commented 11 months ago

Not entirely relevant to this conversation, but that's also an interesting point with LiquidJS's deprecated include tag vs the newer render tag, where the render docs say:

Variable Scope

When a partial template is rendered, the code inside it can’t access its parent’s variables and its variables won’t be accessible by its parent. This encapsulation makes partials easier to understand and maintain.

Again, not relevant to the above Nunjucks specific conversation, but similar concepts I guess.