Browse Source

feat: show matching errors upon saving script

tophf 3 years ago
parent
commit
a1f6cc5a29
3 changed files with 36 additions and 12 deletions
  1. 19 9
      src/background/utils/db.js
  2. 1 1
      src/confirm/views/app.vue
  3. 16 2
      src/options/views/edit/index.vue

+ 19 - 9
src/background/utils/db.js

@@ -85,14 +85,7 @@ Object.assign(commands, {
     }
     return sendCmd('RemoveScript', id);
   },
-  ParseMeta(code) {
-    const meta = parseMeta(code);
-    const errors = [];
-    testerBatch(errors);
-    testScript('', { custom: getDefaultCustom(), meta });
-    testerBatch();
-    return { meta, errors };
-  },
+  ParseMeta: parseMetaWithErrors,
   ParseScript: parseScript,
   /** @return {Promise<void>} */
   UpdateScriptInfo({ id, config, custom }) {
@@ -517,11 +510,28 @@ export async function updateScriptInfo(id, data) {
   return sendCmd('UpdateScript', { where: { id }, update: script });
 }
 
+/**
+ * @param {string} code
+ * @return {{ meta: VMScript.Meta, errors: string[] }}
+ */
+function parseMetaWithErrors(code) {
+  const meta = parseMeta(code);
+  const errors = [];
+  testerBatch(errors);
+  testScript('', { custom: getDefaultCustom(), meta });
+  testerBatch();
+  return {
+    meta,
+    errors: errors.length ? errors : null,
+  };
+}
+
 /** @return {Promise<{ isNew?, update, where }>} */
 export async function parseScript(src) {
-  const meta = parseMeta(src.code);
+  const { meta, errors } = parseMetaWithErrors(src.code);
   if (!meta.name) throw `${i18n('msgInvalidScript')}\n${i18n('labelNoName')}`;
   const result = {
+    errors,
     update: {
       message: src.message == null ? i18n('msgUpdated') : src.message || '',
     },

+ 1 - 1
src/confirm/views/app.vue

@@ -262,7 +262,7 @@ export default {
         .join('\n')
         || ''
       ));
-      this.lists[''] = errors.join('\n');
+      this.lists[''] = errors?.join('\n') || '';
       this.script = { meta, custom: {}, props: {} };
       this.allDeps = [
         [...new Set(meta.require)],

+ 16 - 2
src/options/views/edit/index.vue

@@ -17,7 +17,8 @@
            v-text="i18n('editHowToHint')"/>
       </div>
       <div class="edit-buttons">
-        <button v-text="i18n('buttonSave')" @click="save" :disabled="!canSave"/>
+        <button v-text="i18n('buttonSave')" @click="save" :disabled="!canSave"
+                :class="{'has-error': errors}" :title="errors"/>
         <button v-text="i18n('buttonSaveClose')" @click="saveClose" :disabled="!canSave"/>
         <button v-text="i18n('buttonClose')" @click="close"/>
       </div>
@@ -56,6 +57,12 @@
         :hotkeys="hotkeys"
       />
     </div>
+    <div v-if="errors" class="errors my-1c">
+      <p v-for="e in errors" :key="e" v-text="e" class="text-red"/>
+      <p class="my-1">
+        <a :href="urlMatching" target="_blank" rel="noopener noreferrer" v-text="urlMatching"/>
+      </p>
+    </div>
   </div>
 </template>
 
@@ -168,6 +175,8 @@ export default {
         },
       },
       hotkeys: null,
+      errors: null,
+      urlMatching: 'https://violentmonkey.github.io/api/matching/',
     };
   },
   computed: {
@@ -300,9 +309,10 @@ export default {
         codeComponent.cm.markClean();
         this.codeDirty = false; // triggers onChange which sets canSave
         this.canSave = false; // ...and set it explicitly in case codeDirty was false
+        this.errors = res.errors;
         if (newId) {
           this.script = res.update;
-          window.history.replaceState(null, this.scriptName, `#scripts/${newId}`);
+          if (!id) window.history.replaceState(null, this.scriptName, `#scripts/${newId}`);
         }
       } catch (err) {
         showConfirmation(`${err.message || err}`, {
@@ -406,6 +416,10 @@ export default {
       }
     }
   }
+  .errors {
+    border-top: 2px solid red;
+    padding: .5em 1em;
+  }
 }
 
 @media (max-width: 767px) {