GreasyFork Code: Syntax Highlight by CodeMirror

To syntax highlight GreasyFork Code by CodeMirror

目前為 2023-12-17 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        GreasyFork Code: Syntax Highlight by CodeMirror
// @namespace   Violentmonkey Scripts
// @match       https://greasyfork.org/*
// @match       https://sleazyfork.org/*
// @grant       none
// @version     0.2.6
// @author      CY Fung
// @description To syntax highlight GreasyFork Code by CodeMirror
// @run-at      document-start
// @inject-into page
// @unwrap
// @license     MIT
// ==/UserScript==

(() => {
  let byPass = true;

  let documentReady = new Promise(resolve => {
    Promise.resolve().then(() => {
      if (document.readyState !== 'loading') {
        resolve();
      } else {
        window.addEventListener("DOMContentLoaded", resolve, false);
      }
    });
  });

  // Function to load CodeMirror library
  function loadCodeMirror(arr) {


    const promises = arr.map((href) => {
      return new Promise(resolve => {

        const script = document.createElement('script');
        script.src = href;
        script.onload = () => {
          resolve(script);
        };
        document.head.appendChild(script);

      });


    });

    return Promise.all(promises);
  }

  // Function to load CodeMirror CSS
  function loadCodeMirrorCSS(href) {
    const link = document.createElement('link');
    link.rel = 'stylesheet';
    link.href = href;
    document.head.appendChild(link);
  }

  async function runBlock(codeBlock) {

    let textarea = document.createElement('textarea');
    textarea.value = `${codeBlock.textContent}`;
    textarea.readOnly = true;
    textarea.id = 'editor651';


    // textarea.classList.add('code-container')

    textarea.style.width = '100%';
    textarea.style.height = '100vh';


    codeBlock.replaceWith(textarea);
    codeBlock.remove();


    let editor651 = CodeMirror.fromTextArea(document.querySelector('#editor651'), {

      mode: "javascript",

      readOnly: true,
      styleActiveLine: true,
      lineNumbers: true,
      extraKeys: { "Alt-F": "findPersistent" }
    });
    editor651.save();


  }

  // Main function to apply CodeMirror syntax highlighting to pre elements
  async function applyCodeMirrorSyntaxHighlighting() {

    if (window.requestIdleCallback) await new Promise(r => !!window.requestIdleCallback(r));
    else {
      await new Promise(r => !!window.requestAnimationFrame(r));
      await new Promise(r => !!window.setTimeout(r, 170));
      await new Promise(r => !!window.requestAnimationFrame(r));
    }

    const codeBlocks = document.querySelectorAll('pre.prettyprint.linenums.lang-js');


    // Check if CodeMirror is loaded
    if (typeof CodeMirror !== 'undefined') {

      for (const codeBlock of codeBlocks) {

        await new Promise((resolve) => {

          let io = new IntersectionObserver(() => {

            io.disconnect();
            io.takeRecords();
            io = null;
            resolve();


          })

          io.observe(codeBlock);

        });

        await runBlock(codeBlock);


      }



    } else {
      console.error('CodeMirror library is not loaded. Syntax highlighting cannot be applied.');
    }
  }

  async function doAction() {

    await new Promise(r => setTimeout(r, 1));

    document.head.appendChild(document.createElement('style')).textContent = `

      .code-container{
        height:100vh;
      }
      .code-container .CodeMirror, .code-container textarea{
        height:100%;
      }
      /*
          body {
              display: flex;
              flex-direction: column;
              height: 100vh;
          }
          body > div:last-child {
              height:0;
              flex-grow:1;
              display: flex;
              flex-direction:column;
          }
          body > div:last-child > #script-info:last-child {
              height:0;
              flex-grow:1;
              display: flex;
              flex-direction:column;
          }
          body > div:last-child > #script-info:last-child > #script-content:last-child {
              height:0;
              flex-grow:1;
              display: flex;
              flex-direction:column;
              gap:2px;
          }
          body > div:last-child > #script-info:last-child > #script-content:last-child > * {
              margin:0;
          }
          body > div:last-child > #script-info:last-child > #script-content:last-child > .code-container:last-child {
              height:0;
              flex-grow:1;
              display: flex;
              flex-direction:column;
          }
          body > div:last-child > #script-info:last-child > #script-content:last-child > .code-container:last-child > textarea:last-child {
              height:0;
              flex-grow:1;
              display: flex;
              flex-direction:column;
          }
          body > div:last-child > #script-info:last-child > #script-content:last-child > .code-container:last-child > .CodeMirror:last-child {
              height:0;
              flex-grow:1;
              display: flex;
              flex-direction:column;
          }
          */
      `;

    await loadCodeMirror(['https://cdn.jsdelivr.net/npm/[email protected]/lib/codemirror.min.js']);

    await loadCodeMirror([
      'https://cdn.jsdelivr.net/npm/[email protected]/mode/javascript/javascript.min.js',
      'https://cdn.jsdelivr.net/npm/[email protected]/addon/selection/active-line.min.js',


      'https://cdn.jsdelivr.net/npm/[email protected]/addon/search/search.js',
      'https://cdn.jsdelivr.net/npm/[email protected]/addon/search/searchcursor.js',
      'https://cdn.jsdelivr.net/npm/[email protected]/addon/search/jump-to-line.js',
      'https://cdn.jsdelivr.net/npm/[email protected]/addon/dialog/dialog.js'

    ]);

    loadCodeMirrorCSS('https://cdn.jsdelivr.net/npm/[email protected]/lib/codemirror.min.css');
    loadCodeMirrorCSS('https://cdn.jsdelivr.net/npm/[email protected]/addon/dialog/dialog.css');

    await Promise.all([new Promise(r => setTimeout(r, 60)), new Promise(r => window.requestAnimationFrame(r))]);


    byPass = false;

    applyCodeMirrorSyntaxHighlighting();






  }


  let mgg = 0;
  async function mTz() {
    if (mgg) return;
    mgg = 1;
    documentReady.then(doAction);
  }



  function getElementsByTagName(tag) {

    if (byPass) {
      if (tag === 'pre' || tag === 'code' || tag === 'xmp') {
        if (location.pathname.endsWith('/code')) {

          setTimeout(mTz, 10)
          return [];
        }
      }
    }
    return this.getElementsByTagName331(tag);
  }



  HTMLElement.prototype.getElementsByTagName331 = HTMLElement.prototype.getElementsByTagName
  Document.prototype.getElementsByTagName331 = Document.prototype.getElementsByTagName

  HTMLElement.prototype.getElementsByTagName = getElementsByTagName
  Document.prototype.getElementsByTagName = getElementsByTagName

  /*
  let mz= function(evt){

    if(evt && evt.type ==='readystatechange') return;
    return EventTarget.prototype.addEventListener.apply(this,arguments)

  };
  window.addEventListener = mz
  document.addEventListener = mz;
  */


  documentReady.then(async () => {

    if (location.pathname.endsWith('/code')) return;

    byPass = false;

  });

})();