11ty / webc

Single File Web Components
MIT License
1.32k stars 38 forks source link

Remove implied `webc:raw` on `<template>` and `<noscript>` #105

Closed darthmall closed 1 year ago

darthmall commented 1 year ago

I’m not sure if this is a bug, but it took me by surprise.

WebC doesn’t seem to be processing the contents of <template> tags as WebC, which means if I have something like an HTML-only component that I want to land in a <template> tag in the final output, I have to do a little dance with webc:is (more on that in a minute).

Example

test-p.webc

<p>I am an HTML-only component</p>

test-component

<template>
  <test-p></test-p>
</template>

Expected Output

<template>
  <p>I am an HTML-only component</p>
</template>

Actual Output

<template>
  <test-p></test-p>
</template>

I would’ve expected <test-p> to only survive the WebC process if I’d used <template webc:raw> to signal that I didn’t want the template processed by WebC.

Workaround

You can achieve the desired output using webc:is like this:

test-component.webc

<div webc:is=template>
  <test-p></test-p>
</div>

Maybe this is actually desirable, but it took a little experimenting to figure this out.

Motivation

This came up because I was building a <theme-toggle> component for my website with WebC. I wanted the toggle buttons inside a <template> so that they’d only become visible in the DOM once the web component was upgraded (because they don’t do anything without JavaScript). I put some SVGs in .webc files for the icons in the toggle buttons.

theme-toggle.webc

<template>
  <button>
    <icon-moon></icon-moon>  <!-- icon-moon.webc contains SVG for a moon icon -->
    <span>Dark</span>
  </button>
  <!-- Buttons for system and light mode followed the same pattern -->
</template>
<script>
customElements.define(
  "theme-toggle",
  class extends HTMLElement {
    constructor() { /* Set up shadow DOM */ }
    connectedCallback() { /* Load template tag into shadow DOM */ }
  }
);
</script>
zachleat commented 1 year ago

I think this is sufficiently confusing that I’m going to push some changes. If you’re curious why this was added you can look at #31 but there is too much magic going on here.

So, moving forward in WebC v0.9.0 we’re going to have full WebC processing on <template> and <noscript> content (including slot resolution!), you can opt-out of this as normal with webc:raw.

zachleat commented 1 year ago

Also notably, this change also means that for consistency webc:is="template" will operate the same as <template> in WebC v0.9.0—opting out of this processing will require webc:raw moving forward.