handler-javascript-code.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import { sendMessage } from '@/utils/message';
  2. function getAutomaScript(blockId, everyNewTab) {
  3. const str = `
  4. function automaSetVariable(name, value) {
  5. const data = JSON.parse(sessionStorage.getItem('automa--${blockId}')) || null;
  6. if (data === null) return null;
  7. data.variables[name] = value;
  8. sessionStorage.setItem('automa--${blockId}', JSON.stringify(data));
  9. }
  10. function automaNextBlock(data, insert = true) {
  11. window.dispatchEvent(new CustomEvent('__automa-next-block__', { detail: { data, insert } }));
  12. }
  13. function automaResetTimeout() {
  14. window.dispatchEvent(new CustomEvent('__automa-reset-timeout__'));
  15. }
  16. function findData(obj, path) {
  17. const paths = path.split('.');
  18. const isWhitespace = paths.length === 1 && !/\\S/.test(paths[0]);
  19. if (paths.length === 0 || isWhitespace) return obj;
  20. else if (paths.length === 1) return obj[paths[0]];
  21. let result = obj;
  22. for (let i = 0; i < paths.length; i++) {
  23. if (result[paths[i]] == undefined) {
  24. return undefined;
  25. } else {
  26. result = result[paths[i]];
  27. }
  28. }
  29. return result;
  30. }
  31. function automaRefData(keyword, path = '') {
  32. const data = JSON.parse(sessionStorage.getItem('automa--${blockId}')) || null;
  33. if (data === null) return null;
  34. return findData(data[keyword], path);
  35. }
  36. `;
  37. if (everyNewTab) return '';
  38. return str;
  39. }
  40. function javascriptCode(block) {
  41. if (!block.data.everyNewTab)
  42. sessionStorage.setItem(
  43. `automa--${block.id}`,
  44. JSON.stringify(block.refData)
  45. );
  46. const automaScript = getAutomaScript(block.id, block.data.everyNewTab);
  47. return new Promise((resolve, reject) => {
  48. let documentCtx = document;
  49. if (block.frameSelector) {
  50. const iframeCtx = document.querySelector(
  51. block.frameSelector
  52. )?.contentDocument;
  53. if (!iframeCtx) {
  54. reject(new Error('iframe-not-found'));
  55. return;
  56. }
  57. documentCtx = iframeCtx;
  58. }
  59. const scriptAttr = `block--${block.id}`;
  60. const isScriptExists = documentCtx.querySelector(
  61. `.automa-custom-js[${scriptAttr}]`
  62. );
  63. if (isScriptExists) {
  64. resolve('');
  65. return;
  66. }
  67. const promisePreloadScripts =
  68. block.data?.preloadScripts.map(async (item) => {
  69. try {
  70. const { protocol, pathname } = new URL(item.src);
  71. const isValidUrl = /https?/.test(protocol) && /\.js$/.test(pathname);
  72. if (!isValidUrl) return null;
  73. const script = await sendMessage(
  74. 'fetch:text',
  75. item.src,
  76. 'background'
  77. );
  78. const scriptEl = documentCtx.createElement('script');
  79. scriptEl.type = 'text/javascript';
  80. scriptEl.innerHTML = script;
  81. return {
  82. ...item,
  83. script: scriptEl,
  84. };
  85. } catch (error) {
  86. return null;
  87. }
  88. }) || [];
  89. Promise.allSettled(promisePreloadScripts).then((result) => {
  90. const preloadScripts = result.reduce((acc, { status, value }) => {
  91. if (status !== 'fulfilled' || !value) return acc;
  92. acc.push(value);
  93. documentCtx.body.appendChild(value.script);
  94. return acc;
  95. }, []);
  96. const script = document.createElement('script');
  97. script.setAttribute(scriptAttr, '');
  98. script.classList.add('automa-custom-js');
  99. script.innerHTML = `(() => {\n${automaScript} ${block.data.code}\n})()`;
  100. if (!block.data.everyNewTab) {
  101. let timeout;
  102. const cleanUp = (columns = '') => {
  103. const storageKey = `automa--${block.id}`;
  104. const storageRefData = JSON.parse(sessionStorage.getItem(storageKey));
  105. script.remove();
  106. preloadScripts.forEach((item) => {
  107. if (item.removeAfterExec) item.script.remove();
  108. });
  109. resolve({ columns, variables: storageRefData?.variables });
  110. };
  111. window.addEventListener('__automa-next-block__', ({ detail }) => {
  112. clearTimeout(timeout);
  113. cleanUp(detail || {});
  114. });
  115. window.addEventListener('__automa-reset-timeout__', () => {
  116. clearTimeout(timeout);
  117. timeout = setTimeout(cleanUp, block.data.timeout);
  118. });
  119. timeout = setTimeout(cleanUp, block.data.timeout);
  120. } else {
  121. resolve();
  122. }
  123. documentCtx.body.appendChild(script);
  124. });
  125. });
  126. }
  127. export default javascriptCode;