Expand Code to Fullscreen on StackExchange Site

Toggle fullscreen for code blocks on hover

当前为 2024-02-15 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Expand Code to Fullscreen on StackExchange Site
  3. // @namespace http://tampermonkey.net/
  4. // @author aspen138
  5. // @version 0.1.1
  6. // @description Toggle fullscreen for code blocks on hover
  7. // @match *://*.stackexchange.com/*
  8. // @match *://*.stackoverflow.com/questions/*
  9. // @match *://superuser.com/questions/*
  10. // @match *://meta.superuser.com/questions/*
  11. // @match *://serverfault.com/questions/*
  12. // @match *://meta.serverfault.com/questions/*
  13. // @match *://askubuntu.com/questions/*
  14. // @match *://meta.askubuntu.com/questions/*
  15. // @match *://mathoverflow.net/questions/*
  16. // @match *://meta.mathoverflow.net/questions/*
  17. // @match *://*.stackexchange.com/questions/*
  18. // @match *://answers.onstartups.com/questions/*
  19. // @match *://meta.answers.onstartups.com/questions/*
  20. // @match *://stackapps.com/questions/*
  21. // @match *://*.stackoverflow.com/review/*
  22. // @match *://superuser.com/review/*
  23. // @match *://meta.superuser.com/review/*
  24. // @match *://serverfault.com/review/*
  25. // @match *://meta.serverfault.com/review/*
  26. // @match *://askubuntu.com/review/*
  27. // @match *://meta.askubuntu.com/review/*
  28. // @match *://mathoverflow.net/review/*
  29. // @match *://meta.mathoverflow.net/review/*
  30. // @match *://*.stackexchange.com/review/*
  31. // @match *://answers.onstartups.com/review/*
  32. // @match *://meta.answers.onstartups.com/review/*
  33. // @match *://stackapps.com/review/*
  34. // @match *://*.stackoverflow.com/search*
  35. // @match *://superuser.com/search*
  36. // @match *://meta.superuser.com/search*
  37. // @match *://serverfault.com/search*
  38. // @match *://meta.serverfault.com/search*
  39. // @match *://askubuntu.com/search*
  40. // @match *://meta.askubuntu.com/search*
  41. // @match *://mathoverflow.net/search*
  42. // @match *://meta.mathoverflow.net/search*
  43. // @match *://*.stackexchange.com/search*
  44. // @match *://answers.onstartups.com/search*
  45. // @match *://meta.answers.onstartups.com/search*
  46. // @match *://stackapps.com/search*
  47. // @grant none
  48. // @license MIT
  49. // ==/UserScript==
  50.  
  51.  
  52. (function() {
  53. 'use strict';
  54.  
  55. // Function to inject styles
  56. function addStyles() {
  57. const style = document.createElement('style');
  58. style.type = 'text/css';
  59. style.innerHTML = `
  60. .code-wrapper {
  61. position: relative;
  62. }
  63. .fullscreen-btn {
  64. position: absolute;
  65. top: 0;
  66. right: 0;
  67. z-index: 10;
  68. padding: 4px 8px;
  69. background-color: #eee;
  70. border: none;
  71. cursor: pointer;
  72. border-radius: 4px;
  73. font-size: 12px;
  74. display: none;
  75. }
  76. .fullscreen-btn:hover {
  77. background-color: #ddd;
  78. }
  79. .code-wrapper:hover .fullscreen-btn {
  80. display: block;
  81. }
  82. /* Fullscreen specific styles */
  83. .code-wrapper.fullscreen {
  84. background: white; /* Change this to the desired background color */
  85. color: black; /* And this to the desired text color */
  86. width: 100%;
  87. height: 100%;
  88. overflow: auto; /* This allows scrolling */
  89. margin: 0;
  90. padding: 20px; /* Or however much padding you want */
  91. }
  92. /* Ensure syntax highlighting styles have enough specificity */
  93. .code-wrapper.fullscreen .hljs {
  94. display: block;
  95. overflow-x: auto;
  96. padding: 0.5em;
  97. color: inherit;
  98. background: inherit;
  99. }
  100. `;
  101. document.head.appendChild(style);
  102. }
  103.  
  104. // Function to toggle fullscreen for the specific code block
  105. function toggleFullScreen(codeWrapper) {
  106. if (!document.fullscreenElement && codeWrapper.requestFullscreen) {
  107. codeWrapper.requestFullscreen().then(() => {
  108. codeWrapper.classList.add('fullscreen');
  109. // Copy all classes from <code> to the wrapper
  110. codeWrapper.querySelector('code').classList.forEach(cls => {
  111. codeWrapper.classList.add(cls);
  112. });
  113. });
  114. } else if (document.fullscreenElement && document.exitFullscreen) {
  115. document.exitFullscreen().then(() => {
  116. codeWrapper.classList.remove('fullscreen');
  117. // Remove the copied classes from the wrapper
  118. codeWrapper.querySelector('code').classList.forEach(cls => {
  119. codeWrapper.classList.remove(cls);
  120. });
  121. });
  122. }
  123. }
  124.  
  125. // Function to create a fullscreen button for each code block
  126. function addFullscreenButtons() {
  127. document.querySelectorAll('pre code').forEach((code) => {
  128. // Check if the code block is already wrapped with the code-wrapper
  129. let wrapper = code.closest('.code-wrapper');
  130. if (!wrapper) {
  131. wrapper = document.createElement('div');
  132. wrapper.classList.add('code-wrapper');
  133. // Move the classes from <code> to the wrapper
  134. code.classList.forEach(cls => {
  135. if (cls !== 'hljs') { // Avoid moving the 'hljs' class
  136. wrapper.classList.add(cls);
  137. }
  138. });
  139. code.parentNode.insertBefore(wrapper, code);
  140. wrapper.appendChild(code);
  141. }
  142.  
  143. // Create and append the fullscreen button if not already there
  144. if (!wrapper.querySelector('.fullscreen-btn')) {
  145. const btn = document.createElement('button');
  146. btn.textContent = 'Fullscreen';
  147. btn.classList.add('fullscreen-btn');
  148. btn.addEventListener('click', () => toggleFullScreen(wrapper));
  149. wrapper.appendChild(btn);
  150. }
  151. });
  152. }
  153.  
  154. // Wait for the DOM to be fully loaded
  155. window.addEventListener('load', function() {
  156. addStyles();
  157. // Call addFullscreenButtons with a delay to allow syntax highlighting to process
  158. setTimeout(addFullscreenButtons, 0);
  159. });
  160. })();