Help with "Tried to use templateContent too early" issue #2153
Replies: 8 comments 13 replies
-
@cfjedimaster How about something like this? eleventyConfig.addCollection("entriesBetter", function(collectionApi) {
const posts = [...collectionApi.getFilteredByTag("entries")];
return posts.map(post => {
const content = post.template.frontMatter?.content.trim();
// TODO: Probably do a check to confirm there isn't an existing `title` that we're overwriting here?
post.data.title = content.split("\n")[0];
return post;
});
}); A bit clumsy, but seemed to work for my simplified local test case. |
Beta Was this translation helpful? Give feedback.
-
Sorry, I got distracted by something else, but I also had this idea which uses const cheerio = require("cheerio"); // npm i cheerio -S
...
eleventyConfig.addCollection("entriesBetter", function(collectionApi) {
const posts = [...collectionApi.getFilteredByTag("entries")];
return posts.map(post => {
if (!post.data.title) {
const content = post.template.frontMatter?.content.trim();
const $ = cheerio.load(content);
post.data.title = $("h3").first().text();
if (!post.data.title) {
// Display a console warning if we weren't able to find an `<h3>` in the input file.
console.warn(`Unable to find "title" for ${post.inputPath}`);
}
}
return post;
});
}); |
Beta Was this translation helpful? Give feedback.
-
Back to my original idea… I wonder if you could write a custom script [outside of Eleventy] which would:
That way all your EJS templates would be fixed and have the expected frontmatter without needing to do expensive cheerio lookups on each build/deploy. |
Beta Was this translation helpful? Give feedback.
-
These are all good workarounds - and I appreciate them - but I'd like to focus on the original issue, or expectation at least. In |
Beta Was this translation helpful? Give feedback.
-
I'm facing the same issue here. I am attempting to access the content of the next element in my collection to be able to access its contents (eg. show a link with an image and the title of the next page). How would I go about achieving this. I thought to extend my collection, but at this time the frontmatter/content isn't fully parsed yet: // Module collection (custom sort by fileSlug)
eleventyConfig.addCollection("sortedModules", function (collectionApi) {
const allModules = collectionApi.getFilteredByTag("module");
const sortedModules = allModules
.sort((a, b) => {
return a.fileSlug - b.fileSlug;
})
.map((module, idx) => {
const nextModule = allModules[(idx + 1) % allModules.length];
return {
...module,
next_module: nextModule,
};
});
return sortedModules;
}); Does anyone have an idea how to achieve this. Is this the wrong mindset? |
Beta Was this translation helpful? Give feedback.
-
Here's another unwanted workaround, just to throw a log onto a fire. (LOL) const {inspect} = require("node:util");
module.exports = function (eleventyConfig) {
eleventyConfig.addCollection("entriesBetter", function(collectionApi) {
return collectionApi.getFilteredByTag("entries").map(i => {
// Hack for https://github.com/11ty/eleventy/blob/d1f48f77462d09d8b77ddcf0bbaa7faffb306e51/src/Template.js#L708-L710
i.checkTemplateContent = false;
console.log(i.templateContent); // undefined
// Only other place I immediately saw in my copious debugging output that had my h3 tag content.
const content = i.template.frontMatter.content;
const h3 = content.match(/<h3>(.*?)<\/h3>/i);
const heading = h3 ? h3[1] : "nO HeAdInG FoUnD";
console.log(heading);
// console.log(inspect(i, {sorted:true, depth:8}));
return i;
});
});
return {
dir: {
input: "src",
output: "www",
}
};
}; Kind of a trash fire answer/solution, but did bring up some interesting things… The real gem was if I hacked that I can inspect the page's early content via The rest of my shame lies in the RegExp parsing to pluck an Maybe in an ideal world that |
Beta Was this translation helpful? Give feedback.
-
Hi there, Came across the same thing; "Tried to use templateContent too early". I was creating a modified collection where I only pass the required data, of which templateContent is one of. I "fixed" this, by wrapping calling templateContent inside a function, like so: return {
content: function () { return item.templateContent },
// Other front matter data
}; Calling it inside the template like: {{ item.content() | safe }} Applied to your example, @cfjedimaster, would then look like this: eleventyConfig.addCollection("entriesBetter", function(collectionApi) {
return collectionApi.getFilteredByTag("entries").map(i => {
return {
content: function () { return i.templateContent; }
};
});
}); Hope it helps! |
Beta Was this translation helpful? Give feedback.
-
Looking a bit better on what is asked, I wonder if it wouldn't be faster to write a formatter or scraping script instead to add the frontmatter data to the top of those files? |
Beta Was this translation helpful? Give feedback.
-
I've got an old Jamstack site I'm migrating to Eleventy. It has a large collection of EJS files that do not have metadata. So for example, no title. But, for every file, the content begins with:
So I thought I'd build a collection based on the initial collection. I'd loop over every item, look at the template content, and just parse out the first h3. Kinda like so:
But doing so gives me the error about using the templateContent "too early". Is there a workaround for this?
Beta Was this translation helpful? Give feedback.
All reactions