workflow: improve template explorer hash persistence

This commit is contained in:
Evan You 2022-01-04 17:32:25 +08:00
parent 2b506d7df6
commit eb721d49c0
2 changed files with 50 additions and 17 deletions

View File

@ -1,7 +1,12 @@
import * as m from 'monaco-editor' import * as m from 'monaco-editor'
import { compile, CompilerError, CompilerOptions } from '@vue/compiler-dom' import { compile, CompilerError, CompilerOptions } from '@vue/compiler-dom'
import { compile as ssrCompile } from '@vue/compiler-ssr' import { compile as ssrCompile } from '@vue/compiler-ssr'
import { compilerOptions, initOptions, ssrMode } from './options' import {
defaultOptions,
compilerOptions,
initOptions,
ssrMode
} from './options'
import { toRaw, watchEffect } from '@vue/runtime-dom' import { toRaw, watchEffect } from '@vue/runtime-dom'
import { SourceMapConsumer } from 'source-map' import { SourceMapConsumer } from 'source-map'
import theme from './theme' import theme from './theme'
@ -35,19 +40,32 @@ window.init = () => {
monaco.editor.defineTheme('my-theme', theme) monaco.editor.defineTheme('my-theme', theme)
monaco.editor.setTheme('my-theme') monaco.editor.setTheme('my-theme')
const persistedState: PersistedState = JSON.parse( let persistedState: PersistedState | undefined
decodeURIComponent(window.location.hash.slice(1)) ||
localStorage.getItem('state') || try {
`{}` let hash = window.location.hash.slice(1)
) try {
// functions are not persistable, so delete it in case we sometimes need hash = escape(atob(hash))
// to debug with custom nodeTransforms } catch (e) {}
if (persistedState.options) { persistedState = JSON.parse(
delete persistedState.options.nodeTransforms decodeURIComponent(hash) || localStorage.getItem('state') || `{}`
)
} catch (e: any) {
// bad stored state, clear it
console.warn(
'Persisted state in localStorage seems to be corrupted, please reload.\n' +
e.message
)
localStorage.clear()
} }
ssrMode.value = persistedState.ssr if (persistedState) {
Object.assign(compilerOptions, persistedState.options) // functions are not persistable, so delete it in case we sometimes need
// to debug with custom nodeTransforms
delete persistedState.options.nodeTransforms
ssrMode.value = persistedState.ssr
Object.assign(compilerOptions, persistedState.options)
}
let lastSuccessfulCode: string let lastSuccessfulCode: string
let lastSuccessfulMap: SourceMapConsumer | undefined = undefined let lastSuccessfulMap: SourceMapConsumer | undefined = undefined
@ -99,13 +117,24 @@ window.init = () => {
function reCompile() { function reCompile() {
const src = editor.getValue() const src = editor.getValue()
// every time we re-compile, persist current state // every time we re-compile, persist current state
const optionsToSave = {}
let key: keyof CompilerOptions
for (key in compilerOptions) {
const val = compilerOptions[key]
if (typeof val !== 'object' && val !== defaultOptions[key]) {
// @ts-ignore
optionsToSave[key] = val
}
}
const state = JSON.stringify({ const state = JSON.stringify({
src, src,
ssr: ssrMode.value, ssr: ssrMode.value,
options: compilerOptions options: optionsToSave
} as PersistedState) } as PersistedState)
localStorage.setItem('state', state) localStorage.setItem('state', state)
window.location.hash = encodeURIComponent(state) window.location.hash = btoa(unescape(encodeURIComponent(state)))
const res = compileCode(src) const res = compileCode(src)
if (res) { if (res) {
output.setValue(res) output.setValue(res)
@ -113,7 +142,7 @@ window.init = () => {
} }
const editor = monaco.editor.create(document.getElementById('source')!, { const editor = monaco.editor.create(document.getElementById('source')!, {
value: persistedState.src || `<div>Hello World!</div>`, value: persistedState?.src || `<div>Hello World!</div>`,
language: 'html', language: 'html',
...sharedEditorOptions, ...sharedEditorOptions,
wordWrap: 'bounded' wordWrap: 'bounded'

View File

@ -4,7 +4,7 @@ import { BindingTypes } from '@vue/compiler-core'
export const ssrMode = ref(false) export const ssrMode = ref(false)
export const compilerOptions: CompilerOptions = reactive({ export const defaultOptions: CompilerOptions = {
mode: 'module', mode: 'module',
filename: 'Foo.vue', filename: 'Foo.vue',
prefixIdentifiers: false, prefixIdentifiers: false,
@ -24,7 +24,11 @@ export const compilerOptions: CompilerOptions = reactive({
setupProp: BindingTypes.PROPS, setupProp: BindingTypes.PROPS,
vMySetupDir: BindingTypes.SETUP_CONST vMySetupDir: BindingTypes.SETUP_CONST
} }
}) }
export const compilerOptions: CompilerOptions = reactive(
Object.assign({}, defaultOptions)
)
const App = { const App = {
setup() { setup() {