Skip to content

Commit 9613969

Browse files
committed
workflow(sfc-playground): share and download buttons
1 parent aa8bf1b commit 9613969

File tree

15 files changed

+231
-24
lines changed

15 files changed

+231
-24
lines changed

packages/global.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,10 @@ declare module '*.vue' {
2727

2828
}
2929
declare module '*?raw' {
30+
const content: string
31+
export default content
32+
}
3033

34+
declare module 'file-saver' {
35+
export function saveAs(blob: any, name: any): void
3136
}

packages/sfc-playground/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,9 @@
1919
"@vitejs/plugin-vue": "^1.2.0",
2020
"codemirror": "^5.60.0",
2121
"vite": "^2.1.3"
22+
},
23+
"dependencies": {
24+
"file-saver": "^2.0.5",
25+
"jszip": "^3.6.0"
2226
}
2327
}

packages/sfc-playground/src/App.vue

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ import Output from './output/Output.vue'
2222
<style>
2323
body {
2424
font-size: 13px;
25-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
26-
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
25+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
26+
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
2727
color: #444;
2828
margin: 0;
2929
background-color: #f8f8f8;
@@ -36,4 +36,12 @@ body {
3636
.wrapper {
3737
height: calc(100vh - var(--nav-height));
3838
}
39-
</style>
39+
40+
button {
41+
border: none;
42+
outline: none;
43+
cursor: pointer;
44+
margin: 0;
45+
background-color: transparent;
46+
}
47+
</style>

packages/sfc-playground/src/Header.vue

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,59 @@
11
<template>
22
<nav>
33
<h1>Vue SFC Playground</h1>
4+
5+
<button class="share" @click="copyLink">
6+
<svg width="1.4em" height="1.4em" viewBox="0 0 24 24">
7+
<g fill="none" stroke="#626262" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
8+
<circle cx="18" cy="5" r="3"/>
9+
<circle cx="6" cy="12" r="3"/>
10+
<circle cx="18" cy="19" r="3"/>
11+
<path d="M8.59 13.51l6.83 3.98"/>
12+
<path d="M15.41 6.51l-6.82 3.98"/>
13+
</g>
14+
</svg>
15+
</button>
16+
17+
<button class="download" @click="downloadProject">
18+
<svg width="1.7em" height="1.7em" viewBox="0 0 24 24">
19+
<g fill="#626262">
20+
<rect x="4" y="18" width="16" height="2" rx="1" ry="1"/>
21+
<rect x="3" y="17" width="4" height="2" rx="1" ry="1" transform="rotate(-90 5 18)"/>
22+
<rect x="17" y="17" width="4" height="2" rx="1" ry="1" transform="rotate(-90 19 18)"/>
23+
<path d="M12 15a1 1 0 0 1-.58-.18l-4-2.82a1 1 0 0 1-.24-1.39a1 1 0 0 1 1.4-.24L12 12.76l3.4-2.56a1 1 0 0 1 1.2 1.6l-4 3a1 1 0 0 1-.6.2z"/><path d="M12 13a1 1 0 0 1-1-1V4a1 1 0 0 1 2 0v8a1 1 0 0 1-1 1z"/>
24+
</g>
25+
</svg>
26+
</button>
427
</nav>
528
</template>
629

30+
<script setup lang="ts">
31+
import { exportFiles } from './store'
32+
import { saveAs } from 'file-saver'
33+
34+
function copyLink() {
35+
navigator.clipboard.writeText(location.href)
36+
alert('Sharable URL has been copied to clipboard.')
37+
}
38+
39+
async function downloadProject() {
40+
const { default: JSZip } = await import('jszip')
41+
const zip = new JSZip()
42+
43+
// basic structure
44+
45+
// project src
46+
const src = zip.folder('src')!
47+
const files = exportFiles()
48+
for (const file in files) {
49+
src.file(file, files[file])
50+
}
51+
52+
const blob = await zip.generateAsync({ type: 'blob' })
53+
saveAs(blob, 'vue-project.zip')
54+
}
55+
</script>
56+
757
<style>
858
nav {
959
height: var(--nav-height);
@@ -20,4 +70,16 @@ h1 {
2070
line-height: var(--nav-height);
2171
font-weight: 500;
2272
}
73+
74+
.share {
75+
position: absolute;
76+
top: 14px;
77+
right: 56px;
78+
}
79+
80+
.download {
81+
position: absolute;
82+
top: 13px;
83+
right: 16px;
84+
}
2385
</style>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { exportFiles } from '../store'
2+
import { saveAs } from 'file-saver'
3+
4+
import index from './template/index.html?raw'
5+
import main from './template/main.js?raw'
6+
import pkg from './template/package.json?raw'
7+
import config from './template/vite.config.js?raw'
8+
import readme from './template/README.md?raw'
9+
10+
export async function downloadProject() {
11+
const { default: JSZip } = await import('jszip')
12+
const zip = new JSZip()
13+
14+
// basic structure
15+
zip.file('index.html', index)
16+
zip.file('package.json', pkg)
17+
zip.file('vite.config.js', config)
18+
zip.file('README.md', readme)
19+
20+
// project src
21+
const src = zip.folder('src')!
22+
src.file('main.js', main)
23+
24+
const files = exportFiles()
25+
for (const file in files) {
26+
src.file(file, files[file])
27+
}
28+
29+
const blob = await zip.generateAsync({ type: 'blob' })
30+
saveAs(blob, 'vue-project.zip')
31+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Vite Vue Starter
2+
3+
This is a project template using [Vite](https://vitejs.dev/). It requires [Node.js](https://nodejs.org) v12+.
4+
5+
To start:
6+
7+
```sh
8+
npm install
9+
npm run dev
10+
11+
# if using yarn:
12+
yarn
13+
yarn dev
14+
```
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" href="/favicon.ico" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Vite App</title>
8+
</head>
9+
<body>
10+
<div id="app"></div>
11+
<script type="module" src="/src/main.js"></script>
12+
</body>
13+
</html>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { createApp } from 'vue'
2+
import App from './App.vue'
3+
4+
createApp(App).mount('#app')
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "vite-vue-starter",
3+
"version": "0.0.0",
4+
"scripts": {
5+
"dev": "vite",
6+
"build": "vite build",
7+
"serve": "vite preview"
8+
},
9+
"dependencies": {
10+
"vue": "^3.0.9"
11+
},
12+
"devDependencies": {
13+
"@vitejs/plugin-vue": "^1.1.5",
14+
"@vue/compiler-sfc": "^3.0.9",
15+
"vite": "^2.1.3"
16+
}
17+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { defineConfig } from 'vite'
2+
import vue from '@vitejs/plugin-vue'
3+
4+
// https://vitejs.dev/config/
5+
export default defineConfig({
6+
plugins: [vue()]
7+
})

0 commit comments

Comments
 (0)