OptiYan 2

EYanIDE 优化 2.0

// ==UserScript==
// @name         OptiYan 2
// @namespace    http://lunarine.cc/
// @version      2024.1.6
// @description  EYanIDE 优化 2.0
// @author       Liu Baicheng
// @match        http://121.36.38.167/
// @icon         http://121.36.38.167/static/favicon1.ico
// @grant        unsafeWindow
// @license      MIT
// @resource     css https://unpkg.com/mdui@1.0.2/dist/css/mdui.min.css
// @grant        GM_getResourceURL
// @grant        GM_getResourceText
// @grant        GM_addStyle
// @grant        GM_xmlhttpRequest
// @grant        GM_notification
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @require      https://cdn.jsdelivr.net/npm/mdui@1.0.2/dist/js/mdui.min.js
// @connect      api.mkc.icu
// ==/UserScript==

(function () {
    'use strict';

    function classOptimize() {

        let divs = document.querySelectorAll('div.ui.dropdown.selection');

        // 遍历并删除这些 div
        divs.forEach(div => {
            div.remove();
        });

        const ModalFileList = document.getElementById("file-list-modal");
        ModalFileList.style.height = "auto";
        ModalFileList.style.width = "500px";
        ModalFileList.style.marginTop = "50px";
        // ModalFileList.style.marginLeft = "30%";
        // ModalFileList.style.marginRight = "30% !important";

        var windowWidth = window.innerWidth;
        var windowHeight = window.innerHeight;
        var elementWidth = 500;
        var left = (windowWidth - elementWidth) / 2;

        ModalFileList.style.position = 'absolute';
        ModalFileList.style.left = left + 'px';

        var compilerOptionsInput = document.getElementById('compiler-options');
        compilerOptionsInput.value = "-O3";
        compilerOptionsInput.style.display = "none";
        var comilerArgsInput = document.getElementById('command-line-arguments');
        if (comilerArgsInput) comilerArgsInput.remove();

        document.getElementById("username-display").innerHTML = `<i class="user icon"></i>` + document.getElementById("username-display").innerHTML;
    }

    function formatCppTemplateLine(line) {
        const templateRegex = /(\btemplate\b|\bvector\b|\bmap\b|\bset\b|\bp(?:air|queue)\b|<.*>)/;
        if (templateRegex.test(line.trim())) {
            return line
                .replace(/\s*(<|>)\s*/g, '$1')
                .replace(/>(\w)/g, '> $1');
        }
        return line;
    }

    function formatCppCode(code) {
        code = code.replace(/\/\*[\s\S]*?\*\//g, '');
        code = code.replace(/\/\/.*$/gm, '');
        const lines = code.split('\n');
        let formattedLines = [];
        let indentLevel = 0;
        const indentSpace = '    ';
        let inStruct = false;

        for (let i = 0; i < lines.length; i++) {
            let line = lines[i].trim();
            const isEndOfStructWithVar = line.match(/}\s*[a-zA-Z_][a-zA-Z0-9_]*\s*\[?\s*[^;]*;/);

            if (line.includes('{') && !line.endsWith('{')) {
                line = line.replace(/\s*{\s*/g, ' {\n' + indentSpace.repeat(indentLevel + 1));
            }

            if (line.startsWith('struct')) {
                inStruct = true;
                formattedLines.push(indentSpace.repeat(indentLevel) + line);
                indentLevel++;
                continue;
            }

            if (line.endsWith('};') || isEndOfStructWithVar) {
                if (indentLevel) indentLevel--;
                formattedLines.push(indentSpace.repeat(indentLevel) + line);
                inStruct = false;

                if (isEndOfStructWithVar) {
                    continue;
                }
                formattedLines.push('');
                continue;
            }

            if (inStruct) {
                formattedLines.push(indentSpace.repeat(indentLevel) + line);
                continue;
            }

            if (line.startsWith('#include')) {
                line = line.replace(/#include\s*<\s*([\w./+-]+)\s*>/g, '#include <$1>');
                formattedLines.push(line);
                continue;
            }

            if (line === 'using namespace std;') {
                formattedLines.push(indentSpace.repeat(indentLevel) + line);
                formattedLines.push('');
                continue;
            }

            if (line.endsWith(')') && lines[i + 1] && lines[i + 1].trim() === '{') {
                line += ' {';
                i++;
            }

            line = line.replace(/\s*([+\-*/=<>&|]+)\s*/g, ' $1 ');
            line = line.replace(/\s*,\s*/g, ', ');
            line = line.replace(/\s*([+\-]{2})\s*/g, '$1');
            line = line.replace(/\s*;\s*/g, '; ');
            line = line.replace(/\)\s*(?=[a-zA-Z+\-*/])/g, ') ');

            line = line.replace(/(?<=[+\*/])\s*\(/g, ' (');
            line = line.replace(/(?<!\S)-\s*\(/g, '-(');
            line = line.replace(/\b(for|while|if|else|switch|case|do)\s*(?=[({])/g, '$1 ');

            line = formatCppTemplateLine(line);
            line = line.replace(/!\s*=\s*/g, '!= ');


            if (line.endsWith('}')) {
                if (indentLevel) indentLevel--;
                formattedLines.push(indentSpace.repeat(indentLevel) + line);
                if (indentLevel === 0 && !inStruct && line.endsWith('}')) {
                    formattedLines.push('');
                }
                continue;
            }

            if (line.includes("}")) {
                indentLevel--;
            }

            if (line.includes(') {')) {
                if (indentLevel === 0 && !inStruct && formattedLines[formattedLines.length - 1] != '') {
                    formattedLines.push('');
                    formattedLines.push(indentSpace.repeat(indentLevel) + line);
                    indentLevel++;
                    continue;
                }
            }

            if (line) {
                formattedLines.push(indentSpace.repeat(indentLevel) + line);
            }

            if (line.endsWith('{')) {
                indentLevel++;
            }
        }

        return formattedLines.join('\n').trim();
    }

    function formatCode() {
        const res = formatCppCode(unsafeWindow.sourceEditor.getValue());
        unsafeWindow.sourceEditor.setValue(res);
    }

    classOptimize();

    document.addEventListener('keydown', function (event) {
        if (event.ctrlKey && event.altKey) {
            formatCode(); // 调用目标函数
            mdui.snackbar({
                message: '代码格式化成功'
            });
        } else if (event.keyCode === 122) { // F11
            event.preventDefault();
            unsafeWindow.run();
        } else if (event.keyCode === 116) { // F5
            event.preventDefault();
        } else if (event.ctrlKey && event.keyCode === 82) { // Ctrl+R
            event.preventDefault();
        } else if (event.ctrlKey && event.keyCode === 121) { // Ctrl+R
            event.preventDefault();
        } else if (event.keyCode == 83 && event.ctrlKey) {
            event.preventDefault();
            saveCode();
        }
    });

    var title;

    window.addEventListener('load', function () {

        var footer = document.querySelector('#site-footer');

        if (footer) {
            var span = document.createElement('span');
            span.id = 'optiyan-line';
            span.textContent = 'OptiYan 已加载 Version: V1.1.0';
            span.style.color = "#fff";
            span.style.float = "left";
            span.style.left = "0";
            span.style.textAlign = "left";
            span.style.width = "fit-content";
            footer.appendChild(span);
        }

        var runBtn = document.getElementById('run-btn-label');
        runBtn.textContent = '运行 (F11 / Ctrl + ↵)';
        unsafeWindow.formatCppCode = formatCppCode;


        var loadBtn = document.getElementById('loadcode');
        loadBtn.className = "ui inverted primary labeled icon blue button";

        let fileNameInputDiv = document.createElement("div");

        fileNameInputDiv.className = "ui action inverted icon input";
        document.querySelectorAll("div.item.fitted.borderless.wide.screen.only")[0].appendChild(fileNameInputDiv);

        var fileNameInput = document.createElement('input');
        fileNameInput.id = "filename";
        fileNameInput.placeholder = "请输入文件名"

        fileNameInputDiv.appendChild(fileNameInput);

        document.getElementById("filename").value = "main.cpp";

        fileNameInputDiv.innerHTML += `
        <button id="saveCodeButton" class="ui icon button">
            <i class="save icon"></i>
        </button>
        `;
        document.getElementById("saveCodeButton").addEventListener('click', function () {
            saveCode();
        });
        // const spans = document.querySelectorAll('span.lm_title');

        // spans.forEach(span => {
        //     if (span.textContent.trim() === 'main.cpp') {
        //         title = span;
        //         console.log(title.innerHTML);
        //     }
        // });
        formatCode();
        classOptimize();
        // if (loading) document.getElementById("site-content").removeChild(loading);
        // document.getElementById("site-content").childNodes[0].style.display = '';
    });

    function updateColor() {
        let status = document.getElementById("status-line");
        if (status) {
            if (status.innerText.includes('Error')) {
                const sitefooter = document.querySelector('#site-footer');
                const linefooter = document.querySelector('#status-line');

                sitefooter.style.backgroundColor = "#c14343";
                linefooter.style.backgroundColor = "#c14343";
            } else if (status.innerText.includes('Accept')) {
                const sitefooter = document.querySelector('#site-footer');
                const linefooter = document.querySelector('#status-line');
                sitefooter.style.backgroundColor = "#05a705";
                linefooter.style.backgroundColor = "#05a705";
            } else {
                const sitefooter = document.querySelector('#site-footer');
                const linefooter = document.querySelector('#status-line');
                sitefooter.style.backgroundColor = "#9775fa";
                linefooter.style.backgroundColor = "#9775fa";
            }
        } else {
            const sitefooter = document.querySelector('#site-footer');
            const linefooter = document.querySelector('#status-line');
            sitefooter.style.backgroundColor = "#9775fa";
            linefooter.style.backgroundColor = "#9775fa";
        }

    }

    let script = document.createElement('script');
    script.src = "https://unpkg.com/mdui@1.0.2/dist/js/mdui.min.js?v=20240817";

    script.onload = function () {
        console.log('mdui 已加载');
    };

    document.body.appendChild(script);
    console.log(GM_getResourceURL("css"), GM_getResourceText("css"));
    GM_addStyle(GM_getResourceText("css"));

    setInterval(updateColor, 100);

    function createTimestampString(text) {
        // 获取当前时间的时间戳
        const timestamp = Math.floor(Date.now() / 1000); // 以秒为单位的时间戳
        console.log(timestamp);
        // 返回格式化字符串
        return `${text}:${timestamp}`;
    }

    function parseTimestampString(timestampString) {
        // 分割字符串,获取 text 和时间戳
        const [text, timestamp] = timestampString.split(':');
        // 将时间戳转换为格式化的时间
        const date = new Date(timestamp * 1000); // 将时间戳转换为毫秒
        const formattedTime = date.toLocaleString().slice(0, 19).replace('T', ' '); // 格式化为 YYYY-MM-DD HH:mm:ss
        return { text, formattedTime };
    }

    var curFileName;

    unsafeWindow.loadFileContent = function loadFileContent(filename) {
        document.getElementById("status-line").innerText = '正在加载文件...';
        fetch(`/load_file_content?filename=${encodeURIComponent(filename)}`)
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    // 使用 Monaco 编辑器加载文件内容
                    sourceEditor.setModel(monaco.editor.createModel(data.code, 'plaintext', monaco.Uri.file(filename + Math.floor(Math.random() * (9999 - 1111 + 1)) + 1111)));
                    monaco.editor.setModelLanguage(sourceEditor.getModel(), $selectLanguage.find(":selected").attr("mode"));
                    console.log(title);
                    curFileName = filename;
                    filename = parseTimestampString(filename).text;
                    title.innerText = filename + '.cpp';
                    $('#file-list-modal').modal('hide');
                    document.title = title.innerHTML;
                    document.getElementById("status-line").innerText = `已加载 ${filename}`;
                    document.getElementById("filename").value = filename;
                } else {
                    mdui.snackbar({
                        message: 'Failed to load file content: ' + data.message
                    });
                    document.getElementById("status-line").innerText = `${data.message}`;
                }
            })
            .catch((error) => {
                console.error('Error:', error);
                mdui.snackbar({
                    message: 'An error occurred while loading file content.'
                });
            });
    }

    unsafeWindow.showFileList = function showFileList() {
        fetch('/load_file_list')
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    const fileListDiv = document.getElementById('file-list');
                    fileListDiv.innerHTML = '';
                    fileListDiv.className = "ui middle aligned divided list";
                    // 创建文件列表
                    data.files.forEach(file => {
                        const fileItemDiv = document.createElement('div');
                        fileItemDiv.className = 'item';
                        const fileName = document.createElement('div');
                        fileName.classList.add('content')
                        //fileButton.className = 'ui button';
                        const info = parseTimestampString(file.filename);
                        const filename = info.text;
                        const time = info.formattedTime;

                        fileName.innerHTML = `
<a class="header">${filename}</a>
<div class="description">上次修改时间:${time}</div>

`;

                        const icon = document.createElement('i');
                        icon.className = "large file middle aligned icon";

                        const fileManage = document.createElement('div');
                        fileManage.className = "right floated ui content buttons";

                        const fileButton = document.createElement('div');
                        fileButton.className = 'ui icon circular button';
                        fileButton.innerHTML = `<i class="folder open icon"></i>`;;
                        fileButton.onclick = () => loadFileContent(file.filename);

                        const deleteButton = document.createElement('div');
                        deleteButton.className = 'ui icon circular red button';
                        deleteButton.innerHTML = `<i class="trash icon"></i>`;
                        deleteButton.onclick = () => deleteFile(file.filename, false);

                        fileManage.appendChild(fileButton);
                        
                        const orDiv = document.createElement('div');
                        //orDiv.classList.add('or');
                        //orDiv.setAttribute("data-text", "或");
                        //fileManage.appendChild(orDiv);
                        fileManage.appendChild(deleteButton);

                        fileItemDiv.appendChild(fileManage);
                        fileItemDiv.appendChild(icon);
                        fileItemDiv.appendChild(fileName);
                        fileListDiv.appendChild(fileItemDiv);

                    });

                    // 显示模态框
                    $('#file-list-modal').modal({
                        centered: true
                    }).modal('show')
                } else {
                    mdui.snackbar({
                        message: 'Failed to load file list: ' + data.message
                    });
                }
            })
            .catch((error) => {
                console.error('Error:', error);
                mdui.snackbar({
                    message: 'An error occurred while loading file list.'
                });
            });
    }


    unsafeWindow.deleteFile = function deleteFile(filename, enforce) {
        console.log("deleting")
        console.log(enforce);
        if (filename == null || !filename.includes(":")) return;
        const fileName = parseTimestampString(filename).text;
        if (enforce || confirm(`Are you sure you want to delete "${fileName}"?`)) {
            fetch(`/delete_file?filename=${encodeURIComponent(filename)}`, { method: 'DELETE' })
                .then(response => response.json())
                .then(data => {
                    if (data.success) {
                        if (!enforce) mdui.snackbar({
                            message: '删除成功'
                        });
                        if (!enforce) showFileList(); // Refresh the file list
                    } else {
                        mdui.snackbar({
                            message: 'Failed to delete file: ' + data.message
                        });
                    }
                })
                .catch((error) => {
                    console.error('Error:', error);
                    mdui.snackbar({
                        message: 'An error occurred while deleting the file.'
                    });
                });
        }
    }

    unsafeWindow.saveCode = function saveCode() {
        var fileName;
        console.log(title);
        if (title.innerText == "main.cpp" || "SOURCE") fileName = document.getElementById("filename").value;
        else {
            fileName = document.getElementById("filename").value;
        }
        if (fileName && fileName != "Untitled") {
            if (title.innerText != "main.cpp")
                if (document.getElementById("filename").value == title.innerText.replace(/\.[^/.]+$/, "")) unsafeWindow.deleteFile(curFileName, true);
            title.innerText = fileName + '.cpp';
            fileName = createTimestampString(fileName);
            unsafeWindow.saveFile(fileName);
            mdui.snackbar({
                message: '保存成功'
            });
            curFileName = fileName;
            document.title = title.innerHTML;
        } else {
            mdui.snackbar({
                message: '请输入有效的文件名或描述!'
            });
        }
    }
    setInterval(() => {
        const spans = document.querySelectorAll('span.lm_title');
        spans.forEach(span => {
            if (span.textContent.trim() === 'main.cpp' || span.textContent.trim() === "SOURCE") {
                title = span;
                //console.log(title.innerHTML);
            }
        });
        //console.log(title);
        if (title && title.innerText == "SOURCE") {
            title.innerText = parseTimestampString(curFileName || "main:114514").text + '.cpp';
        }
    }, 100);

})();