-
-
Notifications
You must be signed in to change notification settings - Fork 13
Description
What is the problem
When :
- a data (in the data cascade) and filter have the same name.
- and we are in a in a webc file
=> we cannot access the data value directly in webc.
Note : This works as expected in njk files.
I have investigated in the source code and found a work around that seems fine but not documented anywhere. Maybe the fix to this problem is to simply document it somewhere but why it happens it also interesting.
PS: English not my native langage 😅, sorry for the mistakes i make.
TL;DR :
In njk the syntax is unambiguous eleventyNavigation
is clearly a data while here collections.all | eleventyNavigation
it is cleary a filter function. In webc the syntax is eleventyNavigation
for the data and eleventyNavigation(collections.all)
and it it resolve via a node vm. This is ambiguous because in both case this is considered the same identifier. In the context given to the vm eleventyNavigation
filter function have overridden the data from cascade so it always resolve to the filter.
Workaround: Inspecting the context we can see that it has a $data
property with the data not overridden. We can use $data.eleventyNavigation
instead of eleventyNavigation
when we want to access eleventyNavigation
data.
Contexte : what is not working
For context, I was trying to debug eleventyNavigation
value for a page, I was succeeding reading it in a njk template but when converting it to webc it was not working anymore.
In njk the following was working :
<pre><code>{{ eleventyNavigation | dump(2) | safe }}</code></pre>
but translating it to webc was not working (with a custom dump filter since it does not exist by default in webc) :
<pre><code @raw="dump(eleventyNavigation, 2)"></code></pre>
This is because eleventyNavigation
can be resolved to the data from the cascade or the filter with the same name. In njk it is able to make the difference while in webc it is not. This is because in webc expression are resolved using a node vm and a context object. Context is a proxy object that proxy to the data cascade. However in the data cascade filters overrides data with the same name.
That said, I've found that a copy of the data is kept in a $data
property of the data object before filters and other things are applied. So we can work around this using this non standard, non documented $data
property, like this :
<pre><code @raw="dump($data.eleventyNavigation, 2)"></code></pre>
Resolving this ?
I was not able to find a way to get the same behavior as in the njk files due to the vm proxy usage. Maybe documenting and making the $data
property part of the public spec is a correct way of addressing this issue but I don't know the implications.
Reproduce to test
Let me give you a simple project to reproduce and test this : i will use the @11ty/eleventy-navigation
example since that is how I found the problem.
So first step is to init project :
npm init -y
npm install @11ty/eleventy @11ty/eleventy-plugin-webc @11ty/eleventy-navigation --save-dev
Here is a config with a dump filter (~same as default nunjucks "dump" filter because it does not exist for webc) :
const eleventyNavigationPlugin = require("@11ty/eleventy-navigation");
const pluginWebc = require("@11ty/eleventy-plugin-webc");
module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(eleventyNavigationPlugin);
eleventyConfig.addPlugin(pluginWebc, {
components: ["./_includes/components/*.webc"],
});
eleventyConfig.addFilter("dump", function (obj, space) {
return JSON.stringify(obj, null, space) || "undefined";
});
return {
templateFormats: ["html", "webc", "njk"]
};
};
Create a page those pages:
index.njk :
---
tags: ["tag1", "tag2"]
eleventyNavigation:
key: njk
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
{{ collections.all | eleventyNavigation | eleventyNavigationToHtml | safe }}
<h1>NKJ</h1>
<pre><code>{{ tags | dump | safe }}</code></pre>
<hr>
<pre><code>{{ eleventyNavigation | dump(2) | safe }}</code></pre>
<hr>
</body>
</html>
webc.webc :
---
tags: ["tag1", "tag2"]
eleventyNavigation:
key: webc
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<nav @raw="eleventyNavigationToHtml(eleventyNavigation(collections.all))"></nav>
<h1>WEBC</h1>
<pre><code @raw="dump(tags)"></code></pre>
<hr>
<pre><code @raw="dump(eleventyNavigation, 2)"></code></pre>
<hr>
</body>
</html>
webc_fix.webc :
---
tags: ["tag1", "tag2"]
eleventyNavigation:
key: webc
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<nav @raw="eleventyNavigationToHtml(eleventyNavigation(collections.all))"></nav>
<h1>WEBC</h1>
<pre><code @raw="dump(tags)"></code></pre>
<hr>
<pre><code @raw="dump(eleventyNavigation, 2)"></code></pre>
<hr>
</body>
</html>
Start the project :
npx @11ty/eleventy --serve