embedded REPLs

pull/1901/head
Rich Harris 6 years ago
parent 29fd8d7881
commit b58a75b35c

@ -3,10 +3,16 @@
import Nav from '../components/TopNav.html'; import Nav from '../components/TopNav.html';
export let child; export let child;
export let path;
</script> </script>
<InlineSvg /> <InlineSvg />
{#if path !== '/repl/embed'}
<Nav segment={child.segment} /> <Nav segment={child.segment} />
{/if}
{@debug path}
<main> <main>
<svelte:component this={child.component} {...child.props} /> <svelte:component this={child.component} {...child.props} />
</main> </main>

@ -115,6 +115,20 @@
text-align: center; text-align: center;
} }
.example {
display: grid;
grid-template-columns: 1fr 4fr;
align-items: start;
}
iframe {
/* grid-column: 2/4; */
width: 100%;
height: 420px;
border: 1px solid #999;
border-radius: var(--border-r);
}
@media screen and (min-width: 870px) { @media screen and (min-width: 870px) {
.hero h1 { .hero h1 {
position: relative; position: relative;
@ -175,6 +189,38 @@
</div> </div>
</section> </section>
<section class="container grid example">
<div>
<p>Svelte components are written in HTML files. Just add data.</p>
</div>
<iframe src="/repl/embed?gist=0eb9e3a2d22b981b67924c326ed1293a" scrolling="no"></iframe>
</section>
<section class="container grid example">
<div>
<p>CSS is component-scoped by default — no more style collisions or specificity wars. Or you can <a href="TODO-blog-post-on-css-in-js">use your favourite CSS-in-JS library</a>.</p>
</div>
<iframe src="/repl/embed?gist=ea123e7c4e7edc809670eb2dcab25b56" scrolling="no"></iframe>
</section>
<section class="container grid example">
<div>
<p>Trigger updates by assigning to local variables. The compiler does the rest.</p>
</div>
<iframe src="/repl/embed?gist=7b7908b677eb0c374e17f1c5b6287e6e" scrolling="no"></iframe>
</section>
<section class="container grid example">
<div>
<p>Build beautiful UIs with a powerful, performant transition engine built right into the framework.</p>
</div>
<iframe src="/repl/embed?gist=c5336bba9eb1195bb2403aa04ff25186" scrolling="no"></iframe>
</section>
<section class="container grid half"> <section class="container grid half">
<p>TODO finish building this page. Ideas: Who's using Svelte? Example code (interactive, ideally). What else?</p> <p>TODO finish building this page. Ideas: Who's using Svelte? Example code (interactive, ideally). What else?</p>
</section> </section>

@ -104,7 +104,7 @@
{#if view === 'result'} {#if view === 'result'}
<SplitPane type="vertical"> <SplitPane type="vertical" pos={67}>
<div slot="a"> <div slot="a">
{#if bundle} {#if bundle}
<Viewer <Viewer
@ -153,7 +153,7 @@
</section> </section>
</SplitPane> </SplitPane>
{:else} {:else}
<SplitPane type="vertical"> <SplitPane type="vertical" pos={67}>
<div slot="a"> <div slot="a">
<CodeMirror <CodeMirror
mode="javascript" mode="javascript"

@ -6,12 +6,14 @@
export let type; export let type;
export let min = 50; export let min = 50;
export let min1 = min;
export let min2 = min;
export let pos = 50;
const refs = {}; const refs = {};
const side = type === 'horizontal' ? 'left' : 'top'; const side = type === 'horizontal' ? 'left' : 'top';
const dimension = type === 'horizontal' ? 'width' : 'height'; const dimension = type === 'horizontal' ? 'width' : 'height';
let pos = 50;
let dragging = false; let dragging = false;
function setPos(event) { function setPos(event) {

@ -0,0 +1,144 @@
<script>
import { onMount } from 'svelte';
import * as fleece from 'golden-fleece';
import Repl from './_components/Repl.html';
export let query;
let version = query.version;
let gist_id = query.gist;
let gist;
let app = {
components: [],
values: {}
};
let name = 'loading...';
onMount(() => {
fetch(`https://unpkg.com/svelte@${version || 'alpha'}/package.json`)
.then(r => r.json())
.then(pkg => {
version = pkg.version;
});
if (gist_id) {
fetch(`gist/${gist_id}`).then(r => r.json()).then(data => {
gist = data;
const { id, description, files } = data;
name = description;
let values = {};
const components = Object.keys(files)
.map(file => {
const dot = file.lastIndexOf('.');
if (!~dot) return;
const source = files[file].content;
// while we're here...
if (file === 'data.json' || file === 'data.json5') {
values = tryParseData(source) || {};
}
return {
name: file.slice(0, dot),
type: file.slice(dot + 1),
source
};
})
.filter(x => x.type === 'html' || x.type === 'js')
.sort((a, b) => {
if (a.name === 'App' && a.type === 'html') return -1;
if (b.name === 'App' && b.type === 'html') return 1;
if (a.type !== b.type) return a.type === 'html' ? -1 : 1;
return a.name < b.name ? -1 : 1;
});
app = { components, values };
});
} else {
// TODO err...
}
});
function tryParseData(json5) {
try {
return fleece.evaluate(json5);
} catch (err) {
return null;
}
}
</script>
<style>
.repl-outer {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
--pane-controls-h: 4.2rem;
}
.pane { width: 100%; height: 100% }
h3 {
margin: 4rem 0 0 0;
padding: 0 2.4rem .8rem;
font-size: 1.3rem;
}
@media (min-width: 768px) {
.repl-outer {
background-color: var(--back);
overflow: hidden;
box-sizing: border-box;
}
.repl-outer.zen-mode {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 11;
}
}
.loading {
text-align: center;
color: var(--second);
font-weight: 300;
margin: 2em 0 0 0;
opacity: 0;
animation: fade-in .4s;
animation-delay: .2s;
animation-fill-mode: both;
}
@keyframes fade-in {
0% { opacity: 0 }
100% { opacity: 1 }
}
.input {
padding: 2.4em 0 0 0;
}
</style>
<svelte:head>
<title>{name} • Svelte REPL</title>
</svelte:head>
<div class="repl-outer">
{#if process.browser}
<Repl {version} {app}/>
{/if}
</div>
Loading…
Cancel
Save