GreasyFork Code: Syntax Highlight by highlight.js

To syntax highlight GreasyFork Code by highlight.js

Stan na 11-12-2023. Zobacz najnowsza wersja.

// ==UserScript==
// @name         GreasyFork Code: Syntax Highlight by highlight.js
// @namespace    Violentmonkey Scripts
// @grant        none
// @version      0.3.1
// @author       CY Fung
// @description  To syntax highlight GreasyFork Code by highlight.js
// @run-at       document-start
// @inject-into  page
// @unwrap
// @license      MIT
// @match        https://greasyfork.org/*
// @match        https://sleazyfork.org/*
// @require      https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/javascript.min.js
// ==/UserScript==


(() => {
    let byPass = true;

    const resoruces = {
        'nnfx-light.css': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/nnfx-light.min.css'
    }


    const Promise = (async function () { })().constructor;


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


    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%;
            }
        `;



        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));
        }

        byPass = false;





    }


    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, 100)
                    return [];
                }
            }
        }
        return this.getElementsByTagName331(tag);
    }



    async function onBodyHeadReadyAsync() {

        if (document.body && document.head) {


        } else {

            const promiseBegin = new Promise(resolve => {

                let mo = new MutationObserver(() => {
                    if (document.body && document.head) {
                        mo.disconnect();
                        mo.takeRecords();
                        mo = null;
                        resolve();
                    }

                });
                mo.observe(document, { subtree: true, childList: true });

            });

            await promiseBegin.then();

        }

    }


    // Load CSS
    function loadCSS(href) {
        const link = document.createElement('link');
        link.rel = 'stylesheet';
        link.href = href;
        document.head.appendChild(link);
    }

    const global_css = `

        html {
            line-height: 1.5;
            -webkit-text-size-adjust: 100%;
            -moz-tab-size: 4;
            -o-tab-size: 4;
            tab-size: 4;
            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;
            font-feature-settings: normal;
            font-variation-settings: normal
        }
        /*
        body {
            margin: 0;
            line-height: inherit
        }

        hr {
            height: 0;
            color: inherit;
            border-top-width: 1px
        }

        abbr:where([title]) {
            -webkit-text-decoration: underline dotted;
            text-decoration: underline dotted
        }

        h1,h2,h3,h4,h5,h6 {
            font-size: inherit;
            font-weight: inherit
        }


        b,strong {
            font-weight: bolder
        }
        */
        code,kbd,pre,samp {
            font-family: ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;
            font-size: 1em
        }
        /*
        small {
            font-size: 80%
        }

        sub,sup {
            font-size: 75%;
            line-height: 0;
            position: relative;
            vertical-align: baseline
        }

        sub {
            bottom: -.25em
        }

        sup {
            top: -.5em
        }

        table {
            text-indent: 0;
            border-color: inherit;
            border-collapse: collapse
        }

        button,input,optgroup,select,textarea {
            font-family: inherit;
            font-feature-settings: inherit;
            font-variation-settings: inherit;
            font-size: 100%;
            font-weight: inherit;
            line-height: inherit;
            color: inherit;
            margin: 0;
            padding: 0
        }

        button,select {
            text-transform: none
        }

        :-moz-focusring {
            outline: auto
        }

        :-moz-ui-invalid {
            box-shadow: none
        }

        progress {
            vertical-align: baseline
        }

        ::-webkit-inner-spin-button,::-webkit-outer-spin-button {
            height: auto
        }

        [type=search] {
            -webkit-appearance: textfield;
            outline-offset: -2px
        }

        ::-webkit-search-decoration {
            -webkit-appearance: none
        }

        ::-webkit-file-upload-button {
            -webkit-appearance: button;
            font: inherit
        }

        summary {
            display: list-item
        }

        blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre {
            margin: 0
        }

        fieldset {
            margin: 0
        }

        fieldset,legend {
            padding: 0
        }

        menu,ol,ul {
            list-style: none;
            margin: 0;
            padding: 0
        }
        textarea {
            resize: vertical
        }

        input::-moz-placeholder,textarea::-moz-placeholder {
            opacity: 1;
            color: #9ca3af
        }

        input::placeholder,textarea::placeholder {
            opacity: 1;
            color: #9ca3af
        }
        */

        #script-content > .code-container[class] {
            width: 100%;
        }

        .code-container[class] {
            border-radius: 0;
        }

        .code-container[class] {
            border-radius: 0;
        }

        .code-container > pre:only-child{
            padding:0;
        }

        code.language-javascript.hljs[class] {
            /*
                font-family: ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,"Liberation Mono",monospace !important;
                font-size: 9pt;
            */
            font-family: monospace;
            font-size: 13px;
            font-variant-ligatures: contextual;
            line-height: normal;
        }

        .hljs-comment[class], .hljs-quote[class] {
            font-style: inherit;
            color: #259789;
        }

        .hljs-add-marker-width .marker-fixed-width[class] {
            user-select: none !important;
            width: calc(var(--hljs-marker-width, 0em) + 16px);
            background: #f4f4f4;
            padding-right: 6px;
            margin-right: 4px;
        }

    `;


    const cssForCodePage = /\/scripts\/\d+[^\s\/\\]*\/code(\/|$)/.test(location.href) ? `

        html:not([dkkfv]) div.code-container {
            position: absolute !important;
        }

        html:not([dkkfv]) div.code-container > pre{
            display:none;
        }


        html:not([dkkfv]) code:only-child {
            display:none;
        }


        .code-container,
        .code-container pre:only-child,
        .code-container pre:only-child code:only-child {
            max-height: calc(100vh + 4px);
            max-width: calc(100vw + 4px);
        }
    ` : '';


    const cssAdd = `

        ${global_css}

        ${cssForCodePage}

        .code-container {
            max-width: 100%;
            display: inline-flex;
            flex-direction: column;
            overflow: auto;
            border-radius: 8px;
            max-height: 100%;
            overflow: visible;
        }
        .code-container > pre:only-child {
            max-width: 100%;
            display: inline-flex;
            flex-direction: column;
            flex-grow: 1;
            height: 0;
        }
        .code-container > pre:only-child > code:only-child {
            max-width: 100%;
            flex-grow: 1;
            height: 0;
        }
        .code-container pre code {
            padding: 0;
            font-family: Consolas;
            cursor: text;
            overflow: auto;
        }
        .code-container pre code .marker {
            display: inline-block;
            color: #636d83;
            text-align: right;
            padding-right: 20px;
            user-select: none;
            cursor: auto;
        }
    `;




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

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


    onBodyHeadReadyAsync().then(() => {

        loadCSS(resoruces['nnfx-light.css'])

        document.head.appendChild(document.createElement('style')).textContent = `${cssAdd}`;

        

    });


    documentReady.then(() => {

        if (!location.pathname.endsWith('/code')) {
            byPass = false;
        }

        // Code highlighting
        for (const pre of document.querySelectorAll('pre.lang-js')) {


            for (const li of pre.querySelectorAll('li')) {
                li.append(document.createTextNode('\n'));
            }

            const codeElement = document.createElement('code');
            codeElement.classList.add('language-javascript');
            codeElement.innerHTML = pre.innerHTML;

            // Clearing the original code container and appending the new one
            pre.classList = '';
            pre.innerHTML = '';
            pre.appendChild(codeElement);

            const code = pre.querySelector('code:only-child');
            if (!code) continue;

            // Highlighting
            hljs.highlightElement(code);

            // Adding line numbers
            const html = code.innerHTML || '';
            const htmlSplit = html ? html.split('\n') : [];
            const totalLines = htmlSplit.length;

            if (totalLines >= 1) {
                code.classList.add('hljs-add-marker-width');
                code.style.setProperty('--hljs-marker-width', `${String(totalLines).length * 0.5}em`);
                code.innerHTML = htmlSplit.map((n, i) => `<span class="marker marker-fixed-width">${i + 1}</span>${n}`).join('\n');
            } else {
                code.classList.remove('hljs-add-marker-width');
                code.style.setProperty('--hljs-marker-width', '');
            }


        }

        setTimeout(() => {
            document.documentElement.setAttribute('dkkfv', '');
        }, 1);


    });


})();