Greasy Fork is available in English.

GreasyFork Code: Syntax Highlight by highlight.js

To syntax highlight GreasyFork Code by highlight.js

Verze ze dne 11. 12. 2023. Zobrazit nejnovější verzi.

  1. // ==UserScript==
  2. // @name GreasyFork Code: Syntax Highlight by highlight.js
  3. // @namespace Violentmonkey Scripts
  4. // @grant none
  5. // @version 0.3.0
  6. // @author CY Fung
  7. // @description To syntax highlight GreasyFork Code by highlight.js
  8. // @run-at document-start
  9. // @inject-into page
  10. // @unwrap
  11. // @license MIT
  12. // @match https://greatest.deepsurf.us/*
  13. // @match https://sleazyfork.org/*
  14. // @require https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js
  15. // @require https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/javascript.min.js
  16. // ==/UserScript==
  17.  
  18.  
  19. (() => {
  20. let byPass = true;
  21.  
  22. const resoruces = {
  23. 'nnfx-light.css': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/nnfx-light.min.css'
  24. }
  25.  
  26.  
  27. const Promise = (async function () { })().constructor;
  28.  
  29.  
  30. const documentReady = new Promise(resolve => {
  31. Promise.resolve().then(() => {
  32. if (document.readyState !== 'loading') {
  33. resolve();
  34. } else {
  35. window.addEventListener("DOMContentLoaded", resolve, false);
  36. }
  37. });
  38. });
  39.  
  40.  
  41. async function doAction() {
  42.  
  43. await new Promise(r => setTimeout(r, 1));
  44.  
  45. document.head.appendChild(document.createElement('style')).textContent = `
  46.  
  47. .code-container{
  48. height:100vh;
  49. }
  50. .code-container .CodeMirror, .code-container textarea{
  51. height:100%;
  52. }
  53. `;
  54.  
  55.  
  56.  
  57. if (window.requestIdleCallback) await new Promise(r => !!window.requestIdleCallback(r));
  58. else {
  59. await new Promise(r => !!window.requestAnimationFrame(r));
  60. await new Promise(r => !!window.setTimeout(r, 170));
  61. await new Promise(r => !!window.requestAnimationFrame(r));
  62. }
  63.  
  64. byPass = false;
  65.  
  66.  
  67.  
  68.  
  69.  
  70. }
  71.  
  72.  
  73. let mgg = 0;
  74. async function mTz() {
  75. if (mgg) return;
  76. mgg = 1;
  77. documentReady.then(doAction);
  78. }
  79.  
  80.  
  81.  
  82. function getElementsByTagName(tag) {
  83.  
  84. if (byPass) {
  85. if (tag === 'pre' || tag === 'code' || tag === 'xmp') {
  86. if (location.pathname.endsWith('/code')) {
  87. setTimeout(mTz, 100)
  88. return [];
  89. }
  90. }
  91. }
  92. return this.getElementsByTagName331(tag);
  93. }
  94.  
  95.  
  96.  
  97. async function onBodyHeadReadyAsync() {
  98.  
  99. if (document.body && document.head) {
  100.  
  101.  
  102. } else {
  103.  
  104. const promiseBegin = new Promise(resolve => {
  105.  
  106. let mo = new MutationObserver(() => {
  107. if (document.body && document.head) {
  108. mo.disconnect();
  109. mo.takeRecords();
  110. mo = null;
  111. resolve();
  112. }
  113.  
  114. });
  115. mo.observe(document, { subtree: true, childList: true });
  116.  
  117. });
  118.  
  119. await promiseBegin.then();
  120.  
  121. }
  122.  
  123. }
  124.  
  125.  
  126. // Load CSS
  127. function loadCSS(href) {
  128. const link = document.createElement('link');
  129. link.rel = 'stylesheet';
  130. link.href = href;
  131. document.head.appendChild(link);
  132. }
  133.  
  134. const global_css = `
  135.  
  136. html {
  137. line-height: 1.5;
  138. -webkit-text-size-adjust: 100%;
  139. -moz-tab-size: 4;
  140. -o-tab-size: 4;
  141. tab-size: 4;
  142. font-family: ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;
  143. font-feature-settings: normal;
  144. font-variation-settings: normal
  145. }
  146. /*
  147. body {
  148. margin: 0;
  149. line-height: inherit
  150. }
  151.  
  152. hr {
  153. height: 0;
  154. color: inherit;
  155. border-top-width: 1px
  156. }
  157.  
  158. abbr:where([title]) {
  159. -webkit-text-decoration: underline dotted;
  160. text-decoration: underline dotted
  161. }
  162.  
  163. h1,h2,h3,h4,h5,h6 {
  164. font-size: inherit;
  165. font-weight: inherit
  166. }
  167.  
  168.  
  169. b,strong {
  170. font-weight: bolder
  171. }
  172. */
  173. code,kbd,pre,samp {
  174. font-family: ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;
  175. font-size: 1em
  176. }
  177. /*
  178. small {
  179. font-size: 80%
  180. }
  181.  
  182. sub,sup {
  183. font-size: 75%;
  184. line-height: 0;
  185. position: relative;
  186. vertical-align: baseline
  187. }
  188.  
  189. sub {
  190. bottom: -.25em
  191. }
  192.  
  193. sup {
  194. top: -.5em
  195. }
  196.  
  197. table {
  198. text-indent: 0;
  199. border-color: inherit;
  200. border-collapse: collapse
  201. }
  202.  
  203. button,input,optgroup,select,textarea {
  204. font-family: inherit;
  205. font-feature-settings: inherit;
  206. font-variation-settings: inherit;
  207. font-size: 100%;
  208. font-weight: inherit;
  209. line-height: inherit;
  210. color: inherit;
  211. margin: 0;
  212. padding: 0
  213. }
  214.  
  215. button,select {
  216. text-transform: none
  217. }
  218.  
  219. :-moz-focusring {
  220. outline: auto
  221. }
  222.  
  223. :-moz-ui-invalid {
  224. box-shadow: none
  225. }
  226.  
  227. progress {
  228. vertical-align: baseline
  229. }
  230.  
  231. ::-webkit-inner-spin-button,::-webkit-outer-spin-button {
  232. height: auto
  233. }
  234.  
  235. [type=search] {
  236. -webkit-appearance: textfield;
  237. outline-offset: -2px
  238. }
  239.  
  240. ::-webkit-search-decoration {
  241. -webkit-appearance: none
  242. }
  243.  
  244. ::-webkit-file-upload-button {
  245. -webkit-appearance: button;
  246. font: inherit
  247. }
  248.  
  249. summary {
  250. display: list-item
  251. }
  252.  
  253. blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre {
  254. margin: 0
  255. }
  256.  
  257. fieldset {
  258. margin: 0
  259. }
  260.  
  261. fieldset,legend {
  262. padding: 0
  263. }
  264.  
  265. menu,ol,ul {
  266. list-style: none;
  267. margin: 0;
  268. padding: 0
  269. }
  270. textarea {
  271. resize: vertical
  272. }
  273.  
  274. input::-moz-placeholder,textarea::-moz-placeholder {
  275. opacity: 1;
  276. color: #9ca3af
  277. }
  278.  
  279. input::placeholder,textarea::placeholder {
  280. opacity: 1;
  281. color: #9ca3af
  282. }
  283. */
  284.  
  285.  
  286. .code-container[class] {
  287. border-radius: 0;
  288. }
  289.  
  290. .code-container > pre:only-child{
  291. padding:0;
  292. }
  293.  
  294. code.language-javascript.hljs[class] {
  295. /*
  296. font-family: ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,"Liberation Mono",monospace !important;
  297. font-size: 9pt;
  298. */
  299. font-family: monospace;
  300. font-size: 13px;
  301. font-variant-ligatures: contextual;
  302. line-height: normal;
  303. }
  304.  
  305. .hljs-comment[class], .hljs-quote[class] {
  306. font-style: inherit;
  307. color: #259789;
  308. }
  309.  
  310. .hljs-add-marker-width .marker-fixed-width[class] {
  311. user-select: none !important;
  312. width: calc(var(--hljs-marker-width, 0em) + 16px);
  313. background: #f4f4f4;
  314. padding-right: 6px;
  315. margin-right: 4px;
  316. }
  317.  
  318. `;
  319.  
  320.  
  321. const cssForCodePage = /\/scripts\/\d+[^\s\/\\]*\/code(\/|$)/.test(location.href) ? `
  322.  
  323. html:not([dkkfv]) div.code-container {
  324. position: absolute !important;
  325. }
  326.  
  327. html:not([dkkfv]) div.code-container > pre{
  328. display:none;
  329. }
  330.  
  331.  
  332. html:not([dkkfv]) code:only-child {
  333. display:none;
  334. }
  335.  
  336.  
  337. .code-container,
  338. .code-container pre:only-child,
  339. .code-container pre:only-child code:only-child {
  340. max-height: calc(100vh + 4px);
  341. max-width: calc(100vw + 4px);
  342. }
  343. ` : '';
  344.  
  345.  
  346. const cssAdd = `
  347.  
  348. ${global_css}
  349.  
  350. ${cssForCodePage}
  351.  
  352. .code-container {
  353. max-width: 100%;
  354. display: inline-flex;
  355. flex-direction: column;
  356. overflow: auto;
  357. border-radius: 8px;
  358. max-height: 100%;
  359. overflow: visible;
  360. }
  361. .code-container > pre:only-child {
  362. max-width: 100%;
  363. display: inline-flex;
  364. flex-direction: column;
  365. flex-grow: 1;
  366. height: 0;
  367. }
  368. .code-container > pre:only-child > code:only-child {
  369. max-width: 100%;
  370. flex-grow: 1;
  371. height: 0;
  372. }
  373. .code-container pre code {
  374. padding: 0;
  375. font-family: Consolas;
  376. cursor: text;
  377. overflow: auto;
  378. }
  379. .code-container pre code .marker {
  380. display: inline-block;
  381. color: #636d83;
  382. text-align: right;
  383. padding-right: 20px;
  384. user-select: none;
  385. cursor: auto;
  386. }
  387. `;
  388.  
  389.  
  390.  
  391.  
  392. HTMLElement.prototype.getElementsByTagName331 = HTMLElement.prototype.getElementsByTagName
  393. Document.prototype.getElementsByTagName331 = Document.prototype.getElementsByTagName
  394.  
  395. HTMLElement.prototype.getElementsByTagName = getElementsByTagName
  396. Document.prototype.getElementsByTagName = getElementsByTagName
  397.  
  398.  
  399. onBodyHeadReadyAsync().then(() => {
  400.  
  401. loadCSS(resoruces['nnfx-light.css'])
  402.  
  403. document.head.appendChild(document.createElement('style')).textContent = `${cssAdd}`;
  404.  
  405.  
  406. });
  407.  
  408.  
  409. documentReady.then(() => {
  410.  
  411. if (!location.pathname.endsWith('/code')) {
  412. byPass = false;
  413. }
  414.  
  415. // Code highlighting
  416. for (const pre of document.querySelectorAll('pre.lang-js')) {
  417.  
  418.  
  419. for (const li of pre.querySelectorAll('li')) {
  420. li.append(document.createTextNode('\n'));
  421. }
  422.  
  423. const codeElement = document.createElement('code');
  424. codeElement.classList.add('language-javascript');
  425. codeElement.innerHTML = pre.innerHTML;
  426.  
  427. // Clearing the original code container and appending the new one
  428. pre.classList = '';
  429. pre.innerHTML = '';
  430. pre.appendChild(codeElement);
  431.  
  432. const code = pre.querySelector('code:only-child');
  433. if (!code) continue;
  434.  
  435. // Highlighting
  436. hljs.highlightElement(code);
  437.  
  438. // Adding line numbers
  439. const html = code.innerHTML || '';
  440. const htmlSplit = html ? html.split('\n') : [];
  441. const totalLines = htmlSplit.length;
  442.  
  443. if (totalLines >= 1) {
  444. code.classList.add('hljs-add-marker-width');
  445. code.style.setProperty('--hljs-marker-width', `${String(totalLines).length * 0.5}em`);
  446. code.innerHTML = htmlSplit.map((n, i) => `<span class="marker marker-fixed-width">${i + 1}</span>${n}`).join('\n');
  447. } else {
  448. code.classList.remove('hljs-add-marker-width');
  449. code.style.setProperty('--hljs-marker-width', '');
  450. }
  451.  
  452.  
  453. }
  454.  
  455. setTimeout(() => {
  456. document.documentElement.setAttribute('dkkfv', '');
  457. }, 1);
  458.  
  459.  
  460. });
  461.  
  462.  
  463. })();
  464.