viewsource

Viewsource for Firefox, like Chrome

As of 2016-03-15. See the latest version.

  1. // ==UserScript==
  2. // @name viewsource
  3. // @namespace devs.forumvi.com
  4. // @description Viewsource for Firefox, like Chrome
  5. // @version 2.3.2
  6. // @author Zzbaivong
  7. // @resource light https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.2.0/styles/github-gist.min.css
  8. // @resource dark https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.2.0/styles/monokai-sublime.min.css
  9. // @require https://openuserjs.org/src/libs/baivong/beautify-html.js
  10. // @require https://openuserjs.org/src/libs/baivong/beautify-js.min.js
  11. // @require https://openuserjs.org/src/libs/baivong/beautify-css.min.js
  12. // @require https://openuserjs.org/src/libs/baivong/highlight-xml.js
  13. // @run-at doc-end
  14. // @grant GM_addStyle
  15. // @grant GM_getResourceText
  16. // @grant GM_xmlhttpRequest
  17. // @grant GM_registerMenuCommand
  18. // ==/UserScript==
  19.  
  20. (function () {
  21.  
  22. 'use strict';
  23.  
  24. var theme = 'light', // light|dark
  25.  
  26. win = window,
  27. urlpage = win.top.location.href,
  28. doc = document,
  29. wrapcontent = doc.documentElement,
  30. content = doc.body;
  31.  
  32. function scrollByDragging(container, disableH, disableV) {
  33.  
  34. function mouseUp(e) {
  35. if (e.which !== 3) return;
  36.  
  37. window.removeEventListener('mousemove', mouseMove, true);
  38. container.style.cursor = 'default';
  39. }
  40.  
  41. function mouseDown(e) {
  42. if (e.which !== 3) return;
  43.  
  44. pos = {
  45. x: e.clientX,
  46. y: e.clientY
  47. };
  48.  
  49. window.addEventListener('mousemove', mouseMove, true);
  50. container.style.cursor = 'move';
  51. }
  52.  
  53. function mouseMove(e) {
  54. if (!disableH) container.scrollLeft -= (-pos.x + (pos.x = e.clientX));
  55. if (!disableV) container.scrollTop -= (-pos.y + (pos.y = e.clientY));
  56. }
  57.  
  58. var pos = {
  59. x: 0,
  60. y: 0
  61. };
  62.  
  63. container.oncontextmenu = function (e) {
  64. e.preventDefault();
  65. };
  66.  
  67. container.addEventListener('mousedown', mouseDown, false);
  68. window.addEventListener('mouseup', mouseUp, false);
  69.  
  70. }
  71.  
  72. function removeEvents(ele, attr) {
  73. 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(' '),
  74. x;
  75. for (x in events) {
  76. var _event = events[x];
  77. ele[_event] = null;
  78. if (attr) {
  79. ele.removeAttribute(_event);
  80. }
  81. }
  82. }
  83.  
  84. function viewsource() {
  85. GM_xmlhttpRequest({
  86. method: 'GET',
  87. url: urlpage,
  88. onload: function (response) {
  89.  
  90. removeEvents(win);
  91. removeEvents(doc);
  92. removeEvents(wrapcontent, true);
  93. removeEvents(content, true);
  94.  
  95. var txt = html_beautify(response.response);
  96.  
  97. doc.head.innerHTML = '';
  98. content.innerHTML = '';
  99. content.removeAttribute('id');
  100. content.removeAttribute('class');
  101. content.removeAttribute('style');
  102. doc.title = 'view-source:' + urlpage;
  103.  
  104. GM_addStyle(GM_getResourceText(theme) + 'html,body,pre{margin:0;padding:0}.hljs{overflow:hidden;word-wrap:normal!important;white-space:pre!important;padding-left:4em;line-height:100%}.hljs::before{content:attr(data-lines);position:absolute;color:#d2d2d2;text-align:right;width:3.5em;left:-.5em;border-right:1px solid rgba(221, 221, 221, 0.36);padding-right:.5em}');
  105.  
  106. var output = doc.createElement('PRE');
  107. output.setAttribute('class', 'xml');
  108. output.textContent = txt;
  109.  
  110. content.appendChild(output);
  111.  
  112. hljs.highlightBlock(output);
  113.  
  114. var lines = txt.split('\n'),
  115. l = '';
  116. lines = lines ? lines.length : 0;
  117. for (var i = 0; i < lines; i++) {
  118. l += (i + 1) + '\n';
  119. }
  120.  
  121. output.setAttribute('data-lines', l);
  122. //output.style.width = output.scrollWidth + 'px';
  123.  
  124. scrollByDragging(output, false, true);
  125. scrollByDragging(content, true);
  126. scrollByDragging(wrapcontent, true);
  127.  
  128. var attrUrl = doc.getElementsByClassName('hljs-attr');
  129. for (var j = 0; j < attrUrl.length; j++) {
  130. if (/\b(src|href\b)/.test(attrUrl[j].textContent)) {
  131. var link = attrUrl[j].nextSibling.nextSibling;
  132. var url = link.textContent.slice(1, -1);
  133. link.innerHTML = '<a href="' + url + '" target="_blank">' + url + '</a>';
  134. }
  135. }
  136.  
  137. }
  138. });
  139. }
  140.  
  141. GM_registerMenuCommand('View source', viewsource, 'm');
  142.  
  143. if (doc.contentType === 'text/html' && doc.URL === urlpage) {
  144. win.onkeydown = function (e) {
  145.  
  146. // Ctrl + M
  147. if (e.which === 77 && e.ctrlKey) {
  148. e.preventDefault();
  149.  
  150. viewsource();
  151. }
  152. };
  153. }
  154. }());