Ahmad Kholid 2 lat temu
rodzic
commit
3e93ec9d02

+ 5 - 2
.vscode/settings.json

@@ -1,3 +1,6 @@
 {
-  "editor.formatOnSave": true
-}
+  "editor.formatOnSave": true,
+  "i18n-ally.localesPaths": [
+    "src/locales"
+  ]
+}

+ 22 - 13
package.json

@@ -1,6 +1,6 @@
 {
   "name": "automa",
-  "version": "1.24.1",
+  "version": "1.24.2",
   "description": "An extension for automating your browser by connecting blocks",
   "repository": {
     "type": "git",
@@ -28,25 +28,27 @@
     "*.{js,ts,vue}": "eslint --fix"
   },
   "dependencies": {
-    "@codemirror/autocomplete": "^6.1.0",
+    "@codemirror/autocomplete": "^6.3.4",
     "@codemirror/lang-css": "^6.0.1",
-    "@codemirror/lang-html": "^6.2.0",
-    "@codemirror/lang-javascript": "^6.0.2",
-    "@codemirror/lang-json": "^6.0.0",
+    "@codemirror/lang-html": "^6.4.0",
+    "@codemirror/lang-javascript": "^6.1.1",
+    "@codemirror/lang-json": "^6.0.1",
     "@codemirror/language": "^6.3.1",
-    "@codemirror/theme-one-dark": "^6.0.0",
+    "@codemirror/theme-one-dark": "^6.1.0",
     "@medv/finder": "^2.1.0",
     "@n8n_io/riot-tmpl": "^1.0.1",
-    "@tiptap/extension-character-count": "^2.0.0-beta.31",
-    "@tiptap/extension-image": "^2.0.0-beta.30",
-    "@tiptap/extension-link": "^2.0.0-beta.43",
-    "@tiptap/extension-placeholder": "^2.0.0-beta.53",
-    "@tiptap/starter-kit": "^2.0.0-beta.197",
-    "@tiptap/vue-3": "^2.0.0-beta.96",
+    "@tiptap/core": "^2.0.0-beta.205",
+    "@tiptap/extension-character-count": "^2.0.0-beta.205",
+    "@tiptap/extension-history": "^2.0.0-beta.205",
+    "@tiptap/extension-image": "^2.0.0-beta.205",
+    "@tiptap/extension-link": "^2.0.0-beta.205",
+    "@tiptap/extension-placeholder": "^2.0.0-beta.205",
+    "@tiptap/starter-kit": "^2.0.0-beta.205",
+    "@tiptap/vue-3": "^2.0.0-beta.205",
     "@viselect/vanilla": "^3.1.0",
     "@vue-flow/additional-components": "^1.2.4",
     "@vue-flow/core": "^1.5.0",
-    "@vueuse/head": "^0.9.7",
+    "@vueuse/head": "^1.0.22",
     "@vueuse/rxjs": "^9.1.1",
     "@vuex-orm/core": "^0.36.4",
     "codemirror": "^6.0.1",
@@ -72,7 +74,14 @@
     "object-path": "^0.11.8",
     "papaparse": "^5.3.1",
     "pinia": "^2.0.22",
+    "prosemirror-commands": "^1.5.0",
+    "prosemirror-dropcursor": "^1.6.1",
+    "prosemirror-gapcursor": "^1.3.1",
+    "prosemirror-history": "^1.3.0",
+    "prosemirror-keymap": "^1.2.0",
+    "prosemirror-schema-list": "^1.2.2",
     "rxjs": "^7.5.7",
+    "sizzle": "^2.3.8",
     "tippy.js": "^6.3.1",
     "v-remixicon": "^0.1.1",
     "vue": "^3.2.37",

+ 1 - 1
src/background/BackgroundWorkflowTriggers.js

@@ -19,7 +19,7 @@ async function executeWorkflow(workflowData, options) {
     return;
   }
 
-  await BackgroundUtils.openDashboard('', false);
+  await BackgroundUtils.openDashboard('?fromBackground=true', false);
   await BackgroundUtils.sendMessageToDashboard('workflow:execute', {
     data: workflowData,
     options,

+ 1 - 1
src/background/index.js

@@ -117,7 +117,7 @@ message.on('workflow:execute', async (workflowData, sender) => {
   const context = workflowData.settings.execContext;
   const isMV2 = browser.runtime.getManifest().manifest_version === 2;
   if (!isMV2 && (!context || context === 'popup')) {
-    await BackgroundUtils.openDashboard('', false);
+    await BackgroundUtils.openDashboard('?fromBackground=true', false);
     await BackgroundUtils.sendMessageToDashboard('workflow:execute', {
       data: workflowData,
       options: workflowData.option,

+ 1 - 0
src/components/newtab/shared/SharedCodemirror.vue

@@ -72,6 +72,7 @@ const updateListener = EditorView.updateListener.of((event) => {
 const customExtension = Array.isArray(props.extensions)
   ? props.extensions
   : [props.extensions];
+
 const state = EditorState.create({
   doc: props.modelValue,
   extensions: [

+ 7 - 3
src/components/newtab/workflow/edit/BlockSetting/BlockSettingGeneral.vue

@@ -16,8 +16,7 @@
           class="w-24"
         />
       </div>
-      <ui-list-item v-if="isDebugSupported" small>
-        <ui-switch v-model="state.debugMode" class="mr-4" />
+      <ui-list-item v-if="isDebugSupported" small class="mt-4">
         <div class="flex-1 overflow-hidden">
           <p class="text-overflow">
             {{ t('workflow.settings.debugMode.title') }}
@@ -28,6 +27,7 @@
             Execute block using the Chrome DevTools Protocol
           </p>
         </div>
+        <ui-switch v-model="state.debugMode" class="mr-4" />
       </ui-list-item>
     </ui-list>
   </div>
@@ -41,6 +41,10 @@ const props = defineProps({
     type: Object,
     default: () => ({}),
   },
+  block: {
+    type: Object,
+    default: () => ({}),
+  },
 });
 const emit = defineEmits(['change']);
 
@@ -52,7 +56,7 @@ const supportedDebugBlocks = [
 ];
 const browserType = BROWSER_TYPE;
 const isDebugSupported =
-  browserType !== 'firefox' && supportedDebugBlocks.includes(props.data.id);
+  browserType !== 'firefox' && supportedDebugBlocks.includes(props.block.id);
 
 const { t } = useI18n();
 const state = reactive({ blockTimeout: 0 });

+ 1 - 0
src/components/newtab/workflow/edit/EditBlockSettings.vue

@@ -8,6 +8,7 @@
     <ui-tab-panel value="general">
       <block-setting-general
         v-model:data="state.settings"
+        :block="data"
         @change="onDataChange('settings', $event)"
       />
     </ui-tab-panel>

+ 2 - 1
src/components/newtab/workflow/edit/Parameter/ParameterInputValue.vue

@@ -6,6 +6,7 @@
     class="w-full"
     :placeholder="paramData.placeholder"
     @change="$emit('update:modelValue', $event)"
+    @keyup.enter="$emit('execute')"
   />
 </template>
 <script setup>
@@ -21,7 +22,7 @@ const props = defineProps({
     default: () => ({}),
   },
 });
-defineEmits(['update:modelValue']);
+defineEmits(['update:modelValue', 'execute']);
 
 const mask = computed(() => {
   const options = props.paramData.data;

+ 2 - 2
src/locales/zh/common.json

@@ -54,7 +54,7 @@
     "notSaved": "你真的要退出吗? 你有未保存的更改!",
     "somethingWrong": "出现错误",
     "limitExceeded": "您已超出限制"
-   },
+  },
   "sort": {
     "sortBy": "排序方式",
     "name": "名称",
@@ -64,5 +64,5 @@
     "stopped": "停止",
     "error": "错误",
     "success": "成功"
-  },
+  }
 }

+ 1 - 1
src/locales/zh/newtab.json

@@ -20,7 +20,7 @@
     },
     "categories": {
       "my": "我的包",
-      "installed": "已安装的包",
+      "installed": "已安装的包"
     }
   },
   "scheduledWorkflow": {

+ 3 - 3
src/locales/zh/popup.json

@@ -13,7 +13,7 @@
       "tabs": {
         "new": "新建模块",
         "existing": "已存在工作流"
-	    }
+      }
     },
     "elementSelector": {
       "name": "元素选择器",
@@ -25,8 +25,8 @@
       "delete": "删除工作流",
       "type": {
         "host": "主机",
-        "local": "本地",
+        "local": "本地"
       }
-    },
+    }
   }
 }

+ 23 - 11
src/newtab/App.vue

@@ -57,9 +57,9 @@
   <app-survey />
 </template>
 <script setup>
-import { ref, reactive } from 'vue';
+import { ref, reactive, watch } from 'vue';
 import { useI18n } from 'vue-i18n';
-import { useRouter } from 'vue-router';
+import { useRouter, useRoute } from 'vue-router';
 import { compare } from 'compare-versions';
 import { useHead } from '@vueuse/head';
 import browser from 'webextension-polyfill';
@@ -89,19 +89,16 @@ import iconFirefox from '@/assets/svg/logoFirefox.svg';
 import iconChrome from '@/assets/svg/logo.svg';
 import SharedPermissionsModal from '@/components/newtab/shared/SharedPermissionsModal.vue';
 
-let icon;
-if (window.location.protocol === 'moz-extension:') {
-  icon = iconFirefox;
-} else {
-  icon = iconChrome;
-}
-
 const iconElement = document.createElement('link');
 iconElement.rel = 'icon';
-iconElement.href = icon;
+iconElement.href =
+  window.location.protocol === 'moz-extension' ? iconFirefox : iconChrome;
 document.head.appendChild(iconElement);
 
+window.fromBackground = window.location.href.includes('?fromBackground=true');
+
 const { t } = useI18n();
+const route = useRoute();
 const store = useStore();
 const theme = useTheme();
 const router = useRouter();
@@ -255,7 +252,8 @@ browser.runtime.onMessage.addListener(({ type, data }) => {
 browser.storage.local.onChanged.addListener(({ workflowStates }) => {
   if (!workflowStates) return;
 
-  workflowStore.states = Object.values(workflowStates.newValue);
+  const states = Object.values(workflowStates.newValue);
+  workflowStore.states = states;
 });
 
 useHead(() => {
@@ -301,6 +299,20 @@ window.addEventListener('message', ({ data }) => {
     });
 });
 
+watch(
+  () => workflowStore.popupStates,
+  () => {
+    if (
+      !window.fromBackground ||
+      workflowStore.popupStates.length !== 0 ||
+      route.name !== 'workflows'
+    )
+      return;
+
+    window.close();
+  }
+);
+
 (async () => {
   try {
     workflowState.storage = {

+ 14 - 0
src/params/App.vue

@@ -53,9 +53,15 @@
                 :is="paramsList[param.type].valueComp"
                 v-if="paramsList[param.type]"
                 v-model="param.value"
+                :autofocus="paramIdx === 0"
                 :label="param.name + (param.data?.required ? '*' : '')"
                 :param-data="param"
                 class="w-full"
+                @execute="
+                  workflow.type === 'block'
+                    ? continueWorkflow(index, workflow)
+                    : runWorkflow(index, workflow)
+                "
               />
               <ui-input
                 v-else
@@ -228,6 +234,10 @@ function getParamsValues(params) {
   }, {});
 }
 function runWorkflow(index, { data, params }) {
+  /* eslint-disable-next-line */
+  const isParamsValid = isValidParams(params);
+  if (!isParamsValid) return;
+
   const variables = getParamsValues(params);
   let payload = {
     name: 'background--workflow:execute',
@@ -264,6 +274,10 @@ function cancelParamBlock(index, { data }, message) {
     });
 }
 function continueWorkflow(index, { data, params }) {
+  /* eslint-disable-next-line */
+  const isParamsValid = isValidParams(params);
+  if (!isParamsValid) return;
+
   const timeout = Date.now() > data.timeout;
 
   browser.storage.local

+ 12 - 0
src/utils/FindElement.js

@@ -1,9 +1,21 @@
+import Sizzle from 'sizzle';
+
+const specialSelectors = [':contains', ':header', ':parent'];
+const specialSelectorsRegex = new RegExp(specialSelectors.join('|'));
+
 class FindElement {
   static cssSelector(data, documentCtx = document) {
     const selector = data.markEl
       ? `${data.selector.trim()}:not([${data.blockIdAttr}])`
       : data.selector;
 
+    if (specialSelectorsRegex.test(selector)) {
+      const elements = Sizzle.matches(selector);
+      if (!elements) return null;
+
+      return data.multiple ? elements : elements[0];
+    }
+
     if (data.multiple) {
       const elements = documentCtx.querySelectorAll(selector);
 

+ 2 - 0
src/workflowEngine/index.js

@@ -160,6 +160,8 @@ export function executeWorkflow(workflowData, options) {
     return;
   }
 
+  if (window) window.fromBackground = false;
+
   browser.tabs
     .query({ active: true, currentWindow: true })
     .then(async ([tab]) => {

+ 30 - 5
src/workflowEngine/utils/webhookUtil.js

@@ -1,6 +1,7 @@
 import { parseJSON, isWhitespace } from '@/utils/helper';
+import getFile from '@/utils/getFile';
 
-const renderContent = (content, contentType) => {
+const renderContent = async (content, contentType) => {
   if (contentType === 'text/plain') return content;
 
   const renderedJson = parseJSON(content, new Error('invalid-body'));
@@ -16,9 +17,33 @@ const renderContent = (content, contentType) => {
     }
 
     const formData = new FormData();
-    renderedJson.forEach((data) => {
-      formData.append(...data);
-    });
+    for (const data of renderedJson) {
+      const [name, path, customFilename] = data;
+      const isFile = /\.(.*)/.test(path) && BROWSER_TYPE !== 'firefox';
+      const isURL = path.startsWith('http');
+
+      let formContent = path;
+      let filename = customFilename;
+
+      if (isFile || isURL) {
+        formContent = await getFile(path, { returnValue: true });
+
+        if (!filename) {
+          const { pathname } = new URL(path);
+          filename = pathname.split('/').pop();
+        }
+      } else if (path.includes('base64')) {
+        const response = await fetch(path);
+        const result = await response.blob();
+
+        formContent = result;
+      }
+
+      const args = [name, formContent];
+      if (filename) args.push(filename);
+
+      formData.append(...args);
+    }
 
     return formData;
   }
@@ -74,7 +99,7 @@ export async function executeWebhook({
     };
 
     if (!notHaveBody.includes(method || 'POST') && !isWhitespace(body)) {
-      payload.body = renderContent(body, payload.headers['Content-Type']);
+      payload.body = await renderContent(body, payload.headers['Content-Type']);
     }
 
     const response = await fetch(url, payload);

Plik diff jest za duży
+ 317 - 461
yarn.lock


Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików