Skip to content

Commit 8aaf7c3

Browse files
Copilotsxzz
andcommitted
Add download button feature with zip generation and package.json
Co-authored-by: sxzz <[email protected]>
1 parent a10d4f4 commit 8aaf7c3

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

app/components/Navbar.vue

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
files,
1010
timeCost,
1111
} from '~/state/bundler'
12+
import { handleDownloadProject } from '~/utils/download'
1213
1314
const { data: rolldownVersions } = await useRolldownVersions()
1415
@@ -86,6 +87,14 @@ function resetState() {
8687
<div i-ri:refresh-line />
8788
</button>
8889

90+
<button
91+
title="Download Project"
92+
nav-button
93+
@click="handleDownloadProject"
94+
>
95+
<div i-ri:download-line />
96+
</button>
97+
8998
<button title="Toggle Dark Mode" nav-button @click="toggleDark">
9099
<div i-ri:sun-line dark:i-ri:moon-line />
91100
</button>

app/utils/download.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { strToU8, zip } from 'fflate'
2+
import { currentVersion, files } from '~/state/bundler'
3+
4+
export function downloadProject() {
5+
const projectFiles: Record<string, Uint8Array> = {}
6+
7+
// Add all source files from the REPL
8+
for (const [filename, sourceFile] of files.value) {
9+
projectFiles[filename] = strToU8(sourceFile.code)
10+
}
11+
12+
// Generate package.json with rolldown dependency
13+
const packageJson = {
14+
name: 'rolldown-repl-project',
15+
version: '1.0.0',
16+
private: true,
17+
type: 'module',
18+
scripts: {
19+
build: 'rolldown',
20+
dev: 'rolldown --watch',
21+
},
22+
dependencies: {
23+
rolldown:
24+
currentVersion.value === 'latest' ? '^1.0.0' : currentVersion.value,
25+
},
26+
}
27+
28+
projectFiles['package.json'] = strToU8(JSON.stringify(packageJson, null, 2))
29+
30+
// Create zip file
31+
return new Promise<Uint8Array>((resolve, reject) => {
32+
zip(projectFiles, { level: 6 }, (err, data) => {
33+
if (err) reject(err)
34+
else resolve(data)
35+
})
36+
})
37+
}
38+
39+
export function triggerDownload(data: Uint8Array, filename: string) {
40+
const blob = new Blob([data], { type: 'application/zip' })
41+
const url = URL.createObjectURL(blob)
42+
43+
const link = document.createElement('a')
44+
link.href = url
45+
link.download = filename
46+
document.body.append(link)
47+
link.click()
48+
link.remove()
49+
50+
URL.revokeObjectURL(url)
51+
}
52+
53+
export function handleDownloadProject() {
54+
try {
55+
downloadProject()
56+
.then((zipData) => {
57+
const timestamp = new Date()
58+
.toISOString()
59+
.slice(0, 19)
60+
.replaceAll(':', '-')
61+
triggerDownload(zipData, `rolldown-repl-${timestamp}.zip`)
62+
})
63+
.catch((error) => {
64+
console.error('Failed to download project:', error)
65+
// eslint-disable-next-line no-alert
66+
alert('Failed to download project. Please try again.')
67+
})
68+
} catch (error) {
69+
console.error('Failed to download project:', error)
70+
// eslint-disable-next-line no-alert
71+
alert('Failed to download project. Please try again.')
72+
}
73+
}

0 commit comments

Comments
 (0)