11ty / eleventy-plugin-vue

Use Vue.js templates and Vue.js single file components in Eleventy.
196 stars 11 forks source link

Setting permalink uses file contents as URL #6

Closed oliverjam closed 4 years ago

oliverjam commented 4 years ago

This is kinda weird—I only discovered it trying to build a Svelte plugin by copying this one 😅

It seems like if a custom template sets a permalink in its data Eleventy tries to use the rendered output (whatever compile returns) as the output filename.

To reproduce:

  1. Clone this repo
  2. Add permalink: "/whatever.html" to the data method in /test/sample/another-page.vue
  3. Check the _site/ directory for a weird surprise
Writing _site/index.html from ./test/sample/index.vue.
Writing _site/<div data-server-rendered="true">
  Current page url:
  <p>/<div data-server-rendered="true">
  Current page url:
  <p></p> <div>HELLO</div> <myHeader></myHeader> <hi></hi></div></p> <div>HELLO</div> <myHeader></myHeader> <hi></hi></div> from ./test/sample/another-page.vue.
Wrote 2 files in 0.42 seconds (v0.11.0)

I guess this isn't technically a problem with this plugin, but actually the Custom engine? I can move the issue to the Eleventy repo if you'd prefer.

oliverjam commented 4 years ago

Ignore all this, figured it out in the next comment

~It looks like the problem is templating: Eleventy calls engine.compile with the permalink string to support dynamic permalinks.~

permalinkValue = await super.render(permalink, data, true);

~Template.js#L130~

~However I can't see a good way for custom template engines that aren't general purpose templating languages to work here. I don't think Vue or Svelte support templating arbitrary strings, and I'm not sure how the custom engine would even know to treat the permalink differently, since the function signature is just compile(str, inputPath).~

~Could Eleventy maybe support globally configuring the permalink templating language? That way plugins for engines that can't do string templating could just delegate permalink templating to e.g. Liquid.~

oliverjam commented 4 years ago

Ah I figured out the solution, sorry for wasting your time! 🤦

I did some digging into how the JavaScript Engine handles permalinks and realised that setting read: false when we add the extension means compile will be called with str undefined. So I imagine a quick if (str) return str (or some other permalink templating solution) would fix this issue.

zachleat commented 4 years ago

Thanks for updating!

andeersg commented 4 years ago

Looking at this plugin now and encountered the same problem, but I'm not sure if I understand what the solution is?

oliverjam commented 4 years ago

I had to add this to my Svelte plugin to fix it:

compile: (str, inputPath) => (data) => {
  if (str) {
    // since `read: false` is set 11ty doesn't read file contents
    // so if str has a value, it's a permalink (which can be a string or a function)
    return typeof str === "function" ? str(data) : str;
  }
  // ...
}

I think this Vue Plugin might need something similar for permalinks to work right

zachleat commented 4 years ago

Going to reopen this per discussion at https://github.com/11ty/eleventy/issues/1365

zachleat commented 4 years ago

This shipped with eleventy-vue-plugin v0.2.1