content-script.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. window.codebeautifyContentScript = (() => {
  2. let __importScript = (filename) => {
  3. let url = filename;
  4. if (location.protocol === 'chrome-extension:' || chrome.runtime && chrome.runtime.getURL) {
  5. url = chrome.runtime.getURL('code-beautify/' + filename);
  6. }
  7. // 使用chrome.runtime.sendMessage向background请求加载脚本
  8. chrome.runtime.sendMessage({
  9. type: 'fh-dynamic-any-thing',
  10. thing: 'load-local-script',
  11. script: url
  12. }, (scriptContent) => {
  13. if (!scriptContent) {
  14. console.error('Failed to load script:', filename);
  15. return;
  16. }
  17. // 如果有evalCore则使用它
  18. if (window.evalCore && window.evalCore.getEvalInstance) {
  19. try {
  20. window.evalCore.getEvalInstance(window)(scriptContent);
  21. } catch(e) {
  22. console.error('Failed to evaluate script using evalCore:', e);
  23. }
  24. } else {
  25. // 创建一个函数来执行脚本
  26. try {
  27. // 使用Function构造函数创建一个函数,并在当前窗口上下文中执行
  28. // 这比动态创建script元素更安全,因为它不涉及DOM操作
  29. const executeScript = new Function(scriptContent);
  30. executeScript.call(window);
  31. } catch(e) {
  32. console.error('Failed to execute script:', filename, e);
  33. }
  34. }
  35. });
  36. };
  37. __importScript('beautify.js');
  38. __importScript('beautify-css.js');
  39. let highlightWebWorker = () => {
  40. // TODO ...
  41. // __importScript('../static/vendor/highlight/highlight.js');
  42. self.onmessage = (event) => {
  43. // const result = self.hljs.highlightAuto(event.data);
  44. // postMessage(result.value);
  45. postMessage(event.data);
  46. };
  47. };
  48. let formattedCodes = '';
  49. let cssInjected = false;
  50. // **************************************************************
  51. /**
  52. * 代码美化
  53. */
  54. let format = (fileType, source, callback) => {
  55. let beauty = txtResult => {
  56. let code = document.getElementsByTagName('pre')[0];
  57. formattedCodes = txtResult;
  58. code.textContent = txtResult;
  59. code.classList.add('language-' + fileType.toLowerCase());
  60. document.querySelector('html').classList.add('jf-cb');
  61. // 用webwork的方式来进行格式化,效率更高
  62. let worker = new Worker(URL.createObjectURL(new Blob(["(" + highlightWebWorker.toString() + ")()"], {type: 'text/javascript'})));
  63. worker.onmessage = (event) => {
  64. code.innerHTML = "<ol><li><span>" + event.data
  65. .replace(/</gm,'&lt;').replace(/>/gm,'&gt;')
  66. .replace(/\n/gm, '</span></li><li><span>') + '</span></li></ol>';
  67. callback && callback();
  68. };
  69. worker.postMessage(txtResult);
  70. };
  71. switch (fileType) {
  72. case 'javascript':
  73. let opts = {
  74. brace_style: "collapse",
  75. break_chained_methods: false,
  76. indent_char: " ",
  77. indent_scripts: "keep",
  78. indent_size: "4",
  79. keep_array_indentation: true,
  80. preserve_newlines: true,
  81. space_after_anon_function: true,
  82. space_before_conditional: true,
  83. unescape_strings: false,
  84. wrap_line_length: "120"
  85. };
  86. beauty(js_beautify(source, opts));
  87. break;
  88. case 'css':
  89. css_beautify(source, {}, resp => beauty(resp));
  90. break;
  91. }
  92. };
  93. /**
  94. * 检测
  95. * @returns {boolean}
  96. */
  97. window._codebutifydetect_ = (fileType) => {
  98. if (!document.getElementsByTagName('pre')[0]) {
  99. return;
  100. }
  101. let source = document.getElementsByTagName('pre')[0].textContent;
  102. // 提前注入css
  103. if(!cssInjected) {
  104. chrome.runtime.sendMessage({
  105. type: 'fh-dynamic-any-thing',
  106. thing:'inject-content-css',
  107. tool: 'code-beautify'
  108. });
  109. }
  110. $(document.body).addClass('show-tipsbar');
  111. let tipsBar = $('<div id="fehelper_tips">' +
  112. '<span class="desc">FeHelper检测到这可能是<i>' + fileType + '</i>代码,<span class="ask">是否进行美化处理?</span></span>' +
  113. '<a class="encoding">有乱码?点击修正!</a>' +
  114. '<button class="yes">代码美化</button>' +
  115. '<button class="no">放弃!</button>' +
  116. '<button class="copy hide">复制美化过的代码</button>' +
  117. '<button class="close"><span></span></button>' +
  118. '<a class="forbid">彻底关闭这个功能!&gt;&gt;</a>' +
  119. '</div>').prependTo('body');
  120. tipsBar.find('button.yes').click((evt) => {
  121. tipsBar.find('button.yes,button.no').hide();
  122. let elAsk = tipsBar.find('span.ask').text('正在努力美化,请稍候...');
  123. format(fileType, source, () => {
  124. elAsk.text('已为您美化完毕!');
  125. $(document.body).removeClass('show-tipsbar').addClass('show-beautified');
  126. });
  127. });
  128. tipsBar.find('a.forbid').click((evt) => {
  129. evt.preventDefault();
  130. if (confirm('一旦彻底关闭,不可恢复,请确认?')) {
  131. chrome.runtime.sendMessage({
  132. type: 'fh-dynamic-any-thing',
  133. thing: 'close-beautify'
  134. }, () => {
  135. alert('已关闭,如果要恢复,请在FeHelper「设置页」重新安装「代码美化工具」!');
  136. });
  137. }
  138. });
  139. tipsBar.find('button.no,button.close').click((evt) => {
  140. $(document.body).removeClass('show-tipsbar').removeClass('show-beautified');
  141. tipsBar.remove();
  142. });
  143. tipsBar.find('button.copy').click((evt) => {
  144. _copyToClipboard(formattedCodes);
  145. });
  146. tipsBar.find('a.encoding').click((evt) => {
  147. evt.preventDefault();
  148. fetch(location.href).then(res => res.text()).then(text => {
  149. source = text;
  150. if ($(document.body).hasClass('show-beautified')) {
  151. tipsBar.find('button.yes').trigger('click');
  152. } else {
  153. $('#fehelper_tips+pre').text(text);
  154. }
  155. });
  156. });
  157. };
  158. /**
  159. * chrome 下复制到剪贴板
  160. * @param text
  161. */
  162. let _copyToClipboard = function (text) {
  163. let input = document.createElement('textarea');
  164. input.style.position = 'fixed';
  165. input.style.opacity = 0;
  166. input.value = text;
  167. document.body.appendChild(input);
  168. input.select();
  169. document.execCommand('Copy');
  170. document.body.removeChild(input);
  171. alert('代码复制成功,随处粘贴可用!')
  172. };
  173. return function () {
  174. let ext = location.pathname.substring(location.pathname.lastIndexOf(".") + 1).toLowerCase();
  175. let fileType = ({'js': 'javascript', 'css': 'css'})[ext];
  176. let contentType = document.contentType.toLowerCase();
  177. if (!fileType) {
  178. if (/\/javascript$/.test(contentType)) {
  179. fileType = 'javascript';
  180. } else if (/\/css$/.test(contentType)) {
  181. fileType = 'css';
  182. }
  183. } else if (contentType === 'text/html') {
  184. fileType = undefined;
  185. }
  186. if (['javascript', 'css'].includes(fileType)) {
  187. chrome.runtime.sendMessage({
  188. type: 'fh-dynamic-any-thing',
  189. thing: 'code-beautify',
  190. params: { fileType, tabId: window.__FH_TAB_ID__ || null }
  191. });
  192. }
  193. };
  194. })();