summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/kind-beers-give.md6
-rw-r--r--packages/astro/test/fixtures/lit-element/src/pages/slots.astro30
-rw-r--r--packages/astro/test/fixtures/lit-element/tsconfig.json4
-rw-r--r--packages/astro/test/lit-element.test.js32
-rw-r--r--packages/astro/test/ssr-lit.test.js2
-rw-r--r--packages/integrations/lit/package.json3
-rw-r--r--packages/integrations/lit/server.js21
-rw-r--r--pnpm-lock.yaml2
8 files changed, 83 insertions, 17 deletions
diff --git a/.changeset/kind-beers-give.md b/.changeset/kind-beers-give.md
new file mode 100644
index 000000000..2cda00bcf
--- /dev/null
+++ b/.changeset/kind-beers-give.md
@@ -0,0 +1,6 @@
+---
+'astro': patch
+'@astrojs/lit': patch
+---
+
+Fix Lit slotted content
diff --git a/packages/astro/test/fixtures/lit-element/src/pages/slots.astro b/packages/astro/test/fixtures/lit-element/src/pages/slots.astro
index b8fc4963c..6ef0cd183 100644
--- a/packages/astro/test/fixtures/lit-element/src/pages/slots.astro
+++ b/packages/astro/test/fixtures/lit-element/src/pages/slots.astro
@@ -7,9 +7,33 @@ import {MyElement} from '../components/my-element.js';
<title>LitElement | Slot</title>
</head>
<body>
- <MyElement>
- <div>default</div>
- <div slot="named">named</div>
+ <MyElement id="root">
+ <div class="default">my-element default 1</div>
+ <div class="default">my-element default 2</div>
+
+ <h1 slot="named">my-element named 1</h1>
+ <h2 slot="named">my-element named 2</h2>
+
+ <ul slot="named" id="list">
+ <li>Custom elements</li>
+ <li>Shadow DOM</li>
+ <li>HTML templates</li>
+ </ul>
+
+ <my-element id="slotted" slot="named">
+ <h3 class="default">slotted my-element default</h3>
+
+ <div slot="named">slotted my-element named 1</div>
+ <div slot="named">slotted my-element named 2</div>
+
+ <MyElement id="slotted-slotted" slot="named">
+ <h4 class="default">slotted slotted my-element default 1</h4>
+ <h5 class="default">slotted slotted my-element default 2</h5>
+
+ <div slot="named">slotted slotted my-element named 1</div>
+ <div slot="named">slotted slotted my-element named 2</div>
+ </MyElement>
+ </my-element>
</MyElement>
</body>
</html>
diff --git a/packages/astro/test/fixtures/lit-element/tsconfig.json b/packages/astro/test/fixtures/lit-element/tsconfig.json
index f79d7bdca..504cd646e 100644
--- a/packages/astro/test/fixtures/lit-element/tsconfig.json
+++ b/packages/astro/test/fixtures/lit-element/tsconfig.json
@@ -1,3 +1,5 @@
{
- "experimentalDecorators": true
+ "compilerOptions": {
+ "experimentalDecorators": true
+ }
}
diff --git a/packages/astro/test/lit-element.test.js b/packages/astro/test/lit-element.test.js
index 3ee0a00a5..c14f5af55 100644
--- a/packages/astro/test/lit-element.test.js
+++ b/packages/astro/test/lit-element.test.js
@@ -70,15 +70,35 @@ describe('LitElement test', function () {
const html = await fixture.readFile('/slots/index.html');
const $ = cheerio.load(html);
- expect($('my-element').length).to.equal(1);
+ const $rootMyElement = $('#root');
+ const $slottedMyElement = $('#slotted');
+ const $slottedSlottedMyElement = $('#slotted-slotted');
- const [defaultSlot, namedSlot] = $('template').siblings().toArray();
+ expect($('my-element').length).to.equal(3);
- // has default slot content in lightdom
- expect($(defaultSlot).text()).to.equal('default');
+ // Root my-element
+ expect($rootMyElement.children('.default').length).to.equal(2);
+ expect($rootMyElement.children('.default').eq(1).text()).to.equal('my-element default 2');
- // has named slot content in lightdom
- expect($(namedSlot).text()).to.equal('named');
+ expect($rootMyElement.children('[slot="named"]').length).to.equal(4);
+ expect($rootMyElement.children('[slot="named"]').eq(1).text()).to.equal('my-element named 2');
+ expect($rootMyElement.children('[slot="named"]').eq(2).attr('id')).to.equal('list');
+ expect($rootMyElement.children('[slot="named"]').eq(3).attr('id')).to.equal('slotted');
+
+ // Slotted my-element first level
+ expect($slottedMyElement.children('.default').length).to.equal(1);
+ expect($slottedMyElement.children('.default').eq(0).text()).to.equal('slotted my-element default');
+
+ expect($slottedMyElement.children('[slot="named"]').length).to.equal(3);
+ expect($slottedMyElement.children('[slot="named"]').eq(1).text()).to.equal('slotted my-element named 2');
+ expect($slottedMyElement.children('[slot="named"]').eq(2).attr('id')).to.equal('slotted-slotted');
+
+ // Slotted my-element second level
+ expect($slottedSlottedMyElement.children('.default').length).to.equal(2);
+ expect($slottedSlottedMyElement.children('.default').eq(1).text()).to.equal('slotted slotted my-element default 2');
+
+ expect($slottedSlottedMyElement.children('[slot="named"]').length).to.equal(2);
+ expect($slottedSlottedMyElement.children('[slot="named"]').eq(1).text()).to.equal('slotted slotted my-element named 2');
});
it('Is able to build when behind getStaticPaths', async () => {
diff --git a/packages/astro/test/ssr-lit.test.js b/packages/astro/test/ssr-lit.test.js
index 53555b983..98d58b395 100644
--- a/packages/astro/test/ssr-lit.test.js
+++ b/packages/astro/test/ssr-lit.test.js
@@ -25,7 +25,7 @@ describe('Lit integration in SSR', () => {
}
it('Is able to load', async () => {
- delete globalThis.window;
+ delete globalThis.window; // On Windows this results in `ReferenceError: window is not defined`
const html = await fetchHTML('/');
const $ = cheerioLoad(html);
expect($('#win').text()).to.equal('function');
diff --git a/packages/integrations/lit/package.json b/packages/integrations/lit/package.json
index 9781094c7..24410f7e8 100644
--- a/packages/integrations/lit/package.json
+++ b/packages/integrations/lit/package.json
@@ -33,7 +33,8 @@
"test": "mocha"
},
"dependencies": {
- "@lit-labs/ssr": "^2.2.0"
+ "@lit-labs/ssr": "^2.2.0",
+ "parse5": "^7.1.2"
},
"devDependencies": {
"astro": "workspace:*",
diff --git a/packages/integrations/lit/server.js b/packages/integrations/lit/server.js
index 2f9076672..59c79f55b 100644
--- a/packages/integrations/lit/server.js
+++ b/packages/integrations/lit/server.js
@@ -1,6 +1,7 @@
import './server-shim.js';
import '@lit-labs/ssr/lib/render-lit-html.js';
import { LitElementRenderer } from '@lit-labs/ssr/lib/lit-element-renderer.js';
+import * as parse5 from 'parse5';
function isCustomElementTag(name) {
return typeof name === 'string' && /-/.test(name);
@@ -58,12 +59,22 @@ function* render(Component, attrs, slots) {
yield '</template>';
}
if (slots) {
- for (const [slot, value] of Object.entries(slots)) {
- if (slot === 'default') {
- yield `<astro-slot>${value || ''}</astro-slot>`;
- } else {
- yield `<astro-slot slot="${slot}">${value || ''}</astro-slot>`;
+ for (let [slot, value = ''] of Object.entries(slots)) {
+ if (slot !== 'default' && value) {
+ // Parse the value as a concatenated string
+ const fragment = parse5.parseFragment(`${value}`);
+
+ // Add the missing slot attribute to child Element nodes
+ for (const node of fragment.childNodes) {
+ if (node.tagName && !node.attrs.some(({ name }) => name === 'slot')) {
+ node.attrs.push({ name: 'slot', value: slot});
+ }
+ }
+
+ value = parse5.serialize(fragment);
}
+
+ yield value;
}
}
yield `</${tagName}>`;
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6f26b44e6..f751364fa 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -2838,9 +2838,11 @@ importers:
cheerio: ^1.0.0-rc.11
lit: ^2.2.5
mocha: ^9.2.2
+ parse5: ^7.1.2
sass: ^1.52.2
dependencies:
'@lit-labs/ssr': 2.3.0
+ parse5: 7.1.2
devDependencies:
astro: link:../../astro
astro-scripts: link:../../../scripts