mirror of https://github.com/vuejs/core.git
refactor(sfc-playground): upgrade `@vue/repl` (#10310)
This commit is contained in:
parent
3199189901
commit
fe5d919b0f
|
@ -7,8 +7,6 @@
|
||||||
<link rel="icon" type="image/svg" href="/logo.svg" />
|
<link rel="icon" type="image/svg" href="/logo.svg" />
|
||||||
<title>Vue SFC Playground</title>
|
<title>Vue SFC Playground</title>
|
||||||
<script>
|
<script>
|
||||||
// process shim for old versions of @vue/compiler-sfc dependency
|
|
||||||
window.process = { env: {} }
|
|
||||||
const savedPreferDark = localStorage.getItem('vue-sfc-playground-prefer-dark')
|
const savedPreferDark = localStorage.getItem('vue-sfc-playground-prefer-dark')
|
||||||
if (
|
if (
|
||||||
savedPreferDark === 'true' ||
|
savedPreferDark === 'true' ||
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
"vite": "^5.0.12"
|
"vite": "^5.0.12"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/repl": "^3.1.1",
|
"@vue/repl": "^4.1.0",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"vue": "workspace:*"
|
"vue": "workspace:*"
|
||||||
|
|
|
@ -1,22 +1,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Header from './Header.vue'
|
import Header from './Header.vue'
|
||||||
import { Repl, ReplStore, SFCOptions } from '@vue/repl'
|
import { Repl, useStore, SFCOptions, useVueImportMap } from '@vue/repl'
|
||||||
import type Monaco from '@vue/repl/monaco-editor'
|
import Monaco from '@vue/repl/monaco-editor'
|
||||||
import type CodeMirror from '@vue/repl/codemirror-editor'
|
import { ref, watchEffect, onMounted, computed } from 'vue'
|
||||||
import { ref, watchEffect, onMounted } from 'vue'
|
|
||||||
import { shallowRef } from 'vue'
|
|
||||||
|
|
||||||
const EditorComponent = shallowRef<typeof Monaco | typeof CodeMirror>()
|
|
||||||
|
|
||||||
if (import.meta.env.DEV) {
|
|
||||||
import('@vue/repl/codemirror-editor').then(
|
|
||||||
mod => (EditorComponent.value = mod.default),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
import('@vue/repl/monaco-editor').then(
|
|
||||||
mod => (EditorComponent.value = mod.default),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const replRef = ref<InstanceType<typeof Repl>>()
|
const replRef = ref<InstanceType<typeof Repl>>()
|
||||||
|
|
||||||
|
@ -26,78 +12,80 @@ const setVH = () => {
|
||||||
window.addEventListener('resize', setVH)
|
window.addEventListener('resize', setVH)
|
||||||
setVH()
|
setVH()
|
||||||
|
|
||||||
const useProdMode = ref(false)
|
|
||||||
const useSSRMode = ref(false)
|
const useSSRMode = ref(false)
|
||||||
|
|
||||||
|
const { productionMode, vueVersion, importMap } = useVueImportMap({
|
||||||
|
runtimeDev: import.meta.env.PROD
|
||||||
|
? `${location.origin}/vue.runtime.esm-browser.js`
|
||||||
|
: `${location.origin}/src/vue-dev-proxy`,
|
||||||
|
runtimeProd: import.meta.env.PROD
|
||||||
|
? `${location.origin}/vue.runtime.esm-browser.prod.js`
|
||||||
|
: `${location.origin}/src/vue-dev-proxy-prod`,
|
||||||
|
serverRenderer: import.meta.env.PROD
|
||||||
|
? `${location.origin}/server-renderer.esm-browser.js`
|
||||||
|
: `${location.origin}/src/vue-server-renderer-dev-proxy`,
|
||||||
|
})
|
||||||
|
|
||||||
let hash = location.hash.slice(1)
|
let hash = location.hash.slice(1)
|
||||||
if (hash.startsWith('__DEV__')) {
|
if (hash.startsWith('__DEV__')) {
|
||||||
hash = hash.slice(7)
|
hash = hash.slice(7)
|
||||||
useProdMode.value = false
|
productionMode.value = false
|
||||||
}
|
}
|
||||||
if (hash.startsWith('__PROD__')) {
|
if (hash.startsWith('__PROD__')) {
|
||||||
hash = hash.slice(8)
|
hash = hash.slice(8)
|
||||||
useProdMode.value = true
|
productionMode.value = true
|
||||||
}
|
}
|
||||||
if (hash.startsWith('__SSR__')) {
|
if (hash.startsWith('__SSR__')) {
|
||||||
hash = hash.slice(7)
|
hash = hash.slice(7)
|
||||||
useSSRMode.value = true
|
useSSRMode.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const store = new ReplStore({
|
|
||||||
serializedState: hash,
|
|
||||||
productionMode: useProdMode.value,
|
|
||||||
defaultVueRuntimeURL: import.meta.env.PROD
|
|
||||||
? `${location.origin}/vue.runtime.esm-browser.js`
|
|
||||||
: `${location.origin}/src/vue-dev-proxy`,
|
|
||||||
defaultVueRuntimeProdURL: import.meta.env.PROD
|
|
||||||
? `${location.origin}/vue.runtime.esm-browser.prod.js`
|
|
||||||
: `${location.origin}/src/vue-dev-proxy-prod`,
|
|
||||||
defaultVueServerRendererURL: import.meta.env.PROD
|
|
||||||
? `${location.origin}/server-renderer.esm-browser.js`
|
|
||||||
: `${location.origin}/src/vue-server-renderer-dev-proxy`,
|
|
||||||
})
|
|
||||||
|
|
||||||
// enable experimental features
|
// enable experimental features
|
||||||
const sfcOptions: SFCOptions = {
|
const sfcOptions = computed(
|
||||||
script: {
|
(): SFCOptions => ({
|
||||||
inlineTemplate: useProdMode.value,
|
script: {
|
||||||
isProd: useProdMode.value,
|
inlineTemplate: productionMode.value,
|
||||||
propsDestructure: true,
|
isProd: productionMode.value,
|
||||||
},
|
propsDestructure: true,
|
||||||
style: {
|
|
||||||
isProd: useProdMode.value,
|
|
||||||
},
|
|
||||||
template: {
|
|
||||||
isProd: useProdMode.value,
|
|
||||||
compilerOptions: {
|
|
||||||
isCustomElement: (tag: string) => tag === 'mjx-container',
|
|
||||||
},
|
},
|
||||||
|
style: {
|
||||||
|
isProd: productionMode.value,
|
||||||
|
},
|
||||||
|
template: {
|
||||||
|
isProd: productionMode.value,
|
||||||
|
compilerOptions: {
|
||||||
|
isCustomElement: (tag: string) => tag === 'mjx-container',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
const store = useStore(
|
||||||
|
{
|
||||||
|
builtinImportMap: importMap,
|
||||||
|
vueVersion,
|
||||||
|
sfcOptions,
|
||||||
},
|
},
|
||||||
}
|
hash,
|
||||||
|
)
|
||||||
|
// @ts-expect-error
|
||||||
|
globalThis.store = store
|
||||||
|
|
||||||
// persist state
|
// persist state
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
const newHash = store
|
const newHash = store
|
||||||
.serialize()
|
.serialize()
|
||||||
.replace(/^#/, useSSRMode.value ? `#__SSR__` : `#`)
|
.replace(/^#/, useSSRMode.value ? `#__SSR__` : `#`)
|
||||||
.replace(/^#/, useProdMode.value ? `#__PROD__` : `#`)
|
.replace(/^#/, productionMode.value ? `#__PROD__` : `#`)
|
||||||
history.replaceState({}, '', newHash)
|
history.replaceState({}, '', newHash)
|
||||||
})
|
})
|
||||||
|
|
||||||
function toggleProdMode() {
|
function toggleProdMode() {
|
||||||
const isProd = (useProdMode.value = !useProdMode.value)
|
productionMode.value = !productionMode.value
|
||||||
sfcOptions.script!.inlineTemplate =
|
|
||||||
sfcOptions.script!.isProd =
|
|
||||||
sfcOptions.template!.isProd =
|
|
||||||
sfcOptions.style!.isProd =
|
|
||||||
isProd
|
|
||||||
store.toggleProduction()
|
|
||||||
store.setFiles(store.getFiles())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleSSR() {
|
function toggleSSR() {
|
||||||
useSSRMode.value = !useSSRMode.value
|
useSSRMode.value = !useSSRMode.value
|
||||||
store.setFiles(store.getFiles())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function reloadPage() {
|
function reloadPage() {
|
||||||
|
@ -111,13 +99,16 @@ function toggleTheme(isDark: boolean) {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const cls = document.documentElement.classList
|
const cls = document.documentElement.classList
|
||||||
toggleTheme(cls.contains('dark'))
|
toggleTheme(cls.contains('dark'))
|
||||||
|
|
||||||
|
// @ts-expect-error process shim for old versions of @vue/compiler-sfc dependency
|
||||||
|
window.process = { env: {} }
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Header
|
<Header
|
||||||
:store="store"
|
:store="store"
|
||||||
:prod="useProdMode"
|
:prod="productionMode"
|
||||||
:ssr="useSSRMode"
|
:ssr="useSSRMode"
|
||||||
@toggle-theme="toggleTheme"
|
@toggle-theme="toggleTheme"
|
||||||
@toggle-prod="toggleProdMode"
|
@toggle-prod="toggleProdMode"
|
||||||
|
@ -125,17 +116,15 @@ onMounted(() => {
|
||||||
@reload-page="reloadPage"
|
@reload-page="reloadPage"
|
||||||
/>
|
/>
|
||||||
<Repl
|
<Repl
|
||||||
v-if="EditorComponent"
|
|
||||||
ref="replRef"
|
ref="replRef"
|
||||||
:theme="theme"
|
:theme="theme"
|
||||||
:editor="EditorComponent"
|
:editor="Monaco"
|
||||||
@keydown.ctrl.s.prevent
|
@keydown.ctrl.s.prevent
|
||||||
@keydown.meta.s.prevent
|
@keydown.meta.s.prevent
|
||||||
:ssr="useSSRMode"
|
:ssr="useSSRMode"
|
||||||
:store="store"
|
:store="store"
|
||||||
:showCompileOutput="true"
|
:showCompileOutput="true"
|
||||||
:autoResize="true"
|
:autoResize="true"
|
||||||
:sfcOptions="sfcOptions"
|
|
||||||
:clearConsole="false"
|
:clearConsole="false"
|
||||||
:preview-options="{
|
:preview-options="{
|
||||||
customCode: {
|
customCode: {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import type { ReplStore } from '@vue/repl'
|
||||||
import { downloadProject } from './download/download'
|
import { downloadProject } from './download/download'
|
||||||
import { ref } from 'vue'
|
|
||||||
import Sun from './icons/Sun.vue'
|
import Sun from './icons/Sun.vue'
|
||||||
import Moon from './icons/Moon.vue'
|
import Moon from './icons/Moon.vue'
|
||||||
import Share from './icons/Share.vue'
|
import Share from './icons/Share.vue'
|
||||||
import Download from './icons/Download.vue'
|
import Download from './icons/Download.vue'
|
||||||
import GitHub from './icons/GitHub.vue'
|
import GitHub from './icons/GitHub.vue'
|
||||||
import Reload from './icons/Reload.vue'
|
import Reload from './icons/Reload.vue'
|
||||||
import type { ReplStore } from '@vue/repl'
|
|
||||||
import VersionSelect from './VersionSelect.vue'
|
import VersionSelect from './VersionSelect.vue'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
@ -25,23 +25,20 @@ const emit = defineEmits([
|
||||||
const { store } = props
|
const { store } = props
|
||||||
|
|
||||||
const currentCommit = __COMMIT__
|
const currentCommit = __COMMIT__
|
||||||
const vueVersion = ref(`@${currentCommit}`)
|
|
||||||
|
|
||||||
const vueURL = store.getImportMap().imports.vue
|
const vueVersion = computed(() => {
|
||||||
if (vueURL && !vueURL.startsWith(location.origin)) {
|
if (store.loading) {
|
||||||
const versionMatch = vueURL.match(/runtime-dom@([^/]+)/)
|
return 'loading...'
|
||||||
if (versionMatch) vueVersion.value = versionMatch[1]
|
}
|
||||||
}
|
return store.vueVersion || `@${__COMMIT__}`
|
||||||
|
})
|
||||||
|
|
||||||
async function setVueVersion(v: string) {
|
async function setVueVersion(v: string) {
|
||||||
vueVersion.value = `loading...`
|
store.vueVersion = v
|
||||||
await store.setVueVersion(v)
|
|
||||||
vueVersion.value = v
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetVueVersion() {
|
function resetVueVersion() {
|
||||||
store.resetVueVersion()
|
store.vueVersion = null
|
||||||
vueVersion.value = `@${currentCommit}`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function copyLink(e: MouseEvent) {
|
async function copyLink(e: MouseEvent) {
|
||||||
|
@ -73,7 +70,7 @@ function toggleDark() {
|
||||||
</h1>
|
</h1>
|
||||||
<div class="links">
|
<div class="links">
|
||||||
<VersionSelect
|
<VersionSelect
|
||||||
v-model="store.state.typescriptVersion"
|
v-model="store.typescriptVersion"
|
||||||
pkg="typescript"
|
pkg="typescript"
|
||||||
label="TypeScript Version"
|
label="TypeScript Version"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -347,8 +347,8 @@ importers:
|
||||||
packages/sfc-playground:
|
packages/sfc-playground:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vue/repl':
|
'@vue/repl':
|
||||||
specifier: ^3.1.1
|
specifier: ^4.1.0
|
||||||
version: 3.1.1
|
version: 4.1.0
|
||||||
file-saver:
|
file-saver:
|
||||||
specifier: ^2.0.5
|
specifier: ^2.0.5
|
||||||
version: 2.0.5
|
version: 2.0.5
|
||||||
|
@ -1774,8 +1774,8 @@ packages:
|
||||||
engines: {node: '>= 0.12.0'}
|
engines: {node: '>= 0.12.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@vue/repl@3.1.1:
|
/@vue/repl@4.1.0:
|
||||||
resolution: {integrity: sha512-9nJImsUeywU2MTqvzf4ueqWC49UC3LVXVPk1HmoNnLVumfWXv+w5ytuSA//fxb/N/O5vCqE0UV63/dYvnCZpwQ==}
|
resolution: {integrity: sha512-4ZNEQWlLjl1Sq+WFiACm5siMdwUAmmqOES4XDgZRRFYeeW/BfabO9I6fpU+Y0zO9HFzKb8dwUUH0e0LK7mIYeg==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@zeit/schemas@2.29.0:
|
/@zeit/schemas@2.29.0:
|
||||||
|
|
Loading…
Reference in New Issue