Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Global import of macros fails in Eleventy 3.0.0-alpha.14 #3345

Closed
groenroos opened this issue Jul 3, 2024 · 7 comments
Closed

Global import of macros fails in Eleventy 3.0.0-alpha.14 #3345

groenroos opened this issue Jul 3, 2024 · 7 comments

Comments

@groenroos
Copy link

Operating system

macOS Sonoma 14.4.1

Eleventy

3.0.0-alpha.14

Describe the bug

Using the technique described in this comment to load common macros globally for each Nunjucks and Markdown template. It works without errors in Eleventy 2.x.

However, on Eleventy 3.0.0-alpha.14, this technique quits the build with the following error:

[11ty] Unfortunately you’re using code that monkey patched some Eleventy internals and it isn’t async-friendly. Change your code to use the async `read()` method on the template instead! (via Error)

My understanding of the TemplateContent class (or other Eleventy internals) is limited, but I attempted to adapt it to use the advertised read() method:

const frontMatter = await item.template.read();
frontMatter.content = `${macroImport}\n${frontMatter.content}`;
item.template.frontMatter = frontMatter;

However, this does not appear to make the components available in Markdown files. As a test, I deleted the few Markdown pages that require components, and it then fails by confusingly claiming the collection is already defined (regardless of what the collection is named):

[ELEVENTY] [11ty] 1. Having trouble rendering liquid template ./site/src/blog/example-blog-post-slug.md (via TemplateContentRenderError)
[ELEVENTY] [11ty] 2. Error in your Eleventy config file '.eleventy.js'., file:./site/src/blog/example-blog-post-slug.md, line:18, col:1 (via RenderError)
[ELEVENTY] [11ty] 3. Error in your Eleventy config file '.eleventy.js'. (via EleventyConfigError)
[ELEVENTY] [11ty] 4. config.addCollection(everything) already exists. Try a different name for your collection. (via UserConfigError)

Reproduction steps

  1. Load a macro file globally using this technique
  2. Attempt to build with Eleventy 3.0.0-alpha.14
  3. Build will fail

Expected behavior

Either the build should succeed, or an alternative pattern should be established for loading template macros globally such that they are available in every template

Reproduction URL

No response

Screenshots

No response

@zachleat
Copy link
Member

zachleat commented Jul 5, 2024

Somewhat related to #188—though this request is limited to collection entries I think!

This seems to work for me:

eleventyConfig.addCollection("userCollection", async function (collection) {
  let c = collection.getFilteredByTag("posts");
  for(let item of c) {
    const frontMatter = await item.template.read();
    frontMatter.content = `lol\n${frontMatter.content}`;
    item.template.frontMatter = frontMatter;
  }
  return c;
});

zachleat added a commit that referenced this issue Jul 5, 2024
@zachleat zachleat added the waiting-to-close Issue that is probably resolved, waiting on OP confirmation. label Jul 5, 2024
@groenroos
Copy link
Author

groenroos commented Jul 6, 2024

Somewhat related to #188—though this request is limited to collection entries I think!

I reckon doing it via an (essentially unfiltered) collection is just a way to apply a template fragment to every page. It does unnecessarily "pollute" the collections with this dummy collection. Additionally, this collection approach does have the downside that these macros still aren't automatically available within layouts or includes.

Therefore, I think I'd ultimately personally prefer it if there was a dedicated feature to define global macros such that they are available on every page, include, and layout, without the need for a dummy collection like this.

Thanks for the snippet! I tried a very similar approach, but I didn't get far; I've set up a demo repo:

https://github.com/groenroos/eleventy-global-macro

Each subfolder has the same demo site on different versions of Eleventy, with your async read() approach in the 3.0.0 folder. The build currently fails due to an undefined macro, as though the injected import for component.njk hadn't been computed at all;

[11ty] Problem writing Eleventy templates: (more in DEBUG output)
[11ty] 1. Having trouble rendering njk template ./nunjucks.njk (via TemplateContentRenderError)
[11ty] 2. (./nunjucks.njk) [Line 2, Column 12]
[11ty]   Error: Unable to call `component`, which is undefined or falsey (via Template render error)
[11ty]
[11ty] Original error stack trace: Template render error: (./nunjucks.njk) [Line 2, Column 12]
[11ty]   Error: Unable to call `component`, which is undefined or falsey
[11ty]     at Object._prettifyError (/eleventy-global-macro/eleventy-3.0.0/node_modules/nunjucks/src/lib.js:32:11)
[11ty]     at /eleventy-global-macro/eleventy-3.0.0/node_modules/nunjucks/src/environment.js:464:19
[11ty]     at Template.root [as rootRenderFunc] (eval at _compile (/eleventy-global-macro/eleventy-3.0.0/node_modules/nunjucks/src/environment.js:527:18), <anonymous>:19:3)
[11ty]     at Template.render (/eleventy-global-macro/eleventy-3.0.0/node_modules/nunjucks/src/environment.js:454:10)
[11ty]     at file:///eleventy-global-macro/eleventy-3.0.0/node_modules/@11ty/eleventy/src/Engines/Nunjucks.js:426:10
[11ty]     at new Promise (<anonymous>)
[11ty]     at file:///eleventy-global-macro/eleventy-3.0.0/node_modules/@11ty/eleventy/src/Engines/Nunjucks.js:425:11
[11ty]     at Template._render (file:///eleventy-global-macro/eleventy-3.0.0/node_modules/@11ty/eleventy/src/TemplateContent.js:588:25)
[11ty]     at async TemplateMap.populateContentDataInMap (file:///eleventy-global-macro/eleventy-3.0.0/node_modules/@11ty/eleventy/src/TemplateMap.js:537:7)
[11ty]     at async TemplateMap.cache (file:///eleventy-global-macro/eleventy-3.0.0/node_modules/@11ty/eleventy/src/TemplateMap.js:444:3)
[11ty] Wrote 0 files in 0.06 seconds (v3.0.0-alpha.14)

This is the same behaviour that I get in my production repo; I initially thought it was a specific issue with using this technique in Markdown files (as my prod repo fell over on a Markdown page first), but this demo repo seems to fail with the Nunjucks template, too.

@zachleat zachleat removed the waiting-to-close Issue that is probably resolved, waiting on OP confirmation. label Jul 11, 2024
@zachleat zachleat added this to the Eleventy 3.0.0 milestone Jul 11, 2024
zachleat added a commit that referenced this issue Jul 11, 2024
@zachleat
Copy link
Member

Rather than hack around this one, I just added another API here to do this officially:

#188 (comment)

I tested this with success in your repro repo, thanks!

export default function(eleventyConfig) {
	eleventyConfig.addPreprocessor("macro-inject", ".njk,.md", (data, content) => {
		return `{%- from "component.njk" import component with context -%}\n` + content;
	});
}

@zachleat
Copy link
Member

Shipping with 3.0.0-alpha.17

@groenroos
Copy link
Author

@zachleat Rather than hack around this one, I just added another API here to do this officially:

That looks fantastic! Thank you, can't wait to try it out! 🥳

Does this method inject it into layouts and templates too, or just posts? 👀

@zachleat
Copy link
Member

Any template files—not layouts.

@groenroos
Copy link
Author

Can confirm that this is resolved in Eleventy 3.0.0-alpha.17 as per the addPreprocessor snippet above! Thank you! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants