Redesign pages, remove layout nesting (#24)

* wip

* new svelte-style prop declaration is working

* got it working!

* revert h changes

* format

* style lang update
This commit is contained in:
Fred K. Schott 2021-03-24 16:01:28 -07:00 committed by GitHub
parent 3c24faa8ca
commit a72ab10c62
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 751 additions and 714 deletions

View file

@ -0,0 +1,38 @@
---
import Banner from './Banner.astro';
import Nav from './Nav.astro';
export let title: string;
export let description: string;
export let permalink: string;
---
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png" />
<link rel="manifest" href="/favicon/site.webmanifest" />
<!-- Primary Meta Tags -->
<title>{title}</title>
<meta name="title" content={title} />
<meta name="description" content="{description}" />
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website" />
<meta property="og:url" content={permalink} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content="https://www.snowpack.dev/img/social-2.jpg" />
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content={permalink} />
<meta property="twitter:title" content={title} />
<meta property="twitter:description" content={description} />
<meta property="twitter:image" content="https://www.snowpack.dev/img/social-2.jpg" />
<!-- Global Stylesheets -->
<link rel="stylesheet" href="/css/app.css" />
<link href="https://fonts.googleapis.com/css2?family=Overpass:wght@400;700;900&display=swap" rel="stylesheet" />

View file

@ -0,0 +1,20 @@
---
import Banner from './Banner.astro';
import Nav from './Nav.astro';
---
<Banner></Banner>
<Nav />
<slot></slot>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async="async" src="https://www.googletagmanager.com/gtag/js?id=UA-130280175-9"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'UA-130280175-9', { page_path: location.pathname === '/' ? (location.pathname + location.hash) : (location.pathname) });
</script>

View file

@ -0,0 +1,23 @@
---
import BaseLayout from './BaseLayout.astro';
import Menu from './Menu.astro';
export function setup({ context }) {
return {};
}
---
<BaseLayout>
<div class="container">
<section class="snow-view__docs is-full">
<aside id="nav-primary" class="snow-view-nav">
<Menu />
</aside>
<article class="snow-view-main">
<slot></slot>
</article>
</section>
</div>
</BaseLayout>

View file

@ -1,5 +1,5 @@
---
export let props: { version: string };
export let version: string = '3.1.2';
---
<style lang="scss">
@ -257,7 +257,7 @@
</div>
<div style="flex-grow: 1"></div>
<a href="https://github.com/snowpackjs/snowpack/releases" target="_blank" class="link version">
{`v${props.version}`}
{`v${version}`}
</a>
<a href="https://github.com/snowpackjs/snowpack" target="_blank" class="link link__desktop">
<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="github" class="snow-icon" role="img"

View file

@ -1,9 +1,7 @@
---
export let props: {
title: string,
inputPath: string,
headers: { text: string, slug: string }[]
};
export let title: string;
export let inputPath: string;
export let headers: string;
---
<style lang="scss">
@ -59,12 +57,12 @@
<script type="module" defer src="/js/index.js"></script>
<aside class="subnav">
{props.headers.length > 0 && (
{headers.length > 0 && (
<div>
<h4 class="header">On this page</h4>
<nav class="toc">
<ol>
{props.headers.map((heading) => {
{headers.map((heading) => {
return <li><a href={"#" + heading.slug}>{heading.text}</a></li>
})}
</ol>
@ -74,5 +72,5 @@
)}
<h4 class="header">Suggest a change</h4>
<a href="https://github.com/snowpackjs/snowpack/blob/main/www/{props.inputPath}">Edit this page on GitHub</a>
<a href="https://github.com/snowpackjs/snowpack/blob/main/www/{inputPath}">Edit this page on GitHub</a>
</aside>

View file

@ -1,62 +0,0 @@
---
import Banner from '../components/Banner.astro';
import Nav from '../components/Nav.astro';
export function setup({ context }) {
return {
context: {
title: 'Snowpack',
description: 'Snowpack is a lightning-fast frontend build tool, designed for the modern web.',
currentSnowpackVersion: '3.0.13',
}
};
}
---
<astro:head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png" />
<link rel="manifest" href="/favicon/site.webmanifest" />
<!-- Primary Meta Tags -->
<title>{context.title}</title>
<meta name="title" content={context.title} />
<meta name="description" content="{context.description}" />
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website" />
<meta property="og:url" content={context.permalink} />
<meta property="og:title" content={context.title} />
<meta property="og:description" content={context.description} />
<meta property="og:image" content="https://www.snowpack.dev/img/social-2.jpg" />
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content={context.permalink} />
<meta property="twitter:title" content={context.title} />
<meta property="twitter:description" content={context.description} />
<meta property="twitter:image" content="https://www.snowpack.dev/img/social-2.jpg" />
<!-- Global Stylesheets -->
<link rel="stylesheet" href="/css/app.css" />
<link href="https://fonts.googleapis.com/css2?family=Overpass:wght@400;700;900&display=swap" rel="stylesheet" />
</astro:head>
<Banner></Banner>
<Nav version={context.currentSnowpackVersion} />
<!-- if no slot given, assume add to bottom -->
<slot></slot>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async="async" src="https://www.googletagmanager.com/gtag/js?id=UA-130280175-9"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'UA-130280175-9', { page_path: location.pathname === '/' ? (location.pathname + location.hash) : (location.pathname) });
</script>

View file

@ -1,78 +1,88 @@
---
import Menu from '../components/Menu.astro';
import Subnav from '../components/Subnav.astro';
import Subnav from '../components/Subnav.astro';
import Menu from '../components/Menu.astro';
import BaseHead from '../components/BaseHead.astro';
import BaseLayout from '../components/BaseLayout.astro';
export const layout = 'layouts/base.astro';
export function setup({ context }) {
return {};
}
export let content: any;
---
<html>
<style>
.cover-wrapper {
width: 100%;
height: 44vh;
min-height: 20rem;
max-height: 30rem;
position: relative;
background: #2a85ca40;
overflow: hidden;
}
.cover,
.cover-blur {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
height: 100%;
width: 100%;
}
.cover-blur {
object-fit: cover;
filter: blur(3px) brightness(1.5);
transform: scale(1.1);
}
.cover {
object-fit: contain;
filter: brightness(1.5);
}
@media (max-width: 1200px) {
<head>
<style>
.cover-wrapper {
width: 100%;
height: 44vh;
min-height: 20rem;
max-height: 30rem;
position: relative;
background: #2a85ca40;
overflow: hidden;
}
.cover,
.cover-blur {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
height: 100%;
width: 100%;
}
.cover-blur {
object-fit: cover;
filter: blur(3px) brightness(1.5);
transform: scale(1.1);
}
.cover {
object-fit: cover;
object-fit: contain;
filter: brightness(1.5);
}
}
</style>
@media (max-width: 1200px) {
.cover-blur {
object-fit: cover;
}
.cover {
object-fit: cover;
}
}
</style>
<BaseHead title={content.title} description={content.description} permalink="TODO" />
</head>
<div class="cover-wrapper">
<img class="cover-blur" src={context.cover} alt=""/>
<img class="cover" src={context.cover} alt=""/>
</div>
<body>
<BaseLayout>
<div class="container">
<section class="snow-view__docs has-subnav">
<div class="cover-wrapper">
<img class="cover-blur" src={content.cover} alt=""/>
<img class="cover" src={content.cover} alt=""/>
</div>
<aside id="nav-primary" class="snow-view-nav">
<Menu />
</aside>
<div class="container">
<section class="snow-view__docs has-subnav">
<article class="snow-view-main">
<div class="content">
<h2 class="content-title">
{context.title}
</h2>
<div class="content-layout">
<div class="content-body">
<slot></slot>
<aside id="nav-primary" class="snow-view-nav">
<Menu />
</aside>
<article class="snow-view-main">
<div class="content">
<h2 class="content-title">
{content.title}
</h2>
<div class="content-layout">
<div class="content-body">
{content.body}
</div>
</div>
</div>
</div>
</div>
</article>
</article>
<Subnav title={context.title} headers={context.content.headers} />
</section>
</div>
<Subnav title={content.title} headers={content.headers} />
</section>
</div>
</BaseLayout>
</body>
</html>

View file

@ -1,37 +1,45 @@
---
import Subnav from '../components/Subnav.astro';
import Menu from '../components/Menu.astro';
import Subnav from '../components/Subnav.astro';
import Menu from '../components/Menu.astro';
import BaseHead from '../components/BaseHead.astro';
import BaseLayout from '../components/BaseLayout.astro';
export const layout = 'layouts/base.astro';
export function setup({ context }) {
return {
context: {
}
};
}
export let content: any;
---
<div class="container">
<section class="snow-view__docs has-subnav">
<html>
<aside id="nav-primary" class="snow-view-nav">
<Menu />
</aside>
<head>
<BaseHead title={content.title} description={content.description} permalink="TODO" />
</head>
<Subnav title={context.title} headers={context.content.headers} />
<body>
<BaseLayout>
<div class="container">
<section class="snow-view__docs has-subnav">
<article class="snow-view-main">
<div class="content">
<h2 class="content-title">
{context.title}
</h2>
<div class="content-layout">
<div class="content-body">
<slot></slot>
<aside id="nav-primary" class="snow-view-nav">
<Menu />
</aside>
<Subnav title={content.title} headers={content.headers} />
<article class="snow-view-main">
<div class="content">
<h2 class="content-title">
{content.title}
</h2>
<div class="content-layout">
<div class="content-body">
<slot></slot>
</div>
</div>
</div>
</div>
</div>
</article>
</article>
</section>
</div>
</section>
</div>
</BaseLayout>
</body>
</html>

View file

@ -1,21 +0,0 @@
---
import Menu from '../components/Menu.astro';
export const layout = 'layouts/base.astro';
export function setup({ context }) {
return {};
}
---
<div class="container">
<section class="snow-view__docs is-full">
<aside id="nav-primary" class="snow-view-nav">
<Menu />
</aside>
<article class="snow-view-main">
<slot></slot>
</article>
</section>
</div>

View file

@ -1,127 +1,136 @@
---
import { format as formatDate, parseISO } from 'date-fns';
export const layout = 'layouts/base.astro';
export function setup({ context }) {
return {};
}
import BaseHead from '../components/BaseHead.astro';
import BaseLayout from '../components/BaseLayout.astro';
import { format as formatDate, parseISO } from 'date-fns';
export let content: any;
---
<astro:head>
<link rel="stylesheet" href="/css/legacy-post.css" />
</astro:head>
<style>
.markdown-body img,
.markdown-body video,
.markdown-body iframe {
box-shadow: 0px 5px 12px 0 #CCC;
border-radius: 3px;
min-width: 130%;
width: 130%;
margin-left: -15%;
margin-right: -15%;
margin-top: 4rem;
margin-bottom: -1rem;
}
@media (max-width: 860px) {
<html>
<head>
<style>
.markdown-body img,
.markdown-body video,
.markdown-body iframe {
min-width: 100%;
margin-left: 0;
margin-right: 0;
margin-bottom: -2rem;
box-shadow: 0px 5px 12px 0 #CCC;
border-radius: 3px;
min-width: 130%;
width: 130%;
margin-left: -15%;
margin-right: -15%;
margin-top: 4rem;
margin-bottom: -1rem;
}
}
.markdown-body table td:nth-child(1) {
white-space: nowrap;
}
.markdown-body,
.fbody-header {
max-width: 840px;
}
.markdown-body {
font-size: 18px;
margin-bottom: 20vh;
}
.markdown-body h2 {
font-size: 1.8em;
}
@media (max-width: 860px) {
@media (max-width: 860px) {
.markdown-body img,
.markdown-body video,
.markdown-body iframe {
min-width: 100%;
margin-left: 0;
margin-right: 0;
margin-bottom: -2rem;
}
}
.markdown-body table td:nth-child(1) {
white-space: nowrap;
}
.markdown-body,
.toc {
padding: 1em;
.fbody-header {
max-width: 840px;
}
}
@media (max-width: 740px) {
.markdown-body img,
.markdown-body iframe {
max-width: 108%;
margin-left: -4%;
margin-right: -4%;
.markdown-body {
font-size: 18px;
margin-bottom: 20vh;
}
.grid-body {
padding: 20px 0 0 0;
.markdown-body h2 {
font-size: 1.8em;
}
}
@media (max-width: 860px) {
.markdown-body,
.toc {
padding: 1em;
}
}
@media (max-width: 740px) {
.markdown-body img,
.markdown-body iframe {
max-width: 108%;
margin-left: -4%;
margin-right: -4%;
}
.grid-body {
padding: 20px 0 0 0;
}
}
.header-snowpack {
font-size: 3.5rem;
text-align: center;
}
.markdown-body h1 {
font-size: 3.5em;
}
.markdown-body h3 .header-link {
opacity: 1;
}
</style>
<BaseHead title={content.title} description={content.description} permalink="TODO" />
<link rel="stylesheet" href="/css/legacy-post.css" />
</head>
.header-snowpack {
font-size: 3.5rem;
text-align: center;
}
<body>
<BaseLayout>
.markdown-body h1 {
font-size: 3.5em;
}
.markdown-body h3 .header-link {
opacity: 1;
}
</style>
<div class="grid-extra-space">
<div class="grid-body-header">
<svg height="80px" style="padding-left: 8px;" viewBox="0 0 640 512" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Page-1" stroke="none" stroke-width="1" fill="currentColor" fill-rule="evenodd">
<g id="mountain-solid" transform="translate(-1.000000, 0.000000)" fill-rule="nonzero">
<path
d="M635.92,462.7 L347.92,14.7 C342.03,5.54 331.89,0 321,0 C310.11,0 299.97,5.54 294.08,14.7 L6.08,462.7 C-0.250773249,472.547007 -0.699487627,485.064987 4.91,495.34 C10.522069,505.612419 21.2945349,512 33,512 L609,512 C620.71,512 631.48,505.61 637.09,495.33 C642.699457,485.058495 642.250708,472.543372 635.92,462.7 Z M321,91.18 L406.39,224 L321,224 L257,288 L218.94,249.94 L321,91.18 Z"
id="Shape"></path>
</g>
</g>
</svg>
<h1 class="header-snowpack">{context.title}</h1>
<div class="grid-extra-space">
<div class="grid-body-header">
<svg height="80px" style="padding-left: 8px;" viewBox="0 0 640 512" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Page-1" stroke="none" stroke-width="1" fill="currentColor" fill-rule="evenodd">
<g id="mountain-solid" transform="translate(-1.000000, 0.000000)" fill-rule="nonzero">
<path
d="M635.92,462.7 L347.92,14.7 C342.03,5.54 331.89,0 321,0 C310.11,0 299.97,5.54 294.08,14.7 L6.08,462.7 C-0.250773249,472.547007 -0.699487627,485.064987 4.91,495.34 C10.522069,505.612419 21.2945349,512 33,512 L609,512 C620.71,512 631.48,505.61 637.09,495.33 C642.699457,485.058495 642.250708,472.543372 635.92,462.7 Z M321,91.18 L406.39,224 L321,224 L257,288 L218.94,249.94 L321,91.18 Z"
id="Shape"></path>
</g>
</g>
</svg>
<h1 class="header-snowpack">{content.title}</h1>
<div>
{context.tagline && <div style="margin-bottom: 1rem;">{context.tagline}</div>}
<div>
Published <a href='#published-at'>{formatDate(parseISO(context.date), 'MMMM d, yyyy')}</a>
by <a href="https://twitter.com/FredKSchott">Fred K. Schott</a>
<div>
{content.tagline && <div style="margin-bottom: 1rem;">{content.tagline}</div>}
<div>
Published <a href='#published-at'>{formatDate(parseISO(content.date), 'MMMM d, yyyy')}</a>
by <a href="https://twitter.com/FredKSchott">Fred K. Schott</a>
</div>
</div>
<!-- Place this tag where you want the button to render. -->
<div class="hidden-mobile" style="text-align: center; margin-top: 0.5rem; filter: scale(2);">
<a class="github-button" href="https://github.com/snowpackjs/snowpack" data-icon="octicon-star" data-size="large"
data-show-count="true" aria-label="Star snowpackjs/snowpack on GitHub">Star</a>
</div>
<!-- Place this tag in your head or just before your close body tag. -->
<script defer src="https://buttons.github.io/buttons.js"></script>
</div>
</div>
<!-- Place this tag where you want the button to render. -->
<div class="hidden-mobile" style="text-align: center; margin-top: 0.5rem; filter: scale(2);">
<a class="github-button" href="https://github.com/snowpackjs/snowpack" data-icon="octicon-star" data-size="large"
data-show-count="true" aria-label="Star snowpackjs/snowpack on GitHub">Star</a>
<div class="grid-body">
<article class="markdown-body">
<slot></slot>
</article>
</div>
<!-- Place this tag in your head or just before your close body tag. -->
<script defer src="https://buttons.github.io/buttons.js"></script>
</div>
</div>
<div class="grid-body">
<article class="markdown-body">
<slot></slot>
</article>
</div>
</BaseLayout>
</body>
</html>

View file

@ -1,19 +1,26 @@
---
export const layout = 'layouts/main.astro';
import BaseHead from '../components/BaseHead.astro';
import MainLayout from '../components/MainLayout.astro';
export function setup({ context }) {
return {
context: {
title: '404 - Not Found',
}
};
}
let title = 'Not Found';
let description = 'Snowpack is a lightning-fast frontend build tool, designed for the modern web.';
---
<h2 class="content-title">
{context.title}
</h2>
<html>
<div class="content">
<a href="/">Go Home</a>
</div>
<head>
<BaseHead title={title} description={description} permalink="TODO" />
</head>
<body>
<MainLayout>
<h2 class="content-title">
{title}
</h2>
<div class="content">
<a href="/">Go Home</a>
</div>
</MainLayout>
</body>
</html>

View file

@ -1,73 +1,86 @@
---
import Card from '../components/Card.jsx';
import Card from '../components/Card.jsx';
import BaseHead from '../components/BaseHead.astro';
import MainLayout from '../components/MainLayout.astro';
export const layout = 'layouts/main.astro';
// mocked for now, to be added later
// 1. import {paginate} from 'magicthing';
// 2. export default function ({paginate}) {
function paginate(options) {
if (options.tag === 'guide') {
return [
{ title: 'Test guide 1', href: "#" },
{ title: 'Test guide 2', href: "#" },
];
}
if (options.tag === 'communityGuides') {
return [{ title: 'Test communityGuides', href: "#" }];
}
return [];
// mocked for now, to be added later
// 1. import {paginate} from 'magicthing';
// 2. export default function ({paginate}) {
function paginate(options) {
if (options.tag === 'guide') {
return [
{ title: 'Test guide 1', href: "#" },
{ title: 'Test guide 2', href: "#" },
];
}
export function setup({ context, /* paginate */ }) {
return {
context: {
title: 'Guides',
description: "Snowpack's usage and integration guides.",
guides: paginate({
files: '/posts/guides/*.md',
// sort: ((a, b) => new Date(b) - new Date(a)),
tag: 'guide',
limit: 10,
// page: query.page,
}),
communityGuides: paginate({
files: '/posts/guides/*.md',
// sort: ((a, b) => new Date(b) - new Date(a)),
tag: 'communityGuides',
limit: 10,
}),
}
};
if (options.tag === 'communityGuides') {
return [{ title: 'Test communityGuides', href: "#" }];
}
return [];
}
let title = 'Guides';
let description = 'Snowpack\'s usage and integration guides.';
let guides;
let communityGuides;
export function setup({ /* paginate */ }) {
guides = paginate({
files: '/posts/guides/*.md',
// sort: ((a, b) => new Date(b) - new Date(a)),
tag: 'guide',
limit: 10,
// page: query.page,
});
communityGuides = paginate({
files: '/posts/guides/*.md',
// sort: ((a, b) => new Date(b) - new Date(a)),
tag: 'communityGuides',
limit: 10,
});
return {};
}
---
<h2 class="content-title">
{context.title}
</h2>
<html>
<h3 class="content-title">
Using Snowpack
</h3>
<head>
<BaseHead title={title} description={description} permalink="TODO" />
</head>
<div class="content">
<ul>
{context.guides.map((post) => {
return <li><a href={post.href}>{post.title}</a></li>;
})}
</ul>
</div>
<body>
<MainLayout>
<h2 class="content-title">
{title}
</h2>
<br />
<br />
<h3 class="content-title">
Using Snowpack
</h3>
<h3 class="content-title">
Popular Integration Guides
</h3>
<div class="content">
<ul>
{guides.map((post) => {
return <li><a href={post.href}>{post.title}</a></li>;
})}
</ul>
</div>
<div class="card-grid card-grid-4">
{context.communityGuides.map((post) => {
return
<Card item={post} />;
})}
</div>
<br />
<br />
<h3 class="content-title">
Popular Integration Guides
</h3>
<div class="card-grid card-grid-4">
{communityGuides.map((post) => {
return
<Card item={post} />;
})}
</div>
</MainLayout>
</body>
</html>

View file

@ -1,18 +1,19 @@
---
import Menu from '../components/Menu.astro';
import Hero from '../components/Hero.astro';
import Menu from '../components/Menu.astro';
import Hero from '../components/Hero.astro';
import BaseHead from '../components/BaseHead.astro';
import BaseLayout from '../components/BaseLayout.astro';
export const layout = 'layouts/base.astro';
export function setup({ context }) {
return {};
}
let title = 'Snowpack';
let description = 'Snowpack is a lightning-fast frontend build tool, designed for the modern web.';
---
<astro:head>
<meta charset="AAA" />
<html>
<head>
<style lang="scss">
@use '../../public/css/var' as *;
.top {
text-align: left;
}
@ -56,113 +57,96 @@
margin: 0.5em;
}
</style>
</astro:head>
<Hero bar="{context.title}"></Hero>
<BaseHead title={title} description={description} permalink="TODO" />
</head>
<div foo="{context.title}" class="container" style="margin: 0 auto">
<section class="snow-view__docs is-full is-home">
<aside id="nav-primary" class="snow-view-nav">
<Menu></Menu>
</aside>
<body>
<BaseLayout>
<Hero bar="{title}" />
<div foo="{title}" class="container" style="margin: 0 auto">
<section class="snow-view__docs is-full is-home">
<aside id="nav-primary" class="snow-view-nav">
<Menu></Menu>
</aside>
<article class="snow-view-main">
<div class="content">
<article class="grid-body">
<a
class="img-banner"
href="https://osawards.com/javascript/2020"
target="_blank"
rel="noopener noreferrer"
>
<img
src="/img/JSAwardWinner.png"
alt="2020 JavaScript Open Source Award Winner banner"
/>
</a>
<article class="snow-view-main">
<div class="content">
<article class="grid-body">
<a class="img-banner" href="https://osawards.com/javascript/2020" target="_blank"
rel="noopener noreferrer">
<img src="/img/JSAwardWinner.png" alt="2020 JavaScript Open Source Award Winner banner" />
</a>
<div class="content markdown-body feature-list">
<div class="feature-list-top">
<p>
<strong
>Snowpack is a lightning-fast frontend build tool, designed
for the modern web.</strong
>
It is an alternative to heavier, more complex bundlers like
webpack or Parcel in your development workflow. Snowpack
leverages JavaScript's native module system (<a
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import"
>known as ESM</a
>) to avoid unnecessary work and stay fast no matter how big
your project grows.
</p>
<p>
Once you try it, it's impossible to go back to anything else.
</p>
</div>
<div class="content markdown-body feature-list">
<div class="feature-list-top">
<p>
<strong>Snowpack is a lightning-fast frontend build tool, designed
for the modern web.</strong>
It is an alternative to heavier, more complex bundlers like
webpack or Parcel in your development workflow. Snowpack
leverages JavaScript's native module system (<a
href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import">known
as
ESM</a>) to avoid unnecessary work and stay fast no matter how big
your project grows.
</p>
<p>
Once you try it, it's impossible to go back to anything else.
</p>
</div>
<ul class="feature-list-bullets">
<li class="feature-list-bullet">
<h3>Instant startup</h3>
Snowpack's unbundled web development server
<strong>starts up in 50ms or less</strong>
and stays fast in large projects.
</li>
<li class="feature-list-bullet">
<h3>Build once, cache forever</h3>
Snowpack never builds the same file twice. Powered by
JavaScripts native module system (ESM) in the browser.
</li>
<li class="feature-list-bullet">
<h3>HMR feat. Fast Refresh</h3>
No refresh required. See changes reflected instantly in the
browser with
<a href="/concepts/hot-module-replacement"
>HMR + Fast Refresh</a
>
for React, Preact & Svelte.
</li>
<li class="feature-list-bullet">
<h3>Out-of-the-box support</h3>
Enjoy Snowpack's built-in support for JSX, TypeScript, React,
Preact, CSS Modules
<a href="/reference/supported-files">and more.</a>
</li>
<li class="feature-list-bullet">
<h3>Optimize for production</h3>
Build for production with built-in optimizations and plugin
support for your favorite bundlers.
</li>
<li class="feature-list-bullet">
<h3>Plugins? Plugins!</h3>
Babel? Sass? MDX? Browse the entire
<a href="/plugins">Snowpack Plugin Catalog</a>
to connect your favorite build tool (or
<a href="/reference/plugins">create your own!</a>)
</li>
</ul>
<ul class="feature-list-bullets">
<li class="feature-list-bullet">
<h3>Instant startup</h3>
Snowpack's unbundled web development server
<strong>starts up in 50ms or less</strong>
and stays fast in large projects.
</li>
<li class="feature-list-bullet">
<h3>Build once, cache forever</h3>
Snowpack never builds the same file twice. Powered by
JavaScripts native module system (ESM) in the browser.
</li>
<li class="feature-list-bullet">
<h3>HMR feat. Fast Refresh</h3>
No refresh required. See changes reflected instantly in the
browser with
<a href="/concepts/hot-module-replacement">HMR + Fast Refresh</a>
for React, Preact & Svelte.
</li>
<li class="feature-list-bullet">
<h3>Out-of-the-box support</h3>
Enjoy Snowpack's built-in support for JSX, TypeScript, React,
Preact, CSS Modules
<a href="/reference/supported-files">and more.</a>
</li>
<li class="feature-list-bullet">
<h3>Optimize for production</h3>
Build for production with built-in optimizations and plugin
support for your favorite bundlers.
</li>
<li class="feature-list-bullet">
<h3>Plugins? Plugins!</h3>
Babel? Sass? MDX? Browse the entire
<a href="/plugins">Snowpack Plugin Catalog</a>
to connect your favorite build tool (or
<a href="/reference/plugins">create your own!</a>)
</li>
</ul>
<div class="feature-list-buttons">
<a
href="/tutorials/quick-start"
class="button button-primary feature-list-button"
>Get started</a
>
<a
href="/concepts/how-snowpack-works"
class="button feature-list-button"
>Learn more</a
>
</div>
<div class="feature-list-buttons">
<a href="/tutorials/quick-start" class="button button-primary feature-list-button">Get started</a>
<a href="/concepts/how-snowpack-works" class="button feature-list-button">Learn more</a>
</div>
</div>
</article>
</div>
</article>
</div>
</article>
</section>
</div>
</section>
</div>
</BaseLayout>
<!-- Place this tag in your head or just before your close body tag. -->
<script async="async" defer="defer" src="https://buttons.github.io/buttons.js"></script>
</body>
<!-- Place this tag in your head or just before your close body tag. -->
<script
async="async"
defer="defer"
src="https://buttons.github.io/buttons.js"
></script>
</html>

View file

@ -1,78 +1,86 @@
---
import Card from '../components/Card.jsx';
import CompanyLogo from '../components/CompanyLogo.jsx';
import NewsAssets from '../components/NewsAssets.svelte';
import NewsTitle from '../components/NewsTitle.vue';
import Card from '../components/Card.jsx';
import CompanyLogo from '../components/CompanyLogo.jsx';
import NewsAssets from '../components/NewsAssets.svelte';
import NewsTitle from '../components/NewsTitle.vue';
import BaseHead from '../components/BaseHead.astro';
import MainLayout from '../components/MainLayout.astro';
export const layout = 'layouts/main.astro';
// Using Snowpack? Want to be featured on snowpack.dev?
// Add your project, organization, or company to the end of this list!
import news from '../data/news.json';
import users from '../data/users.json';
import news from '../data/news.json';
import users from '../data/users.json';
let title = 'Community & News';
let description = 'Snowpack community news and companies that use Snowpack.';
let pokemonData;
export async function setup({ context, request, fetch }) {
const pokemonData = await fetch(`https://pokeapi.co/api/v2/pokemon/ditto`);
return {
context: {
title: 'Community & News',
description: "Snowpack community news and companies that use Snowpack.",
// Using Snowpack? Want to be featured on snowpack.dev?
// Add your project, organization, or company to the end of this list!
news,
users,
pokemonData: await pokemonData.json(),
}
}
}
export async function setup({ context, request, fetch }) {
const pokemonDataReq = await fetch(`https://pokeapi.co/api/v2/pokemon/ditto`);
pokemonData = await pokemonDataReq.json();
return {};
}
---
<NewsTitle title={context.title} />
<html>
<p>
Get the latest news, blog posts, and tutorials on Snowpack. <a href="/feed.xml">Also available via RSS.</a>
</p>
<head>
<BaseHead title={title} description={description} permalink="TODO" />
</head>
<p>
Got something that you think we should feature?
<a href="https://github.com/snowpackjs/snowpack/edit/main/www/_data/news.js">Submit it!</a>
</p>
<body>
<MainLayout>
<NewsTitle title={title} />
<p>
Get the latest news, blog posts, and tutorials on Snowpack. <a href="/feed.xml">Also available via RSS.</a>
</p>
<p>
In case you're curious, the best pokemon is <strong>{context.pokemonData.name}.</strong>
</p>
<p>
Got something that you think we should feature?
<a href="https://github.com/snowpackjs/snowpack/edit/main/www/_data/news.js">Submit it!</a>
</p>
<div class="card-grid card-grid-3">
<article class="discord-banner">
<a href="https://discord.gg/snowpack" style="flex-shrink: 0; height: 48px;"><img alt="Join us on Discord!"
src="https://img.shields.io/discord/712696926406967308.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2"
style="height: 48px; border: none; margin-right: 1rem; filter: brightness(1.2) contrast(1.5);" /></a>
<div>Join us on Discord to discuss Snowpack, meet other developers in our community, and show off what youre
working on!</div>
</article>
<p>
In case you're curious, the best pokemon is <strong>{pokemonData.name}.</strong>
</p>
{context.news.reverse().map((item: any) =>
<Card:dynamic item={item} />)}
</div>
<div class="card-grid card-grid-3">
<article class="discord-banner">
<a href="https://discord.gg/snowpack" style="flex-shrink: 0; height: 48px;"><img alt="Join us on Discord!"
src="https://img.shields.io/discord/712696926406967308.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2"
style="height: 48px; border: none; margin-right: 1rem; filter: brightness(1.2) contrast(1.5);" /></a>
<div>Join us on Discord to discuss Snowpack, meet other developers in our community, and show off what youre
working on!</div>
</article>
<div class="content">
{news.reverse().map((item: any) =>
<Card:dynamic item={item} />)}
</div>
<h3>Who's Using Snowpack?</h3>
<div class="content">
<div class="company-logos">
<h3>Who's Using Snowpack?</h3>
{context.users.map((user) =>
<CompanyLogo user={user} />)}
<div class="company-logos">
<a href="https://github.com/snowpackjs/snowpack/edit/main/www/_template/news.md" target="_blank"
title="Add Your Project/Company!" class="add-company-button">
<svg style="height: 22px; margin-right: 8px;" aria-hidden="true" focusable="false" data-prefix="fas"
data-icon="plus" class="company-logo" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
<path fill="currentColor"
d="M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z">
</path>
</svg>
Add your logo
</a>
</div>
{users.map((user) =>
<CompanyLogo user={user} />)}
<NewsAssets />
</div>
<a href="https://github.com/snowpackjs/snowpack/edit/main/www/_template/news.md" target="_blank"
title="Add Your Project/Company!" class="add-company-button">
<svg style="height: 22px; margin-right: 8px;" aria-hidden="true" focusable="false" data-prefix="fas"
data-icon="plus" class="company-logo" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
<path fill="currentColor"
d="M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z">
</path>
</svg>
Add your logo
</a>
</div>
<NewsAssets />
</div>
</MainLayout>
</body>
</html>

View file

@ -1,70 +1,72 @@
---
import news from '../data/news.json';
import users from '../data/users.json';
import PluginSearchPage from '../components/PluginSearchPage.jsx';
import PluginSearchPage from '../components/PluginSearchPage.jsx';
import BaseHead from '../components/BaseHead.astro';
import MainLayout from '../components/MainLayout.astro';
export const layout = 'layouts/main.astro';
export function setup({ context }) {
return {
context: {
title: 'The Snowpack Plugin Catalog',
description:
'Snowpack plugins allow for configuration-minimal tooling integration.',
},
};
}
let title = 'The Snowpack Plugin Catalog';
let description = 'Snowpack plugins allow for configuration-minimal tooling integration.';
---
<style lang="scss">
.intro {
margin-top: 1rem;
margin-bottom: 1rem;
line-height: 1.5;
text-align: left;
<html>
a {
<head>
<BaseHead title={title} description={description} permalink="TODO" />
<style lang="scss">
.intro {
margin-top: 1rem;
margin-bottom: 1rem;
line-height: 1.5;
text-align: left;
a {
color: #2e5e82;
}
}
.subheading {
margin-top: -2.5rem;
margin-bottom: 0;
color: #2e5e82;
font-weight: 500;
font-size: 1em;
font-family: 'Overpass', sans-serif;
letter-spacing: -0.02em;
text-align: left;
@media (min-width: 600px) {
font-size: 1.5em;
}
}
}
.subheading {
margin-top: -2.5rem;
margin-bottom: 0;
color: #2e5e82;
font-weight: 500;
font-size: 1em;
font-family: 'Overpass', sans-serif;
letter-spacing: -0.02em;
text-align: left;
.zero-heading {
margin-top: 1.5rem;
margin-bottom: 1.5rem;
font-weight: 700;
font-size: 1.4em;
text-align: left;
@media (min-width: 600px) {
font-size: 1.5em;
@media (min-width: 600px) {
font-size: 1.5em;
}
}
}
</style>
</head>
.zero-heading {
margin-top: 1.5rem;
margin-bottom: 1.5rem;
font-weight: 700;
font-size: 1.4em;
text-align: left;
<body>
<MainLayout>
<h2 class="content-title">{ title }</h2>
@media (min-width: 600px) {
font-size: 1.5em;
}
}
</style>
<h3 class="pluginPage-subheading">
Customize Snowpack with optimized build plugins.
</h3>
<p class="pluginPage-intro">
To learn more about our plugin system, check out the
<a href="/reference/plugins">Plugin API.</a><br />Can't find what you need?
<a href="/reference/plugins">Creating your own plugin is easy!</a>
</p>
<h2 class="content-title">{ context.title }</h2>
<PluginSearchPage:dynamic />
</MainLayout>
</body>
<h3 class="pluginPage-subheading">
Customize Snowpack with optimized build plugins.
</h3>
<p class="pluginPage-intro">
To learn more about our plugin system, check out the
<a href="/reference/plugins">Plugin API.</a><br />Can't find what you need?
<a href="/reference/plugins">Creating your own plugin is easy!</a>
</p>
<PluginSearchPage:dynamic />
</html>

View file

@ -1,23 +1,34 @@
---
import Subnav from '../components/Subnav.astro';
import { content as Menu } from '../components/Menu.astro';
// import contentful from 'skypack:contentful';
import Subnav from '../components/Subnav.astro';
import Menu from '../components/Menu.astro';
import BaseHead from '../components/BaseHead.astro';
import BaseLayout from '../components/BaseLayout.astro';
// import contentful from 'skypack:contentful';
export default async function ({ params }) {
const entry = await contentful.getEntry(params.slug);
return { title: entry.fields.title, description: entry.fields.description, layout: 'layouts/base.astro', props: { entry } };
}
let title = 'Community & News';
let description = 'Snowpack community news and companies that use Snowpack.';
let entry;
export default async function ({ params }) {
entry = await contentful.getEntry(params.slug);
return { title: entry.fields.title, description: entry.fields.description, layout: 'layouts/base.astro', props: { entry } };
}
---
<div class="container">
<section class="snow-view__docs has-subnav">
<html>
<head>
<BaseHead title={title} description={description} permalink="TODO" />
</head>
<body>
<MainLayout>
<div class="container">
<section class="snow-view__docs has-subnav">
<aside id="nav-primary" class="snow-view-nav">
<Menu />
</aside>
<Subnav title={context.title} headers={context.content.headers} />
<Subnav title={context.title} headers={context.content.headers} />
<article class="snow-view-main">
<div class="content">
<h2 class="content-title">
@ -30,6 +41,9 @@
</div>
</div>
</article>
</section>
</div>
</MainLayout>
</body>
</section>
</div>
</html>

View file

@ -11,7 +11,7 @@ export interface AstroConfig {
dist: string;
projectRoot: URL;
astroRoot: URL;
extensions?: Record<string, ValidExtensionPlugins>
extensions?: Record<string, ValidExtensionPlugins>;
}
export interface JsxItem {
@ -21,7 +21,7 @@ export interface JsxItem {
export interface TransformResult {
script: string;
head: JsxItem | undefined;
props: string[];
items: JsxItem[];
}

View file

@ -99,20 +99,17 @@ const defaultExtensions: Readonly<Record<string, ValidExtensionPlugins>> = {
'.astro': 'astro',
'.jsx': 'react',
'.vue': 'vue',
'.svelte': 'svelte'
'.svelte': 'svelte',
};
function getComponentWrapper(_name: string, { type, url }: ComponentInfo, compileOptions: CompileOptions) {
const {
resolve,
extensions = defaultExtensions
} = compileOptions;
const { resolve, extensions = defaultExtensions } = compileOptions;
const [name, kind] = _name.split(':');
const plugin = extensions[type] || defaultExtensions[type];
if(!plugin) {
if (!plugin) {
throw new Error(`No supported plugin found for extension ${type}`);
}
@ -142,7 +139,9 @@ function getComponentWrapper(_name: string, { type, url }: ComponentInfo, compil
case 'react': {
if (kind === 'dynamic') {
return {
wrapper: `__react_dynamic(${name}, new URL(${JSON.stringify(url.replace(/\.[^.]+$/, '.js'))}, \`http://TEST\${import.meta.url}\`).pathname, '${resolve('react')}', '${resolve('react-dom')}')`,
wrapper: `__react_dynamic(${name}, new URL(${JSON.stringify(url.replace(/\.[^.]+$/, '.js'))}, \`http://TEST\${import.meta.url}\`).pathname, '${resolve(
'react'
)}', '${resolve('react-dom')}')`,
wrapperImport: `import {__react_dynamic} from '${internalImport('render/react.js')}';`,
};
} else {
@ -215,6 +214,9 @@ export async function codegen(ast: Ast, { compileOptions }: CodeGenOptions): Pro
// Compile scripts as TypeScript, always
const script = compileScriptSafe(ast.module ? ast.module.content : '');
// Collect all exported variables for props
const scannedExports = eslexer.parse(script)[1].filter((n) => n !== 'setup' && n !== 'layout');
// Todo: Validate that `h` and `Fragment` aren't defined in the script
const [scriptImports] = eslexer.parse(script, 'optional-sourcename');
const components = Object.fromEntries(
@ -380,7 +382,7 @@ export async function codegen(ast: Ast, { compileOptions }: CodeGenOptions): Pro
return {
script: script + '\n' + Array.from(additionalImports).join('\n'),
head: headItem,
items,
props: scannedExports,
};
}

View file

@ -72,4 +72,4 @@ export default async function (astroConfig: AstroConfig) {
function formatErrorForBrowser(error: Error) {
// TODO make this pretty.
return error.toString();
}
}

View file

@ -3,13 +3,7 @@ import ReactDOMServer from 'react-dom/server';
export function __react_static(ReactComponent: any) {
return (attrs: Record<string, any>, ...children: any): string => {
let html = ReactDOMServer.renderToString(
React.createElement(
ReactComponent,
attrs,
children
)
);
let html = ReactDOMServer.renderToString(React.createElement(ReactComponent, attrs, children));
return html;
};
}

View file

@ -32,4 +32,4 @@ const plugin: HtmlExtension = {
},
};
export { plugin as encodeMarkdown };
export { plugin as encodeMarkdown };

View file

@ -69,6 +69,7 @@ async function load(config: RuntimeConfig, rawPathname: string | undefined): Pro
href: fullurl.toString(),
},
children: [],
props: {},
})) as string;
return {
@ -103,7 +104,7 @@ export async function createRuntime(astroConfig: AstroConfig, logging: LogOption
// Workaround for SKY-251
const astroPlugOptions: {
resolve?: (s: string) => string;
extensions?: Record<string, string>
extensions?: Record<string, string>;
} = { extensions };
if (existsSync(new URL('./package-lock.json', projectRoot))) {
const pkgLockStr = await readFile(new URL('./package-lock.json', projectRoot), 'utf-8');
@ -128,10 +129,7 @@ export async function createRuntime(astroConfig: AstroConfig, logging: LogOption
},
packageOptions: {
knownEntrypoints: ['preact-render-to-string'],
external: [
'@vue/server-renderer',
'node-fetch'
],
external: ['@vue/server-renderer', 'node-fetch'],
},
});
const snowpack = await startSnowpackServer({

View file

@ -52,7 +52,7 @@ async function convertMdToJsx(
contents: string,
{ compileOptions, filename, fileID }: { compileOptions: CompileOptions; filename: string; fileID: string }
): Promise<TransformResult> {
const { data: _frontmatterData, content } = matter(contents);
const { data: frontmatterData, content } = matter(contents);
const { headers, headersExtension } = createMarkdownHeadersCollector();
const mdHtml = micromark(content, {
allowDangerousHtml: true,
@ -60,31 +60,27 @@ async function convertMdToJsx(
htmlExtensions: [gfmHtml, encodeMarkdown, headersExtension],
});
const setupContext = {
..._frontmatterData,
content: {
frontmatter: _frontmatterData,
headers,
source: content,
html: mdHtml,
},
// TODO: Warn if reserved word is used in "frontmatterData"
const contentData: any = {
...frontmatterData,
headers,
source: content,
html: mdHtml,
};
let imports = '';
for(let [ComponentName, specifier] of Object.entries(_frontmatterData.import || {})) {
for (let [ComponentName, specifier] of Object.entries(frontmatterData.import || {})) {
imports += `import ${ComponentName} from '${specifier}';\n`;
}
// </script> can't be anywhere inside of a JS string, otherwise the HTML parser fails.
// Break it up here so that the HTML parser won't detect it.
const stringifiedSetupContext = JSON.stringify(setupContext).replace(/\<\/script\>/g, `</scrip" + "t>`);
const stringifiedSetupContext = JSON.stringify(contentData).replace(/\<\/script\>/g, `</scrip" + "t>`);
const raw = `---
const raw = `---
${imports}
${_frontmatterData.layout ? `export const layout = ${JSON.stringify(_frontmatterData.layout)};` : ''}
export function setup({context}) {
return {context: ${stringifiedSetupContext} };
}
${frontmatterData.layout ? `const __layout = ${JSON.stringify(frontmatterData.layout)};` : ''}
const __content = ${stringifiedSetupContext};
---
<section>${mdHtml}</section>`;
@ -115,11 +111,10 @@ export async function compileComponent(
{ compileOptions = defaultCompileOptions, filename, projectRoot }: { compileOptions: CompileOptions; filename: string; projectRoot: string }
): Promise<CompileResult> {
const sourceJsx = await transformFromSource(source, { compileOptions, filename, projectRoot });
const headItem = sourceJsx.head;
const headItemJsx = !headItem ? 'null' : headItem.jsx;
// sort <style> tags first
// TODO: remove these and inject in <head>
const isPage = path.extname(filename) === '.md' || sourceJsx.items.some((item) => item.name === 'html');
sourceJsx.items.sort((a, b) => (a.name === 'style' && b.name !== 'style' ? -1 : 0));
// return template
@ -127,61 +122,47 @@ export async function compileComponent(
// <script astro></script>
${sourceJsx.script}
// \`__render()\`: Render the contents of the Astro module. "<slot:*>" elements are not
// included (see below).
// \`__render()\`: Render the contents of the Astro module.
import { h, Fragment } from '${internalImport('h.js')}';
export function __slothead(children, context) { return h(Fragment, null, ${headItemJsx}); }
function __render(props, children, context) { return h(Fragment, null, ${sourceJsx.items.map(({ jsx }) => jsx).join(',')}); }
function __render(props, ...children) {
${sourceJsx.props.map((p) => `${p} = props.${p} ?? ${p};`).join('\n')}
return h(Fragment, null, ${sourceJsx.items.map(({ jsx }) => jsx).join(',')});
}
export default __render;
`;
if (headItemJsx) {
if (isPage) {
modJsx += `
// \`__renderPage()\`: Render the contents of the Astro module as a page. This is a special flow,
// triggered by loading a component directly by URL.
// If the page exports a defined "layout", then load + render those first. "context", "astro:head",
// and "slot:body" should all inherit from parent layouts, merging together in the correct order.
export async function __renderPage({request, children}) {
export async function __renderPage({request, children, props}) {
const currentChild = {
__slothead,
__render,
setup: typeof setup === 'undefined' ? (passthrough) => passthrough : setup,
layout: typeof layout === 'undefined' ? undefined : layout,
layout: typeof __layout === 'undefined' ? undefined : __layout,
content: typeof __content === 'undefined' ? undefined : __content,
__render,
};
// find all layouts, going up the layout chain.
const fetch = (await import('node-fetch')).default;
await currentChild.setup({request, fetch});
const childBodyResult = await currentChild.__render(props, children);
// find layout, if one was given.
if (currentChild.layout) {
const layoutComponent = (await import('/_astro/layouts/' + layout.replace(/.*layouts\\//, "").replace(/\.astro$/, '.js')));
const layoutComponent = (await import('/_astro/layouts/' + currentChild.layout.replace(/.*layouts\\//, "").replace(/\.astro$/, '.js')));
return layoutComponent.__renderPage({
request,
children: [currentChild, ...children],
props: {content: currentChild.content},
children: [childBodyResult],
});
}
const isRoot = true;
const merge = (await import('deepmerge')).default;
const fetch = (await import('node-fetch')).default;
// call all children setup scripts, in order, and return.
let mergedContext = {};
for (const child of [currentChild, ...children]) {
const childSetupResult = await child.setup({request, fetch, context: mergedContext});
mergedContext = childSetupResult.context ? merge(mergedContext, childSetupResult.context) : mergedContext;
}
Object.freeze(mergedContext);
let headResult;
let bodyResult;
for (const child of children.reverse()) {
headResult = await child.__slothead([headResult], mergedContext);
bodyResult = await child.__render(undefined, [bodyResult], mergedContext);
}
return h(Fragment, null, [
h("head", null, currentChild.__slothead([headResult], mergedContext)),
h("body", null, currentChild.__render(undefined, [bodyResult], mergedContext)),
]);
return childBodyResult;
};\n`;
} else {
modJsx += `
export async function __renderPage() { throw new Error("No <html> page element found!"); }\n`;
}
return {

View file

@ -1,13 +1,14 @@
---
export function setup() {
return {
props: {}
}
return {props: {}}
}
---
<astro:head>
<!-- Head Stuff -->
</astro:head>
<h1>Hello world!</h1>
<html>
<head>
<!-- Head Stuff -->
</head>
<body>
<h1>Hello world!</h1>
</body>
</html>

View file

@ -1,3 +1,10 @@
<div class="container">
<slot></slot>
</div>
<html>
<head>
<!-- Head Stuff -->
</head>
<body>
<div class="container">
<slot></slot>
</div>
</body>
</html>

View file

@ -1,13 +1,14 @@
---
export function setup() {
return {
props: {}
}
return {props: {}}
}
---
<astro:head>
<!-- Head Stuff -->
</astro:head>
<h1>Hello world!</h1>
<html>
<head>
<!-- Head Stuff -->
</head>
<body>
<h1>Hello world!</h1>
</body>
</html>

View file

@ -2,9 +2,11 @@
import Hello from '../components/Hello.jsx';
---
<astro:head>
<!-- Head Stuff -->
</astro:head>
<h1>My page</h1>
<Hello name="world" />
<html>
<head>
<!-- Head Stuff -->
</head>
<body>
<Hello name="world" />
</body>
</html>

View file

@ -72,7 +72,7 @@ SnowpackDev('Can load every page', async () => {
}
const result = await runtime.load(pathname);
if (result.statusCode === 500) {
failed.push(result);
failed.push({...result, pathname});
continue;
}
assert.equal(result.statusCode, 200, `Loading ${pathname}`);