start adding site to main repo

This commit is contained in:
Richard Harris
2019-04-28 14:37:02 -04:00
parent 01dd08849a
commit 36f91d4e9a
76 changed files with 6165 additions and 0 deletions

6
site/src/client.js Normal file
View File

@@ -0,0 +1,6 @@
import '@sveltejs/site-kit/base.css';
import * as sapper from '@sapper/app';
sapper.start({
target: document.querySelector('#sapper')
});

View File

@@ -0,0 +1,60 @@
<script>
export let segment;
</script>
<style>
nav {
border-bottom: 1px solid rgba(170,30,30,0.1);
font-weight: 300;
padding: 0 1em;
}
ul {
margin: 0;
padding: 0;
}
/* clearfix */
ul::after {
content: '';
display: block;
clear: both;
}
li {
display: block;
float: left;
}
.selected {
position: relative;
display: inline-block;
}
.selected::after {
position: absolute;
content: '';
width: calc(100% - 1em);
height: 2px;
background-color: rgb(170,30,30);
display: block;
bottom: -1px;
}
a {
text-decoration: none;
padding: 1em 0.5em;
display: block;
}
</style>
<nav>
<ul>
<li><a class='{segment === undefined ? "selected" : ""}' href='.'>home</a></li>
<li><a class='{segment === "about" ? "selected" : ""}' href='about'>about</a></li>
<!-- for the blog link, we're using rel=prefetch so that Sapper prefetches
the blog data when we hover over the link or tap it on a touchscreen -->
<li><a rel=prefetch class='{segment === "blog" ? "selected" : ""}' href='blog'>blog</a></li>
</ul>
</nav>

View File

@@ -0,0 +1,40 @@
<script>
export let status;
export let error;
const dev = process.env.NODE_ENV === 'development';
</script>
<style>
h1, p {
margin: 0 auto;
}
h1 {
font-size: 2.8em;
font-weight: 700;
margin: 0 0 0.5em 0;
}
p {
margin: 1em auto;
}
@media (min-width: 480px) {
h1 {
font-size: 4em;
}
}
</style>
<svelte:head>
<title>{status}</title>
</svelte:head>
<h1>{status}</h1>
<p>{error.message}</p>
{#if dev && error.stack}
<pre>{error.stack}</pre>
{/if}

View File

@@ -0,0 +1,37 @@
<script>
import { page } from '@sapper/app';
import { Icons, Icon, Nav, NavItem } from '@sveltejs/site-kit';
export let segment;
</script>
<style>
main {
position: relative;
margin: 0 auto;
/* padding: var(--nav-h) var(--side-nav) 0 var(--side-nav); */
padding: var(--nav-h) 0 0 0;
overflow-x: hidden;
--prime: rgb(21, 151, 148);
}
</style>
<Icons/>
<Nav {segment} {page} logo="sapper-logo-horizontal.svg">
<NavItem segment="guide">Guide</NavItem>
<NavItem external="https://svelte.dev">Svelte</NavItem>
<NavItem external="https://discord.gg/yy75DKs" title="Discord Chat">
<Icon name="message-square"/>
</NavItem>
<NavItem external="https://github.com/sveltejs/sapper" title="GitHub Repo">
<Icon name="github"/>
</NavItem>
</Nav>
<main>
<slot></slot>
</main>

View File

@@ -0,0 +1,15 @@
export default function process_markdown(markdown) {
const match = /---\n([\s\S]+?)\n---/.exec(markdown);
const frontMatter = match[1];
const content = markdown.slice(match[0].length);
const metadata = {};
frontMatter.split('\n').forEach(pair => {
const colonIndex = pair.indexOf(':');
metadata[pair.slice(0, colonIndex).trim()] = pair
.slice(colonIndex + 1)
.trim();
});
return { metadata, content };
}

View File

@@ -0,0 +1,82 @@
import fs from 'fs';
import path from 'path';
import process_markdown from './_process_markdown.js';
import marked from 'marked';
import hljs from 'highlight.js';
const langs = {
'hidden-data': 'json',
'html-no-repl': 'html'
};
function btoa(str) {
return new Buffer(str).toString('base64');
}
const escaped = {
'"': '&quot;',
"'": '&#39;',
'&': '&amp;',
'<': '&lt;',
'>': '&gt;'
};
const unescaped = Object.keys(escaped).reduce(
(unescaped, key) => ((unescaped[escaped[key]] = key), unescaped),
{}
);
function unescape(str) {
return String(str).replace(/&.+?;/g, match => unescaped[match] || match);
}
export default () => fs
.readdirSync(`content/guide`)
.filter(file => file[0] !== '.' && path.extname(file) === '.md')
.map(file => {
const markdown = fs.readFileSync(`content/guide/${file}`, 'utf-8');
const { content, metadata } = process_markdown(markdown);
// syntax highlighting
let uid = 0;
const highlighted = {};
const tweaked_content = content.replace(
/```([\w-]+)?\n([\s\S]+?)```/g,
(match, lang, code) => {
const { value } = hljs.highlight(lang, code);
highlighted[++uid] = value;
return `@@${uid}`;
}
);
const html = marked(tweaked_content)
.replace(/<p>@@(\d+)<\/p>/g, (match, id) => {
return `<pre><code>${highlighted[id]}</code></pre>`;
})
.replace(/^\t+/gm, match => match.split('\t').join(' '));
const subsections = [];
const pattern = /<h3 id="(.+?)">(.+?)<\/h3>/g;
let match;
while ((match = pattern.exec(html))) {
const slug = match[1];
// const title = unescape(
// match[2].replace(/<\/?code>/g, '').replace(/\.(\w+)\W.*/, '.$1')
// );
const title = unescape(match[2]);
subsections.push({ slug, title });
}
return {
html,
metadata,
subsections,
slug: file.replace(/^\d+-/, '').replace(/\.md$/, ''),
file
};
});

View File

@@ -0,0 +1,16 @@
import sections from './_sections.js';
const dev = process.env.NODE_ENV === 'development';
let json;
export function get(req, res) {
if (dev || !json) {
json = JSON.stringify(sections());
}
res.set({
'Content-Type': 'application/json',
'Cache-Control': `max-age=${30 * 60 * 1e3}` // 30 minutes
});
res.end(json);
}

View File

@@ -0,0 +1 @@
TODO

View File

@@ -0,0 +1,70 @@
<script>
import { Hero, Blurb } from '@sveltejs/site-kit';
</script>
<style>
</style>
<svelte:head>
<title>Sapper • The next small thing in web development</title>
</svelte:head>
<Hero
title="Sapper"
tagline="The next small thing in web development"
outline="sapper-logo-outline.svg"
logotype="sapper-logotype.svg"
/>
<Blurb>
<a href="https://svelte.dev" slot="one">
<h2>Powered by Svelte</h2>
<p>Sapper is an application framework powered by Svelte — build bigger apps with a smaller footprint</p>
<span class="learn-more">learn more</span>
</a>
<a href="TKTK" slot="two">
<h2>Best of both worlds</h2>
<p>All the SEO and progressive enhancement of a server-rendered app, with the slick navigation of an SPA</p>
<span class="learn-more">learn more</span>
</a>
<a href="TKTK" slot="three">
<h2>Build fast</h2>
<p>Hit the ground running with advanced routing, server-side rendering, code-splitting, offline support and more</p>
<span class="learn-more">learn more</span>
</a>
<!-- <a href="TKTK" slot="three">
<h2>Works everywhere</h2>
<p>Deploy as a cloud function or a traditional Node.js app, or export your app as a collection of static files</p>
<span class="learn-more">learn more</span>
</a> -->
<div class="description" slot="what">
<p>Sapper is a framework for building web applications of all sizes, with a beautiful development experience and flexible filesystem-based routing.</p>
<p>Unlike single-page apps, Sapper doesn't compromise on SEO, progressive enhancement or the initial load experience — but unlike traditional server-rendered apps, navigation is instantaneous for that app-like feel.</p>
<p><a href="https://svelte.dev/blog/sapper-towards-the-ideal-web-app-framework">Read the introductory blog post</a> to learn more.</p>
</div>
<div style="grid-area: start; display: flex; flex-direction: column; min-width: 0" slot="how">
<pre class="language-bash" style="margin: 0 0 1em 0; min-width: 0; min-height: 0">
npx degit sveltejs/template my-svelte-project
cd my-svelte-project
npm install
npm run dev & open http://localhost:5000
</pre>
<p style="flex: 1">See the <a href="blog/the-easiest-way-to-get-started">quickstart guide</a> for more information.</p>
<p class="cta"><a rel="prefetch" href="tutorial">Learn Svelte</a></p>
</div>
</Blurb>

17
site/src/server.js Normal file
View File

@@ -0,0 +1,17 @@
import sirv from 'sirv';
import polka from 'polka';
import compression from 'compression';
import * as sapper from '@sapper/server';
const { PORT, NODE_ENV } = process.env;
const dev = NODE_ENV === 'development';
polka() // You can also use Express
.use(
compression({ threshold: 0 }),
sirv('static', { dev }),
sapper.middleware()
)
.listen(PORT, err => {
if (err) console.log('error', err);
});

View File

@@ -0,0 +1,82 @@
import { timestamp, files, shell, routes } from '@sapper/service-worker';
const ASSETS = `cache${timestamp}`;
// `shell` is an array of all the files generated by the bundler,
// `files` is an array of everything in the `static` directory
const to_cache = shell.concat(files);
const cached = new Set(to_cache);
self.addEventListener('install', event => {
event.waitUntil(
caches
.open(ASSETS)
.then(cache => cache.addAll(to_cache))
.then(() => {
self.skipWaiting();
})
);
});
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(async keys => {
// delete old caches
for (const key of keys) {
if (key !== ASSETS) await caches.delete(key);
}
self.clients.claim();
})
);
});
self.addEventListener('fetch', event => {
if (event.request.method !== 'GET' || event.request.headers.has('range')) return;
const url = new URL(event.request.url);
// don't try to handle e.g. data: URIs
if (!url.protocol.startsWith('http')) return;
// ignore dev server requests
if (url.hostname === self.location.hostname && url.port !== self.location.port) return;
// always serve static files and bundler-generated assets from cache
if (url.host === self.location.host && cached.has(url.pathname)) {
event.respondWith(caches.match(event.request));
return;
}
// for pages, you might want to serve a shell `service-worker-index.html` file,
// which Sapper has generated for you. It's not right for every
// app, but if it's right for yours then uncomment this section
/*
if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) {
event.respondWith(caches.match('/service-worker-index.html'));
return;
}
*/
if (event.request.cache === 'only-if-cached') return;
// for everything else, try the network first, falling back to
// cache if the user is offline. (If the pages never change, you
// might prefer a cache-first approach to a network-first one.)
event.respondWith(
caches
.open(`offline${timestamp}`)
.then(async cache => {
try {
const response = await fetch(event.request);
cache.put(event.request, response.clone());
return response;
} catch(err) {
const response = await cache.match(event.request);
if (response) return response;
throw err;
}
})
);
});

38
site/src/template.html Normal file
View File

@@ -0,0 +1,38 @@
<!doctype html>
<html lang='en' class="theme-default typo-default">
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width;initial-scale=1.0'>
<meta name='theme-color' content='#ff3e00'>
%sapper.base%
<link href=prism.css rel=stylesheet>
<link rel='manifest' href='manifest.json'>
<link rel='icon' type='image/png' href='favicon.png'>
<meta name='twitter:card' content='summary_large_image'>
<meta name='twitter:site' content='@sveltejs'>
<meta name='twitter:creator' content='@sveltejs'>
<meta name='twitter:image' content='https://sapper.svelte.dev/images/twitter-card.png'>
<!-- Sapper generates a <style> tag containing critical CSS
for the current page. CSS for the rest of the app is
lazily loaded when it precaches secondary pages -->
%sapper.styles%
<!-- This contains the contents of the <svelte:head> component, if
the current page has one -->
%sapper.head%
</head>
<body>
<!-- The application will be rendered inside this element,
because `app/client.js` references it -->
<div id='sapper'>%sapper.html%</div>
<!-- Sapper creates a <script> tag containing `app/client.js`
and anything else it needs to hydrate the app and
initialise the router -->
%sapper.scripts%
</body>
</html>