mirror of https://github.com/sveltejs/svelte
parent
2e6f9c4214
commit
a4f79544b4
@ -1,65 +0,0 @@
|
|||||||
import send from '@polka/send';
|
|
||||||
import { body } from './_utils.js';
|
|
||||||
import { query } from '../../utils/db';
|
|
||||||
import { isUser } from '../../backend/auth';
|
|
||||||
|
|
||||||
export async function get(req, res) {
|
|
||||||
const [row] = await query(`
|
|
||||||
select g.*, u.uid as owner from gists g
|
|
||||||
left join users u on g.user_id = u.id
|
|
||||||
where g.uid = $1 limit 1
|
|
||||||
`, [req.params.id]); // via filename pattern
|
|
||||||
|
|
||||||
if (!row) {
|
|
||||||
return send(res, 404, { error: 'Gist not found' });
|
|
||||||
}
|
|
||||||
|
|
||||||
send(res, 200, {
|
|
||||||
uid: row.uid,
|
|
||||||
name: row.name,
|
|
||||||
files: row.files,
|
|
||||||
owner: row.owner
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function patch(req, res) {
|
|
||||||
const user = await isUser(req, res);
|
|
||||||
if (!user) return; // response already sent
|
|
||||||
|
|
||||||
let id, uid=req.params.id;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const [row] = await query(`select * from gists where uid = $1 limit 1`, [uid]);
|
|
||||||
if (!row) return send(res, 404, { error: 'Gist not found' });
|
|
||||||
if (row.user_id !== user.id) return send(res, 403, { error: 'Item does not belong to you' });
|
|
||||||
id = row.id;
|
|
||||||
} catch (err) {
|
|
||||||
console.error('PATCH /gists @ select', err);
|
|
||||||
return send(res, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const obj = await body(req);
|
|
||||||
obj.updated_at = 'now()';
|
|
||||||
let k, cols=[], vals=[];
|
|
||||||
for (k in obj) {
|
|
||||||
cols.push(k);
|
|
||||||
vals.push(obj[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const tmp = vals.map((x, i) => `$${i + 1}`).join(',');
|
|
||||||
const set = `set (${cols.join(',')}) = (${tmp})`;
|
|
||||||
|
|
||||||
const [row] = await query(`update gists ${set} where id = ${id} returning *`, vals);
|
|
||||||
|
|
||||||
send(res, 200, {
|
|
||||||
uid: row.uid,
|
|
||||||
name: row.name,
|
|
||||||
files: row.files,
|
|
||||||
owner: user.uid,
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
console.error('PATCH /gists @ update', err);
|
|
||||||
send(res, 500, { error: err.message });
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
import { user, logout } from '../../../../user.js';
|
import { user, logout } from '../../../../../user.js';
|
||||||
|
|
||||||
let showMenu = false;
|
let showMenu = false;
|
||||||
let name;
|
let name;
|
@ -0,0 +1,134 @@
|
|||||||
|
import send from '@polka/send';
|
||||||
|
import redirect from '@polka/redirect';
|
||||||
|
import body from '../_utils/body.js';
|
||||||
|
import * as httpie from 'httpie';
|
||||||
|
import { query, find } from '../../../utils/db';
|
||||||
|
import { isUser } from '../../../backend/auth';
|
||||||
|
import { get_example } from '../../examples/_examples.js';
|
||||||
|
|
||||||
|
const { GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET } = process.env;
|
||||||
|
|
||||||
|
async function import_gist(req, res) {
|
||||||
|
const base = `https://api.github.com/gists/${req.params.id}`;
|
||||||
|
const url = `${base}?client_id=${GITHUB_CLIENT_ID}&client_secret=${GITHUB_CLIENT_SECRET}`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { data } = await httpie.get(url, {
|
||||||
|
headers: {
|
||||||
|
'User-Agent': 'https://svelte.dev'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// create owner if necessary...
|
||||||
|
let user = await find(`select * from users where uid = $1`, [data.owner.id]);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
const { id, name, login, avatar_url } = data.owner;
|
||||||
|
|
||||||
|
[user] = await query(`
|
||||||
|
insert into users(uid, name, username, avatar)
|
||||||
|
values ($1, $2, $3, $4) on conflict (uid) do nothing
|
||||||
|
returning *
|
||||||
|
`, [id, name, login, avatar_url]);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete data.files['README.md'];
|
||||||
|
delete data.files['meta.json'];
|
||||||
|
|
||||||
|
const files = Object.keys(data.files).map(key => {
|
||||||
|
const name = key.replace(/\.html$/, '.svelte');
|
||||||
|
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
source: data.files[key].content
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// add gist to database...
|
||||||
|
const [gist] = await query(`
|
||||||
|
insert into gists(uid, user_id, name, files)
|
||||||
|
values ($1, $2, $3, $4) returning *`, [req.params.id, user.id, data.description, JSON.stringify(files)]);
|
||||||
|
|
||||||
|
send(res, 200, {
|
||||||
|
uid: req.params.id,
|
||||||
|
name: data.description,
|
||||||
|
files,
|
||||||
|
owner: data.owner.id
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
send(res, err.statusCode, { error: err.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function get(req, res) {
|
||||||
|
// is this an example?
|
||||||
|
const example = get_example(req.params.id);
|
||||||
|
|
||||||
|
if (example) {
|
||||||
|
return send(res, 200, {
|
||||||
|
uid: req.params.id,
|
||||||
|
name: example.title,
|
||||||
|
files: example.files,
|
||||||
|
owner: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const [row] = await query(`
|
||||||
|
select g.*, u.uid as owner from gists g
|
||||||
|
left join users u on g.user_id = u.id
|
||||||
|
where g.uid = $1 limit 1
|
||||||
|
`, [req.params.id]); // via filename pattern
|
||||||
|
|
||||||
|
if (!row) {
|
||||||
|
return import_gist(req, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
send(res, 200, {
|
||||||
|
uid: row.uid.replace(/-/g, ''),
|
||||||
|
name: row.name,
|
||||||
|
files: row.files,
|
||||||
|
owner: row.owner
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function patch(req, res) {
|
||||||
|
const user = await isUser(req, res);
|
||||||
|
if (!user) return; // response already sent
|
||||||
|
|
||||||
|
let id, uid=req.params.id;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const [row] = await query(`select * from gists where uid = $1 limit 1`, [uid]);
|
||||||
|
if (!row) return send(res, 404, { error: 'Gist not found' });
|
||||||
|
if (row.user_id !== user.id) return send(res, 403, { error: 'Item does not belong to you' });
|
||||||
|
id = row.id;
|
||||||
|
} catch (err) {
|
||||||
|
console.error('PATCH /gists @ select', err);
|
||||||
|
return send(res, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const obj = await body(req);
|
||||||
|
obj.updated_at = 'now()';
|
||||||
|
let k, cols=[], vals=[];
|
||||||
|
for (k in obj) {
|
||||||
|
cols.push(k);
|
||||||
|
vals.push(obj[k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tmp = vals.map((x, i) => `$${i + 1}`).join(',');
|
||||||
|
const set = `set (${cols.join(',')}) = (${tmp})`;
|
||||||
|
|
||||||
|
const [row] = await query(`update gists ${set} where id = ${id} returning *`, vals);
|
||||||
|
|
||||||
|
send(res, 200, {
|
||||||
|
uid: row.uid.replace(/-/g, ''),
|
||||||
|
name: row.name,
|
||||||
|
files: row.files,
|
||||||
|
owner: user.uid,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error('PATCH /gists @ update', err);
|
||||||
|
send(res, 500, { error: err.message });
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,209 @@
|
|||||||
|
<script context="module">
|
||||||
|
export function preload({ params, query }) {
|
||||||
|
return {
|
||||||
|
version: query.version || '3',
|
||||||
|
id: params.id
|
||||||
|
};
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Repl from '@sveltejs/svelte-repl';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
|
import { process_example } from '../../../utils/examples';
|
||||||
|
import InputOutputToggle from '../../../components/Repl/InputOutputToggle.svelte';
|
||||||
|
import AppControls from './_components/AppControls/index.svelte';
|
||||||
|
|
||||||
|
export let version;
|
||||||
|
export let id;
|
||||||
|
|
||||||
|
let repl;
|
||||||
|
let gist;
|
||||||
|
let name = 'Loading...';
|
||||||
|
let zen_mode = false;
|
||||||
|
let relaxed = false;
|
||||||
|
let width = process.browser ? window.innerWidth : 1000;
|
||||||
|
let checked = false;
|
||||||
|
|
||||||
|
$: if (typeof history !== 'undefined') {
|
||||||
|
const params = [];
|
||||||
|
|
||||||
|
if (version !== 'latest') params.push(`version=${version}`);
|
||||||
|
|
||||||
|
const url = params.length > 0
|
||||||
|
? `repl/${id}?${params.join('&')}`
|
||||||
|
: `repl/${id}`;
|
||||||
|
|
||||||
|
history.replaceState({}, 'x', url);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (version !== 'local') {
|
||||||
|
fetch(`https://unpkg.com/svelte@${version || '3'}/package.json`)
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(pkg => {
|
||||||
|
version = pkg.version;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO handle `relaxed` logic
|
||||||
|
|
||||||
|
fetch(`repl/${id}.json`).then(r => {
|
||||||
|
if (r.ok) {
|
||||||
|
r.json().then(data => {
|
||||||
|
gist = data;
|
||||||
|
name = data.name;
|
||||||
|
|
||||||
|
const rgx = /(js|svelte)$/i;
|
||||||
|
const components = data.files.map(file => {
|
||||||
|
let [name, type] = file.name.split('.');
|
||||||
|
if (type === 'html') type = 'svelte'; // TODO do this on the server
|
||||||
|
return { name, type, source: file.source };
|
||||||
|
});
|
||||||
|
|
||||||
|
components.sort((a, b) => {
|
||||||
|
if (a.name === 'App' && a.type === 'svelte') return -1;
|
||||||
|
if (b.name === 'App' && b.type === 'svelte') return 1;
|
||||||
|
|
||||||
|
if (a.type !== b.type) return a.type === 'svelte' ? -1 : 1;
|
||||||
|
|
||||||
|
return a.name < b.name ? -1 : 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
repl.set({ components });
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.warn('TODO: 404 Gist')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function handle_fork(event) {
|
||||||
|
example = null;
|
||||||
|
console.log('> handle_fork', event);
|
||||||
|
gist = event.detail.gist;
|
||||||
|
gist_id = gist.uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
$: svelteUrl = process.browser && version === 'local' ?
|
||||||
|
`${location.origin}/repl/local` :
|
||||||
|
`https://unpkg.com/svelte@${version}`;
|
||||||
|
|
||||||
|
const rollupUrl = `https://unpkg.com/rollup@1/dist/rollup.browser.js`;
|
||||||
|
|
||||||
|
// needed for context API example
|
||||||
|
const mapbox_setup = `window.MAPBOX_ACCESS_TOKEN = process.env.MAPBOX_ACCESS_TOKEN;`;
|
||||||
|
|
||||||
|
$: mobile = width < 540;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.repl-outer {
|
||||||
|
position: relative;
|
||||||
|
height: calc(100vh - var(--nav-h));
|
||||||
|
--app-controls-h: 5.6rem;
|
||||||
|
--pane-controls-h: 4.2rem;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: var(--back);
|
||||||
|
padding: var(--app-controls-h) 0 0 0;
|
||||||
|
/* margin: 0 calc(var(--side-nav) * -1); */
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewport {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile .viewport {
|
||||||
|
width: 200%;
|
||||||
|
height: calc(100% - 42px);
|
||||||
|
transition: transform 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile .offset {
|
||||||
|
transform: translate(-50%, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* temp fix for #2499 and #2550 while waiting for a fix for https://github.com/sveltejs/svelte-repl/issues/8 */
|
||||||
|
|
||||||
|
.viewport :global(.tab-content),
|
||||||
|
.viewport :global(.tab-content.visible) {
|
||||||
|
pointer-events: all;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
.viewport :global(.tab-content) {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
.viewport :global(.tab-content.visible) {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zen-mode {
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
z-index: 111;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pane { width: 100%; height: 100% }
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
text-align: center;
|
||||||
|
color: var(--second);
|
||||||
|
font-weight: 400;
|
||||||
|
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} • REPL • Svelte</title>
|
||||||
|
|
||||||
|
<meta name="twitter:title" content="Svelte REPL">
|
||||||
|
<meta name="twitter:description" content="Cybernetically enhanced web apps">
|
||||||
|
<meta name="Description" content="Interactive Svelte playground">
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
|
<svelte:window bind:innerWidth={width}/>
|
||||||
|
|
||||||
|
<div class="repl-outer {zen_mode ? 'zen-mode' : ''}" class:mobile>
|
||||||
|
<AppControls
|
||||||
|
{gist}
|
||||||
|
{repl}
|
||||||
|
bind:name
|
||||||
|
bind:zen_mode
|
||||||
|
on:forked={handle_fork}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{#if process.browser}
|
||||||
|
<div class="viewport" class:offset={checked}>
|
||||||
|
<Repl
|
||||||
|
bind:this={repl}
|
||||||
|
{svelteUrl}
|
||||||
|
{rollupUrl}
|
||||||
|
{relaxed}
|
||||||
|
fixed={mobile}
|
||||||
|
injectedJS={mapbox_setup}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if mobile}
|
||||||
|
<InputOutputToggle bind:checked/>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
</div>
|
@ -1,4 +1,4 @@
|
|||||||
export function body(req) {
|
export default function body(req) {
|
||||||
return new Promise((fulfil, reject) => {
|
return new Promise((fulfil, reject) => {
|
||||||
let str = '';
|
let str = '';
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
import send from '@polka/send';
|
import send from '@polka/send';
|
||||||
import { body } from './_utils.js';
|
import body from './_utils/body.js';
|
||||||
import { query } from '../../utils/db';
|
import { query } from '../../utils/db';
|
||||||
import { isUser } from '../../backend/auth';
|
import { isUser } from '../../backend/auth';
|
||||||
|
|
@ -1,238 +1,16 @@
|
|||||||
<script context="module">
|
<script context="module">
|
||||||
export function preload({ query }) {
|
export function preload({ query }) {
|
||||||
if (/^[^>]?[12]/.test(query.version)) {
|
const { gist, example, version } = query;
|
||||||
const search = Object.keys(query).map(key => `${key}=${query[key]}`).join('&');
|
|
||||||
return this.redirect(302, `https://v2.svelte.dev/repl?${search}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
version: query.version || '3',
|
|
||||||
gist_id: query.gist,
|
|
||||||
example: query.example || 'hello-world'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import Repl from '@sveltejs/svelte-repl';
|
|
||||||
import { onMount } from 'svelte';
|
|
||||||
|
|
||||||
import { process_example } from '../../utils/examples';
|
|
||||||
import InputOutputToggle from '../../components/Repl/InputOutputToggle.svelte';
|
|
||||||
import AppControls from './_components/AppControls/index.svelte';
|
|
||||||
|
|
||||||
export let version;
|
|
||||||
export let example;
|
|
||||||
export let gist_id;
|
|
||||||
|
|
||||||
let repl;
|
|
||||||
let gist;
|
|
||||||
let name = 'Loading...';
|
|
||||||
let zen_mode = false;
|
|
||||||
let relaxed = false;
|
|
||||||
let width = process.browser ? window.innerWidth : 1000;
|
|
||||||
let checked = false;
|
|
||||||
|
|
||||||
$: if (typeof history !== 'undefined') {
|
// redirect to v2 REPL if appropriate
|
||||||
const params = [];
|
if (/^[^>]?[12]/.test(version)) {
|
||||||
|
const q = Object.keys(query).map(key => `${key}=${query[key]}`).join('&');
|
||||||
if (version !== 'latest') params.push(`version=${version}`);
|
return this.redirect(302, `https://v2.svelte.dev/repl?${q}`);
|
||||||
if (gist_id) params.push(`gist=${gist_id}`);
|
|
||||||
else if (example) params.push(`example=${example}`);
|
|
||||||
|
|
||||||
const url = params.length > 0
|
|
||||||
? `repl?${params.join('&')}`
|
|
||||||
: 'repl';
|
|
||||||
|
|
||||||
history.replaceState({}, 'x', url);
|
|
||||||
}
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
if (version !== 'local') {
|
|
||||||
fetch(`https://unpkg.com/svelte@${version || '3'}/package.json`)
|
|
||||||
.then(r => r.json())
|
|
||||||
.then(pkg => {
|
|
||||||
version = pkg.version;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gist_id) {
|
const id = gist || example || 'hello-world';
|
||||||
relaxed = false;
|
const q = version ? `?version=${version}` : ``;
|
||||||
fetch(`gist/${gist_id}`).then(r => {
|
|
||||||
if (r.ok) {
|
|
||||||
r.json().then(data => {
|
|
||||||
gist = data;
|
|
||||||
name = data.name;
|
|
||||||
|
|
||||||
const components = [];
|
|
||||||
const files = data.files;
|
|
||||||
const rgx = /(js|svelte)$/i;
|
|
||||||
|
|
||||||
Object.keys(files).forEach(key => {
|
|
||||||
let [name, type] = key.split('.');
|
|
||||||
if (type === 'html') type = 'svelte';
|
|
||||||
if (rgx.test(type)) {
|
|
||||||
components.push({ name, type, source:files[key] });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
components.sort((a, b) => {
|
|
||||||
if (a.name === 'App' && a.type === 'svelte') return -1;
|
|
||||||
if (b.name === 'App' && b.type === 'svelte') return 1;
|
|
||||||
|
|
||||||
if (a.type !== b.type) return a.type === 'svelte' ? -1 : 1;
|
|
||||||
|
|
||||||
return a.name < b.name ? -1 : 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
repl.set({ components });
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.warn('TODO: 404 Gist')
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
relaxed = true;
|
|
||||||
fetch(`examples/${example}.json`).then(async response => {
|
|
||||||
if (response.ok) {
|
|
||||||
const data = await response.json();
|
|
||||||
|
|
||||||
name = data.title;
|
|
||||||
|
|
||||||
const components = process_example(data.files);
|
|
||||||
repl.set({ components });
|
|
||||||
|
|
||||||
gist = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function handle_fork(event) {
|
|
||||||
example = null;
|
|
||||||
console.log('> handle_fork', event);
|
|
||||||
gist = event.detail.gist;
|
|
||||||
gist_id = gist.uid;
|
|
||||||
}
|
|
||||||
|
|
||||||
$: svelteUrl = process.browser && version === 'local' ?
|
|
||||||
`${location.origin}/repl/local` :
|
|
||||||
`https://unpkg.com/svelte@${version}`;
|
|
||||||
|
|
||||||
const rollupUrl = `https://unpkg.com/rollup@1/dist/rollup.browser.js`;
|
|
||||||
|
|
||||||
// needed for context API example
|
|
||||||
const mapbox_setup = `window.MAPBOX_ACCESS_TOKEN = process.env.MAPBOX_ACCESS_TOKEN;`;
|
|
||||||
|
|
||||||
$: mobile = width < 540;
|
this.redirect(301, `repl/${id}${q}`);
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.repl-outer {
|
|
||||||
position: relative;
|
|
||||||
height: calc(100vh - var(--nav-h));
|
|
||||||
--app-controls-h: 5.6rem;
|
|
||||||
--pane-controls-h: 4.2rem;
|
|
||||||
overflow: hidden;
|
|
||||||
background-color: var(--back);
|
|
||||||
padding: var(--app-controls-h) 0 0 0;
|
|
||||||
/* margin: 0 calc(var(--side-nav) * -1); */
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.viewport {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mobile .viewport {
|
|
||||||
width: 200%;
|
|
||||||
height: calc(100% - 42px);
|
|
||||||
transition: transform 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mobile .offset {
|
|
||||||
transform: translate(-50%, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* temp fix for #2499 and #2550 while waiting for a fix for https://github.com/sveltejs/svelte-repl/issues/8 */
|
|
||||||
|
|
||||||
.viewport :global(.tab-content),
|
|
||||||
.viewport :global(.tab-content.visible) {
|
|
||||||
pointer-events: all;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
.viewport :global(.tab-content) {
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
.viewport :global(.tab-content.visible) {
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.zen-mode {
|
|
||||||
position: fixed;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
top: 0;
|
|
||||||
z-index: 111;
|
|
||||||
}
|
}
|
||||||
|
</script>
|
||||||
.pane { width: 100%; height: 100% }
|
|
||||||
|
|
||||||
.loading {
|
|
||||||
text-align: center;
|
|
||||||
color: var(--second);
|
|
||||||
font-weight: 400;
|
|
||||||
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} • REPL • Svelte</title>
|
|
||||||
|
|
||||||
<meta name="twitter:title" content="Svelte REPL">
|
|
||||||
<meta name="twitter:description" content="Cybernetically enhanced web apps">
|
|
||||||
<meta name="Description" content="Interactive Svelte playground">
|
|
||||||
</svelte:head>
|
|
||||||
|
|
||||||
<svelte:window bind:innerWidth={width}/>
|
|
||||||
|
|
||||||
<div class="repl-outer {zen_mode ? 'zen-mode' : ''}" class:mobile>
|
|
||||||
<AppControls
|
|
||||||
{gist}
|
|
||||||
{repl}
|
|
||||||
bind:name
|
|
||||||
bind:zen_mode
|
|
||||||
on:forked={handle_fork}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{#if process.browser}
|
|
||||||
<div class="viewport" class:offset={checked}>
|
|
||||||
<Repl
|
|
||||||
bind:this={repl}
|
|
||||||
{svelteUrl}
|
|
||||||
{rollupUrl}
|
|
||||||
{relaxed}
|
|
||||||
fixed={mobile}
|
|
||||||
injectedJS={mapbox_setup}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{#if mobile}
|
|
||||||
<InputOutputToggle bind:checked/>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
Loading…
Reference in new issue