How to have *.11tydata.js file define different data for its different sub-folders? #2997
-
Hi, first time asker. Second time wrangling an 11ty site. 😅 I'm hoping to have a content folder structure like this:
The files (templates) in each of the 3 subdirs of The reason for this is I don't want to (can't?) have *.11tydata.js files in those directories. Ideally, I'd have I had hoped it'd be as simple as
But that wasn't the case. I'm guessing some sort of function? But what can I pass in and match against? Each directory also has a collection configured via CollectionsAPI so perhaps that? But… how? I tried
But that didn't do anything either (didn't error out either though heh) (Ideally, I wouldn't do this with if/else or case switching but just taking the collection name and inserting it. That alone would serve my purposes probably). I'm just getting my legs with JS, so, sorry if this is dead obvious! Thanks in advance for any help! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
I think it's possible, but it's overly complex and I'd suggest just using nested directory data files since it is a lot clearer and requires significantly less code/workarounds:
In my src/content/content.11tydata.js file I had to use module.exports = {
eleventyComputed: {
tags(data) {
// This will dynamically create `tags[]` like `["content", "studio", "about"]`
// (although see caveats about dynamically set tags not auto-creating collections).
return baseDirFromFilePathStem(data.page.filePathStem);
},
layout(data) {
// If the template specified a specific `layout` use that and exit early.
if (data.layout) {
return data.layout;
}
// `baseDirFromFilePathStem()` will return at most the first 4 directories/files,
// but we only want the last one.
const _layout = baseDirFromFilePathStem(data.page.filePathStem).at(-1);
switch (_layout) {
case "about":
case "readings":
case "writing":
return _layout;
}
// HACK: Fall back to a default template if we didn't get our expected layout.
return "base";
},
permalink(data) {
// Had to special case this because sometimes your `page.filePathStem` is
// `./src/content/studio/readings/index` which was causing unwanted filenames like
// `www/content/studio/readings/index/index.php`.
if (data.page.filePathStem.endsWith("/index")) {
return `${data.page.filePathStem}.php`;
}
return `${data.page.filePathStem}/index.php`;
}
},
};
function baseDirFromFilePathStem(filePathStem = "") {
return filePathStem.split("/", 4).filter(Boolean);
} But it gets weird fast since the site started breaking when I added a src/content/index.njk file since then it starts looking for a layout file named "_includes/layouts/index.njk" which didn't exist. So then I needed to do an explicit check for expected layouts based on directories and then default to a fallback layout. /**
* @param {import("@11ty/eleventy/src/UserConfig")} eleventyConfig
* @returns {ReturnType<import("@11ty/eleventy/src/defaultConfig")>}
*/
module.exports = function (eleventyConfig) {
// Add layout alias for "_includes/layouts/base.njk" which is our default layout and is
// extended by _includes/layouts/about.njk, etc.
eleventyConfig.addLayoutAlias("base", "layouts/base.njk");
["about", "readings", "writing"].forEach(dir => {
// Alias a layout named "about" to "_includes/layouts/about.njk".
eleventyConfig.addLayoutAlias(dir, `layouts/${dir}.njk`);
// Manually create our custom collections based on dynamically set tags.
// This will create collections named "about" based on templates that have both "content" and "about" tags.
eleventyConfig.addCollection(dir, collectionApi => collectionApi.getFilteredByTags("content", dir));
});
return {
dir: {
input: "src",
output: "www",
}
};
}; Sample repo: https://github.com/pdehaan/11ty-2997 Build log: [11ty] Writing www/content/index.php from ./src/content/index.njk
[11ty] Writing www/content/studio/readings/books/index.php from ./src/content/studio/readings/books.njk
[11ty] Writing www/content/studio/readings/index.php from ./src/content/studio/readings/index.njk
[11ty] Writing www/content/studio/about/index.php from ./src/content/studio/about/index.njk
[11ty] Writing www/content/studio/writing/index.php from ./src/content/studio/writing/index.njk
[11ty] Wrote 5 files in 0.04 seconds (v2.0.1) tree -A --gitignore.
├── eleventy.config.js
├── package-lock.json
├── package.json
├── src/
│ ├── _includes/
│ │ └── layouts/
│ │ ├── about.njk
│ │ ├── base.njk
│ │ ├── readings.njk
│ │ └── writing.njk
│ └── content/
│ ├── content.11tydata.js
│ ├── index.njk
│ └── studio/
│ ├── about/
│ │ └── index.njk
│ ├── readings/
│ │ ├── books.njk
│ │ └── index.njk
│ └── writing/
│ └── index.njk
└── www/
└── content/
├── index.php
└── studio/
├── about/
│ └── index.php
├── readings/
│ ├── books/
│ │ └── index.php
│ └── index.php
└── writing/
└── index.php
15 directories, 18 files |
Beta Was this translation helpful? Give feedback.
I think it's possible, but it's overly complex and I'd suggest just using nested directory data files since it is a lot clearer and requires significantly less code/workarounds:
In my src/content/content.11tydata.js file I had to use
eleventyComputed
and then try and infer the directory from thefilePathStem
, and then dynamically set thetags[]
,layout
, andpermalink
: