Skip to content

Commit 897ce99

Browse files
authored
chore: output-only embedded mode (#1217)
Embed mode, but with hash support and a new query param that makes it so only the output is shown, nothing else
1 parent 2734659 commit 897ce99

File tree

3 files changed

+67
-21
lines changed

3 files changed

+67
-21
lines changed

apps/svelte.dev/src/routes/(authed)/playground/[id]/embed/+page.svelte

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import { Repl } from '@sveltejs/repl';
66
import { mapbox_setup } from '../../../../../config.js';
77
import { page } from '$app/state';
8+
import { decode_and_decompress_text } from '../gzip.js';
9+
import type { File } from 'editor';
810
911
let { data } = $props();
1012
@@ -25,10 +27,40 @@
2527
});
2628
}
2729
30+
// TODO make this munging unnecessary
31+
function munge(data: any): File {
32+
const basename = `${data.name}.${data.type}`;
33+
34+
return {
35+
type: 'file',
36+
name: basename,
37+
basename,
38+
contents: data.source,
39+
text: true
40+
};
41+
}
42+
43+
async function set_files() {
44+
const hash = location.hash.slice(1);
45+
46+
if (!hash) {
47+
repl?.set({
48+
files: data.gist.components.map(munge)
49+
});
50+
51+
return;
52+
}
53+
54+
try {
55+
const recovered = JSON.parse(await decode_and_decompress_text(hash));
56+
repl.set({ files: recovered.files });
57+
} catch {
58+
alert(`Couldn't load the code from the URL. Make sure you copied the link correctly.`);
59+
}
60+
}
61+
2862
afterNavigate(() => {
29-
repl?.set({
30-
files: data.gist.components
31-
});
63+
set_files();
3264
});
3365
3466
const relaxed = $derived(data.gist.relaxed || (data.user && data.user.id === data.gist.owner));
@@ -51,7 +83,7 @@
5183
can_escape
5284
injectedJS={mapbox_setup}
5385
previewTheme={theme.current}
54-
embedded
86+
embedded={page.url.searchParams.has('output-only') ? 'output-only' : true}
5587
/>
5688
{/if}
5789
</div>

packages/repl/src/lib/Output/Output.svelte

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
interface Props {
1313
status: string | null;
1414
runtimeError?: Error | null;
15-
embedded?: boolean;
15+
embedded?: boolean | 'output-only';
1616
relaxed?: boolean;
1717
can_escape?: boolean;
1818
injectedJS: string;
@@ -182,16 +182,18 @@
182182
});
183183
</script>
184184

185-
<div class="view-toggle">
186-
{#if workspace.current.name.endsWith('.md')}
187-
<button class="active">Markdown</button>
188-
{:else}
189-
<button aria-current={view === 'result'} onclick={() => (view = 'result')}>Result</button>
190-
<button aria-current={view === 'js'} onclick={() => (view = 'js')}>JS output</button>
191-
<button aria-current={view === 'css'} onclick={() => (view = 'css')}>CSS output</button>
192-
<button aria-current={view === 'ast'} onclick={() => (view = 'ast')}>AST output</button>
193-
{/if}
194-
</div>
185+
{#if embedded !== 'output-only'}
186+
<div class="view-toggle">
187+
{#if workspace.current.name.endsWith('.md')}
188+
<button class="active">Markdown</button>
189+
{:else}
190+
<button aria-current={view === 'result'} onclick={() => (view = 'result')}>Result</button>
191+
<button aria-current={view === 'js'} onclick={() => (view = 'js')}>JS output</button>
192+
<button aria-current={view === 'css'} onclick={() => (view = 'css')}>CSS output</button>
193+
<button aria-current={view === 'ast'} onclick={() => (view = 'ast')}>AST output</button>
194+
{/if}
195+
</div>
196+
{/if}
195197

196198
<!-- component viewer -->
197199
<div class="tab-content" class:visible={!is_markdown && view === 'result'}>
@@ -202,6 +204,7 @@
202204
{can_escape}
203205
{injectedJS}
204206
{injectedCSS}
207+
onLog={embedded === 'output-only' ? () => {} : undefined}
205208
theme={previewTheme}
206209
/>
207210
</div>

packages/repl/src/lib/Repl.svelte

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
interface Props {
1414
packagesUrl?: string;
1515
svelteVersion?: string;
16-
embedded?: boolean;
16+
embedded?: boolean | 'output-only';
1717
orientation?: 'columns' | 'rows';
1818
relaxed?: boolean;
1919
can_escape?: boolean;
@@ -152,7 +152,7 @@
152152
let mobile = $derived(width < 540);
153153
154154
$effect(() => {
155-
$toggleable = mobile && orientation === 'columns';
155+
$toggleable = mobile && orientation === 'columns' && embedded !== 'output-only';
156156
});
157157
158158
let runes = $derived(
@@ -166,13 +166,24 @@
166166

167167
<svelte:window onbeforeunload={before_unload} />
168168

169-
<div class="container" class:embedded class:toggleable={$toggleable} bind:clientWidth={width}>
169+
<div
170+
class="container {embedded === 'output-only' ? '' : 'container-normal'}"
171+
class:embedded
172+
class:toggleable={$toggleable}
173+
bind:clientWidth={width}
174+
>
170175
<div class="viewport" class:output={show_output}>
171176
<SplitPane
172177
id="main"
173178
type={orientation === 'rows' ? 'vertical' : 'horizontal'}
174-
pos="{mobile || fixed ? fixedPos : orientation === 'rows' ? 60 : 50}%"
175-
min="100px"
179+
pos="{embedded === 'output-only'
180+
? 0
181+
: mobile || fixed
182+
? fixedPos
183+
: orientation === 'rows'
184+
? 60
185+
: 50}%"
186+
min={embedded === 'output-only' ? '0px' : '100px'}
176187
max="-4.1rem"
177188
>
178189
{#snippet a()}
@@ -264,7 +275,7 @@
264275
265276
/* on mobile, override the <SplitPane> controls */
266277
@media (max-width: 799px) {
267-
:global {
278+
.container-normal :global {
268279
[data-pane='main'] {
269280
--pos: 50% !important;
270281
}

0 commit comments

Comments
 (0)