final pass at Outlet approach
This commit is contained in:
parent
d8608bb947
commit
976b6ccf6e
10 changed files with 74 additions and 43 deletions
1
examples/minimal/src/content/posts/intro.md
Normal file
1
examples/minimal/src/content/posts/intro.md
Normal file
|
@ -0,0 +1 @@
|
|||
Hello world!
|
1
examples/minimal/src/env.d.ts
vendored
1
examples/minimal/src/env.d.ts
vendored
|
@ -1 +1,2 @@
|
|||
/// <reference path="../.astro/types.d.ts" />
|
||||
/// <reference types="astro/client" />
|
||||
|
|
|
@ -15,16 +15,31 @@ import { Outlet } from 'astro/components';
|
|||
<h1>My Website</h1>
|
||||
</header>
|
||||
|
||||
<slot name="nav" />
|
||||
<Outlet id="nav">
|
||||
<slot name="nav" />
|
||||
</Outlet>
|
||||
|
||||
<main>
|
||||
{() => new Promise((resolve) => setTimeout(resolve, 1000))}
|
||||
<slot />
|
||||
<Outlet id="main">
|
||||
<slot />
|
||||
</Outlet>
|
||||
{() => new Promise((resolve) => setTimeout(resolve, 1000))}
|
||||
|
||||
<slot name="tabs" />
|
||||
</main>
|
||||
|
||||
<style is:global>
|
||||
nav ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
}
|
||||
a.active {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
function getOutlets() {
|
||||
const query = "//comment()[contains(., 'astro:outlet')]";
|
||||
|
@ -98,6 +113,7 @@ import { Outlet } from 'astro/components';
|
|||
async function update() {
|
||||
const promises: any[] = [];
|
||||
for (const [outlet, range] of Object.entries(getOutlets())) {
|
||||
console.log({ outlet });
|
||||
promises.push(
|
||||
fetch(event.destination.url, {
|
||||
headers: { 'x-astro-outlet': outlet },
|
||||
|
@ -115,18 +131,5 @@ import { Outlet } from 'astro/components';
|
|||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style is:global>
|
||||
nav ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
}
|
||||
a.active {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
---
|
||||
import Layout from '../layouts/Default.astro';
|
||||
|
||||
import { getEntryBySlug } from 'astro:content';
|
||||
|
||||
const entry = await getEntryBySlug('posts', 'intro');
|
||||
const { Content } = await entry.render();
|
||||
---
|
||||
|
||||
<Layout>
|
||||
<div>
|
||||
<h2>Home</h2>
|
||||
<p>Streaming partials!</p>
|
||||
|
||||
<Content />
|
||||
</div>
|
||||
|
||||
<nav slot="nav">
|
||||
|
|
|
@ -31,6 +31,11 @@ const { title, description } = Astro.props;
|
|||
addEventListener('load', () => document.documentElement.classList.add('loaded'));
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import listen from 'micromorph/spa';
|
||||
listen();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--_placeholder-bg: linear-gradient(transparent, transparent);
|
||||
|
|
|
@ -6,7 +6,7 @@ interface Props {
|
|||
const { id } = Astro.props;
|
||||
|
||||
// @ts-ignore untyped internals
|
||||
// $$result.outlets.set(id, $$slots.default);
|
||||
$$result.outlets.set(id, () => Astro.slots.render('default'));
|
||||
---
|
||||
|
||||
<Fragment set:html={`<!--astro:outlet ${id}-->`} /><slot /><Fragment
|
||||
|
|
|
@ -113,11 +113,11 @@
|
|||
"test:e2e:match": "playwright test -g"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/compiler": "^1.4.0",
|
||||
"@astrojs/language-server": "^1.0.0",
|
||||
"@astrojs/markdown-remark": "^2.2.0",
|
||||
"@astrojs/telemetry": "^2.1.1",
|
||||
"@astrojs/webapi": "^2.1.1",
|
||||
"@astrojs/compiler": "^1.4.1",
|
||||
"@astrojs/language-server": "^0.28.3",
|
||||
"@astrojs/markdown-remark": "^2.1.4",
|
||||
"@astrojs/telemetry": "^2.1.0",
|
||||
"@astrojs/webapi": "^2.1.0",
|
||||
"@babel/core": "^7.18.2",
|
||||
"@babel/generator": "^7.18.2",
|
||||
"@babel/parser": "^7.18.4",
|
||||
|
|
|
@ -83,7 +83,7 @@ export function createAstroComponentInstance(
|
|||
const instance = new AstroComponentInstance(result, props, slots, factory);
|
||||
if (result._metadata.request.headers.has('x-astro-outlet')) {
|
||||
for (const [name, slot] of Object.entries(slots)) {
|
||||
result.outletPropagators.set(`${factory.hash} ${name}`, slot);
|
||||
result.outletPropagators.set(name, slot);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
|
|
@ -70,14 +70,13 @@ async function bufferHeadContent(result: SSRResult) {
|
|||
// Recursively calls component instances that might have slots to be propagated up.
|
||||
async function bufferSlottedContent(result: SSRResult, outlet: string) {
|
||||
const iterator = result.outletPropagators.entries();
|
||||
let promises = [];
|
||||
while (true) {
|
||||
const { value: [name, slot] = [], done } = iterator.next();
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
const returnValue = await slot(result);
|
||||
result.outlets.set(name, returnValue);
|
||||
// TODO: exhaust all expressions
|
||||
if (name === outlet) {
|
||||
break;
|
||||
}
|
||||
|
@ -153,6 +152,8 @@ export async function renderPage(
|
|||
result.scripts.clear();
|
||||
await bufferSlottedContent(result, outlet);
|
||||
|
||||
console.log(result.outlets);
|
||||
|
||||
if (!result.outlets.get(outlet)) {
|
||||
let init = result.response;
|
||||
let headers = new Headers(init.headers);
|
||||
|
|
|
@ -535,19 +535,19 @@ importers:
|
|||
packages/astro:
|
||||
dependencies:
|
||||
'@astrojs/compiler':
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0
|
||||
specifier: ^1.4.1
|
||||
version: 1.4.1
|
||||
'@astrojs/language-server':
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0
|
||||
specifier: ^0.28.3
|
||||
version: 0.28.3
|
||||
'@astrojs/markdown-remark':
|
||||
specifier: ^2.2.0
|
||||
specifier: ^2.1.4
|
||||
version: link:../markdown/remark
|
||||
'@astrojs/telemetry':
|
||||
specifier: ^2.1.1
|
||||
specifier: ^2.1.0
|
||||
version: link:../telemetry
|
||||
'@astrojs/webapi':
|
||||
specifier: ^2.1.1
|
||||
specifier: ^2.1.0
|
||||
version: link:../webapi
|
||||
'@babel/core':
|
||||
specifier: ^7.18.2
|
||||
|
@ -5393,20 +5393,22 @@ packages:
|
|||
sisteransi: 1.0.5
|
||||
dev: false
|
||||
|
||||
/@astrojs/compiler@1.4.0:
|
||||
resolution: {integrity: sha512-Vav3a32Ct+omowV9X9kDM2ghWAvFdjZkv5BdvBjZCKYbFVT6//IZApDIVbHI1UPuLuD2sKyLWx2T+E7clqUJdg==}
|
||||
/@astrojs/compiler@0.31.4:
|
||||
resolution: {integrity: sha512-6bBFeDTtPOn4jZaiD3p0f05MEGQL9pw2Zbfj546oFETNmjJFWO3nzHz6/m+P53calknCvyVzZ5YhoBLIvzn5iw==}
|
||||
dev: false
|
||||
|
||||
/@astrojs/language-server@1.0.0:
|
||||
resolution: {integrity: sha512-oEw7AwJmzjgy6HC9f5IdrphZ1GVgfV/+7xQuyf52cpTiRWd/tJISK3MsKP0cDkVlfodmNABNFnAaAWuLZEiiiA==}
|
||||
/@astrojs/compiler@1.4.1:
|
||||
resolution: {integrity: sha512-aXAxapNWZwGN41P+Am/ma/2kAzKOhMNaY6YuvLkUHFv+UZkmDHD6F0fE1sQA2Up0bLjgPQa1VQzoAaii5tZWaA==}
|
||||
|
||||
/@astrojs/language-server@0.28.3:
|
||||
resolution: {integrity: sha512-fPovAX/X46eE2w03jNRMpQ7W9m2mAvNt4Ay65lD9wl1Z5vIQYxlg7Enp9qP225muTr4jSVB5QiLumFJmZMAaVA==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@astrojs/compiler': 1.4.0
|
||||
'@jridgewell/trace-mapping': 0.3.18
|
||||
'@vscode/emmet-helper': 2.8.8
|
||||
events: 3.3.0
|
||||
prettier: 2.8.8
|
||||
prettier-plugin-astro: 0.8.0
|
||||
synckit: 0.8.5
|
||||
prettier-plugin-astro: 0.7.2
|
||||
source-map: 0.7.4
|
||||
vscode-css-languageservice: 6.2.5
|
||||
vscode-html-languageservice: 5.0.5
|
||||
vscode-languageserver: 8.1.0
|
||||
|
@ -8436,7 +8438,7 @@ packages:
|
|||
/@ts-morph/common@0.16.0:
|
||||
resolution: {integrity: sha512-SgJpzkTgZKLKqQniCjLaE3c2L2sdL7UShvmTmPBejAKd2OKV/yfMpQ2IWpAuA+VY5wy7PkSUaEObIqEK6afFuw==}
|
||||
dependencies:
|
||||
fast-glob: 3.2.11
|
||||
fast-glob: 3.2.12
|
||||
minimatch: 5.1.6
|
||||
mkdirp: 1.0.4
|
||||
path-browserify: 1.0.1
|
||||
|
@ -15247,14 +15249,25 @@ packages:
|
|||
fast-diff: 1.2.0
|
||||
dev: true
|
||||
|
||||
/prettier-plugin-astro@0.7.2:
|
||||
resolution: {integrity: sha512-mmifnkG160BtC727gqoimoxnZT/dwr8ASxpoGGl6EHevhfblSOeu+pwH1LAm5Qu1MynizktztFujHHaijLCkww==}
|
||||
engines: {node: ^14.15.0 || >=16.0.0, pnpm: '>=7.14.0'}
|
||||
dependencies:
|
||||
'@astrojs/compiler': 0.31.4
|
||||
prettier: 2.8.8
|
||||
sass-formatter: 0.7.6
|
||||
synckit: 0.8.5
|
||||
dev: false
|
||||
|
||||
/prettier-plugin-astro@0.8.0:
|
||||
resolution: {integrity: sha512-kt9wk33J7HvFGwFaHb8piwy4zbUmabC8Nu+qCw493jhe96YkpjscqGBPy4nJ9TPy9pd7+kEx1zM81rp+MIdrXg==}
|
||||
engines: {node: ^14.15.0 || >=16.0.0, pnpm: '>=7.14.0'}
|
||||
dependencies:
|
||||
'@astrojs/compiler': 1.4.0
|
||||
'@astrojs/compiler': 1.4.1
|
||||
prettier: 2.8.8
|
||||
sass-formatter: 0.7.6
|
||||
synckit: 0.8.5
|
||||
dev: true
|
||||
|
||||
/prettier@2.8.8:
|
||||
resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==}
|
||||
|
|
Loading…
Reference in a new issue