From eb721d49c004abf5eff0a4e7da71bad904aa6bac Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 4 Jan 2022 17:32:25 +0800 Subject: [PATCH] workflow: improve template explorer hash persistence --- packages/template-explorer/src/index.ts | 59 +++++++++++++++++------ packages/template-explorer/src/options.ts | 8 ++- 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/packages/template-explorer/src/index.ts b/packages/template-explorer/src/index.ts index 5efe07eb..7b7e2ae2 100644 --- a/packages/template-explorer/src/index.ts +++ b/packages/template-explorer/src/index.ts @@ -1,7 +1,12 @@ import * as m from 'monaco-editor' import { compile, CompilerError, CompilerOptions } from '@vue/compiler-dom' 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 { SourceMapConsumer } from 'source-map' import theme from './theme' @@ -35,19 +40,32 @@ window.init = () => { monaco.editor.defineTheme('my-theme', theme) monaco.editor.setTheme('my-theme') - const persistedState: PersistedState = JSON.parse( - decodeURIComponent(window.location.hash.slice(1)) || - localStorage.getItem('state') || - `{}` - ) - // functions are not persistable, so delete it in case we sometimes need - // to debug with custom nodeTransforms - if (persistedState.options) { - delete persistedState.options.nodeTransforms + let persistedState: PersistedState | undefined + + try { + let hash = window.location.hash.slice(1) + try { + hash = escape(atob(hash)) + } catch (e) {} + persistedState = JSON.parse( + 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 - Object.assign(compilerOptions, persistedState.options) + if (persistedState) { + // 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 lastSuccessfulMap: SourceMapConsumer | undefined = undefined @@ -99,13 +117,24 @@ window.init = () => { function reCompile() { const src = editor.getValue() // 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({ src, ssr: ssrMode.value, - options: compilerOptions + options: optionsToSave } as PersistedState) localStorage.setItem('state', state) - window.location.hash = encodeURIComponent(state) + window.location.hash = btoa(unescape(encodeURIComponent(state))) const res = compileCode(src) if (res) { output.setValue(res) @@ -113,7 +142,7 @@ window.init = () => { } const editor = monaco.editor.create(document.getElementById('source')!, { - value: persistedState.src || `
Hello World!
`, + value: persistedState?.src || `
Hello World!
`, language: 'html', ...sharedEditorOptions, wordWrap: 'bounded' diff --git a/packages/template-explorer/src/options.ts b/packages/template-explorer/src/options.ts index c5c5eba5..2b66b2e7 100644 --- a/packages/template-explorer/src/options.ts +++ b/packages/template-explorer/src/options.ts @@ -4,7 +4,7 @@ import { BindingTypes } from '@vue/compiler-core' export const ssrMode = ref(false) -export const compilerOptions: CompilerOptions = reactive({ +export const defaultOptions: CompilerOptions = { mode: 'module', filename: 'Foo.vue', prefixIdentifiers: false, @@ -24,7 +24,11 @@ export const compilerOptions: CompilerOptions = reactive({ setupProp: BindingTypes.PROPS, vMySetupDir: BindingTypes.SETUP_CONST } -}) +} + +export const compilerOptions: CompilerOptions = reactive( + Object.assign({}, defaultOptions) +) const App = { setup() {