Skip to content

Commit 81c2768

Browse files
committed
feat(astro): add "Download lesson as zip" button
1 parent 5a2a64f commit 81c2768

File tree

9 files changed

+59
-17
lines changed

9 files changed

+59
-17
lines changed

docs/tutorialkit.dev/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
},
1313
"dependencies": {
1414
"@tutorialkit/react": "workspace:*",
15-
"@webcontainer/api": "1.2.4",
15+
"@webcontainer/api": "1.5.0",
1616
"classnames": "^2.5.1",
1717
"react": "^18.3.1",
1818
"react-dom": "^18.3.1"

packages/astro/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"@tutorialkit/types": "workspace:*",
4646
"@types/react": "^18.3.3",
4747
"@unocss/reset": "^0.62.2",
48-
"@webcontainer/api": "1.2.4",
48+
"@webcontainer/api": "1.5.0",
4949
"astro": "^4.15.0",
5050
"astro-expressive-code": "^0.35.3",
5151
"chokidar": "3.6.0",
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { tutorialStore, webcontainer as webcontainerPromise } from './webcontainer.js';
2+
3+
export function DownloadButton() {
4+
return (
5+
<button
6+
title="Download lesson as zip-file"
7+
className="flex items-center font-size-3.5 text-tk-elements-topBar-iconButton-iconColor hover:text-tk-elements-topBar-iconButton-iconColorHover transition-theme bg-tk-elements-topBar-iconButton-backgroundColor hover:bg-tk-elements-topBar-iconButton-backgroundColorHover p-1 rounded-md"
8+
onClick={onClick}
9+
>
10+
<span className="i-ph-download-simple h-6 w-6" />
11+
</button>
12+
);
13+
}
14+
15+
async function onClick() {
16+
const lesson = tutorialStore.lesson;
17+
18+
if (!lesson) {
19+
throw new Error('Missing lesson');
20+
}
21+
22+
const webcontainer = await webcontainerPromise;
23+
const data = await webcontainer.export('/home/tutorial', { format: 'zip', excludes: ['node_modules'] });
24+
25+
const link = document.createElement('a');
26+
link.style.display = 'none';
27+
link.download = `${lesson.part.id}-${lesson.chapter.id}-${lesson.id}.zip`;
28+
link.href = URL.createObjectURL(new Blob([data], { type: 'application/zip' }));
29+
30+
document.body.appendChild(link);
31+
link.click();
32+
33+
document.body.removeChild(link);
34+
URL.revokeObjectURL(link.href);
35+
}

packages/astro/src/default/components/TopBar.astro

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
<div class="flex flex-1">
55
<slot name="logo" />
66
</div>
7+
8+
<div class="mr-2">
9+
<slot name="download-button" />
10+
</div>
711
<div class="mr-2">
812
<slot name="open-in-stackblitz-link" />
913
</div>

packages/astro/src/default/components/TopBarWrapper.astro

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { TopBar } from 'tutorialkit:override-components';
33
import type { Lesson } from '@tutorialkit/types';
44
import { ThemeSwitch } from './ThemeSwitch';
55
import { LoginButton } from './LoginButton';
6+
import { DownloadButton } from './DownloadButton';
67
import { OpenInStackblitzLink } from './OpenInStackblitzLink';
78
import Logo from './Logo.astro';
89
import { useAuth } from './setup';
@@ -18,6 +19,8 @@ const { logoLink, openInStackBlitz } = Astro.props;
1819
<TopBar>
1920
<Logo slot="logo" logoLink={logoLink ?? '/'} />
2021

22+
<DownloadButton client:load transition:persist slot="download-button" />
23+
2124
{openInStackBlitz && <OpenInStackblitzLink client:load transition:persist slot="open-in-stackblitz-link" />}
2225

2326
<ThemeSwitch client:load transition:persist slot="theme-switch" />

packages/react/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
"@replit/codemirror-lang-svelte": "^6.0.0",
8686
"@tutorialkit/runtime": "workspace:*",
8787
"@tutorialkit/theme": "workspace:*",
88-
"@webcontainer/api": "1.2.4",
88+
"@webcontainer/api": "1.5.0",
8989
"@xterm/addon-fit": "^0.10.0",
9090
"@xterm/addon-web-links": "^0.11.0",
9191
"@xterm/xterm": "^5.5.0",

packages/runtime/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
},
3535
"dependencies": {
3636
"@tutorialkit/types": "workspace:*",
37-
"@webcontainer/api": "1.2.4",
37+
"@webcontainer/api": "1.5.0",
3838
"nanostores": "^0.10.3",
3939
"picomatch": "^4.0.2"
4040
},

packages/test-utils/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"type": "module",
66
"private": true,
77
"devDependencies": {
8-
"@webcontainer/api": "1.2.4",
8+
"@webcontainer/api": "1.5.0",
99
"typescript": "^5.4.5",
1010
"vitest": "^2.1.1"
1111
}

pnpm-lock.yaml

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)