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