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