Skip to content

Cannot access data with the same name as a filter in webc (+ workaround) #97

@glimps-fde

Description

@glimps-fde

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions