viewsource

View and beauty website source code. Support to view the source code by holding the right mouse and drag. Shortcut: Alt+U.

目前為 2018-05-16 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name viewsource
  3. // @namespace devs.forumvi.com
  4. // @description View and beauty website source code. Support to view the source code by holding the right mouse and drag. Shortcut: Alt+U.
  5. // @version 2.6.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. // @resource light https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/tomorrow.min.css
  13. // @resource dark https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/tomorrow-night.min.css
  14. // @require https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.7.5/beautify-html.min.js
  15. // @require https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.7.5/beautify.min.js
  16. // @require https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.7.5/beautify-css.min.js
  17. // @require https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js
  18. // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js?v=a834d46
  19. // @noframes
  20. // @connect self
  21. // @supportURL https://github.com/lelinhtinh/Userscript/issues
  22. // @run-at document-idle
  23. // @grant GM.getResourceUrl
  24. // @grant GM.xmlHttpRequest
  25. // ==/UserScript==
  26.  
  27. /* global html_beautify, hljs */
  28. (function () {
  29.  
  30. 'use strict';
  31.  
  32. var theme = 'dark', // light|dark
  33. lineColor = {
  34. light: ['#a7a7a7', '#e8e8e7'],
  35. dark: ['#4d4d4d', '#3a3a3a']
  36. },
  37. bgColor = {
  38. light: '#ffffff',
  39. dark: '#1d1f21'
  40. },
  41. linkColor = {
  42. light: ['#718c00', '#556416'],
  43. dark: ['#b5bd68', '#8b9433']
  44. },
  45.  
  46. win = window,
  47. urlpage = location.href,
  48. doc = document,
  49. wrapcontent = doc.documentElement,
  50. content = doc.body;
  51.  
  52. function scrollByDragging(container, disableH, disableV) {
  53.  
  54. function mouseUp(e) {
  55. if (e.which !== 3) return;
  56.  
  57. window.removeEventListener('mousemove', mouseMove, true);
  58. container.style.cursor = 'default';
  59. }
  60.  
  61. function mouseDown(e) {
  62. if (e.which !== 3) return;
  63.  
  64. pos = {
  65. x: e.clientX,
  66. y: e.clientY
  67. };
  68.  
  69. window.addEventListener('mousemove', mouseMove, true);
  70. container.style.cursor = 'move';
  71. }
  72.  
  73. function mouseMove(e) {
  74. if (!disableH) container.scrollLeft -= (-pos.x + (pos.x = e.clientX));
  75. if (!disableV) container.scrollTop -= (-pos.y + (pos.y = e.clientY));
  76. }
  77.  
  78. var pos = {
  79. x: 0,
  80. y: 0
  81. };
  82.  
  83. container.oncontextmenu = function (e) {
  84. e.preventDefault();
  85. };
  86.  
  87. container.addEventListener('mousedown', mouseDown, false);
  88. window.addEventListener('mouseup', mouseUp, false);
  89.  
  90. }
  91.  
  92. function removeEvents(ele, attr) {
  93. var events = 'onafterprint onbeforeprint onbeforeunload onerror onhashchange onload onmessage onoffline ononline onpagehide onpageshow onpopstate onresize onstorage onunload onblur onchange oncontextmenu onfocus oninput oninvalid onreset onsearch onselect onsubmit onkeydown onkeypress onkeyup onclick ondblclick ondrag ondragend ondragenter ondragleave ondragover ondragstart ondrop onmousedown onmousemove onmouseout onmouseover onmouseup onmousewheel onscroll onwheel oncopy oncut onpaste onerror onshow ontoggle'.split(' '),
  94. x;
  95. for (x in events) {
  96. var _event = events[x];
  97. ele[_event] = null;
  98. if (attr) {
  99. ele.removeAttribute(_event);
  100. }
  101. }
  102. }
  103.  
  104. function viewsource() {
  105. GM.xmlHttpRequest({
  106. method: 'GET',
  107. url: urlpage,
  108. onload: function (response) {
  109.  
  110. removeEvents(win);
  111. removeEvents(doc);
  112. removeEvents(wrapcontent, true);
  113. removeEvents(content, true);
  114.  
  115. var txt = html_beautify(response.response);
  116.  
  117. doc.head.innerHTML = '';
  118. content.innerHTML = '';
  119. content.removeAttribute('id');
  120. content.removeAttribute('class');
  121. content.removeAttribute('style');
  122. doc.title = 'view-source:' + urlpage;
  123.  
  124. GM_getResourceText(theme).then(function (res) {
  125. GM_addStyle(res + 'html,body,pre{margin:0;padding:0;background:' + bgColor[theme] + '}.hljs{word-wrap:normal!important;white-space:pre!important;padding-left:4em;line-height:100%}.hljs::before{content:attr(data-lines);position:absolute;color:' + lineColor[theme][0] + ';text-align:right;width:3.5em;left:-.5em;border-right:1px solid ' + lineColor[theme][1] + ';padding-right:.5em}a{color:' + linkColor[theme][0] + '}a:active,a:hover,a:visited{color:' + linkColor[theme][1] + '}');
  126. });
  127.  
  128. var output = doc.createElement('PRE');
  129. output.setAttribute('class', 'xml');
  130. output.textContent = txt;
  131.  
  132. content.appendChild(output);
  133.  
  134. hljs.highlightBlock(output);
  135.  
  136. var lines = txt.split('\n'),
  137. l = '';
  138. lines = lines ? lines.length : 0;
  139. for (var i = 0; i < lines; i++) {
  140. l += (i + 1) + '\n';
  141. }
  142.  
  143. output.setAttribute('data-lines', l);
  144. output.style.width = output.scrollWidth + 'px';
  145.  
  146. scrollByDragging(content);
  147. scrollByDragging(wrapcontent);
  148.  
  149. var attrUrl = doc.getElementsByClassName('hljs-attr');
  150. for (var j = 0; j < attrUrl.length; j++) {
  151. if (/\b(src|href\b)/.test(attrUrl[j].textContent)) {
  152. var link = attrUrl[j].nextSibling.nextSibling,
  153. url = link.textContent,
  154. quote = url.slice(0, 1);
  155.  
  156. if (quote !== '\'' && quote !== '"') {
  157. quote = '';
  158. } else {
  159. url = url.slice(1, -1);
  160. }
  161.  
  162. link.innerHTML = quote + '<a href="' + url + '" target="_blank">' + url + '</a>' + quote;
  163. }
  164. }
  165.  
  166. }
  167. });
  168. }
  169.  
  170. GM_registerMenuCommand('Beautify Page Source', viewsource, 'u');
  171.  
  172. if (/^application\/(xhtml+xml|xml|rss+xml)|text\/(html|xml)$/.test(doc.contentType)) {
  173. doc.onkeydown = function (e) {
  174.  
  175. // Alt+U
  176. if (e.which === 85 && e.altKey) {
  177. e.preventDefault();
  178.  
  179. viewsource();
  180. }
  181. };
  182. }
  183.  
  184. }());