viewsource

View and beautify page source. Shortcut: Alt+U.

当前为 2018-05-19 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name viewsource
  3. // @namespace devs.forumvi.com
  4. // @description View and beautify page source. Shortcut: Alt+U.
  5. // @version 3.0.0
  6. // @icon http://i.imgur.com/6yZMOeH.png
  7. // @author Zzbaivong
  8. // @oujs:author baivong
  9. // @license MIT; https://baivong.mit-license.org/license.txt
  10. // @match http://*/*
  11. // @match https://*/*
  12. // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js?v=a834d46
  13. // @noframes
  14. // @connect *
  15. // @supportURL https://github.com/lelinhtinh/Userscript/issues
  16. // @run-at document-idle
  17. // @grant GM.xmlHttpRequest
  18. // @grant GM_xmlhttpRequest
  19. // @grant GM.openInTab
  20. // @grant GM_openInTab
  21. // @grant GM_registerMenuCommand
  22. // ==/UserScript==
  23.  
  24. /* global importScripts */
  25. (function () {
  26. 'use strict';
  27.  
  28. var doc = document,
  29. urlpage = location.href,
  30. urlbeautify = 'https://lelinhtinh.github.io/Userscript/?beautify-source=';
  31.  
  32. if (!/^application\/(xhtml+xml|xml|rss+xml)|text\/(html|xml)$/.test(doc.contentType)) return;
  33.  
  34. if (urlpage.indexOf(urlbeautify) !== 0) {
  35. var viewsource = function () {
  36. if (urlpage.indexOf(urlbeautify) === 0) return;
  37. GM.openInTab(urlbeautify + encodeURIComponent(urlpage), false);
  38. };
  39.  
  40. GM_registerMenuCommand('Beautify Page Source', viewsource, 'u');
  41. doc.onkeydown = function (e) {
  42. if (e.which === 85 && e.altKey) { // Alt+U
  43. e.preventDefault();
  44. viewsource();
  45. }
  46. };
  47.  
  48. return;
  49. }
  50.  
  51. urlbeautify = urlpage.replace(urlbeautify, '');
  52. urlbeautify = decodeURIComponent(urlbeautify);
  53.  
  54. var blobURL, worker,
  55.  
  56. addstyle = function (aCss) {
  57. var head = doc.getElementsByTagName('head')[0];
  58. if (!head) return null;
  59. var style = doc.createElement('style');
  60. style.setAttribute('type', 'text/css');
  61. style.textContent = aCss;
  62. head.appendChild(style);
  63. return style;
  64. };
  65.  
  66. blobURL = URL.createObjectURL(new Blob(['(',
  67. function () {
  68. self.window = {};
  69.  
  70. self.onmessage = function (e) {
  71. var source = e.data.content;
  72.  
  73. importScripts('https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.7.5/beautify-html.min.js');
  74. source = self.window.html_beautify(source);
  75.  
  76. self.postMessage({
  77. action: 'beautify',
  78. source: source
  79. });
  80.  
  81. importScripts('https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js');
  82. source = self.window.hljs.highlight('xml', source, true).value;
  83.  
  84. source = source.split('\n');
  85. source = source.join('</code><code>');
  86. source = '<code>' + source + '</code>';
  87.  
  88. self.postMessage({
  89. action: 'hljs',
  90. source: source
  91. });
  92. };
  93.  
  94. }.toString(),
  95. ')()'
  96. ], {
  97. type: 'text/javascript'
  98. }));
  99. worker = new Worker(blobURL);
  100.  
  101. worker.onmessage = function (e) {
  102. if (!e.data) return;
  103. var fragment = doc.createDocumentFragment(),
  104. pre = doc.createElement('pre');
  105.  
  106. if (e.data.action === 'beautify') {
  107. addstyle('*{margin:0;padding:0}html{line-height:1em;background:#1d1f21;color:#c5c8c6}pre{counter-reset:line-numbers;white-space:pre-wrap}code::before{counter-increment:line-numbers;content:counter(line-numbers);display:block;position:absolute;left:-4.5em;top:0;width:4em;text-align:right;color:#60686f;white-space:pre}code{display:block;position:relative;margin-left:4em;padding-left:.5em;min-height:1em;border-left:1px solid #32363b}pre{padding:.5em .5em .5em 5em;border-left:1px solid #1d1f21}pre.hljs{padding-left:.5em;border-left:0 none}code::after{content:".";visibility:hidden}a{color:#b5bd68}a:active,a:hover,a:visited{color:#8b9433} .hljs-comment,.hljs-quote{color:#969896}.hljs-variable,.hljs-template-variable,.hljs-tag,.hljs-name,.hljs-selector-id,.hljs-selector-class,.hljs-regexp,.hljs-deletion{color:#c66}.hljs-number,.hljs-built_in,.hljs-builtin-name,.hljs-literal,.hljs-type,.hljs-params,.hljs-meta,.hljs-link{color:#de935f}.hljs-attribute{color:#f0c674}.hljs-string,.hljs-symbol,.hljs-bullet,.hljs-addition{color:#b5bd68}.hljs-title,.hljs-section{color:#81a2be}.hljs-keyword,.hljs-selector-tag{color:#b294bb}.hljs{display:block;overflow-x:auto;background:#1d1f21;color:#c5c8c6;padding:.5em}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}');
  108.  
  109. pre.textContent = e.data.source;
  110. fragment.appendChild(pre);
  111. doc.body.appendChild(fragment);
  112. } else {
  113. pre.innerHTML = e.data.source;
  114. pre.className = 'hljs xml';
  115. fragment.appendChild(pre);
  116. doc.body.replaceChild(fragment, doc.getElementsByTagName('pre')[0]);
  117.  
  118. var attrUrl = doc.getElementsByClassName('hljs-attr');
  119. for (var j = 0; j < attrUrl.length; j++) {
  120. if (/\b(src|href\b)/.test(attrUrl[j].textContent)) {
  121. var link = attrUrl[j].nextSibling.nextSibling,
  122. url = link.textContent,
  123. quote = url.slice(0, 1);
  124.  
  125. if (quote !== '\'' && quote !== '"') {
  126. quote = '';
  127. } else {
  128. url = url.slice(1, -1);
  129. }
  130.  
  131. link.innerHTML = quote + '<a href="' + url + '" target="_blank">' + url + '</a>' + quote;
  132. }
  133. }
  134. }
  135. };
  136.  
  137. GM.xmlHttpRequest({
  138. method: 'GET',
  139. url: urlbeautify,
  140. onload: function (response) {
  141. doc.title = 'beautify-source:' + urlbeautify;
  142. worker.postMessage({
  143. content: response.response
  144. });
  145.  
  146. var baseUrl,
  147. baseMatch = response.response.match(/<base\s+href="([^"]+)"\s?[^>]*>/),
  148. base = doc.createElement('base');
  149.  
  150. baseUrl = baseMatch ? baseMatch[1] : urlbeautify.replace(/[^/]*$/, '');
  151.  
  152. base.href = baseUrl;
  153. doc.head.appendChild(base);
  154. }
  155. });
  156.  
  157. }());