eleventy icon indicating copy to clipboard operation
eleventy copied to clipboard

Data cascading issue when change from template syntax to JS eleventyComputed

Open hidegh opened this issue 3 years ago • 1 comments

Describe the bug

There's probably a data cascading issue @zachleat.

  • The setup works nicely with the deprecated template syntax inside the directory data files 11tydata.json)...
  • ...but it fails when we switch to 11tydata.js and use (have to) eleventyComputed to set up permalink.

Based on these 2 official links: https://www.11ty.dev/docs/data-template-dir/#template-and-directory-specific-data-files and https://www.11ty.dev/docs/data-cascade/#sources-of-data I'd expect this behavior:

  1. the data files nearest to the template are taking priority (e.g. the 11tydata.json in the same directory takes precedence over the 11tydata.json in the parent directories and over other global settings)
  2. computed data takes priority over other data (if on the same level - so computedData in a template would override the same variable in the same template, but a computedData on the directory data file should be overridden by a regular non-computed data on a template or even with a regular, non calculated data from a data file placed deeper/nearer to a template)

Since using JS data files is great, but not having access to the already (temporary) calculated data outside eleventyConfig, there's no other way to change the:

{
  "eleventyExcludeFromCollections": false,
  "layout": "page",
  "permalink": "{{ title | slug }}/",
  "aside": 0,
  "tags": "www"
}

...but to use this:

module.exports = function(configData) {
  return {
    eleventyExcludeFromCollections: false,
    layout: "page",
    aside: 0,
    tags: "www",
    eleventyComputed: {
      permalink: data => {
        const pemalinkTitle = data.title + "/";
        console.warn(`template: ${data.page.inputPath}, title (also computed in some cases): ${pemalinkTitle}`);
        return configData.eleventyConfig.liquidFilters.slug(pemalinkTitle);
      }
    }
  };
};

but then it generates this error:

[11ty] Problem writing Eleventy templates: (more in DEBUG output)
[11ty] Output conflict: multiple input files are writing to `_site/undefined`. Use distinct `permalink` values to resolve this conflict.

To Reproduce Provided the solution in a ZIP. npm install npm run serve

Expected behavior Replace web.11tydata.js with the *.json I've provided in this ticket

Screenshots N/A

Environment: See provided sample: web.reflection.zip

Additional context Will provide detailed description in a comment below! The bug is discussed on the 3rd place. Possible solutions and some missing data (that could help to solve issue in an other fashion is described in Nr1 and Nr2 section).

hidegh avatar Oct 30 '22 15:10 hidegh

Run into an issue with data (javascript data file).

  1. missing eleventyConfig inside data JS file (can be fixed via addGlobalData, although the aim is to have access to the same filters as elsewhere in the templates)
  2. missing data object inside data JS file (there's avail. at the eleventyComputed part, but why not earlier!?)
  3. unusual behaviour at data cascade - some scenario of cascading is not quiet clear, possible bug, see. 3 / 2.2

Details:

  1. they lack eleventyConfig data - had to add them via: eleventyConfig.addGlobalData("eleventyConfig", () => eleventyConfig) - but the main goal was to have access to the slug/slugify function
module.exports = function(configData) {
  return {
    eleventyExcludeFromCollections: false,
    layout: "page",
    aside: 0,
    tags: "www",
    eleventyComputed: {
      permalink: data => {
        return configData.eleventyConfig.liquidFilters.slug(data.title + "/")
      }
    }
  };
};

  1. they lack the data object (which in case of eleventyComputed is there)
module.exports = function(configData) {
  return {
    eleventyExcludeFromCollections: true,
    eleventyComputed: {
      aside: data => data.globals.site.defaultAside
    }
  };
};

  1. unusual behavior (possible BUG) in data cascading

based on these 2 links:

  • https://www.11ty.dev/docs/data-template-dir/#template-and-directory-specific-data-files
  • https://www.11ty.dev/docs/data-cascade/#sources-of-data

we expect that:

  1. the data files nearest to the template are taking priority (e.g. the 11tydata.json in the same directory takes precedence over the 11tydata.json in the parent directories and over other global settings)
  2. computed data takes priority over template
    1. but computed data in template takes priority over regulal data in template,
    2. or even computed data in a directory data file will take precedence over a template data - because then this conflicts with: https://www.11ty.dev/docs/data-template-dir/#template-and-directory-specific-data-files where directory data is merged with template data (latter having higher priority)

consider working solution with template markdown inside the directory json data file:

{
  "eleventyExcludeFromCollections": false,
  "layout": "page",
  "permalink": "{{ title | slug }}/",
  "aside": 0,
  "tags": "www"
}

also note that inside some of the templates (due to nested paging) there's a eleventyComputed title

www/_blog-related/tag.njk
---
pagination:
    data: collections.pagedPostsByTagCollection
    size: 1
    alias: customPagination
permalink: "{{ customPagination.pagedPath | normalize }}"
eleventyComputed:
    title: "Tagged with \"{{ customPagination.name }}\""
---

anyhow the scenario above ^ works perfectly!

--

since data file preprocessing will be deprecated see: https://www.11ty.dev/docs/data-preprocessing/, I've tried to solve the issue with JavaScript and eleventyComputed, see: www\www.11tydata.js

had to use: eleventyConfig.addGlobalData("eleventyConfig", () => eleventyConfig to get access to slug/slugify also had to use: eleventyComputed as otherwise access to data.title would not be possilbe

the config file:

module.exports = function(configData) {
  return {
    eleventyExcludeFromCollections: false,
    layout: "page",
    aside: 0,
    tags: "www",
    eleventyComputed: {
      permalink: data => {
        const pemalinkTitle = data.title + "/";
        console.warn(`template: ${data.page.inputPath}, title (also computed in some cases): ${pemalinkTitle}`);
        return configData.eleventyConfig.liquidFilters.slug(pemalinkTitle);
      }
    }
  };
};

the output is:

[11ty] Problem writing Eleventy templates: (more in DEBUG output)
[11ty] Output conflict: multiple input files are writing to `_site/undefined`. Use distinct `permalink` values to resolve this conflict.

which might happen only, if the permalink inside the www_blog-related/tag.njk is not taking priority / precedence over the generic permalink, defined at www\www.11tydata.js

the questions are then:

  1. is this behaviour correct? does not conflicts with the expected behavior based on https://www.11ty.dev/docs/data-template-dir/#template-and-directory-specific-data-files and https://www.11ty.dev/docs/data-cascade/#sources-of-data?
  2. assuming this behaviour is intended (although it already conflicts with the behaviour noticed while using deprecated template syntax inside the json data file) - would be really odd, but if so, how to achieve a generic calculated permalink with a local override on the template level?

note: for the 2nd question a solution might be to make the already collected data available on the export function level (outside eleventyComputed)...

hidegh avatar Oct 30 '22 15:10 hidegh