fix(repl): update broken embed repl to work like regular one, remove obsolete ReplWidget.svelte (#10180)

pull/10284/head
Tobias Messner 11 months ago committed by GitHub
parent d9fcc87235
commit 9d0f7d7279
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,95 +0,0 @@
<script>
import { browser } from '$app/environment';
import { process_example } from '$lib/utils/examples';
import Repl from '@sveltejs/repl';
import { theme } from '@sveltejs/site-kit/stores';
import { onMount } from 'svelte';
export let version = '4';
export let gist = null;
export let example = null;
export let embedded = false;
/** @type {import('@sveltejs/repl').default} */
let repl;
let name = 'loading...';
let mounted = false;
async function load(gist, example) {
if (version !== 'local') {
fetch(`https://unpkg.com/svelte@${version}/package.json`)
.then((r) => r.json())
.then((pkg) => {
version = pkg.version;
});
}
if (gist) {
fetch(`/repl/api/${gist}.json`)
.then((r) => r.json())
.then((data) => {
const { description, components } = data;
name = description;
const files = Object.keys(components)
.map((file) => {
const dot = file.lastIndexOf('.');
if (!~dot) return;
const source = components[file].content;
return {
name: file.slice(0, dot),
type: file.slice(dot + 1),
source
};
})
.filter((x) => x.type === 'svelte' || x.type === 'js')
.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({ files });
});
} else if (example) {
const files = process_example(
(await fetch(`/examples/api/${example}.json`).then((r) => r.json())).files
);
repl.set({
files
});
}
}
onMount(() => {
mounted = true;
});
$: if (mounted) load(gist, example);
$: if (embedded) document.title = `${name} • Svelte REPL`;
$: svelteUrl =
browser && version === 'local'
? `${location.origin}/repl/local`
: `https://unpkg.com/svelte@${version}`;
</script>
{#if browser}
<Repl
bind:this={repl}
autocomplete={embedded}
{svelteUrl}
embedded
relaxed
previewTheme={$theme.current}
/>
{/if}

@ -0,0 +1,16 @@
import { error } from '@sveltejs/kit';
export async function load({ fetch, params, url }) {
const res = await fetch(`/repl/api/${params.id}.json`);
if (!res.ok) {
throw error(res.status);
}
const gist = await res.json();
return {
gist,
version: url.searchParams.get('version') || '4'
};
}

@ -0,0 +1,92 @@
<script>
import { browser } from '$app/environment';
import { afterNavigate } from '$app/navigation';
import { theme } from '@sveltejs/site-kit/stores';
import Repl from '@sveltejs/repl';
import { mapbox_setup } from '../../../../../config.js';
import { onMount } from 'svelte';
export let data;
let version = data.version;
/** @type {import('@sveltejs/repl').default} */
let repl;
function update_query_string(version) {
const params = [];
if (version !== 'latest') params.push(`version=${version}`);
const url =
params.length > 0
? `/repl/${data.gist.id}/embed?${params.join('&')}`
: `/repl/${data.gist.id}/embed`;
history.replaceState({}, 'x', url);
}
$: if (typeof history !== 'undefined') update_query_string(version);
onMount(() => {
if (data.version !== 'local') {
fetch(`https://unpkg.com/svelte@${data.version || '4'}/package.json`)
.then((r) => r.json())
.then((pkg) => {
version = pkg.version;
});
}
});
afterNavigate(() => {
repl?.set({
files: data.gist.components
});
});
$: svelteUrl =
browser && version === 'local'
? `${location.origin}/repl/local`
: `https://unpkg.com/svelte@${version}`;
$: relaxed = data.gist.relaxed || (data.user && data.user.id === data.gist.owner);
</script>
<svelte:head>
<title>{data.gist.name} • REPL • Svelte</title>
<meta name="twitter:title" content="{data.gist.name} • REPL • Svelte" />
<meta name="twitter:description" content="Cybernetically enhanced web apps" />
<meta name="Description" content="Interactive Svelte playground" />
</svelte:head>
<div class="repl-outer">
{#if browser}
<Repl
bind:this={repl}
{svelteUrl}
{relaxed}
injectedJS={mapbox_setup}
showModified
showAst
previewTheme={$theme.current}
embedded
/>
{/if}
</div>
<style>
.repl-outer {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: var(--sk-back-1);
overflow: hidden;
box-sizing: border-box;
--pane-controls-h: 4.2rem;
display: flex;
flex-direction: column;
}
</style>

@ -1,8 +0,0 @@
export function load({ url }) {
const query = url.searchParams;
return {
version: query.get('version') || '3',
gist: query.get('gist'),
example: query.get('example')
};
}

@ -0,0 +1,14 @@
import { redirect } from '@sveltejs/kit';
export function load({ url }) {
if (!url.searchParams.has('gist')) {
throw redirect(301, '/repl/hello-world/embed');
} else {
const searchParamsWithoutGist = new URLSearchParams(url.searchParams);
searchParamsWithoutGist.delete('gist');
throw redirect(
301,
`/repl/${url.searchParams.get('gist')}/embed?${searchParamsWithoutGist.toString()}`
);
}
}

@ -1,36 +0,0 @@
<script>
import { browser } from '$app/environment';
import ReplWidget from '$lib/components/ReplWidget.svelte';
export let data;
</script>
<svelte:head>
<title>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>
<div class="repl-outer">
{#if browser}
<ReplWidget version={data.version} gist={data.gist} example={data.example} embedded={true} />
{/if}
</div>
<style>
.repl-outer {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: var(--sk-back-1);
overflow: hidden;
box-sizing: border-box;
--pane-controls-h: 4.2rem;
display: flex;
flex-direction: column;
}
</style>

@ -33,7 +33,10 @@
</svelte:head>
<div style:display={$page.url.pathname !== '/docs' ? 'contents' : 'none'}>
<Shell nav_visible={$page.url.pathname !== '/repl/embed'} bind:snapshot={shell_snapshot}>
<Shell
nav_visible={$page.route.id !== '/(authed)/repl/[id]/embed'}
bind:snapshot={shell_snapshot}
>
<Nav slot="top-nav" title={data.nav_title} links={data.nav_links}>
<svelte:fragment slot="home-large">
<strong>svelte</strong>.dev

@ -1,14 +1,38 @@
<script>
import IntersectionObserver from '$lib/components/IntersectionObserver.svelte';
import ReplWidget from '$lib/components/ReplWidget.svelte';
import { process_example } from '$lib/utils/examples';
import Repl from '@sveltejs/repl';
import { theme } from '@sveltejs/site-kit/stores';
export let id;
/** @type {import('@sveltejs/repl').default} */
let repl;
$: {
if (repl) {
fetch(`/examples/api/${id}.json`)
.then((r) => r.json())
.then((data) => process_example(data.files))
.then((files) => {
repl.set({
files
});
});
}
}
</script>
<div class="repl-container">
<IntersectionObserver once let:intersecting top={400}>
{#if intersecting}
<ReplWidget example={id} />
<Repl
bind:this={repl}
svelteUrl="https://unpkg.com/svelte@4"
relaxed
showAst
previewTheme={$theme.current}
/>
{/if}
</IntersectionObserver>
</div>

Loading…
Cancel
Save