11ty / eleventy-plugin-webc

Adds support for WebC *.webc files to Eleventy
https://www.11ty.dev/docs/languages/webc/
119 stars 10 forks source link

Permalink DuplicatePermalinkOutputError when using `.webc` with pagination in 2.0.0-canary.16 #36

Closed rijkvanzanten closed 1 year ago

rijkvanzanten commented 1 year ago

Describe the bug

When rendering a paginated page that is a .webc component, I'm getting a DuplicatePermalinkOutputError. It seems to work as expected with njk or other rendering engines (from what I can tell). This feels very similar to https://github.com/11ty/eleventy/issues/2333, but seeing that was confirmed fixed, I'm not sure if it's the exact same cause.

To Reproduce

Setup the following structure:

src/
  _data/
    test.json
  index.webc
.eleventy.js

with the following contents:

src/_data/test.json

[{ "title": "Test 1" }, { "title": "Test 2" }, { "title": "Test 3" }]

src/index.webc

---
pagination:
  data: test
  size: 1
  alias: item
permalink: "thing/{{ item.title | slugify }}/"
---

<h1>{{ item.title }}</h1>

.eleventy.js

const pluginWebc = require("@11ty/eleventy-plugin-webc");

module.exports = function (eleventyConfig) {
    eleventyConfig.addPlugin(pluginWebc, {
        components: "./src/_components/**/*.webc",
    });

    return {
        dir: {
            input: "src",
            output: "dist",
        },
    };
}

When you try building the site with eleventy, witness the following error:

> eleventy 

[11ty] Problem writing Eleventy templates: (more in DEBUG output)
[11ty] Output conflict: multiple input files are writing to `dist/thing/{{ item.title | slugify }}/index.html`. Use distinct `permalink` values to resolve this conflict.
[11ty]   1. ./src/index.webc
[11ty]   2. ./src/index.webc
[11ty]   3. ./src/index.webc (via DuplicatePermalinkOutputError)
[11ty]
[11ty] Original error stack trace: (Repeated output has been truncated…) [...truncated]

Expected behavior

By changing .webc to .njk or another rendering engine, note how it works as expected:

> eleventy

[11ty] Writing dist/thing/test-1/index.html from ./src/index.njk
[11ty] Writing dist/thing/test-2/index.html from ./src/index.njk
[11ty] Writing dist/thing/test-3/index.html from ./src/index.njk
[11ty] Wrote 3 files in 0.10 seconds (v2.0.0-canary.16)

WebC should work the same here

Environment:

rijkvanzanten commented 1 year ago

FWIW the custom dir input/output configuration in .eleventy.js doesn't seem to matter for this bug

rijkvanzanten commented 1 year ago

Update!

This is caused by the fact that the permalink is rendered by the engine used for the current file (for example a .liquid file uses Liquid for the permalink). For most of the default supported rendering engines, the {{ }} syntax for the permalink (as per the docs) works to render a basic string inline, however webc doesn't have such a syntax. Instead, to make things work, you gotta use permalink: 'books/<template webc:type="11ty" 11ty:type="njk">{{ book.title | slugify }}</template>/' instead of permalink: "books/{{ book.title | slugify }}/"

rijkvanzanten commented 1 year ago

For other people coming across this, you can achieve the same without having to rely on a nested rendering engine as follows:

permalink: '/example/<template webc:nokeep @html="slugify(data.example)"></template>/'
zachleat commented 1 year ago

Just for future visitors this bug was fixed with WebC v0.7.0! https://github.com/11ty/eleventy-plugin-webc/issues/27 No workaround needed!

zachleat commented 1 year ago

I am going to move this over to the Eleventy WebC plugin repo, thanks!

rijkvanzanten commented 1 year ago

I am going to move this over to the Eleventy WebC plugin repo, thanks!

My bad! Was still trying to find my way around the org structure at the time ☺️ Thanks for the fix!

robb-j commented 9 months ago

Hey, has this regressed? I've been getting the duplicate files error with the current versions of Eleventy & WebC. I put together a repro repo if its helpful?

https://github.com/robb-j/eleventy-webc-pagination-permalink-repro

I'm trying to do a permalink with pagination and I can't get it working

layout: html.webc
pagination:
  data: members.users
  size: 1
  alias: member
  resolve: values
permalink: 'share/{{ member.username | hash }}/index.html'
zachleat commented 9 months ago

@robb-j the takeaway here is that you can’t use njk or liquid syntax in a WebC template permalink. You need to use WebC syntax! https://github.com/11ty/eleventy-plugin-webc/issues/36#issuecomment-1355594796 has a good explanation

robb-j commented 8 months ago

Hey @zachleat, I've tried that but it still doesn't seem to be working? I tried in the repro repo, so my webc page is this now:

---
layout: html.webc
pagination:
  data: members.users
  size: 1
  alias: member
  resolve: values
permalink: 'share/<template webc:type="11ty" 11ty:type="njk">{{ member.username | hash }}</template>/'
---

<main>
  <h1>Hello there</h1>
  <section class="headshot">
    <p>Hi, <template @text="member" webc:nokeep></template></p>
  </section>
</main>

paginating this data file:

{
  "users": [
    { "username": "geoff-testington" },
    { "username": "jess-smith" },
    { "username": "phil-wang" }
  ]
}

but I'm still getting the DuplicatePermalinkOutputError:

[11ty] Problem writing Eleventy templates: (more in DEBUG output)
[11ty] Output conflict: multiple input files are writing to `_site/share/<template webc:type="11ty" 11ty:type="njk">{{ member.username | hash }}</template>/index.html`. Use distinct `permalink` values to resolve this conflict.
[11ty]   1. ./page.webc
[11ty]   2. ./page.webc
[11ty]   3. ./page.webc (via DuplicatePermalinkOutputError)
[11ty] 
[11ty] Original error stack trace: (Repeated output has been truncated…)
[11ty]     at TemplateMap.checkForDuplicatePermalinks (/Users/rob/tmp/eleventy-webc-pagination-permalink-repro/node_modules/@11ty/eleventy/src/TemplateMap.js:803:13)
[11ty]     at TemplateMap.cache (/Users/rob/tmp/eleventy-webc-pagination-permalink-repro/node_modules/@11ty/eleventy/src/TemplateMap.js:488:10)
[11ty]     at async TemplateWriter._createTemplateMap (/Users/rob/tmp/eleventy-webc-pagination-permalink-repro/node_modules/@11ty/eleventy/src/TemplateWriter.js:330:5)
[11ty]     at async TemplateWriter.generateTemplates (/Users/rob/tmp/eleventy-webc-pagination-permalink-repro/node_modules/@11ty/eleventy/src/TemplateWriter.js:360:5)
[11ty]     at async TemplateWriter.write (/Users/rob/tmp/eleventy-webc-pagination-permalink-repro/node_modules/@11ty/eleventy/src/TemplateWriter.js:407:23)
[11ty]     at async Eleventy.executeBuild (/Users/rob/tmp/eleventy-webc-pagination-permalink-repro/node_modules/@11ty/eleventy/src/Eleventy.js:1191:13)

looking with DEBUG=1 there is another error actually:

Eleventy:WebC Error evaluating dynamic permalink, returning raw string contents instead: 'share/<template webc:type="11ty" 11ty:type="njk">{{ member.username | hash }}</template>/'
  Eleventy:WebC Error: Check the permalink for ./page.webc
  Eleventy:WebC Original error message: Unexpected token '<'
  Eleventy:WebC     at ModuleScript.evaluateScript (/Users/rob/tmp/eleventy-webc-pagination-permalink-repro/node_modules/@11ty/webc/src/moduleScript.cjs:71:10)
  Eleventy:WebC     at Object.<anonymous> (/Users/rob/tmp/eleventy-webc-pagination-permalink-repro/node_modules/@11ty/eleventy-plugin-webc/src/eleventyWebcTemplate.js:80:49)
  Eleventy:WebC     at Template._renderFunction (/Users/rob/tmp/eleventy-webc-pagination-permalink-repro/node_modules/@11ty/eleventy/src/TemplateContent.js:405:27)
  Eleventy:WebC     at Template.renderPermalink (/Users/rob/tmp/eleventy-webc-pagination-permalink-repro/node_modules/@11ty/eleventy/src/TemplateContent.js:454:19)
  Eleventy:WebC     at async Template._getLink (/Users/rob/tmp/eleventy-webc-pagination-permalink-repro/node_modules/@11ty/eleventy/src/Template.js:251:24)
  Eleventy:WebC     at async Template.getOutputLocations (/Users/rob/tmp/eleventy-webc-pagination-permalink-repro/node_modules/@11ty/eleventy/src/Template.js:301:16)
  Eleventy:WebC     at async Pagination.getPageTemplates (/Users/rob/tmp/eleventy-webc-pagination-permalink-repro/node_modules/@11ty/eleventy/src/Plugins/Pagination.js:419:51)
  Eleventy:WebC     at async Template.getTemplates (/Users/rob/tmp/eleventy-webc-pagination-permalink-repro/node_modules/@11ty/eleventy/src/Template.js:705:27)
  Eleventy:WebC     at async TemplateMap.initDependencyMap (/Users/rob/tmp/eleventy-webc-pagination-permalink-repro/node_modules/@11ty/eleventy/src/TemplateMap.js:414:22)
  Eleventy:WebC     at async TemplateMap.cache (/Users/rob/tmp/eleventy-webc-pagination-permalink-repro/node_modules/@11ty/eleventy/src/TemplateMap.js:458:5) +1ms
VAggrippino commented 1 month ago

I don't understand how to make use of "no workaround needed" solution.

I tried this:

permalink: 'blog/history/<template webc:nokeep @html="pagination.pageNumber + 1"></template>/index.html'

I still have the DuplicatePermalinkOutputError.

I've read it has to be WebC syntax but that looks to me like a combination of HTML, WebC, & JavaScript syntax, and very much like a hacky workaround.

I'm probably doing something wrong.

I don't see any reason not to just use Liquid for the files that need pagination with a dynamic permalink.