瀏覽代碼

feat: add automaRefData function in javascript block

Ahmad Kholid 3 年之前
父節點
當前提交
90fdc72265

+ 14 - 4
src/background/workflow-engine/blocks-handler.js

@@ -418,13 +418,23 @@ export async function switchTo(block) {
   }
 }
 
-export async function interactionHandler(block) {
+export async function interactionHandler(block, prevBlockData) {
   const nextBlockId = getBlockConnection(block);
 
   try {
-    const data = await this._sendMessageToTab(block, {
-      frameId: this.frameId || 0,
-    });
+    const refData = {
+      prevBlockData,
+      dataColumns: this.data,
+      loopData: this.loopData,
+      globalData: this.globalData,
+      activeTabUrl: this.activeTabUrl,
+    };
+    const data = await this._sendMessageToTab(
+      { ...block, refData },
+      {
+        frameId: this.frameId || 0,
+      }
+    );
 
     if (block.name === 'link')
       await new Promise((resolve) => setTimeout(resolve, 5000));

+ 2 - 2
src/background/workflow-engine/index.js

@@ -332,7 +332,7 @@ class WorkflowEngine {
     }
   }
 
-  _sendMessageToTab(block, options = {}) {
+  _sendMessageToTab(payload, options = {}) {
     return new Promise((resolve, reject) => {
       if (!this.tabId) {
         reject(new Error('no-tab'));
@@ -340,7 +340,7 @@ class WorkflowEngine {
       }
 
       browser.tabs
-        .sendMessage(this.tabId, { isBlock: true, ...block }, options)
+        .sendMessage(this.tabId, { isBlock: true, ...payload }, options)
         .then(resolve)
         .catch(reject);
     });

+ 23 - 0
src/components/newtab/workflow/edit/EditJavascriptCode.vue

@@ -35,6 +35,23 @@
         line-numbers
         style="height: calc(100vh - 12rem)"
       />
+      <p class="mt-1">
+        {{ t('workflow.blocks.javascript-code.availabeFuns') }}
+      </p>
+      <p class="space-x-1">
+        <a
+          v-for="func in availableFuncs"
+          :key="func.id"
+          :href="`https://github.com/Kholid060/automa/wiki/Blocks#${func.id}`"
+          target="_blank"
+          rel="noopener"
+          class="inline-block"
+        >
+          <code>
+            {{ func.name }}
+          </code>
+        </a>
+      </p>
     </ui-modal>
   </div>
 </template>
@@ -54,6 +71,12 @@ const emit = defineEmits(['update:data']);
 
 const { t } = useI18n();
 
+const availableFuncs = [
+  { name: 'automaNextBlock(data)', id: 'automanextblockdata' },
+  { name: 'automaRefData(keyword, path)', id: 'automarefdatakeyword-path' },
+  { name: 'automaResetTimeout', id: 'automaresettimeout' },
+];
+
 const code = ref(props.data.code);
 const showCodeModal = ref(false);
 

+ 44 - 13
src/content/blocks-handler.js

@@ -1,6 +1,7 @@
 /* eslint-disable consistent-return, no-param-reassign */
 import simulateEvent from '@/utils/simulate-event';
 import handleFormElement from '@/utils/handle-form-element';
+import { generateJSON } from '@/utils/data-exporter';
 
 function markElement(el, { id, data }) {
   if (data.markEl) {
@@ -91,16 +92,47 @@ export function getText(block) {
   });
 }
 
-const automaScript = `
+export function javascriptCode(block) {
+  block.refData.dataColumns = generateJSON(
+    Object.keys(block.refData.dataColumns),
+    block.refData.dataColumns
+  );
+
+  sessionStorage.setItem(`automa--${block.id}`, JSON.stringify(block.refData));
+  const automaScript = `
 function automaNextBlock(data) {
   window.dispatchEvent(new CustomEvent('__automa-next-block__', { detail: data }));
 }
 function automaResetTimeout() {
  window.dispatchEvent(new CustomEvent('__automa-reset-timeout__'));
 }
+function findData(obj, path) {
+  const paths = path.split('.');
+  const isWhitespace = paths.length === 1 && !/\\S/.test(paths[0]);
+
+  if (paths.length === 0 || isWhitespace) return obj;
+
+  let current = obj;
+
+  for (let i = 0; i < paths.length; i++) {
+    if (current[paths[i]] == undefined) {
+      return undefined;
+    } else {
+      current = current[paths[i]];
+    }
+  }
+
+  return current;
+}
+function automaRefData(keyword, path = '') {
+  const data = JSON.parse(sessionStorage.getItem('automa--${block.id}')) || null;
+
+  if (data === null) return null;
+
+  return findData(data[keyword], path);
+}
 `;
 
-export function javascriptCode(block) {
   return new Promise((resolve) => {
     const isScriptExists = document.getElementById('automa-custom-js');
     const scriptAttr = `block--${block.id}`;
@@ -115,28 +147,27 @@ export function javascriptCode(block) {
 
     script.setAttribute(scriptAttr, '');
     script.id = 'automa-custom-js';
-    script.innerHTML = `${automaScript} ${block.data.code}`;
+    script.innerHTML = `(() => {\n${automaScript} ${block.data.code}\n})()`;
+
+    const cleanUp = (data = '') => {
+      script.remove();
+      sessionStorage.removeItem(`automa--${block.id}`);
+      resolve(data);
+    };
 
     window.addEventListener('__automa-next-block__', ({ detail }) => {
       clearTimeout(timeout);
-      script.remove();
-      resolve(detail || {});
+      cleanUp(detail || {});
     });
     window.addEventListener('__automa-reset-timeout__', () => {
       clearTimeout(timeout);
 
-      timeout = setTimeout(() => {
-        script.remove();
-        resolve('');
-      }, block.data.timeout);
+      timeout = setTimeout(cleanUp, block.data.timeout);
     });
 
     document.body.appendChild(script);
 
-    timeout = setTimeout(() => {
-      script.remove();
-      resolve('');
-    }, block.data.timeout);
+    timeout = setTimeout(cleanUp, block.data.timeout);
   });
 }
 

+ 3 - 2
src/locales/en/blocks.json

@@ -166,11 +166,12 @@
       "javascript-code": {
         "name": "JavaScript code",
         "description": "Execute your javascript code in the web page",
+        "modal": "JavaScript code",
+        "availabeFuns": "Available functions:",
         "timeout": {
           "placeholder": "Timeout",
           "title": "Javascript code execution timeout"
-        },
-        "modal": "JavaScript code"
+        }
       },
       "trigger-event": {
         "name": "Trigger event",

+ 4 - 4
src/utils/reference-data.js

@@ -3,7 +3,7 @@ import { isObject, objectHasKey, replaceMustache } from '@/utils/helper';
 
 const objectPath = { get, set };
 
-function parseKey(key) {
+export function parseKey(key) {
   const [dataKey, path] = key.split('@');
 
   if (
@@ -13,7 +13,7 @@ function parseKey(key) {
   )
     return { dataKey, path: path || '' };
 
-  const pathArr = path?.split('.') ?? '';
+  const pathArr = path?.split('.') ?? [];
   let dataPath = '';
 
   if (pathArr.length === 1) {
@@ -37,10 +37,10 @@ function parseKey(key) {
 export default function (block, data) {
   const replaceKeys = [
     'url',
-    'fileName',
     'name',
-    'value',
     'body',
+    'value',
+    'fileName',
     'selector',
     'prefixText',
     'suffixText',