Ahmad Kholid 2 年之前
父节点
当前提交
5d22ad67ee

+ 7 - 6
package.json

@@ -1,6 +1,6 @@
 {
   "name": "automa",
-  "version": "1.21.3",
+  "version": "1.21.4",
   "description": "An extension for automating your browser by connecting blocks",
   "repository": {
     "type": "git",
@@ -44,6 +44,7 @@
     "@tiptap/starter-kit": "^2.0.0-beta.197",
     "@tiptap/vue-3": "^2.0.0-beta.96",
     "@viselect/vanilla": "^3.1.1",
+    "@vueuse/head": "^0.9.8",
     "@vueuse/rxjs": "^9.1.1",
     "@vuex-orm/core": "^0.36.4",
     "codemirror": "^6.0.1",
@@ -68,7 +69,7 @@
     "object-path": "^0.11.8",
     "papaparse": "^5.3.1",
     "pinia": "^2.0.22",
-    "rxjs": "^7.5.5",
+    "rxjs": "^7.5.7",
     "tippy.js": "^6.3.1",
     "v-remixicon": "^0.1.1",
     "vue": "^3.2.37",
@@ -87,16 +88,16 @@
     "@babel/preset-env": "^7.18.2",
     "@intlify/vue-i18n-loader": "^4.2.0",
     "@tailwindcss/typography": "^0.5.1",
-    "@vue/compiler-sfc": "^3.2.39",
+    "@vue/compiler-sfc": "^3.2.41",
     "archiver": "^5.3.1",
-    "autoprefixer": "^10.4.7",
+    "autoprefixer": "^10.4.12",
     "babel-loader": "^8.2.2",
     "clean-webpack-plugin": "4.0.0",
     "copy-webpack-plugin": "^11.0.0",
     "core-js": "^3.25.0",
     "cross-env": "^7.0.3",
     "css-loader": "^6.7.1",
-    "eslint": "^8.23.0",
+    "eslint": "^8.25.0",
     "eslint-config-airbnb-base": "^15.0.0",
     "eslint-config-prettier": "^8.3.0",
     "eslint-friendly-formatter": "^4.0.1",
@@ -110,7 +111,7 @@
     "html-webpack-plugin": "^5.5.0",
     "lint-staged": "^13.0.2",
     "mini-css-extract-plugin": "^2.3.0",
-    "postcss": "^8.4.16",
+    "postcss": "^8.4.18",
     "postcss-loader": "^7.0.0",
     "prettier": "^2.7.1",
     "simple-git-hooks": "^2.6.1",

+ 1 - 1
src/background/index.js

@@ -270,7 +270,7 @@ async function checkRecordingWorkflow(tabId, tabUrl) {
     file: 'recordWorkflow.bundle.js',
   });
 }
-browser.webNavigation.onCompleted.addListener(
+browser.webNavigation.onHistoryStateUpdated.addListener(
   async ({ tabId, url, frameId }) => {
     if (frameId > 0) return;
 

+ 0 - 2
src/components/newtab/workflow/WorkflowEditBlock.vue

@@ -45,7 +45,6 @@
       }"
     />
     <edit-block-settings
-      v-if="!excludeOnError.includes(data.id)"
       :key="data.itemId || data.blockId"
       :data="data"
       class="mt-4"
@@ -56,7 +55,6 @@
 <script setup>
 import { computed } from 'vue';
 import { useI18n } from 'vue-i18n';
-import { excludeOnError } from '@/utils/shared';
 import customEditComponents from '@business/blocks/editComponents';
 import EditBlockSettings from './edit/EditBlockSettings.vue';
 

+ 10 - 3
src/components/newtab/workflow/edit/EditBlockSettings.vue

@@ -55,6 +55,7 @@
 import { reactive, onMounted } from 'vue';
 import { useI18n } from 'vue-i18n';
 import defu from 'defu';
+import { excludeOnError } from '@/utils/shared';
 import BlockSettingLines from './BlockSetting/BlockSettingLines.vue';
 import BlockSettingOnError from './BlockSetting/BlockSettingOnError.vue';
 import BlockSettingGeneral from './BlockSetting/BlockSettingGeneral.vue';
@@ -73,6 +74,7 @@ const emit = defineEmits(['change']);
 
 const { t } = useI18n();
 
+let currActiveTab = 'on-error';
 const browserType = BROWSER_TYPE;
 const supportedBlocks = ['forms', 'event-click', 'trigger-event', 'press-key'];
 const tabs = [
@@ -82,11 +84,16 @@ const tabs = [
   },
   { id: 'lines', name: t('workflow.blocks.base.settings.line.title') },
 ];
-const isSupported =
+const isOnErrorSupported = !excludeOnError.includes(props.data.id);
+const isDebugSupported =
   browserType !== 'firefox' && supportedBlocks.includes(props.data.id);
 
-if (isSupported) {
+if (isDebugSupported) {
+  currActiveTab = 'general';
   tabs.unshift({ id: 'general', name: t('settings.menu.general') });
+} else if (!isOnErrorSupported) {
+  currActiveTab = 'lines';
+  tabs.shift();
 }
 
 const defaultSettings = {
@@ -107,9 +114,9 @@ const defaultSettings = {
 const state = reactive({
   showModal: false,
   retrieved: false,
+  activeTab: currActiveTab,
   onError: defaultSettings.onError,
   settings: defaultSettings.general,
-  activeTab: !isSupported ? 'on-error' : 'general',
 });
 
 function onDataChange(key, data) {

+ 16 - 2
src/components/newtab/workflow/edit/EditClipboard.vue

@@ -6,7 +6,7 @@
       :placeholder="t('common.description')"
       @change="updateData({ description: $event })"
     />
-    <template v-if="permission.has.clipboardRead">
+    <template v-if="hasAllPermissions">
       <ui-select
         :model-value="data.type"
         class="mt-4 w-full"
@@ -50,6 +50,7 @@
   </div>
 </template>
 <script setup>
+import { computed } from 'vue';
 import { useI18n } from 'vue-i18n';
 import { useHasPermissions } from '@/composable/hasPermissions';
 import InsertWorkflowData from './InsertWorkflowData.vue';
@@ -63,9 +64,22 @@ const props = defineProps({
 const emit = defineEmits(['update:data']);
 
 const types = ['get', 'insert'];
+const permissions = ['clipboardRead'];
+const isFirefox = BROWSER_TYPE === 'firefox';
+
+if (isFirefox) {
+  permissions.push('clipboardWrite');
+}
 
 const { t } = useI18n();
-const permission = useHasPermissions(['clipboardRead']);
+const permission = useHasPermissions(permissions);
+
+const hasAllPermissions = computed(() => {
+  if (isFirefox)
+    return permission.has.clipboardRead && permission.has.clipboardWrite;
+
+  return permission.has.clipboardRead;
+});
 
 function updateData(value) {
   emit('update:data', { ...props.data, ...value });

+ 1 - 1
src/components/newtab/workflow/edit/EditInsertData.vue

@@ -11,7 +11,7 @@
       variant="accent"
       @click="showModal = !showModal"
     >
-      Insert data
+      Insert data ({{ dataList.length }})
     </ui-button>
     <ui-modal
       v-model="showModal"

+ 22 - 9
src/components/newtab/workflow/edit/EditWorkflowParameters.vue

@@ -55,8 +55,8 @@
               </div>
               <div class="col-span-4 flex items-center">
                 <component
-                  :is="paramTypes[param.type].valueComp"
-                  v-if="paramTypes[param.type].valueComp"
+                  :is="paramTypes[param.type]?.valueComp"
+                  v-if="paramTypes[param.type]?.valueComp"
                   v-model="param.defaultValue"
                   :param-data="param"
                   :editor="true"
@@ -92,13 +92,22 @@
                   <span>Options</span>
                 </template>
                 <div class="pl-[28px] mt-2 mb-4">
-                  <ui-textarea
-                    v-model="param.description"
-                    placeholder="Description"
-                    title="Description"
-                    class="mb-2 block"
-                    style="max-width: 400px"
-                  />
+                  <div class="flex mb-2 items-start">
+                    <ui-textarea
+                      v-model="param.description"
+                      placeholder="Description"
+                      title="Description"
+                      style="max-width: 400px"
+                    />
+                    <ui-checkbox
+                      v-if="['string', 'number'].includes(param.type)"
+                      :model-value="param.data?.required"
+                      class="ml-6"
+                      @change="param.data.required = $event"
+                    >
+                      Parameter required
+                    </ui-checkbox>
+                  </div>
                   <component
                     :is="paramTypes[param.type].options"
                     v-if="paramTypes[param.type].options"
@@ -144,6 +153,7 @@ const paramTypes = {
     valueComp: ParameterInputValue,
     data: {
       masks: [],
+      required: false,
       useMask: false,
       unmaskValue: false,
     },
@@ -151,6 +161,9 @@ const paramTypes = {
   number: {
     id: 'number',
     name: 'Input (number)',
+    data: {
+      required: false,
+    },
   },
   ...customParameters,
 };

+ 9 - 2
src/components/ui/UiModal.vue

@@ -7,10 +7,13 @@
       <transition name="modal" mode="out-in">
         <div
           v-if="show"
-          class="bg-black overflow-y-auto bg-opacity-20 dark:bg-opacity-60 modal-ui__content-container z-50 flex justify-center items-end md:items-center"
+          class="overflow-y-auto modal-ui__content-container z-50 flex justify-center items-center"
           :style="{ 'backdrop-filter': blur && 'blur(2px)' }"
-          @click.self="closeModal"
         >
+          <div
+            class="absolute h-full w-full bg-black bg-opacity-20 dark:bg-opacity-60"
+            @click="closeModal"
+          />
           <slot v-if="customContent"></slot>
           <ui-card
             v-else
@@ -75,6 +78,9 @@ export default {
     const show = ref(false);
     const modalContent = ref(null);
 
+    function onClickOverlay(event) {
+      console.log(event);
+    }
     function toggleBodyOverflow(value) {
       document.body.classList.toggle('overflow-hidden', value);
     }
@@ -109,6 +115,7 @@ export default {
       show,
       closeModal,
       modalContent,
+      onClickOverlay,
     };
   },
 };

+ 1 - 1
src/content/commandPalette/App.vue

@@ -249,7 +249,7 @@ function onKeydown(event) {
   }
 
   const shortcuts = window._automaShortcuts;
-  if (shortcuts.length < 1) return;
+  if (!shortcuts || shortcuts.length < 1) return;
 
   const automaShortcut = shortcuts.every((shortcutKey) => {
     if (shortcutKey === 'mod') return ctrlKey || metaKey;

+ 34 - 9
src/content/index.js

@@ -1,8 +1,10 @@
 import browser from 'webextension-polyfill';
-import findSelector from '@/lib/findSelector';
-import { toCamelCase } from '@/utils/helper';
+import cloneDeep from 'lodash.clonedeep';
 import { nanoid } from 'nanoid';
 import automa from '@business';
+import FindElement from '@/utils/FindElement';
+import findSelector from '@/lib/findSelector';
+import { toCamelCase, isXPath } from '@/utils/helper';
 import handleSelector from './handleSelector';
 import blocksHandler from './blocksHandler';
 import showExecutedBlock from './showExecutedBlock';
@@ -44,7 +46,13 @@ async function executeBlock(data) {
   const removeExecutedBlock = showExecutedBlock(data, data.executedBlockOnWeb);
   if (data.data?.selector?.includes('|>')) {
     const [frameSelector, selector] = data.data.selector.split(/\|>(.+)/);
-    const frameElement = document.querySelector(frameSelector);
+
+    let findBy = data?.data?.findBy;
+    if (!findBy) {
+      findBy = isXPath(frameSelector) ? 'xpath' : 'cssSelector';
+    }
+
+    const frameElement = FindElement[findBy]({ selector: frameSelector });
     const frameError = (message) => {
       const error = new Error(message);
       error.data = { selector: frameSelector };
@@ -151,18 +159,28 @@ function messageListener({ data, source }) {
       const tag = target.tagName;
       if (tag === 'A') {
         $ctxLink = target.href;
+      } else {
+        const closestUrl = target.closest('a');
+        if (closestUrl) $ctxLink = closestUrl.href;
       }
 
-      const mediaTags = ['AUDIO', 'VIDEO', 'IMG'];
-      if (mediaTags.includes(tag)) {
-        let mediaSrc = target.src || '';
+      const getMediaSrc = (element) => {
+        let mediaSrc = element.src || '';
 
         if (!mediaSrc.src) {
-          const sourceEl = target.querySelector('source');
+          const sourceEl = element.querySelector('source');
           if (sourceEl) mediaSrc = sourceEl.src;
         }
 
-        $ctxMediaUrl = mediaSrc;
+        return mediaSrc;
+      };
+
+      const mediaTags = ['AUDIO', 'VIDEO', 'IMG'];
+      if (mediaTags.includes(tag)) {
+        $ctxMediaUrl = getMediaSrc(target);
+      } else {
+        const closestMedia = target.closest('audio,video,img');
+        if (closestMedia) $ctxMediaUrl = getMediaSrc(closestMedia);
       }
     },
     true
@@ -230,12 +248,19 @@ function messageListener({ data, source }) {
               $ctxTextSelection = window.getSelection().toString();
             }
 
-            resolve({
+            const cloneContextData = cloneDeep({
               $ctxLink,
               $ctxMediaUrl,
               $ctxElSelector,
               $ctxTextSelection,
             });
+
+            $ctxLink = '';
+            $ctxMediaUrl = '';
+            $ctxElSelector = '';
+            $ctxTextSelection = '';
+
+            resolve(cloneContextData);
             break;
           }
           default:

+ 1 - 1
src/manifest.firefox.json

@@ -40,7 +40,7 @@
       "all_frames": false
     }
   ],
-  "optional_permissions": ["clipboardRead", "downloads", "notifications", "cookies"],
+  "optional_permissions": ["clipboardRead", "clipboardWrite", "downloads", "notifications", "cookies"],
   "permissions": [
     "tabs",
     "proxy",

+ 4 - 0
src/newtab/index.js

@@ -1,4 +1,5 @@
 import { createApp } from 'vue';
+import { createHead } from '@vueuse/head';
 import App from './App.vue';
 import router from './router';
 import pinia from '../lib/pinia';
@@ -11,10 +12,13 @@ import '../assets/css/fonts.css';
 import '../assets/css/style.css';
 import '../assets/css/flow.css';
 
+const head = createHead();
+
 createApp(App)
   .use(router)
   .use(compsUi)
   .use(pinia)
+  .use(head)
   .use(vueI18n)
   .use(vueToastification)
   .use(vRemixicon, icons)

+ 6 - 0
src/newtab/pages/workflows/[id].vue

@@ -294,6 +294,7 @@ import { useI18n } from 'vue-i18n';
 import { useRoute, useRouter, onBeforeRouteLeave } from 'vue-router';
 import { customAlphabet } from 'nanoid';
 import { useToast } from 'vue-toastification';
+import { useHead } from '@vueuse/head';
 import defu from 'defu';
 import dagre from 'dagre';
 import { useUserStore } from '@/stores/user';
@@ -1157,6 +1158,8 @@ function onEditorInit(instance) {
   // });
 
   instance.onNodeDragStop(({ nodes }) => {
+    if (!editorCommands?.state?.nodes) return;
+
     nodes.forEach((node) => {
       editorCommands.state.nodes[node.id] = node;
     });
@@ -1514,6 +1517,9 @@ function checkWorkflowUpdate() {
     });
 }
 
+useHead({
+  title: () => `${workflow.value?.name} workflow - Automa` || 'Automa',
+});
 const shortcut = useShortcut([
   getShortcut('editor:toggle-sidebar', toggleSidebar),
   getShortcut('editor:duplicate-block', duplicateElements),

+ 13 - 3
src/params/App.vue

@@ -53,7 +53,7 @@
                 :is="paramsList[param.type].valueComp"
                 v-if="paramsList[param.type]"
                 v-model="param.value"
-                :label="param.name"
+                :label="param.name + (param.data?.required ? '*' : '')"
                 :param-data="param"
                 class="w-full"
               />
@@ -61,10 +61,9 @@
                 v-else
                 v-model="param.value"
                 :type="param.inputType"
-                :label="param.name"
+                :label="param.name + (param.data?.required ? '*' : '')"
                 :placeholder="param.placeholder"
                 class="w-full"
-                @keyup.enter="runWorkflow(index, workflow)"
               />
               <p
                 v-if="param.description"
@@ -83,6 +82,7 @@
             </ui-button>
             <ui-button
               v-if="workflow.type === 'block'"
+              :disabled="!isValidParams(workflow.params)"
               variant="accent"
               @click="continueWorkflow(index, workflow)"
             >
@@ -90,6 +90,7 @@
             </ui-button>
             <ui-button
               v-else
+              :disabled="!isValidParams(workflow.params)"
               variant="accent"
               @click="runWorkflow(index, workflow)"
             >
@@ -245,6 +246,15 @@ function continueWorkflow(index, { data, params }) {
       deleteWorkflow(index);
     });
 }
+function isValidParams(params) {
+  const isValid = params.every((param) => {
+    if (!param.data?.required) return true;
+
+    return param.value;
+  });
+
+  return isValid;
+}
 
 browser.runtime.onMessage.addListener(({ name, data }) => {
   if (name === 'workflow:params') {

+ 1 - 1
src/utils/helper.js

@@ -1,7 +1,7 @@
 import browser from 'webextension-polyfill';
 
 export function isXPath(str) {
-  const regex = /^[(/@]/;
+  const regex = /^([(/@]|id\()/;
 
   return regex.test(str);
 }

+ 1 - 1
src/utils/shared.js

@@ -1659,7 +1659,7 @@ export const conditionBuilder = {
       placeholder: 'name',
     },
     dataPath: {
-      label: 'variables.variableName',
+      label: 'variables@variableName',
       placeholder: '',
     },
   },

+ 9 - 1
src/utils/testConditions.js

@@ -43,7 +43,15 @@ export default async function (conditionsArr, workflowData) {
 
   async function getConditionItemValue({ type, data }) {
     if (type.startsWith('data')) {
-      return objectPath.has(workflowData.refData, data.dataPath);
+      let dataPath = data.dataPath.trim().replace('@', '.');
+      const isInsideBrackets =
+        dataPath.startsWith('{{') && dataPath.endsWith('}}');
+
+      if (isInsideBrackets) {
+        dataPath = dataPath.slice(2, -2).trim();
+      }
+
+      return objectPath.has(workflowData.refData, dataPath);
     }
 
     const copyData = cloneDeep(data);

+ 139 - 29
yarn.lock

@@ -1046,10 +1046,10 @@
   resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
   integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
 
-"@eslint/eslintrc@^1.3.2":
-  version "1.3.2"
-  resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.2.tgz#58b69582f3b7271d8fa67fe5251767a5b38ea356"
-  integrity sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==
+"@eslint/eslintrc@^1.3.3":
+  version "1.3.3"
+  resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.3.tgz#2b044ab39fdfa75b4688184f9e573ce3c5b0ff95"
+  integrity sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==
   dependencies:
     ajv "^6.12.4"
     debug "^4.3.2"
@@ -1061,20 +1061,15 @@
     minimatch "^3.1.2"
     strip-json-comments "^3.1.1"
 
-"@humanwhocodes/config-array@^0.10.4":
-  version "0.10.4"
-  resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.10.4.tgz#01e7366e57d2ad104feea63e72248f22015c520c"
-  integrity sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==
+"@humanwhocodes/config-array@^0.10.5":
+  version "0.10.7"
+  resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.10.7.tgz#6d53769fd0c222767e6452e8ebda825c22e9f0dc"
+  integrity sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==
   dependencies:
     "@humanwhocodes/object-schema" "^1.2.1"
     debug "^4.1.1"
     minimatch "^3.0.4"
 
-"@humanwhocodes/gitignore-to-minimatch@^1.0.2":
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz#316b0a63b91c10e53f242efb4ace5c3b34e8728d"
-  integrity sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==
-
 "@humanwhocodes/module-importer@^1.0.1":
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
@@ -1689,6 +1684,16 @@
     estree-walker "^2.0.2"
     source-map "^0.6.1"
 
+"@vue/compiler-core@3.2.41":
+  version "3.2.41"
+  resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.41.tgz#fb5b25f23817400f44377d878a0cdead808453ef"
+  integrity sha512-oA4mH6SA78DT+96/nsi4p9DX97PHcNROxs51lYk7gb9Z4BPKQ3Mh+BLn6CQZBw857Iuhu28BfMSRHAlPvD4vlw==
+  dependencies:
+    "@babel/parser" "^7.16.4"
+    "@vue/shared" "3.2.41"
+    estree-walker "^2.0.2"
+    source-map "^0.6.1"
+
 "@vue/compiler-dom@3.2.39":
   version "3.2.39"
   resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.39.tgz#bd69d35c1a48fe2cea4ab9e96d2a3a735d146fdf"
@@ -1697,7 +1702,15 @@
     "@vue/compiler-core" "3.2.39"
     "@vue/shared" "3.2.39"
 
-"@vue/compiler-sfc@3.2.39", "@vue/compiler-sfc@^3.2.39":
+"@vue/compiler-dom@3.2.41":
+  version "3.2.41"
+  resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.41.tgz#dc63dcd3ce8ca8a8721f14009d498a7a54380299"
+  integrity sha512-xe5TbbIsonjENxJsYRbDJvthzqxLNk+tb3d/c47zgREDa/PCp6/Y4gC/skM4H6PIuX5DAxm7fFJdbjjUH2QTMw==
+  dependencies:
+    "@vue/compiler-core" "3.2.41"
+    "@vue/shared" "3.2.41"
+
+"@vue/compiler-sfc@3.2.39":
   version "3.2.39"
   resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.39.tgz#8fe29990f672805b7c5a2ecfa5b05e681c862ea2"
   integrity sha512-fqAQgFs1/BxTUZkd0Vakn3teKUt//J3c420BgnYgEOoVdTwYpBTSXCMJ88GOBCylmUBbtquGPli9tVs7LzsWIA==
@@ -1713,6 +1726,22 @@
     postcss "^8.1.10"
     source-map "^0.6.1"
 
+"@vue/compiler-sfc@^3.2.41":
+  version "3.2.41"
+  resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.41.tgz#238fb8c48318408c856748f4116aff8cc1dc2a73"
+  integrity sha512-+1P2m5kxOeaxVmJNXnBskAn3BenbTmbxBxWOtBq3mQTCokIreuMULFantBUclP0+KnzNCMOvcnKinqQZmiOF8w==
+  dependencies:
+    "@babel/parser" "^7.16.4"
+    "@vue/compiler-core" "3.2.41"
+    "@vue/compiler-dom" "3.2.41"
+    "@vue/compiler-ssr" "3.2.41"
+    "@vue/reactivity-transform" "3.2.41"
+    "@vue/shared" "3.2.41"
+    estree-walker "^2.0.2"
+    magic-string "^0.25.7"
+    postcss "^8.1.10"
+    source-map "^0.6.1"
+
 "@vue/compiler-ssr@3.2.39":
   version "3.2.39"
   resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.39.tgz#4f3bfb535cb98b764bee45e078700e03ccc60633"
@@ -1721,6 +1750,14 @@
     "@vue/compiler-dom" "3.2.39"
     "@vue/shared" "3.2.39"
 
+"@vue/compiler-ssr@3.2.41":
+  version "3.2.41"
+  resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.41.tgz#344f564d68584b33367731c04ffc949784611fcb"
+  integrity sha512-Y5wPiNIiaMz/sps8+DmhaKfDm1xgj6GrH99z4gq2LQenfVQcYXmHIOBcs5qPwl7jaW3SUQWjkAPKMfQemEQZwQ==
+  dependencies:
+    "@vue/compiler-dom" "3.2.41"
+    "@vue/shared" "3.2.41"
+
 "@vue/devtools-api@^6.0.0-beta.11", "@vue/devtools-api@^6.1.4", "@vue/devtools-api@^6.2.1":
   version "6.2.1"
   resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.2.1.tgz#6f2948ff002ec46df01420dfeff91de16c5b4092"
@@ -1737,6 +1774,17 @@
     estree-walker "^2.0.2"
     magic-string "^0.25.7"
 
+"@vue/reactivity-transform@3.2.41":
+  version "3.2.41"
+  resolved "https://registry.yarnpkg.com/@vue/reactivity-transform/-/reactivity-transform-3.2.41.tgz#9ff938877600c97f646e09ac1959b5150fb11a0c"
+  integrity sha512-mK5+BNMsL4hHi+IR3Ft/ho6Za+L3FA5j8WvreJ7XzHrqkPq8jtF/SMo7tuc9gHjLDwKZX1nP1JQOKo9IEAn54A==
+  dependencies:
+    "@babel/parser" "^7.16.4"
+    "@vue/compiler-core" "3.2.41"
+    "@vue/shared" "3.2.41"
+    estree-walker "^2.0.2"
+    magic-string "^0.25.7"
+
 "@vue/reactivity@3.2.39":
   version "3.2.39"
   resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.39.tgz#e6e3615fe2288d4232b104640ddabd0729a78c80"
@@ -1774,6 +1822,11 @@
   resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.39.tgz#302df167559a1a5156da162d8cc6760cef67f8e3"
   integrity sha512-D3dl2ZB9qE6mTuWPk9RlhDeP1dgNRUKC3NJxji74A4yL8M2MwlhLKUC/49WHjrNzSPug58fWx/yFbaTzGAQSBw==
 
+"@vue/shared@3.2.41":
+  version "3.2.41"
+  resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.41.tgz#fbc95422df654ea64e8428eced96ba6ad555d2bb"
+  integrity sha512-W9mfWLHmJhkfAmV+7gDjcHeAWALQtgGT3JErxULl0oz6R6+3ug91I7IErs93eCFhPCZPHBs4QJS7YWEV7A3sxw==
+
 "@vueuse/core@^9.1.0":
   version "9.2.0"
   resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-9.2.0.tgz#58e3588b9bc5a69010aa9104b00056ee9ebff738"
@@ -1784,6 +1837,15 @@
     "@vueuse/shared" "9.2.0"
     vue-demi "*"
 
+"@vueuse/head@^0.9.8":
+  version "0.9.8"
+  resolved "https://registry.yarnpkg.com/@vueuse/head/-/head-0.9.8.tgz#0216fb44fa832ec710862cc60351dbb3e2c6b84c"
+  integrity sha512-zt8+JksoVFKxRvmABlaUHA62w+8nOcD8cJnaJ0+SHcr6xaIP3GXgh7/n2TzUoWw4l3d9UxRNs+tapgHdsQ7RbA==
+  dependencies:
+    "@vueuse/shared" "^9.3.0"
+    "@zhead/schema" "^0.8.5"
+    "@zhead/schema-vue" "^0.8.5"
+
 "@vueuse/metadata@9.2.0":
   version "9.2.0"
   resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-9.2.0.tgz#6bf7c9c44b9f5ece405837226a0e04a997994458"
@@ -1804,6 +1866,13 @@
   dependencies:
     vue-demi "*"
 
+"@vueuse/shared@^9.2.0", "@vueuse/shared@^9.3.0":
+  version "9.3.0"
+  resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-9.3.0.tgz#40fc138ba4e379c894075830aa2e15404aaa8a5b"
+  integrity sha512-caGUWLY0DpPC6l31KxeUy6vPVNA0yKxx81jFYLoMpyP6cF84FG5Dkf69DfSUqL57wX8JcUkJDMnQaQIZPWFEQQ==
+  dependencies:
+    vue-demi "*"
+
 "@vuex-orm/core@^0.36.4":
   version "0.36.4"
   resolved "https://registry.yarnpkg.com/@vuex-orm/core/-/core-0.36.4.tgz#9e2b1b8dfd74c2a508f1862ffa3e4a2c1e4cc60c"
@@ -1959,6 +2028,27 @@
   resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
   integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
 
+"@zhead/schema-raw@0.8.5":
+  version "0.8.5"
+  resolved "https://registry.yarnpkg.com/@zhead/schema-raw/-/schema-raw-0.8.5.tgz#934d8680eac26576e526aefabc50eaf3b7f7bfb2"
+  integrity sha512-Aq+9mksf5zbtj7HYluT6PVyfpQ6z7mja9MzjFxg76Vt+Q9i0oL1XN6ZYaCXImWRafwbyAxjFQ5aUCVyFn79OpA==
+  dependencies:
+    "@zhead/schema" "0.8.5"
+
+"@zhead/schema-vue@^0.8.5":
+  version "0.8.5"
+  resolved "https://registry.yarnpkg.com/@zhead/schema-vue/-/schema-vue-0.8.5.tgz#5bc52b363b2eddcf489100602dfdb3f278b78dfe"
+  integrity sha512-6aXjYy3fZVeYBLrHcJQqzqwzC/2tafRO5UxZEgBHnryRnzeLNZV6nTptDvIPWiJObMoJTK21vbg3gkfLNQg84g==
+  dependencies:
+    "@vueuse/shared" "^9.2.0"
+    "@zhead/schema" "0.8.5"
+    "@zhead/schema-raw" "0.8.5"
+
+"@zhead/schema@0.8.5", "@zhead/schema@^0.8.5":
+  version "0.8.5"
+  resolved "https://registry.yarnpkg.com/@zhead/schema/-/schema-0.8.5.tgz#17f5c6be3b587a938f76d93637a210c0d05a9069"
+  integrity sha512-1S3Otr2zpl1zwP72dNseVXQNG9tnTQ6hHUEUYwINvBjRj6bHcUwdE+Itc9OLxnGAJT/7p8P7GHGo5sshXJNJsA==
+
 abab@^2.0.6:
   version "2.0.6"
   resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291"
@@ -2214,13 +2304,13 @@ atob@^2.1.2:
   resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
   integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
 
-autoprefixer@^10.4.7:
-  version "10.4.11"
-  resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.11.tgz#835136aff1d9cd43640151e0d2dba00f8eac7c1c"
-  integrity sha512-5lHp6DgRodxlBLSkzHOTcufWFflH1ewfy2hvFQyjrblBFlP/0Yh4O/Wrg4ow8WRlN3AAUFFLAQwX8hTptzqVHg==
+autoprefixer@^10.4.12:
+  version "10.4.12"
+  resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.12.tgz#183f30bf0b0722af54ee5ef257f7d4320bb33129"
+  integrity sha512-WrCGV9/b97Pa+jtwf5UGaRjgQIg7OK3D06GnoYoZNcG1Xb8Gt3EfuKjlhh9i/VtT16g6PYjZ69jdJ2g8FxSC4Q==
   dependencies:
-    browserslist "^4.21.3"
-    caniuse-lite "^1.0.30001399"
+    browserslist "^4.21.4"
+    caniuse-lite "^1.0.30001407"
     fraction.js "^4.2.0"
     normalize-range "^0.1.2"
     picocolors "^1.0.0"
@@ -2430,11 +2520,16 @@ camelcase-css@^2.0.1:
   resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
   integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
 
-caniuse-lite@^1.0.30001399, caniuse-lite@^1.0.30001400:
+caniuse-lite@^1.0.30001400:
   version "1.0.30001402"
   resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001402.tgz#aa29e1f47f5055b0d0c07696a67b8b08023d14c8"
   integrity sha512-Mx4MlhXO5NwuvXGgVb+hg65HZ+bhUYsz8QtDGDo2QmaJS2GBX47Xfi2koL86lc8K+l+htXeTEB/Aeqvezoo6Ew==
 
+caniuse-lite@^1.0.30001407:
+  version "1.0.30001419"
+  resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001419.tgz#3542722d57d567c8210d5e4d0f9f17336b776457"
+  integrity sha512-aFO1r+g6R7TW+PNQxKzjITwLOyDhVRLjW0LcwS/HCZGUUKTGNp9+IwLC4xyDSZBygVL/mxaFR3HIV6wEKQuSzw==
+
 canvg@^3.0.6:
   version "3.0.10"
   resolved "https://registry.yarnpkg.com/canvg/-/canvg-3.0.10.tgz#8e52a2d088b6ffa23ac78970b2a9eebfae0ef4b3"
@@ -3420,14 +3515,13 @@ eslint-visitor-keys@^3.3.0:
   resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
   integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
 
-eslint@^8.23.0:
-  version "8.23.1"
-  resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.23.1.tgz#cfd7b3f7fdd07db8d16b4ac0516a29c8d8dca5dc"
-  integrity sha512-w7C1IXCc6fNqjpuYd0yPlcTKKmHlHHktRkzmBPZ+7cvNBQuiNjx0xaMTjAJGCafJhQkrFJooREv0CtrVzmHwqg==
+eslint@^8.25.0:
+  version "8.25.0"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.25.0.tgz#00eb962f50962165d0c4ee3327708315eaa8058b"
+  integrity sha512-DVlJOZ4Pn50zcKW5bYH7GQK/9MsoQG2d5eDH0ebEkE8PbgzTTmtt/VTH9GGJ4BfeZCpBLqFfvsjX35UacUL83A==
   dependencies:
-    "@eslint/eslintrc" "^1.3.2"
-    "@humanwhocodes/config-array" "^0.10.4"
-    "@humanwhocodes/gitignore-to-minimatch" "^1.0.2"
+    "@eslint/eslintrc" "^1.3.3"
+    "@humanwhocodes/config-array" "^0.10.5"
     "@humanwhocodes/module-importer" "^1.0.1"
     ajv "^6.10.0"
     chalk "^4.0.0"
@@ -5377,7 +5471,7 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0, postcss-value-parser@^
   resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
   integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
 
-postcss@^8.1.10, postcss@^8.4.14, postcss@^8.4.16, postcss@^8.4.7:
+postcss@^8.1.10, postcss@^8.4.14, postcss@^8.4.7:
   version "8.4.16"
   resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.16.tgz#33a1d675fac39941f5f445db0de4db2b6e01d43c"
   integrity sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==
@@ -5386,6 +5480,15 @@ postcss@^8.1.10, postcss@^8.4.14, postcss@^8.4.16, postcss@^8.4.7:
     picocolors "^1.0.0"
     source-map-js "^1.0.2"
 
+postcss@^8.4.18:
+  version "8.4.18"
+  resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.18.tgz#6d50046ea7d3d66a85e0e782074e7203bc7fbca2"
+  integrity sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==
+  dependencies:
+    nanoid "^3.3.4"
+    picocolors "^1.0.0"
+    source-map-js "^1.0.2"
+
 prelude-ls@^1.2.1:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
@@ -5808,6 +5911,13 @@ rxjs@^7.5.5:
   dependencies:
     tslib "^2.1.0"
 
+rxjs@^7.5.7:
+  version "7.5.7"
+  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.7.tgz#2ec0d57fdc89ece220d2e702730ae8f1e49def39"
+  integrity sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==
+  dependencies:
+    tslib "^2.1.0"
+
 safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
   version "5.1.2"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"