]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
workflow: improve template explorer hash persistence
authorEvan You <yyx990803@gmail.com>
Tue, 4 Jan 2022 09:32:25 +0000 (17:32 +0800)
committerEvan You <yyx990803@gmail.com>
Tue, 4 Jan 2022 09:32:25 +0000 (17:32 +0800)
packages/template-explorer/src/index.ts
packages/template-explorer/src/options.ts

index 5efe07eb83e03a1058aeafb1b69894347c2ca824..7b7e2ae273aac8208001ed7c5140bd65ed408f49 100644 (file)
@@ -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 || `<div>Hello World!</div>`,
+    value: persistedState?.src || `<div>Hello World!</div>`,
     language: 'html',
     ...sharedEditorOptions,
     wordWrap: 'bounded'
index c5c5eba5a478938679c4f3a1f1dc042423d1bb9e..2b66b2e70d95ce680d5d2ed3c05d8ba39df4958e 100644 (file)
@@ -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() {